lcd.c 12 KB

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