diff --git a/components/esp_lcd/include/esp_lcd_panel_io.h b/components/esp_lcd/include/esp_lcd_panel_io.h index 74b3335987..6d225c9e91 100644 --- a/components/esp_lcd/include/esp_lcd_panel_io.h +++ b/components/esp_lcd/include/esp_lcd_panel_io.h @@ -98,7 +98,8 @@ typedef struct { unsigned int dc_as_cmd_phase: 1; /*!< D/C line value is encoded into SPI transaction command phase */ unsigned int dc_low_on_data: 1; /*!< If this flag is enabled, DC line = 0 means transfer data, DC line = 1 means transfer command; vice versa */ unsigned int octal_mode: 1; /*!< transmit with octal mode (8 data lines), this mode is used to simulate Intel 8080 timing */ - } flags; + unsigned int lsb_first: 1; /*!< transmit LSB bit first */ + } flags; /*!< Extra flags to fine-tune the SPI device */ } esp_lcd_panel_io_spi_config_t; /** diff --git a/components/esp_lcd/include/esp_lcd_panel_ops.h b/components/esp_lcd/include/esp_lcd_panel_ops.h index 5099233ce8..fcea1db00b 100644 --- a/components/esp_lcd/include/esp_lcd_panel_ops.h +++ b/components/esp_lcd/include/esp_lcd_panel_ops.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -110,6 +110,17 @@ esp_err_t esp_lcd_panel_set_gap(esp_lcd_panel_handle_t panel, int x_gap, int y_g */ esp_err_t esp_lcd_panel_invert_color(esp_lcd_panel_handle_t panel, bool invert_color_data); +/** + * @brief Turn on or off the display + * + * @param[in] panel LCD panel handle, which is created by other factory API like `esp_lcd_new_panel_st7789()` + * @param[in] on_off True to turns on display, False to turns off display + * @return + * - ESP_OK on success + * - ESP_ERR_NOT_SUPPORTED if this function is not supported by the panel + */ +esp_err_t esp_lcd_panel_disp_on_off(esp_lcd_panel_handle_t panel, bool on_off); + /** * @brief Turn off the display * @@ -119,7 +130,8 @@ esp_err_t esp_lcd_panel_invert_color(esp_lcd_panel_handle_t panel, bool invert_c * - ESP_OK on success * - ESP_ERR_NOT_SUPPORTED if this function is not supported by the panel */ -esp_err_t esp_lcd_panel_disp_off(esp_lcd_panel_handle_t panel, bool off); +esp_err_t esp_lcd_panel_disp_off(esp_lcd_panel_handle_t panel, bool off) +__attribute__((deprecated("use esp_lcd_panel_disp_on_off instead"))); #ifdef __cplusplus } diff --git a/components/esp_lcd/interface/esp_lcd_panel_interface.h b/components/esp_lcd/interface/esp_lcd_panel_interface.h index 0705b145a2..b172c25d2b 100644 --- a/components/esp_lcd/interface/esp_lcd_panel_interface.h +++ b/components/esp_lcd/interface/esp_lcd_panel_interface.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -110,15 +110,15 @@ struct esp_lcd_panel_t { esp_err_t (*invert_color)(esp_lcd_panel_t *panel, bool invert_color_data); /** - * @brief Turn off the display + * @brief Turn on or off the display * * @param[in] panel LCD panel handle, which is created by other factory API like `esp_lcd_new_panel_st7789()` - * @param[in] off Whether to turn off the screen + * @param[in] on_off True to turns on display, False to turns off display * @return * - ESP_OK on success * - ESP_ERR_NOT_SUPPORTED if this function is not supported by the panel */ - esp_err_t (*disp_off)(esp_lcd_panel_t *panel, bool off); + esp_err_t (*disp_on_off)(esp_lcd_panel_t *panel, bool on_off); }; #ifdef __cplusplus diff --git a/components/esp_lcd/src/esp_lcd_panel_io_spi.c b/components/esp_lcd/src/esp_lcd_panel_io_spi.c index 9ce2a3000d..d5a792d092 100644 --- a/components/esp_lcd/src/esp_lcd_panel_io_spi.c +++ b/components/esp_lcd/src/esp_lcd_panel_io_spi.c @@ -72,7 +72,8 @@ esp_err_t esp_lcd_new_panel_io_spi(esp_lcd_spi_bus_handle_t bus, const esp_lcd_p ESP_GOTO_ON_FALSE(spi_panel_io, ESP_ERR_NO_MEM, err, TAG, "no mem for spi panel io"); spi_device_interface_config_t devcfg = { - .flags = SPI_DEVICE_HALFDUPLEX, // only use TX path, so half duplex is enough + // currently the driver only supports TX path, so half duplex is enough + .flags = SPI_DEVICE_HALFDUPLEX | (io_config->flags.lsb_first ? SPI_DEVICE_TXBIT_LSBFIRST : 0), .clock_speed_hz = io_config->pclk_hz, .mode = io_config->spi_mode, .spics_io_num = io_config->cs_gpio_num, diff --git a/components/esp_lcd/src/esp_lcd_panel_nt35510.c b/components/esp_lcd/src/esp_lcd_panel_nt35510.c index 15a33a0a72..8a66a5a77b 100644 --- a/components/esp_lcd/src/esp_lcd_panel_nt35510.c +++ b/components/esp_lcd/src/esp_lcd_panel_nt35510.c @@ -33,7 +33,7 @@ static esp_err_t panel_nt35510_invert_color(esp_lcd_panel_t *panel, bool invert_ static esp_err_t panel_nt35510_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y); static esp_err_t panel_nt35510_swap_xy(esp_lcd_panel_t *panel, bool swap_axes); static esp_err_t panel_nt35510_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap); -static esp_err_t panel_nt35510_disp_off(esp_lcd_panel_t *panel, bool off); +static esp_err_t panel_nt35510_disp_on_off(esp_lcd_panel_t *panel, bool off); typedef struct { esp_lcd_panel_t base; @@ -105,7 +105,7 @@ esp_err_t esp_lcd_new_panel_nt35510(const esp_lcd_panel_io_handle_t io, const es nt35510->base.set_gap = panel_nt35510_set_gap; nt35510->base.mirror = panel_nt35510_mirror; nt35510->base.swap_xy = panel_nt35510_swap_xy; - nt35510->base.disp_off = panel_nt35510_disp_off; + nt35510->base.disp_on_off = panel_nt35510_disp_on_off; *ret_panel = &(nt35510->base); ESP_LOGD(TAG, "new nt35510 panel @%p", nt35510); @@ -166,8 +166,6 @@ static esp_err_t panel_nt35510_init(esp_lcd_panel_t *panel) esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD << 8, (uint16_t[]) { nt35510->colmod_cal, }, 2); - // turn on display - esp_lcd_panel_io_tx_param(io, LCD_CMD_DISPON << 8, NULL, 0); return ESP_OK; } @@ -272,15 +270,15 @@ static esp_err_t panel_nt35510_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_ return ESP_OK; } -static esp_err_t panel_nt35510_disp_off(esp_lcd_panel_t *panel, bool off) +static esp_err_t panel_nt35510_disp_on_off(esp_lcd_panel_t *panel, bool on_off) { nt35510_panel_t *nt35510 = __containerof(panel, nt35510_panel_t, base); esp_lcd_panel_io_handle_t io = nt35510->io; int command = 0; - if (off) { - command = LCD_CMD_DISPOFF; - } else { + if (on_off) { command = LCD_CMD_DISPON; + } else { + command = LCD_CMD_DISPOFF; } esp_lcd_panel_io_tx_param(io, command << 8, NULL, 0); return ESP_OK; diff --git a/components/esp_lcd/src/esp_lcd_panel_ops.c b/components/esp_lcd/src/esp_lcd_panel_ops.c index 5b634e22ca..b70611e246 100644 --- a/components/esp_lcd/src/esp_lcd_panel_ops.c +++ b/components/esp_lcd/src/esp_lcd_panel_ops.c @@ -58,8 +58,13 @@ esp_err_t esp_lcd_panel_invert_color(esp_lcd_panel_handle_t panel, bool invert_c return panel->invert_color(panel, invert_color_data); } -esp_err_t esp_lcd_panel_disp_off(esp_lcd_panel_handle_t panel, bool off) +esp_err_t esp_lcd_panel_disp_on_off(esp_lcd_panel_handle_t panel, bool on_off) { ESP_RETURN_ON_FALSE(panel, ESP_ERR_INVALID_ARG, TAG, "invalid panel handle"); - return panel->disp_off(panel, off); + return panel->disp_on_off(panel, on_off); +} + +esp_err_t esp_lcd_panel_disp_off(esp_lcd_panel_handle_t panel, bool off) +{ + return esp_lcd_panel_disp_on_off(panel, !off); } diff --git a/components/esp_lcd/src/esp_lcd_panel_ssd1306.c b/components/esp_lcd/src/esp_lcd_panel_ssd1306.c index aa0129591f..ad6e89807d 100644 --- a/components/esp_lcd/src/esp_lcd_panel_ssd1306.c +++ b/components/esp_lcd/src/esp_lcd_panel_ssd1306.c @@ -46,7 +46,7 @@ static esp_err_t panel_ssd1306_invert_color(esp_lcd_panel_t *panel, bool invert_ static esp_err_t panel_ssd1306_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y); static esp_err_t panel_ssd1306_swap_xy(esp_lcd_panel_t *panel, bool swap_axes); static esp_err_t panel_ssd1306_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap); -static esp_err_t panel_ssd1306_disp_off(esp_lcd_panel_t *panel, bool off); +static esp_err_t panel_ssd1306_disp_on_off(esp_lcd_panel_t *panel, bool off); typedef struct { esp_lcd_panel_t base; @@ -91,7 +91,7 @@ esp_err_t esp_lcd_new_panel_ssd1306(const esp_lcd_panel_io_handle_t io, const es ssd1306->base.set_gap = panel_ssd1306_set_gap; ssd1306->base.mirror = panel_ssd1306_mirror; ssd1306->base.swap_xy = panel_ssd1306_swap_xy; - ssd1306->base.disp_off = panel_ssd1306_disp_off; + ssd1306->base.disp_on_off = panel_ssd1306_disp_on_off; *ret_panel = &(ssd1306->base); ESP_LOGD(TAG, "new ssd1306 panel @%p", ssd1306); @@ -144,9 +144,6 @@ static esp_err_t panel_ssd1306_init(esp_lcd_panel_t *panel) esp_lcd_panel_io_tx_param(io, SSD1306_CMD_SET_CHARGE_PUMP, (uint8_t[]) { 0x14 // enable charge pump }, 1); - esp_lcd_panel_io_tx_param(io, SSD1306_CMD_DISP_ON, NULL, 0); - // SEG/COM will be ON after 100ms after sending DISP_ON command - vTaskDelay(pdMS_TO_TICKS(100)); return ESP_OK; } @@ -227,16 +224,18 @@ static esp_err_t panel_ssd1306_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_ return ESP_OK; } -static esp_err_t panel_ssd1306_disp_off(esp_lcd_panel_t *panel, bool off) +static esp_err_t panel_ssd1306_disp_on_off(esp_lcd_panel_t *panel, bool on_off) { ssd1306_panel_t *ssd1306 = __containerof(panel, ssd1306_panel_t, base); esp_lcd_panel_io_handle_t io = ssd1306->io; int command = 0; - if (off) { - command = SSD1306_CMD_DISP_OFF; - } else { + if (on_off) { command = SSD1306_CMD_DISP_ON; + } else { + command = SSD1306_CMD_DISP_OFF; } esp_lcd_panel_io_tx_param(io, command, NULL, 0); + // SEG/COM will be ON/OFF after 100ms after sending DISP_ON/OFF command + vTaskDelay(pdMS_TO_TICKS(100)); return ESP_OK; } diff --git a/components/esp_lcd/src/esp_lcd_panel_st7789.c b/components/esp_lcd/src/esp_lcd_panel_st7789.c index 6e22faddff..eb9364dd26 100644 --- a/components/esp_lcd/src/esp_lcd_panel_st7789.c +++ b/components/esp_lcd/src/esp_lcd_panel_st7789.c @@ -33,7 +33,7 @@ static esp_err_t panel_st7789_invert_color(esp_lcd_panel_t *panel, bool invert_c static esp_err_t panel_st7789_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y); static esp_err_t panel_st7789_swap_xy(esp_lcd_panel_t *panel, bool swap_axes); static esp_err_t panel_st7789_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap); -static esp_err_t panel_st7789_disp_off(esp_lcd_panel_t *panel, bool off); +static esp_err_t panel_st7789_disp_on_off(esp_lcd_panel_t *panel, bool off); typedef struct { esp_lcd_panel_t base; @@ -102,7 +102,7 @@ esp_err_t esp_lcd_new_panel_st7789(const esp_lcd_panel_io_handle_t io, const esp st7789->base.set_gap = panel_st7789_set_gap; st7789->base.mirror = panel_st7789_mirror; st7789->base.swap_xy = panel_st7789_swap_xy; - st7789->base.disp_off = panel_st7789_disp_off; + st7789->base.disp_on_off = panel_st7789_disp_on_off; *ret_panel = &(st7789->base); ESP_LOGD(TAG, "new st7789 panel @%p", st7789); @@ -162,8 +162,6 @@ 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); - // turn on display - esp_lcd_panel_io_tx_param(io, LCD_CMD_DISPON, NULL, 0); return ESP_OK; } @@ -256,15 +254,15 @@ static esp_err_t panel_st7789_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_g return ESP_OK; } -static esp_err_t panel_st7789_disp_off(esp_lcd_panel_t *panel, bool off) +static esp_err_t panel_st7789_disp_on_off(esp_lcd_panel_t *panel, bool on_off) { st7789_panel_t *st7789 = __containerof(panel, st7789_panel_t, base); esp_lcd_panel_io_handle_t io = st7789->io; int command = 0; - if (off) { - command = LCD_CMD_DISPOFF; - } else { + if (on_off) { command = LCD_CMD_DISPON; + } else { + command = LCD_CMD_DISPOFF; } esp_lcd_panel_io_tx_param(io, command, NULL, 0); return ESP_OK; diff --git a/components/esp_lcd/src/esp_lcd_rgb_panel.c b/components/esp_lcd/src/esp_lcd_rgb_panel.c index 9ea6ff8675..40fc6778a0 100644 --- a/components/esp_lcd/src/esp_lcd_rgb_panel.c +++ b/components/esp_lcd/src/esp_lcd_rgb_panel.c @@ -60,7 +60,7 @@ static esp_err_t rgb_panel_invert_color(esp_lcd_panel_t *panel, bool invert_colo static esp_err_t rgb_panel_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y); static esp_err_t rgb_panel_swap_xy(esp_lcd_panel_t *panel, bool swap_axes); static esp_err_t rgb_panel_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap); -static esp_err_t rgb_panel_disp_off(esp_lcd_panel_t *panel, bool off); +static esp_err_t rgb_panel_disp_on_off(esp_lcd_panel_t *panel, bool off); static esp_err_t lcd_rgb_panel_select_periph_clock(esp_rgb_panel_t *panel, lcd_clock_source_t clk_src); static esp_err_t lcd_rgb_panel_create_trans_link(esp_rgb_panel_t *panel); static esp_err_t lcd_rgb_panel_configure_gpio(esp_rgb_panel_t *panel, const esp_lcd_rgb_panel_config_t *panel_config); @@ -190,7 +190,7 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf rgb_panel->base.reset = rgb_panel_reset; rgb_panel->base.init = rgb_panel_init; rgb_panel->base.draw_bitmap = rgb_panel_draw_bitmap; - rgb_panel->base.disp_off = rgb_panel_disp_off; + rgb_panel->base.disp_on_off = rgb_panel_disp_on_off; rgb_panel->base.invert_color = rgb_panel_invert_color; rgb_panel->base.mirror = rgb_panel_mirror; rgb_panel->base.swap_xy = rgb_panel_swap_xy; @@ -374,13 +374,13 @@ static esp_err_t rgb_panel_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap) return ESP_OK; } -static esp_err_t rgb_panel_disp_off(esp_lcd_panel_t *panel, bool off) +static esp_err_t rgb_panel_disp_on_off(esp_lcd_panel_t *panel, bool on_off) { esp_rgb_panel_t *rgb_panel = __containerof(panel, esp_rgb_panel_t, base); if (rgb_panel->disp_gpio_num < 0) { return ESP_ERR_NOT_SUPPORTED; } - if (off) { // turn off screen + if (!on_off) { // turn off screen gpio_set_level(rgb_panel->disp_gpio_num, !rgb_panel->flags.disp_en_level); } else { // turn on screen gpio_set_level(rgb_panel->disp_gpio_num, rgb_panel->flags.disp_en_level); diff --git a/components/esp_lcd/test_apps/i2c_lcd/main/test_i2c_lcd_panel.c b/components/esp_lcd/test_apps/i2c_lcd/main/test_i2c_lcd_panel.c index f71c1c4a3a..52d9fe95e6 100644 --- a/components/esp_lcd/test_apps/i2c_lcd/main/test_i2c_lcd_panel.c +++ b/components/esp_lcd/test_apps/i2c_lcd/main/test_i2c_lcd_panel.c @@ -56,6 +56,8 @@ TEST_CASE("lcd_panel_with_i2c_interface_(ssd1306)", "[lcd]") TEST_ESP_OK(esp_lcd_new_panel_ssd1306(io_handle, &panel_config, &panel_handle)); TEST_ESP_OK(esp_lcd_panel_reset(panel_handle)); TEST_ESP_OK(esp_lcd_panel_init(panel_handle)); + // turn on display + TEST_ESP_OK(esp_lcd_panel_disp_on_off(panel_handle, true)); for (int i = 0; i < TEST_LCD_H_RES / 16; i++) { for (int j = 0; j < TEST_LCD_V_RES / 8; j++) { 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 4dda0849eb..4d3be8bc5f 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 @@ -437,6 +437,8 @@ TEST_CASE("lcd_panel_with_i80_interface_(st7789, 8bits)", "[lcd]") esp_lcd_panel_invert_color(panel_handle, true); // the gap is LCD panel specific, even panels with the same driver IC, can have different gap value esp_lcd_panel_set_gap(panel_handle, 0, 20); + // turn on display + esp_lcd_panel_disp_on_off(panel_handle, true); // turn on backlight gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 1); @@ -447,7 +449,8 @@ TEST_CASE("lcd_panel_with_i80_interface_(st7789, 8bits)", "[lcd]") memset(img, color_byte, TEST_IMG_SIZE); esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img); } - esp_lcd_panel_disp_off(panel_handle, true); // turn off screen + // turn off screen + esp_lcd_panel_disp_on_off(panel_handle, false); TEST_ESP_OK(esp_lcd_panel_del(panel_handle)); TEST_ESP_OK(esp_lcd_panel_io_del(io_handle)); diff --git a/components/esp_lcd/test_apps/spi_lcd/main/test_spi_lcd_panel.c b/components/esp_lcd/test_apps/spi_lcd/main/test_spi_lcd_panel.c index c02426160c..8a9a561e0b 100644 --- a/components/esp_lcd/test_apps/spi_lcd/main/test_spi_lcd_panel.c +++ b/components/esp_lcd/test_apps/spi_lcd/main/test_spi_lcd_panel.c @@ -79,6 +79,8 @@ static void lcd_panel_test(esp_lcd_panel_io_handle_t io_handle, esp_lcd_panel_ha esp_lcd_panel_invert_color(panel_handle, true); // the gap is LCD panel specific, even panels with the same driver IC, can have different gap value esp_lcd_panel_set_gap(panel_handle, 0, 20); + // turn on display + esp_lcd_panel_disp_on_off(panel_handle, true); // turn on backlight gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 1); @@ -90,7 +92,7 @@ static void lcd_panel_test(esp_lcd_panel_io_handle_t io_handle, esp_lcd_panel_ha esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 200, y_start + 200, img); } // turn off screen - esp_lcd_panel_disp_off(panel_handle, true); + esp_lcd_panel_disp_on_off(panel_handle, false); TEST_ESP_OK(esp_lcd_panel_del(panel_handle)); TEST_ESP_OK(esp_lcd_panel_io_del(io_handle)); TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID)); diff --git a/components/hal/esp32/include/hal/rmt_ll.h b/components/hal/esp32/include/hal/rmt_ll.h index e82bd4c629..df042e6097 100644 --- a/components/hal/esp32/include/hal/rmt_ll.h +++ b/components/hal/esp32/include/hal/rmt_ll.h @@ -459,7 +459,19 @@ static inline uint32_t rmt_ll_tx_get_interrupt_status(rmt_dev_t *dev, uint32_t c */ static inline uint32_t rmt_ll_tx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel) { - return dev->int_raw.val & RMT_LL_EVENT_TX_MASK(channel); + return dev->int_raw.val & (RMT_LL_EVENT_TX_MASK(channel) | RMT_LL_EVENT_TX_ERROR(channel)); +} + +/** + * @brief Get interrupt raw status for RX channel + * + * @param dev Peripheral instance address + * @param channel RMT RX channel number + * @return Interrupt raw status + */ +static inline uint32_t rmt_ll_rx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel) +{ + return dev->int_raw.val & (RMT_LL_EVENT_RX_MASK(channel) | RMT_LL_EVENT_RX_ERROR(channel)); } /** diff --git a/components/hal/esp32c3/include/hal/rmt_ll.h b/components/hal/esp32c3/include/hal/rmt_ll.h index 73c2f66cfc..f73ae68a06 100644 --- a/components/hal/esp32c3/include/hal/rmt_ll.h +++ b/components/hal/esp32c3/include/hal/rmt_ll.h @@ -637,7 +637,19 @@ static inline uint32_t rmt_ll_tx_get_interrupt_status(rmt_dev_t *dev, uint32_t c */ static inline uint32_t rmt_ll_tx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel) { - return dev->int_raw.val & RMT_LL_EVENT_TX_MASK(channel); + return dev->int_raw.val & (RMT_LL_EVENT_TX_MASK(channel) | RMT_LL_EVENT_TX_ERROR(channel)); +} + +/** + * @brief Get interrupt raw status for RX channel + * + * @param dev Peripheral instance address + * @param channel RMT RX channel number + * @return Interrupt raw status + */ +static inline uint32_t rmt_ll_rx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel) +{ + return dev->int_raw.val & (RMT_LL_EVENT_RX_MASK(channel) | RMT_LL_EVENT_RX_ERROR(channel)); } /** diff --git a/components/hal/esp32h2/include/hal/rmt_ll.h b/components/hal/esp32h2/include/hal/rmt_ll.h index 12b736e8f2..f82f36a799 100644 --- a/components/hal/esp32h2/include/hal/rmt_ll.h +++ b/components/hal/esp32h2/include/hal/rmt_ll.h @@ -637,7 +637,19 @@ static inline uint32_t rmt_ll_tx_get_interrupt_status(rmt_dev_t *dev, uint32_t c */ static inline uint32_t rmt_ll_tx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel) { - return dev->int_raw.val & RMT_LL_EVENT_TX_MASK(channel); + return dev->int_raw.val & (RMT_LL_EVENT_TX_MASK(channel) | RMT_LL_EVENT_TX_ERROR(channel)); +} + +/** + * @brief Get interrupt raw status for RX channel + * + * @param dev Peripheral instance address + * @param channel RMT RX channel number + * @return Interrupt raw status + */ +static inline uint32_t rmt_ll_rx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel) +{ + return dev->int_raw.val & (RMT_LL_EVENT_RX_MASK(channel) | RMT_LL_EVENT_RX_ERROR(channel)); } /** diff --git a/components/hal/esp32s2/include/hal/rmt_ll.h b/components/hal/esp32s2/include/hal/rmt_ll.h index 8ab268510a..290270632c 100644 --- a/components/hal/esp32s2/include/hal/rmt_ll.h +++ b/components/hal/esp32s2/include/hal/rmt_ll.h @@ -600,7 +600,19 @@ static inline uint32_t rmt_ll_tx_get_interrupt_status(rmt_dev_t *dev, uint32_t c */ static inline uint32_t rmt_ll_tx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel) { - return dev->int_raw.val & RMT_LL_EVENT_TX_MASK(channel); + return dev->int_raw.val & (RMT_LL_EVENT_TX_MASK(channel) | RMT_LL_EVENT_TX_ERROR(channel)); +} + +/** + * @brief Get interrupt raw status for RX channel + * + * @param dev Peripheral instance address + * @param channel RMT RX channel number + * @return Interrupt raw status + */ +static inline uint32_t rmt_ll_rx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel) +{ + return dev->int_raw.val & (RMT_LL_EVENT_RX_MASK(channel) | RMT_LL_EVENT_RX_ERROR(channel)); } /** diff --git a/components/hal/esp32s3/include/hal/rmt_ll.h b/components/hal/esp32s3/include/hal/rmt_ll.h index a506d30b4d..79134e83d4 100644 --- a/components/hal/esp32s3/include/hal/rmt_ll.h +++ b/components/hal/esp32s3/include/hal/rmt_ll.h @@ -674,7 +674,19 @@ static inline uint32_t rmt_ll_tx_get_interrupt_status(rmt_dev_t *dev, uint32_t c */ static inline uint32_t rmt_ll_tx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel) { - return dev->int_raw.val & RMT_LL_EVENT_TX_MASK(channel); + return dev->int_raw.val & (RMT_LL_EVENT_TX_MASK(channel) | RMT_LL_EVENT_TX_ERROR(channel)); +} + +/** + * @brief Get interrupt raw status for RX channel + * + * @param dev Peripheral instance address + * @param channel RMT RX channel number + * @return Interrupt raw status + */ +static inline uint32_t rmt_ll_rx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel) +{ + return dev->int_raw.val & (RMT_LL_EVENT_RX_MASK(channel) | RMT_LL_EVENT_RX_ERROR(channel)); } /** diff --git a/components/heap/heap_caps.c b/components/heap/heap_caps.c index cfda5e1508..f7b0f4ed17 100644 --- a/components/heap/heap_caps.c +++ b/components/heap/heap_caps.c @@ -574,6 +574,7 @@ void heap_caps_dump_all(void) size_t heap_caps_get_allocated_size( void *ptr ) { heap_t *heap = find_containing_heap(ptr); + assert(heap); size_t size = multi_heap_get_allocated_size(heap->heap, ptr); return size; } diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index baf5c35df2..8392fe9a57 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -431,6 +431,10 @@ config SOC_RMT_SUPPORT_REF_TICK bool default y +config SOC_RMT_SUPPORT_APB + bool + default y + config SOC_RMT_CHANNEL_CLK_INDEPENDENT bool default y diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 610055b1d9..d73c88010b 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -68,7 +68,7 @@ #define SOC_MCPWM_SUPPORTED 1 #define SOC_SDMMC_HOST_SUPPORTED 1 #define SOC_BT_SUPPORTED 1 -#define SOC_BLUEDROID_SUPPORTED 1 +#define SOC_BLUEDROID_SUPPORTED 1 #define SOC_CLASSIC_BT_SUPPORTED 1 #define SOC_PCNT_SUPPORTED 1 #define SOC_WIFI_SUPPORTED 1 @@ -238,6 +238,7 @@ #define SOC_RMT_CHANNELS_PER_GROUP 8 /*!< Total 8 channels */ #define SOC_RMT_MEM_WORDS_PER_CHANNEL 64 /*!< Each channel owns 64 words memory */ #define SOC_RMT_SUPPORT_REF_TICK 1 /*!< Support set REF_TICK as the RMT clock source */ +#define SOC_RMT_SUPPORT_APB 1 /*!< Support set APB as the RMT clock source */ #define SOC_RMT_CHANNEL_CLK_INDEPENDENT 1 /*!< Can select different source clock for each channel */ /*-------------------------- RTCIO CAPS --------------------------------------*/ diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index 8cf1bf63ee..9d1ffc10bf 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -423,6 +423,14 @@ config SOC_RMT_SUPPORT_XTAL bool default y +config SOC_RMT_SUPPORT_APB + bool + default y + +config SOC_RMT_SUPPORT_RC_FAST + bool + default y + config SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH int default 128 diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index ba5a68a7c5..d17bb59beb 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -197,6 +197,8 @@ #define SOC_RMT_SUPPORT_TX_SYNCHRO 1 /*!< Support coordinate a group of TX channels to start simultaneously */ #define SOC_RMT_SUPPORT_TX_CARRIER_ALWAYS_ON 1 /*!< TX carrier can be modulated all the time */ #define SOC_RMT_SUPPORT_XTAL 1 /*!< Support set XTAL clock as the RMT clock source */ +#define SOC_RMT_SUPPORT_APB 1 /*!< Support set APB as the RMT clock source */ +#define SOC_RMT_SUPPORT_RC_FAST 1 /*!< Support set RC_FAST clock as the RMT clock source */ /*-------------------------- RTC CAPS --------------------------------------*/ #define SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH (128) diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index a6d5823ebf..12e6cafbd5 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -415,6 +415,14 @@ config SOC_RMT_SUPPORT_XTAL bool default y +config SOC_RMT_SUPPORT_AHB + bool + default y + +config SOC_RMT_SUPPORT_RC_FAST + bool + default y + config SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH int default 128 diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 37857d579d..18b33eefac 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -40,7 +40,7 @@ #define SOC_TWAI_SUPPORTED 1 #define SOC_BT_SUPPORTED 1 #define SOC_BLUEDROID_SUPPORTED 0 -#define SOC_ESP_NIMBLE_CONTROLLER 1 +#define SOC_ESP_NIMBLE_CONTROLLER 1 #define SOC_ASYNC_MEMCPY_SUPPORTED 1 #define SOC_USB_SERIAL_JTAG_SUPPORTED 1 #define SOC_SUPPORTS_SECURE_DL_MODE 1 @@ -208,6 +208,8 @@ #define SOC_RMT_SUPPORT_TX_SYNCHRO 1 /*!< Support coordinate a group of TX channels to start simultaneously */ #define SOC_RMT_SUPPORT_TX_CARRIER_ALWAYS_ON 1 /*!< TX carrier can be modulated all the time */ #define SOC_RMT_SUPPORT_XTAL 1 /*!< Support set XTAL clock as the RMT clock source */ +#define SOC_RMT_SUPPORT_AHB 1 /*!< Support set AHB clock as the RMT clock source */ +#define SOC_RMT_SUPPORT_RC_FAST 1 /*!< Support set RC_FAST clock as the RMT clock source */ /*-------------------------- RTC CAPS --------------------------------------*/ #define SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH (128) diff --git a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in index 7aea75892e..a9dbc9204c 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -463,6 +463,10 @@ config SOC_RMT_SUPPORT_REF_TICK bool default y +config SOC_RMT_SUPPORT_APB + bool + default y + config SOC_RMT_CHANNEL_CLK_INDEPENDENT bool default y diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index 9aee67f1fc..9990b9d137 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -216,6 +216,7 @@ #define SOC_RMT_SUPPORT_TX_SYNCHRO 1 /*!< Support coordinate a group of TX channels to start simultaneously */ #define SOC_RMT_SUPPORT_TX_CARRIER_ALWAYS_ON 1 /*!< TX carrier can be modulated all the time */ #define SOC_RMT_SUPPORT_REF_TICK 1 /*!< Support set REF_TICK as the RMT clock source */ +#define SOC_RMT_SUPPORT_APB 1 /*!< Support set APB as the RMT clock source */ #define SOC_RMT_CHANNEL_CLK_INDEPENDENT 1 /*!< Can select different source clock for each channel */ /*-------------------------- RTCIO CAPS --------------------------------------*/ diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index 7cf74ec90e..629da0fc1f 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -515,6 +515,14 @@ config SOC_RMT_SUPPORT_XTAL bool default y +config SOC_RMT_SUPPORT_RC_FAST + bool + default y + +config SOC_RMT_SUPPORT_APB + bool + default y + config SOC_RMT_SUPPORT_DMA bool default y diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 295b7ca322..6f7e4c11fc 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -208,6 +208,8 @@ #define SOC_RMT_SUPPORT_TX_SYNCHRO 1 /*!< Support coordinate a group of TX channels to start simultaneously */ #define SOC_RMT_SUPPORT_TX_CARRIER_ALWAYS_ON 1 /*!< TX carrier can be modulated all the time */ #define SOC_RMT_SUPPORT_XTAL 1 /*!< Support set XTAL clock as the RMT clock source */ +#define SOC_RMT_SUPPORT_RC_FAST 1 /*!< Support set RC_FAST clock as the RMT clock source */ +#define SOC_RMT_SUPPORT_APB 1 /*!< Support set APB as the RMT clock source */ #define SOC_RMT_SUPPORT_DMA 1 /*!< RMT peripheral can connect to DMA channel */ /*-------------------------- LCD CAPS ----------------------------------------*/ diff --git a/docs/en/migration-guides/peripherals.rst b/docs/en/migration-guides/peripherals.rst index 33281f247c..b91439be93 100644 --- a/docs/en/migration-guides/peripherals.rst +++ b/docs/en/migration-guides/peripherals.rst @@ -116,3 +116,9 @@ I2C - ``rmt_set_intr_enable_mask`` and ``rmt_clr_intr_enable_mask`` are removed, as the interrupt is handled by the driver, user doesn't need to take care of it. - ``rmt_set_pin`` is removed, as ``rmt_set_gpio`` can do the same thing. - ``rmt_memory_rw_rst`` is removed, user can use ``rmt_tx_memory_reset`` and ``rmt_rx_memory_reset`` for TX and RX channel respectively. + +LCD +--- + +- The LCD panel initialization flow is slightly changed. Now the :cpp:func:`esp_lcd_panel_init` won't turn on the display automatically. User needs to call :cpp:func:`esp_lcd_panel_disp_on_off` to manually turn on the display. Note, this is different from turning on backlight. With this breaking change, user can flush a predefined pattern to the screen before turning on the screen. This can help avoid random noise on the screen after a power on reset. +- :cpp:func:`esp_lcd_panel_disp_off` is deprecated, please use :cpp:func:`esp_lcd_panel_disp_on_off` instead. diff --git a/examples/peripherals/lcd/gc9a01/main/esp_lcd_panel_gc9a01.c b/examples/peripherals/lcd/gc9a01/main/esp_lcd_panel_gc9a01.c index 11b67cf659..dd63de01d1 100644 --- a/examples/peripherals/lcd/gc9a01/main/esp_lcd_panel_gc9a01.c +++ b/examples/peripherals/lcd/gc9a01/main/esp_lcd_panel_gc9a01.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,7 +27,7 @@ static esp_err_t panel_gc9a01_invert_color(esp_lcd_panel_t *panel, bool invert_c static esp_err_t panel_gc9a01_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y); static esp_err_t panel_gc9a01_swap_xy(esp_lcd_panel_t *panel, bool swap_axes); static esp_err_t panel_gc9a01_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap); -static esp_err_t panel_gc9a01_disp_off(esp_lcd_panel_t *panel, bool off); +static esp_err_t panel_gc9a01_disp_on_off(esp_lcd_panel_t *panel, bool off); typedef struct { esp_lcd_panel_t base; @@ -93,7 +93,7 @@ esp_err_t esp_lcd_new_panel_gc9a01(const esp_lcd_panel_io_handle_t io, const esp gc9a01->base.set_gap = panel_gc9a01_set_gap; gc9a01->base.mirror = panel_gc9a01_mirror; gc9a01->base.swap_xy = panel_gc9a01_swap_xy; - gc9a01->base.disp_off = panel_gc9a01_disp_off; + gc9a01->base.disp_on_off = panel_gc9a01_disp_on_off; *ret_panel = &(gc9a01->base); ESP_LOGD(TAG, "new gc9a01 panel @%p", gc9a01); @@ -217,8 +217,6 @@ static esp_err_t panel_gc9a01_init(esp_lcd_panel_t *panel) cmd++; } - // turn on display - esp_lcd_panel_io_tx_param(io, LCD_CMD_DISPON, NULL, 0); return ESP_OK; } @@ -310,15 +308,15 @@ static esp_err_t panel_gc9a01_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_g return ESP_OK; } -static esp_err_t panel_gc9a01_disp_off(esp_lcd_panel_t *panel, bool off) +static esp_err_t panel_gc9a01_disp_on_off(esp_lcd_panel_t *panel, bool on_off) { gc9a01_panel_t *gc9a01 = __containerof(panel, gc9a01_panel_t, base); esp_lcd_panel_io_handle_t io = gc9a01->io; int command = 0; - if (off) { - command = LCD_CMD_DISPOFF; - } else { + if (on_off) { command = LCD_CMD_DISPON; + } else { + command = LCD_CMD_DISPOFF; } esp_lcd_panel_io_tx_param(io, command, NULL, 0); return ESP_OK; diff --git a/examples/peripherals/lcd/gc9a01/main/gc9a01_example_main.c b/examples/peripherals/lcd/gc9a01/main/gc9a01_example_main.c index 21093fadf1..c3e181142f 100644 --- a/examples/peripherals/lcd/gc9a01/main/gc9a01_example_main.c +++ b/examples/peripherals/lcd/gc9a01/main/gc9a01_example_main.c @@ -124,6 +124,9 @@ void app_main(void) ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_handle, true)); ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, true, false)); + // user can flush pre-defined pattern to the screen before we turn on the screen or backlight + ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true)); + ESP_LOGI(TAG, "Turn on LCD backlight"); gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL); diff --git a/examples/peripherals/lcd/i2c_oled/main/i2c_oled_example_main.c b/examples/peripherals/lcd/i2c_oled/main/i2c_oled_example_main.c index e6b8c5cf61..d3bae5e43c 100644 --- a/examples/peripherals/lcd/i2c_oled/main/i2c_oled_example_main.c +++ b/examples/peripherals/lcd/i2c_oled/main/i2c_oled_example_main.c @@ -124,6 +124,7 @@ void app_main(void) ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle)); ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle)); + ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true)); ESP_LOGI(TAG, "Initialize LVGL library"); lv_init(); diff --git a/examples/peripherals/lcd/i80_controller/main/i80_controller_example_main.c b/examples/peripherals/lcd/i80_controller/main/i80_controller_example_main.c index 0bc8365801..6ab5b687ed 100644 --- a/examples/peripherals/lcd/i80_controller/main/i80_controller_example_main.c +++ b/examples/peripherals/lcd/i80_controller/main/i80_controller_example_main.c @@ -191,6 +191,9 @@ void app_main(void) // the gap is LCD panel specific, even panels with the same driver IC, can have different gap value esp_lcd_panel_set_gap(panel_handle, 0, 20); + // user can flush pre-defined pattern to the screen before we turn on the screen or backlight + ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true)); + ESP_LOGI(TAG, "Turn on LCD backlight"); gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL); diff --git a/examples/peripherals/lcd/tjpgd/main/lcd_tjpgd_example_main.c b/examples/peripherals/lcd/tjpgd/main/lcd_tjpgd_example_main.c index d9faab0372..4df5b42797 100644 --- a/examples/peripherals/lcd/tjpgd/main/lcd_tjpgd_example_main.c +++ b/examples/peripherals/lcd/tjpgd/main/lcd_tjpgd_example_main.c @@ -145,6 +145,9 @@ void app_main(void) // Initialize LCD panel ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle)); + // Turn on the screen + ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(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));