feat(lcd): support rgb lcd driver for esp32p4

This commit is contained in:
morris
2024-10-22 17:18:05 +08:00
parent 5b8db196f8
commit efcb91b47e
25 changed files with 683 additions and 394 deletions
@@ -1,23 +1,29 @@
menu "Example Configuration"
config EXAMPLE_DOUBLE_FB
bool "Use double Frame Buffer"
default "n"
choice EXAMPLE_LCD_BUFFER_MODE
prompt "RGB LCD Buffer Mode"
default EXAMPLE_USE_SINGLE_FB
help
Enable this option, driver will allocate two frame buffers.
Select the LCD buffer mode.
config EXAMPLE_USE_BOUNCE_BUFFER
depends on !EXAMPLE_DOUBLE_FB
bool "Use bounce buffer"
help
Enable bounce buffer mode can achieve higher PCLK frequency at the cost of higher CPU consumption.
config EXAMPLE_USE_SINGLE_FB
bool "Use single frame buffer"
help
Allocate one frame buffer in the driver.
Allocate one draw buffer in LVGL.
config EXAMPLE_AVOID_TEAR_EFFECT_WITH_SEM
depends on !EXAMPLE_DOUBLE_FB
bool "Avoid tearing effect"
default "y"
help
Enable this option, the example will use a pair of semaphores to avoid the tearing effect.
Note, if the Double Frame Buffer is used, then we can also avoid the tearing effect without the lock.
config EXAMPLE_USE_DOUBLE_FB
bool "Use double frame buffer"
help
Allocate two frame buffers in the driver.
The frame buffers also work as ping-pong draw buffers in LVGL.
config EXAMPLE_USE_BOUNCE_BUFFER
bool "Use bounce buffer"
help
Allocate one frame buffer in the driver.
Allocate two bounce buffers in the driver.
Allocate one draw buffer in LVGL.
endchoice
choice EXAMPLE_LCD_DATA_LINES
prompt "RGB LCD Data Lines"
@@ -27,11 +33,15 @@ menu "Example Configuration"
config EXAMPLE_LCD_DATA_LINES_16
bool "16 data lines"
config EXAMPLE_LCD_DATA_LINES_24
bool "24 data lines"
endchoice
config EXAMPLE_LCD_DATA_LINES
int
default 16 if EXAMPLE_LCD_DATA_LINES_16
default 24 if EXAMPLE_LCD_DATA_LINES_24
menu "GPIO assignment"
config EXAMPLE_LCD_VSYNC_GPIO
@@ -114,5 +124,45 @@ menu "Example Configuration"
int "DATA15 GPIO"
help
GPIO pin number for data bus[15].
config EXAMPLE_LCD_DATA16_GPIO
int "DATA16 GPIO"
depends on EXAMPLE_LCD_DATA_LINES > 16
help
GPIO pin number for data bus[16].
config EXAMPLE_LCD_DATA17_GPIO
int "DATA17 GPIO"
depends on EXAMPLE_LCD_DATA_LINES > 16
help
GPIO pin number for data bus[17].
config EXAMPLE_LCD_DATA18_GPIO
int "DATA18 GPIO"
depends on EXAMPLE_LCD_DATA_LINES > 16
help
GPIO pin number for data bus[18].
config EXAMPLE_LCD_DATA19_GPIO
int "DATA19 GPIO"
depends on EXAMPLE_LCD_DATA_LINES > 16
help
GPIO pin number for data bus[19].
config EXAMPLE_LCD_DATA20_GPIO
int "DATA20 GPIO"
depends on EXAMPLE_LCD_DATA_LINES > 16
help
GPIO pin number for data bus[20].
config EXAMPLE_LCD_DATA21_GPIO
int "DATA21 GPIO"
depends on EXAMPLE_LCD_DATA_LINES > 16
help
GPIO pin number for data bus[21].
config EXAMPLE_LCD_DATA22_GPIO
int "DATA22 GPIO"
depends on EXAMPLE_LCD_DATA_LINES > 16
help
GPIO pin number for data bus[22].
config EXAMPLE_LCD_DATA23_GPIO
int "DATA23 GPIO"
depends on EXAMPLE_LCD_DATA_LINES > 16
help
GPIO pin number for data bus[23].
endmenu
endmenu
@@ -10,7 +10,6 @@
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_timer.h"
#include "esp_lcd_panel_ops.h"
#include "esp_lcd_panel_rgb.h"
@@ -61,17 +60,31 @@ static const char *TAG = "example";
#define EXAMPLE_PIN_NUM_DATA13 CONFIG_EXAMPLE_LCD_DATA13_GPIO
#define EXAMPLE_PIN_NUM_DATA14 CONFIG_EXAMPLE_LCD_DATA14_GPIO
#define EXAMPLE_PIN_NUM_DATA15 CONFIG_EXAMPLE_LCD_DATA15_GPIO
#if CONFIG_EXAMPLE_LCD_DATA_LINES > 16
#define EXAMPLE_PIN_NUM_DATA16 CONFIG_EXAMPLE_LCD_DATA16_GPIO
#define EXAMPLE_PIN_NUM_DATA17 CONFIG_EXAMPLE_LCD_DATA17_GPIO
#define EXAMPLE_PIN_NUM_DATA18 CONFIG_EXAMPLE_LCD_DATA18_GPIO
#define EXAMPLE_PIN_NUM_DATA19 CONFIG_EXAMPLE_LCD_DATA19_GPIO
#define EXAMPLE_PIN_NUM_DATA20 CONFIG_EXAMPLE_LCD_DATA20_GPIO
#define EXAMPLE_PIN_NUM_DATA21 CONFIG_EXAMPLE_LCD_DATA21_GPIO
#define EXAMPLE_PIN_NUM_DATA22 CONFIG_EXAMPLE_LCD_DATA22_GPIO
#define EXAMPLE_PIN_NUM_DATA23 CONFIG_EXAMPLE_LCD_DATA23_GPIO
#endif
#if CONFIG_EXAMPLE_DOUBLE_FB
#if CONFIG_EXAMPLE_USE_DOUBLE_FB
#define EXAMPLE_LCD_NUM_FB 2
#else
#define EXAMPLE_LCD_NUM_FB 1
#endif // CONFIG_EXAMPLE_DOUBLE_FB
#endif // CONFIG_EXAMPLE_USE_DOUBLE_FB
#if CONFIG_EXAMPLE_LCD_DATA_LINES_16
#define EXAMPLE_DATA_BUS_WIDTH 16
#define EXAMPLE_PIXEL_SIZE 2
#define EXAMPLE_LV_COLOR_FORMAT LV_COLOR_FORMAT_RGB565
#elif CONFIG_EXAMPLE_LCD_DATA_LINES_24
#define EXAMPLE_DATA_BUS_WIDTH 24
#define EXAMPLE_PIXEL_SIZE 3
#define EXAMPLE_LV_COLOR_FORMAT LV_COLOR_FORMAT_RGB888
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -86,23 +99,13 @@ 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;
// we use two semaphores to sync the VSYNC event and the LVGL task, to avoid potential tearing effect
#if CONFIG_EXAMPLE_AVOID_TEAR_EFFECT_WITH_SEM
SemaphoreHandle_t sem_vsync_end;
SemaphoreHandle_t sem_gui_ready;
#endif
extern void example_lvgl_demo_ui(lv_display_t *disp);
static bool example_on_vsync_event(esp_lcd_panel_handle_t panel, const esp_lcd_rgb_panel_event_data_t *event_data, void *user_data)
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)
{
BaseType_t high_task_awoken = pdFALSE;
#if CONFIG_EXAMPLE_AVOID_TEAR_EFFECT_WITH_SEM
if (xSemaphoreTakeFromISR(sem_gui_ready, &high_task_awoken) == pdTRUE) {
xSemaphoreGiveFromISR(sem_vsync_end, &high_task_awoken);
}
#endif
return high_task_awoken == pdTRUE;
lv_display_t *disp = (lv_display_t *)user_ctx;
lv_display_flush_ready(disp);
return false;
}
static void example_lvgl_flush_cb(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map)
@@ -112,13 +115,8 @@ 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_AVOID_TEAR_EFFECT_WITH_SEM
xSemaphoreGive(sem_gui_ready);
xSemaphoreTake(sem_vsync_end, portMAX_DELAY);
#endif
// pass the draw buffer to the driver
esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, px_map);
lv_display_flush_ready(disp);
}
static void example_increase_lvgl_tick(void *arg)
@@ -165,14 +163,6 @@ static void example_bsp_set_lcd_backlight(uint32_t level)
void app_main(void)
{
#if CONFIG_EXAMPLE_AVOID_TEAR_EFFECT_WITH_SEM
ESP_LOGI(TAG, "Create semaphores");
sem_vsync_end = xSemaphoreCreateBinary();
assert(sem_vsync_end);
sem_gui_ready = xSemaphoreCreateBinary();
assert(sem_gui_ready);
#endif
ESP_LOGI(TAG, "Turn off LCD backlight");
example_bsp_init_lcd_backlight();
example_bsp_set_lcd_backlight(EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL);
@@ -209,6 +199,16 @@ void app_main(void)
EXAMPLE_PIN_NUM_DATA13,
EXAMPLE_PIN_NUM_DATA14,
EXAMPLE_PIN_NUM_DATA15,
#if CONFIG_EXAMPLE_LCD_DATA_LINES > 16
EXAMPLE_PIN_NUM_DATA16,
EXAMPLE_PIN_NUM_DATA17,
EXAMPLE_PIN_NUM_DATA18,
EXAMPLE_PIN_NUM_DATA19,
EXAMPLE_PIN_NUM_DATA20,
EXAMPLE_PIN_NUM_DATA21,
EXAMPLE_PIN_NUM_DATA22,
EXAMPLE_PIN_NUM_DATA23
#endif
},
.timings = {
.pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ,
@@ -246,7 +246,7 @@ void app_main(void)
// create draw buffers
void *buf1 = NULL;
void *buf2 = NULL;
#if CONFIG_EXAMPLE_DOUBLE_FB
#if CONFIG_EXAMPLE_USE_DOUBLE_FB
ESP_LOGI(TAG, "Use frame buffers as LVGL draw buffers");
ESP_ERROR_CHECK(esp_lcd_rgb_panel_get_frame_buffer(panel_handle, 2, &buf1, &buf2));
// set LVGL draw buffers and direct mode
@@ -259,14 +259,14 @@ void app_main(void)
assert(buf1);
// set LVGL draw buffers and partial mode
lv_display_set_buffers(display, buf1, buf2, draw_buffer_sz, LV_DISPLAY_RENDER_MODE_PARTIAL);
#endif // CONFIG_EXAMPLE_DOUBLE_FB
#endif // CONFIG_EXAMPLE_USE_DOUBLE_FB
// 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);
ESP_LOGI(TAG, "Register event callbacks");
esp_lcd_rgb_panel_event_callbacks_t cbs = {
.on_vsync = example_on_vsync_event,
.on_color_trans_done = example_notify_lvgl_flush_ready,
};
ESP_ERROR_CHECK(esp_lcd_rgb_panel_register_event_callbacks(panel_handle, &cbs, display));