refactor(lcd): unify the color conversion API in RGB and DSI driver

Also adopt the FourCC standard to describe color format.
See also
https://developer.espressif.com/blog/2025/04/esp-fourcc-introduction/
This commit is contained in:
morris
2025-10-23 12:21:16 +08:00
parent 3911e65523
commit dff7c452e6
23 changed files with 314 additions and 330 deletions
+62
View File
@@ -0,0 +1,62 @@
# ESP Hardware Abstraction Layer for LCD Peripherals
> [!NOTE]
> This component is currently in beta. Its API, behavior, and compatibility may change at any time and without notice; backward compatibility is not guaranteed. Use caution when integrating into production systems.
## Overview
The `esp_hal_lcd` component provides a **Hardware Abstraction Layer** for LCD (Liquid Crystal Display) controllers and MIPI DSI (Display Serial Interface) peripherals across ESP-IDF supported targets. This HAL enables efficient communication with various display interfaces including I80 parallel, RGB parallel, and MIPI DSI serial interfaces.
## Architecture
The LCD HAL is structured in two main sub-layers:
1. **HAL Layer (Upper)**: Defines the operational steps and data structures required to control LCD peripherals (e.g., initialization, clock configuration, data transmission).
2. **Low-Level Layer (Bottom)**: Serves as a translation layer between the HAL and the register files defined in the `soc` component, handling target-specific register configurations.
## Supported LCD Interfaces
This HAL supports various LCD interface types depending on the ESP chip:
- **I80 (Intel 8080) Parallel Interface**: 8-bit/16-bit parallel interface commonly used for MCU-based displays
- **RGB Parallel Interface**: Direct RGB pixel data interface for high-performance displays
- **MIPI DSI Interface**: High-speed serial interface supporting:
- DSI Host Controller
- DSI Bridge Controller
- PHY layer configuration
- DCS (Display Command Set) commands
- Generic read/write operations
## Features
### LCD Common Features
- Pixel clock (PCLK) calculation and configuration
- Multiple color format support using FourCC standard:
- RGB565, RGB888
- YUV422 (YUYV, YVYU, VYUY, UYVY)
- GRAY8 (8-bit grayscale)
- RGB data endian configuration (MSB/LSB first)
- Color space conversion (RGB ↔ YUV)
- YUV conversion standards (BT.601, BT.709)
- Color range control (Limited/Full)
### MIPI DSI Specific Features
- PHY PLL configuration for high-speed lanes
- Virtual channel management
- DCS command transmission (short/long writes)
- Generic interface for command/data operations
- Test pattern generation (vertical/horizontal bars, BER patterns)
- Multi-lane data transmission support
- DPI (Display Pixel Interface) clock configuration
## Usage
The HAL functions primarily serve ESP-IDF LCD peripheral drivers such as `esp_lcd` component.
Advanced developers can use these interfaces directly when implementing custom display drivers, with the understanding that API stability is not guaranteed.
## Dependencies
- `soc`: Provides chip-specific register definitions and peripheral capabilities
- `hal`: Core hardware abstraction utilities, macros, and color type definitions
@@ -224,7 +224,7 @@ static inline void lcd_ll_set_pixel_clock_prescale(lcd_cam_dev_t *dev, uint32_t
* @param dev LCD register base address
* @param en True to enable converter, False to disable converter
*/
static inline void lcd_ll_enable_rgb_yuv_convert(lcd_cam_dev_t *dev, bool en)
static inline void lcd_ll_enable_color_convert(lcd_cam_dev_t *dev, bool en)
{
dev->lcd_rgb_yuv.lcd_conv_enable = en;
}
@@ -287,50 +287,46 @@ static inline void lcd_ll_set_yuv_convert_std(lcd_cam_dev_t *dev, lcd_yuv_conv_s
}
/**
* @brief Set the converter mode: RGB565 to YUV
* @brief Set the converter mode: RGB to YUV
*
* @param dev LCD register base address
* @param yuv_sample YUV sample mode
* @param in_color_format Input color format
* @param out_color_format Output color format
*/
static inline void lcd_ll_set_convert_mode_rgb_to_yuv(lcd_cam_dev_t *dev, lcd_yuv_sample_t yuv_sample)
static inline void lcd_ll_set_rgb2yuv_convert_mode(lcd_cam_dev_t *dev, lcd_color_format_t in_color_format, lcd_color_format_t out_color_format)
{
dev->lcd_rgb_yuv.lcd_conv_trans_mode = 1;
dev->lcd_rgb_yuv.lcd_conv_yuv2yuv_mode = 3;
switch (yuv_sample) {
case LCD_YUV_SAMPLE_422:
switch (out_color_format) {
case LCD_COLOR_FMT_YUV422_UYVY:
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 0;
break;
case LCD_YUV_SAMPLE_420:
case LCD_COLOR_FMT_YUV420_OUYY_EVYY:
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 1;
break;
case LCD_YUV_SAMPLE_411:
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 2;
break;
default:
abort();
}
}
/**
* @brief Set the converter mode: YUV to RGB565
* @brief Set the converter mode: YUV to RGB
*
* @param dev LCD register base address
* @param yuv_sample YUV sample mode
* @param in_color_format Input color format
* @param out_color_format Output color format
*/
static inline void lcd_ll_set_convert_mode_yuv_to_rgb(lcd_cam_dev_t *dev, lcd_yuv_sample_t yuv_sample)
static inline void lcd_ll_set_yuv2rgb_convert_mode(lcd_cam_dev_t *dev, lcd_color_format_t in_color_format, lcd_color_format_t out_color_format)
{
dev->lcd_rgb_yuv.lcd_conv_trans_mode = 0;
dev->lcd_rgb_yuv.lcd_conv_yuv2yuv_mode = 3;
switch (yuv_sample) {
case LCD_YUV_SAMPLE_422:
switch (in_color_format) {
case LCD_COLOR_FMT_YUV422_UYVY:
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 0;
break;
case LCD_YUV_SAMPLE_420:
case LCD_COLOR_FMT_YUV420_OUYY_EVYY:
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 1;
break;
case LCD_YUV_SAMPLE_411:
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 2;
break;
default:
abort();
}
@@ -340,36 +336,29 @@ static inline void lcd_ll_set_convert_mode_yuv_to_rgb(lcd_cam_dev_t *dev, lcd_yu
* @brief Set the converter mode: YUV to YUV
*
* @param dev LCD register base address
* @param src_sample Source YUV sample mode
* @param dst_sample Destination YUV sample mode
* @param in_color_format Input color format
* @param out_color_format Output color format
*/
static inline void lcd_ll_set_convert_mode_yuv_to_yuv(lcd_cam_dev_t *dev, lcd_yuv_sample_t src_sample, lcd_yuv_sample_t dst_sample)
static inline void lcd_ll_set_yuv2yuv_convert_mode(lcd_cam_dev_t *dev, lcd_color_format_t in_color_format, lcd_color_format_t out_color_format)
{
HAL_ASSERT(src_sample != dst_sample);
dev->lcd_rgb_yuv.lcd_conv_trans_mode = 1;
switch (src_sample) {
case LCD_YUV_SAMPLE_422:
switch (in_color_format) {
case LCD_COLOR_FMT_YUV422_UYVY:
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 0;
break;
case LCD_YUV_SAMPLE_420:
case LCD_COLOR_FMT_YUV420_OUYY_EVYY:
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 1;
break;
case LCD_YUV_SAMPLE_411:
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 2;
break;
default:
abort();
}
switch (dst_sample) {
case LCD_YUV_SAMPLE_422:
switch (out_color_format) {
case LCD_COLOR_FMT_YUV422_UYVY:
dev->lcd_rgb_yuv.lcd_conv_yuv2yuv_mode = 0;
break;
case LCD_YUV_SAMPLE_420:
case LCD_COLOR_FMT_YUV420_OUYY_EVYY:
dev->lcd_rgb_yuv.lcd_conv_yuv2yuv_mode = 1;
break;
case LCD_YUV_SAMPLE_411:
dev->lcd_rgb_yuv.lcd_conv_yuv2yuv_mode = 2;
break;
default:
abort();
}
@@ -310,24 +310,24 @@ 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
* @param color_format Color format
*/
static inline void mipi_dsi_brg_ll_set_yuv422_pack_order(dsi_brg_dev_t *dev, lcd_yuv422_pack_order_t order)
static inline void _mipi_dsi_brg_ll_set_yuv422_pack_order(dsi_brg_dev_t *dev, lcd_color_format_t color_format)
{
switch (order) {
case LCD_YUV422_PACK_ORDER_UYVY:
switch (color_format) {
case LCD_COLOR_FMT_YUV422_UYVY:
dev->yuv_cfg.yuv422_format = 0;
dev->yuv_cfg.yuv_pix_endian = 1;
break;
case LCD_YUV422_PACK_ORDER_VYUY:
case LCD_COLOR_FMT_YUV422_VYUY:
dev->yuv_cfg.yuv422_format = 1;
dev->yuv_cfg.yuv_pix_endian = 1;
break;
case LCD_YUV422_PACK_ORDER_YUYV:
case LCD_COLOR_FMT_YUV422_YUYV:
dev->yuv_cfg.yuv422_format = 2;
dev->yuv_cfg.yuv_pix_endian = 1;
break;
case LCD_YUV422_PACK_ORDER_YVYU:
case LCD_COLOR_FMT_YUV422_YVYU:
dev->yuv_cfg.yuv422_format = 3;
dev->yuv_cfg.yuv_pix_endian = 1;
break;
@@ -349,22 +349,23 @@ static inline void mipi_dsi_brg_ll_set_yuv422_pack_order(dsi_brg_dev_t *dev, lcd
*/
static inline void mipi_dsi_brg_ll_set_input_color_format(dsi_brg_dev_t *dev, lcd_color_format_t color_format)
{
bool is_yuv422 = false;
switch (color_format) {
case LCD_COLOR_FMT_RGB888:
dev->pixel_type.raw_type = 0;
dev->pixel_type.data_in_type = 0;
break;
case LCD_COLOR_FMT_RGB666:
dev->pixel_type.raw_type = 1;
dev->pixel_type.data_in_type = 0;
break;
case LCD_COLOR_FMT_RGB565:
dev->pixel_type.raw_type = 2;
dev->pixel_type.data_in_type = 0;
break;
case LCD_COLOR_FMT_YUV422:
case LCD_COLOR_FMT_YUV422_YUYV:
case LCD_COLOR_FMT_YUV422_YVYU:
case LCD_COLOR_FMT_YUV422_VYUY:
case LCD_COLOR_FMT_YUV422_UYVY:
dev->pixel_type.raw_type = 9;
dev->pixel_type.data_in_type = 1;
is_yuv422 = true;
break;
case LCD_COLOR_FMT_GRAY8:
dev->pixel_type.raw_type = 12;
@@ -373,6 +374,11 @@ static inline void mipi_dsi_brg_ll_set_input_color_format(dsi_brg_dev_t *dev, lc
default:
abort();
}
// set YUV422 packing order
if (is_yuv422) {
_mipi_dsi_brg_ll_set_yuv422_pack_order(dev, color_format);
}
}
/**
@@ -387,9 +393,6 @@ static inline void mipi_dsi_brg_ll_set_output_color_format(dsi_brg_dev_t *dev, l
case LCD_COLOR_FMT_RGB888:
dev->pixel_type.dpi_type = 0;
break;
case LCD_COLOR_FMT_RGB666:
dev->pixel_type.dpi_type = 1;
break;
case LCD_COLOR_FMT_RGB565:
dev->pixel_type.dpi_type = 2;
break;
@@ -435,25 +438,31 @@ static inline void mipi_dsi_brg_ll_set_input_color_range(dsi_brg_dev_t *dev, lcd
*/
static inline void mipi_dsi_brg_ll_set_input_color_format(dsi_brg_dev_t *dev, lcd_color_format_t color_format)
{
bool is_yuv422 = false;
switch (color_format) {
case LCD_COLOR_FMT_RGB888:
dev->pixel_type.raw_type = 0;
dev->pixel_type.data_in_type = 0;
break;
case LCD_COLOR_FMT_RGB666:
dev->pixel_type.raw_type = 1;
dev->pixel_type.data_in_type = 0;
break;
case LCD_COLOR_FMT_RGB565:
dev->pixel_type.raw_type = 2;
dev->pixel_type.data_in_type = 0;
break;
case LCD_COLOR_FMT_YUV422:
case LCD_COLOR_FMT_YUV422_YUYV:
case LCD_COLOR_FMT_YUV422_YVYU:
case LCD_COLOR_FMT_YUV422_VYUY:
case LCD_COLOR_FMT_YUV422_UYVY:
dev->pixel_type.data_in_type = 1;
is_yuv422 = true;
break;
default:
abort();
}
// set YUV422 packing order
if (is_yuv422) {
_mipi_dsi_brg_ll_set_yuv422_pack_order(dev, color_format);
}
}
/**
@@ -468,9 +477,6 @@ static inline void mipi_dsi_brg_ll_set_output_color_format(dsi_brg_dev_t *dev, l
case LCD_COLOR_FMT_RGB565:
dev->pixel_type.raw_type = 2;
break;
case LCD_COLOR_FMT_RGB666:
dev->pixel_type.raw_type = 1;
break;
case LCD_COLOR_FMT_RGB888:
dev->pixel_type.raw_type = 0;
break;
@@ -188,9 +188,6 @@ static inline void mipi_dsi_host_ll_dpi_set_color_coding(dsi_host_dev_t *dev, lc
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_FMT_RGB666:
dev->dpi_color_coding.dpi_color_coding = MIPI_DSI_LL_COLOR_CODE_18BIT_CONFIG1 + sub_config;
break;
case LCD_COLOR_FMT_RGB888:
dev->dpi_color_coding.dpi_color_coding = MIPI_DSI_LL_COLOR_CODE_24BIT;
break;
@@ -195,7 +195,7 @@ static inline void lcd_ll_set_pixel_clock_prescale(lcd_cam_dev_t *dev, uint32_t
* @param dev LCD register base address
* @param en True to enable converter, False to disable converter
*/
static inline void lcd_ll_enable_rgb_yuv_convert(lcd_cam_dev_t *dev, bool en)
static inline void lcd_ll_enable_color_convert(lcd_cam_dev_t *dev, bool en)
{
dev->lcd_rgb_yuv.lcd_conv_bypass = en;
}
@@ -258,50 +258,46 @@ static inline void lcd_ll_set_yuv_convert_std(lcd_cam_dev_t *dev, lcd_yuv_conv_s
}
/**
* @brief Set the converter mode: RGB565 to YUV
* @brief Set the converter mode: RGB to YUV
*
* @param dev LCD register base address
* @param yuv_sample YUV sample mode
* @param in_color_format Input color format
* @param out_color_format Output color format
*/
static inline void lcd_ll_set_convert_mode_rgb_to_yuv(lcd_cam_dev_t *dev, lcd_yuv_sample_t yuv_sample)
static inline void lcd_ll_set_rgb2yuv_convert_mode(lcd_cam_dev_t *dev, lcd_color_format_t in_color_format, lcd_color_format_t out_color_format)
{
dev->lcd_rgb_yuv.lcd_conv_trans_mode = 1;
dev->lcd_rgb_yuv.lcd_conv_yuv2yuv_mode = 3;
switch (yuv_sample) {
case LCD_YUV_SAMPLE_422:
switch (out_color_format) {
case LCD_COLOR_FMT_YUV422_UYVY:
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 0;
break;
case LCD_YUV_SAMPLE_420:
case LCD_COLOR_FMT_YUV420_OUYY_EVYY:
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 1;
break;
case LCD_YUV_SAMPLE_411:
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 2;
break;
default:
abort();
}
}
/**
* @brief Set the converter mode: YUV to RGB565
* @brief Set the converter mode: YUV to RGB
*
* @param dev LCD register base address
* @param yuv_sample YUV sample mode
* @param in_color_format Input color format
* @param out_color_format Output color format
*/
static inline void lcd_ll_set_convert_mode_yuv_to_rgb(lcd_cam_dev_t *dev, lcd_yuv_sample_t yuv_sample)
static inline void lcd_ll_set_yuv2rgb_convert_mode(lcd_cam_dev_t *dev, lcd_color_format_t in_color_format, lcd_color_format_t out_color_format)
{
dev->lcd_rgb_yuv.lcd_conv_trans_mode = 0;
dev->lcd_rgb_yuv.lcd_conv_yuv2yuv_mode = 3;
switch (yuv_sample) {
case LCD_YUV_SAMPLE_422:
switch (in_color_format) {
case LCD_COLOR_FMT_YUV422_UYVY:
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 0;
break;
case LCD_YUV_SAMPLE_420:
case LCD_COLOR_FMT_YUV420_OUYY_EVYY:
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 1;
break;
case LCD_YUV_SAMPLE_411:
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 2;
break;
default:
abort();
}
@@ -311,36 +307,29 @@ static inline void lcd_ll_set_convert_mode_yuv_to_rgb(lcd_cam_dev_t *dev, lcd_yu
* @brief Set the converter mode: YUV to YUV
*
* @param dev LCD register base address
* @param src_sample Source YUV sample mode
* @param dst_sample Destination YUV sample mode
* @param in_color_format Input color format
* @param out_color_format Output color format
*/
static inline void lcd_ll_set_convert_mode_yuv_to_yuv(lcd_cam_dev_t *dev, lcd_yuv_sample_t src_sample, lcd_yuv_sample_t dst_sample)
static inline void lcd_ll_set_yuv2yuv_convert_mode(lcd_cam_dev_t *dev, lcd_color_format_t in_color_format, lcd_color_format_t out_color_format)
{
HAL_ASSERT(src_sample != dst_sample);
dev->lcd_rgb_yuv.lcd_conv_trans_mode = 1;
switch (src_sample) {
case LCD_YUV_SAMPLE_422:
switch (in_color_format) {
case LCD_COLOR_FMT_YUV422_UYVY:
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 0;
break;
case LCD_YUV_SAMPLE_420:
case LCD_COLOR_FMT_YUV420_OUYY_EVYY:
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 1;
break;
case LCD_YUV_SAMPLE_411:
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 2;
break;
default:
abort();
}
switch (dst_sample) {
case LCD_YUV_SAMPLE_422:
switch (out_color_format) {
case LCD_COLOR_FMT_YUV422_UYVY:
dev->lcd_rgb_yuv.lcd_conv_yuv2yuv_mode = 0;
break;
case LCD_YUV_SAMPLE_420:
case LCD_COLOR_FMT_YUV420_OUYY_EVYY:
dev->lcd_rgb_yuv.lcd_conv_yuv2yuv_mode = 1;
break;
case LCD_YUV_SAMPLE_411:
dev->lcd_rgb_yuv.lcd_conv_yuv2yuv_mode = 2;
break;
default:
abort();
}
+9 -42
View File
@@ -32,31 +32,17 @@ typedef enum {
} lcd_rgb_data_endian_t;
/**
* @brief The color space of the LCD input color data
* @brief LCD color type, in FourCC format
*/
typedef enum {
LCD_COLOR_SPACE_RGB = COLOR_SPACE_RGB, /*!< Color space: RGB */
LCD_COLOR_SPACE_YUV = COLOR_SPACE_YUV, /*!< Color space: YUV */
} lcd_color_space_t;
/**
* @brief LCD color pixel format in RGB color space
*/
typedef enum {
LCD_COLOR_PIXEL_FORMAT_RGB565 = COLOR_PIXEL_RGB565, /*!< 16 bits, 5 bits per R/B value, 6 bits for G value */
LCD_COLOR_PIXEL_FORMAT_RGB666 = COLOR_PIXEL_RGB666, /*!< 18 bits, 6 bits per R/G/B value */
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_FMT_GRAY8 = COLOR_TYPE_ID(COLOR_SPACE_GRAY, COLOR_PIXEL_GRAY8), ///< 8-bit gray scale
LCD_COLOR_FMT_GRAY8 = ESP_COLOR_FOURCC_GREY, ///< 8-bit gray scale
LCD_COLOR_FMT_RGB565 = ESP_COLOR_FOURCC_RGB16_BE, ///< RGB565
LCD_COLOR_FMT_RGB888 = ESP_COLOR_FOURCC_RGB24, ///< RGB888
LCD_COLOR_FMT_YUV422_YUYV = ESP_COLOR_FOURCC_YUYV, ///< YUV422 packed in YUYV order
LCD_COLOR_FMT_YUV422_YVYU = ESP_COLOR_FOURCC_YVYU, ///< YUV422 packed in YVYU order
LCD_COLOR_FMT_YUV422_VYUY = ESP_COLOR_FOURCC_VYUY, ///< YUV422 packed in VYUY order
LCD_COLOR_FMT_YUV422_UYVY = ESP_COLOR_FOURCC_UYVY, ///< YUV422 packed in UYVY order
LCD_COLOR_FMT_YUV420_OUYY_EVYY = ESP_COLOR_FOURCC_OUYY_EVYY, ///< YUV420 packed in OUYY/EVYY order
} lcd_color_format_t;
/**
@@ -67,15 +53,6 @@ typedef enum {
LCD_COLOR_RANGE_FULL = COLOR_RANGE_FULL, /*!< Full color range */
} lcd_color_range_t;
/**
* @brief YUV sampling method
*/
typedef enum {
LCD_YUV_SAMPLE_422 = COLOR_PIXEL_YUV422, /*!< YUV 4:2:2 sampling */
LCD_YUV_SAMPLE_420 = COLOR_PIXEL_YUV420, /*!< YUV 4:2:0 sampling */
LCD_YUV_SAMPLE_411 = COLOR_PIXEL_YUV411, /*!< YUV 4:1:1 sampling */
} lcd_yuv_sample_t;
/**
* @brief The standard used for conversion between RGB and YUV
*/
@@ -84,16 +61,6 @@ 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
+7 -38
View File
@@ -184,33 +184,11 @@ esp_err_t esp_lcd_new_panel_dpi(esp_lcd_dsi_bus_handle_t bus, const esp_lcd_dpi_
// by default, use RGB888 as the input color format
lcd_color_format_t in_color_format = LCD_COLOR_FMT_RGB888;
size_t bits_per_pixel = 24;
// the deprecated way to set the pixel format
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
switch (panel_config->pixel_format) {
case LCD_COLOR_PIXEL_FORMAT_RGB565:
bits_per_pixel = 16;
break;
case LCD_COLOR_PIXEL_FORMAT_RGB666:
// RGB data in the memory must be constructed in 6-6-6 (18 bits) for each pixel
bits_per_pixel = 18;
break;
case LCD_COLOR_PIXEL_FORMAT_RGB888:
bits_per_pixel = 24;
break;
}
in_color_format = COLOR_TYPE_ID(COLOR_SPACE_RGB, panel_config->pixel_format);
#pragma GCC diagnostic pop
// the recommended way to set the input color format
// override in_color_format if specified by the user
if (panel_config->in_color_format) {
in_color_format = panel_config->in_color_format;
// if user sets the in_color_format, it can override the pixel format setting
color_space_pixel_format_t in_color_id = {
.color_type_id = in_color_format,
};
bits_per_pixel = color_hal_pixel_format_get_bit_depth(in_color_id);
}
size_t bits_per_pixel = color_hal_pixel_format_fourcc_get_bit_depth(in_color_format);
// by default, out_color_format is the same as in_color_format (i.e. no color format conversion)
lcd_color_format_t out_color_format = in_color_format;
if (panel_config->out_color_format) {
@@ -574,9 +552,7 @@ static esp_err_t dpi_panel_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int
.dst_offset_y = y_start,
.copy_size_x = x_end - x_start,
.copy_size_y = y_end - y_start,
.pixel_format_unique_id = {
.color_type_id = dpi_panel->in_color_format,
}
.pixel_format_fourcc_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");
}
@@ -584,22 +560,15 @@ 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_err_t esp_lcd_dpi_panel_set_yuv_conversion(esp_lcd_panel_handle_t panel, const esp_lcd_color_conv_yuv_config_t *config)
{
ESP_RETURN_ON_FALSE(panel, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ESP_RETURN_ON_FALSE(panel && config, 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_input_color_range(hal->bridge, config->in_color_range);
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");
}
mipi_dsi_brg_ll_set_input_color_range(hal->bridge, config->in_color_range);
mipi_dsi_brg_ll_set_yuv_convert_std(hal->bridge, config->conv_std);
return ESP_OK;
}
@@ -91,8 +91,6 @@ typedef struct {
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 */
/** @deprecated Duplicate of in_color_format; use in_color_format instead. */
lcd_color_rgb_pixel_format_t pixel_format __attribute__((deprecated("pixel_format is deprecated, use in_color_format instead"))); /*!< Pixel format that used by the MIPI LCD device */
/// Extra configuration flags for MIPI DSI DPI panel
struct extra_dpi_panel_flags {
uint32_t use_dma2d: 1; /*!< Use DMA2D to copy user buffer to the frame buffer when necessary */
@@ -141,7 +139,7 @@ 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
* @brief Set color conversion (YUV<->RGB) 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
@@ -150,7 +148,7 @@ esp_err_t esp_lcd_dpi_panel_set_pattern(esp_lcd_panel_handle_t dpi_panel, mipi_d
* - 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);
esp_err_t esp_lcd_dpi_panel_set_yuv_conversion(esp_lcd_panel_handle_t dpi_panel, const esp_lcd_color_conv_yuv_config_t *config);
/**
* @brief Type of LCD DPI panel event data
@@ -176,8 +176,8 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc
ESP_GOTO_ON_ERROR(ret, err, TAG, "install DMA failed");
// disable RGB-LCD mode
lcd_ll_enable_rgb_mode(bus->hal.dev, false);
// disable YUV-RGB converter
lcd_ll_enable_rgb_yuv_convert(bus->hal.dev, false);
// disable color converter
lcd_ll_enable_color_convert(bus->hal.dev, false);
// set how much data to read from DMA each time
lcd_ll_set_dma_read_stride(bus->hal.dev, bus->bus_width);
// sometime, we need to change the output data order: ABAB->BABA
+5 -12
View File
@@ -64,20 +64,13 @@ typedef struct {
} esp_lcd_panel_io_callbacks_t;
/**
* @brief Configuration of LCD color conversion
* @brief Configuration of LCD color conversion: YUV <-> RGB
*/
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;
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 */
lcd_yuv_conv_std_t conv_std; /*!< YUV conversion standard: BT601, BT709 */
} esp_lcd_color_conv_yuv_config_t;
#ifdef __cplusplus
}
@@ -60,7 +60,7 @@ typedef struct {
size_t dst_offset_y; /*!< Copy action will start from this offset in destination buffer in the y direction, offset count in the number of pixels */
size_t copy_size_x; /*!< Copy size in the x direction, size count in the number of pixels */
size_t copy_size_y; /*!< Copy size in the y direction, size count in the number of pixels */
color_space_pixel_format_t pixel_format_unique_id; /*!< Pixel format unique ID */
uint32_t pixel_format_fourcc_id; /*!< Pixel format unique ID */
} esp_async_fbcpy_trans_desc_t;
/**
+57 -66
View File
@@ -12,12 +12,13 @@
#include "sdkconfig.h"
#if CONFIG_LCD_ENABLE_DEBUG_LOG
// The local log level must be defined before including esp_log.h
// Set the maximum log level for this source file
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
// Set the maximum log level for gptimer driver
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
#endif
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_attr.h"
#include "esp_log.h"
#include "esp_check.h"
#include "esp_pm.h"
#include "esp_lcd_panel_interface.h"
@@ -45,6 +46,7 @@
#include "hal/lcd_ll.h"
#include "hal/cache_hal.h"
#include "hal/cache_ll.h"
#include "hal/color_hal.h"
#include "rgb_lcd_rotation_sw.h"
// hardware issue workaround
@@ -73,7 +75,7 @@
#define RGB_LCD_PANEL_MAX_FB_NUM 3 // maximum supported frame buffer number
#define RGB_LCD_PANEL_BOUNCE_BUF_NUM 2 // bounce buffer number
static const char *TAG = "lcd_panel.rgb";
ESP_LOG_ATTR_TAG(TAG, "lcd.rgb");
typedef struct esp_rgb_panel_t esp_rgb_panel_t;
@@ -99,11 +101,12 @@ struct esp_rgb_panel_t {
int panel_id; // LCD panel ID
lcd_hal_context_t hal; // Hal layer object
size_t data_width; // Number of data lines
size_t fb_bits_per_pixel; // Frame buffer color depth, in bpp
size_t num_fbs; // Number of frame buffers
size_t output_bits_per_pixel; // Color depth seen from the output data line. Default to fb_bits_per_pixel, but can be changed by YUV-RGB conversion
size_t dma_burst_size; // DMA transfer burst size
intr_handle_t intr; // LCD peripheral interrupt handle
size_t num_fbs; // Number of frame buffers
lcd_color_format_t in_color_format; // Input color format
lcd_color_format_t out_color_format; // Output color format
size_t fb_bits_per_pixel; // Frame buffer (the input buffer of the LCD controller) color depth, in bpp
size_t dma_burst_size; // DMA transfer burst size
intr_handle_t intr; // LCD peripheral interrupt handle
#if CONFIG_PM_ENABLE
esp_pm_lock_handle_t pm_lock; // Power management lock
#endif
@@ -259,9 +262,6 @@ static esp_err_t lcd_rgb_panel_destroy(esp_rgb_panel_t *rgb_panel)
esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_config, esp_lcd_panel_handle_t *ret_panel)
{
#if CONFIG_LCD_ENABLE_DEBUG_LOG
esp_log_level_set(TAG, ESP_LOG_DEBUG);
#endif
esp_err_t ret = ESP_OK;
esp_rgb_panel_t *rgb_panel = NULL;
ESP_RETURN_ON_FALSE(rgb_panel_config && ret_panel, ESP_ERR_INVALID_ARG, TAG, "invalid parameter");
@@ -288,13 +288,23 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf
}
ESP_RETURN_ON_FALSE(num_fbs <= RGB_LCD_PANEL_MAX_FB_NUM, ESP_ERR_INVALID_ARG, TAG, "too many frame buffers");
// bpp defaults to the number of data lines, but for serial RGB interface, they're not equal
// e.g. for serial RGB 8-bit interface, data lines are 8, whereas the bpp is 24 (RGB888)
size_t fb_bits_per_pixel = data_width;
if (rgb_panel_config->bits_per_pixel) { // override bpp if it's set
fb_bits_per_pixel = rgb_panel_config->bits_per_pixel;
// by default, we guess the input color format according to the data lines number, usually 16 lines means RGB565, 24 lines means RGB888
lcd_color_format_t in_color_format = 0;
if (rgb_panel_config->data_width == 24) {
in_color_format = LCD_COLOR_FMT_RGB888;
} else if (rgb_panel_config->data_width == 16) {
in_color_format = LCD_COLOR_FMT_RGB565;
}
// override the color format if it's explicitly specified by the user
if (rgb_panel_config->in_color_format) {
in_color_format = rgb_panel_config->in_color_format;
}
ESP_RETURN_ON_FALSE(in_color_format != 0, ESP_ERR_INVALID_ARG, TAG, "cannot determine input color format");
// if out_color_format is not specified, set it the same as in_color_format
lcd_color_format_t out_color_format = rgb_panel_config->out_color_format ? rgb_panel_config->out_color_format : in_color_format;
// calculate buffer size
size_t fb_bits_per_pixel = color_hal_pixel_format_fourcc_get_bit_depth(in_color_format);
size_t fb_size = rgb_panel_config->timings.h_res * rgb_panel_config->timings.v_res * fb_bits_per_pixel / 8;
size_t bb_size = rgb_panel_config->bounce_buffer_size_px * fb_bits_per_pixel / 8;
size_t expect_bb_eof_count = 0;
@@ -314,6 +324,8 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf
rgb_panel->fb_size = fb_size;
rgb_panel->bb_size = bb_size;
rgb_panel->fb_bits_per_pixel = fb_bits_per_pixel;
rgb_panel->in_color_format = in_color_format;
rgb_panel->out_color_format = out_color_format;
rgb_panel->expect_eof_count = expect_bb_eof_count;
// register to platform
int panel_id = lcd_com_register_device(LCD_COM_DEVICE_TYPE_RGB, rgb_panel);
@@ -330,26 +342,27 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf
// initialize HAL layer, so we can call LL APIs later
lcd_hal_init(&rgb_panel->hal, panel_id);
lcd_hal_context_t *hal = &rgb_panel->hal;
// enable clock
LCD_CLOCK_SRC_ATOMIC() {
lcd_ll_enable_clock(rgb_panel->hal.dev, true);
lcd_ll_enable_clock(hal->dev, true);
}
// set clock source
ret = lcd_rgb_panel_select_clock_src(rgb_panel, rgb_panel_config->clk_src);
ESP_GOTO_ON_ERROR(ret, err, TAG, "set source clock failed");
// reset peripheral and FIFO after we select a correct clock source
lcd_ll_fifo_reset(rgb_panel->hal.dev);
lcd_ll_reset(rgb_panel->hal.dev);
lcd_ll_fifo_reset(hal->dev);
lcd_ll_reset(hal->dev);
// install interrupt service, (LCD peripheral shares the interrupt source with Camera by different mask)
int isr_flags = LCD_RGB_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED;
ret = esp_intr_alloc_intrstatus(soc_lcd_rgb_signals[panel_id].irq_id, isr_flags,
(uint32_t)lcd_ll_get_interrupt_status_reg(rgb_panel->hal.dev),
(uint32_t)lcd_ll_get_interrupt_status_reg(hal->dev),
LCD_LL_EVENT_RGB, rgb_lcd_default_isr_handler, rgb_panel, &rgb_panel->intr);
ESP_GOTO_ON_ERROR(ret, err, TAG, "install interrupt failed");
PERIPH_RCC_ATOMIC() {
lcd_ll_enable_interrupt(rgb_panel->hal.dev, LCD_LL_EVENT_RGB, false); // disable all interrupts
lcd_ll_enable_interrupt(hal->dev, LCD_LL_EVENT_RGB, false); // disable all interrupts
}
lcd_ll_clear_interrupt_status(rgb_panel->hal.dev, UINT32_MAX); // clear pending interrupt
lcd_ll_clear_interrupt_status(hal->dev, UINT32_MAX); // clear pending interrupt
// install DMA service
rgb_panel->flags.stream_mode = !rgb_panel_config->flags.refresh_on_demand;
@@ -373,7 +386,6 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf
rgb_panel->pclk_gpio_num = rgb_panel_config->pclk_gpio_num;
rgb_panel->timings = rgb_panel_config->timings;
rgb_panel->data_width = rgb_panel_config->data_width;
rgb_panel->output_bits_per_pixel = fb_bits_per_pixel; // by default, the output bpp is the same as the frame buffer bpp
rgb_panel->flags.disp_en_level = !rgb_panel_config->flags.disp_active_low;
rgb_panel->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
// fill function table
@@ -486,53 +498,21 @@ esp_err_t esp_lcd_rgb_panel_refresh(esp_lcd_panel_handle_t panel)
return ESP_OK;
}
esp_err_t esp_lcd_rgb_panel_set_yuv_conversion(esp_lcd_panel_handle_t panel, const esp_lcd_yuv_conv_config_t *config)
esp_err_t esp_lcd_rgb_panel_set_yuv_conversion(esp_lcd_panel_handle_t panel, const esp_lcd_color_conv_yuv_config_t *config)
{
ESP_RETURN_ON_FALSE(panel, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ESP_RETURN_ON_FALSE(panel && config, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
esp_rgb_panel_t *rgb_panel = __containerof(panel, esp_rgb_panel_t, base);
lcd_hal_context_t *hal = &rgb_panel->hal;
bool en_conversion = config != NULL;
// bits per pixel for different YUV sample
const uint8_t bpp_yuv[] = {
[LCD_YUV_SAMPLE_422] = 16,
[LCD_YUV_SAMPLE_420] = 12,
[LCD_YUV_SAMPLE_411] = 12,
};
if (en_conversion) {
if (memcmp(&config->src, &config->dst, sizeof(config->src)) == 0) {
ESP_RETURN_ON_FALSE(false, ESP_ERR_INVALID_ARG, TAG, "conversion source and destination are the same");
}
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);
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];
} else if (config->src.color_space == LCD_COLOR_SPACE_YUV && config->dst.color_space == LCD_COLOR_SPACE_YUV) { // YUV->YUV
lcd_ll_set_convert_mode_yuv_to_yuv(hal->dev, config->src.yuv_sample, config->dst.yuv_sample);
rgb_panel->output_bits_per_pixel = bpp_yuv[config->dst.yuv_sample];
} else {
ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG, "unsupported conversion mode");
}
// set conversion standard
lcd_ll_set_yuv_convert_std(hal->dev, config->std);
// set conversion data width
lcd_ll_set_convert_data_width(hal->dev, rgb_panel->data_width);
// set color range
lcd_ll_set_input_color_range(hal->dev, config->src.color_range);
lcd_ll_set_output_color_range(hal->dev, config->dst.color_range);
} else {
// output bpp equals to frame buffer bpp
rgb_panel->output_bits_per_pixel = rgb_panel->fb_bits_per_pixel;
}
// enable or disable RGB-YUV conversion
lcd_ll_enable_rgb_yuv_convert(hal->dev, en_conversion);
lcd_ll_set_yuv2rgb_convert_mode(hal->dev, rgb_panel->in_color_format, rgb_panel->out_color_format);
// set conversion standard
lcd_ll_set_yuv_convert_std(hal->dev, config->conv_std);
// set color range
lcd_ll_set_input_color_range(hal->dev, config->in_color_range);
lcd_ll_set_output_color_range(hal->dev, config->out_color_range);
// set conversion data width
lcd_ll_set_convert_data_width(hal->dev, rgb_panel->data_width);
return ESP_OK;
}
@@ -569,6 +549,8 @@ static esp_err_t rgb_panel_init(esp_lcd_panel_t *panel)
// enable RGB mode and set data width
lcd_ll_enable_rgb_mode(rgb_panel->hal.dev, true);
lcd_ll_set_dma_read_stride(rgb_panel->hal.dev, rgb_panel->data_width);
// enable conversion if the input color format is different from the output color format
lcd_ll_enable_color_convert(rgb_panel->hal.dev, rgb_panel->in_color_format != rgb_panel->out_color_format);
// enable data phase only
lcd_ll_set_phase_cycles(rgb_panel->hal.dev, 0, 0, 1);
// number of data cycles is controlled by DMA buffer size
@@ -578,8 +560,9 @@ static esp_err_t rgb_panel_init(esp_lcd_panel_t *panel)
!rgb_panel->timings.flags.vsync_idle_low, rgb_panel->timings.flags.de_idle_high);
// configure blank region timing
lcd_ll_set_blank_cycles(rgb_panel->hal.dev, 1, 1); // RGB panel always has a front and back blank (porch region)
size_t out_bits_per_pixel = color_hal_pixel_format_fourcc_get_bit_depth(rgb_panel->out_color_format);
lcd_ll_set_horizontal_timing(rgb_panel->hal.dev, rgb_panel->timings.hsync_pulse_width,
rgb_panel->timings.hsync_back_porch, rgb_panel->timings.h_res * rgb_panel->output_bits_per_pixel / rgb_panel->data_width,
rgb_panel->timings.hsync_back_porch, rgb_panel->timings.h_res * out_bits_per_pixel / rgb_panel->data_width,
rgb_panel->timings.hsync_front_porch);
lcd_ll_set_vertical_timing(rgb_panel->hal.dev, rgb_panel->timings.vsync_pulse_width,
rgb_panel->timings.vsync_back_porch, rgb_panel->timings.v_res,
@@ -1233,3 +1216,11 @@ IRAM_ATTR static void rgb_lcd_default_isr_handler(void *args)
portYIELD_FROM_ISR();
}
}
#if CONFIG_LCD_ENABLE_DEBUG_LOG
__attribute__((constructor))
static void rgb_lcd_override_default_log_level(void)
{
esp_log_level_set(TAG, ESP_LOG_VERBOSE);
}
#endif
@@ -139,8 +139,10 @@ typedef struct {
lcd_clock_source_t clk_src; /*!< Clock source for the RGB LCD peripheral */
esp_lcd_rgb_timing_t timings; /*!< RGB timing parameters, including the screen resolution */
size_t data_width; /*!< Number of data lines */
size_t bits_per_pixel; /*!< Frame buffer color depth, in bpp, specially, if set to zero, it will default to `data_width`.
When using a Serial RGB interface, this value could be different from `data_width` */
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 device can accept */
size_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 used. Maximum number of buffers are 3 */
size_t bounce_buffer_size_px; /*!< If it's non-zero, the driver allocates two DRAM bounce buffers for DMA use.
DMA fetching from DRAM bounce buffer is much faster than PSRAM frame buffer. */
@@ -250,38 +252,17 @@ esp_err_t esp_lcd_rgb_panel_get_frame_buffer(esp_lcd_panel_handle_t panel, uint3
*/
esp_err_t esp_lcd_rgb_panel_refresh(esp_lcd_panel_handle_t panel);
/**
* @brief LCD color conversion profile
*/
typedef struct {
lcd_color_space_t color_space; /*!< Color space of the image */
lcd_color_range_t color_range; /*!< Color range of the image */
lcd_yuv_sample_t yuv_sample; /*!< YUV sample format of the image */
} esp_lcd_color_conv_profile_t;
/**
* @brief Configuration of YUG-RGB conversion
*/
typedef struct {
lcd_yuv_conv_std_t std; /*!< YUV conversion standard: BT601, BT709 */
esp_lcd_color_conv_profile_t src; /*!< Color conversion profile of the input image */
esp_lcd_color_conv_profile_t dst; /*!< Color conversion profile of the output image */
} esp_lcd_yuv_conv_config_t;
/**
* @brief Configure how to convert the color format between RGB and YUV
*
* @note Pass in `config` as NULL will disable the RGB-YUV converter.
* @note The hardware converter can only parse a "packed" storage format, while "planar" and "semi-planar" format is not supported.
*
* @param[in] panel LCD panel handle, returned from `esp_lcd_new_rgb_panel`
* @param[in] config Configuration of RGB-YUV conversion
* @param[in] config Configuration of RGB-YUV conversion profile
* @return
* - ESP_ERR_INVALID_ARG: Configure RGB-YUV conversion failed because of invalid argument
* - ESP_ERR_NOT_SUPPORTED: Configure RGB-YUV conversion failed because the conversion mode is not supported by the hardware
* - ESP_OK: Configure RGB-YUV conversion successfully
*/
esp_err_t esp_lcd_rgb_panel_set_yuv_conversion(esp_lcd_panel_handle_t panel, const esp_lcd_yuv_conv_config_t *config);
esp_err_t esp_lcd_rgb_panel_set_yuv_conversion(esp_lcd_panel_handle_t panel, const esp_lcd_color_conv_yuv_config_t *config);
#endif // SOC_LCD_RGB_SUPPORTED
+1 -1
View File
@@ -101,7 +101,7 @@ static void async_memcpy_setup_dma2d_descriptor(esp_async_fbcpy_context_t* mcp_c
dma2d_descriptor_t* tx_desc = mcp_ctx->tx_desc;
dma2d_descriptor_t* rx_desc = mcp_ctx->rx_desc;
size_t dma_desc_size = mcp_ctx->dma_desc_size;
uint8_t dma2d_pbyte = dma2d_desc_pixel_format_to_pbyte_value(transaction->pixel_format_unique_id);
uint8_t dma2d_pbyte = dma2d_desc_pixel_format_to_pbyte_value_fourcc(transaction->pixel_format_fourcc_id);
tx_desc->buffer = (void*)transaction->src_buffer;
tx_desc->next = NULL;
@@ -14,9 +14,18 @@ target_add_binary_data(mipi_dsi_lcd_panel_test.elf "resources/pictures/world.gra
idf_build_get_property(elf EXECUTABLE)
if(CONFIG_COMPILER_DUMP_RTL_FILES)
# Collect RTL directories in a variable for readability. Join them
# with commas so they are passed as a single --rtl-dirs argument to the script.
set(LCD_RTL_DIRS
${CMAKE_BINARY_DIR}/esp-idf/esp_lcd
${CMAKE_BINARY_DIR}/esp-idf/hal
${CMAKE_BINARY_DIR}/esp-idf/esp_hal_lcd
)
string(JOIN "," LCD_RTL_DIRS_JOINED ${LCD_RTL_DIRS})
add_custom_target(check_test_app_sections ALL
COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py
--rtl-dirs ${CMAKE_BINARY_DIR}/esp-idf/esp_lcd/,${CMAKE_BINARY_DIR}/esp-idf/hal/
--rtl-dirs ${LCD_RTL_DIRS_JOINED}
--elf-file ${CMAKE_BINARY_DIR}/mipi_dsi_lcd_panel_test.elf
find-refs
--from-sections=.iram0.text
@@ -269,7 +269,7 @@ TEST_CASE("MIPI DSI draw YUV422 image (EK79007)", "[mipi_dsi]")
.virtual_channel = 0,
// YUV422 -> RGB888
.in_color_format = LCD_COLOR_FMT_YUV422,
.in_color_format = LCD_COLOR_FMT_YUV422_YUYV,
.out_color_format = LCD_COLOR_FMT_RGB888,
.video_timing = {
@@ -298,15 +298,12 @@ TEST_CASE("MIPI DSI draw YUV422 image (EK79007)", "[mipi_dsi]")
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 = {
esp_lcd_color_conv_yuv_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,
}
.conv_std = LCD_YUV_CONV_STD_BT601,
};
TEST_ESP_OK(esp_lcd_dpi_panel_set_color_conversion(mipi_dpi_panel, &convert_config));
TEST_ESP_OK(esp_lcd_dpi_panel_set_yuv_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));
@@ -12,9 +12,18 @@ target_add_binary_data(rgb_lcd_panel_test.elf "resources/pictures/world.yuv" BIN
idf_build_get_property(elf EXECUTABLE)
if(CONFIG_COMPILER_DUMP_RTL_FILES)
# Collect RTL directories in a variable for readability. Join them
# with commas so they are passed as a single --rtl-dirs argument to the script.
set(LCD_RTL_DIRS
${CMAKE_BINARY_DIR}/esp-idf/esp_lcd
${CMAKE_BINARY_DIR}/esp-idf/hal
${CMAKE_BINARY_DIR}/esp-idf/esp_hal_lcd
)
string(JOIN "," LCD_RTL_DIRS_JOINED ${LCD_RTL_DIRS})
add_custom_target(check_test_app_sections ALL
COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py
--rtl-dirs ${CMAKE_BINARY_DIR}/esp-idf/esp_lcd/,${CMAKE_BINARY_DIR}/esp-idf/hal/
--rtl-dirs ${LCD_RTL_DIRS_JOINED}
--elf-file ${CMAKE_BINARY_DIR}/rgb_lcd_panel_test.elf
find-refs
--from-sections=.iram0.text
@@ -25,15 +25,15 @@
#define TEST_IMG_SIZE (100 * 100 * sizeof(uint16_t))
static esp_lcd_panel_handle_t test_rgb_panel_initialization(size_t data_width, size_t bpp, size_t bb_pixels, bool refresh_on_demand,
static esp_lcd_panel_handle_t test_rgb_panel_initialization(size_t data_width, lcd_color_format_t in_color_format, size_t bb_pixels, bool refresh_on_demand,
esp_lcd_rgb_panel_vsync_cb_t vsync_cb, void *user_data)
{
esp_lcd_panel_handle_t panel_handle = NULL;
esp_lcd_rgb_panel_config_t panel_config = {
.data_width = data_width,
.in_color_format = in_color_format,
.dma_burst_size = 64,
.bounce_buffer_size_px = bb_pixels,
.bits_per_pixel = bpp,
.clk_src = LCD_CLK_SRC_DEFAULT,
.disp_gpio_num = TEST_LCD_DISP_EN_GPIO,
.pclk_gpio_num = TEST_LCD_PCLK_GPIO,
@@ -91,7 +91,7 @@ TEST_CASE("lcd_rgb_panel_stream_mode", "[lcd]")
TEST_ASSERT_NOT_NULL(img);
printf("initialize RGB panel with stream mode\r\n");
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, 16, 0, false, NULL, NULL);
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, false, NULL, NULL);
printf("flush random color block\r\n");
for (int i = 0; i < 200; i++) {
uint8_t color_byte = esp_random() & 0xFF;
@@ -113,7 +113,7 @@ TEST_CASE("lcd_rgb_panel_8bit_interface", "[lcd]")
printf("initialize RGB panel with stream mode\r\n");
// bpp for RGB888 is 24
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(8, 24, 0, false, NULL, NULL);
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(8, LCD_COLOR_FMT_RGB888, 0, false, NULL, NULL);
uint8_t color_byte = esp_random() & 0xFF;
printf("flush random color block 0x%x\r\n", color_byte);
int x_start = esp_random() % (TEST_LCD_H_RES - 100);
@@ -141,7 +141,7 @@ TEST_CASE("lcd_rgb_panel_refresh_on_demand", "[lcd]")
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
printf("initialize RGB panel with non-stream mode\r\n");
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, 16, 0, true, test_rgb_panel_trans_done, cur_task);
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, true, test_rgb_panel_trans_done, cur_task);
printf("flush random color block\r\n");
for (int i = 0; i < 200; i++) {
uint8_t color_byte = esp_random() & 0xFF;
@@ -166,7 +166,7 @@ TEST_CASE("lcd_rgb_panel_bounce_buffer", "[lcd]")
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
printf("initialize RGB panel with non-stream mode\r\n");
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, 16, 20 * TEST_LCD_H_RES, false, test_rgb_panel_trans_done, cur_task);
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 20 * TEST_LCD_H_RES, false, test_rgb_panel_trans_done, cur_task);
printf("flush random color block\r\n");
for (int i = 0; i < 200; i++) {
uint8_t color_byte = esp_random() & 0xFF;
@@ -189,7 +189,7 @@ TEST_CASE("lcd_rgb_panel_update_pclk", "[lcd]")
TEST_ASSERT_NOT_NULL(img);
printf("initialize RGB panel with stream mode\r\n");
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, 16, 0, false, NULL, NULL);
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, false, NULL, NULL);
printf("flush one clock block to the LCD\r\n");
uint8_t color_byte = esp_random() & 0xFF;
int x_start = esp_random() % (TEST_LCD_H_RES - 100);
@@ -217,7 +217,7 @@ TEST_CASE("lcd_rgb_panel_restart", "[lcd]")
TEST_ASSERT_NOT_NULL(img);
printf("initialize RGB panel with stream mode\r\n");
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, 16, 0, false, NULL, NULL);
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, false, NULL, NULL);
printf("flush one clock block to the LCD\r\n");
uint8_t color_byte = esp_random() & 0xFF;
int x_start = esp_random() % (TEST_LCD_H_RES - 100);
@@ -247,7 +247,7 @@ TEST_CASE("lcd_rgb_panel_rotate", "[lcd]")
memset(img, color_byte, w * h * sizeof(uint16_t));
printf("initialize RGB panel with stream mode\r\n");
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, 16, 0, false, NULL, NULL);
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, false, NULL, NULL);
printf("Update the rotation of panel\r\n");
for (size_t i = 0; i < 8; i++) {
@@ -291,7 +291,7 @@ TEST_CASE("lcd_rgb_panel_iram_safe", "[lcd]")
uint32_t callback_calls = 0;
printf("initialize RGB panel with stream mode\r\n");
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, 16, 0, false, test_rgb_panel_count_in_callback, &callback_calls);
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, false, test_rgb_panel_count_in_callback, &callback_calls);
printf("flush one clock block to the LCD\r\n");
uint8_t color_byte = esp_random() & 0xFF;
int x_start = esp_random() % (TEST_LCD_H_RES - 100);
@@ -28,7 +28,8 @@ TEST_CASE("lcd_rgb_panel_yuv422_conversion", "[lcd]")
esp_lcd_rgb_panel_config_t panel_config = {
.data_width = 16,
.dma_burst_size = 64,
.bits_per_pixel = 16, // YUV422: 16bits per pixel
.in_color_format = LCD_COLOR_FMT_YUV422_UYVY,
.out_color_format = LCD_COLOR_FMT_RGB565,
.clk_src = LCD_CLK_SRC_DEFAULT,
.disp_gpio_num = TEST_LCD_DISP_EN_GPIO,
.pclk_gpio_num = TEST_LCD_PCLK_GPIO,
@@ -72,21 +73,11 @@ TEST_CASE("lcd_rgb_panel_yuv422_conversion", "[lcd]")
TEST_ESP_OK(esp_lcd_panel_reset(panel_handle));
printf("Set YUV-RGB conversion profile\r\n");
esp_lcd_yuv_conv_config_t conv_config = {
.std = LCD_YUV_CONV_STD_BT601,
.src = {
.color_range = LCD_COLOR_RANGE_FULL,
.color_space = LCD_COLOR_SPACE_RGB,
},
.dst = {
.color_range = LCD_COLOR_RANGE_FULL,
.color_space = LCD_COLOR_SPACE_RGB,
},
esp_lcd_color_conv_yuv_config_t conv_config = {
.conv_std = LCD_YUV_CONV_STD_BT601,
.in_color_range = LCD_COLOR_RANGE_FULL,
.out_color_range = LCD_COLOR_RANGE_FULL,
};
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_lcd_rgb_panel_set_yuv_conversion(panel_handle, &conv_config));
conv_config.src.color_space = LCD_COLOR_SPACE_YUV;
conv_config.src.yuv_sample = LCD_YUV_SAMPLE_422;
TEST_ESP_OK(esp_lcd_rgb_panel_set_yuv_conversion(panel_handle, &conv_config));
TEST_ESP_OK(esp_lcd_panel_init(panel_handle));
+3
View File
@@ -50,7 +50,10 @@ uint32_t color_hal_pixel_format_fourcc_get_bit_depth(uint32_t four_character_cod
return 8;
case ESP_COLOR_FOURCC_OUYY_EVYY:
return 12;
case ESP_COLOR_FOURCC_YUYV:
case ESP_COLOR_FOURCC_UYVY:
case ESP_COLOR_FOURCC_YVYU:
case ESP_COLOR_FOURCC_VYUY:
case ESP_COLOR_FOURCC_RGB16_BE:
return 16;
case ESP_COLOR_FOURCC_RGB24:
+34 -7
View File
@@ -26,7 +26,7 @@ extern "C" {
* Byte 1: | G7 - G0 |
* Byte 0: | R7 - R0 |
*/
#define ESP_COLOR_FOURCC_RGB24 ESP_COLOR_FOURCC('R', 'G', 'B', '3') /* 24 bpp RGB-8-8-8 */
#define ESP_COLOR_FOURCC_RGB24 ESP_COLOR_FOURCC('R', 'G', 'B', '3') /* 24 bpp RGB-8-8-8 */
/**
* RGB565_BE
@@ -35,7 +35,7 @@ extern "C" {
* Byte 1: | G2 G1 G0 | B4 B3 B2 B1 B0 |
* Byte 0: | R4 R3 R2 R1 R0 | G5 G4 G3 |
*/
#define ESP_COLOR_FOURCC_RGB16_BE ESP_COLOR_FOURCC('R', 'G', 'B', 'B') /* 16 bpp RGB-5-6-5, big endian */
#define ESP_COLOR_FOURCC_RGB16_BE ESP_COLOR_FOURCC('R', 'G', 'B', 'B') /* 16 bpp RGB-5-6-5, big endian */
/**
* Grey8
@@ -43,7 +43,7 @@ extern "C" {
* | bit7 - bit0 |
* Byte 0: | G7 - G0 |
*/
#define ESP_COLOR_FOURCC_GREY ESP_COLOR_FOURCC('G', 'R', 'E', 'Y') /* 8 bpp Greyscale */
#define ESP_COLOR_FOURCC_GREY ESP_COLOR_FOURCC('G', 'R', 'E', 'Y') /* 8 bpp Greyscale */
/**
* YUV444
@@ -52,7 +52,16 @@ extern "C" {
* |Y0|U0|V0| |Y1|U1|V1|
* +--+--+--+ +--+--+--+
*/
#define ESP_COLOR_FOURCC_YUV ESP_COLOR_FOURCC('V', '3', '0', '8') /* 24 bpp, Y-U-V 4:4:4 */
#define ESP_COLOR_FOURCC_YUV ESP_COLOR_FOURCC('V', '3', '0', '8') /* 24 bpp, Y-U-V 4:4:4 */
/**
* YUYV422
* Memory Layout:
* +--+--+--+--+ +--+--+--+--+
* |Y0|U0|Y1|V0| |Y2|U2|Y3|V2|
* +--+--+--+--+ +--+--+--+--+
*/
#define ESP_COLOR_FOURCC_YUYV ESP_COLOR_FOURCC('Y', 'U', 'Y', 'V') /* 16 bpp, YUYV 4:2:2 */
/**
* YVYU422
@@ -61,7 +70,25 @@ extern "C" {
* |Y0|V0|Y1|U0| |Y2|V2|Y3|U2|
* +--+--+--+--+ +--+--+--+--+
*/
#define ESP_COLOR_FOURCC_YVYU ESP_COLOR_FOURCC('Y', 'V', 'Y', 'U') /* 16 bpp, YVYU 4:2:2 */
#define ESP_COLOR_FOURCC_YVYU ESP_COLOR_FOURCC('Y', 'V', 'Y', 'U') /* 16 bpp, YVYU 4:2:2 */
/**
* UYVY422
* Memory Layout:
* +--+--+--+--+ +--+--+--+--+
* |U0|Y0|V0|Y1| |U2|Y2|V2|Y3|
* +--+--+--+--+ +--+--+--+--+
*/
#define ESP_COLOR_FOURCC_UYVY ESP_COLOR_FOURCC('U', 'Y', 'V', 'Y') /* 16 bpp, UYVY 4:2:2 */
/**
* VYUY422
* Memory Layout:
* +--+--+--+--+ +--+--+--+--+
* |V0|Y0|U0|Y1| |V2|Y2|U2|Y3|
* +--+--+--+--+ +--+--+--+--+
*/
#define ESP_COLOR_FOURCC_VYUY ESP_COLOR_FOURCC('V', 'Y', 'U', 'Y') /* 16 bpp, VYUY 4:2:2 */
/**
* Espressif YUV420, U00 V10 shared Y00 Y01 Y10 Y11, U02 V12 shared Y02 Y03 Y12 Y13
@@ -72,7 +99,7 @@ extern "C" {
* Line2 |V10|Y10|Y11| |V12|Y12|Y13|
* +---+---+---+ +---+---+---+
*/
#define ESP_COLOR_FOURCC_OUYY_EVYY ESP_COLOR_FOURCC('O', 'U', 'E', 'V') /* 12 bpp, Espressif Y-U-V 4:2:0 */
#define ESP_COLOR_FOURCC_OUYY_EVYY ESP_COLOR_FOURCC('O', 'U', 'E', 'V') /* 12 bpp, Espressif Y-U-V 4:2:0 */
/*---------------------------------------------------------------
@@ -215,7 +242,7 @@ typedef enum {
*
* @note Save enum 0 for special purpose
*/
typedef enum {
typedef enum {
COLOR_SPACE_RAW = 1, ///< Color space raw
COLOR_SPACE_RGB, ///< Color space rgb
COLOR_SPACE_YUV, ///< Color space yuv
@@ -255,7 +255,10 @@ LCD
- The ``esp_lcd_panel_disp_off`` function has been removed. Please use the :func:`esp_lcd_panel_disp_on_off` function to control display on/off.
- The ``on_bounce_frame_finish`` member in :cpp:type:`esp_lcd_rgb_panel_event_callbacks_t` has been replaced by :cpp:member:`esp_lcd_rgb_panel_event_callbacks_t::on_frame_buf_complete`, which indicates that a complete frame buffer has been sent to the LCD controller.
- The LCD IO layer driver for the I2C interface previously had two implementations, based on the new and legacy I2C master bus drivers. As the legacy I2C driver is being deprecated, support for it in the LCD IO layer has been removed. Only the APIs provided in ``driver/i2c_master.h`` are now used.
- :cpp:member:`esp_lcd_dpi_panel_config_t::pixel_format` member is deprecated. It is recommended to only use :cpp:member:`esp_lcd_dpi_panel_config_t::in_color_format` to set the MIPI DSI driver's input pixel data format.
- ``pixel_format`` member in the :cpp:type:`esp_lcd_dpi_panel_config_t` structure has been removed. It is recommended to only use :cpp:member:`esp_lcd_dpi_panel_config_t::in_color_format` to set the MIPI DSI driver's input pixel data format.
- ``bits_per_pixel`` member in the :cpp:type:`esp_lcd_rgb_panel_config_t` structure has been removed. The color depth of the internal framebuffer is now determined by the :cpp:member:`esp_lcd_rgb_panel_config_t::in_color_format` member.
- ``esp_lcd_dpi_panel_set_color_conversion`` function is replaced by :cpp:func:`esp_lcd_dpi_panel_set_yuv_conversion` to set YUV to RGB color conversion profile.
- :cpp:func:`esp_lcd_rgb_panel_set_yuv_conversion` function has a different signature. The ``esp_lcd_yuv_conv_config_t`` configuration type is now replaced by :cpp:type:`esp_lcd_color_conv_yuv_config_t`.
- The NT35510 LCD device driver has been moved out of ESP-IDF and is now hosted in the `ESP Component Registry <https://components.espressif.com/components/espressif/esp_lcd_nt35510/versions/1.0.0/readme>`__. If your project uses the NT35510 driver, you can add it to your project by running ``idf.py add-dependency "espressif/esp_lcd_nt35510"``.
SPI
@@ -255,7 +255,10 @@ LCD
- ``esp_lcd_panel_disp_off`` 函数已被移除。请使用 :func:`esp_lcd_panel_disp_on_off` 函数来控制显示内容的开关。
- :cpp:type:`esp_lcd_rgb_panel_event_callbacks_t` 中的 ``on_bounce_frame_finish`` 成员已被 :cpp:member:`esp_lcd_rgb_panel_event_callbacks_t::on_frame_buf_complete` 成员取代,用于指示一个完整的帧缓冲区已被发送给 LCD 控制器。
- I2C 接口的 LCD IO 层驱动有两套实现,分别基于新、旧 I2C Master 总线驱动。由于旧版的 I2C Master 驱动逐渐被弃用,遂 LCD 的 IO 层也移除对旧版的支持,只使用 ``driver/i2c_master.h`` 中提供的 API。
- :cpp:member:`esp_lcd_dpi_panel_config_t::pixel_format` 成员已经被废弃。建议仅使用 :cpp:member:`esp_lcd_dpi_panel_config_t::in_color_format` 来设定 MIPI DSI 驱动输入的像素数据格式。
- :cpp:type:`esp_lcd_dpi_panel_config_t` 结构体中的 ``pixel_format`` 成员已经被删除。建议仅使用 :cpp:member:`esp_lcd_dpi_panel_config_t::in_color_format` 来设定 MIPI DSI 驱动输入的像素数据格式。
- :cpp:type:`esp_lcd_rgb_panel_config_t` 结构体中的 ``bits_per_pixel`` 成员已经被删除。内部帧缓冲区的色彩深度现在由 :cpp:member:`esp_lcd_rgb_panel_config_t::in_color_format` 成员决定。
- ``esp_lcd_dpi_panel_set_color_conversion`` 函数已被 :cpp:func:`esp_lcd_dpi_panel_set_yuv_conversion` 取代,用于设置 YUV 到 RGB 的色彩转换配置。
- :cpp:func:`esp_lcd_rgb_panel_set_yuv_conversion` 函数的签名已改变。原先使用的 ``esp_lcd_yuv_conv_config_t`` 配置类型现已被 :cpp:type:`esp_lcd_color_conv_yuv_config_t` 取代。
- NT35510 LCD 设备驱动已经从 ESP-IDF 中移动到外部仓库,并且托管在了 `ESP Component Registry <https://components.espressif.com/components/espressif/esp_lcd_nt35510/versions/1.0.0/readme>`__ 上。如果你的项目使用到了 NT35510 驱动,你可以通过运行 ``idf.py add-dependency "espressif/esp_lcd_nt35510"`` 将它添加到你的项目中。
SPI