feat(lcd): support color conversion for mipi dsi driver

This commit is contained in:
morris 2024-10-30 15:25:16 +08:00
parent 5e056de1e7
commit 0ed4c19c5e
32 changed files with 376 additions and 113 deletions

View File

@ -29,6 +29,7 @@ menu "DW_GDMA Configurations"
config DW_GDMA_CTRL_FUNC_IN_IRAM
bool
default n
select DW_GDMA_OBJ_DRAM_SAFE
help
Place DW_GDMA control functions (e.g. dw_gdma_channel_continue) into IRAM,
so that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.
@ -36,6 +37,7 @@ menu "DW_GDMA Configurations"
config DW_GDMA_SETTER_FUNC_IN_IRAM
bool
default n
select DW_GDMA_OBJ_DRAM_SAFE
help
Place DW_GDMA setter functions (e.g. dw_gdma_channel_set_block_markers) into IRAM,
so that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.
@ -43,6 +45,7 @@ menu "DW_GDMA Configurations"
config DW_GDMA_GETTER_FUNC_IN_IRAM
bool
default n
select DW_GDMA_OBJ_DRAM_SAFE
help
Place DW_GDMA getter functions (e.g. dw_gdma_link_list_get_item) into IRAM,
so that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.
@ -50,11 +53,19 @@ menu "DW_GDMA Configurations"
config DW_GDMA_ISR_IRAM_SAFE
bool
default n
select DW_GDMA_OBJ_DRAM_SAFE
help
This will ensure the DW_GDMA interrupt handler is IRAM-Safe, allow to avoid flash
cache misses, and also be able to run whilst the cache is disabled.
(e.g. SPI Flash write).
config DW_GDMA_OBJ_DRAM_SAFE
bool
default n
help
This will ensure the DW_GDMA object is DRAM-Safe, allow to avoid external memory
cache misses, and also be accessible whilst the cache is disabled.
config DW_GDMA_ENABLE_DEBUG_LOG
bool "Enable debug log"
default n

View File

@ -48,7 +48,7 @@ static const char *TAG = "dw-gdma";
#define DW_GDMA_GET_CACHE_ADDRESS(nc_addr) (nc_addr)
#endif
#if CONFIG_DW_GDMA_ISR_IRAM_SAFE || CONFIG_DW_GDMA_CTRL_FUNC_IN_IRAM || DW_GDMA_SETTER_FUNC_IN_IRAM
#if CONFIG_DW_GDMA_OBJ_DRAM_SAFE
#define DW_GDMA_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
#else
#define DW_GDMA_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT

View File

@ -13,6 +13,7 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "soc/soc_caps.h"
#include "soc/ext_mem_defs.h"
#include "esp_log.h"
#include "esp_check.h"
#include "esp_memory_utils.h"

View File

