#include "lcd.h" #include "log.h" #define DIV_NUM 10 #define COL_ADDR_SET 0x2A #define ROW_ADDR_SET 0x2B #define MEMORY_WRITE 0x2C /** * MADCTL(36H): * +---------------------------------------+ * | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 | * | MY | MX | MV | ML | RGB| MH | - | - | * +---------------------------------------+ * [3] 0=RGB,1=BGR */ #define DATA_ACCESS 0x36 /** * COLMOD(3AH): * +---------------------------------------+ * | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 | * | 0 | D6 | D5 | D4 | 0 | D2 | D1 | D0 | * +---------------------------------------+ * [6:4] RGB interface Color format: * 101=65K RGB * 110=262K RGB * [2:0] Control interface color format: * 011=12bit/pixel * 101=16bit/pixel * 110=18bit/pixel * 111=16M truncated */ #define PIXEL_FORMAT 0x3A #define delay_ms(x) rt_thread_mdelay(x) static void st7789_fill(lcd_handle_t *h, uint16_t color); static void write_reg(lcd_handle_t *h, uint8_t reg) { gpio_set(DC_PIN, 0); rt_spi_send(h->dev, ®, 1); } static void write_data(lcd_handle_t *h, uint8_t data) { gpio_set(DC_PIN, 1); rt_spi_send(h->dev, &data, 1); } static void write_reg_data(lcd_handle_t *h, uint8_t reg, uint16_t data) { write_reg(h,reg); write_data(h,data); } static void read_data(lcd_handle_t *h, uint8_t *data, int length) { gpio_set(DC_PIN, 1); rt_spi_transfer(h->dev, RT_NULL, data, length); } static void write_16bit(lcd_handle_t *h, uint16_t data) { uint8_t buf[2]; buf[0] = data >> 8; buf[1] = data & 0xff; gpio_set(DC_PIN, 1); rt_spi_send(h->dev, buf, 2); } void st7789_rotate(lcd_handle_t *h, int rotate) { switch (rotate) { case 0: //h->width = LCD_W; //h->height = LCD_H; write_reg_data(h, DATA_ACCESS, (0 << 3) | (0 << 5) | (0 << 6) | (0 << 7)); /* BGR==0,MV==0,MX==0,MY==0 */ break; case 90: //h->width = LCD_H; //h->height = LCD_W; write_reg_data(h, DATA_ACCESS, (0 << 3) | (1 << 5) | (1 << 6) | (0 << 7)); /* BGR==0,MV==1,MX==0,MY==1 */ break; case 180: //h->width = LCD_W; //h->height = LCD_H; write_reg_data(h, DATA_ACCESS, (0 << 3) | (0 << 5) | (1 << 6) | (1 << 7)); /* BGR==0,MV==0,MX==1,MY==1 */ break; case 270: //h->width = LCD_H; //h->height = LCD_W; write_reg_data(h, DATA_ACCESS, (0 << 3) | (1 << 5) | (0 << 6) | (1 << 7)); /* BGR==0,MV==1,MX==0,MY==1 */ break; default: break; } } static void st7789_set_win(lcd_handle_t *hd, int x, int y, int w, int h) { write_reg(hd,COL_ADDR_SET); write_data(hd,x>>8); write_data(hd,x&0xff); write_data(hd,(x+w-1)>>8); write_data(hd,(x+w-1)&0xff); write_reg(hd,ROW_ADDR_SET); write_data(hd,y>>8); write_data(hd,y&0xff); write_data(hd,(y+h-1)>>8); write_data(hd,(y+h-1)&0xff); write_reg(hd,MEMORY_WRITE); } void st7789_refresh(lcd_handle_t *hd, uint16_t x, uint16_t y, uint16_t w, uint16_t h, void *data, uint32_t len) { int r; st7789_set_win(hd, x, y, x + w - 1, y + h - 1); gpio_set(DC_PIN, 1); r = rt_spi_send(hd->dev, data, len); } static void st7789_reg_init(lcd_handle_t *h) { write_reg(h, DATA_ACCESS); write_data(h, 0x00); write_reg(h, PIXEL_FORMAT); write_data(h, 0X05); //03=RGB444,05=RGB565,06=RGB666 write_reg(h, 0xB2); //Porch Setting write_data(h, 0x0C); write_data(h, 0x0C); write_data(h, 0X00); write_data(h, 0X33); write_data(h, 0X33); write_reg(h, 0xB7); //Gate Control write_data(h, 0x46); write_reg(h, 0xBB); //VCOM Setting write_data(h, 0x1B); write_reg(h, 0xC0); //LCM Control write_data(h, 0x2C); write_reg(h, 0xC2); //VDV and VRH Command Enable write_data(h, 0x01); write_reg(h, 0xC3); //VRH set write_data(h, 0x0F); write_reg(h, 0xC4); //VDV set write_data(h, 0x20); write_reg(h, 0xC6); //Frame Rate Control write_data(h, 0x0F); write_reg(h, 0xD0); //Power Control 1 write_data(h, 0xA4); write_data(h, 0xA1); write_reg(h, 0xD6); write_data(h, 0xA1); write_reg(h, 0xE0); /* set Positive Voltage Gamma */ write_data(h, 0xF0); write_data(h, 0x00); write_data(h, 0x06); write_data(h, 0x04); write_data(h, 0x05); write_data(h, 0x05); write_data(h, 0x31); write_data(h, 0x44); write_data(h, 0x48); write_data(h, 0x36); write_data(h, 0x12); write_data(h, 0x12); write_data(h, 0x2B); write_data(h, 0x34); write_reg(h, 0xE1); /* set Negative Voltage Gamma */ write_data(h, 0XF0); write_data(h, 0X0B); write_data(h, 0X0F); write_data(h, 0X0F); write_data(h, 0X0D); write_data(h, 0X26); write_data(h, 0X31); write_data(h, 0X43); write_data(h, 0X47); write_data(h, 0X38); write_data(h, 0X14); write_data(h, 0X14); write_data(h, 0X2C); write_data(h, 0X32); write_reg(h, 0x21); // Dispaly Inversion On write_reg(h, 0x29); // Display On write_reg(h,MEMORY_WRITE); // Memory Write } static void st7789_reset(lcd_handle_t *h) { gpio_set(RST_PIN, 0); /* LCD Hardware Reset */ delay_ms(100); gpio_set(RST_PIN, 1); delay_ms(120); /* Delay 120ms */ write_reg(h,0x11); /* Sleep out */ delay_ms(120); /* Delay 120ms */ } static void set_color(lcd_handle_t *h, uint16_t color) { int i,cnt=h->buflen/2; for(i=0; ibuf[i] = color; } } static void st7789_fill(lcd_handle_t *h, uint16_t color) { int i; int height=h->height/DIV_NUM; set_color(h, color); for(i=0; iwidth, height, h->buf, h->buflen); } } #define SPI_BUS "spi2" #define SPI_DEV_NAME "spi2.0" int st7789_init(lcd_handle_t *h) { int r; struct rt_spi_configuration sc; gpio_init(BK_PIN, GPIO_OUT, 0); gpio_init(DC_PIN, GPIO_OUT, 0); gpio_init(RST_PIN, GPIO_OUT, 0); r = rt_hw_spi_device_attach(SPI_BUS, SPI_DEV_NAME, CS_PIN); if(r!=RT_EOK) { return -1; } h->dev = (struct rt_spi_device*)rt_device_find(SPI_DEV_NAME); if(h->dev==NULL) { return -1; } sc.data_width = 8; sc.max_hz = 5 * 1000 * 1000; sc.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB; r = rt_spi_configure(h->dev, &sc); h->buflen = (h->width*h->height*2)/DIV_NUM; h->buf = (uint16_t*)malloc(h->buflen); if (!h->buf) { LOGE("malloc buffer falied\n"); return -1; } st7789_reset(h); st7789_reg_init(h); gpio_set(BK_PIN, 1); st7789_fill(h, COLOR_GREEN); return 0; } int st7789_deinit(lcd_handle_t *h) { gpio_deinit(BK_PIN); gpio_deinit(DC_PIN); gpio_deinit(RST_PIN); free(h->buf); return 0; }