lcd.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2011-03-05 lgnq ZYMG12864C3 LCD driver
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #include "lcd.h"
  13. #include "font.h"
  14. static struct rt_device_graphic_info _lcd_info;
  15. static rt_uint8_t gui_disp_buf[GUI_LCM_YMAX/8][GUI_LCM_XMAX];
  16. const unsigned char BIT_MASK[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
  17. /* simple font: ' ', '0'~'9','a'~'z','A'~'Z' */
  18. extern const unsigned char FONTTYPE8_8[][8];
  19. rt_uint32_t x;
  20. rt_uint32_t y;
  21. void power_delay(void)
  22. {
  23. rt_uint32_t i = 0x4ffff;
  24. while(i--)
  25. ;
  26. }
  27. void delay(void)
  28. {
  29. rt_uint8_t i = 0x8;
  30. while(i--)
  31. ;
  32. }
  33. void reset_delay(void)
  34. {
  35. rt_uint8_t i = 0xff;
  36. while(i--)
  37. ;
  38. }
  39. void lcd_write_cmd(unsigned char command)
  40. {
  41. rt_uint8_t i;
  42. LCD_PS_LOW();
  43. LCD_CS_LOW();
  44. LCD_CD_LOW();
  45. for (i=0; i<8; i++)
  46. {
  47. if (command & (0x80 >> i))
  48. LCD_DATA_HIGH();
  49. else
  50. LCD_DATA_LOW();
  51. LCD_CLK_LOW();
  52. delay();
  53. LCD_CLK_HIGH();
  54. delay();
  55. }
  56. LCD_CS_HIGH();
  57. }
  58. void lcd_write_data(unsigned char data)
  59. {
  60. rt_uint8_t i;
  61. LCD_PS_LOW();
  62. LCD_CS_LOW();
  63. LCD_CD_HIGH();
  64. for (i=0; i<8; i++)
  65. {
  66. if (data & (0x80 >> i))
  67. LCD_DATA_HIGH();
  68. else
  69. LCD_DATA_LOW();
  70. LCD_CLK_LOW();
  71. delay();
  72. LCD_CLK_HIGH();
  73. delay();
  74. }
  75. LCD_CS_HIGH();
  76. }
  77. #ifdef RT_USING_RTGUI
  78. #include <rtgui/driver.h>
  79. #include <rtgui/color.h>
  80. static void rt_hw_lcd_update(struct rt_device_rect_info *rect_info)
  81. {
  82. rt_uint8_t i,j = GUI_LCM_XMAX;
  83. rt_uint8_t* p = (rt_uint8_t*)gui_disp_buf;
  84. for (i=0; i<GUI_LCM_PAGE; i++)
  85. {
  86. lcd_write_cmd(SET_PAGE_ADDR_0|i);
  87. lcd_write_cmd(SET_COLH_ADDR_0);
  88. lcd_write_cmd(SET_COLL_ADDR_0);
  89. j = GUI_LCM_XMAX;
  90. while (j--)
  91. {
  92. lcd_write_data(*p++);
  93. delay();
  94. }
  95. }
  96. }
  97. static rt_uint8_t * rt_hw_lcd_get_framebuffer(void)
  98. {
  99. return(rt_uint8_t *)gui_disp_buf;
  100. }
  101. static void rt_hw_lcd_set_pixel(rtgui_color_t *c, int x, int y)
  102. {
  103. rt_uint8_t page;
  104. page = y/8;
  105. if (*c == rtgui_color_to_565(black))
  106. gui_disp_buf[page][x] |= 1<<(y%8);
  107. else
  108. if (*c == rtgui_color_to_565(white))
  109. gui_disp_buf[page][x] &= ~(1<<(y%8));
  110. }
  111. static void rt_hw_lcd_get_pixel(rtgui_color_t *c, int x, int y)
  112. {
  113. rt_uint8_t page;
  114. page = y/8;
  115. if (gui_disp_buf[page][x] & (1<<(y%8)))
  116. *c = black;
  117. else
  118. *c = white;
  119. }
  120. static void rt_hw_lcd_draw_hline(rtgui_color_t *c, int x1, int x2, int y)
  121. {
  122. rt_uint8_t page;
  123. rt_uint8_t i;
  124. page = y/8;
  125. for (i=x1; i<x2; i++)
  126. {
  127. if (*c == rtgui_color_to_565(black))
  128. gui_disp_buf[page][i] |= 1<<(y%8);
  129. else
  130. if (*c == rtgui_color_to_565(white))
  131. gui_disp_buf[page][i] &= ~(1<<(y%8));
  132. }
  133. }
  134. static void rt_hw_lcd_draw_vline(rtgui_color_t *c, int x, int y1, int y2)
  135. {
  136. rt_uint8_t y;
  137. for (y = y1; y < y2; y ++)
  138. {
  139. rt_hw_lcd_set_pixel(c, x, y);
  140. }
  141. }
  142. static void rt_hw_lcd_draw_raw_hline(rt_uint8_t *pixels, int x1, int x2, int y)
  143. {
  144. rt_uint8_t coll;
  145. rt_uint8_t colh;
  146. rt_uint8_t page;
  147. rt_uint8_t i;
  148. page = y/8;
  149. for (i=x1; i<x2; i++)
  150. {
  151. gui_disp_buf[page][i] |= 1<<(y%8);
  152. coll = i & 0x0f;
  153. colh = i >> 4;
  154. lcd_write_cmd(SET_PAGE_ADDR_0 | page);
  155. lcd_write_cmd(SET_COLH_ADDR_0 | colh);
  156. lcd_write_cmd(SET_COLL_ADDR_0 | coll);
  157. lcd_write_data(gui_disp_buf[page][i]);
  158. }
  159. }
  160. const struct rtgui_graphic_driver_ops _lcd_ops =
  161. {
  162. rt_hw_lcd_set_pixel,
  163. rt_hw_lcd_get_pixel,
  164. rt_hw_lcd_draw_hline,
  165. rt_hw_lcd_draw_vline,
  166. rt_hw_lcd_draw_raw_hline
  167. };
  168. #endif
  169. void lcd_io_init()
  170. {
  171. /* Release the analog input function*/
  172. FM3_GPIO->ADE =0x03;
  173. /*Select CPIO function*/
  174. LCD_CS_PFR &= ~LCD_CS;
  175. /*Make pin output*/
  176. LCD_CS_DDR |= LCD_CS;
  177. /*Select CPIO function*/
  178. LCD_CD_PFR &= ~LCD_CD;
  179. /*Make pin output*/
  180. LCD_CD_DDR |= LCD_CD;
  181. /*Select CPIO function*/
  182. LCD_PS_PFR &= ~LCD_PS;
  183. /*Make pin output*/
  184. LCD_PS_DDR |= LCD_PS;
  185. /*Select CPIO function*/
  186. LCD_CLK_PFR &= ~LCD_CLK;
  187. /*Make pin output*/
  188. LCD_CLK_DDR |= LCD_CLK;
  189. /*Select CPIO function*/
  190. LCD_DATA_PFR &= ~LCD_DATA;
  191. /*Make pin output*/
  192. LCD_DATA_DDR |= LCD_DATA;
  193. }
  194. /* RT-Thread Device Interface */
  195. static rt_err_t rt_lcd_init (rt_device_t dev)
  196. {
  197. lcd_io_init();
  198. power_delay();
  199. lcd_write_cmd(DISPLAY_OFF);
  200. reset_delay();
  201. // Resetting circuit
  202. lcd_write_cmd(RESET_LCD);
  203. reset_delay();
  204. // LCD bias setting
  205. lcd_write_cmd(SET_LCD_BIAS_9);
  206. reset_delay();
  207. // ADC selection: display from left to right
  208. lcd_write_cmd(SET_ADC_NORMAL);
  209. reset_delay();
  210. // Common output state selection: display from up to down
  211. lcd_write_cmd(COM_SCAN_DIR_REVERSE);
  212. reset_delay();
  213. lcd_write_cmd(POWER_BOOSTER_ON);
  214. power_delay(); // 50ms requried
  215. lcd_write_cmd(POWER_REGULATOR_ON);
  216. power_delay(); // 50ms
  217. lcd_write_cmd(POWER_FOLLOWER_ON);
  218. power_delay(); // 50ms
  219. // Setting the built-in resistance radio for regulation of the V0 voltage
  220. // Electronic volume control
  221. // Power control setting
  222. lcd_write_cmd(SET_ELECVOL_REG|0x05);
  223. delay();
  224. lcd_write_cmd(SET_ELECVOL_MODE);
  225. delay();
  226. lcd_write_cmd(SET_ELECVOL_REG);
  227. delay();
  228. // LCD_Clear();
  229. delay();
  230. lcd_write_cmd(SET_PAGE_ADDR_0);
  231. delay();
  232. lcd_write_cmd(SET_COLH_ADDR_0);
  233. delay();
  234. lcd_write_cmd(SET_COLL_ADDR_0);
  235. delay();
  236. lcd_write_cmd(DISPLAY_ON);
  237. delay();
  238. lcd_write_cmd(DISPLAY_ALL_ON);
  239. delay();
  240. lcd_write_cmd(DISPLAY_OFF);
  241. delay();
  242. lcd_write_cmd(DISPLAY_ON);
  243. delay();
  244. lcd_write_cmd(DISPLAY_ALL_NORMAL);
  245. delay();
  246. return RT_EOK;
  247. }
  248. /*******************************************************************************
  249. * Function Name : LCD_FillAll
  250. * Description : Fill the whole LCD.
  251. * Input : None
  252. * Output : None
  253. * Return : None
  254. *******************************************************************************/
  255. void LCD_FillAll(unsigned char* buffer)
  256. {
  257. unsigned char i,j = GUI_LCM_XMAX;
  258. unsigned char* p = buffer;
  259. for (i=0; i<GUI_LCM_PAGE; i++)
  260. {
  261. lcd_write_cmd(SET_PAGE_ADDR_0|i);
  262. lcd_write_cmd(SET_COLH_ADDR_0);
  263. lcd_write_cmd(SET_COLL_ADDR_0);
  264. j = GUI_LCM_XMAX;
  265. while (j--)
  266. {
  267. lcd_write_data(*p++);
  268. delay();
  269. }
  270. }
  271. }
  272. /*******************************************************************************
  273. * Function Name : LCD_ClearSCR
  274. * Description : clean screen
  275. * Input : None
  276. * Output : None
  277. * Return : None
  278. *******************************************************************************/
  279. void LCD_ClearSCR(void)
  280. {
  281. unsigned char i, j;
  282. for(i=0; i<GUI_LCM_PAGE; i++)
  283. {
  284. for(j = 0; j < GUI_LCM_XMAX; j++)
  285. gui_disp_buf[i][j] = 0;
  286. }
  287. LCD_FillAll((unsigned char*)gui_disp_buf);
  288. }
  289. /****************************************************************************
  290. * Function Name : LCD_UpdatePoint
  291. * Description : refresh the point in screen
  292. * Input : x X-coordinate
  293. y Y-coordinate
  294. * Output : None
  295. * Return : None
  296. ****************************************************************************/
  297. void LCD_UpdatePoint(unsigned int x, unsigned int y)
  298. {
  299. unsigned char coll, colh, page;
  300. page = y / 8;
  301. coll = x & 0x0f;
  302. colh = x >> 4;
  303. lcd_write_cmd(SET_PAGE_ADDR_0 | page); // page no.
  304. lcd_write_cmd(SET_COLH_ADDR_0 | colh); // fixed col first addr
  305. lcd_write_cmd(SET_COLL_ADDR_0 | coll);
  306. lcd_write_data(gui_disp_buf[page][x]);
  307. }
  308. /****************************************************************************
  309. * Function Name : LCD_PutChar
  310. * Description : output a char to screen
  311. (the char only can be ' ','0'~'9','A'~'Z','a'~'z')
  312. * Input : x X-coordinate
  313. y Y-coordinate
  314. ch character
  315. * Output : None
  316. * Return : 1 Success
  317. 0 Fail
  318. ****************************************************************************/
  319. unsigned char LCD_PutChar(unsigned long x, unsigned long y, unsigned char ch)
  320. {
  321. unsigned char data;
  322. unsigned char i, j;
  323. if( x >=(GUI_LCM_XMAX-8) ) return(0);
  324. if( y >=(GUI_LCM_YMAX-8) ) return(0);
  325. if(ch == 0x20)
  326. ch -= 0x20;
  327. else if((ch >= 0x30)&&(ch <= 0x39))
  328. ch -= 0x2f;
  329. else if((ch >= 0x41)&&(ch <= 0x5a))
  330. ch -= 0x36;
  331. else if((ch >= 0x61)&&(ch <= 0x7a))
  332. ch -= 0x3C;
  333. else
  334. return(0);
  335. for(i = 0; i < 8; i++)
  336. {
  337. data = FONTTYPE8_8[ch][i];
  338. for(j = 0; j < 8; j++)
  339. {
  340. if( (data&BIT_MASK[j]) == 0)
  341. gui_disp_buf[y / 8][x] &= (~(0x01 << ( y % 8)));
  342. else
  343. gui_disp_buf[y / 8][x] |= (0x01 <<( y % 8));
  344. LCD_UpdatePoint(x, y);
  345. x ++;
  346. }
  347. x -= 8;
  348. y++;
  349. }
  350. return(1);
  351. }
  352. /****************************************************************************
  353. * Function Name : LCD_PutString
  354. * Description : output string to screen
  355. * Input : x X-coordinate
  356. y Y-coordinate
  357. str pointer to string
  358. * Output : None
  359. * Return : None
  360. ****************************************************************************/
  361. void LCD_PutString(unsigned long x, unsigned long y, char *str)
  362. {
  363. while(1)
  364. {
  365. if( (*str)=='\0' ) break;
  366. if( LCD_PutChar(x, y, *str++) == 0 ) break;
  367. x += 6;
  368. }
  369. }
  370. static rt_err_t rt_lcd_control (rt_device_t dev, int cmd, void *args)
  371. {
  372. switch (cmd)
  373. {
  374. #ifdef RT_USING_RTGUI
  375. case RTGRAPHIC_CTRL_RECT_UPDATE:
  376. rt_hw_lcd_update(args);
  377. break;
  378. case RTGRAPHIC_CTRL_POWERON:
  379. break;
  380. case RTGRAPHIC_CTRL_POWEROFF:
  381. break;
  382. case RTGRAPHIC_CTRL_GET_INFO:
  383. rt_memcpy(args, &_lcd_info, sizeof(_lcd_info));
  384. break;
  385. case RTGRAPHIC_CTRL_SET_MODE:
  386. break;
  387. #else
  388. case RT_DEVICE_CTRL_LCD_DISPLAY_ON:
  389. lcd_write_cmd(DISPLAY_ON);
  390. break;
  391. case RT_DEVICE_CTRL_LCD_DISPLAY_OFF:
  392. lcd_write_cmd(DISPLAY_OFF);
  393. break;
  394. case RT_DEVICE_CTRL_LCD_PUT_STRING:
  395. LCD_PutString(x, y, (char*)args);
  396. break;
  397. case RT_DEVICE_CTRL_LCD_CLEAR_SCR:
  398. LCD_ClearSCR();
  399. break;
  400. #endif
  401. }
  402. return RT_EOK;
  403. }
  404. void rt_hw_lcd_init(void)
  405. {
  406. rt_device_t lcd = rt_malloc(sizeof(struct rt_device));
  407. if (lcd == RT_NULL) return; /* no memory yet */
  408. _lcd_info.bits_per_pixel = 16;
  409. _lcd_info.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB565;
  410. _lcd_info.framebuffer = RT_NULL;
  411. _lcd_info.width = LCD_WIDTH;
  412. _lcd_info.height = LCD_HEIGHT;
  413. /* init device structure */
  414. lcd->type = RT_Device_Class_Unknown;
  415. lcd->init = rt_lcd_init;
  416. lcd->open = RT_NULL;
  417. lcd->close = RT_NULL;
  418. lcd->control = rt_lcd_control;
  419. #ifdef RT_USING_RTGUI
  420. lcd->user_data = (void*)&_lcd_ops;
  421. #endif
  422. /* register lcd device to RT-Thread */
  423. rt_device_register(lcd, "lcd", RT_DEVICE_FLAG_RDWR);
  424. }