diff --git a/components/esp_lcd/include/esp_lcd_panel_ssd1306.h b/components/esp_lcd/include/esp_lcd_panel_ssd1306.h new file mode 100644 index 0000000000..387e016523 --- /dev/null +++ b/components/esp_lcd/include/esp_lcd_panel_ssd1306.h @@ -0,0 +1,61 @@ +/* + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "esp_err.h" +#include "esp_lcd_panel_dev.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief SSD1306 configuration structure + * + * To be used as esp_lcd_panel_dev_config_t.vendor_config. + * See esp_lcd_new_panel_ssd1306(). + */ +typedef struct { + /** + * @brief Display's height in pixels (64(default) or 32) + */ + uint8_t height; +} esp_lcd_panel_ssd1306_config_t; + +/** + * @brief Create LCD panel for model SSD1306 + * + * @param[in] io LCD panel IO handle + * @param[in] panel_dev_config general panel device configuration + * @param[out] ret_panel Returned LCD panel handle + * @return + * - ESP_ERR_INVALID_ARG if parameter is invalid + * - ESP_ERR_NO_MEM if out of memory + * - ESP_OK on success + * + * @note The default panel size is 128x64. + * @note Use esp_lcd_panel_ssd1306_config_t to set the correct size. + * Example usage: + * @code {c} + * + * esp_lcd_panel_ssd1306_config_t ssd1306_config = { + * .height = 32 + * }; + * esp_lcd_panel_dev_config_t panel_config = { + * <...> + * .vendor_config = &ssd1306_config + * }; + * + * esp_lcd_panel_handle_t panel_handle = NULL; + * esp_lcd_new_panel_ssd1306(io_handle, &panel_config, &panel_handle); + * @endcode + */ +esp_err_t esp_lcd_new_panel_ssd1306(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); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_lcd/src/esp_lcd_panel_io_i2c_v1.c b/components/esp_lcd/src/esp_lcd_panel_io_i2c_v1.c index ba7731b2dc..3928d81ed9 100644 --- a/components/esp_lcd/src/esp_lcd_panel_io_i2c_v1.c +++ b/components/esp_lcd/src/esp_lcd_panel_io_i2c_v1.c @@ -95,7 +95,7 @@ static esp_err_t panel_io_i2c_register_event_callbacks(esp_lcd_panel_io_handle_t lcd_panel_io_i2c_t *i2c_panel_io = __containerof(io, lcd_panel_io_i2c_t, base); if (i2c_panel_io->on_color_trans_done != NULL) { - ESP_LOGW(TAG, "Callback on_color_trans_done was already set and now it was owerwritten!"); + ESP_LOGW(TAG, "Callback on_color_trans_done was already set and now it was overwritten!"); } i2c_panel_io->on_color_trans_done = cbs->on_color_trans_done; diff --git a/components/esp_lcd/src/esp_lcd_panel_io_i2c_v2.c b/components/esp_lcd/src/esp_lcd_panel_io_i2c_v2.c index fa2c834adc..e8a50d8ee4 100644 --- a/components/esp_lcd/src/esp_lcd_panel_io_i2c_v2.c +++ b/components/esp_lcd/src/esp_lcd_panel_io_i2c_v2.c @@ -106,7 +106,7 @@ static esp_err_t panel_io_i2c_register_event_callbacks(esp_lcd_panel_io_handle_t lcd_panel_io_i2c_t *i2c_panel_io = __containerof(io, lcd_panel_io_i2c_t, base); if (i2c_panel_io->on_color_trans_done != NULL) { - ESP_LOGW(TAG, "Callback on_color_trans_done was already set and now it was owerwritten!"); + ESP_LOGW(TAG, "Callback on_color_trans_done was already set and now it was overwritten!"); } i2c_panel_io->on_color_trans_done = cbs->on_color_trans_done; diff --git a/components/esp_lcd/src/esp_lcd_panel_ssd1306.c b/components/esp_lcd/src/esp_lcd_panel_ssd1306.c index 969163925d..4ccb6710a5 100644 --- a/components/esp_lcd/src/esp_lcd_panel_ssd1306.c +++ b/components/esp_lcd/src/esp_lcd_panel_ssd1306.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 */ @@ -17,7 +17,7 @@ #include "freertos/task.h" #include "esp_lcd_panel_interface.h" #include "esp_lcd_panel_io.h" -#include "esp_lcd_panel_vendor.h" +#include "esp_lcd_panel_ssd1306.h" #include "esp_lcd_panel_ops.h" #include "driver/gpio.h" #include "esp_log.h" @@ -54,21 +54,15 @@ static esp_err_t panel_ssd1306_disp_on_off(esp_lcd_panel_t *panel, bool off); typedef struct { esp_lcd_panel_t base; esp_lcd_panel_io_handle_t io; + uint8_t height; int reset_gpio_num; - bool reset_level; int x_gap; int y_gap; unsigned int bits_per_pixel; + bool reset_level; bool swap_axes; - esp_lcd_panel_ssd1306_config_t vendor; } ssd1306_panel_t; -static esp_lcd_panel_ssd1306_config_t default_ssd1306_config = { - .mux_ratio = 63, - .com_pin_alt = true, - .com_lr_remap = false -}; - esp_err_t esp_lcd_new_panel_ssd1306(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) { #if CONFIG_LCD_ENABLE_DEBUG_LOG @@ -78,6 +72,7 @@ esp_err_t esp_lcd_new_panel_ssd1306(const esp_lcd_panel_io_handle_t io, const es ssd1306_panel_t *ssd1306 = NULL; ESP_GOTO_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); ESP_GOTO_ON_FALSE(panel_dev_config->bits_per_pixel == 1, ESP_ERR_INVALID_ARG, err, TAG, "bpp must be 1"); + esp_lcd_panel_ssd1306_config_t *ssd1306_spec_config = (esp_lcd_panel_ssd1306_config_t *)panel_dev_config->vendor_config; ssd1306 = calloc(1, sizeof(ssd1306_panel_t)); ESP_GOTO_ON_FALSE(ssd1306, ESP_ERR_NO_MEM, err, TAG, "no mem for ssd1306 panel"); @@ -93,10 +88,7 @@ esp_err_t esp_lcd_new_panel_ssd1306(const esp_lcd_panel_io_handle_t io, const es ssd1306->bits_per_pixel = panel_dev_config->bits_per_pixel; ssd1306->reset_gpio_num = panel_dev_config->reset_gpio_num; ssd1306->reset_level = panel_dev_config->flags.reset_active_high; - ssd1306->vendor = - panel_dev_config->vendor_config - ? *(esp_lcd_panel_ssd1306_config_t*)panel_dev_config->vendor_config - : default_ssd1306_config; + ssd1306->height = ssd1306_spec_config ? ssd1306_spec_config->height : 64; ssd1306->base.del = panel_ssd1306_del; ssd1306->base.reset = panel_ssd1306_reset; ssd1306->base.init = panel_ssd1306_init; @@ -153,11 +145,10 @@ static esp_err_t panel_ssd1306_init(esp_lcd_panel_t *panel) esp_lcd_panel_io_handle_t io = ssd1306->io; ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, SSD1306_CMD_SET_MULTIPLEX, (uint8_t[]) { - // set multiplex ratio - ssd1306->vendor.mux_ratio + ssd1306->height - 1 // set multiplex ratio }, 1), TAG, "io tx param SSD1306_CMD_SET_MULTIPLEX failed"); ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, SSD1306_CMD_SET_COMPINS, (uint8_t[1]) { - 0x2 | (ssd1306->vendor.com_pin_alt << 4) | (ssd1306->vendor.com_lr_remap << 5) + ssd1306->height == 64 ? 0x12 : 0x02 // set COM pins hardware configuration }, 1), TAG, "io tx param SSD1306_CMD_SET_COMPINS failed"); ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, SSD1306_CMD_DISP_OFF, NULL, 0), TAG, "io tx param SSD1306_CMD_DISP_OFF failed"); diff --git a/components/esp_lcd/src/esp_lcd_panel_st7789.c b/components/esp_lcd/src/esp_lcd_panel_st7789.c index 76e26fd6da..fc43f91582 100644 --- a/components/esp_lcd/src/esp_lcd_panel_st7789.c +++ b/components/esp_lcd/src/esp_lcd_panel_st7789.c @@ -77,11 +77,11 @@ esp_lcd_new_panel_st7789(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel 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: st7789->madctl_val = 0; break; - case LCD_RGB_ENDIAN_BGR: + case LCD_RGB_ELEMENT_ORDER_BGR: st7789->madctl_val |= LCD_CMD_BGR_BIT; break; default: diff --git a/examples/peripherals/lcd/i2c_oled/main/Kconfig.projbuild b/examples/peripherals/lcd/i2c_oled/main/Kconfig.projbuild index 64101e6c43..f868a52184 100644 --- a/examples/peripherals/lcd/i2c_oled/main/Kconfig.projbuild +++ b/examples/peripherals/lcd/i2c_oled/main/Kconfig.projbuild @@ -13,4 +13,23 @@ menu "Example Configuration" bool "SH1107" endchoice + if EXAMPLE_LCD_CONTROLLER_SSD1306 + choice EXAMPLE_SSD1306_HEIGHT + prompt "SSD1306 Height in pixels" + default EXAMPLE_SSD1306_HEIGHT_64 + help + Height of the display in pixels. a.k.a vertical resolution + + config EXAMPLE_SSD1306_HEIGHT_64 + bool "64" + config EXAMPLE_SSD1306_HEIGHT_32 + bool "32" + endchoice + + config EXAMPLE_SSD1306_HEIGHT + int + default 64 if EXAMPLE_SSD1306_HEIGHT_64 + default 32 if EXAMPLE_SSD1306_HEIGHT_32 + endif + endmenu 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 7947ffd702..0ddc6e7a48 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 @@ -38,7 +38,7 @@ static const char *TAG = "example"; // The pixel number in horizontal and vertical #if CONFIG_EXAMPLE_LCD_CONTROLLER_SSD1306 #define EXAMPLE_LCD_H_RES 128 -#define EXAMPLE_LCD_V_RES 64 +#define EXAMPLE_LCD_V_RES CONFIG_EXAMPLE_SSD1306_HEIGHT #elif CONFIG_EXAMPLE_LCD_CONTROLLER_SH1107 #define EXAMPLE_LCD_H_RES 64 #define EXAMPLE_LCD_V_RES 128 @@ -49,16 +49,6 @@ static const char *TAG = "example"; extern void example_lvgl_demo_ui(lv_disp_t *disp); -/* The LVGL port component calls esp_lcd_panel_draw_bitmap API for send data to the screen. There must be called -lvgl_port_flush_ready(disp) after each transaction to display. The best way is to use on_color_trans_done -callback from esp_lcd IO config structure. In IDF 5.1 and higher, it is solved inside LVGL port component. */ -static bool notify_lvgl_flush_ready(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx) -{ - lv_disp_t * disp = (lv_disp_t *)user_ctx; - lvgl_port_flush_ready(disp); - return false; -} - void app_main(void) { ESP_LOGI(TAG, "Initialize I2C bus"); @@ -90,7 +80,7 @@ void app_main(void) } #endif }; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)I2C_HOST, &io_config, &io_handle)); + ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(I2C_HOST, &io_config, &io_handle)); ESP_LOGI(TAG, "Install SSD1306 panel driver"); esp_lcd_panel_handle_t panel_handle = NULL; @@ -99,14 +89,10 @@ void app_main(void) .reset_gpio_num = EXAMPLE_PIN_NUM_RST, }; #if CONFIG_EXAMPLE_LCD_CONTROLLER_SSD1306 -#if EXAMPLE_LCD_V_RES != 64 esp_lcd_panel_ssd1306_config_t ssd1306_config = { - .mux_ratio = EXAMPLE_LCD_V_RES - 1, - .com_pin_alt = false + .height = EXAMPLE_LCD_V_RES, }; panel_config.vendor_config = &ssd1306_config; -#endif - ESP_ERROR_CHECK(esp_lcd_new_panel_ssd1306(io_handle, &panel_config, &panel_handle)); #elif CONFIG_EXAMPLE_LCD_CONTROLLER_SH1107 ESP_ERROR_CHECK(esp_lcd_new_panel_sh1107(io_handle, &panel_config, &panel_handle)); @@ -139,11 +125,6 @@ void app_main(void) } }; lv_disp_t * disp = lvgl_port_add_disp(&disp_cfg); - /* Register done callback for IO */ - const esp_lcd_panel_io_callbacks_t cbs = { - .on_color_trans_done = notify_lvgl_flush_ready, - }; - esp_lcd_panel_io_register_event_callbacks(io_handle, &cbs, disp); /* Rotation of the screen */ lv_disp_set_rotation(disp, LV_DISP_ROT_NONE);