lcd_ssd1963.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  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. * 2022-2-23 Wayne First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(NU_PKG_USING_SSD1963)
  14. #include <rtdevice.h>
  15. #include <lcd_ssd1963.h>
  16. #if defined(NU_PKG_SSD1963_WITH_OFFSCREEN_FRAMEBUFFER)
  17. #if !defined(NU_PKG_SSD1963_LINE_BUFFER_NUMBER)
  18. #define NU_PKG_SSD1963_LINE_BUFFER_NUMBER YSIZE_PHYS
  19. #endif
  20. #endif
  21. #define ssd1963_delay_ms(ms) rt_thread_mdelay(ms)
  22. static void ssd1963_fillscreen(rt_uint16_t color);
  23. static struct rt_device_graphic_info g_SSD1963Info =
  24. {
  25. .bits_per_pixel = 16,
  26. .pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB565,
  27. .framebuffer = RT_NULL,
  28. .width = XSIZE_PHYS,
  29. .pitch = XSIZE_PHYS * 2,
  30. .height = YSIZE_PHYS
  31. };
  32. static rt_err_t ssd1963_pin_init(void)
  33. {
  34. rt_pin_mode(BOARD_USING_SSD1963_PIN_DC, PIN_MODE_OUTPUT);
  35. rt_pin_mode(BOARD_USING_SSD1963_PIN_RESET, PIN_MODE_OUTPUT);
  36. rt_pin_mode(BOARD_USING_SSD1963_PIN_BACKLIGHT, PIN_MODE_OUTPUT);
  37. rt_pin_mode(BOARD_USING_SSD1963_PIN_DISPLAY, PIN_MODE_OUTPUT);
  38. CLR_RS;
  39. CLR_RST;
  40. SET_BACKLIGHT_OFF;
  41. SET_DISP_OFF;
  42. return RT_EOK;
  43. }
  44. static rt_err_t ssd1963_lcd_init(rt_device_t dev)
  45. {
  46. /* Hardware reset */
  47. SET_RST;
  48. ssd1963_delay_ms(5); // Delay 5ms
  49. CLR_RST;
  50. ssd1963_delay_ms(20); // Delay 20ms
  51. SET_RST;
  52. ssd1963_delay_ms(40); // Delay 40ms
  53. /* Initial control registers */
  54. ssd1963_send_cmd(0x01); //Software reset
  55. ssd1963_delay_ms(10);
  56. ssd1963_send_cmd(0xe0); //Start PLL. Before the start, the system was operated with the crystal oscillator or clock input.
  57. ssd1963_send_cmd_parameter(0x01); //0: Disable PLL, 1:Enable PLL.
  58. ssd1963_delay_ms(50);
  59. ssd1963_send_cmd(0xe0);
  60. ssd1963_send_cmd_parameter(0x03); //0: Disable PLL, 1:Enable PLL. 3:Enable+LOCK PLL
  61. ssd1963_delay_ms(5);
  62. ssd1963_send_cmd(0xb0); //SET LCD MODE SET TFT MODE
  63. ssd1963_send_cmd_parameter(0x20); //SET 24Bit, Disable TFT FRC & dithering, DCLK in falling edge, LLINE Active low, LFRAME Active low
  64. ssd1963_send_cmd_parameter(0x00); //SET TFT mode
  65. ssd1963_send_cmd_parameter(0x01); //SET horizontal size=480-1 HightByte
  66. ssd1963_send_cmd_parameter(0xdf); //SET horizontal size=480-1 LowByte
  67. ssd1963_send_cmd_parameter(0x01); //SET vertical size=272-1 HightByte
  68. ssd1963_send_cmd_parameter(0x0f); //SET vertical size=272-1 LowByte
  69. ssd1963_send_cmd_parameter(0x00); //SET even/odd line RGB seq.=RGB
  70. ssd1963_send_cmd(0xf0); //SET pixel data I/F format=16bit(565 format)
  71. ssd1963_send_cmd_parameter(0x03);
  72. //ssd1963_send_cmd(0xf0); //SET pixel data I/F format=8bit (666 format)
  73. //ssd1963_send_cmd_parameter(0x00);
  74. ssd1963_send_cmd(0x36); // SET read from frame buffer to the display is RGB
  75. ssd1963_send_cmd_parameter(0x00);
  76. ssd1963_send_cmd(0xe2);
  77. ssd1963_send_cmd_parameter(0x1d);
  78. ssd1963_send_cmd_parameter(0x02);
  79. ssd1963_send_cmd_parameter(0x54);
  80. ssd1963_send_cmd(0xe6); //SET pixel clock frequency
  81. ssd1963_send_cmd_parameter(0x01);
  82. ssd1963_send_cmd_parameter(0x99);
  83. ssd1963_send_cmd_parameter(0x9a);
  84. ssd1963_send_cmd(0xb4); //SET HBP,
  85. ssd1963_send_cmd_parameter(0x02); //SET HSYNC Tatol = 525
  86. ssd1963_send_cmd_parameter(0x0d);
  87. ssd1963_send_cmd_parameter(0x00); //SET HBP = 20
  88. ssd1963_send_cmd_parameter(0x14);
  89. ssd1963_send_cmd_parameter(0x05); //SET VBP 5
  90. ssd1963_send_cmd_parameter(0x00); //SET Hsync pulse start position
  91. ssd1963_send_cmd_parameter(0x00);
  92. ssd1963_send_cmd_parameter(0x00); //SET Hsync pulse subpixel start position
  93. ssd1963_send_cmd(0xb6); //SET VBP,
  94. ssd1963_send_cmd_parameter(0x01); //SET Vsync total 292
  95. ssd1963_send_cmd_parameter(0x24);
  96. ssd1963_send_cmd_parameter(0x00); //SET VBP = 10
  97. ssd1963_send_cmd_parameter(0x0a);
  98. ssd1963_send_cmd_parameter(0x05); //SET Vsync pulse 5
  99. ssd1963_send_cmd_parameter(0x00); //SET Vsync pulse start position
  100. ssd1963_send_cmd_parameter(0x00);
  101. ssd1963_send_cmd(0x29); //SET display on
  102. ssd1963_delay_ms(5);
  103. ssd1963_fillscreen(0);
  104. SET_DISP_ON;
  105. SET_BACKLIGHT_ON;
  106. return RT_EOK;
  107. }
  108. #if defined(NU_PKG_SSD1963_WITH_OFFSCREEN_FRAMEBUFFER)
  109. static void ssd1963_fillrect(uint16_t *pixels, struct rt_device_rect_info *pRectInfo)
  110. {
  111. ssd1963_set_column(pRectInfo->x, pRectInfo->x + pRectInfo->width - 1);
  112. ssd1963_set_page(pRectInfo->y, pRectInfo->y + pRectInfo->height - 1);
  113. ssd1963_send_cmd(0x2c);
  114. ssd1963_send_pixels(pixels, pRectInfo->height * pRectInfo->width * 2);
  115. }
  116. #endif
  117. static void ssd1963_fillscreen(rt_uint16_t color)
  118. {
  119. #if defined(NU_PKG_SSD1963_WITH_OFFSCREEN_FRAMEBUFFER)
  120. struct rt_device_rect_info rectinfo;
  121. int filled_line_num = 0;
  122. while (filled_line_num < YSIZE_PHYS)
  123. {
  124. int pixel_count;
  125. rectinfo.x = 0;
  126. rectinfo.y = filled_line_num;
  127. rectinfo.width = XSIZE_PHYS;
  128. rectinfo.height = (NU_PKG_SSD1963_LINE_BUFFER_NUMBER < YSIZE_PHYS) ? NU_PKG_SSD1963_LINE_BUFFER_NUMBER : YSIZE_PHYS;
  129. pixel_count = XSIZE_PHYS * NU_PKG_SSD1963_LINE_BUFFER_NUMBER;
  130. rt_uint16_t *pu16ShadowBuf = (rt_uint16_t *)g_SSD1963Info.framebuffer;
  131. while (pixel_count > 0)
  132. {
  133. *pu16ShadowBuf++ = color;
  134. pixel_count--;
  135. }
  136. ssd1963_fillrect((uint16_t *)g_SSD1963Info.framebuffer, &rectinfo);
  137. filled_line_num += NU_PKG_SSD1963_LINE_BUFFER_NUMBER;
  138. }
  139. #else
  140. ssd1963_set_column(0, (XSIZE_PHYS - 1));
  141. ssd1963_set_page(0, (YSIZE_PHYS - 1));
  142. ssd1963_send_cmd(0x2c);
  143. for (int i = 0; i < (XSIZE_PHYS * YSIZE_PHYS); i++)
  144. ssd1963_send_pixel_data(color);
  145. #endif
  146. }
  147. static void ssd1963_lcd_set_pixel(const char *color, int x, int y)
  148. {
  149. ssd1963_set_column(x, x);
  150. ssd1963_set_page(y, y);
  151. ssd1963_send_cmd(0x2c);
  152. ssd1963_send_pixel_data(*(uint16_t *)color);
  153. }
  154. static void ssd1963_lcd_draw_hline(const char *pixel, int x1, int x2, int y)
  155. {
  156. ssd1963_set_column(x1, x2);
  157. ssd1963_set_page(y, y);
  158. ssd1963_send_cmd(0x2c);
  159. for (; x1 < x2; x1++)
  160. ssd1963_send_pixel_data(*(uint16_t *)pixel);
  161. }
  162. static void ssd1963_lcd_draw_vline(const char *pixel, int x, int y1, int y2)
  163. {
  164. ssd1963_set_column(x, x);
  165. ssd1963_set_page(y1, y2);
  166. ssd1963_send_cmd(0x2c);
  167. for (; y1 < y2; y1++)
  168. ssd1963_send_pixel_data(*(uint16_t *)pixel);
  169. }
  170. static void ssd1963_lcd_blit_line(const char *pixels, int x, int y, rt_size_t size)
  171. {
  172. rt_uint16_t *ptr = (rt_uint16_t *)pixels;
  173. ssd1963_set_column(x, x + size);
  174. ssd1963_set_page(y, y);
  175. ssd1963_send_cmd(0x2c);
  176. while (size--)
  177. ssd1963_send_pixel_data(*ptr++);
  178. }
  179. static rt_err_t ssd1963_lcd_open(rt_device_t dev, rt_uint16_t oflag)
  180. {
  181. return RT_EOK;
  182. }
  183. static rt_err_t ssd1963_lcd_close(rt_device_t dev)
  184. {
  185. return RT_EOK;
  186. }
  187. static rt_err_t ssd1963_lcd_control(rt_device_t dev, int cmd, void *args)
  188. {
  189. switch (cmd)
  190. {
  191. case RTGRAPHIC_CTRL_GET_INFO:
  192. {
  193. struct rt_device_graphic_info *info;
  194. info = (struct rt_device_graphic_info *) args;
  195. RT_ASSERT(info != RT_NULL);
  196. rt_memcpy(args, (void *)&g_SSD1963Info, sizeof(struct rt_device_graphic_info));
  197. }
  198. break;
  199. case RTGRAPHIC_CTRL_RECT_UPDATE:
  200. {
  201. #if defined(NU_PKG_SSD1963_WITH_OFFSCREEN_FRAMEBUFFER)
  202. struct rt_device_rect_info *psRectInfo = (struct rt_device_rect_info *)args;
  203. rt_uint16_t *pixels = (rt_uint16_t *)g_SSD1963Info.framebuffer;
  204. RT_ASSERT(args);
  205. ssd1963_fillrect(pixels, psRectInfo);
  206. #else
  207. /* nothong to be done */
  208. #endif
  209. }
  210. break;
  211. default:
  212. break;
  213. }
  214. return RT_EOK;
  215. }
  216. static struct rt_device lcd_device;
  217. static struct rt_device_graphic_ops ssd1963_ops =
  218. {
  219. ssd1963_lcd_set_pixel,
  220. ssd1963_lcd_get_pixel,
  221. ssd1963_lcd_draw_hline,
  222. ssd1963_lcd_draw_vline,
  223. ssd1963_lcd_blit_line
  224. };
  225. int rt_hw_lcd_ssd1963_init(void)
  226. {
  227. ssd1963_pin_init();
  228. /* register lcd device */
  229. lcd_device.type = RT_Device_Class_Graphic;
  230. lcd_device.init = ssd1963_lcd_init;
  231. lcd_device.open = ssd1963_lcd_open;
  232. lcd_device.close = ssd1963_lcd_close;
  233. lcd_device.control = ssd1963_lcd_control;
  234. lcd_device.read = RT_NULL;
  235. lcd_device.write = RT_NULL;
  236. lcd_device.user_data = &ssd1963_ops;
  237. #if defined(NU_PKG_SSD1963_WITH_OFFSCREEN_FRAMEBUFFER)
  238. g_SSD1963Info.framebuffer = rt_malloc_align((g_SSD1963Info.pitch * NU_PKG_SSD1963_LINE_BUFFER_NUMBER) + 32, 32);
  239. RT_ASSERT(g_SSD1963Info.framebuffer != RT_NULL);
  240. g_SSD1963Info.smem_len = g_SSD1963Info.pitch * NU_PKG_SSD1963_LINE_BUFFER_NUMBER;
  241. #endif
  242. /* register graphic device driver */
  243. rt_device_register(&lcd_device, "lcd", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
  244. return 0;
  245. }
  246. #ifdef RT_USING_FINSH
  247. #define LINE_LEN 32
  248. static void lcd_test(int argc, char *argv[])
  249. {
  250. uint16_t pixels[LINE_LEN];
  251. uint16_t color;
  252. int x, y, i;
  253. x = y = 100;
  254. ssd1963_lcd_init(NULL);
  255. color = 0x0; //Black, RGB
  256. rt_kprintf("Brush 0x%X on screen.\n", color);
  257. ssd1963_fillscreen(color);
  258. ssd1963_lcd_get_pixel((char *)&color, x, y);
  259. rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
  260. color = 0xffff; //White, RGB
  261. rt_kprintf("Brush 0x%X on screen.\n", color);
  262. ssd1963_fillscreen(color);
  263. ssd1963_lcd_get_pixel((char *)&color, x, y);
  264. rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
  265. color = 0x1f; //Blue, RGB
  266. rt_kprintf("Brush 0x%X on screen.\n", color);
  267. ssd1963_fillscreen(color);
  268. ssd1963_lcd_get_pixel((char *)&color, x, y);
  269. rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
  270. color = 0x07e0; //Green, RGB
  271. rt_kprintf("Brush 0x%X on screen.\n", color);
  272. ssd1963_fillscreen(color);
  273. ssd1963_lcd_get_pixel((char *)&color, x, y);
  274. rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
  275. color = 0xf800; //Red, RGB
  276. rt_kprintf("Brush 0x%X on screen.\n", color);
  277. ssd1963_fillscreen(color);
  278. ssd1963_lcd_get_pixel((char *)&color, x, y);
  279. rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
  280. color = 0xffff; //White, RGB
  281. rt_kprintf("lcd draw hline, pixel: 0x%X, x1: %d, x2: %d, y: %d\n", color, x, x + 20, y);
  282. ssd1963_lcd_draw_hline((const char *)&color, x, x + 20, y);
  283. color = 0xffff; //White, RGB
  284. rt_kprintf("lcd draw vline, pixel: 0x%X, x: %d, y: %d\n", color, y, y + 20);
  285. ssd1963_lcd_draw_vline((const char *)&color, x, y, y + 20);
  286. for (i = 0; i < LINE_LEN; i++)
  287. pixels[i] = 20 + i * 5;
  288. x = y = 50;
  289. rt_kprintf("lcd blit line, start: x: %d, y: %d\n", x, y);
  290. ssd1963_lcd_blit_line((const char *)&pixels[0], x, y, LINE_LEN);
  291. x = y = 200;
  292. color = 0x07E0; //Green, RGB
  293. rt_kprintf("lcd set pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
  294. ssd1963_lcd_set_pixel((const char *)&color, x, y);
  295. color = 0x0;
  296. ssd1963_lcd_get_pixel((char *)&color, x, y);
  297. rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
  298. x = y = 200;
  299. color = 0x1f; //Blue, RGB
  300. rt_kprintf("lcd set pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
  301. ssd1963_lcd_set_pixel((const char *)&color, x, y);
  302. color = 0x0;
  303. ssd1963_lcd_get_pixel((char *)&color, x, y);
  304. rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
  305. x = y = 200;
  306. color = 0xf800; //Red, RGB
  307. rt_kprintf("lcd set pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
  308. ssd1963_lcd_set_pixel((const char *)&color, x, y);
  309. color = 0x0;
  310. ssd1963_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. }
  313. MSH_CMD_EXPORT(lcd_test, test lcd display);
  314. #endif
  315. #endif /* if defined(NU_PKG_USING_SSD1963) */