123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427 |
- /**************************************************************************//**
- *
- * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-1-16 Wayne First version
- *
- ******************************************************************************/
- #include <rtconfig.h>
- #if defined(NU_PKG_USING_ILI9341)
- #include <rtdevice.h>
- #include <lcd_ili9341.h>
- #if defined(NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER)
- #if !defined(NU_PKG_ILI9341_LINE_BUFFER_NUMBER)
- #define NU_PKG_ILI9341_LINE_BUFFER_NUMBER YSIZE_PHYS
- #endif
- #endif
- #define ili9341_delay_ms(ms) rt_thread_mdelay(ms)
- static struct rt_device_graphic_info g_Ili9341Info =
- {
- .bits_per_pixel = 16,
- .pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB565,
- .framebuffer = RT_NULL,
- .width = XSIZE_PHYS,
- .pitch = XSIZE_PHYS * 2,
- .height = YSIZE_PHYS
- };
- static rt_err_t ili9341_pin_init(void)
- {
- rt_pin_mode(BOARD_USING_ILI9341_PIN_DC, PIN_MODE_OUTPUT);
- rt_pin_mode(BOARD_USING_ILI9341_PIN_RESET, PIN_MODE_OUTPUT);
- rt_pin_mode(BOARD_USING_ILI9341_PIN_BACKLIGHT, PIN_MODE_OUTPUT);
- SET_RS;
- SET_RST;
- SET_BACKLIGHT_OFF;
- return RT_EOK;
- }
- static rt_err_t ili9341_lcd_init(rt_device_t dev)
- {
- /* Hardware reset */
- SET_RST;
- ili9341_delay_ms(5); // Delay 5ms
- CLR_RST;
- ili9341_delay_ms(20); // Delay 20ms
- SET_RST;
- ili9341_delay_ms(40); // Delay 40ms
- /* Initial control registers */
- ili9341_send_cmd(0xCB);
- ili9341_send_cmd_parameter(0x39);
- ili9341_send_cmd_parameter(0x2C);
- ili9341_send_cmd_parameter(0x00);
- ili9341_send_cmd_parameter(0x34);
- ili9341_send_cmd_parameter(0x02);
- ili9341_send_cmd(0xCF);
- ili9341_send_cmd_parameter(0x00);
- ili9341_send_cmd_parameter(0xC1);
- ili9341_send_cmd_parameter(0x30);
- ili9341_send_cmd(0xE8);
- ili9341_send_cmd_parameter(0x85);
- ili9341_send_cmd_parameter(0x00);
- ili9341_send_cmd_parameter(0x78);
- ili9341_send_cmd(0xEA);
- ili9341_send_cmd_parameter(0x00);
- ili9341_send_cmd_parameter(0x00);
- ili9341_send_cmd(0xED);
- ili9341_send_cmd_parameter(0x64);
- ili9341_send_cmd_parameter(0x03);
- ili9341_send_cmd_parameter(0x12);
- ili9341_send_cmd_parameter(0x81);
- ili9341_send_cmd(0xF7);
- ili9341_send_cmd_parameter(0x20);
- ili9341_send_cmd(0xC0);
- ili9341_send_cmd_parameter(0x23);
- ili9341_send_cmd(0xC1);
- ili9341_send_cmd_parameter(0x10);
- ili9341_send_cmd(0xC5);
- ili9341_send_cmd_parameter(0x3e);
- ili9341_send_cmd_parameter(0x28);
- ili9341_send_cmd(0xC7);
- ili9341_send_cmd_parameter(0x86);
- ili9341_send_cmd(0x36);
- if (g_Ili9341Info.width == 240)
- ili9341_send_cmd_parameter(0x48); // for 240x320
- else
- ili9341_send_cmd_parameter(0xE8); // for 320x240
- ili9341_send_cmd(0x3A);
- ili9341_send_cmd_parameter(0x55);
- ili9341_send_cmd(0xB1);
- ili9341_send_cmd_parameter(0x00);
- ili9341_send_cmd_parameter(0x18);
- ili9341_send_cmd(0xB6);
- ili9341_send_cmd_parameter(0x08);
- ili9341_send_cmd_parameter(0x82);
- ili9341_send_cmd_parameter(0x27);
- ili9341_send_cmd(0xF2);
- ili9341_send_cmd_parameter(0x00);
- ili9341_send_cmd(0x26);
- ili9341_send_cmd_parameter(0x01);
- ili9341_send_cmd(0xE0);
- ili9341_send_cmd_parameter(0x0F);
- ili9341_send_cmd_parameter(0x31);
- ili9341_send_cmd_parameter(0x2B);
- ili9341_send_cmd_parameter(0x0C);
- ili9341_send_cmd_parameter(0x0E);
- ili9341_send_cmd_parameter(0x08);
- ili9341_send_cmd_parameter(0x4E);
- ili9341_send_cmd_parameter(0xF1);
- ili9341_send_cmd_parameter(0x37);
- ili9341_send_cmd_parameter(0x07);
- ili9341_send_cmd_parameter(0x10);
- ili9341_send_cmd_parameter(0x03);
- ili9341_send_cmd_parameter(0x0E);
- ili9341_send_cmd_parameter(0x09);
- ili9341_send_cmd_parameter(0x00);
- ili9341_send_cmd(0xE1);
- ili9341_send_cmd_parameter(0x00);
- ili9341_send_cmd_parameter(0x0E);
- ili9341_send_cmd_parameter(0x14);
- ili9341_send_cmd_parameter(0x03);
- ili9341_send_cmd_parameter(0x11);
- ili9341_send_cmd_parameter(0x07);
- ili9341_send_cmd_parameter(0x31);
- ili9341_send_cmd_parameter(0xC1);
- ili9341_send_cmd_parameter(0x48);
- ili9341_send_cmd_parameter(0x08);
- ili9341_send_cmd_parameter(0x0F);
- ili9341_send_cmd_parameter(0x0C);
- ili9341_send_cmd_parameter(0x31);
- ili9341_send_cmd_parameter(0x36);
- ili9341_send_cmd_parameter(0x0F);
- ili9341_send_cmd(0x11);
- ili9341_delay_ms(120); // Delay 120ms
- ili9341_send_cmd(0x29); //Display on
- SET_BACKLIGHT_ON;
- return RT_EOK;
- }
- #if defined(NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER)
- static void ili9341_fillrect(uint16_t *pixels, struct rt_device_rect_info *pRectInfo)
- {
- ili9341_set_column(pRectInfo->x, pRectInfo->x + pRectInfo->width - 1);
- ili9341_set_page(pRectInfo->y, pRectInfo->y + pRectInfo->height - 1);
- ili9341_send_cmd(0x2c);
- ili9341_send_pixels(pixels, pRectInfo->height * pRectInfo->width * 2);
- }
- #endif
- static void ili9341_fillscreen(rt_uint16_t color)
- {
- #if defined(NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER)
- struct rt_device_rect_info rectinfo;
- int filled_line_num = 0;
- while (filled_line_num < YSIZE_PHYS)
- {
- int pixel_count;
- rectinfo.x = 0;
- rectinfo.y = filled_line_num;
- rectinfo.width = XSIZE_PHYS;
- rectinfo.height = (NU_PKG_ILI9341_LINE_BUFFER_NUMBER < YSIZE_PHYS) ? NU_PKG_ILI9341_LINE_BUFFER_NUMBER : YSIZE_PHYS;
- pixel_count = XSIZE_PHYS * NU_PKG_ILI9341_LINE_BUFFER_NUMBER;
- rt_uint16_t *pu16ShadowBuf = (rt_uint16_t *)g_Ili9341Info.framebuffer;
- while (pixel_count > 0)
- {
- *pu16ShadowBuf++ = color;
- pixel_count--;
- }
- ili9341_fillrect((uint16_t *)g_Ili9341Info.framebuffer, &rectinfo);
- filled_line_num += NU_PKG_ILI9341_LINE_BUFFER_NUMBER;
- }
- #else
- ili9341_set_column(0, (XSIZE_PHYS - 1));
- ili9341_set_page(0, (YSIZE_PHYS - 1));
- ili9341_send_cmd(0x2c);
- for (int i = 0; i < (XSIZE_PHYS * YSIZE_PHYS); i++)
- ili9341_send_pixel_data(color);
- #endif
- }
- static void ili9341_lcd_set_pixel(const char *color, int x, int y)
- {
- ili9341_set_column(x, x);
- ili9341_set_page(y, y);
- ili9341_send_cmd(0x2c);
- ili9341_send_pixel_data(*(uint16_t *)color);
- }
- static void ili9341_lcd_draw_hline(const char *pixel, int x1, int x2, int y)
- {
- ili9341_set_column(x1, x2);
- ili9341_set_page(y, y);
- ili9341_send_cmd(0x2c);
- for (; x1 < x2; x1++)
- ili9341_send_pixel_data(*(uint16_t *)pixel);
- }
- static void ili9341_lcd_draw_vline(const char *pixel, int x, int y1, int y2)
- {
- ili9341_set_column(x, x);
- ili9341_set_page(y1, y2);
- ili9341_send_cmd(0x2c);
- for (; y1 < y2; y1++)
- ili9341_send_pixel_data(*(uint16_t *)pixel);
- }
- static void ili9341_lcd_blit_line(const char *pixels, int x, int y, rt_size_t size)
- {
- rt_uint16_t *ptr = (rt_uint16_t *)pixels;
- ili9341_set_column(x, x + size);
- ili9341_set_page(y, y);
- ili9341_send_cmd(0x2c);
- while (size--)
- ili9341_send_pixel_data(*ptr++);
- }
- static rt_err_t ili9341_lcd_open(rt_device_t dev, rt_uint16_t oflag)
- {
- return RT_EOK;
- }
- static rt_err_t ili9341_lcd_close(rt_device_t dev)
- {
- return RT_EOK;
- }
- static rt_err_t ili9341_lcd_control(rt_device_t dev, int cmd, void *args)
- {
- switch (cmd)
- {
- case RTGRAPHIC_CTRL_GET_INFO:
- {
- struct rt_device_graphic_info *info;
- info = (struct rt_device_graphic_info *) args;
- RT_ASSERT(info != RT_NULL);
- rt_memcpy(args, (void *)&g_Ili9341Info, sizeof(struct rt_device_graphic_info));
- }
- break;
- case RTGRAPHIC_CTRL_RECT_UPDATE:
- {
- #if defined(NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER)
- struct rt_device_rect_info *psRectInfo = (struct rt_device_rect_info *)args;
- rt_uint16_t *pixels = (rt_uint16_t *)g_Ili9341Info.framebuffer;
- RT_ASSERT(args);
- ili9341_fillrect(pixels, psRectInfo);
- #else
- /* nothong to be done */
- #endif
- }
- break;
- default:
- return -RT_ERROR;
- }
- return RT_EOK;
- }
- static struct rt_device lcd_device;
- static struct rt_device_graphic_ops ili9341_ops =
- {
- ili9341_lcd_set_pixel,
- ili9341_lcd_get_pixel,
- ili9341_lcd_draw_hline,
- ili9341_lcd_draw_vline,
- ili9341_lcd_blit_line
- };
- int rt_hw_lcd_ili9341_init(void)
- {
- ili9341_pin_init();
- /* register lcd device */
- lcd_device.type = RT_Device_Class_Graphic;
- lcd_device.init = ili9341_lcd_init;
- lcd_device.open = ili9341_lcd_open;
- lcd_device.close = ili9341_lcd_close;
- lcd_device.control = ili9341_lcd_control;
- lcd_device.read = RT_NULL;
- lcd_device.write = RT_NULL;
- lcd_device.user_data = &ili9341_ops;
- #if defined(NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER)
- g_Ili9341Info.framebuffer = rt_malloc_align((g_Ili9341Info.pitch * NU_PKG_ILI9341_LINE_BUFFER_NUMBER) + 32, 32);
- RT_ASSERT(g_Ili9341Info.framebuffer != RT_NULL);
- g_Ili9341Info.smem_len = g_Ili9341Info.pitch * NU_PKG_ILI9341_LINE_BUFFER_NUMBER;
- #endif
- /* register graphic device driver */
- rt_device_register(&lcd_device, "lcd", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
- return 0;
- }
- #ifdef RT_USING_FINSH
- #define LINE_LEN 32
- static void lcd_test(int argc, char *argv[])
- {
- uint16_t pixels[LINE_LEN];
- uint16_t color;
- int x, y, i;
- x = y = 100;
- ili9341_lcd_init(NULL);
- color = 0x0; //Black, RGB
- rt_kprintf("Brush 0x%X on screen.\n", color);
- ili9341_fillscreen(color);
- ili9341_lcd_get_pixel((char *)&color, x, y);
- rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
- color = 0xffff; //White, RGB
- rt_kprintf("Brush 0x%X on screen.\n", color);
- ili9341_fillscreen(color);
- ili9341_lcd_get_pixel((char *)&color, x, y);
- rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
- color = 0x1f; //Blue, RGB
- rt_kprintf("Brush 0x%X on screen.\n", color);
- ili9341_fillscreen(color);
- ili9341_lcd_get_pixel((char *)&color, x, y);
- rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
- color = 0x07e0; //Green, RGB
- rt_kprintf("Brush 0x%X on screen.\n", color);
- ili9341_fillscreen(color);
- ili9341_lcd_get_pixel((char *)&color, x, y);
- rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
- color = 0xf800; //Red, RGB
- rt_kprintf("Brush 0x%X on screen.\n", color);
- ili9341_fillscreen(color);
- ili9341_lcd_get_pixel((char *)&color, x, y);
- rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
- color = 0xffff; //White, RGB
- rt_kprintf("lcd draw hline, pixel: 0x%X, x1: %d, x2: %d, y: %d\n", color, x, x + 20, y);
- ili9341_lcd_draw_hline((const char *)&color, x, x + 20, y);
- color = 0xffff; //White, RGB
- rt_kprintf("lcd draw vline, pixel: 0x%X, x: %d, y: %d\n", color, y, y + 20);
- ili9341_lcd_draw_vline((const char *)&color, x, y, y + 20);
- for (i = 0; i < LINE_LEN; i++)
- pixels[i] = 20 + i * 5;
- x = y = 50;
- rt_kprintf("lcd blit line, start: x: %d, y: %d\n", x, y);
- ili9341_lcd_blit_line((const char *)&pixels[0], x, y, LINE_LEN);
- x = y = 200;
- color = 0x07E0; //Green, RGB
- rt_kprintf("lcd set pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
- ili9341_lcd_set_pixel((const char *)&color, x, y);
- color = 0x0;
- ili9341_lcd_get_pixel((char *)&color, x, y);
- rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
- x = y = 200;
- color = 0x1f; //Blue, RGB
- rt_kprintf("lcd set pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
- ili9341_lcd_set_pixel((const char *)&color, x, y);
- color = 0x0;
- ili9341_lcd_get_pixel((char *)&color, x, y);
- rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
- x = y = 200;
- color = 0xf800; //Red, RGB
- rt_kprintf("lcd set pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
- ili9341_lcd_set_pixel((const char *)&color, x, y);
- color = 0x0;
- ili9341_lcd_get_pixel((char *)&color, x, y);
- rt_kprintf("lcd get pixel, pixel: 0x%X, x: %d, y: %d\n", color, x, y);
- }
- MSH_CMD_EXPORT(lcd_test, test lcd display);
- #endif
- #endif /* if defined(NU_PKG_USING_ILI9341) */
|