mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
feat(lcd): support buffer switch interrupt
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
idf_component_register(SRCS "rgb_lcd_example_main.c" "lvgl_demo_ui.c"
|
||||
PRIV_REQUIRES esp_lcd
|
||||
PRIV_REQUIRES esp_lcd esp_timer
|
||||
INCLUDE_DIRS ".")
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
dependencies:
|
||||
lvgl/lvgl: "9.2.0"
|
||||
lvgl/lvgl: "9.5.0"
|
||||
|
||||
@@ -101,15 +101,43 @@ static const char *TAG = "example";
|
||||
|
||||
// LVGL library is not thread-safe, this example will call LVGL APIs from different tasks, so use a mutex to protect it
|
||||
static _lock_t lvgl_api_lock;
|
||||
static TaskHandle_t lvgl_task_handle;
|
||||
|
||||
extern void example_lvgl_demo_ui(lv_display_t *disp);
|
||||
|
||||
#if CONFIG_EXAMPLE_USE_DOUBLE_FB
|
||||
static bool example_on_frame_buf_complete(esp_lcd_panel_handle_t panel, const esp_lcd_rgb_panel_event_data_t *event_data, void *user_ctx)
|
||||
{
|
||||
(void)panel;
|
||||
(void)event_data;
|
||||
(void)user_ctx;
|
||||
BaseType_t need_yield = pdFALSE;
|
||||
|
||||
if (lvgl_task_handle) {
|
||||
vTaskNotifyGiveFromISR(lvgl_task_handle, &need_yield);
|
||||
}
|
||||
return need_yield == pdTRUE;
|
||||
}
|
||||
|
||||
static void example_lvgl_flush_wait_cb(lv_display_t *disp)
|
||||
{
|
||||
// The flush callback only submits the rendered buffer to the LCD driver.
|
||||
// With direct-mode double buffering, LVGL must wait until the RGB panel has
|
||||
// switched away from the previous frame buffer before rendering into it again.
|
||||
if (lv_display_flush_is_last(disp)) {
|
||||
// Wait until the previous frame buffer is no longer referenced by DMA.
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
}
|
||||
lv_display_flush_ready(disp);
|
||||
}
|
||||
#else
|
||||
static bool example_notify_lvgl_flush_ready(esp_lcd_panel_handle_t panel, const esp_lcd_rgb_panel_event_data_t *event_data, void *user_ctx)
|
||||
{
|
||||
lv_display_t *disp = (lv_display_t *)user_ctx;
|
||||
lv_display_flush_ready(disp);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void example_lvgl_flush_cb(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map)
|
||||
{
|
||||
@@ -118,6 +146,20 @@ static void example_lvgl_flush_cb(lv_display_t *disp, const lv_area_t *area, uin
|
||||
int offsetx2 = area->x2;
|
||||
int offsety1 = area->y1;
|
||||
int offsety2 = area->y2;
|
||||
#if CONFIG_EXAMPLE_USE_DOUBLE_FB
|
||||
if (!lv_display_flush_is_last(disp)) {
|
||||
lv_display_flush_ready(disp);
|
||||
return;
|
||||
}
|
||||
// In direct mode, LVGL may flush multiple dirty areas. Switch the RGB panel to the new
|
||||
// frame buffer only after the last dirty area has been rendered.
|
||||
offsetx1 = 0;
|
||||
offsety1 = 0;
|
||||
offsetx2 = EXAMPLE_LCD_H_RES - 1;
|
||||
offsety2 = EXAMPLE_LCD_V_RES - 1;
|
||||
// Clear any stale completion from the previous frame before waiting for this frame.
|
||||
ulTaskNotifyTake(pdTRUE, 0);
|
||||
#endif
|
||||
// pass the draw buffer to the driver
|
||||
esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, px_map);
|
||||
}
|
||||
@@ -264,10 +306,19 @@ void app_main(void)
|
||||
|
||||
// set the callback which can copy the rendered image to an area of the display
|
||||
lv_display_set_flush_cb(display, example_lvgl_flush_cb);
|
||||
#if CONFIG_EXAMPLE_USE_DOUBLE_FB
|
||||
// The wait callback keeps LVGL from reusing a frame buffer until the panel driver
|
||||
// reports that the buffer has finished refreshing.
|
||||
lv_display_set_flush_wait_cb(display, example_lvgl_flush_wait_cb);
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "Register event callbacks");
|
||||
esp_lcd_rgb_panel_event_callbacks_t cbs = {
|
||||
#if CONFIG_EXAMPLE_USE_DOUBLE_FB
|
||||
.on_frame_buf_complete = example_on_frame_buf_complete,
|
||||
#else
|
||||
.on_color_trans_done = example_notify_lvgl_flush_ready,
|
||||
#endif
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_lcd_rgb_panel_register_event_callbacks(panel_handle, &cbs, display));
|
||||
|
||||
@@ -282,7 +333,7 @@ void app_main(void)
|
||||
ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, EXAMPLE_LVGL_TICK_PERIOD_MS * 1000));
|
||||
|
||||
ESP_LOGI(TAG, "Create LVGL task");
|
||||
xTaskCreate(example_lvgl_port_task, "LVGL", EXAMPLE_LVGL_TASK_STACK_SIZE, NULL, EXAMPLE_LVGL_TASK_PRIORITY, NULL);
|
||||
xTaskCreate(example_lvgl_port_task, "LVGL", EXAMPLE_LVGL_TASK_STACK_SIZE, NULL, EXAMPLE_LVGL_TASK_PRIORITY, &lvgl_task_handle);
|
||||
|
||||
ESP_LOGI(TAG, "Display LVGL UI");
|
||||
// Lock the mutex due to the LVGL APIs are not thread-safe
|
||||
|
||||
Reference in New Issue
Block a user