Skip to content

Commit

Permalink
feat(LVGL port): Allow to select color format with LVGL9
Browse files Browse the repository at this point in the history
  • Loading branch information
espzav committed May 9, 2024
1 parent 9a5482c commit 87a2a0d
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 17 deletions.
1 change: 1 addition & 0 deletions components/esp_lvgl_port/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Added unit test
- Allow to sleep main LVGL task
- Wake LVGL task from touch and display, when set big maximum sleep
- Allow to select display color mode (only with LVGL9)

### Fixes
- Apply display rotation from configuration
Expand Down
4 changes: 3 additions & 1 deletion components/esp_lvgl_port/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ Add an LCD screen to the LVGL. It can be called multiple times for adding multip
.vres = DISP_HEIGHT,
.monochrome = false,
.mipi_dsi = false,
/* Rotation values must be same as used in esp_lcd for initial settings of the screen */
.color_format = LV_COLOR_FORMAT_RGB565,
.rotation = {
.swap_xy = false,
.mirror_x = false,
Expand All @@ -84,6 +84,8 @@ Add an LCD screen to the LVGL. It can be called multiple times for adding multip
lvgl_port_remove_disp(disp_handle);
```
**Note:** DMA buffer can be used only When you use color format LV_COLOR_FORMAT_RGB565.
### Add touch input
Add touch input to the LVGL. It can be called more times for adding more touch inputs.
Expand Down
2 changes: 1 addition & 1 deletion components/esp_lvgl_port/examples/touchscreen/main/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ static esp_err_t app_lvgl_init(void)
.hres = EXAMPLE_LCD_H_RES,
.vres = EXAMPLE_LCD_V_RES,
.monochrome = false,
/* Rotation values must be same as used in esp_lcd for initial settings of the screen */
.color_format = LV_COLOR_FORMAT_RGB565,
.rotation = {
.swap_xy = false,
.mirror_x = true,
Expand Down
10 changes: 7 additions & 3 deletions components/esp_lvgl_port/include/esp_lvgl_port_disp.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,17 @@ typedef struct {
bool monochrome; /*!< True, if display is monochrome and using 1bit for 1px */
bool mipi_dsi; /*!< True, if display is MIPI-DSI */

lvgl_port_rotation_cfg_t rotation; /*!< Default values of the screen rotation */

lvgl_port_rotation_cfg_t rotation; /*!< Default values of the screen rotation */
#if LVGL_VERSION_MAJOR >= 9
lv_color_format_t color_format; /*!< The color format of the display */
#endif
struct {
unsigned int buff_dma: 1; /*!< Allocated LVGL buffer will be DMA capable */
unsigned int buff_spiram: 1; /*!< Allocated LVGL buffer will be in PSRAM */
unsigned int sw_rotate: 1; /*!< Use software rotation (slower) */
unsigned int swap_bytes: 1; /*!< Swap bytes in RGB656 (16-bit) before send to LCD driver */
#if LVGL_VERSION_MAJOR >= 9
unsigned int swap_bytes: 1; /*!< Swap bytes in RGB656 (16-bit) color format before send to LCD driver */
#endif
} flags;
} lvgl_port_display_cfg_t;

Expand Down
38 changes: 26 additions & 12 deletions components/esp_lvgl_port/src/lvgl9/esp_lvgl_port_disp.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ typedef struct {
esp_lcd_panel_handle_t panel_handle; /* LCD panel handle */
esp_lcd_panel_handle_t control_handle; /* LCD panel control handle */
lvgl_port_rotation_cfg_t rotation; /* Default values of the screen rotation */
lv_color16_t *draw_buffs[2]; /* Display draw buffers */
lv_color_t *draw_buffs[2]; /* Display draw buffers */
lv_display_t *disp_drv; /* LVGL display driver */
struct {
unsigned int monochrome: 1; /* True, if display is monochrome and using 1bit for 1px */
Expand Down Expand Up @@ -65,15 +65,29 @@ lv_display_t *lvgl_port_add_disp(const lvgl_port_display_cfg_t *disp_cfg)
{
esp_err_t ret = ESP_OK;
lv_display_t *disp = NULL;
lv_color16_t *buf1 = NULL;
lv_color16_t *buf2 = NULL;
lv_color_t *buf1 = NULL;
lv_color_t *buf2 = NULL;
assert(disp_cfg != NULL);
assert(disp_cfg->io_handle != NULL);
assert(disp_cfg->panel_handle != NULL);
assert(disp_cfg->buffer_size > 0);
assert(disp_cfg->hres > 0);
assert(disp_cfg->vres > 0);

/* Check supported display color formats */
ESP_RETURN_ON_FALSE(disp_cfg->color_format == 0 || disp_cfg->color_format == LV_COLOR_FORMAT_RGB565 || disp_cfg->color_format == LV_COLOR_FORMAT_RGB888 || disp_cfg->color_format == LV_COLOR_FORMAT_XRGB8888 || disp_cfg->color_format == LV_COLOR_FORMAT_ARGB8888, NULL, TAG, "Not supported display color format!");

lv_color_format_t display_color_format = (disp_cfg->color_format != 0 ? disp_cfg->color_format : LV_COLOR_FORMAT_RGB565);
if (disp_cfg->flags.swap_bytes) {
/* Swap bytes can be used only in RGB656 color format */
ESP_RETURN_ON_FALSE(display_color_format == LV_COLOR_FORMAT_RGB565, NULL, TAG, "Swap bytes can be used only in display color format RGB565!");
}

if (disp_cfg->flags.buff_dma) {
/* DMA buffer can be used only in RGB656 color format */
ESP_RETURN_ON_FALSE(display_color_format == LV_COLOR_FORMAT_RGB565, NULL, TAG, "DMA buffer can be used only in display color format RGB565 (not alligned copy)!");
}

/* Display context */
lvgl_port_display_ctx_t *disp_ctx = malloc(sizeof(lvgl_port_display_ctx_t));
ESP_GOTO_ON_FALSE(disp_ctx, ESP_ERR_NO_MEM, err, TAG, "Not enough memory for display context allocation!");
Expand All @@ -96,10 +110,10 @@ lv_display_t *lvgl_port_add_disp(const lvgl_port_display_cfg_t *disp_cfg)

/* alloc draw buffers used by LVGL */
/* it's recommended to choose the size of the draw buffer(s) to be at least 1/10 screen sized */
buf1 = heap_caps_malloc(disp_cfg->buffer_size * sizeof(lv_color16_t), buff_caps);
buf1 = heap_caps_malloc(disp_cfg->buffer_size * sizeof(lv_color_t), buff_caps);
ESP_GOTO_ON_FALSE(buf1, ESP_ERR_NO_MEM, err, TAG, "Not enough memory for LVGL buffer (buf1) allocation!");
if (disp_cfg->double_buffer) {
buf2 = heap_caps_malloc(disp_cfg->buffer_size * sizeof(lv_color16_t), buff_caps);
buf2 = heap_caps_malloc(disp_cfg->buffer_size * sizeof(lv_color_t), buff_caps);
ESP_GOTO_ON_FALSE(buf2, ESP_ERR_NO_MEM, err, TAG, "Not enough memory for LVGL buffer (buf2) allocation!");
}

Expand All @@ -115,14 +129,12 @@ lv_display_t *lvgl_port_add_disp(const lvgl_port_display_cfg_t *disp_cfg)
ESP_GOTO_ON_FALSE((disp_cfg->hres * disp_cfg->vres == disp_cfg->buffer_size), ESP_ERR_INVALID_ARG, err, TAG, "Monochromatic display must using full buffer!");

disp_ctx->flags.monochrome = 1;

//lv_display_set_color_format(disp, LV_COLOR_FORMAT_RGB565);
lv_display_set_buffers(disp, buf1, buf2, disp_cfg->buffer_size * sizeof(lv_color16_t), LV_DISPLAY_RENDER_MODE_FULL);
lv_display_set_buffers(disp, buf1, buf2, disp_cfg->buffer_size * sizeof(lv_color_t), LV_DISPLAY_RENDER_MODE_FULL);
} else {
lv_display_set_buffers(disp, buf1, buf2, disp_cfg->buffer_size * sizeof(lv_color16_t), LV_DISPLAY_RENDER_MODE_PARTIAL);
lv_display_set_buffers(disp, buf1, buf2, disp_cfg->buffer_size * sizeof(lv_color_t), LV_DISPLAY_RENDER_MODE_PARTIAL);
}


lv_display_set_color_format(disp, display_color_format);
lv_display_set_flush_cb(disp, lvgl_port_flush_callback);
lv_display_add_event_cb(disp, lvgl_port_disp_size_update_callback, LV_EVENT_RESOLUTION_CHANGED, disp_ctx);
lv_display_add_event_cb(disp, lvgl_port_display_invalidate_callback, LV_EVENT_INVALIDATE_AREA, disp_ctx);
Expand Down Expand Up @@ -225,7 +237,7 @@ static bool lvgl_port_flush_panel_ready_callback(esp_lcd_panel_handle_t panel_io
static void _lvgl_port_transform_monochrome(lv_display_t *display, const lv_area_t *area, uint8_t *color_map)
{
uint8_t *buf = color_map;
lv_color16_t *color = (lv_color16_t *)color_map;
lv_color_t *color = (lv_color_t *)color_map;
uint16_t hor_res = lv_display_get_physical_horizontal_resolution(display);
uint16_t ver_res = lv_display_get_physical_vertical_resolution(display);
uint16_t res = hor_res;
Expand Down Expand Up @@ -269,7 +281,6 @@ static void lvgl_port_flush_callback(lv_display_t *drv, const lv_area_t *area, u
lvgl_port_display_ctx_t *disp_ctx = (lvgl_port_display_ctx_t *)lv_display_get_user_data(drv);
assert(disp_ctx != NULL);

//TODO: try to use SPI_SWAP_DATA_RX from https://docs.espressif.com/projects/esp-idf/en/v5.1/esp32s3/api-reference/peripherals/spi_master.html#c.SPI_SWAP_DATA_TX
if (disp_ctx->flags.swap_bytes) {
size_t len = lv_area_get_size(area);
lv_draw_sw_rgb565_swap(color_map, len);
Expand Down Expand Up @@ -324,6 +335,9 @@ static void lvgl_port_disp_rotation_update(lvgl_port_display_ctx_t *disp_ctx)
}
break;
}

/* Wake LVGL task, if needed */
lvgl_port_task_wake(LVGL_PORT_EVENT_DISPLAY, false);
}

static void lvgl_port_disp_size_update_callback(lv_event_t *e)
Expand Down

0 comments on commit 87a2a0d

Please sign in to comment.