mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
feat(lcd): support rgb lcd driver for esp32p4
This commit is contained in:
@@ -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));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user