From f29404338265320fde2af8c57ea69a8e4045741c Mon Sep 17 00:00:00 2001 From: Tomas Rezucha Date: Tue, 21 Feb 2023 10:34:36 +0100 Subject: [PATCH] bsp: Expose private API to initialize display without LVGL --- esp-box/CMakeLists.txt | 2 +- esp-box/esp-box.c | 154 ++++++++++-------- esp-box/include/bsp/display.h | 42 +++++ esp32_s2_kaluga_kit/CMakeLists.txt | 2 +- esp32_s2_kaluga_kit/esp32_s2_kaluga_kit.c | 49 ++++-- esp32_s2_kaluga_kit/include/bsp/display.h | 42 +++++ esp32_s3_eye/CMakeLists.txt | 2 +- esp32_s3_eye/esp32_s3_eye.c | 49 ++++-- esp32_s3_eye/include/bsp/display.h | 42 +++++ esp32_s3_korvo_2/CMakeLists.txt | 2 +- esp32_s3_korvo_2/esp32_s3_korvo_2.c | 69 +++++--- esp32_s3_korvo_2/include/bsp/display.h | 42 +++++ .../include/bsp/esp32_s3_korvo_2.h | 23 +-- esp32_s3_lcd_ev_board/esp32_s3_lcd_ev_board.c | 1 + esp32_s3_lcd_ev_board/include/bsp/display.h | 42 +++++ esp32_s3_usb_otg/CMakeLists.txt | 2 +- esp32_s3_usb_otg/esp32_s3_usb_otg.c | 51 ++++-- esp32_s3_usb_otg/include/bsp/display.h | 42 +++++ esp_wrover_kit/CMakeLists.txt | 2 +- esp_wrover_kit/esp_wrover_kit.c | 64 +++++--- esp_wrover_kit/include/bsp/display.h | 42 +++++ esp_wrover_kit/include/bsp/esp_wrover_kit.h | 4 +- 22 files changed, 597 insertions(+), 173 deletions(-) create mode 100644 esp-box/include/bsp/display.h create mode 100644 esp32_s2_kaluga_kit/include/bsp/display.h create mode 100644 esp32_s3_eye/include/bsp/display.h create mode 100644 esp32_s3_korvo_2/include/bsp/display.h create mode 100644 esp32_s3_lcd_ev_board/include/bsp/display.h create mode 100644 esp32_s3_usb_otg/include/bsp/display.h create mode 100644 esp_wrover_kit/include/bsp/display.h diff --git a/esp-box/CMakeLists.txt b/esp-box/CMakeLists.txt index 8fb57aa24..caa865550 100644 --- a/esp-box/CMakeLists.txt +++ b/esp-box/CMakeLists.txt @@ -3,5 +3,5 @@ idf_component_register( INCLUDE_DIRS "include" PRIV_INCLUDE_DIRS "priv_include" REQUIRES driver spiffs - PRIV_REQUIRES esp_timer esp_lcd esp_lcd_touch + PRIV_REQUIRES esp_lcd ) diff --git a/esp-box/esp-box.c b/esp-box/esp-box.c index e9a3bd32d..0e9b72ae7 100644 --- a/esp-box/esp-box.c +++ b/esp-box/esp-box.c @@ -4,18 +4,19 @@ * SPDX-License-Identifier: CC0-1.0 */ -#include "esp_timer.h" #include "driver/gpio.h" #include "driver/ledc.h" #include "driver/spi_master.h" #include "esp_err.h" #include "esp_log.h" +#include "esp_check.h" #include "esp_spiffs.h" #include "esp_lcd_panel_io.h" #include "esp_lcd_panel_vendor.h" #include "esp_lcd_panel_ops.h" #include "bsp/esp-box.h" +#include "bsp/display.h" #include "esp_lcd_touch_tt21100.h" #include "esp_lvgl_port.h" #include "bsp_err_check.h" @@ -133,8 +134,65 @@ esp_err_t bsp_audio_poweramp_enable(bool enable) #define LCD_PARAM_BITS 8 #define LCD_LEDC_CH CONFIG_BSP_DISPLAY_BRIGHTNESS_LEDC_CH -static lv_disp_t *bsp_display_lcd_init(void) +static esp_err_t bsp_display_brightness_init(void) +{ + // Setup LEDC peripheral for PWM backlight control + const ledc_channel_config_t LCD_backlight_channel = { + .gpio_num = BSP_LCD_BACKLIGHT, + .speed_mode = LEDC_LOW_SPEED_MODE, + .channel = LCD_LEDC_CH, + .intr_type = LEDC_INTR_DISABLE, + .timer_sel = 1, + .duty = 0, + .hpoint = 0 + }; + const ledc_timer_config_t LCD_backlight_timer = { + .speed_mode = LEDC_LOW_SPEED_MODE, + .duty_resolution = LEDC_TIMER_10_BIT, + .timer_num = 1, + .freq_hz = 5000, + .clk_cfg = LEDC_AUTO_CLK + }; + + BSP_ERROR_CHECK_RETURN_ERR(ledc_timer_config(&LCD_backlight_timer)); + BSP_ERROR_CHECK_RETURN_ERR(ledc_channel_config(&LCD_backlight_channel)); + + return ESP_OK; +} + +esp_err_t bsp_display_brightness_set(int brightness_percent) +{ + if (brightness_percent > 100) { + brightness_percent = 100; + } + if (brightness_percent < 0) { + brightness_percent = 0; + } + + ESP_LOGI(TAG, "Setting LCD backlight: %d%%", brightness_percent); + uint32_t duty_cycle = (1023 * brightness_percent) / 100; // LEDC resolution set to 10bits, thus: 100% = 1023 + BSP_ERROR_CHECK_RETURN_ERR(ledc_set_duty(LEDC_LOW_SPEED_MODE, LCD_LEDC_CH, duty_cycle)); + BSP_ERROR_CHECK_RETURN_ERR(ledc_update_duty(LEDC_LOW_SPEED_MODE, LCD_LEDC_CH)); + + return ESP_OK; +} + +esp_err_t bsp_display_backlight_off(void) { + return bsp_display_brightness_set(0); +} + +esp_err_t bsp_display_backlight_on(void) +{ + return bsp_display_brightness_set(100); +} + +esp_err_t bsp_display_new(esp_lcd_panel_handle_t *ret_panel, esp_lcd_panel_io_handle_t *ret_io) +{ + esp_err_t ret = ESP_OK; + + ESP_RETURN_ON_ERROR(bsp_display_brightness_init(), TAG, "Brightness init failed"); + ESP_LOGD(TAG, "Initialize SPI bus"); const spi_bus_config_t buscfg = { .sclk_io_num = BSP_LCD_PCLK, @@ -144,10 +202,9 @@ static lv_disp_t *bsp_display_lcd_init(void) .quadhd_io_num = GPIO_NUM_NC, .max_transfer_sz = BSP_LCD_H_RES * 80 * sizeof(uint16_t), }; - BSP_ERROR_CHECK_RETURN_NULL(spi_bus_initialize(BSP_LCD_SPI_NUM, &buscfg, SPI_DMA_CH_AUTO)); + ESP_RETURN_ON_ERROR(spi_bus_initialize(BSP_LCD_SPI_NUM, &buscfg, SPI_DMA_CH_AUTO), TAG, "SPI init failed"); ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_handle_t io_handle = NULL; const esp_lcd_panel_io_spi_config_t io_config = { .dc_gpio_num = BSP_LCD_DC, .cs_gpio_num = BSP_LCD_CS, @@ -157,22 +214,38 @@ static lv_disp_t *bsp_display_lcd_init(void) .spi_mode = 0, .trans_queue_depth = 10, }; + ESP_GOTO_ON_ERROR(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)BSP_LCD_SPI_NUM, &io_config, ret_io), err, TAG, "New panel IO failed"); - // Attach the LCD to the SPI bus - BSP_ERROR_CHECK_RETURN_NULL(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)BSP_LCD_SPI_NUM, &io_config, &io_handle)); - - ESP_LOGD(TAG, "Install LCD driver of st7789"); - esp_lcd_panel_handle_t panel_handle = NULL; + ESP_LOGD(TAG, "Install LCD driver"); const esp_lcd_panel_dev_config_t panel_config = { .reset_gpio_num = BSP_LCD_RST, // Shared with Touch reset .color_space = ESP_LCD_COLOR_SPACE_BGR, .bits_per_pixel = 16, }; - BSP_ERROR_CHECK_RETURN_NULL(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle)); + ESP_GOTO_ON_ERROR(esp_lcd_new_panel_st7789(*ret_io, &panel_config, ret_panel), err, TAG, "New panel failed"); + + esp_lcd_panel_reset(*ret_panel); + esp_lcd_panel_init(*ret_panel); + esp_lcd_panel_mirror(*ret_panel, true, true); + return ret; + +err: + if (*ret_panel) { + esp_lcd_panel_del(*ret_panel); + } + if (*ret_io) { + esp_lcd_panel_io_del(*ret_io); + } + spi_bus_free(BSP_LCD_SPI_NUM); + return ret; +} + +static lv_disp_t *bsp_display_lcd_init(void) +{ + esp_lcd_panel_io_handle_t io_handle = NULL; + esp_lcd_panel_handle_t panel_handle = NULL; + BSP_ERROR_CHECK_RETURN_NULL(bsp_display_new(&panel_handle, &io_handle)); - esp_lcd_panel_reset(panel_handle); - esp_lcd_panel_init(panel_handle); - esp_lcd_panel_mirror(panel_handle, true, true); esp_lcd_panel_disp_on_off(panel_handle, true); /* Add LCD screen */ @@ -232,66 +305,11 @@ static lv_indev_t *bsp_display_indev_init(lv_disp_t *disp) return lvgl_port_add_touch(&touch_cfg); } -static esp_err_t bsp_display_brightness_init(void) -{ - // Setup LEDC peripheral for PWM backlight control - const ledc_channel_config_t LCD_backlight_channel = { - .gpio_num = BSP_LCD_BACKLIGHT, - .speed_mode = LEDC_LOW_SPEED_MODE, - .channel = LCD_LEDC_CH, - .intr_type = LEDC_INTR_DISABLE, - .timer_sel = 1, - .duty = 0, - .hpoint = 0 - }; - const ledc_timer_config_t LCD_backlight_timer = { - .speed_mode = LEDC_LOW_SPEED_MODE, - .duty_resolution = LEDC_TIMER_10_BIT, - .timer_num = 1, - .freq_hz = 5000, - .clk_cfg = LEDC_AUTO_CLK - }; - - BSP_ERROR_CHECK_RETURN_ERR(ledc_timer_config(&LCD_backlight_timer)); - BSP_ERROR_CHECK_RETURN_ERR(ledc_channel_config(&LCD_backlight_channel)); - - return ESP_OK; -} - -esp_err_t bsp_display_brightness_set(int brightness_percent) -{ - if (brightness_percent > 100) { - brightness_percent = 100; - } - if (brightness_percent < 0) { - brightness_percent = 0; - } - - ESP_LOGI(TAG, "Setting LCD backlight: %d%%", brightness_percent); - uint32_t duty_cycle = (1023 * brightness_percent) / 100; // LEDC resolution set to 10bits, thus: 100% = 1023 - BSP_ERROR_CHECK_RETURN_ERR(ledc_set_duty(LEDC_LOW_SPEED_MODE, LCD_LEDC_CH, duty_cycle)); - BSP_ERROR_CHECK_RETURN_ERR(ledc_update_duty(LEDC_LOW_SPEED_MODE, LCD_LEDC_CH)); - - return ESP_OK; -} - -esp_err_t bsp_display_backlight_off(void) -{ - return bsp_display_brightness_set(0); -} - -esp_err_t bsp_display_backlight_on(void) -{ - return bsp_display_brightness_set(100); -} - lv_disp_t *bsp_display_start(void) { const lvgl_port_cfg_t lvgl_cfg = ESP_LVGL_PORT_INIT_CONFIG(); BSP_ERROR_CHECK_RETURN_NULL(lvgl_port_init(&lvgl_cfg)); - BSP_ERROR_CHECK_RETURN_NULL(bsp_display_brightness_init()); - BSP_NULL_CHECK(disp = bsp_display_lcd_init(), NULL); BSP_NULL_CHECK(bsp_display_indev_init(disp), NULL); diff --git a/esp-box/include/bsp/display.h b/esp-box/include/bsp/display.h new file mode 100644 index 000000000..ff068ee24 --- /dev/null +++ b/esp-box/include/bsp/display.h @@ -0,0 +1,42 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +/** + * @file + * @brief BSP LCD + * + * This file offers API for basic LCD control. + * It is useful for users who want to use the LCD without the default Graphical Library LVGL. + * + * For standard LCD initialization, you can call all-in-one function bsp_display_start(). + */ + +#pragma once +#include "esp_lcd_types.h" + +/** + * @brief Create new display panel + * + * For maximum flexibility, this function performs only reset and initialization of the display. + * You must turn on the display explicitly by calling esp_lcd_panel_disp_on_off(). + * The display's backlight is not turned on either. You can use bsp_display_backlight_on/off(), + * bsp_display_brightness_set() (on supported boards) or implement your own backlight control. + * + * If you want to free resources allocated by this function, you can use esp_lcd API, ie.: + * + * \code{.c} + * esp_lcd_panel_del(panel); + * esp_lcd_panel_io_del(io); + * spi_bus_free(spi_num_from_configuration); + * \endcode + * + * @param[out] ret_panel esp_lcd panel handle + * @param[out] ret_io esp_lcd IO handle + * @return + * - ESP_OK On success + * - Else esp_lcd failure + */ +esp_err_t bsp_display_new(esp_lcd_panel_handle_t *ret_panel, esp_lcd_panel_io_handle_t *ret_io); diff --git a/esp32_s2_kaluga_kit/CMakeLists.txt b/esp32_s2_kaluga_kit/CMakeLists.txt index 010bf57f0..d4babeb89 100644 --- a/esp32_s2_kaluga_kit/CMakeLists.txt +++ b/esp32_s2_kaluga_kit/CMakeLists.txt @@ -3,5 +3,5 @@ idf_component_register( INCLUDE_DIRS "include" PRIV_INCLUDE_DIRS "priv_include" REQUIRES driver - PRIV_REQUIRES esp_lcd esp_timer + PRIV_REQUIRES esp_lcd ) diff --git a/esp32_s2_kaluga_kit/esp32_s2_kaluga_kit.c b/esp32_s2_kaluga_kit/esp32_s2_kaluga_kit.c index 51710fec4..929e6b473 100644 --- a/esp32_s2_kaluga_kit/esp32_s2_kaluga_kit.c +++ b/esp32_s2_kaluga_kit/esp32_s2_kaluga_kit.c @@ -4,14 +4,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "esp_timer.h" -#include "bsp/esp32_s2_kaluga_kit.h" #include "driver/spi_master.h" #include "esp_err.h" #include "esp_log.h" +#include "esp_check.h" #include "esp_lcd_panel_io.h" #include "esp_lcd_panel_vendor.h" #include "esp_lcd_panel_ops.h" + +#include "bsp/esp32_s2_kaluga_kit.h" +#include "bsp/display.h" #include "esp_lvgl_port.h" #include "bsp_err_check.h" @@ -205,8 +207,9 @@ esp_err_t bsp_touchpad_calibrate(bsp_touchpad_button_t tch_pad, float tch_thresh #define LCD_CMD_BITS (8) #define LCD_PARAM_BITS (8) -static lv_disp_t *bsp_display_lcd_init(void) +esp_err_t bsp_display_new(esp_lcd_panel_handle_t *ret_panel, esp_lcd_panel_io_handle_t *ret_io) { + esp_err_t ret = ESP_OK; ESP_LOGD(TAG, "Initialize SPI bus"); const spi_bus_config_t buscfg = { .sclk_io_num = BSP_LCD_SPI_CLK, @@ -216,10 +219,9 @@ static lv_disp_t *bsp_display_lcd_init(void) .quadhd_io_num = GPIO_NUM_NC, .max_transfer_sz = BSP_LCD_H_RES * BSP_LCD_V_RES * sizeof(lv_color_t), }; - BSP_ERROR_CHECK_RETURN_NULL(spi_bus_initialize(BSP_LCD_SPI_NUM, &buscfg, SPI_DMA_CH_AUTO)); + ESP_RETURN_ON_ERROR(spi_bus_initialize(BSP_LCD_SPI_NUM, &buscfg, SPI_DMA_CH_AUTO), TAG, "SPI init failed"); ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_handle_t io_handle = NULL; const esp_lcd_panel_io_spi_config_t io_config = { .dc_gpio_num = BSP_LCD_DC, .cs_gpio_num = BSP_LCD_SPI_CS, @@ -229,23 +231,40 @@ static lv_disp_t *bsp_display_lcd_init(void) .spi_mode = 0, .trans_queue_depth = 10, }; - // Attach the LCD to the SPI bus - BSP_ERROR_CHECK_RETURN_NULL(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)BSP_LCD_SPI_NUM, &io_config, &io_handle)); + ESP_GOTO_ON_ERROR(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)BSP_LCD_SPI_NUM, &io_config, ret_io), err, TAG, "New panel IO failed"); - ESP_LOGD(TAG, "Install LCD driver for ST7789"); - esp_lcd_panel_handle_t panel_handle = NULL; + ESP_LOGD(TAG, "Install LCD driver"); const esp_lcd_panel_dev_config_t panel_config = { .reset_gpio_num = BSP_LCD_RST, .color_space = ESP_LCD_COLOR_SPACE_RGB, .bits_per_pixel = 16, }; - BSP_ERROR_CHECK_RETURN_NULL(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle)); + ESP_GOTO_ON_ERROR(esp_lcd_new_panel_st7789(*ret_io, &panel_config, ret_panel), err, TAG, "New panel failed"); + + esp_lcd_panel_reset(*ret_panel); + esp_lcd_panel_init(*ret_panel); + esp_lcd_panel_mirror(*ret_panel, true, false); + esp_lcd_panel_swap_xy(*ret_panel, true); + esp_lcd_panel_invert_color(*ret_panel, false); + return ret; + +err: + if (*ret_panel) { + esp_lcd_panel_del(*ret_panel); + } + if (*ret_io) { + esp_lcd_panel_io_del(*ret_io); + } + spi_bus_free(BSP_LCD_SPI_NUM); + return ret; +} + +static lv_disp_t *bsp_display_lcd_init(void) +{ + esp_lcd_panel_io_handle_t io_handle = NULL; + esp_lcd_panel_handle_t panel_handle = NULL; + BSP_ERROR_CHECK_RETURN_NULL(bsp_display_new(&panel_handle, &io_handle)); - esp_lcd_panel_reset(panel_handle); - esp_lcd_panel_init(panel_handle); - esp_lcd_panel_mirror(panel_handle, true, false); - esp_lcd_panel_swap_xy(panel_handle, true); - esp_lcd_panel_invert_color(panel_handle, false); esp_lcd_panel_disp_on_off(panel_handle, true); /* Add LCD screen */ diff --git a/esp32_s2_kaluga_kit/include/bsp/display.h b/esp32_s2_kaluga_kit/include/bsp/display.h new file mode 100644 index 000000000..ff068ee24 --- /dev/null +++ b/esp32_s2_kaluga_kit/include/bsp/display.h @@ -0,0 +1,42 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +/** + * @file + * @brief BSP LCD + * + * This file offers API for basic LCD control. + * It is useful for users who want to use the LCD without the default Graphical Library LVGL. + * + * For standard LCD initialization, you can call all-in-one function bsp_display_start(). + */ + +#pragma once +#include "esp_lcd_types.h" + +/** + * @brief Create new display panel + * + * For maximum flexibility, this function performs only reset and initialization of the display. + * You must turn on the display explicitly by calling esp_lcd_panel_disp_on_off(). + * The display's backlight is not turned on either. You can use bsp_display_backlight_on/off(), + * bsp_display_brightness_set() (on supported boards) or implement your own backlight control. + * + * If you want to free resources allocated by this function, you can use esp_lcd API, ie.: + * + * \code{.c} + * esp_lcd_panel_del(panel); + * esp_lcd_panel_io_del(io); + * spi_bus_free(spi_num_from_configuration); + * \endcode + * + * @param[out] ret_panel esp_lcd panel handle + * @param[out] ret_io esp_lcd IO handle + * @return + * - ESP_OK On success + * - Else esp_lcd failure + */ +esp_err_t bsp_display_new(esp_lcd_panel_handle_t *ret_panel, esp_lcd_panel_io_handle_t *ret_io); diff --git a/esp32_s3_eye/CMakeLists.txt b/esp32_s3_eye/CMakeLists.txt index d506af4c6..85bfd8217 100644 --- a/esp32_s3_eye/CMakeLists.txt +++ b/esp32_s3_eye/CMakeLists.txt @@ -3,5 +3,5 @@ idf_component_register( INCLUDE_DIRS "include" PRIV_INCLUDE_DIRS "priv_include" REQUIRES driver - PRIV_REQUIRES fatfs esp_lcd esp_timer + PRIV_REQUIRES fatfs esp_lcd ) diff --git a/esp32_s3_eye/esp32_s3_eye.c b/esp32_s3_eye/esp32_s3_eye.c index e6cd69f74..6951f1edb 100644 --- a/esp32_s3_eye/esp32_s3_eye.c +++ b/esp32_s3_eye/esp32_s3_eye.c @@ -5,14 +5,12 @@ */ #include -#include "bsp/esp32_s3_eye.h" #include "esp_vfs_fat.h" -#include "esp_timer.h" #include "esp_lcd_panel_io.h" #include "esp_lcd_panel_vendor.h" #include "esp_lcd_panel_ops.h" #include "esp_log.h" -#include "esp_lvgl_port.h" +#include "esp_check.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -21,7 +19,10 @@ #include "driver/ledc.h" #include "driver/i2c.h" +#include "bsp/esp32_s3_eye.h" #include "bsp_err_check.h" +#include "bsp/display.h" +#include "esp_lvgl_port.h" static const char *TAG = "S3-EYE"; @@ -179,8 +180,12 @@ esp_err_t bsp_display_backlight_on(void) return bsp_display_brightness_set(100); } -static lv_disp_t *bsp_display_lcd_init(void) +esp_err_t bsp_display_new(esp_lcd_panel_handle_t *ret_panel, esp_lcd_panel_io_handle_t *ret_io) { + esp_err_t ret = ESP_OK; + + ESP_RETURN_ON_ERROR(bsp_display_brightness_init(), TAG, "Brightness init failed"); + ESP_LOGD(TAG, "Initialize SPI bus"); const spi_bus_config_t buscfg = { .sclk_io_num = BSP_LCD_SPI_CLK, @@ -190,10 +195,9 @@ static lv_disp_t *bsp_display_lcd_init(void) .quadhd_io_num = GPIO_NUM_NC, .max_transfer_sz = LVGL_BUFF_SIZE_PIX * sizeof(lv_color_t), }; - BSP_ERROR_CHECK_RETURN_NULL(spi_bus_initialize(BSP_LCD_SPI_NUM, &buscfg, SPI_DMA_CH_AUTO)); + ESP_RETURN_ON_ERROR(spi_bus_initialize(BSP_LCD_SPI_NUM, &buscfg, SPI_DMA_CH_AUTO), TAG, "SPI init failed"); ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_handle_t io_handle = NULL; const esp_lcd_panel_io_spi_config_t io_config = { .dc_gpio_num = BSP_LCD_DC, .cs_gpio_num = BSP_LCD_SPI_CS, @@ -203,21 +207,39 @@ static lv_disp_t *bsp_display_lcd_init(void) .spi_mode = 2, .trans_queue_depth = 10, }; - // Attach the LCD to the SPI bus - BSP_ERROR_CHECK_RETURN_NULL(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)BSP_LCD_SPI_NUM, &io_config, &io_handle)); + ESP_GOTO_ON_ERROR(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)BSP_LCD_SPI_NUM, &io_config, ret_io), err, TAG, "New panel IO failed"); ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_handle_t panel_handle = NULL; const esp_lcd_panel_dev_config_t panel_config = { .reset_gpio_num = BSP_LCD_RST, .color_space = ESP_LCD_COLOR_SPACE_RGB, .bits_per_pixel = 16, }; - BSP_ERROR_CHECK_RETURN_NULL(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle)); + ESP_GOTO_ON_ERROR(esp_lcd_new_panel_st7789(*ret_io, &panel_config, ret_panel), err, TAG, "New panel failed"); + + + esp_lcd_panel_reset(*ret_panel); + esp_lcd_panel_init(*ret_panel); + esp_lcd_panel_invert_color(*ret_panel, true); + return ret; + +err: + if (*ret_panel) { + esp_lcd_panel_del(*ret_panel); + } + if (*ret_io) { + esp_lcd_panel_io_del(*ret_io); + } + spi_bus_free(BSP_LCD_SPI_NUM); + return ret; +} + +static lv_disp_t *bsp_display_lcd_init(void) +{ + esp_lcd_panel_io_handle_t io_handle = NULL; + esp_lcd_panel_handle_t panel_handle = NULL; + BSP_ERROR_CHECK_RETURN_NULL(bsp_display_new(&panel_handle, &io_handle)); - esp_lcd_panel_reset(panel_handle); - esp_lcd_panel_init(panel_handle); - esp_lcd_panel_invert_color(panel_handle, true); #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) esp_lcd_panel_disp_off(panel_handle, false); #else @@ -251,7 +273,6 @@ static lv_disp_t *bsp_display_lcd_init(void) lv_disp_t *bsp_display_start(void) { lv_disp_t *disp = NULL; - BSP_ERROR_CHECK_RETURN_NULL(bsp_display_brightness_init()); const lvgl_port_cfg_t lvgl_cfg = { .task_priority = CONFIG_BSP_DISPLAY_LVGL_TASK_PRIORITY, .task_stack = 4096, diff --git a/esp32_s3_eye/include/bsp/display.h b/esp32_s3_eye/include/bsp/display.h new file mode 100644 index 000000000..ff068ee24 --- /dev/null +++ b/esp32_s3_eye/include/bsp/display.h @@ -0,0 +1,42 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +/** + * @file + * @brief BSP LCD + * + * This file offers API for basic LCD control. + * It is useful for users who want to use the LCD without the default Graphical Library LVGL. + * + * For standard LCD initialization, you can call all-in-one function bsp_display_start(). + */ + +#pragma once +#include "esp_lcd_types.h" + +/** + * @brief Create new display panel + * + * For maximum flexibility, this function performs only reset and initialization of the display. + * You must turn on the display explicitly by calling esp_lcd_panel_disp_on_off(). + * The display's backlight is not turned on either. You can use bsp_display_backlight_on/off(), + * bsp_display_brightness_set() (on supported boards) or implement your own backlight control. + * + * If you want to free resources allocated by this function, you can use esp_lcd API, ie.: + * + * \code{.c} + * esp_lcd_panel_del(panel); + * esp_lcd_panel_io_del(io); + * spi_bus_free(spi_num_from_configuration); + * \endcode + * + * @param[out] ret_panel esp_lcd panel handle + * @param[out] ret_io esp_lcd IO handle + * @return + * - ESP_OK On success + * - Else esp_lcd failure + */ +esp_err_t bsp_display_new(esp_lcd_panel_handle_t *ret_panel, esp_lcd_panel_io_handle_t *ret_io); diff --git a/esp32_s3_korvo_2/CMakeLists.txt b/esp32_s3_korvo_2/CMakeLists.txt index 72b05ca62..a6c5b2ffb 100644 --- a/esp32_s3_korvo_2/CMakeLists.txt +++ b/esp32_s3_korvo_2/CMakeLists.txt @@ -3,5 +3,5 @@ idf_component_register( INCLUDE_DIRS "include" PRIV_INCLUDE_DIRS "priv_include" REQUIRES driver - PRIV_REQUIRES fatfs esp_timer esp_lcd esp_lcd_touch esp_adc + PRIV_REQUIRES fatfs esp_lcd esp_adc ) diff --git a/esp32_s3_korvo_2/esp32_s3_korvo_2.c b/esp32_s3_korvo_2/esp32_s3_korvo_2.c index 46af7c078..12abea994 100644 --- a/esp32_s3_korvo_2/esp32_s3_korvo_2.c +++ b/esp32_s3_korvo_2/esp32_s3_korvo_2.c @@ -4,12 +4,12 @@ * SPDX-License-Identifier: CC0-1.0 */ -#include "esp_timer.h" #include "driver/gpio.h" #include "driver/ledc.h" #include "driver/spi_master.h" #include "esp_err.h" #include "esp_log.h" +#include "esp_check.h" #include "esp_lcd_panel_io.h" #include "esp_lcd_panel_vendor.h" #include "esp_lcd_panel_ops.h" @@ -19,6 +19,7 @@ //#include "esp_adc/adc_cali_scheme.h" #include "bsp/esp32_s3_korvo_2.h" +#include "bsp/display.h" #include "esp_lcd_ili9341.h" #include "esp_io_expander_tca9554.h" #include "esp_lcd_touch_tt21100.h" @@ -189,7 +190,7 @@ esp_err_t bsp_audio_poweramp_enable(bool enable) esp_io_expander_handle_t bsp_io_expander_init(void) { if (io_expander) { - ESP_LOGW(TAG, "io_expander is initialized"); + ESP_LOGD(TAG, "io_expander is initialized"); } else { BSP_ERROR_CHECK_RETURN_NULL(esp_io_expander_new_i2c_tca9554(BSP_I2C_NUM, BSP_IO_EXPANDER_I2C_ADDRESS, &io_expander)); } @@ -201,14 +202,9 @@ esp_io_expander_handle_t bsp_io_expander_init(void) #define LCD_CMD_BITS 8 #define LCD_PARAM_BITS 8 -static lv_disp_t *bsp_display_lcd_init(void) +esp_err_t bsp_display_new(esp_lcd_panel_handle_t *ret_panel, esp_lcd_panel_io_handle_t *ret_io) { - BSP_NULL_CHECK(bsp_io_expander_init(), NULL); - BSP_ERROR_CHECK_RETURN_ERR(esp_io_expander_set_dir(io_expander, BSP_LCD_IO_CS, IO_EXPANDER_OUTPUT)); - BSP_ERROR_CHECK_RETURN_ERR(esp_io_expander_set_dir(io_expander, BSP_LCD_IO_RST, IO_EXPANDER_OUTPUT)); - BSP_ERROR_CHECK_RETURN_ERR(esp_io_expander_set_dir(io_expander, BSP_LCD_IO_BACKLIGHT, IO_EXPANDER_OUTPUT)); - BSP_ERROR_CHECK_RETURN_ERR(esp_io_expander_set_level(io_expander, BSP_LCD_IO_CS, 0)); - + esp_err_t ret = ESP_OK; ESP_LOGD(TAG, "Initialize SPI bus"); const spi_bus_config_t buscfg = { .sclk_io_num = BSP_LCD_PCLK, @@ -218,10 +214,9 @@ static lv_disp_t *bsp_display_lcd_init(void) .quadhd_io_num = GPIO_NUM_NC, .max_transfer_sz = BSP_LCD_H_RES * 80 * sizeof(uint16_t), }; - BSP_ERROR_CHECK_RETURN_NULL(spi_bus_initialize(BSP_LCD_SPI_NUM, &buscfg, SPI_DMA_CH_AUTO)); + ESP_RETURN_ON_ERROR(spi_bus_initialize(BSP_LCD_SPI_NUM, &buscfg, SPI_DMA_CH_AUTO), TAG, "SPI init failed"); ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_handle_t io_handle = NULL; const esp_lcd_panel_io_spi_config_t io_config = { .dc_gpio_num = BSP_LCD_DC, .cs_gpio_num = BSP_LCD_CS, @@ -231,30 +226,52 @@ static lv_disp_t *bsp_display_lcd_init(void) .spi_mode = 0, .trans_queue_depth = 10, }; + ESP_GOTO_ON_ERROR(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)BSP_LCD_SPI_NUM, &io_config, ret_io), err, TAG, "New panel IO failed"); - // Attach the LCD to the SPI bus - BSP_ERROR_CHECK_RETURN_NULL(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)BSP_LCD_SPI_NUM, &io_config, &io_handle)); - - ESP_LOGD(TAG, "Install LCD driver of ILI9341"); - esp_lcd_panel_handle_t panel_handle = NULL; + ESP_LOGD(TAG, "Install LCD driver"); const esp_lcd_panel_dev_config_t panel_config = { .reset_gpio_num = BSP_LCD_RST, // Shared with Touch reset .color_space = ESP_LCD_COLOR_SPACE_BGR, .bits_per_pixel = 16, }; - BSP_ERROR_CHECK_RETURN_NULL(esp_lcd_new_panel_ili9341(io_handle, &panel_config, &panel_handle)); + ESP_GOTO_ON_ERROR(esp_lcd_new_panel_ili9341(*ret_io, &panel_config, ret_panel), err, TAG, "New panel failed"); + + bsp_io_expander_init(); + ESP_GOTO_ON_ERROR(esp_io_expander_set_dir(io_expander, BSP_LCD_IO_CS, IO_EXPANDER_OUTPUT), err, TAG, ""); + ESP_GOTO_ON_ERROR(esp_io_expander_set_dir(io_expander, BSP_LCD_IO_RST, IO_EXPANDER_OUTPUT), err, TAG, ""); + ESP_GOTO_ON_ERROR(esp_io_expander_set_dir(io_expander, BSP_LCD_IO_BACKLIGHT, IO_EXPANDER_OUTPUT), err, TAG, ""); + ESP_GOTO_ON_ERROR(esp_io_expander_set_level(io_expander, BSP_LCD_IO_CS, 0), err, TAG, ""); // Reset LCD - BSP_ERROR_CHECK_RETURN_ERR(esp_io_expander_set_level(io_expander, BSP_LCD_IO_RST, 0)); + ESP_GOTO_ON_ERROR(esp_io_expander_set_level(io_expander, BSP_LCD_IO_RST, 0), err, TAG, ""); vTaskDelay(pdMS_TO_TICKS(10)); - BSP_ERROR_CHECK_RETURN_ERR(esp_io_expander_set_level(io_expander, BSP_LCD_IO_RST, 1)); + ESP_GOTO_ON_ERROR(esp_io_expander_set_level(io_expander, BSP_LCD_IO_RST, 1), err, TAG, ""); vTaskDelay(pdMS_TO_TICKS(10)); // Enable display - BSP_ERROR_CHECK_RETURN_ERR(esp_io_expander_set_level(io_expander, BSP_LCD_IO_CS, 0)); + ESP_GOTO_ON_ERROR(esp_io_expander_set_level(io_expander, BSP_LCD_IO_CS, 0), err, TAG, ""); + + esp_lcd_panel_init(*ret_panel); + esp_lcd_panel_mirror(*ret_panel, true, true); + return ret; + +err: + if (*ret_panel) { + esp_lcd_panel_del(*ret_panel); + } + if (*ret_io) { + esp_lcd_panel_io_del(*ret_io); + } + spi_bus_free(BSP_LCD_SPI_NUM); + return ret; +} + +static lv_disp_t *bsp_display_lcd_init(void) +{ + esp_lcd_panel_io_handle_t io_handle = NULL; + esp_lcd_panel_handle_t panel_handle = NULL; + BSP_ERROR_CHECK_RETURN_NULL(bsp_display_new(&panel_handle, &io_handle)); - esp_lcd_panel_init(panel_handle); - esp_lcd_panel_mirror(panel_handle, true, true); esp_lcd_panel_disp_on_off(panel_handle, true); /* Add LCD screen */ @@ -322,12 +339,14 @@ esp_err_t bsp_display_brightness_set(int brightness_percent) esp_err_t bsp_display_backlight_off(void) { - return bsp_display_brightness_set(0); + BSP_NULL_CHECK(bsp_io_expander_init(), ESP_ERR_INVALID_STATE); + return esp_io_expander_set_level(io_expander, BSP_LCD_IO_BACKLIGHT, 0); } esp_err_t bsp_display_backlight_on(void) { - return bsp_display_brightness_set(100); + BSP_NULL_CHECK(bsp_io_expander_init(), ESP_ERR_INVALID_STATE); + return esp_io_expander_set_level(io_expander, BSP_LCD_IO_BACKLIGHT, 1); } lv_disp_t *bsp_display_start(void) @@ -405,7 +424,7 @@ int bsp_voltage_battery_get(void) esp_err_t bsp_leds_init(void) { - BSP_NULL_CHECK(bsp_io_expander_init(), NULL); + BSP_NULL_CHECK(bsp_io_expander_init(), ESP_ERR_INVALID_STATE); BSP_ERROR_CHECK_RETURN_ERR(esp_io_expander_set_dir(io_expander, BSP_LED_RED, IO_EXPANDER_OUTPUT)); BSP_ERROR_CHECK_RETURN_ERR(esp_io_expander_set_dir(io_expander, BSP_LED_BLUE, IO_EXPANDER_OUTPUT)); BSP_ERROR_CHECK_RETURN_ERR(esp_io_expander_set_level(io_expander, BSP_LED_RED, true)); diff --git a/esp32_s3_korvo_2/include/bsp/display.h b/esp32_s3_korvo_2/include/bsp/display.h new file mode 100644 index 000000000..ff068ee24 --- /dev/null +++ b/esp32_s3_korvo_2/include/bsp/display.h @@ -0,0 +1,42 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +/** + * @file + * @brief BSP LCD + * + * This file offers API for basic LCD control. + * It is useful for users who want to use the LCD without the default Graphical Library LVGL. + * + * For standard LCD initialization, you can call all-in-one function bsp_display_start(). + */ + +#pragma once +#include "esp_lcd_types.h" + +/** + * @brief Create new display panel + * + * For maximum flexibility, this function performs only reset and initialization of the display. + * You must turn on the display explicitly by calling esp_lcd_panel_disp_on_off(). + * The display's backlight is not turned on either. You can use bsp_display_backlight_on/off(), + * bsp_display_brightness_set() (on supported boards) or implement your own backlight control. + * + * If you want to free resources allocated by this function, you can use esp_lcd API, ie.: + * + * \code{.c} + * esp_lcd_panel_del(panel); + * esp_lcd_panel_io_del(io); + * spi_bus_free(spi_num_from_configuration); + * \endcode + * + * @param[out] ret_panel esp_lcd panel handle + * @param[out] ret_io esp_lcd IO handle + * @return + * - ESP_OK On success + * - Else esp_lcd failure + */ +esp_err_t bsp_display_new(esp_lcd_panel_handle_t *ret_panel, esp_lcd_panel_io_handle_t *ret_io); diff --git a/esp32_s3_korvo_2/include/bsp/esp32_s3_korvo_2.h b/esp32_s3_korvo_2/include/bsp/esp32_s3_korvo_2.h index a0c7d923a..fe6b9e8aa 100644 --- a/esp32_s3_korvo_2/include/bsp/esp32_s3_korvo_2.h +++ b/esp32_s3_korvo_2/include/bsp/esp32_s3_korvo_2.h @@ -231,7 +231,7 @@ esp_err_t bsp_audio_poweramp_enable(const bool enable); * * After initialization of I2C, use BSP_I2C_NUM macro when creating I2C devices drivers ie.: * \code{.c} - * es8311_handle_t es8311_dev = es8311_create(BSP_I2C_NUM, ES8311_ADDRRES_0); + * es8311_handle_t es8311_dev = es8311_create(BSP_I2C_NUM, ES8311_ADDRESS_0); * \endcode **************************************************************************************************/ #define BSP_I2C_NUM CONFIG_BSP_I2C_NUM @@ -267,10 +267,11 @@ esp_err_t bsp_i2c_deinit(void); /** * @brief Init IO expander chip TCA9554 * + * @note I2C must be already initialized by bsp_i2c_init() * @note If the device was already initialized, users can also call it to get handle * @note This function will be called in `bsp_display_start()` * - * @return Pointer to device handle or NULL when error occured + * @return Pointer to device handle or NULL when error occurred */ esp_io_expander_handle_t bsp_io_expander_init(void); @@ -412,34 +413,33 @@ void bsp_display_unlock(void); /** * @brief Set display's brightness * - * Brightness is controlled with PWM signal to a pin controling backlight. + * @attention ESP32-S3 Korvo v2 board has backlight control connected through IO expander, so brightness control is not supported. * * @param[in] brightness_percent Brightness in [%] * @return - * - ESP_OK On success - * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_SUPPORTED Always */ esp_err_t bsp_display_brightness_set(int brightness_percent); /** * @brief Turn on display backlight * - * Display must be already initialized by calling bsp_display_start() + * @note I2C must be already initialized by bsp_i2c_init() * * @return * - ESP_OK On success - * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_INVALID_STATE Could not init IO expander */ esp_err_t bsp_display_backlight_on(void); /** * @brief Turn off display backlight * - * Display must be already initialized by calling bsp_display_start() + * @note I2C must be already initialized by bsp_i2c_init() * * @return * - ESP_OK On success - * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_INVALID_STATE Could not init IO expander */ esp_err_t bsp_display_backlight_off(void); @@ -490,9 +490,12 @@ bool bsp_button_get(const bsp_button_t btn); /** * @brief Set LED's GPIOs as output push-pull * + * @note I2C must be already initialized by bsp_i2c_init() + * * @return * - ESP_OK Success - * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_INVALID_STATE Could not init IO expander + * - ESP_ERR_INVALID_ARG Parameter error */ esp_err_t bsp_leds_init(void); diff --git a/esp32_s3_lcd_ev_board/esp32_s3_lcd_ev_board.c b/esp32_s3_lcd_ev_board/esp32_s3_lcd_ev_board.c index 85de56b37..860c7d399 100644 --- a/esp32_s3_lcd_ev_board/esp32_s3_lcd_ev_board.c +++ b/esp32_s3_lcd_ev_board/esp32_s3_lcd_ev_board.c @@ -20,6 +20,7 @@ #include "lvgl.h" #include "bsp/esp32_s3_lcd_ev_board.h" +#include "bsp/display.h" #include "bsp_err_check.h" #include "bsp_sub_board.h" diff --git a/esp32_s3_lcd_ev_board/include/bsp/display.h b/esp32_s3_lcd_ev_board/include/bsp/display.h new file mode 100644 index 000000000..ff068ee24 --- /dev/null +++ b/esp32_s3_lcd_ev_board/include/bsp/display.h @@ -0,0 +1,42 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +/** + * @file + * @brief BSP LCD + * + * This file offers API for basic LCD control. + * It is useful for users who want to use the LCD without the default Graphical Library LVGL. + * + * For standard LCD initialization, you can call all-in-one function bsp_display_start(). + */ + +#pragma once +#include "esp_lcd_types.h" + +/** + * @brief Create new display panel + * + * For maximum flexibility, this function performs only reset and initialization of the display. + * You must turn on the display explicitly by calling esp_lcd_panel_disp_on_off(). + * The display's backlight is not turned on either. You can use bsp_display_backlight_on/off(), + * bsp_display_brightness_set() (on supported boards) or implement your own backlight control. + * + * If you want to free resources allocated by this function, you can use esp_lcd API, ie.: + * + * \code{.c} + * esp_lcd_panel_del(panel); + * esp_lcd_panel_io_del(io); + * spi_bus_free(spi_num_from_configuration); + * \endcode + * + * @param[out] ret_panel esp_lcd panel handle + * @param[out] ret_io esp_lcd IO handle + * @return + * - ESP_OK On success + * - Else esp_lcd failure + */ +esp_err_t bsp_display_new(esp_lcd_panel_handle_t *ret_panel, esp_lcd_panel_io_handle_t *ret_io); diff --git a/esp32_s3_usb_otg/CMakeLists.txt b/esp32_s3_usb_otg/CMakeLists.txt index 1ea545321..9fcd0923d 100644 --- a/esp32_s3_usb_otg/CMakeLists.txt +++ b/esp32_s3_usb_otg/CMakeLists.txt @@ -3,5 +3,5 @@ idf_component_register( INCLUDE_DIRS "include" PRIV_INCLUDE_DIRS "priv_include" REQUIRES driver - PRIV_REQUIRES fatfs esp_lcd esp_timer usb esp_adc + PRIV_REQUIRES fatfs esp_lcd usb esp_adc ) diff --git a/esp32_s3_usb_otg/esp32_s3_usb_otg.c b/esp32_s3_usb_otg/esp32_s3_usb_otg.c index eb7bf2307..9778334bf 100644 --- a/esp32_s3_usb_otg/esp32_s3_usb_otg.c +++ b/esp32_s3_usb_otg/esp32_s3_usb_otg.c @@ -5,15 +5,12 @@ */ #include -#include "bsp/esp32_s3_usb_otg.h" #include "esp_vfs_fat.h" -#include "esp_timer.h" #include "esp_lcd_panel_io.h" #include "esp_lcd_panel_vendor.h" #include "esp_lcd_panel_ops.h" #include "esp_log.h" -#include "esp_lvgl_port.h" -#include "bsp_err_check.h" +#include "esp_check.h" #include "esp_adc/adc_oneshot.h" #include "esp_adc/adc_cali.h" @@ -27,6 +24,11 @@ #include "usb/usb_host.h" +#include "bsp/esp32_s3_usb_otg.h" +#include "bsp/display.h" +#include "esp_lvgl_port.h" +#include "bsp_err_check.h" + static const char *TAG = "USB-OTG"; static TaskHandle_t usb_host_task; // USB Host Library task @@ -164,8 +166,12 @@ esp_err_t bsp_display_backlight_on(void) return bsp_display_brightness_set(100); } -static lv_disp_t *bsp_display_lcd_init(void) +esp_err_t bsp_display_new(esp_lcd_panel_handle_t *ret_panel, esp_lcd_panel_io_handle_t *ret_io) { + esp_err_t ret = ESP_OK; + + ESP_RETURN_ON_ERROR(bsp_display_brightness_init(), TAG, "Brightness init failed"); + ESP_LOGD(TAG, "Initialize SPI bus"); const spi_bus_config_t buscfg = { .sclk_io_num = BSP_LCD_SPI_CLK, @@ -175,10 +181,9 @@ static lv_disp_t *bsp_display_lcd_init(void) .quadhd_io_num = GPIO_NUM_NC, .max_transfer_sz = BSP_LCD_BUFF_SIZE * sizeof(lv_color_t), }; - BSP_ERROR_CHECK_RETURN_NULL(spi_bus_initialize(BSP_LCD_SPI_NUM, &buscfg, SPI_DMA_CH_AUTO)); + ESP_RETURN_ON_ERROR(spi_bus_initialize(BSP_LCD_SPI_NUM, &buscfg, SPI_DMA_CH_AUTO), TAG, "SPI init failed"); ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_handle_t io_handle = NULL; const esp_lcd_panel_io_spi_config_t io_config = { .dc_gpio_num = BSP_LCD_DC, .cs_gpio_num = BSP_LCD_SPI_CS, @@ -188,21 +193,38 @@ static lv_disp_t *bsp_display_lcd_init(void) .spi_mode = 0, .trans_queue_depth = 10, }; - // Attach the LCD to the SPI bus - BSP_ERROR_CHECK_RETURN_NULL(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)BSP_LCD_SPI_NUM, &io_config, &io_handle)); + ESP_GOTO_ON_ERROR(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)BSP_LCD_SPI_NUM, &io_config, ret_io), err, TAG, "New panel IO failed"); ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_handle_t panel_handle = NULL; const esp_lcd_panel_dev_config_t panel_config = { .reset_gpio_num = BSP_LCD_RST, .color_space = ESP_LCD_COLOR_SPACE_RGB, .bits_per_pixel = 16, }; - BSP_ERROR_CHECK_RETURN_NULL(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle)); + ESP_GOTO_ON_ERROR(esp_lcd_new_panel_st7789(*ret_io, &panel_config, ret_panel), err, TAG, "New panel failed"); + + esp_lcd_panel_reset(*ret_panel); + esp_lcd_panel_init(*ret_panel); + esp_lcd_panel_invert_color(*ret_panel, true); + return ret; + +err: + if (*ret_panel) { + esp_lcd_panel_del(*ret_panel); + } + if (*ret_io) { + esp_lcd_panel_io_del(*ret_io); + } + spi_bus_free(BSP_LCD_SPI_NUM); + return ret; +} + +static lv_disp_t *bsp_display_lcd_init(void) +{ + esp_lcd_panel_io_handle_t io_handle = NULL; + esp_lcd_panel_handle_t panel_handle = NULL; + BSP_ERROR_CHECK_RETURN_NULL(bsp_display_new(&panel_handle, &io_handle)); - esp_lcd_panel_reset(panel_handle); - esp_lcd_panel_init(panel_handle); - esp_lcd_panel_invert_color(panel_handle, true); esp_lcd_panel_disp_on_off(panel_handle, true); /* Add LCD screen */ @@ -232,7 +254,6 @@ static lv_disp_t *bsp_display_lcd_init(void) lv_disp_t *bsp_display_start(void) { lv_disp_t *disp = NULL; - BSP_ERROR_CHECK_RETURN_NULL(bsp_display_brightness_init()); const lvgl_port_cfg_t lvgl_cfg = ESP_LVGL_PORT_INIT_CONFIG(); BSP_ERROR_CHECK_RETURN_NULL(lvgl_port_init(&lvgl_cfg)); BSP_NULL_CHECK(disp = bsp_display_lcd_init(), NULL); diff --git a/esp32_s3_usb_otg/include/bsp/display.h b/esp32_s3_usb_otg/include/bsp/display.h new file mode 100644 index 000000000..ff068ee24 --- /dev/null +++ b/esp32_s3_usb_otg/include/bsp/display.h @@ -0,0 +1,42 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +/** + * @file + * @brief BSP LCD + * + * This file offers API for basic LCD control. + * It is useful for users who want to use the LCD without the default Graphical Library LVGL. + * + * For standard LCD initialization, you can call all-in-one function bsp_display_start(). + */ + +#pragma once +#include "esp_lcd_types.h" + +/** + * @brief Create new display panel + * + * For maximum flexibility, this function performs only reset and initialization of the display. + * You must turn on the display explicitly by calling esp_lcd_panel_disp_on_off(). + * The display's backlight is not turned on either. You can use bsp_display_backlight_on/off(), + * bsp_display_brightness_set() (on supported boards) or implement your own backlight control. + * + * If you want to free resources allocated by this function, you can use esp_lcd API, ie.: + * + * \code{.c} + * esp_lcd_panel_del(panel); + * esp_lcd_panel_io_del(io); + * spi_bus_free(spi_num_from_configuration); + * \endcode + * + * @param[out] ret_panel esp_lcd panel handle + * @param[out] ret_io esp_lcd IO handle + * @return + * - ESP_OK On success + * - Else esp_lcd failure + */ +esp_err_t bsp_display_new(esp_lcd_panel_handle_t *ret_panel, esp_lcd_panel_io_handle_t *ret_io); diff --git a/esp_wrover_kit/CMakeLists.txt b/esp_wrover_kit/CMakeLists.txt index 423236ace..174f92596 100644 --- a/esp_wrover_kit/CMakeLists.txt +++ b/esp_wrover_kit/CMakeLists.txt @@ -2,5 +2,5 @@ idf_component_register(SRCS "esp_wrover_kit.c" INCLUDE_DIRS "include" PRIV_INCLUDE_DIRS "priv_include" REQUIRES driver - PRIV_REQUIRES fatfs esp_lcd esp_timer) + PRIV_REQUIRES fatfs esp_lcd) diff --git a/esp_wrover_kit/esp_wrover_kit.c b/esp_wrover_kit/esp_wrover_kit.c index ee1c03b54..8ca2bc12c 100644 --- a/esp_wrover_kit/esp_wrover_kit.c +++ b/esp_wrover_kit/esp_wrover_kit.c @@ -1,22 +1,25 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ #include -#include "bsp/esp_wrover_kit.h" #include "esp_vfs_fat.h" -#include "esp_timer.h" +#include "esp_log.h" +#include "esp_check.h" #include "esp_lcd_panel_io.h" #include "esp_lcd_panel_vendor.h" #include "esp_lcd_panel_ops.h" #include "driver/spi_master.h" #include "driver/ledc.h" -#include "esp_lvgl_port.h" + +#include "bsp/esp_wrover_kit.h" +#include "bsp/display.h" #include "bsp_err_check.h" +#include "esp_lvgl_port.h" -#define TAG "Wrover" +static const char *TAG = "Wrover"; sdmmc_card_t *bsp_sdcard = NULL; // Global uSD card handler @@ -138,8 +141,12 @@ esp_err_t bsp_display_backlight_on(void) return bsp_display_brightness_set(100); } -static lv_disp_t *bsp_display_lcd_init(void) +esp_err_t bsp_display_new(esp_lcd_panel_handle_t *ret_panel, esp_lcd_panel_io_handle_t *ret_io) { + esp_err_t ret = ESP_OK; + + ESP_RETURN_ON_ERROR(bsp_display_brightness_init(), TAG, "Brightness init failed"); + ESP_LOGD(TAG, "Initialize SPI bus"); const spi_bus_config_t buscfg = { .sclk_io_num = BSP_LCD_SPI_CLK, @@ -147,12 +154,11 @@ static lv_disp_t *bsp_display_lcd_init(void) .miso_io_num = BSP_LCD_SPI_MISO, .quadwp_io_num = -1, .quadhd_io_num = -1, - .max_transfer_sz = BSP_LCD_H_RES * 80 * sizeof(uint16_t), + .max_transfer_sz = BSP_LCD_DRAW_BUF_SIZE * sizeof(uint16_t), }; - BSP_ERROR_CHECK_RETURN_NULL(spi_bus_initialize(BSP_LCD_SPI_NUM, &buscfg, SPI_DMA_CH_AUTO)); + ESP_RETURN_ON_ERROR(spi_bus_initialize(BSP_LCD_SPI_NUM, &buscfg, SPI_DMA_CH_AUTO), TAG, "SPI init failed"); ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_handle_t io_handle = NULL; const esp_lcd_panel_io_spi_config_t io_config = { .dc_gpio_num = BSP_LCD_DC, .cs_gpio_num = BSP_LCD_SPI_CS, @@ -162,11 +168,9 @@ static lv_disp_t *bsp_display_lcd_init(void) .spi_mode = 0, .trans_queue_depth = 10, }; - // Attach the LCD to the SPI bus - BSP_ERROR_CHECK_RETURN_NULL(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)BSP_LCD_SPI_NUM, &io_config, &io_handle)); + ESP_GOTO_ON_ERROR(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)BSP_LCD_SPI_NUM, &io_config, ret_io), err, TAG, "New panel IO failed"); ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_handle_t panel_handle = NULL; const esp_lcd_panel_dev_config_t panel_config = { .reset_gpio_num = BSP_LCD_RST, #ifdef CONFIG_BSP_LCD_ILI9341 @@ -176,22 +180,45 @@ static lv_disp_t *bsp_display_lcd_init(void) #endif .bits_per_pixel = 16, }; - BSP_ERROR_CHECK_RETURN_NULL(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle)); + ESP_GOTO_ON_ERROR(esp_lcd_new_panel_st7789(*ret_io, &panel_config, ret_panel), err, TAG, "New panel failed"); - esp_lcd_panel_reset(panel_handle); - esp_lcd_panel_init(panel_handle); + esp_lcd_panel_reset(*ret_panel); + esp_lcd_panel_init(*ret_panel); #ifdef CONFIG_BSP_LCD_ILI9341 - esp_lcd_panel_mirror(panel_handle, true, false); + esp_lcd_panel_mirror(*ret_panel, true, false); #endif + return ret; + +err: + if (*ret_panel) { + esp_lcd_panel_del(*ret_panel); + } + if (*ret_io) { + esp_lcd_panel_io_del(*ret_io); + } + spi_bus_free(BSP_LCD_SPI_NUM); + return ret; +} + +static lv_disp_t *bsp_display_lcd_init(void) +{ + esp_lcd_panel_io_handle_t io_handle = NULL; + esp_lcd_panel_handle_t panel_handle = NULL; + BSP_ERROR_CHECK_RETURN_NULL(bsp_display_new(&panel_handle, &io_handle)); + +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) esp_lcd_panel_disp_off(panel_handle, false); +#else + esp_lcd_panel_disp_on_off(panel_handle, true); +#endif /* Add LCD screen */ ESP_LOGD(TAG, "Add LCD screen"); const lvgl_port_display_cfg_t disp_cfg = { .io_handle = io_handle, .panel_handle = panel_handle, - .buffer_size = BSP_LCD_H_RES * 20, - .double_buffer = true, + .buffer_size = BSP_LCD_DRAW_BUF_SIZE, + .double_buffer = BSP_LCD_DRAW_BUF_DOUBLE, .hres = BSP_LCD_H_RES, .vres = BSP_LCD_V_RES, .monochrome = false, @@ -216,7 +243,6 @@ static lv_disp_t *bsp_display_lcd_init(void) lv_disp_t *bsp_display_start(void) { lv_disp_t *disp = NULL; - BSP_ERROR_CHECK_RETURN_NULL(bsp_display_brightness_init()); const lvgl_port_cfg_t lvgl_cfg = ESP_LVGL_PORT_INIT_CONFIG(); BSP_ERROR_CHECK_RETURN_NULL(lvgl_port_init(&lvgl_cfg)); BSP_NULL_CHECK(disp = bsp_display_lcd_init(), NULL); diff --git a/esp_wrover_kit/include/bsp/display.h b/esp_wrover_kit/include/bsp/display.h new file mode 100644 index 000000000..ff068ee24 --- /dev/null +++ b/esp_wrover_kit/include/bsp/display.h @@ -0,0 +1,42 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +/** + * @file + * @brief BSP LCD + * + * This file offers API for basic LCD control. + * It is useful for users who want to use the LCD without the default Graphical Library LVGL. + * + * For standard LCD initialization, you can call all-in-one function bsp_display_start(). + */ + +#pragma once +#include "esp_lcd_types.h" + +/** + * @brief Create new display panel + * + * For maximum flexibility, this function performs only reset and initialization of the display. + * You must turn on the display explicitly by calling esp_lcd_panel_disp_on_off(). + * The display's backlight is not turned on either. You can use bsp_display_backlight_on/off(), + * bsp_display_brightness_set() (on supported boards) or implement your own backlight control. + * + * If you want to free resources allocated by this function, you can use esp_lcd API, ie.: + * + * \code{.c} + * esp_lcd_panel_del(panel); + * esp_lcd_panel_io_del(io); + * spi_bus_free(spi_num_from_configuration); + * \endcode + * + * @param[out] ret_panel esp_lcd panel handle + * @param[out] ret_io esp_lcd IO handle + * @return + * - ESP_OK On success + * - Else esp_lcd failure + */ +esp_err_t bsp_display_new(esp_lcd_panel_handle_t *ret_panel, esp_lcd_panel_io_handle_t *ret_io); diff --git a/esp_wrover_kit/include/bsp/esp_wrover_kit.h b/esp_wrover_kit/include/bsp/esp_wrover_kit.h index 8bc589f39..0d0631e4a 100644 --- a/esp_wrover_kit/include/bsp/esp_wrover_kit.h +++ b/esp_wrover_kit/include/bsp/esp_wrover_kit.h @@ -157,7 +157,7 @@ bool bsp_button_get(const bsp_button_t btn); * If your colours on the display are distorted, try changing the display type in menuconfig. * * LVGL is used as graphics library. LVGL is NOT thread safe, therefore the user must take LVGL mutex - * by calling bsp_display_lock() before calling and LVGL API (lv_...) and then give the mutex with + * by calling bsp_display_lock() before calling any LVGL API (lv_...) and then give the mutex with * bsp_display_unlock(). * * Display's backlight must be enabled explicitly by calling bsp_display_backlight_on() @@ -166,6 +166,8 @@ bool bsp_button_get(const bsp_button_t btn); #define BSP_LCD_V_RES (320) #define BSP_LCD_PIXEL_CLOCK_HZ (40 * 1000 * 1000) #define BSP_LCD_SPI_NUM (SPI2_HOST) +#define BSP_LCD_DRAW_BUF_SIZE (BSP_LCD_H_RES * 30) +#define BSP_LCD_DRAW_BUF_DOUBLE (1) /** * @brief Initialize display