mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
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:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
@@ -581,9 +559,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");
|
||||
}
|
||||
@@ -591,22 +567,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
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
@@ -72,7 +74,7 @@
|
||||
|
||||
#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;
|
||||
|
||||
@@ -98,11 +100,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
|
||||
@@ -288,9 +291,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");
|
||||
@@ -317,13 +317,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 <= ESP_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;
|
||||
@@ -343,6 +353,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);
|
||||
@@ -359,26 +371,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;
|
||||
@@ -402,7 +415,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
|
||||
@@ -522,53 +534,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;
|
||||
}
|
||||
|
||||
@@ -619,6 +599,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
|
||||
@@ -628,8 +610,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,
|
||||
@@ -1283,3 +1266,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
|
||||
|
||||
@@ -142,8 +142,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 */
|
||||
void *user_fbs[ESP_RGB_LCD_PANEL_MAX_FB_NUM]; /*!< Array of user-provided frame buffers. If not NULL, the driver will use these buffers instead of allocating its own */
|
||||
size_t bounce_buffer_size_px; /*!< If it's non-zero, the driver allocates two DRAM bounce buffers for DMA use.
|
||||
@@ -266,38 +268,17 @@ esp_err_t esp_lcd_rgb_panel_refresh(esp_lcd_panel_handle_t panel);
|
||||
*/
|
||||
void *esp_lcd_rgb_alloc_draw_buffer(esp_lcd_panel_handle_t panel, size_t size, uint32_t caps);
|
||||
|
||||
/**
|
||||
* @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
|
||||
|
||||
|
||||
@@ -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, bool user_fb,
|
||||
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, bool user_fb,
|
||||
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,
|
||||
@@ -97,7 +97,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, false, NULL, NULL);
|
||||
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, false, false, NULL, NULL);
|
||||
printf("flush random color block\r\n");
|
||||
for (int i = 0; i < 200; i++) {
|
||||
uint8_t color_byte = esp_random() & 0xFF;
|
||||
@@ -119,7 +119,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, false, NULL, NULL);
|
||||
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(8, LCD_COLOR_FMT_RGB888, 0, false, 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);
|
||||
@@ -147,7 +147,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, false, 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, 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;
|
||||
@@ -172,7 +172,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, 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, 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;
|
||||
@@ -195,7 +195,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, false, NULL, NULL);
|
||||
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, false, 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);
|
||||
@@ -223,7 +223,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, false, NULL, NULL);
|
||||
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, false, 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);
|
||||
@@ -253,7 +253,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, false, NULL, NULL);
|
||||
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, false, false, NULL, NULL);
|
||||
|
||||
printf("Update the rotation of panel\r\n");
|
||||
for (size_t i = 0; i < 8; i++) {
|
||||
@@ -278,7 +278,7 @@ TEST_CASE("lcd_rgb_panel_user_frame_buffer", "[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, true, NULL, NULL);
|
||||
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, false, true, NULL, NULL);
|
||||
|
||||
printf("flush one clock block to the LCD\r\n");
|
||||
uint8_t color_byte = esp_random() & 0xFF;
|
||||
@@ -325,7 +325,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, 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, 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));
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user