feat(st7789): add data endian config

Closes https://github.com/espressif/esp-idf/issues/11416
This commit is contained in:
Planck (Lu Zeyu) 2023-08-22 17:54:09 +08:00 committed by morris
parent 8ff8486735
commit 9d535c05f7
13 changed files with 64 additions and 32 deletions

View File

@ -19,9 +19,11 @@ extern "C" {
typedef struct {
int reset_gpio_num; /*!< GPIO used to reset the LCD panel, set to -1 if it's not used */
union {
lcd_color_rgb_endian_t color_space; /*!< @deprecated Set RGB color space, please use rgb_endian instead */
lcd_color_rgb_endian_t rgb_endian; /*!< Set RGB data endian: RGB or BGR */
lcd_rgb_element_order_t color_space; /*!< @deprecated Set RGB color space, please use rgb_ele_order instead */
lcd_rgb_element_order_t rgb_endian; /*!< @deprecated Set RGB data endian, please use rgb_ele_order instead */
lcd_rgb_element_order_t rgb_ele_order; /*!< Set RGB element order, RGB or BGR */
};
lcd_rgb_data_endian_t data_endian; /*!< Set the data endian for color data larger than 1 byte */
unsigned int bits_per_pixel; /*!< Color depth, in bpp */
struct {
unsigned int reset_active_high: 1; /*!< Setting this if the panel reset is high level active */

View File

@ -28,8 +28,8 @@ typedef enum {
} esp_lcd_color_space_t __attribute__((deprecated));
// Ensure binary compatibility with lcd_color_rgb_endian_t
ESP_STATIC_ASSERT((lcd_color_rgb_endian_t)ESP_LCD_COLOR_SPACE_RGB == LCD_RGB_ENDIAN_RGB, "ESP_LCD_COLOR_SPACE_RGB is not compatible with LCD_RGB_ENDIAN_RGB");
ESP_STATIC_ASSERT((lcd_color_rgb_endian_t)ESP_LCD_COLOR_SPACE_BGR == LCD_RGB_ENDIAN_BGR, "ESP_LCD_COLOR_SPACE_BGR is not compatible with LCD_RGB_ENDIAN_BGR");
ESP_STATIC_ASSERT((lcd_rgb_element_order_t)ESP_LCD_COLOR_SPACE_RGB == LCD_RGB_ELEMENT_ORDER_RGB, "ESP_LCD_COLOR_SPACE_RGB is not compatible with LCD_RGB_ORDER_RGB");
ESP_STATIC_ASSERT((lcd_rgb_element_order_t)ESP_LCD_COLOR_SPACE_BGR == LCD_RGB_ELEMENT_ORDER_BGR, "ESP_LCD_COLOR_SPACE_BGR is not compatible with LCD_RGB_ORDER_BGR");
/** @endcond */
#ifdef __cplusplus

View File

@ -66,11 +66,11 @@ esp_err_t esp_lcd_new_panel_nt35510(const esp_lcd_panel_io_handle_t io, const es
ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed");
}
switch (panel_dev_config->rgb_endian) {
case LCD_RGB_ENDIAN_RGB:
switch (panel_dev_config->rgb_ele_order) {
case LCD_RGB_ELEMENT_ORDER_RGB:
nt35510->madctl_val = 0;
break;
case LCD_RGB_ENDIAN_BGR:
case LCD_RGB_ELEMENT_ORDER_BGR:
nt35510->madctl_val |= LCD_CMD_BGR_BIT;
break;
default:

View File

@ -23,6 +23,9 @@
#include "esp_log.h"
#include "esp_check.h"
#define ST7789_CMD_RAMCTRL 0xb0
#define ST7789_DATA_LITTLE_ENDIAN_BIT (1 << 3)
static const char *TAG = "lcd_panel.st7789";
static esp_err_t panel_st7789_del(esp_lcd_panel_t *panel);
@ -45,6 +48,8 @@ typedef struct {
uint8_t fb_bits_per_pixel;
uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register
uint8_t colmod_cal; // save surrent value of LCD_CMD_COLMOD register
uint8_t ramctl_val_1;
uint8_t ramctl_val_2;
} st7789_panel_t;
esp_err_t esp_lcd_new_panel_st7789(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel)
@ -94,6 +99,13 @@ esp_err_t esp_lcd_new_panel_st7789(const esp_lcd_panel_io_handle_t io, const esp
break;
}
st7789->ramctl_val_1 = 0x00;
st7789->ramctl_val_2 = 0xf0; // Use big endian by default
if ((panel_dev_config->data_endian) == LCD_RGB_DATA_ENDIAN_LITTLE) {
// Use little endian
st7789->ramctl_val_2 |= ST7789_DATA_LITTLE_ENDIAN_BIT;
}
st7789->io = io;
st7789->fb_bits_per_pixel = fb_bits_per_pixel;
st7789->reset_gpio_num = panel_dev_config->reset_gpio_num;
@ -166,6 +178,9 @@ static esp_err_t panel_st7789_init(esp_lcd_panel_t *panel)
esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD, (uint8_t[]) {
st7789->colmod_cal,
}, 1);
esp_lcd_panel_io_tx_param(io, ST7789_CMD_RAMCTRL, (uint8_t[]) {
st7789->ramctl_val_1, st7789->ramctl_val_2
}, 2);
return ESP_OK;
}

View File

@ -300,7 +300,7 @@ TEST_CASE("lcd_panel_i80_io_test", "[lcd]")
esp_lcd_panel_handle_t panel_handle = NULL;
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = TEST_LCD_RST_GPIO,
.rgb_endian = LCD_RGB_ENDIAN_RGB,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
};
@ -420,7 +420,7 @@ TEST_CASE("lcd_panel_with_i80_interface_(st7789, 8bits)", "[lcd]")
esp_lcd_panel_handle_t panel_handle = NULL;
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = TEST_LCD_RST_GPIO,
.rgb_endian = LCD_RGB_ENDIAN_RGB,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
};
TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
@ -509,7 +509,7 @@ TEST_CASE("i80_lcd_send_colors_to_fixed_region", "[lcd]")
esp_lcd_panel_handle_t panel_handle = NULL;
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = TEST_LCD_RST_GPIO,
.rgb_endian = LCD_RGB_ENDIAN_RGB,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
};
TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));

