lcd.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  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. static rt_uint8_t gui_disp_buf[GUI_LCM_YMAX/8][GUI_LCM_XMAX];
  17. struct rtgui_lcd_device
  18. {
  19. struct rt_device parent;
  20. /* screen width and height */
  21. rt_uint16_t width;
  22. rt_uint16_t height;
  23. void* hw_framebuffer;
  24. };
  25. static struct rtgui_lcd_device *lcd = RT_NULL;
  26. void Power_Delay(void)
  27. {
  28. rt_uint32_t i=0x4ffff;
  29. while(i--)
  30. ;//asm("nop");
  31. }
  32. void Delay(void)
  33. {
  34. rt_uint8_t i=0x8;
  35. while(i--)
  36. ;//asm("nop");
  37. }
  38. void Reset_Delay(void)
  39. {
  40. rt_uint8_t i=0xff;
  41. while(i--)
  42. ;//asm("nop");
  43. }
  44. void LCD_WriteCmd(unsigned char command)
  45. {
  46. rt_uint8_t i;
  47. LCD_PS_LOW();
  48. LCD_CS_LOW();
  49. LCD_CD_LOW();
  50. for(i=0; i<8; i++)
  51. {
  52. if(command & (0x80 >> i))
  53. LCD_DATA_HIGH();
  54. else
  55. LCD_DATA_LOW();
  56. LCD_CLK_LOW();
  57. Delay();
  58. LCD_CLK_HIGH();
  59. Delay();
  60. }
  61. LCD_CS_HIGH();
  62. }
  63. void LCD_WriteData(unsigned char data)
  64. {
  65. rt_uint8_t i;
  66. LCD_PS_LOW();
  67. LCD_CS_LOW();
  68. LCD_CD_HIGH();
  69. for(i=0; i<8; i++)
  70. {
  71. if(data & (0x80 >> i))
  72. LCD_DATA_HIGH();
  73. else
  74. LCD_DATA_LOW();
  75. LCD_CLK_LOW();
  76. Delay();
  77. LCD_CLK_HIGH();
  78. Delay();
  79. }
  80. LCD_CS_HIGH();
  81. }
  82. #ifdef RT_USING_RTGUI
  83. #include <rtgui/driver.h>
  84. #include <rtgui/color.h>
  85. static void rt_hw_lcd_update(rtgui_rect_t *rect)
  86. {
  87. rt_uint8_t i,j = GUI_LCM_XMAX;
  88. rt_uint8_t* p = (rt_uint8_t*)gui_disp_buf;
  89. for(i=0; i<GUI_LCM_PAGE; i++)
  90. {
  91. LCD_WriteCmd(Set_Page_Addr_0|i);
  92. LCD_WriteCmd(Set_ColH_Addr_0);
  93. LCD_WriteCmd(Set_ColL_Addr_0);
  94. j = GUI_LCM_XMAX;
  95. while(j--)
  96. {
  97. LCD_WriteData(*p++);
  98. Delay();
  99. }
  100. }
  101. }
  102. static rt_uint8_t * rt_hw_lcd_get_framebuffer(void)
  103. {
  104. return(rt_uint8_t *)gui_disp_buf;
  105. }
  106. static void rt_hw_lcd_set_pixel(rtgui_color_t *c, rt_base_t x, rt_base_t y)
  107. {
  108. rt_uint8_t page;
  109. page = y/8;
  110. if(*c == black)
  111. gui_disp_buf[page][x] |= 1<<(y%8);
  112. else
  113. if(*c == white)
  114. gui_disp_buf[page][x] &= ~(1<<(y%8));
  115. }
  116. static void rt_hw_lcd_get_pixel(rtgui_color_t *c, rt_base_t x, rt_base_t y)
  117. {
  118. rt_uint8_t page;
  119. page = y/8;
  120. if(gui_disp_buf[page][x] & (1<<(y%8)))
  121. *c = black;
  122. else
  123. *c = white;
  124. }
  125. static void rt_hw_lcd_draw_hline(rtgui_color_t *c, rt_base_t x1, rt_base_t x2, rt_base_t y)
  126. {
  127. rt_uint8_t page;
  128. rt_uint8_t i;
  129. page = y/8;
  130. for(i=x1; i<x2; i++)
  131. {
  132. if(*c == black)
  133. gui_disp_buf[page][i] |= 1<<(y%8);
  134. else
  135. if(*c == white)
  136. gui_disp_buf[page][i] &= ~(1<<(y%8));
  137. }
  138. }
  139. static void rt_hw_lcd_draw_vline(rtgui_color_t *c, rt_base_t x, rt_base_t y1, rt_base_t y2)
  140. {
  141. rt_uint8_t y;
  142. for(y = y1; y < y2; y ++)
  143. {
  144. rt_hw_lcd_set_pixel(c, x, y);
  145. }
  146. }
  147. static void rt_hw_lcd_draw_raw_hline(rt_uint8_t *pixels, rt_base_t x1, rt_base_t x2, rt_base_t y)
  148. {
  149. rt_uint8_t coll;
  150. rt_uint8_t colh;
  151. rt_uint8_t page;
  152. rt_uint8_t i;
  153. page = y/8;
  154. for(i=x1; i<x2; i++)
  155. {
  156. gui_disp_buf[page][i] |= 1<<(y%8);
  157. coll = i & 0x0f;
  158. colh = i >> 4;
  159. LCD_WriteCmd(Set_Page_Addr_0 | page);
  160. LCD_WriteCmd(Set_ColH_Addr_0 | colh);
  161. LCD_WriteCmd(Set_ColL_Addr_0 | coll);
  162. LCD_WriteData(gui_disp_buf[page][i]);
  163. }
  164. }
  165. struct rtgui_graphic_driver _rtgui_lcd_driver =
  166. {
  167. "lcd",
  168. 1,
  169. LCD_WIDTH,
  170. LCD_HEIGHT,
  171. rt_hw_lcd_update,
  172. rt_hw_lcd_get_framebuffer,
  173. rt_hw_lcd_set_pixel,
  174. rt_hw_lcd_get_pixel,
  175. rt_hw_lcd_draw_hline,
  176. rt_hw_lcd_draw_vline,
  177. rt_hw_lcd_draw_raw_hline
  178. };
  179. #endif
  180. void lcd_io_init()
  181. {
  182. /* Release the analog input function*/
  183. FM3_GPIO->ADE =0x03;
  184. /*Select CPIO function*/
  185. LCD_CS_PFR &= ~LCD_CS;
  186. /*Make pin output*/
  187. LCD_CS_DDR |= LCD_CS;
  188. /*Select CPIO function*/
  189. LCD_CD_PFR &= ~LCD_CD;
  190. /*Make pin output*/
  191. LCD_CD_DDR |= LCD_CD;
  192. /*Select CPIO function*/
  193. LCD_PS_PFR &= ~LCD_PS;
  194. /*Make pin output*/
  195. LCD_PS_DDR |= LCD_PS;
  196. /*Select CPIO function*/
  197. LCD_CLK_PFR &= ~LCD_CLK;
  198. /*Make pin output*/
  199. LCD_CLK_DDR |= LCD_CLK;
  200. /*Select CPIO function*/
  201. LCD_DATA_PFR &= ~LCD_DATA;
  202. /*Make pin output*/
  203. LCD_DATA_DDR |= LCD_DATA;
  204. }
  205. /* RT-Thread Device Interface */
  206. static rt_err_t rt_lcd_init (rt_device_t dev)
  207. {
  208. lcd_io_init();
  209. Power_Delay();
  210. LCD_WriteCmd(Display_Off);
  211. Reset_Delay();
  212. // Resetting circuit
  213. LCD_WriteCmd(Reset_LCD);
  214. Reset_Delay();
  215. // LCD bias setting
  216. LCD_WriteCmd(Set_LCD_Bias_9);
  217. Reset_Delay();
  218. // ADC selection: display from left to right
  219. LCD_WriteCmd(Set_ADC_Normal);
  220. Reset_Delay();
  221. // Common output state selection: display from up to down
  222. LCD_WriteCmd(COM_Scan_Dir_Reverse);
  223. Reset_Delay();
  224. LCD_WriteCmd(Power_Booster_On);
  225. Power_Delay(); // 50ms requried
  226. LCD_WriteCmd(Power_Regulator_On);
  227. Power_Delay(); // 50ms
  228. LCD_WriteCmd(Power_Follower_On);
  229. Power_Delay(); // 50ms
  230. // Setting the built-in resistance radio for regulation of the V0 voltage
  231. // Electronic volume control
  232. // Power control setting
  233. LCD_WriteCmd(Set_ElecVol_Reg|0x05);
  234. Delay();
  235. LCD_WriteCmd(Set_ElecVol_Mode);
  236. Delay();
  237. LCD_WriteCmd(Set_ElecVol_Reg);
  238. Delay();
  239. // LCD_Clear();
  240. Delay();
  241. LCD_WriteCmd(Set_Page_Addr_0);
  242. Delay();
  243. LCD_WriteCmd(Set_ColH_Addr_0);
  244. Delay();
  245. LCD_WriteCmd(Set_ColL_Addr_0);
  246. Delay();
  247. LCD_WriteCmd(Display_On);
  248. Delay();
  249. LCD_WriteCmd(Display_All_On);
  250. Delay();
  251. LCD_WriteCmd(Display_Off);
  252. Delay();
  253. LCD_WriteCmd(Display_On);
  254. Delay();
  255. LCD_WriteCmd(Display_All_Normal);
  256. Delay();
  257. return RT_EOK;
  258. }
  259. static rt_err_t rt_lcd_control (rt_device_t dev, rt_uint8_t cmd, void *args)
  260. {
  261. switch (cmd)
  262. {
  263. case RT_DEVICE_CTRL_LCD_GET_WIDTH:
  264. *((rt_uint16_t*)args) = lcd->width;
  265. break;
  266. case RT_DEVICE_CTRL_LCD_GET_HEIGHT:
  267. *((rt_uint16_t*)args) = lcd->height;
  268. break;
  269. case RT_DEVICE_CTRL_LCD_DISPLAY_ON:
  270. LCD_WriteCmd(Display_On);
  271. break;
  272. case RT_DEVICE_CTRL_LCD_DISPLAY_OFF:
  273. LCD_WriteCmd(Display_Off);
  274. break;
  275. }
  276. return RT_EOK;
  277. }
  278. static rt_err_t rt_lcd_open(rt_device_t dev, rt_uint16_t oflag)
  279. {
  280. RT_ASSERT(dev != RT_NULL);
  281. return RT_EOK;
  282. }
  283. static rt_err_t rt_lcd_close(rt_device_t dev)
  284. {
  285. RT_ASSERT(dev != RT_NULL);
  286. return RT_EOK;
  287. }
  288. void rt_hw_lcd_init(void)
  289. {
  290. lcd = (struct rtgui_lcd_device*)rt_malloc(sizeof(struct rtgui_lcd_device));
  291. if (lcd == RT_NULL)
  292. return; /* no memory yet */
  293. /* init device structure */
  294. lcd->parent.type = RT_Device_Class_Unknown;
  295. lcd->parent.init = rt_lcd_init;
  296. lcd->parent.open = rt_lcd_open;
  297. lcd->parent.close = rt_lcd_close;
  298. lcd->parent.control = rt_lcd_control;
  299. lcd->parent.user_data = RT_NULL;
  300. lcd->width = LCD_WIDTH;
  301. lcd->height = LCD_HEIGHT;
  302. lcd->hw_framebuffer = (void*)gui_disp_buf;
  303. /* register touch device to RT-Thread */
  304. rt_device_register(&(lcd->parent), "lcd", RT_DEVICE_FLAG_RDWR);
  305. #ifdef RT_USING_RTGUI
  306. /* add lcd driver into graphic driver */
  307. rtgui_graphic_driver_add(&_rtgui_lcd_driver);
  308. #endif
  309. }