diff --git a/CMakeLists.txt b/CMakeLists.txt index bd2b3b5..d6a67f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,13 @@ set(LVGL_INCLUDE_DIRS . lvgl_tft) list(APPEND SOURCES "lvgl_tft/disp_driver.c") list(APPEND SOURCES "lvgl_tft/esp_lcd_backlight.c") +# This are the source files used for mcu abstraction +set(LV_PORT_PATH "lv_port") + +list(APPEND SOURCES "${LV_PORT_PATH}/lv_port_display_espressif.c") + +#@todo add SimleInclude macro here + # Build all display drivers list(APPEND SOURCES "lvgl_tft/ili9341.c") list(APPEND SOURCES "lvgl_tft/ili9481.c") diff --git a/display_config.h b/display_config.h new file mode 100644 index 0000000..37e6387 --- /dev/null +++ b/display_config.h @@ -0,0 +1,29 @@ +#ifndef DISPLAY_CONFIG_H_ +#define DISPLAY_CONFIG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sdkconfig.h" + +/* Configuration options for ST7789 display controllers */ +#if CONFIG_LV_DISP_USE_RST + #if CONFIG_LV_DISP_ST7789_SOFT_RESET + #define ST7789_SOFT_RST + #endif +#else + #define ST7789_SOFT_RST +#endif + +#if defined (CONFIG_LV_INVERT_COLORS) +#define ST7789_INVERT_COLORS 1U +#endif + +#define ST7789_INITIAL_ORIENTATION CONFIG_LV_DISPLAY_ORIENTATION + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* DISPLAY_CONFIG_H_ */ diff --git a/lv_port/lv_port_display_espressif.c b/lv_port/lv_port_display_espressif.c new file mode 100644 index 0000000..9f6f4b1 --- /dev/null +++ b/lv_port/lv_port_display_espressif.c @@ -0,0 +1,41 @@ +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "display_port.h" + +#include "sdkconfig.h" +#include "driver/gpio.h" + +void display_port_delay(lv_disp_drv_t *drv, uint32_t delay_ms) +{ + (void) drv; + + vTaskDelay(pdMS_TO_TICKS(delay_ms)); +} + +void display_port_backlight(lv_disp_drv_t *drv, uint8_t state) +{ + (void) drv; + +#ifdef CONFIG_LV_DISP_PIN_BCKL + gpio_set_level(CONFIG_LV_DISP_PIN_BCKL, state); +#endif +} + +void display_port_gpio_dc(lv_disp_drv_t *drv, uint8_t state) +{ + (void) drv; + +#ifdef CONFIG_LV_DISPLAY_USE_DC + gpio_set_level(CONFIG_LV_DISP_PIN_DC, state); +#endif +} + +void display_port_gpio_rst(lv_disp_drv_t *drv, uint8_t state) +{ + (void) drv; + +#ifdef CONFIG_LV_DISP_USE_RST + gpio_set_level(CONFIG_LV_DISP_PIN_RST, state); +#endif +} diff --git a/lvgl_helpers.c b/lvgl_helpers.c index edc522f..02f4017 100644 --- a/lvgl_helpers.c +++ b/lvgl_helpers.c @@ -69,7 +69,6 @@ void lvgl_driver_init(void) DISP_SPI_IO2, DISP_SPI_IO3); disp_spi_add_device(TFT_SPI_HOST); - disp_driver_init(); #if defined (CONFIG_LV_TOUCH_CONTROLLER_FT81X) touch_driver_init(); @@ -89,7 +88,6 @@ void lvgl_driver_init(void) disp_spi_add_device(TFT_SPI_HOST); tp_spi_add_device(TOUCH_SPI_HOST); - disp_driver_init(); touch_driver_init(); return; @@ -105,10 +103,7 @@ void lvgl_driver_init(void) DISP_SPI_IO2, DISP_SPI_IO3); disp_spi_add_device(TFT_SPI_HOST); - - disp_driver_init(); #elif defined (CONFIG_LV_I2C_DISPLAY) - disp_driver_init(); #else #error "No protocol defined for display controller" #endif diff --git a/lvgl_tft/Kconfig b/lvgl_tft/Kconfig index f42351e..140c173 100644 --- a/lvgl_tft/Kconfig +++ b/lvgl_tft/Kconfig @@ -195,24 +195,24 @@ menu "LVGL TFT Display controller" # Used in display init function to send display orientation commands choice DISPLAY_ORIENTATION prompt "Display orientation" - default DISPLAY_ORIENTATION_PORTRAIT if !LV_TFT_DISPLAY_CONTROLLER_SSD1306 - default DISPLAY_ORIENTATION_LANDSCAPE if LV_TFT_DISPLAY_CONTROLLER_SSD1306 - config DISPLAY_ORIENTATION_PORTRAIT + default LV_DISPLAY_ORIENTATION_PORTRAIT if !LV_TFT_DISPLAY_CONTROLLER_SSD1306 + default LV_DISPLAY_ORIENTATION_LANDSCAPE if LV_TFT_DISPLAY_CONTROLLER_SSD1306 + config LV_DISPLAY_ORIENTATION_PORTRAIT bool "Portrait" if !LV_TFT_DISPLAY_CONTROLLER_SSD1306 - config DISPLAY_ORIENTATION_PORTRAIT_INVERTED + config LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED bool "Portrait inverted" if !LV_TFT_DISPLAY_CONTROLLER_SSD1306 - config DISPLAY_ORIENTATION_LANDSCAPE + config LV_DISPLAY_ORIENTATION_LANDSCAPE bool "Landscape" - config DISPLAY_ORIENTATION_LANDSCAPE_INVERTED + config LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED bool "Landscape inverted" endchoice config LV_DISPLAY_ORIENTATION int - default 0 if DISPLAY_ORIENTATION_PORTRAIT - default 1 if DISPLAY_ORIENTATION_PORTRAIT_INVERTED - default 2 if DISPLAY_ORIENTATION_LANDSCAPE - default 3 if DISPLAY_ORIENTATION_LANDSCAPE_INVERTED + default 0 if LV_DISPLAY_ORIENTATION_PORTRAIT + default 1 if LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED + default 2 if LV_DISPLAY_ORIENTATION_LANDSCAPE + default 3 if LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED config LV_TFT_DISPLAY_OFFSETS bool @@ -222,15 +222,15 @@ menu "LVGL TFT Display controller" config LV_TFT_DISPLAY_X_OFFSET depends on LV_TFT_DISPLAY_OFFSETS int "X offset" - default 40 if LV_PREDEFINED_DISPLAY_TTGO && (DISPLAY_ORIENTATION_LANDSCAPE || DISPLAY_ORIENTATION_LANDSCAPE_INVERTED) - default 53 if LV_PREDEFINED_DISPLAY_TTGO && (DISPLAY_ORIENTATION_PORTRAIT || DISPLAY_ORIENTATION_PORTRAIT_INVERTED) + default 40 if LV_PREDEFINED_DISPLAY_TTGO && (LV_DISPLAY_ORIENTATION_LANDSCAPE || LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED) + default 53 if LV_PREDEFINED_DISPLAY_TTGO && (LV_DISPLAY_ORIENTATION_PORTRAIT || LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED) default 0 config LV_TFT_DISPLAY_Y_OFFSET depends on LV_TFT_DISPLAY_OFFSETS int "Y offset" - default 53 if LV_PREDEFINED_DISPLAY_TTGO && (DISPLAY_ORIENTATION_LANDSCAPE || DISPLAY_ORIENTATION_LANDSCAPE_INVERTED) - default 40 if LV_PREDEFINED_DISPLAY_TTGO && (DISPLAY_ORIENTATION_PORTRAIT || DISPLAY_ORIENTATION_PORTRAIT_INVERTED) + default 53 if LV_PREDEFINED_DISPLAY_TTGO && (LV_DISPLAY_ORIENTATION_LANDSCAPE || LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED) + default 40 if LV_PREDEFINED_DISPLAY_TTGO && (LV_DISPLAY_ORIENTATION_PORTRAIT || LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED) default 0 diff --git a/lvgl_tft/disp_driver.c b/lvgl_tft/disp_driver.c index f62a947..95569a8 100644 --- a/lvgl_tft/disp_driver.c +++ b/lvgl_tft/disp_driver.c @@ -7,7 +7,7 @@ #include "esp_lcd_backlight.h" #include "sdkconfig.h" -void *disp_driver_init(void) +void *disp_driver_init(lv_disp_drv_t *drv) { #if defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9341 ili9341_init(); @@ -16,7 +16,7 @@ void *disp_driver_init(void) #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488 ili9488_init(); #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7789 - st7789_init(); + st7789_init(drv); #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7796S st7796s_init(); #elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ST7735S @@ -45,6 +45,11 @@ void *disp_driver_init(void) ili9163c_init(); #endif + return disp_backlight_init(); +} + +void *disp_backlight_init(void) +{ // We still use menuconfig for these settings // It will be set up during runtime in the future #if (defined(CONFIG_LV_DISP_BACKLIGHT_SWITCH) || defined(CONFIG_LV_DISP_BACKLIGHT_PWM)) diff --git a/lvgl_tft/disp_driver.h b/lvgl_tft/disp_driver.h index 8c70fda..a4a282b 100644 --- a/lvgl_tft/disp_driver.h +++ b/lvgl_tft/disp_driver.h @@ -67,7 +67,7 @@ extern "C" { **********************/ /* Initialize display */ -void *disp_driver_init(void); +void *disp_driver_init(lv_disp_drv_t *drv); /* Display flush callback */ void disp_driver_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map); @@ -79,6 +79,8 @@ void disp_driver_rounder(lv_disp_drv_t * disp_drv, lv_area_t * area); void disp_driver_set_px(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa); +/* Display backlight configuration */ +void *disp_backlight_init(void); /********************** * MACROS **********************/ diff --git a/lvgl_tft/display_port.h b/lvgl_tft/display_port.h new file mode 100644 index 0000000..2136ec6 --- /dev/null +++ b/lvgl_tft/display_port.h @@ -0,0 +1,51 @@ +#ifndef DISPLAY_PORT_H_ +#define DISPLAY_PORT_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifdef LV_LVGL_H_INCLUDE_SIMPLE +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + +/** + * Busy wait delay port + * + * @param drv Pointer to driver See @ref lv_disp_drv_t + * @param delay_ms Delay duration in milliseconds + */ +void display_port_delay(lv_disp_drv_t *drv, uint32_t delay_ms); + +/** + * Backlight control port + * + * @param drv Pointer to driver See @ref lv_disp_drv_t + * @param state State of the backlight signal + */ +void display_port_backlight(lv_disp_drv_t *drv, uint8_t state); + +/** + * DC signal control port + * + * @param drv Pointer to driver See @ref lv_disp_drv_t + * @param state State of the DC signal, 1 for logic high, 0 for logic low + */ +void display_port_gpio_dc(lv_disp_drv_t *drv, uint8_t state); + +/** + * Hardware reset control port + * + * @param drv Pointer to driver See @ref lv_disp_drv_t + * @param state State of the reset signal, 1 for logic high, 0 for logic low + */ +void display_port_gpio_rst(lv_disp_drv_t *drv, uint8_t state); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/lvgl_tft/ssd1306.c b/lvgl_tft/ssd1306.c index d282a7f..1700d02 100644 --- a/lvgl_tft/ssd1306.c +++ b/lvgl_tft/ssd1306.c @@ -99,10 +99,10 @@ void ssd1306_init(void) uint8_t orientation_1 = 0; uint8_t orientation_2 = 0; -#if defined (CONFIG_DISPLAY_ORIENTATION_LANDSCAPE) +#if defined (CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE) orientation_1 = OLED_CMD_SET_SEGMENT_REMAP; orientation_2 = OLED_CMD_SET_COM_SCAN_MODE_REMAP; -#elif defined (CONFIG_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED) +#elif defined (CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED) orientation_1 = 0xA0; orientation_2 = OLED_CMD_SET_COM_SCAN_MODE_NORMAL; #else diff --git a/lvgl_tft/st7789.c b/lvgl_tft/st7789.c index 962eb44..1aa1b75 100644 --- a/lvgl_tft/st7789.c +++ b/lvgl_tft/st7789.c @@ -4,21 +4,16 @@ * Mostly taken from lbthomsen/esp-idf-littlevgl github. */ -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "sdkconfig.h" - -#include "esp_log.h" - #include "st7789.h" #include "disp_spi.h" -#include "driver/gpio.h" +#include "display_port.h" /********************* * DEFINES *********************/ -#define TAG "st7789" +#define TAG "ST7789" + /********************** * TYPEDEFS **********************/ @@ -33,10 +28,13 @@ typedef struct { /********************** * STATIC PROTOTYPES **********************/ -static void st7789_set_orientation(uint8_t orientation); +static void st7789_set_orientation(lv_disp_drv_t *drv, uint8_t orientation); -static void st7789_send_color(void *data, uint16_t length); +static void st7789_send_cmd(lv_disp_drv_t * drv, uint8_t cmd); +static void st7789_send_data(lv_disp_drv_t * drv, void *data, uint16_t length); +static void st7789_send_color(lv_disp_drv_t * drv, void *data, uint16_t length); +static void st7789_reset(lv_disp_drv_t * drv); /********************** * STATIC VARIABLES **********************/ @@ -48,7 +46,7 @@ static void st7789_send_color(void *data, uint16_t length); /********************** * GLOBAL FUNCTIONS **********************/ -void st7789_init(void) +void st7789_init(lv_disp_drv_t *drv) { lcd_init_cmd_t st7789_init_cmds[] = { {0xCF, {0x00, 0x83, 0X30}, 3}, @@ -85,39 +83,21 @@ void st7789_init(void) {0, {0}, 0xff}, }; - //Initialize non-SPI GPIOs - gpio_pad_select_gpio(ST7789_DC); - gpio_set_direction(ST7789_DC, GPIO_MODE_OUTPUT); - -#if !defined(ST7789_SOFT_RST) - gpio_pad_select_gpio(ST7789_RST); - gpio_set_direction(ST7789_RST, GPIO_MODE_OUTPUT); -#endif - - //Reset the display -#if !defined(ST7789_SOFT_RST) - gpio_set_level(ST7789_RST, 0); - vTaskDelay(100 / portTICK_RATE_MS); - gpio_set_level(ST7789_RST, 1); - vTaskDelay(100 / portTICK_RATE_MS); -#else - st7789_send_cmd(ST7789_SWRESET); -#endif - - printf("ST7789 initialization.\n"); + st7789_reset(drv); //Send all the commands uint16_t cmd = 0; while (st7789_init_cmds[cmd].databytes!=0xff) { - st7789_send_cmd(st7789_init_cmds[cmd].cmd); - st7789_send_data(st7789_init_cmds[cmd].data, st7789_init_cmds[cmd].databytes&0x1F); + st7789_send_cmd(drv, st7789_init_cmds[cmd].cmd); + st7789_send_data(drv, st7789_init_cmds[cmd].data, st7789_init_cmds[cmd].databytes&0x1F); if (st7789_init_cmds[cmd].databytes & 0x80) { - vTaskDelay(100 / portTICK_RATE_MS); + display_port_delay(drv, 100); } cmd++; } - st7789_set_orientation(CONFIG_LV_DISPLAY_ORIENTATION); + /* FIXME We're setting up the initial orientation in the cmd array */ + st7789_set_orientation(drv, ST7789_INITIAL_ORIENTATION); } /* The ST7789 display controller can drive 320*240 displays, when using a 240*240 @@ -131,6 +111,7 @@ void st7789_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * colo uint16_t offsetx2 = area->x2; uint16_t offsety1 = area->y1; uint16_t offsety2 = area->y2; + uint32_t size = lv_area_get_width(area) * lv_area_get_height(area); #if (CONFIG_LV_TFT_DISPLAY_OFFSETS) offsetx1 += CONFIG_LV_TFT_DISPLAY_X_OFFSET; @@ -149,64 +130,66 @@ void st7789_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * colo #endif /*Column addresses*/ - st7789_send_cmd(ST7789_CASET); + st7789_send_cmd(drv, ST7789_CASET); data[0] = (offsetx1 >> 8) & 0xFF; data[1] = offsetx1 & 0xFF; data[2] = (offsetx2 >> 8) & 0xFF; data[3] = offsetx2 & 0xFF; - st7789_send_data(data, 4); + st7789_send_data(drv, data, 4); /*Page addresses*/ - st7789_send_cmd(ST7789_RASET); + st7789_send_cmd(drv, ST7789_RASET); data[0] = (offsety1 >> 8) & 0xFF; data[1] = offsety1 & 0xFF; data[2] = (offsety2 >> 8) & 0xFF; data[3] = offsety2 & 0xFF; - st7789_send_data(data, 4); + st7789_send_data(drv, data, 4); /*Memory write*/ - st7789_send_cmd(ST7789_RAMWR); - - uint32_t size = lv_area_get_width(area) * lv_area_get_height(area); - - st7789_send_color((void*)color_map, size * 2); - + st7789_send_cmd(drv, ST7789_RAMWR); + st7789_send_color(drv, (void*) color_map, size * 2); } /********************** * STATIC FUNCTIONS **********************/ -void st7789_send_cmd(uint8_t cmd) +static void st7789_send_cmd(lv_disp_drv_t *drv, uint8_t cmd) { disp_wait_for_pending_transactions(); - gpio_set_level(ST7789_DC, 0); + display_port_gpio_dc(drv, 0); disp_spi_send_data(&cmd, 1); } -void st7789_send_data(void * data, uint16_t length) +static void st7789_send_data(lv_disp_drv_t *drv, void * data, uint16_t length) { disp_wait_for_pending_transactions(); - gpio_set_level(ST7789_DC, 1); + display_port_gpio_dc(drv, 1); disp_spi_send_data(data, length); } -static void st7789_send_color(void * data, uint16_t length) +static void st7789_send_color(lv_disp_drv_t *drv, void * data, uint16_t length) { disp_wait_for_pending_transactions(); - gpio_set_level(ST7789_DC, 1); + display_port_gpio_dc(drv, 1); disp_spi_send_colors(data, length); } -static void st7789_set_orientation(uint8_t orientation) +/* Reset the display, if we don't have a reset pin we use software reset */ +static void st7789_reset(lv_disp_drv_t *drv) { - // ESP_ASSERT(orientation < 4); - - const char *orientation_str[] = { - "PORTRAIT", "PORTRAIT_INVERTED", "LANDSCAPE", "LANDSCAPE_INVERTED" - }; - - ESP_LOGI(TAG, "Display orientation: %s", orientation_str[orientation]); +#if !defined(ST7789_SOFT_RST) + display_port_gpio_rst(drv, 0); + display_port_delay(drv, 100); + display_port_gpio_rst(drv, 1); + display_port_delay(drv, 100); +#else + st7789_send_cmd(drv, ST7789_SWRESET); + display_port_delay(drv, 5); +#endif +} +static void st7789_set_orientation(lv_disp_drv_t *drv, uint8_t orientation) +{ uint8_t data[] = { #if CONFIG_LV_PREDEFINED_DISPLAY_TTGO @@ -216,8 +199,13 @@ static void st7789_set_orientation(uint8_t orientation) #endif }; - ESP_LOGI(TAG, "0x36 command value: 0x%02X", data[orientation]); - - st7789_send_cmd(ST7789_MADCTL); - st7789_send_data((void *) &data[orientation], 1); + st7789_send_cmd(drv, ST7789_MADCTL); + st7789_send_data(drv, (void *) &data[orientation], 1); +} + +/* Display update callback, we could update the orientation in here + * NOTE Available only for LVGL v8 */ +void st7789_update_cb(lv_disp_drv_t *drv) +{ + (void) drv; } diff --git a/lvgl_tft/st7789.h b/lvgl_tft/st7789.h index cacb31b..be86c21 100644 --- a/lvgl_tft/st7789.h +++ b/lvgl_tft/st7789.h @@ -17,22 +17,11 @@ extern "C" #else #include "lvgl/lvgl.h" #endif -#include "../lvgl_helpers.h" -#include "sdkconfig.h" - -#define ST7789_DC CONFIG_LV_DISP_PIN_DC -#define ST7789_RST CONFIG_LV_DISP_PIN_RST - -#if CONFIG_LV_DISP_USE_RST - #if CONFIG_LV_DISP_ST7789_SOFT_RESET - #define ST7789_SOFT_RST - #endif -#else - #define ST7789_SOFT_RST -#endif - -#define ST7789_INVERT_COLORS CONFIG_LV_INVERT_COLORS +/* For SPI transfers */ +#include "lvgl_helpers.h" +/* For ST7789 particular configurations */ +#include "display_config.h" /* ST7789 commands */ #define ST7789_NOP 0x00 @@ -110,11 +99,28 @@ extern "C" #define ST7789_NVMSET 0xFC // NVM setting #define ST7789_PROMACT 0xFE // Program action -void st7789_init(void); +/** + * Initialize the ST7789 display controller with default configuration + * + * @param drv Pointer to lv_disp_drv_t being used + */ +void st7789_init(lv_disp_drv_t *drv); + +/** + * Send buffer content to display + * + * @param drv Pointer to lv_disp_drv_t being used + * @param area Pointer to area to be sent + * @param color_map Pointer to color map + */ void st7789_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map); -void st7789_send_cmd(uint8_t cmd); -void st7789_send_data(void *data, uint16_t length); +/** + * Display updated callback + * + * @param drv Pointer to lv_disp_drv_t being used + */ +void st7789_update_cb(lv_disp_drv_t *drv); #ifdef __cplusplus } /* extern "C" */