View File

@ -157,7 +157,7 @@ TEST_CASE("lcd_panel_with_8-line_spi_interface_(st7789)", "[lcd]")
test_spi_lcd_common_initialize(&io_handle, NULL, NULL, 8, 8, true);
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = TEST_LCD_RST_GPIO,
.rgb_endian = LCD_RGB_ENDIAN_RGB,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
};
TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
@ -171,7 +171,7 @@ TEST_CASE("lcd_panel_with_8-line_spi_interface_(nt35510)", "[lcd]")
test_spi_lcd_common_initialize(&io_handle, NULL, NULL, 16, 16, true);
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = TEST_LCD_RST_GPIO,
.rgb_endian = LCD_RGB_ENDIAN_RGB,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
};
TEST_ESP_OK(esp_lcd_new_panel_nt35510(io_handle, &panel_config, &panel_handle));
@ -186,7 +186,7 @@ TEST_CASE("lcd_panel_with_1-line_spi_interface_(st7789)", "[lcd]")
test_spi_lcd_common_initialize(&io_handle, NULL, NULL, 8, 8, false);
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = TEST_LCD_RST_GPIO,
.rgb_endian = LCD_RGB_ENDIAN_RGB,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
};
TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
@ -212,7 +212,7 @@ TEST_CASE("spi_lcd_send_colors_to_fixed_region", "[lcd]")
// we don't use the panel handle in this test, creating the panel just for a quick initialization
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = TEST_LCD_RST_GPIO,
.rgb_endian = LCD_RGB_ENDIAN_RGB,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
};
TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));

View File

