lcd.c 11 KB

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