From e73d8166aa192495fc5be07a5e0cf7115d7deb22 Mon Sep 17 00:00:00 2001 From: morris Date: Mon, 3 Apr 2023 14:08:59 +0800 Subject: [PATCH] i80_lcd: support skip command phase Closes https://github.com/espressif/esp-idf/issues/10794 --- .../esp_lcd/include/esp_lcd_panel_commands.h | 8 +-- components/esp_lcd/include/esp_lcd_panel_io.h | 4 +- components/esp_lcd/src/esp_lcd_panel_io_i80.c | 13 +++-- .../i80_lcd/main/test_i80_lcd_panel.c | 53 +++++++++++++++++++ .../lcd/i80_controller/main/Kconfig.projbuild | 2 +- .../i80_controller/sdkconfig.defaults.esp32s3 | 7 ++- 6 files changed, 75 insertions(+), 12 deletions(-) diff --git a/components/esp_lcd/include/esp_lcd_panel_commands.h b/components/esp_lcd/include/esp_lcd_panel_commands.h index 091ef1cffef..5917c3e8774 100644 --- a/components/esp_lcd/include/esp_lcd_panel_commands.h +++ b/components/esp_lcd/include/esp_lcd_panel_commands.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -31,7 +31,7 @@ #define LCD_CMD_RAMRD 0x2E // Read frame memory #define LCD_CMD_PTLAR 0x30 // Define the partial area #define LCD_CMD_VSCRDEF 0x33 // Vertical scrolling definition -#define LCD_CMD_TEOFF 0x34 // Turns of tearing effect +#define LCD_CMD_TEOFF 0x34 // Turns off tearing effect #define LCD_CMD_TEON 0x35 // Turns on tearing effect #define LCD_CMD_MADCTL 0x36 // Memory data access control @@ -48,7 +48,7 @@ #define LCD_CMD_COLMOD 0x3A // Defines the format of RGB picture data #define LCD_CMD_RAMWRC 0x3C // Memory write continue #define LCD_CMD_RAMRDC 0x3E // Memory read continue -#define LCD_CMD_STE 0x44 // Set tear scanline, tearing effect output signal when display module reaches line N -#define LCD_CMD_GDCAN 0x45 // Get scanline +#define LCD_CMD_STE 0x44 // Set tear scan line, tearing effect output signal when display module reaches line N +#define LCD_CMD_GDCAN 0x45 // Get scan line #define LCD_CMD_WRDISBV 0x51 // Write display brightness #define LCD_CMD_RDDISBV 0x52 // Read display brightness value diff --git a/components/esp_lcd/include/esp_lcd_panel_io.h b/components/esp_lcd/include/esp_lcd_panel_io.h index c01fe3e441f..de7b434b5f8 100644 --- a/components/esp_lcd/include/esp_lcd_panel_io.h +++ b/components/esp_lcd/include/esp_lcd_panel_io.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -71,7 +71,7 @@ esp_err_t esp_lcd_panel_io_rx_param(esp_lcd_panel_io_handle_t io, int lcd_cmd, v * this function will wait until they are finished and the queue is empty before sending the command(s). * * @param[in] io LCD panel IO handle, which is created by other factory API like `esp_lcd_new_panel_io_spi()` - * @param[in] lcd_cmd The specific LCD command (set to -1 if no command needed - only in SPI and I2C) + * @param[in] lcd_cmd The specific LCD command, set to -1 if no command needed * @param[in] param Buffer that holds the command specific parameters, set to NULL if no parameter is needed for the command * @param[in] param_size Size of `param` in memory, in bytes, set to zero if no parameter is needed for the command * @return diff --git a/components/esp_lcd/src/esp_lcd_panel_io_i80.c b/components/esp_lcd/src/esp_lcd_panel_io_i80.c index fb6f3ce284a..712dfd40b36 100644 --- a/components/esp_lcd/src/esp_lcd_panel_io_i80.c +++ b/components/esp_lcd/src/esp_lcd_panel_io_i80.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -578,9 +578,16 @@ static void lcd_periph_trigger_quick_trans_done_event(esp_lcd_i80_bus_handle_t b static void lcd_start_transaction(esp_lcd_i80_bus_t *bus, lcd_i80_trans_descriptor_t *trans_desc) { // by default, the dummy phase is disabled because it's not common for most LCDs + uint32_t dummy_cycles = 0; + uint32_t cmd_cycles = trans_desc->cmd_value >= 0 ? trans_desc->cmd_cycles : 0; // Number of data phase cycles are controlled by DMA buffer length, we only need to enable/disable the phase here - lcd_ll_set_phase_cycles(bus->hal.dev, trans_desc->cmd_cycles, 0, trans_desc->data ? 1 : 0); - lcd_ll_set_command(bus->hal.dev, bus->bus_width, trans_desc->cmd_value); + uint32_t data_cycles = trans_desc->data ? 1 : 0; + if (trans_desc->cmd_value >= 0) { + lcd_ll_set_command(bus->hal.dev, bus->bus_width, trans_desc->cmd_value); + } + lcd_ll_set_phase_cycles(bus->hal.dev, cmd_cycles, dummy_cycles, data_cycles); + lcd_ll_set_blank_cycles(bus->hal.dev, 1, 1); + if (trans_desc->data) { // some specific LCD commands can have no parameters gdma_start(bus->dma_chan, (intptr_t)(bus->dma_nodes)); // delay 1us is sufficient for DMA to pass data to LCD FIFO diff --git a/components/esp_lcd/test_apps/i80_lcd/main/test_i80_lcd_panel.c b/components/esp_lcd/test_apps/i80_lcd/main/test_i80_lcd_panel.c index 91d743b6989..746bd844878 100644 --- a/components/esp_lcd/test_apps/i80_lcd/main/test_i80_lcd_panel.c +++ b/components/esp_lcd/test_apps/i80_lcd/main/test_i80_lcd_panel.c @@ -453,3 +453,56 @@ TEST_CASE("lcd_panel_with_i80_interface_(st7789, 8bits)", "[lcd]") free(img); #undef TEST_IMG_SIZE } + +TEST_CASE("i80_io_skip_command_phase", "[lcd]") +{ + esp_lcd_i80_bus_handle_t i80_bus = NULL; + esp_lcd_i80_bus_config_t bus_config = { + .dc_gpio_num = TEST_LCD_DC_GPIO, + .wr_gpio_num = TEST_LCD_PCLK_GPIO, + .clk_src = LCD_CLK_SRC_DEFAULT, + .data_gpio_nums = { + TEST_LCD_DATA0_GPIO, + TEST_LCD_DATA1_GPIO, + TEST_LCD_DATA2_GPIO, + TEST_LCD_DATA3_GPIO, + TEST_LCD_DATA4_GPIO, + TEST_LCD_DATA5_GPIO, + TEST_LCD_DATA6_GPIO, + TEST_LCD_DATA7_GPIO, + }, + .bus_width = 8, + .max_transfer_bytes = 100, + }; + esp_lcd_panel_io_handle_t io_handle = NULL; + esp_lcd_panel_io_i80_config_t io_config = { + .cs_gpio_num = TEST_LCD_CS_GPIO, + .pclk_hz = 5000000, // 5MHz + .trans_queue_depth = 10, + .dc_levels = { + .dc_idle_level = 0, + .dc_cmd_level = 0, + .dc_dummy_level = 0, + .dc_data_level = 1, + }, + .lcd_cmd_bits = 8, + .lcd_param_bits = 8, + }; + + TEST_ESP_OK(esp_lcd_new_i80_bus(&bus_config, &i80_bus)); + TEST_ESP_OK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle)); + + uint8_t buf[4] = {0x01, 0x02, 0x03, 0x04}; + // lcd_cmd = -1 to skip the command phase + TEST_ESP_OK(esp_lcd_panel_io_tx_color(io_handle, -1, buf, 4)); + vTaskDelay(100 / portTICK_PERIOD_MS); + TEST_ESP_OK(esp_lcd_panel_io_tx_param(io_handle, -1, buf, 4)); + + // use command phase + TEST_ESP_OK(esp_lcd_panel_io_tx_color(io_handle, 0x2C, buf, 4)); + vTaskDelay(100 / portTICK_PERIOD_MS); + TEST_ESP_OK(esp_lcd_panel_io_tx_param(io_handle, 0x2A, buf, 4)); + + TEST_ESP_OK(esp_lcd_panel_io_del(io_handle)); + TEST_ESP_OK(esp_lcd_del_i80_bus(i80_bus)); +} diff --git a/examples/peripherals/lcd/i80_controller/main/Kconfig.projbuild b/examples/peripherals/lcd/i80_controller/main/Kconfig.projbuild index 1980e2972b1..1edfd6df5ff 100644 --- a/examples/peripherals/lcd/i80_controller/main/Kconfig.projbuild +++ b/examples/peripherals/lcd/i80_controller/main/Kconfig.projbuild @@ -47,7 +47,7 @@ menu "Example Configuration" config EXAMPLE_LCD_TOUCH_ENABLED bool "Enable LCD touch" - default y + default n help Enable this option if you wish to use display touch. You can select from three touch controllers. diff --git a/examples/peripherals/lcd/i80_controller/sdkconfig.defaults.esp32s3 b/examples/peripherals/lcd/i80_controller/sdkconfig.defaults.esp32s3 index 3119d63719c..2cfad7e5220 100644 --- a/examples/peripherals/lcd/i80_controller/sdkconfig.defaults.esp32s3 +++ b/examples/peripherals/lcd/i80_controller/sdkconfig.defaults.esp32s3 @@ -1,4 +1,7 @@ CONFIG_SPIRAM=y CONFIG_SPIRAM_SPEED_80M=y -# Can't set the FPS too high due to the limitation of PSRAM bandwidth -CONFIG_LV_DISP_DEF_REFR_PERIOD=100 + +# Enabling the following configurations can help increase the PCLK frequency in the case when +# the Frame Buffer is allocated from the PSRAM and fetched by EDMA +CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y +CONFIG_SPIRAM_RODATA=y