espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.33k stars 7.2k forks source link

SSD1309 on SPI bus (IDFGH-9249) #10635

Closed DmytroKoval closed 8 months ago

DmytroKoval commented 1 year ago

Answers checklist.

IDF version.

esp-idf-v5.0

Operating System used.

Windows

How did you build your project?

Command line with idf.py

If you are using Windows, please specify command line type.

PowerShell

Development Kit.

ESP-WROOM32

Power Supply used.

USB

What is the expected behavior?

I tried to use ESP-IDF 5.0 LED driver + LVGL with SSD1309 OLED connected via SPI. As a code base an I2C OLED example for SSD1306 display was taken. SSD1306 and SSD1309 are compatible at command level. I changed I2C bus/io config to SPI. Sample initialization code is shown below.

    ESP_LOGI(TAG, "Initialize SPI bus");
    spi_bus_config_t buscfg = {
        .sclk_io_num = EXAMPLE_PIN_NUM_SCL,
        .mosi_io_num = EXAMPLE_PIN_NUM_SDA,
        .miso_io_num = -1,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1,
        .max_transfer_sz = EXAMPLE_LCD_H_RES * 80 * sizeof(uint16_t),
    };
    ESP_ERROR_CHECK(spi_bus_initialize(LCD_HOST, &buscfg, SPI_DMA_CH_AUTO));

    ESP_LOGI(TAG, "Install panel IO");
    esp_lcd_panel_io_handle_t io_handle = NULL;
    esp_lcd_panel_io_spi_config_t io_config = {
        .dc_gpio_num = EXAMPLE_PIN_NUM_LCD_DC,
        .cs_gpio_num = EXAMPLE_PIN_NUM_LCD_CS,
        .pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ,
        .lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS,
        .lcd_param_bits = EXAMPLE_LCD_PARAM_BITS,
        .spi_mode = 0,
        .trans_queue_depth = 10,
        .on_color_trans_done = example_notify_lvgl_flush_ready,
        .user_ctx = &disp_drv,
    };
    // Attach the LCD to the SPI bus
    ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_HOST, &io_config, &io_handle));

    ESP_LOGI(TAG, "Install SSD1309 panel driver");
    esp_lcd_panel_handle_t panel_handle = NULL;
    esp_lcd_panel_dev_config_t panel_config = {
        .reset_gpio_num = EXAMPLE_PIN_NUM_LCD_RST,
        .bits_per_pixel = 1,
    };

    ESP_ERROR_CHECK(esp_lcd_new_panel_ssd1306(io_handle, &panel_config, &panel_handle));

    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));

After 3 last lines of code display should have being initialized.

What is the actual behavior?

After 3 last lines of code shown above display is filled with noisy pixels with no other output.

Steps to reproduce.

  1. Connect SSD1309 128x64 monochrome OLED display to ESP32 via 3- or 4-line SPI
  2. Try to initialize it using esp_lcd component
  3. Osberve pixel noise at the display output

Debug Logs.

No response

More Information.

After investigation I found function static esp_err_t panel_io_spi_tx_param(esp_lcd_panel_io_t io, int lcd_cmd, const void param, size_t param_size) at components/esp_lcd/src/esp_lcd_panel_io_spi.c which transmits data/commands via SPI. I noticed, that it inverts D/C line before command parameter transmission (this line). But according to SSD1309 datasheet D/C line should be held at low level (command mode) during transmission of command parameters, and it is stated in both SSD1306 and SSD1309 datasheets.

suda-morris commented 1 year ago

@DmytroKoval Thanks for reporting! Looks like SSD13xx OLED LCD SPI mode is a little different from other LCD screens like ST7789, where the DC level will turn high when transmitting parameters.

We will consider to make that configurable in the esp_lcd_panel_io_spi_config_t structure. e.g. by introducing a new flag dc_high_on_param

DmytroKoval commented 1 year ago

@DmytroKoval Thanks for reporting! Looks like SSD13xx OLED LCD SPI mode is a little different from other LCD screens like ST7789, where the DC level will turn high when transmitting parameters. We will consider to make that configurable in the esp_lcd_panel_io_spi_config_t structure. e.g. by introducing a new flag dc_high_on_param

That's smart, because SSD1322 and 1351 (for example, I didn't check all product line) require D/C high on parameter transmission.

Good luck with update!

kscz commented 8 months ago

Any chance this might be resolved before the 5.2 release? I can make the pull request if it would help

suda-morris commented 8 months ago

Thanks for the contribution. After the PR gets merged to the master branch, we will backport it to release/v5.2 for sure. @kscz