@ -24,9 +24,22 @@ typedef soc_periph_lcd_clk_src_t lcd_clock_source_t;
* @brief RGB color endian
*/
typedef enum {
LCD_RGB_ENDIAN_RGB, /*!< RGB data endian: RGB */
LCD_RGB_ENDIAN_BGR, /*!< RGB data endian: BGR */
} lcd_color_rgb_endian_t;
LCD_RGB_ELEMENT_ORDER_RGB, /*!< RGB element order: RGB */
LCD_RGB_ELEMENT_ORDER_BGR, /*!< RGB element order: BGR */
} lcd_rgb_element_order_t;
/// for backward compatible
typedef lcd_rgb_element_order_t lcd_color_rgb_endian_t;
#define LCD_RGB_ENDIAN_RGB LCD_RGB_ELEMENT_ORDER_RGB
#define LCD_RGB_ENDIAN_BGR LCD_RGB_ELEMENT_ORDER_BGR
/**
* @brief RGB data endian
*/
typedef enum {
LCD_RGB_DATA_ENDIAN_BIG = 0, /*!< RGB data endian: MSB first */
LCD_RGB_DATA_ENDIAN_LITTLE, /*!< RGB data endian: LSB first */
} lcd_rgb_data_endian_t;
/**
* @brief LCD color space

View File

@ -66,15 +66,16 @@ SPI Interfaced LCD
#. Install the LCD controller driver. The LCD controller driver is responsible for sending the commands and parameters to the LCD controller chip. In this step, you need to specify the SPI IO device handle that allocated in the last step, and some panel specific configurations:
- :cpp:member:`esp_lcd_panel_dev_config_t::reset_gpio_num` sets the LCD's hardware reset GPIO number. If the LCD does not have a hardware reset pin, set this to ``-1``.
- :cpp:member:`esp_lcd_panel_dev_config_t::rgb_endian` sets the endian of the RGB color data.
- :cpp:member:`esp_lcd_panel_dev_config_t::bits_per_pixel` sets the bit width of the pixel color data. The LCD driver will use this value to calculate the number of bytes to send to the LCD controller chip.
- :cpp:member:`esp_lcd_panel_dev_config_t::rgb_ele_order` sets the R-G-B element order of each color data.
- :cpp:member:`esp_lcd_panel_dev_config_t::bits_per_pixel` sets the bit width of the pixel color data. The LCD driver uses this value to calculate the number of bytes to send to the LCD controller chip.
- :cpp:member:`esp_lcd_panel_dev_config_t::data_endian` specifies the data endian to be transmitted to the screen. No need to specify for color data within 1 byte, like RGB232. For drivers that do not support specifying data endian, this field would be ignored.
.. code-block:: c
esp_lcd_panel_handle_t panel_handle = NULL;
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = EXAMPLE_PIN_NUM_RST,
.rgb_endian = LCD_RGB_ENDIAN_BGR,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR,
.bits_per_pixel = 16,
};
// Create LCD panel handle for ST7789, with the SPI IO device handle
@ -200,13 +201,13 @@ I2C Interfaced LCD
- :cpp:member:`esp_lcd_panel_dev_config_t::bits_per_pixel` sets the bit width of the pixel color data. The LCD driver will use this value to calculate the number of bytes to send to the LCD controller chip.
- :cpp:member:`esp_lcd_panel_dev_config_t::reset_gpio_num` sets the GPIO number of the reset pin. If the LCD controller chip does not have a reset pin, you can set this value to ``-1``.
- :cpp:member:`esp_lcd_panel_dev_config_t::rgb_endian` sets the endian of the pixel color data.
- :cpp:member:`esp_lcd_panel_dev_config_t::rgb_ele_order` sets the color order the pixel color data.
.. code-block:: c
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = EXAMPLE_PIN_NUM_RST,
.rgb_endian = LCD_RGB_ENDIAN_RGB,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));

View File

@ -373,8 +373,8 @@ LCD
- ``dc_as_cmd_phase`` is removed. The SPI LCD driver currently doesn't support a 9-bit SPI LCD. Please always use a dedicated GPIO to control the LCD D/C line.
- The way to register RGB panel event callbacks has been moved from the :cpp:type:`esp_lcd_rgb_panel_config_t` into a separate API :cpp:func:`esp_lcd_rgb_panel_register_event_callbacks`. However, the event callback signature is not changed.
- Previous ``relax_on_idle`` flag in :cpp:type:`esp_lcd_rgb_panel_config_t` has been renamed into :cpp:member:`esp_lcd_rgb_panel_config_t::refresh_on_demand`, which expresses the same meaning but with a clear name.
- If the RGB LCD is created with the ``refresh_on_demand`` flag enabled, the driver won't start a refresh in the :cpp:func:`esp_lcd_panel_draw_bitmap`. Now users have to call :cpp:func:`esp_lcd_rgb_panel_refresh` to refresh the screen by themselves.
- :cpp:type:`esp_lcd_color_space_t` is deprecated, please use :cpp:type:`lcd_color_space_t` to describe the color space, and use :cpp:type:`lcd_color_rgb_endian_t` to describe the data order of RGB color.
- If the RGB LCD is created with the ``refresh_on_demand`` flag enabled, the driver will not start a refresh in the :cpp:func:`esp_lcd_panel_draw_bitmap`. Now users have to call :cpp:func:`esp_lcd_rgb_panel_refresh` to refresh the screen by themselves.
- :cpp:type:`esp_lcd_color_space_t` is deprecated, please use :cpp:type:`lcd_color_space_t` to describe the color space, and use :cpp:type:`lcd_rgb_element_order_t` to describe the data order of RGB color.
.. only:: SOC_MCPWM_SUPPORTED

View File

@ -374,7 +374,7 @@ LCD
- 更新后,用于注册 RGB 面板的事件回调函数已从 :cpp:type:`esp_lcd_rgb_panel_config_t` 更新为单独的 API :cpp:func:`esp_lcd_rgb_panel_register_event_callbacks`。但是,事件回调签名仍保持不变。
- 更新后, :cpp:type:`esp_lcd_rgb_panel_config_t` 中的标志位 ``relax_on_idle`` 被重命名为 :cpp:member:`esp_lcd_rgb_panel_config_t::refresh_on_demand`,后者虽表达了同样的含义,但是其命名更有意义。
- 更新后,如果创建 RGB LCD 时,标志位 ``refresh_on_demand`` 使能,驱动不会在 :cpp:func:`esp_lcd_panel_draw_bitmap` 中进行刷新,用户需要调用 :cpp:func:`esp_lcd_rgb_panel_refresh` 来刷新屏幕。
- 更新后,:cpp:type:`esp_lcd_color_space_t` 已被弃用,请使用 :cpp:type:`lcd_color_space_t` 来描述色彩空间,使用 :cpp:type:`lcd_color_rgb_endian_t` 来描述 RGB 颜色的排列顺序。
- 更新后,:cpp:type:`esp_lcd_color_space_t` 已被弃用,请使用 :cpp:type:`lcd_color_space_t` 来描述色彩空间,使用 :cpp:type:`lcd_rgb_element_order_t` 来描述 RGB 颜色的排列顺序。
.. only:: SOC_MCPWM_SUPPORTED

View File

@ -211,7 +211,7 @@ void app_main(void)
ESP_LOGI(TAG, "Install LCD driver of st7789");
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = EXAMPLE_PIN_NUM_RST,
.rgb_endian = LCD_RGB_ENDIAN_RGB,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
@ -226,7 +226,7 @@ void app_main(void)
ESP_LOGI(TAG, "Install LCD driver of nt35510");
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = EXAMPLE_PIN_NUM_RST,
.rgb_endian = LCD_RGB_ENDIAN_BGR,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR,
.bits_per_pixel = 16,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_nt35510(io_handle, &panel_config, &panel_handle));
@ -244,7 +244,7 @@ void app_main(void)
ESP_LOGI(TAG, "Install LCD driver of ili9341 (st7789 compatible)");
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = EXAMPLE_PIN_NUM_RST,
.rgb_endian = LCD_RGB_ENDIAN_BGR,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR,
.bits_per_pixel = 16,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));

View File

@ -206,7 +206,7 @@ void app_main(void)
esp_lcd_panel_handle_t panel_handle = NULL;
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = EXAMPLE_PIN_NUM_LCD_RST,
.rgb_endian = LCD_RGB_ENDIAN_BGR,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR,
.bits_per_pixel = 16,
};
#if CONFIG_EXAMPLE_LCD_CONTROLLER_ILI9341

View File

@ -130,7 +130,7 @@ void app_main(void)
esp_lcd_panel_handle_t panel_handle = NULL;
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = EXAMPLE_PIN_NUM_RST,
.rgb_endian = LCD_RGB_ENDIAN_BGR,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
};
// Initialize the LCD configuration
@ -148,6 +148,7 @@ void app_main(void)
// Turn on the screen
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_handle, true));
// Swap x and y axis (Different LCD screens may need different options)
ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, true));