lcd_ili9341.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. /**************************************************************************//**
  2. *
  3. * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2020-1-16 Wayne First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(NU_PKG_USING_ILI9341)
  14. #include <rtdevice.h>
  15. #include <lcd_ili9341.h>
  16. #if defined(NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER)
  17. #if !defined(NU_PKG_ILI9341_LINE_BUFFER_NUMBER)
  18. #define NU_PKG_ILI9341_LINE_BUFFER_NUMBER YSIZE_PHYS
  19. #endif
  20. #endif
  21. #define ili9341_delay_ms(ms) rt_thread_mdelay(ms)
  22. static struct rt_device_graphic_info g_Ili9341Info =
  23. {
  24. .bits_per_pixel = 16,
  25. .pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB565,
  26. .framebuffer = RT_NULL,
  27. .width = XSIZE_PHYS,
  28. .pitch = XSIZE_PHYS * 2,
  29. .height = YSIZE_PHYS
  30. };
  31. static rt_err_t ili9341_pin_init(void)
  32. {
  33. rt_pin_mode(BOARD_USING_ILI9341_PIN_DC, PIN_MODE_OUTPUT);
  34. rt_pin_mode(BOARD_USING_ILI9341_PIN_RESET, PIN_MODE_OUTPUT);
  35. rt_pin_mode(BOARD_USING_ILI9341_PIN_BACKLIGHT, PIN_MODE_OUTPUT);
  36. SET_RS;
  37. SET_RST;
  38. SET_BACKLIGHT_OFF;
  39. return RT_EOK;
  40. }
  41. static rt_err_t ili9341_lcd_init(rt_device_t dev)
  42. {
  43. /* Hardware reset */
  44. SET_RST;
  45. ili9341_delay_ms(5); // Delay 5ms
  46. CLR_RST;
  47. ili9341_delay_ms(20); // Delay 20ms
  48. SET_RST;
  49. ili9341_delay_ms(40); // Delay 40ms
  50. /* Initial control registers */
  51. ili9341_send_cmd(0xCB);
  52. ili9341_send_cmd_parameter(0x39);
  53. ili9341_send_cmd_parameter(0x2C);
  54. ili9341_send_cmd_parameter(0x00);
  55. ili9341_send_cmd_parameter(0x34);
  56. ili9341_send_cmd_parameter(0x02);
  57. ili9341_send_cmd(0xCF);
  58. ili9341_send_cmd_parameter(0x00);
  59. ili9341_send_cmd_parameter(0xC1);
  60. ili9341_send_cmd_parameter(0x30);
  61. ili9341_send_cmd(0xE8);
  62. ili9341_send_cmd_parameter(0x85);
  63. ili9341_send_cmd_parameter(0x00);
  64. ili9341_send_cmd_parameter(0x78);
  65. ili9341_send_cmd(0xEA);
  66. ili9341_send_cmd_parameter(0x00);
  67. ili9341_send_cmd_parameter(0x00);
  68. ili9341_send_cmd(0xED);
  69. ili9341_send_cmd_parameter(0x64);
  70. ili9341_send_cmd_parameter(0x03);
  71. ili9341_send_cmd_parameter(0x12);
  72. ili9341_send_cmd_parameter(0x81);
  73. ili9341_send_cmd(0xF7);
  74. ili9341_send_cmd_parameter(0x20);
  75. ili9341_send_cmd(0xC0);
  76. ili9341_send_cmd_parameter(0x23);
  77. ili9341_send_cmd(0xC1);
  78. ili9341_send_cmd_parameter(0x10);
  79. ili9341_send_cmd(0xC5);
  80. ili9341_send_cmd_parameter(0x3e);
  81. ili9341_send_cmd_parameter(0x28);
  82. ili9341_send_cmd(0xC7);
  83. ili9341_send_cmd_parameter(0x86);
  84. ili9341_send_cmd(0x36);
  85. if (g_Ili9341Info.width == 240)
  86. ili9341_send_cmd_parameter(0x48); // for 240x320
  87. else
  88. ili9341_send_cmd_parameter(0xE8); // for 320x240
  89. ili9341_send_cmd(0x3A);
  90. ili9341_send_cmd_parameter(0x55);
  91. ili9341_send_cmd(0xB1);
  92. ili9341_send_cmd_parameter(0x00);
  93. ili9341_send_cmd_parameter(0x18);
  94. ili9341_send_cmd(0xB6);
  95. ili9341_send_cmd_parameter(0x08);
  96. ili9341_send_cmd_parameter(0x82);
  97. ili9341_send_cmd_parameter(0x27);
  98. ili9341_send_cmd(0xF2);
  99. ili9341_send_cmd_parameter(0x00);
  100. ili9341_send_cmd(0x26);
  101. ili9341_send_cmd_parameter(0x01);
  102. ili9341_send_cmd(0xE0);
  103. ili9341_send_cmd_parameter(0x0F);
  104. ili9341_send_cmd_parameter(0x31);
  105. ili9341_send_cmd_parameter(0x2B);
  106. ili9341_send_cmd_parameter(0x0C);
  107. ili9341_send_cmd_parameter(0x0E);
  108. ili9341_send_cmd_parameter(0x08);
  109. ili9341_send_cmd_parameter(0x4E);
  110. ili9341_send_cmd_parameter(0xF1);
  111. ili9341_send_cmd_parameter(0x37);
  112. ili9341_send_cmd_parameter(0x07);
  113. ili9341_send_cmd_parameter(0x10);
  114. ili9341_send_cmd_parameter(0x03);
  115. ili9341_send_cmd_parameter(0x0E);
  116. ili9341_send_cmd_parameter(0x09);
  117. ili9341_send_cmd_parameter(0x00);
  118. ili9341_send_cmd(0xE1);
  119. ili9341_send_cmd_parameter(0x00);
  120. ili9341_send_cmd_parameter(0x0E);
  121. ili9341_send_cmd_parameter(0x14);
  122. ili9341_send_cmd_parameter(0x03);
  123. ili9341_send_cmd_parameter(0x11);
  124. ili9341_send_cmd_parameter(0x07);
  125. ili9341_send_cmd_parameter(0x31);
  126. ili9341_send_cmd_parameter(0xC1);
  127. ili9341_send_cmd_parameter(0x48);
  128. ili9341_send_cmd_parameter(0x08);
  129. ili9341_send_cmd_parameter(0x0F);
  130. ili9341_send_cmd_parameter(0x0C);
  131. ili9341_send_cmd_parameter(0x31);
  132. ili9341_send_cmd_parameter(0x36);
  133. ili9341_send_cmd_parameter(0x0F);
  134. ili9341_send_cmd(0x11);
  135. ili9341_delay_ms(120); // Delay 120ms
  136. ili9341_send_cmd(0x29); //Display on
  137. SET_BACKLIGHT_ON;
  138. return RT_EOK;
  139. }
  140. #if defined(NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER)
  141. static void ili9341_fillrect(uint16_t *pixels, struct rt_device_rect_info *pRectInfo)
  142. {
  143. ili9341_set_column(pRectInfo->x, pRectInfo->x + pRectInfo->width - 1);
  144. ili9341_set_page(pRectInfo->y, pRectInfo->y + pRectInfo->height - 1);
  145. ili9341_send_cmd(0x2c);
  146. ili9341_send_pixels(pixels, pRectInfo->height * pRectInfo->width * 2);
  147. }
  148. #endif
  149. static void ili9341_fillscreen(rt_uint16_t color)
  150. {
  151. #if defined(NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER)
  152. struct rt_device_rect_info rectinfo;
  153. int filled_line_num = 0;
  154. while (filled_line_num < YSIZE_PHYS)
  155. {
  156. int pixel_count;
  157. rectinfo.x = 0;
  158. rectinfo.y = filled_line_num;
  159. rectinfo.width = XSIZE_PHYS;
  160. rectinfo.height = (NU_PKG_ILI9341_LINE_BUFFER_NUMBER < YSIZE_PHYS) ? NU_PKG_ILI9341_LINE_BUFFER_NUMBER : YSIZE_PHYS;
  161. pixel_count = XSIZE_PHYS * NU_PKG_ILI9341_LINE_BUFFER_NUMBER;
  162. rt_uint16_t *pu16ShadowBuf = (rt_uint16_t *)g_Ili9341Info.framebuffer;
  163. while (pixel_count > 0)
  164. {
  165. *pu16ShadowBuf++ = color;
  166. pixel_count--;
  167. }
  168. ili9341_fillrect((uint16_t *)g_Ili9341Info.framebuffer, &rectinfo);
  169. filled_line_num += NU_PKG_ILI9341_LINE_BUFFER_NUMBER;
  170. }
  171. #else
  172. ili9341_set_column(0, (XSIZE_PHYS - 1));
  173. ili9341_set_page(0, (YSIZE_PHYS - 1));
  174. ili9341_send_cmd(0x2c);
  175. for (int i = 0; i < (XSIZE_PHYS * YSIZE_PHYS); i++)
  176. ili9341_send_pixel_data(color);
  177. #endif
  178. }
  179. static void ili9341_lcd_set_pixel(const char *color, int x, int y)
  180. {
  181. ili9341_set_column(x, x);
  182. ili9341_set_page(y, y);
  183. ili9341_send_cmd(0x2c);
  184. ili9341_send_pixel_data(*(uint16_t *)color);
  185. }
  186. static void ili9341_lcd_draw_hline(const char *pixel, int x1, int x2, int y)
  187. {
  188. ili9341_set_column(x1, x2);
  189. ili9341_set_page(y, y);
  190. ili9341_send_cmd(0x2c);
  191. for (; x1 < x2; x1++)
  192. ili9341_send_pixel_data(*(uint16_t *)pixel);
  193. }
  194. static void ili9341_lcd_draw_vline(const char *pixel, int x, int y1, int y2)
  195. {
  196. ili9341_set_column(x, x);
  197. ili9341_set_page(y1, y2);
  198. ili9341_send_cmd(0x2c);
  199. for (; y1 < y2; y1++)
  200. ili9341_send_pixel_data(*(uint16_t *)pixel);
  201. }
  202. static void ili9341_lcd_blit_line(const char *pixels, int x, int y, rt_size_t size)
  203. {
  204. rt_uint16_t *ptr = (rt_uint16_t *)pixels;
  205. ili9341_set_column(x, x + size);
  206. ili9341_set_page(y, y);
  207. ili9341_send_cmd(0x2c);
  208. while (size--)
  209. ili9341_send_pixel_data(*ptr++);
  210. }
  211. static rt_err_t ili9341_lcd_open(rt_device_t dev, rt_uint16_t oflag)
  212. {
  213. return RT_EOK;
  214. }
  215. static rt_err_t ili9341_lcd_close(rt_device_t dev)
  216. {
  217. return RT_EOK;
  218. }
  219. static rt_err_t ili9341_lcd_control(rt_device_t dev, int cmd, void *args)
  220. {
  221. switch (cmd)
  222. {
  223. case RTGRAPHIC_CTRL_GET_INFO:
  224. {
  225. struct rt_device_graphic_info *info;
  226. info = (struct rt_device_graphic_info *) args;
  227. RT_ASSERT(info != RT_NULL);
  228. rt_memcpy(args, (void *)&g_Ili9341Info, sizeof(struct rt_device_graphic_info));
  229. }
  230. break;
  231. case RTGRAPHIC_CTRL_RECT_UPDATE:
  232. {
  233. #if defined(NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER)
  234. struct rt_device_rect_info *psRectInfo = (struct rt_device_rect_info *)args;
  235. rt_uint16_t *pixels = (rt_uint16_t *)g_Ili9341Info.framebuffer;
  236. RT_ASSERT(args);
  237. ili9341_fillrect(pixels, psRectInfo);
  238. #else
  239. /* nothong to be done */
  240. #endif
  241. }
  242. break;
  243. default:
  244. return -RT_ERROR;
  245. }
  246. return RT_EOK;
  247. }
  248. static struct rt_device lcd_device;
  249. static struct rt_device_graphic_ops ili9341_ops =
  250. {
  251. ili9341_lcd_set_pixel,
  252. ili9341_lcd_get_pixel,
  253. ili9341_lcd_draw_hline,
  254. ili9341_lcd_draw_vline,
  255. ili9341_lcd_blit_line
  256. };
  257. int rt_hw_lcd_ili9341_init(void)
  258. {
  259. ili9341_pin_init();
  260. /* register lcd device */
  261. lcd_device.type = RT_Device_Class_Graphic;
  262. lcd_device.init = ili9341_lcd_init;
  263. lcd_device.open = ili9341_lcd_open;
  264. lcd_device.close = ili9341_lcd_close;
  265. lcd_device.control = ili9341_lcd_control;
  266. lcd_device.read = RT_NULL;
  267. lcd_device.write = RT_NULL;
  268. lcd_device.user_data = &ili9341_ops;
  269. #if defined(NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER)
  270. g_Ili9341Info.framebuffer = rt_malloc_align((g_Ili9341Info.pitch * NU_PKG_ILI9341_LINE_BUFFER_NUMBER) + 32, 32);
  271. RT_ASSERT(g_Ili9341Info.framebuffer != RT_NULL);
  272. g_Ili9341Info.smem_len = g_Ili9341Info.pitch * NU_PKG_ILI9341_LINE_BUFFER_NUMBER;
  273. #endif
  274. /* register graphic device driver */
  275. rt_device_register(&lcd_device, "lcd", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
  276. return 0;
  277. }
  278. #ifdef RT_USING_FINSH
  279. #define LINE_LEN 32
  280. static void lcd_test(int argc, char *argv[])
  281. {
  282. uint16_t pixels[LINE_LEN];
  283. uint16_t color;
  284. int x, y, i;
  285. x = y = 100;
  286. ili9341_lcd_init(NULL);
  287. color = 0x0; //Black, RGB
  288. rt_kprintf("Brush 0x%X on screen.\n", color);
  289. ili9341_fillscreen(color);
  290. ili9341_lcd_get_pixel((char *)&color, x, y);
  291. rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
  292. color = 0xffff; //White, RGB
  293. rt_kprintf("Brush 0x%X on screen.\n", color);
  294. ili9341_fillscreen(color);
  295. ili9341_lcd_get_pixel((char *)&color, x, y);
  296. rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
  297. color = 0x1f; //Blue, RGB
  298. rt_kprintf("Brush 0x%X on screen.\n", color);
  299. ili9341_fillscreen(color);
  300. ili9341_lcd_get_pixel((char *)&color, x, y);
  301. rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
  302. color = 0x07e0; //Green, RGB
  303. rt_kprintf("Brush 0x%X on screen.\n", color);
  304. ili9341_fillscreen(color);
  305. ili9341_lcd_get_pixel((char *)&color, x, y);
  306. rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
  307. color = 0xf800; //Red, RGB
  308. rt_kprintf("Brush 0x%X on screen.\n", color);
  309. ili9341_fillscreen(color);
  310. ili9341_lcd_get_pixel((char *)&color, x, y);
  311. rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
  312. color = 0xffff; //White, RGB
  313. rt_kprintf("lcd draw hline, pixel: 0x%X, x1: %d, x2: %d, y: %d\n", color, x, x + 20, y);
  314. ili9341_lcd_draw_hline((const char *)&color, x, x + 20, y);
  315. color = 0xffff; //White, RGB
  316. rt_kprintf("lcd draw vline, pixel: 0x%X, x: %d, y: %d\n", color, y, y + 20);
  317. ili9341_lcd_draw_vline((const char *)&color, x, y, y + 20);
  318. for (i = 0; i < LINE_LEN; i++)
  319. pixels[i] = 20 + i * 5;
  320. x = y = 50;
  321. rt_kprintf("lcd blit line, start: x: %d, y: %d\n", x, y);
  322. ili9341_lcd_blit_line((const char *)&pixels[0], x, y, LINE_LEN);
  323. x = y = 200;
  324. color = 0x07E0; //Green, RGB
  325. rt_kprintf("lcd set pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
  326. ili9341_lcd_set_pixel((const char *)&color, x, y);
  327. color = 0x0;
  328. ili9341_lcd_get_pixel((char *)&color, x, y);
  329. rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
  330. x = y = 200;
  331. color = 0x1f; //Blue, RGB
  332. rt_kprintf("lcd set pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
  333. ili9341_lcd_set_pixel((const char *)&color, x, y);
  334. color = 0x0;
  335. ili9341_lcd_get_pixel((char *)&color, x, y);
  336. rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
  337. x = y = 200;
  338. color = 0xf800; //Red, RGB
  339. rt_kprintf("lcd set pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
  340. ili9341_lcd_set_pixel((const char *)&color, x, y);
  341. color = 0x0;
  342. ili9341_lcd_get_pixel((char *)&color, x, y);
  343. rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
  344. }
  345. MSH_CMD_EXPORT(lcd_test, test lcd display);
  346. #endif
  347. #endif /* if defined(NU_PKG_USING_ILI9341) */