@ -380,6 +380,7 @@ static bool test_dw_gdma_list_mode_invalid_block_cb(dw_gdma_channel_handle_t cha
udata->count++;
// clear the destination buffer
memset(udata->dst_buffer_addr, 0, udata->dst_buffer_size);
esp_cache_msync(udata->dst_buffer_addr, udata->dst_buffer_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
dw_gdma_block_markers_t markers = {
.is_last = true, // mark the next block as the last one
.is_valid = true, // mark the block as valid so that the DMA can continue the transfer

View File

@ -30,10 +30,7 @@ menu "ESP-Driver:LCD Controller Configurations"
config LCD_DSI_ISR_IRAM_SAFE
bool "DSI LCD ISR IRAM-Safe"
default n
select DW_GDMA_ISR_IRAM_SAFE
select DW_GDMA_CTRL_FUNC_IN_IRAM
select DW_GDMA_SETTER_FUNC_IN_IRAM
select DW_GDMA_GETTER_FUNC_IN_IRAM
select DW_GDMA_ISR_IRAM_SAFE # relies on DW_GDMA Full trans done interrupt
help
Ensure the LCD interrupt is IRAM-Safe by allowing the interrupt handler to be
executable when the cache is disabled (e.g. SPI Flash write).

View File

@ -16,7 +16,7 @@ static const char *TAG = "lcd.dsi.bus";
#define MIPI_DSI_DEFAULT_TIMEOUT_CLOCK_FREQ_MHZ 10
// TxClkEsc frequency must be configured between 2 and 20 MHz
#define MIPI_DSI_DEFAULT_ESCAPE_CLOCK_FREQ_MHZ 10
#define MIPI_DSI_DEFAULT_ESCAPE_CLOCK_FREQ_MHZ 18
esp_err_t esp_lcd_new_dsi_bus(const esp_lcd_dsi_bus_config_t *bus_config, esp_lcd_dsi_bus_handle_t *ret_bus)
{

View File

@ -20,6 +20,7 @@
#include "esp_private/esp_clk_tree_common.h"
#include "hal/cache_hal.h"
#include "hal/cache_ll.h"
#include "hal/color_hal.h"
static const char *TAG = "lcd.dsi.dpi";
@ -40,7 +41,8 @@ struct esp_lcd_dpi_panel_t {
uint32_t v_pixels; // Vertical pixels
size_t fb_size; // Frame buffer size, in bytes
size_t bits_per_pixel; // Bits per pixel
lcd_color_rgb_pixel_format_t pixel_format; // RGB Pixel format
lcd_color_format_t in_color_format; // Input color format
lcd_color_format_t out_color_format; // Output color format
dw_gdma_channel_handle_t dma_chan; // DMA channel
dw_gdma_link_list_handle_t link_lists[DPI_PANEL_MAX_FB_NUM]; // DMA link list
esp_async_fbcpy_handle_t fbcpy_handle; // Use DMA2D to do frame buffer copy
@ -175,6 +177,19 @@ esp_err_t esp_lcd_new_panel_dpi(esp_lcd_dsi_bus_handle_t bus, const esp_lcd_dpi_
bits_per_pixel = 24;
break;
}
lcd_color_format_t in_color_format = COLOR_TYPE_ID(COLOR_SPACE_RGB, panel_config->pixel_format);
// if user sets the in_color_format, it can override the pixel format setting
if (panel_config->in_color_format) {
color_space_pixel_format_t in_color_id = {
.color_type_id = panel_config->in_color_format,
};
bits_per_pixel = color_hal_pixel_format_get_bit_depth(in_color_id);
in_color_format = panel_config->in_color_format;
}
lcd_color_format_t out_color_format = in_color_format;
if (panel_config->out_color_format) {
out_color_format = panel_config->out_color_format;
}
ESP_RETURN_ON_FALSE(panel_config->video_timing.h_size * panel_config->video_timing.v_size * bits_per_pixel % 8 == 0,
ESP_ERR_INVALID_ARG, TAG, "frame buffer size not aligned to byte boundary");
@ -184,7 +199,8 @@ esp_err_t esp_lcd_new_panel_dpi(esp_lcd_dsi_bus_handle_t bus, const esp_lcd_dpi_
dpi_panel = heap_caps_calloc(1, sizeof(esp_lcd_dpi_panel_t), DSI_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(dpi_panel, ESP_ERR_NO_MEM, err, TAG, "no memory for DPI panel");
dpi_panel->virtual_channel = panel_config->virtual_channel;
dpi_panel->pixel_format = panel_config->pixel_format;
dpi_panel->in_color_format = in_color_format;
dpi_panel->out_color_format = out_color_format;
dpi_panel->bus = bus;
dpi_panel->num_fbs = num_fbs;
@ -253,7 +269,7 @@ esp_err_t esp_lcd_new_panel_dpi(esp_lcd_dsi_bus_handle_t bus, const esp_lcd_dpi_
ESP_GOTO_ON_ERROR(dpi_panel_create_dma_link(dpi_panel), err, TAG, "initialize DMA link failed");
mipi_dsi_host_ll_dpi_set_vcid(hal->host, panel_config->virtual_channel);
mipi_dsi_hal_host_dpi_set_color_coding(hal, panel_config->pixel_format, 0);
mipi_dsi_hal_host_dpi_set_color_coding(hal, out_color_format, 0);
// these signals define how the DPI interface interacts with the controller
mipi_dsi_host_ll_dpi_set_timing_polarity(hal->host, false, false, false, false, false);
@ -291,6 +307,8 @@ esp_err_t esp_lcd_new_panel_dpi(esp_lcd_dsi_bus_handle_t bus, const esp_lcd_dpi_
panel_config->video_timing.vsync_front_porch);
mipi_dsi_brg_ll_set_num_pixel_bits(hal->bridge, panel_config->video_timing.h_size * panel_config->video_timing.v_size * bits_per_pixel);
mipi_dsi_brg_ll_set_underrun_discard_count(hal->bridge, panel_config->video_timing.h_size);
// set input color space
mipi_dsi_brg_ll_set_input_color_space(hal->bridge, COLOR_SPACE_TYPE(in_color_format));
// use the DW_GDMA as the flow controller
mipi_dsi_brg_ll_set_flow_controller(hal->bridge, MIPI_DSI_LL_FLOW_CONTROLLER_DMA);
mipi_dsi_brg_ll_set_multi_block_number(hal->bridge, DPI_PANEL_MIN_DMA_NODES_PER_LINK);
@ -343,7 +361,7 @@ static esp_err_t dpi_panel_del(esp_lcd_panel_t *panel)
esp_async_fbcpy_uninstall(dpi_panel->fbcpy_handle);
}
if (dpi_panel->draw_sem) {
vSemaphoreDelete(dpi_panel->draw_sem);
vSemaphoreDeleteWithCaps(dpi_panel->draw_sem);
}
if (dpi_panel->pm_lock) {
esp_pm_lock_release(dpi_panel->pm_lock);
@ -515,9 +533,8 @@ static esp_err_t dpi_panel_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int
.copy_size_x = x_end - x_start,
.copy_size_y = y_end - y_start,
.pixel_format_unique_id = {
.color_space = COLOR_SPACE_RGB,
.pixel_format = dpi_panel->pixel_format,
},
.color_type_id = dpi_panel->in_color_format,
}
};
ESP_RETURN_ON_ERROR(esp_async_fbcpy(dpi_panel->fbcpy_handle, &fbcpy_trans_config, async_fbcpy_done_cb, dpi_panel), TAG, "async memcpy failed");
}
@ -525,6 +542,24 @@ static esp_err_t dpi_panel_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int
return ESP_OK;
}
esp_err_t esp_lcd_dpi_panel_set_color_conversion(esp_lcd_panel_handle_t panel, const esp_lcd_color_conv_config_t *config)
{
ESP_RETURN_ON_FALSE(panel, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
esp_lcd_dpi_panel_t *dpi_panel = __containerof(panel, esp_lcd_dpi_panel_t, base);
esp_lcd_dsi_bus_handle_t bus = dpi_panel->bus;
mipi_dsi_hal_context_t *hal = &bus->hal;
if (dpi_panel->in_color_format == COLOR_TYPE_ID(COLOR_SPACE_YUV, COLOR_PIXEL_YUV422)
&& COLOR_SPACE_TYPE(dpi_panel->out_color_format) == LCD_COLOR_SPACE_RGB) {
// YUV422->RGB
mipi_dsi_brg_ll_set_yuv_convert_std(hal->bridge, config->spec.yuv.conv_std);
mipi_dsi_brg_ll_set_yuv422_pack_order(hal->bridge, config->spec.yuv.yuv422.in_pack_order);
} else {
ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG, "unsupported conversion mode");
}
return ESP_OK;
}
esp_err_t esp_lcd_dpi_panel_set_pattern(esp_lcd_panel_handle_t panel, mipi_dsi_pattern_type_t pattern)
{
ESP_RETURN_ON_FALSE(panel, ESP_ERR_INVALID_ARG, TAG, "invalid argument");

View File

@ -84,6 +84,10 @@ typedef struct {
mipi_dsi_dpi_clock_source_t dpi_clk_src; /*!< MIPI DSI DPI clock source */
uint32_t dpi_clock_freq_mhz; /*!< DPI clock frequency in MHz */
lcd_color_rgb_pixel_format_t pixel_format; /*!< Pixel format that used by the MIPI LCD device */
lcd_color_format_t in_color_format; /*!< Format of the input data (color space and pixel format),
which is the format stored in the frame buffer */
lcd_color_format_t out_color_format; /*!< Format of the output data (color space and pixel format),
which is the format that the panel can accept */
uint8_t num_fbs; /*!< Number of screen-sized frame buffers that allocated by the driver
By default (set to either 0 or 1) only one frame buffer will be created */
esp_lcd_video_timing_t video_timing; /*!< Video timing */
@ -134,6 +138,18 @@ esp_err_t esp_lcd_dpi_panel_get_frame_buffer(esp_lcd_panel_handle_t dpi_panel, u
*/
esp_err_t esp_lcd_dpi_panel_set_pattern(esp_lcd_panel_handle_t dpi_panel, mipi_dsi_pattern_type_t pattern);
/**
* @brief Set color conversion configuration for DPI panel
*
* @param[in] dpi_panel MIPI DPI panel handle, returned from esp_lcd_new_panel_dpi()
* @param[in] config Color conversion configuration
* @return
* - ESP_OK: Set color conversion configuration successfully
* - ESP_ERR_INVALID_ARG: Set color conversion configuration failed because of invalid argument
* - ESP_FAIL: Set color conversion configuration failed because of other error
*/
esp_err_t esp_lcd_dpi_panel_set_color_conversion(esp_lcd_panel_handle_t dpi_panel, const esp_lcd_color_conv_config_t *config);
/**
* @brief Type of LCD DPI panel event data
*/

View File

@ -75,6 +75,22 @@ typedef struct {
esp_lcd_panel_io_color_trans_done_cb_t on_color_trans_done; /*!< Callback invoked when color data transfer has finished */
} esp_lcd_panel_io_callbacks_t;
/**
* @brief Configuration of LCD color conversion
*/
typedef struct {
lcd_color_range_t in_color_range; /*!< Color range of the input color */
lcd_color_range_t out_color_range; /*!< Color range of the output color */
union {
struct {
lcd_yuv_conv_std_t conv_std; /*!< YUV conversion standard: BT601, BT709 */
struct {
lcd_yuv422_pack_order_t in_pack_order; /*!< YUV422 packing order of the input color */
} yuv422; /*!< YUV422 specific */
} yuv; /*!< YUV specific */
} spec; /*!< Extra configuration for specific color conversion */
} esp_lcd_color_conv_config_t;
#ifdef __cplusplus
}
#endif

View File

@ -7,7 +7,7 @@
#include <stdbool.h>
#include "esp_err.h"
#include "esp_lcd_panel_io.h"
#include "esp_lcd_types.h"
#ifdef __cplusplus
extern "C" {

View File

@ -5,6 +5,11 @@ entries:
gdma: gdma_reset (noflash)
gdma: gdma_start (noflash)
gdma_link: gdma_link_get_head_addr (noflash)
if LCD_DSI_ISR_IRAM_SAFE = y:
dw_gdma: dw_gdma_link_list_get_item (noflash)
dw_gdma: dw_gdma_lli_set_block_markers (noflash)
dw_gdma: dw_gdma_channel_use_link_list (noflash)
dw_gdma: dw_gdma_channel_enable_ctrl (noflash)
[mapping:esp_lcd_hal]
archive: libhal.a

View File

@ -490,8 +490,7 @@ esp_err_t esp_lcd_rgb_panel_set_yuv_conversion(esp_lcd_panel_handle_t panel, con
if (config->src.color_space == LCD_COLOR_SPACE_YUV && config->dst.color_space == LCD_COLOR_SPACE_RGB) { // YUV->RGB
lcd_ll_set_convert_mode_yuv_to_rgb(hal->dev, config->src.yuv_sample);
// Note, the RGB->YUV conversion only support RGB565
rgb_panel->output_bits_per_pixel = 16;
rgb_panel->output_bits_per_pixel = rgb_panel->fb_bits_per_pixel;
} else if (config->src.color_space == LCD_COLOR_SPACE_RGB && config->dst.color_space == LCD_COLOR_SPACE_YUV) { // RGB->YUV
lcd_ll_set_convert_mode_rgb_to_yuv(hal->dev, config->dst.yuv_sample);
rgb_panel->output_bits_per_pixel = bpp_yuv[config->dst.yuv_sample];

View File

@ -7,6 +7,9 @@ set(COMPONENTS main)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(mipi_dsi_lcd_panel_test)
target_add_binary_data(mipi_dsi_lcd_panel_test.elf "resources/pictures/hello.yuv" BINARY)
target_add_binary_data(mipi_dsi_lcd_panel_test.elf "resources/pictures/world.yuv" BINARY)
if(CONFIG_COMPILER_DUMP_RTL_FILES)
add_custom_target(check_test_app_sections ALL
COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py

View File

@ -1,2 +1,2 @@
dependencies:
esp_lcd_ili9881c: "~0.2.0"
esp_lcd_ek79007: "^1.0.0"

View File

@ -9,16 +9,16 @@
extern "C" {
#endif
// Refresh Rate = 80000000/(40+140+40+800)/(4+16+16+1280) = 60Hz
#define MIPI_DSI_DPI_CLK_MHZ 80
#define MIPI_DSI_LCD_H_RES 800
#define MIPI_DSI_LCD_V_RES 1280
#define MIPI_DSI_LCD_HSYNC 40
#define MIPI_DSI_LCD_HBP 140
#define MIPI_DSI_LCD_HFP 40
#define MIPI_DSI_LCD_VSYNC 4
#define MIPI_DSI_LCD_VBP 16
#define MIPI_DSI_LCD_VFP 16
// Refresh Rate = 48000000/(10+120+120+1024)/(1+20+10+600) = 60Hz
#define MIPI_DSI_DPI_CLK_MHZ 48
#define MIPI_DSI_LCD_H_RES 1024
#define MIPI_DSI_LCD_V_RES 600
#define MIPI_DSI_LCD_HSYNC 10
#define MIPI_DSI_LCD_HBP 120
#define MIPI_DSI_LCD_HFP 120
#define MIPI_DSI_LCD_VSYNC 1
#define MIPI_DSI_LCD_VBP 20
#define MIPI_DSI_LCD_VFP 20
#define TEST_MIPI_DSI_PHY_PWR_LDO_CHAN 3
#define TEST_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV 2500

View File

@ -16,7 +16,7 @@
#include "esp_random.h"
#include "esp_attr.h"
#include "test_mipi_dsi_board.h"
#include "esp_lcd_ili9881c.h"
#include "esp_lcd_ek79007.h"
IRAM_ATTR static bool test_rgb_panel_count_in_callback(esp_lcd_panel_handle_t panel, esp_lcd_dpi_panel_event_data_t *edata, void *user_ctx)
{
@ -32,12 +32,11 @@ static void IRAM_ATTR test_delay_post_cache_disable(void *args)
#define TEST_IMG_SIZE (100 * 100 * sizeof(uint16_t))
TEST_CASE("MIPI DSI draw bitmap (ILI9881C) IRAM Safe", "[mipi_dsi]")
TEST_CASE("MIPI DSI draw bitmap (EK79007) IRAM Safe", "[mipi_dsi]")
{
esp_lcd_dsi_bus_handle_t mipi_dsi_bus;
esp_lcd_panel_io_handle_t mipi_dbi_io;
esp_lcd_panel_handle_t mipi_dpi_panel;
esp_lcd_panel_handle_t ili9881c_ctrl_panel;
test_bsp_enable_dsi_phy_power();
@ -59,22 +58,11 @@ TEST_CASE("MIPI DSI draw bitmap (ILI9881C) IRAM Safe", "[mipi_dsi]")
};
TEST_ESP_OK(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &mipi_dbi_io));
esp_lcd_panel_dev_config_t lcd_dev_config = {
.bits_per_pixel = 16,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.reset_gpio_num = -1,
};
TEST_ESP_OK(esp_lcd_new_panel_ili9881c(mipi_dbi_io, &lcd_dev_config, &ili9881c_ctrl_panel));
TEST_ESP_OK(esp_lcd_panel_reset(ili9881c_ctrl_panel));
TEST_ESP_OK(esp_lcd_panel_init(ili9881c_ctrl_panel));
// turn on display
TEST_ESP_OK(esp_lcd_panel_disp_on_off(ili9881c_ctrl_panel, true));
esp_lcd_dpi_panel_config_t dpi_config = {
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
.dpi_clock_freq_mhz = MIPI_DSI_DPI_CLK_MHZ,
.virtual_channel = 0,
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565,
.in_color_format = LCD_COLOR_FMT_RGB565,
.video_timing = {
.h_size = MIPI_DSI_LCD_H_RES,
.v_size = MIPI_DSI_LCD_V_RES,
@ -86,8 +74,22 @@ TEST_CASE("MIPI DSI draw bitmap (ILI9881C) IRAM Safe", "[mipi_dsi]")
.vsync_front_porch = MIPI_DSI_LCD_VFP,
},
};
TEST_ESP_OK(esp_lcd_new_panel_dpi(mipi_dsi_bus, &dpi_config, &mipi_dpi_panel));
ek79007_vendor_config_t vendor_config = {
.mipi_config = {
.dsi_bus = mipi_dsi_bus,
.dpi_config = &dpi_config,
},
};
esp_lcd_panel_dev_config_t lcd_dev_config = {
.reset_gpio_num = -1,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
.vendor_config = &vendor_config,
};
TEST_ESP_OK(esp_lcd_new_panel_ek79007(mipi_dbi_io, &lcd_dev_config, &mipi_dpi_panel));
TEST_ESP_OK(esp_lcd_panel_reset(mipi_dpi_panel));
TEST_ESP_OK(esp_lcd_panel_init(mipi_dpi_panel));
uint32_t callback_calls = 0;
esp_lcd_dpi_panel_event_callbacks_t cbs = {
.on_refresh_done = test_rgb_panel_count_in_callback,
@ -110,7 +112,6 @@ TEST_CASE("MIPI DSI draw bitmap (ILI9881C) IRAM Safe", "[mipi_dsi]")
TEST_ASSERT(callback_calls > 2);
TEST_ESP_OK(esp_lcd_panel_del(mipi_dpi_panel));
TEST_ESP_OK(esp_lcd_panel_del(ili9881c_ctrl_panel));
TEST_ESP_OK(esp_lcd_panel_io_del(mipi_dbi_io));
TEST_ESP_OK(esp_lcd_del_dsi_bus(mipi_dsi_bus));
free(img);

View File

@ -15,14 +15,13 @@
#include "esp_random.h"
#include "esp_attr.h"
#include "test_mipi_dsi_board.h"
#include "esp_lcd_ili9881c.h"
#include "esp_lcd_ek79007.h"
TEST_CASE("MIPI DSI Pattern Generator (ILI9881C)", "[mipi_dsi]")
TEST_CASE("MIPI DSI Pattern Generator (EK79007)", "[mipi_dsi]")
{
esp_lcd_dsi_bus_handle_t mipi_dsi_bus;
esp_lcd_panel_io_handle_t mipi_dbi_io;
esp_lcd_panel_handle_t mipi_dpi_panel;
esp_lcd_panel_handle_t ili9881c_ctrl_panel;
test_bsp_enable_dsi_phy_power();
@ -41,22 +40,11 @@ TEST_CASE("MIPI DSI Pattern Generator (ILI9881C)", "[mipi_dsi]")
};
TEST_ESP_OK(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &mipi_dbi_io));
esp_lcd_panel_dev_config_t lcd_dev_config = {
.bits_per_pixel = 16,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.reset_gpio_num = -1,
};
TEST_ESP_OK(esp_lcd_new_panel_ili9881c(mipi_dbi_io, &lcd_dev_config, &ili9881c_ctrl_panel));
TEST_ESP_OK(esp_lcd_panel_reset(ili9881c_ctrl_panel));
TEST_ESP_OK(esp_lcd_panel_init(ili9881c_ctrl_panel));
// turn on display
TEST_ESP_OK(esp_lcd_panel_disp_on_off(ili9881c_ctrl_panel, true));
esp_lcd_dpi_panel_config_t dpi_config = {
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
.dpi_clock_freq_mhz = MIPI_DSI_DPI_CLK_MHZ,
.virtual_channel = 0,
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565,
.in_color_format = LCD_COLOR_FMT_RGB888,
.video_timing = {
.h_size = MIPI_DSI_LCD_H_RES,
.v_size = MIPI_DSI_LCD_V_RES,
@ -68,7 +56,20 @@ TEST_CASE("MIPI DSI Pattern Generator (ILI9881C)", "[mipi_dsi]")
.vsync_front_porch = MIPI_DSI_LCD_VFP,
},
};
TEST_ESP_OK(esp_lcd_new_panel_dpi(mipi_dsi_bus, &dpi_config, &mipi_dpi_panel));
ek79007_vendor_config_t vendor_config = {
.mipi_config = {
.dsi_bus = mipi_dsi_bus,
.dpi_config = &dpi_config,
},
};
esp_lcd_panel_dev_config_t lcd_dev_config = {
.reset_gpio_num = -1,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 24,
.vendor_config = &vendor_config,
};
TEST_ESP_OK(esp_lcd_new_panel_ek79007(mipi_dbi_io, &lcd_dev_config, &mipi_dpi_panel));
TEST_ESP_OK(esp_lcd_panel_reset(mipi_dpi_panel));
TEST_ESP_OK(esp_lcd_panel_init(mipi_dpi_panel));
TEST_ESP_OK(esp_lcd_dpi_panel_set_pattern(mipi_dpi_panel, MIPI_DSI_PATTERN_BAR_HORIZONTAL));
@ -80,7 +81,6 @@ TEST_CASE("MIPI DSI Pattern Generator (ILI9881C)", "[mipi_dsi]")
TEST_ESP_OK(esp_lcd_dpi_panel_set_pattern(mipi_dpi_panel, MIPI_DSI_PATTERN_NONE));
TEST_ESP_OK(esp_lcd_panel_del(mipi_dpi_panel));
TEST_ESP_OK(esp_lcd_panel_del(ili9881c_ctrl_panel));
TEST_ESP_OK(esp_lcd_panel_io_del(mipi_dbi_io));
TEST_ESP_OK(esp_lcd_del_dsi_bus(mipi_dsi_bus));
@ -89,12 +89,11 @@ TEST_CASE("MIPI DSI Pattern Generator (ILI9881C)", "[mipi_dsi]")
#define TEST_IMG_SIZE (100 * 100 * sizeof(uint16_t))
TEST_CASE("MIPI DSI draw bitmap (ILI9881C)", "[mipi_dsi]")
TEST_CASE("MIPI DSI draw bitmap (EK79007)", "[mipi_dsi]")
{
esp_lcd_dsi_bus_handle_t mipi_dsi_bus;
esp_lcd_panel_io_handle_t mipi_dbi_io;
esp_lcd_panel_handle_t mipi_dpi_panel;
esp_lcd_panel_handle_t ili9881c_ctrl_panel;
test_bsp_enable_dsi_phy_power();
@ -116,22 +115,11 @@ TEST_CASE("MIPI DSI draw bitmap (ILI9881C)", "[mipi_dsi]")
};
TEST_ESP_OK(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &mipi_dbi_io));
esp_lcd_panel_dev_config_t lcd_dev_config = {
.bits_per_pixel = 16,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.reset_gpio_num = -1,
};
TEST_ESP_OK(esp_lcd_new_panel_ili9881c(mipi_dbi_io, &lcd_dev_config, &ili9881c_ctrl_panel));
TEST_ESP_OK(esp_lcd_panel_reset(ili9881c_ctrl_panel));
TEST_ESP_OK(esp_lcd_panel_init(ili9881c_ctrl_panel));
// turn on display
TEST_ESP_OK(esp_lcd_panel_disp_on_off(ili9881c_ctrl_panel, true));
esp_lcd_dpi_panel_config_t dpi_config = {
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
.dpi_clock_freq_mhz = MIPI_DSI_DPI_CLK_MHZ,
.virtual_channel = 0,
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565,
.in_color_format = LCD_COLOR_FMT_RGB565,
.video_timing = {
.h_size = MIPI_DSI_LCD_H_RES,
.v_size = MIPI_DSI_LCD_V_RES,
@ -143,7 +131,20 @@ TEST_CASE("MIPI DSI draw bitmap (ILI9881C)", "[mipi_dsi]")
.vsync_front_porch = MIPI_DSI_LCD_VFP,
},
};
TEST_ESP_OK(esp_lcd_new_panel_dpi(mipi_dsi_bus, &dpi_config, &mipi_dpi_panel));
ek79007_vendor_config_t vendor_config = {
.mipi_config = {
.dsi_bus = mipi_dsi_bus,
.dpi_config = &dpi_config,
},
};
esp_lcd_panel_dev_config_t lcd_dev_config = {
.reset_gpio_num = -1,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
.vendor_config = &vendor_config,
};
TEST_ESP_OK(esp_lcd_new_panel_ek79007(mipi_dbi_io, &lcd_dev_config, &mipi_dpi_panel));
TEST_ESP_OK(esp_lcd_panel_reset(mipi_dpi_panel));
TEST_ESP_OK(esp_lcd_panel_init(mipi_dpi_panel));
for (int i = 0; i < 100; i++) {
@ -156,7 +157,6 @@ TEST_CASE("MIPI DSI draw bitmap (ILI9881C)", "[mipi_dsi]")
}
TEST_ESP_OK(esp_lcd_panel_del(mipi_dpi_panel));
TEST_ESP_OK(esp_lcd_panel_del(ili9881c_ctrl_panel));
TEST_ESP_OK(esp_lcd_panel_io_del(mipi_dbi_io));
TEST_ESP_OK(esp_lcd_del_dsi_bus(mipi_dsi_bus));
free(img);
@ -164,12 +164,11 @@ TEST_CASE("MIPI DSI draw bitmap (ILI9881C)", "[mipi_dsi]")
test_bsp_disable_dsi_phy_power();
}
TEST_CASE("MIPI DSI with multiple frame buffers (ILI9881C)", "[mipi_dsi]")
TEST_CASE("MIPI DSI with multiple frame buffers (EK79007)", "[mipi_dsi]")
{
esp_lcd_dsi_bus_handle_t mipi_dsi_bus;
esp_lcd_panel_io_handle_t mipi_dbi_io;
esp_lcd_panel_handle_t mipi_dpi_panel;
esp_lcd_panel_handle_t ili9881c_ctrl_panel;
test_bsp_enable_dsi_phy_power();
@ -188,22 +187,11 @@ TEST_CASE("MIPI DSI with multiple frame buffers (ILI9881C)", "[mipi_dsi]")
};
TEST_ESP_OK(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &mipi_dbi_io));
esp_lcd_panel_dev_config_t lcd_dev_config = {
.bits_per_pixel = 16,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.reset_gpio_num = -1,
};
TEST_ESP_OK(esp_lcd_new_panel_ili9881c(mipi_dbi_io, &lcd_dev_config, &ili9881c_ctrl_panel));
TEST_ESP_OK(esp_lcd_panel_reset(ili9881c_ctrl_panel));
TEST_ESP_OK(esp_lcd_panel_init(ili9881c_ctrl_panel));
// turn on display
TEST_ESP_OK(esp_lcd_panel_disp_on_off(ili9881c_ctrl_panel, true));
esp_lcd_dpi_panel_config_t dpi_config = {
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
.dpi_clock_freq_mhz = MIPI_DSI_DPI_CLK_MHZ,
.virtual_channel = 0,
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565,
.in_color_format = LCD_COLOR_FMT_RGB565,
.num_fbs = 3, // the driver will allocate and maintain 3 frame buffers
.video_timing = {
.h_size = MIPI_DSI_LCD_H_RES,
@ -216,7 +204,21 @@ TEST_CASE("MIPI DSI with multiple frame buffers (ILI9881C)", "[mipi_dsi]")
.vsync_front_porch = MIPI_DSI_LCD_VFP,
},
};
TEST_ESP_OK(esp_lcd_new_panel_dpi(mipi_dsi_bus, &dpi_config, &mipi_dpi_panel));
ek79007_vendor_config_t vendor_config = {
.mipi_config = {
.dsi_bus = mipi_dsi_bus,
.dpi_config = &dpi_config,
},
};
esp_lcd_panel_dev_config_t lcd_dev_config = {
.reset_gpio_num = -1,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
.vendor_config = &vendor_config,
};
TEST_ESP_OK(esp_lcd_new_panel_ek79007(mipi_dbi_io, &lcd_dev_config, &mipi_dpi_panel));
TEST_ESP_OK(esp_lcd_panel_reset(mipi_dpi_panel));
TEST_ESP_OK(esp_lcd_panel_init(mipi_dpi_panel));
uint16_t *fbs[3];
@ -236,9 +238,106 @@ TEST_CASE("MIPI DSI with multiple frame buffers (ILI9881C)", "[mipi_dsi]")
}
TEST_ESP_OK(esp_lcd_panel_del(mipi_dpi_panel));
TEST_ESP_OK(esp_lcd_panel_del(ili9881c_ctrl_panel));
TEST_ESP_OK(esp_lcd_panel_io_del(mipi_dbi_io));
TEST_ESP_OK(esp_lcd_del_dsi_bus(mipi_dsi_bus));
test_bsp_disable_dsi_phy_power();
}
TEST_CASE("MIPI DSI draw YUV422 (EK79007)", "[mipi_dsi]")
{
esp_lcd_dsi_bus_handle_t mipi_dsi_bus;
esp_lcd_panel_io_handle_t mipi_dbi_io;
esp_lcd_panel_handle_t mipi_dpi_panel;
test_bsp_enable_dsi_phy_power();
uint8_t *img = malloc(TEST_IMG_SIZE);
TEST_ASSERT_NOT_NULL(img);
esp_lcd_dsi_bus_config_t bus_config = {
.bus_id = 0,
.num_data_lanes = 2,
.phy_clk_src = MIPI_DSI_PHY_CLK_SRC_DEFAULT,
.lane_bit_rate_mbps = 1000, // 1000 Mbps
};
TEST_ESP_OK(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus));
esp_lcd_dbi_io_config_t dbi_config = {
.virtual_channel = 0,
.lcd_cmd_bits = 8,
.lcd_param_bits = 8,
};
TEST_ESP_OK(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &mipi_dbi_io));
esp_lcd_dpi_panel_config_t dpi_config = {
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
.dpi_clock_freq_mhz = MIPI_DSI_DPI_CLK_MHZ,
.virtual_channel = 0,
// YUV422 -> RGB888
.in_color_format = LCD_COLOR_FMT_YUV422,
.out_color_format = LCD_COLOR_FMT_RGB888,
.video_timing = {
.h_size = MIPI_DSI_LCD_H_RES,
.v_size = MIPI_DSI_LCD_V_RES,
.hsync_back_porch = MIPI_DSI_LCD_HBP,
.hsync_pulse_width = MIPI_DSI_LCD_HSYNC,
.hsync_front_porch = MIPI_DSI_LCD_HFP,
.vsync_back_porch = MIPI_DSI_LCD_VBP,
.vsync_pulse_width = MIPI_DSI_LCD_VSYNC,
.vsync_front_porch = MIPI_DSI_LCD_VFP,
},
.flags = {
.use_dma2d = true,
}
};
ek79007_vendor_config_t vendor_config = {
.mipi_config = {
.dsi_bus = mipi_dsi_bus,
.dpi_config = &dpi_config,
},
};
esp_lcd_panel_dev_config_t lcd_dev_config = {
.reset_gpio_num = -1,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 24,
.vendor_config = &vendor_config,
};
TEST_ESP_OK(esp_lcd_new_panel_ek79007(mipi_dbi_io, &lcd_dev_config, &mipi_dpi_panel));
// Set color conversion configuration
esp_lcd_color_conv_config_t convert_config = {
.in_color_range = LCD_COLOR_RANGE_FULL,
.out_color_range = LCD_COLOR_RANGE_FULL,
.spec.yuv = {
.conv_std = LCD_YUV_CONV_STD_BT601,
.yuv422.in_pack_order = LCD_YUV422_PACK_ORDER_YUYV,
}
};
TEST_ESP_OK(esp_lcd_dpi_panel_set_color_conversion(mipi_dpi_panel, &convert_config));
TEST_ESP_OK(esp_lcd_panel_reset(mipi_dpi_panel));
TEST_ESP_OK(esp_lcd_panel_init(mipi_dpi_panel));
// YUV images are embedded in the firmware binary
extern const uint8_t image_hello_yuv_start[] asm("_binary_hello_yuv_start");
extern const uint8_t image_world_yuv_start[] asm("_binary_world_yuv_start");
printf("Draw YUV images\r\n");
for (int i = 0; i < 4; i++) {
TEST_ESP_OK(esp_lcd_panel_draw_bitmap(mipi_dpi_panel, 0, 0, 320, 320, image_hello_yuv_start));
vTaskDelay(pdMS_TO_TICKS(1000));
TEST_ESP_OK(esp_lcd_panel_draw_bitmap(mipi_dpi_panel, 0, 0, 320, 320, image_world_yuv_start));
vTaskDelay(pdMS_TO_TICKS(1000));
}
TEST_ESP_OK(esp_lcd_panel_del(mipi_dpi_panel));
TEST_ESP_OK(esp_lcd_panel_io_del(mipi_dbi_io));
TEST_ESP_OK(esp_lcd_del_dsi_bus(mipi_dsi_bus));
free(img);
test_bsp_disable_dsi_phy_power();
}

View File

@ -0,0 +1,13 @@
# How to generate the YUV image from the PNG image
```bash
ffmpeg -i hello.png -pix_fmt yuyv422 hello.yuv
```
## Supported YUV422 packing order
| NAME | NB_COMPONENTS | BITS_PER_PIXEL | BIT_DEPTHS |
|----------|----------------|----------------|------------|
| yuyv422 | 3 | 16 | 8-8-8 |
| yvyu422 | 3 | 16 | 8-8-8 |
| uyvy422 | 3 | 16 | 8-8-8 |

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because one or more lines are too long

View File

@ -170,23 +170,25 @@ static inline void mipi_dsi_brg_ll_credit_reset(dsi_brg_dev_t *dev)
* @brief Set the color coding for the bridge controller
*
* @param dev Pointer to the DSI bridge controller register base address
* @param pixel_format Color coding
* @param color_coding Color coding value
* @param sub_config Sub configuration
*/
static inline void mipi_dsi_brg_ll_set_pixel_format(dsi_brg_dev_t *dev, lcd_color_rgb_pixel_format_t pixel_format, uint32_t sub_config)
static inline void mipi_dsi_brg_ll_set_pixel_format(dsi_brg_dev_t *dev, lcd_color_format_t color_coding, uint32_t sub_config)
{
switch (pixel_format) {
case LCD_COLOR_PIXEL_FORMAT_RGB565:
switch (color_coding) {
case LCD_COLOR_FMT_RGB565:
dev->pixel_type.raw_type = 2;
break;
case LCD_COLOR_PIXEL_FORMAT_RGB666:
case LCD_COLOR_FMT_RGB666:
dev->pixel_type.raw_type = 1;
break;
case LCD_COLOR_PIXEL_FORMAT_RGB888:
case LCD_COLOR_FMT_RGB888:
dev->pixel_type.raw_type = 0;
break;
default:
abort();
// MIPI DSI host can only accept RGB data, no YUV data
HAL_ASSERT(false);
break;
}
dev->pixel_type.dpi_config = sub_config;
}
@ -344,6 +346,36 @@ static inline void mipi_dsi_brg_ll_set_yuv_convert_std(dsi_brg_dev_t *dev, lcd_y
}
}
/**
* @brief Set the YUV422 packing order
*
* @param dev Pointer to the DSI bridge controller register base address
* @param order YUV422 packing order
*/
static inline void mipi_dsi_brg_ll_set_yuv422_pack_order(dsi_brg_dev_t *dev, lcd_yuv422_pack_order_t order)
{
switch (order) {
case LCD_YUV422_PACK_ORDER_UYVY:
dev->yuv_cfg.yuv422_format = 0;
dev->yuv_cfg.yuv_pix_endian = 1;
break;
case LCD_YUV422_PACK_ORDER_VYUY:
dev->yuv_cfg.yuv422_format = 1;
dev->yuv_cfg.yuv_pix_endian = 1;
break;
case LCD_YUV422_PACK_ORDER_YUYV:
dev->yuv_cfg.yuv422_format = 2;
dev->yuv_cfg.yuv_pix_endian = 1;
break;
case LCD_YUV422_PACK_ORDER_YVYU:
dev->yuv_cfg.yuv422_format = 3;
dev->yuv_cfg.yuv_pix_endian = 1;
break;
default:
abort();
}
}
#ifdef __cplusplus
}
#endif

View File

@ -181,19 +181,20 @@ static inline void mipi_dsi_host_ll_dpi_set_vcid(dsi_host_dev_t *dev, uint32_t v
* @param color_coding Color coding value
* @param sub_config Sub configuration value
*/
static inline void mipi_dsi_host_ll_dpi_set_color_coding(dsi_host_dev_t *dev, lcd_color_rgb_pixel_format_t color_coding, uint32_t sub_config)
static inline void mipi_dsi_host_ll_dpi_set_color_coding(dsi_host_dev_t *dev, lcd_color_format_t color_coding, uint32_t sub_config)
{
switch (color_coding) {
case LCD_COLOR_PIXEL_FORMAT_RGB565:
case LCD_COLOR_FMT_RGB565:
dev->dpi_color_coding.dpi_color_coding = MIPI_DSI_LL_COLOR_CODE_16BIT_CONFIG1 + sub_config;
break;
case LCD_COLOR_PIXEL_FORMAT_RGB666:
case LCD_COLOR_FMT_RGB666:
dev->dpi_color_coding.dpi_color_coding = MIPI_DSI_LL_COLOR_CODE_18BIT_CONFIG1 + sub_config;
break;
case LCD_COLOR_PIXEL_FORMAT_RGB888:
case LCD_COLOR_FMT_RGB888:
dev->dpi_color_coding.dpi_color_coding = MIPI_DSI_LL_COLOR_CODE_24BIT;
break;
default:
// MIPI DSI bridge can only write RGB data to the DSI host controller, no YUV data
HAL_ASSERT(false);
break;
}

View File

@ -211,6 +211,16 @@ typedef enum {
COLOR_COMPONENT_INVALID, /*!< Invalid color component */
} color_component_t;
/**
* @brief The order of the components per pack in the YUV422 format
*/
typedef enum {
COLOR_YUV422_PACK_ORDER_YUYV, /*!< YUYV */
COLOR_YUV422_PACK_ORDER_YVYU, /*!< YVYU */
COLOR_YUV422_PACK_ORDER_UYVY, /*!< UYVY */
COLOR_YUV422_PACK_ORDER_VYUY, /*!< VYUY */
} color_yuv422_pack_order_t;
#ifdef __cplusplus
}
#endif

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -48,6 +48,16 @@ typedef enum {
LCD_COLOR_PIXEL_FORMAT_RGB888 = COLOR_PIXEL_RGB888, /*!< 24 bits, 8 bits per R/G/B value */
} lcd_color_rgb_pixel_format_t;
/**
* @brief LCD color format
*/
typedef enum {
LCD_COLOR_FMT_RGB565 = COLOR_TYPE_ID(COLOR_SPACE_RGB, COLOR_PIXEL_RGB565), ///< RGB565
LCD_COLOR_FMT_RGB666 = COLOR_TYPE_ID(COLOR_SPACE_RGB, COLOR_PIXEL_RGB666), ///< RGB666
LCD_COLOR_FMT_RGB888 = COLOR_TYPE_ID(COLOR_SPACE_RGB, COLOR_PIXEL_RGB888), ///< RGB888
LCD_COLOR_FMT_YUV422 = COLOR_TYPE_ID(COLOR_SPACE_YUV, COLOR_PIXEL_YUV422), ///< YUV422
} lcd_color_format_t;
/**
* @brief LCD color range
*/
@ -73,6 +83,17 @@ typedef enum {
LCD_YUV_CONV_STD_BT709 = COLOR_CONV_STD_RGB_YUV_BT709, /*!< YUV<->RGB conversion standard: BT.709 */
} lcd_yuv_conv_std_t;
/**
* @brief YUV422 packing order
*/
typedef enum {
LCD_YUV422_PACK_ORDER_YUYV = COLOR_YUV422_PACK_ORDER_YUYV, /*!< YUYV */
LCD_YUV422_PACK_ORDER_YVYU = COLOR_YUV422_PACK_ORDER_YVYU, /*!< YVYU */
LCD_YUV422_PACK_ORDER_UYVY = COLOR_YUV422_PACK_ORDER_UYVY, /*!< UYVY */
LCD_YUV422_PACK_ORDER_VYUY = COLOR_YUV422_PACK_ORDER_VYUY, /*!< VYUY */
} lcd_yuv422_pack_order_t;
#ifdef __cplusplus
}
#endif

View File

@ -150,7 +150,7 @@ void mipi_dsi_hal_host_gen_read_short_packet(mipi_dsi_hal_context_t *hal, uint8_
* @param color_coding Color coding
* @param sub_config Sub configuration
*/
void mipi_dsi_hal_host_dpi_set_color_coding(mipi_dsi_hal_context_t *hal, lcd_color_rgb_pixel_format_t color_coding, uint32_t sub_config);
void mipi_dsi_hal_host_dpi_set_color_coding(mipi_dsi_hal_context_t *hal, lcd_color_format_t color_coding, uint32_t sub_config);
/**
* @brief Set horizontal timing parameters for DPI

View File

@ -220,7 +220,7 @@ void mipi_dsi_hal_host_gen_read_dcs_command(mipi_dsi_hal_context_t *hal, uint8_t
mipi_dsi_hal_host_gen_read_short_packet(hal, vc, MIPI_DSI_DT_DCS_READ_0, header_data, ret_param, param_buf_size);
}
void mipi_dsi_hal_host_dpi_set_color_coding(mipi_dsi_hal_context_t *hal, lcd_color_rgb_pixel_format_t color_coding, uint32_t sub_config)
void mipi_dsi_hal_host_dpi_set_color_coding(mipi_dsi_hal_context_t *hal, lcd_color_format_t color_coding, uint32_t sub_config)
{
mipi_dsi_host_ll_dpi_set_color_coding(hal->host, color_coding, sub_config);
mipi_dsi_brg_ll_set_pixel_format(hal->bridge, color_coding, sub_config);

View File

@ -60,7 +60,7 @@ MIPI DSI Interfaced LCD
- :cpp:member:`esp_lcd_dpi_panel_config_t::virtual_channel` sets the virtual channel number to use. Like the DBI interface, we also need to set the virtual channel for the DPI interface. If you only have one LCD connected, you can set this to ``0``.
- :cpp:member:`esp_lcd_dpi_panel_config_t::dpi_clk_src` sets the clock source for the DPI interface. The available clock sources are listed in :cpp:type:`mipi_dsi_dpi_clock_source_t`.
- :cpp:member:`esp_lcd_dpi_panel_config_t::dpi_clock_freq_mhz` sets the DPI clock frequency in MHz. Higher pixel clock frequency results in higher refresh rate, but may cause flickering if the DMA bandwidth is not sufficient or the LCD controller chip does not support high pixel clock frequency.
- :cpp:member:`esp_lcd_dpi_panel_config_t::pixel_format` sets the pixel format of the pixel data. The available pixel formats are listed in :cpp:type:`lcd_color_rgb_pixel_format_t`. We usually use **RGB888** for MIPI LCD to get the best color depth.
- :cpp:member:`esp_lcd_dpi_panel_config_t::in_color_format` sets the pixel format of the input pixel data. The available pixel formats are listed in :cpp:type:`lcd_color_format_t`. We usually use **RGB888** for MIPI LCD to get the best color depth.
- :cpp:member:`esp_lcd_dpi_panel_config_t::video_timing` sets the LCD panel specific timing parameters. All required parameters are listed in the :cpp:type:`esp_lcd_video_timing_t`, including the LCD resolution and blanking porches. Please fill them according to the datasheet of your LCD.
- :cpp:member:`esp_lcd_dpi_panel_config_t::extra_dpi_panel_flags::use_dma2d` sets whether to use the 2D DMA peripheral to copy the user data to the frame buffer, asynchronously.
@ -71,7 +71,7 @@ MIPI DSI Interfaced LCD
.virtual_channel = 0,
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
.dpi_clock_freq_mhz = 1 * 1000,
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB888,
.in_color_format = LCD_COLOR_FMT_RGB888,
.video_timing = {
.h_size = EXAMPLE_MIPI_DSI_LCD_H_RES,
.v_size = EXAMPLE_MIPI_DSI_LCD_V_RES,

View File

@ -60,7 +60,7 @@ MIPI DSI 接口的 LCD
- :cpp:member:`esp_lcd_dpi_panel_config_t::virtual_channel` 设置虚拟通道号。与 DBI 接口类似DPI 接口也需要设置虚拟通道。如果只连接了一个 LCD则将此值设置为 ``0``
- :cpp:member:`esp_lcd_dpi_panel_config_t::dpi_clk_src` 设置 DPI 接口的时钟源。可用的时钟源列表见 :cpp:type:`mipi_dsi_dpi_clock_source_t`
- :cpp:member:`esp_lcd_dpi_panel_config_t::dpi_clock_freq_mhz` 设置 DPI 时钟频率 (MHz)。像素时钟频率越高,刷新率越高,但如果 DMA 带宽不足或 LCD 控制器芯片不支持高像素时钟频率,则可能会导致闪烁。
- :cpp:member:`esp_lcd_dpi_panel_config_t::pixel_format` 设置像素数据的像素格式。可用的像素格式见 :cpp:type:`lcd_color_rgb_pixel_format_t`。MIPI LCD 通常使用 **RGB888** 来获得最佳色彩深度。
- :cpp:member:`esp_lcd_dpi_panel_config_t::in_color_format` 设置输入的像素数据的格式。可用的像素格式见 :cpp:type:`lcd_color_format_t`。MIPI LCD 通常使用 **RGB888** 来获得最佳色彩深度。
- :cpp:member:`esp_lcd_dpi_panel_config_t::video_timing` 设置 LCD 面板的特定时序参数。包括 LCD 分辨率和消隐间隔在内的必要参数列表见 :cpp:type:`esp_lcd_video_timing_t`,请依据 LCD 技术规格书填写参数。
- :cpp:member:`esp_lcd_dpi_panel_config_t::extra_dpi_panel_flags::use_dma2d` 设置是否用 2D DMA 将用户数据异步复制到帧 buffer 中。
@ -71,7 +71,7 @@ MIPI DSI 接口的 LCD
.virtual_channel = 0,
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
.dpi_clock_freq_mhz = 1 * 1000,
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB888,
.in_color_format = LCD_COLOR_FMT_RGB888,
.video_timing = {
.h_size = EXAMPLE_MIPI_DSI_LCD_H_RES,
.v_size = EXAMPLE_MIPI_DSI_LCD_V_RES,

View File

@ -36,7 +36,7 @@ void example_dsi_resource_alloc(esp_lcd_dsi_bus_handle_t *mipi_dsi_bus, esp_lcd_
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
.dpi_clock_freq_mhz = EXAMPLE_MIPI_DSI_DPI_CLK_MHZ,
.virtual_channel = 0,
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565,
.in_color_format = LCD_COLOR_FMT_RGB565,
.video_timing = {
.h_size = CONFIG_EXAMPLE_MIPI_DSI_DISP_HRES,
.v_size = CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES,

View File

@ -216,7 +216,7 @@ void app_main(void)
.virtual_channel = 0,
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
.dpi_clock_freq_mhz = EXAMPLE_MIPI_DSI_DPI_CLK_MHZ,
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB888,
.in_color_format = LCD_COLOR_FMT_RGB888,
.video_timing = {
.h_size = EXAMPLE_MIPI_DSI_LCD_H_RES,
.v_size = EXAMPLE_MIPI_DSI_LCD_V_RES,