diff --git a/bsp/esp32_s3_lcd_ev_board/src/esp32_s3_lcd_ev_board.c b/bsp/esp32_s3_lcd_ev_board/src/esp32_s3_lcd_ev_board.c index ee85a31e..06c87f59 100644 --- a/bsp/esp32_s3_lcd_ev_board/src/esp32_s3_lcd_ev_board.c +++ b/bsp/esp32_s3_lcd_ev_board/src/esp32_s3_lcd_ev_board.c @@ -350,7 +350,7 @@ lv_disp_t *bsp_display_start(void) bsp_display_cfg_t cfg = { .lvgl_port_cfg = ESP_LVGL_PORT_INIT_CONFIG() }; - cfg.lvgl_port_cfg.task_stack = 8092; + cfg.lvgl_port_cfg.task_stack = CONFIG_BSP_DISPLAY_LVGL_TASK_STACK_SIZE_KB * 1024; return bsp_display_start_with_config(&cfg); } diff --git a/components/esp_lvgl_port/CMakeLists.txt b/components/esp_lvgl_port/CMakeLists.txt index 9a9edb3f..ab38ef54 100644 --- a/components/esp_lvgl_port/CMakeLists.txt +++ b/components/esp_lvgl_port/CMakeLists.txt @@ -1,6 +1,6 @@ file(GLOB_RECURSE IMAGE_SOURCES images/*.c) -idf_component_register(SRCS "esp_lvgl_port.c" ${IMAGE_SOURCES} INCLUDE_DIRS "include" REQUIRES "esp_lcd" PRIV_REQUIRES "esp_timer") +idf_component_register(SRCS "esp_lvgl_port.c" "esp_lvgl_rgb.c" ${IMAGE_SOURCES} INCLUDE_DIRS "include" "priv_include" REQUIRES "esp_lcd" PRIV_REQUIRES "esp_timer") idf_build_get_property(build_components BUILD_COMPONENTS) if("espressif__button" IN_LIST build_components) diff --git a/components/esp_lvgl_port/esp_lvgl_port.c b/components/esp_lvgl_port/esp_lvgl_port.c index da3ec163..ecf6e470 100644 --- a/components/esp_lvgl_port/esp_lvgl_port.c +++ b/components/esp_lvgl_port/esp_lvgl_port.c @@ -16,6 +16,7 @@ #include "esp_lcd_panel_ops.h" #include "esp_lcd_panel_rgb.h" #include "esp_lvgl_port.h" +#include "esp_lvgl_rgb.h" #include "lvgl.h" @@ -81,11 +82,6 @@ typedef struct lvgl_port_ctx_s { #endif } lvgl_port_ctx_t; -typedef struct { - esp_lcd_panel_handle_t rgb_handle; - uint32_t rgb_ref_period; -} lv_manual_refresh; - #ifdef ESP_LVGL_PORT_TOUCH_COMPONENT typedef struct { esp_lcd_touch_handle_t handle; /* LCD touch IO handle */ @@ -126,7 +122,6 @@ typedef struct { static lvgl_port_ctx_t lvgl_port_ctx; static int lvgl_port_timer_period_ms = 5; static TaskHandle_t lvgl_task_handle = NULL; -static TaskHandle_t lcd_task_handle = NULL; /******************************************************************************* * Function definitions @@ -137,7 +132,6 @@ static void lvgl_port_task_deinit(void); // LVGL callbacks #if LVGL_PORT_HANDLE_FLUSH_READY -static bool lvgl_port_rgb_on_vsync_callback(esp_lcd_panel_handle_t panel, const esp_lcd_rgb_panel_event_data_t *edata, void *user_ctx); static bool lvgl_port_flush_ready_callback(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx); #endif static void lvgl_port_flush_callback(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map); @@ -248,37 +242,6 @@ esp_err_t lvgl_port_deinit(void) return ESP_OK; } -static void lvgl_manual_task(void *arg) -{ - TickType_t tick; - lv_manual_refresh *refresh = (lv_manual_refresh *)arg; - - ESP_LOGI(TAG, "Starting LCD refresh task"); - - for (;;) { - esp_lcd_rgb_panel_refresh(refresh->rgb_handle); - tick = xTaskGetTickCount(); - ulTaskNotifyTake(pdTRUE, portMAX_DELAY); - vTaskDelayUntil(&tick, pdMS_TO_TICKS(refresh->rgb_ref_period)); - } -} - -esp_err_t create_manual_task(const lvgl_port_display_cfg_t *disp_cfg) -{ - static lv_manual_refresh refresh; - - refresh.rgb_handle = disp_cfg->panel_handle; - refresh.rgb_ref_period = disp_cfg->trans_mode.flags.ref_period; - - BaseType_t ret = xTaskCreate(lvgl_manual_task, "LCD", 2048, &refresh, disp_cfg->trans_mode.flags.ref_priority, &lcd_task_handle); - if (ret != pdPASS) { - ESP_LOGE(TAG, "Failed to create LCD task"); - return ESP_FAIL; - } - - return ESP_OK; -} - lv_disp_t *lvgl_port_add_disp(const lvgl_port_display_cfg_t *disp_cfg) { esp_err_t ret = ESP_OK; @@ -348,20 +311,13 @@ lv_disp_t *lvgl_port_add_disp(const lvgl_port_display_cfg_t *disp_cfg) disp_ctx->disp_drv.user_data = disp_ctx; if (disp_cfg->trans_mode.manual_mode) { - create_manual_task(disp_cfg); + lvgl_rgb_create_manual_task(disp_cfg); } #if LVGL_PORT_HANDLE_FLUSH_READY /* Register done callback */ if (disp_cfg->flags.interface_RGB) { - const esp_lcd_rgb_panel_event_callbacks_t cbs = { -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 2) && CONFIG_BSP_LCD_RGB_BOUNCE_BUFFER_MODE - .on_bounce_frame_finish = lvgl_port_rgb_on_vsync_callback, -#else - .on_vsync = lvgl_port_rgb_on_vsync_callback, -#endif - }; - esp_lcd_rgb_panel_register_event_callbacks(disp_ctx->panel_handle, &cbs, &disp_ctx->disp_drv); + lvgl_rgb_register_event_callbacks(disp_ctx, disp_cfg); } else { const esp_lcd_panel_io_callbacks_t cbs = { .on_color_trans_done = lvgl_port_flush_ready_callback, @@ -736,8 +692,6 @@ void lvgl_port_flush_ready(lv_disp_t *disp) lv_disp_flush_ready(disp->driver); } - - /******************************************************************************* * Private functions *******************************************************************************/ @@ -780,25 +734,6 @@ static void lvgl_port_task_deinit(void) } #if LVGL_PORT_HANDLE_FLUSH_READY -IRAM_ATTR static bool lvgl_port_rgb_on_vsync_callback(esp_lcd_panel_handle_t panel_handle, const esp_lcd_rgb_panel_event_data_t *edata, void *user_ctx) -{ - BaseType_t need_yield = pdFALSE; - - lv_disp_drv_t *disp_drv = (lv_disp_drv_t *)user_ctx; - assert(disp_drv != NULL); - lvgl_port_display_ctx_t *disp_ctx = disp_drv->user_data; - - if (disp_ctx->lcd_manual_mode) { - xTaskNotifyFromISR(lcd_task_handle, ULONG_MAX, eNoAction, &need_yield); - } - - if (disp_ctx->lcd_transdone_cb) { - need_yield = disp_ctx->lcd_transdone_cb(panel_handle, user_ctx); - } - - return (need_yield == pdTRUE); -} - static bool lvgl_port_flush_ready_callback(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx) { lv_disp_drv_t *disp_drv = (lv_disp_drv_t *)user_ctx; diff --git a/components/esp_lvgl_port/esp_lvgl_rgb.c b/components/esp_lvgl_port/esp_lvgl_rgb.c new file mode 100644 index 00000000..c6fc22e1 --- /dev/null +++ b/components/esp_lvgl_port/esp_lvgl_rgb.c @@ -0,0 +1,116 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_system.h" +#include "esp_log.h" +#include "esp_err.h" +#include "esp_check.h" +#include "esp_timer.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "esp_lcd_panel_io.h" +#include "esp_lcd_panel_ops.h" +#include "esp_lcd_panel_rgb.h" +#include "esp_lvgl_port.h" + +static const char *TAG = "LV_RGB"; + +#if CONFIG_IDF_TARGET_ESP32S3 + +typedef struct { + esp_lcd_panel_handle_t rgb_handle; + uint32_t rgb_ref_period; +} lv_manual_refresh; + +static TaskHandle_t lcd_task_handle = NULL; + +IRAM_ATTR static bool lvgl_port_rgb_on_vsync_callback(esp_lcd_panel_handle_t panel_handle, const esp_lcd_rgb_panel_event_data_t *edata, void *user_ctx) +{ + BaseType_t need_yield = pdFALSE; + + lv_disp_drv_t *disp_drv = (lv_disp_drv_t *)user_ctx; + assert(disp_drv != NULL); + lvgl_port_display_ctx_t *disp_ctx = disp_drv->user_data; + + if (disp_ctx->lcd_manual_mode) { + xTaskNotifyFromISR(lcd_task_handle, ULONG_MAX, eNoAction, &need_yield); + } + + if (disp_ctx->lcd_transdone_cb) { + need_yield = disp_ctx->lcd_transdone_cb(panel_handle, user_ctx); + } + + return (need_yield == pdTRUE); +} + +esp_err_t lvgl_rgb_register_event_callbacks(lvgl_port_display_ctx_t *disp_ctx, const lvgl_port_display_cfg_t *disp_cfg) +{ + esp_err_t ret; + /* Register done callback */ + const esp_lcd_rgb_panel_event_callbacks_t vsync_cbs = { + .on_vsync = lvgl_port_rgb_on_vsync_callback, + }; + + const esp_lcd_rgb_panel_event_callbacks_t bb_cbs = { +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 2) && CONFIG_BSP_LCD_RGB_BOUNCE_BUFFER_MODE + .on_bounce_frame_finish = lvgl_port_rgb_on_vsync_callback, +#endif + }; + + if (disp_cfg->trans_mode.bb_mode && (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 2))) { + esp_lcd_rgb_panel_register_event_callbacks(disp_ctx->panel_handle, &bb_cbs, &disp_ctx->disp_drv); + } else { + esp_lcd_rgb_panel_register_event_callbacks(disp_ctx->panel_handle, &vsync_cbs, &disp_ctx->disp_drv); + } + + return ESP_OK; +} + +static void lvgl_rgb_manual_task(void *arg) +{ + TickType_t tick; + lv_manual_refresh *refresh = (lv_manual_refresh *)arg; + + ESP_LOGI(TAG, "Starting LCD refresh task"); + + for (;;) { + esp_lcd_rgb_panel_refresh(refresh->rgb_handle); + tick = xTaskGetTickCount(); + ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + vTaskDelayUntil(&tick, pdMS_TO_TICKS(refresh->rgb_ref_period)); + } +} + +esp_err_t lvgl_rgb_create_manual_task(const lvgl_port_display_cfg_t *disp_cfg) +{ + static lv_manual_refresh refresh; + + refresh.rgb_handle = disp_cfg->panel_handle; + refresh.rgb_ref_period = disp_cfg->trans_mode.flags.ref_period; + + BaseType_t ret = xTaskCreate(lvgl_rgb_manual_task, "LCD", 2048, &refresh, disp_cfg->trans_mode.flags.ref_priority, &lcd_task_handle); + if (ret != pdPASS) { + ESP_LOGE(TAG, "Failed to create LCD task"); + return ESP_FAIL; + } + + return ESP_OK; +} + +#else + +esp_err_t lvgl_rgb_register_event_callbacks(lvgl_port_display_ctx_t *disp_ctx, const lvgl_port_display_cfg_t *disp_cfg) +{ + ESP_LOGE(TAG, "RGB mode not supported!"); +} + +esp_err_t lvgl_rgb_create_manual_task(const lvgl_port_display_cfg_t *disp_cfg) +{ + ESP_LOGE(TAG, "RGB mode not supported!"); +} + +#endif diff --git a/components/esp_lvgl_port/priv_include/esp_lvgl_rgb.h b/components/esp_lvgl_port/priv_include/esp_lvgl_rgb.h new file mode 100644 index 00000000..de3cebbe --- /dev/null +++ b/components/esp_lvgl_port/priv_include/esp_lvgl_rgb.h @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief ESP LVGL port + */ + +#pragma once + +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +esp_err_t lvgl_rgb_create_manual_task(const lvgl_port_display_cfg_t *disp_cfg); + +esp_err_t lvgl_rgb_register_event_callbacks(lvgl_port_display_ctx_t *disp_ctx, const lvgl_port_display_cfg_t *disp_cfg); + +#ifdef __cplusplus +} +#endif