Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSD1306 128x32 display garbled (IDFGH-13950) #14784

Closed
mutatrum opened this issue Oct 25, 2024 · 6 comments
Closed

SSD1306 128x32 display garbled (IDFGH-13950) #14784

mutatrum opened this issue Oct 25, 2024 · 6 comments
Labels
Status: Opened Issue is new Type: Bug bugs in IDF

Comments

@mutatrum
Copy link

mutatrum commented Oct 25, 2024

IDF version.

v5.3.1

Espressif SoC revision.

ESP32-S3

Operating System used.

Linux

How did you build your project?

VS Code

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

None

Development Kit.

ESP32-S3-WROOM-1

Power Supply used.

USB

What is the expected behavior?

Pixels shown on display

What is the actual behavior?

Garbled pixels on display

Steps to reproduce.

Add lvgl and lvg_esp_ports dependency, follow i2c_oled_example_main as close as possible.

Display does initialize, LVGL is initialized, but the pixels show up garbled.

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_timer.h"
#include "esp_lcd_panel_io.h"
#include "esp_lcd_panel_ops.h"
#include "esp_err.h"
#include "esp_log.h"
#include "lvgl.h"
#include "esp_lvgl_port.h"
#include "i2c_bitaxe.h"
#include "driver/i2c_master.h"
#include "driver/i2c_types.h"
#include "esp_lcd_panel_ssd1306.h"

// #define EXAMPLE_LCD_PIXEL_CLOCK_HZ    (400 * 1000)
#define EXAMPLE_I2C_HW_ADDR           0x3C

// The pixel number in horizontal and vertical
#define EXAMPLE_LCD_H_RES              128
#define EXAMPLE_LCD_V_RES              32
#define EXAMPLE_LCD_CMD_BITS           8
#define EXAMPLE_LCD_PARAM_BITS         8

#define I2C_HOST  0

static const char * TAG = "display";

static i2c_master_bus_handle_t i2c_bus_handle;

void example_lvgl_demo_ui()
{
    lv_obj_t *scr = lv_scr_act();

    lv_obj_t *label = lv_label_create(scr);
    lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR); /* Circular scroll */
    lv_label_set_text(label, "Hello Bitaxe, Hello LVGL.");
    /* Size of the screen (if you use rotation 90 or 270, please set disp->driver->ver_res) */
    lv_obj_set_width(label, EXAMPLE_LCD_H_RES);
    lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 0);
}

esp_err_t display_init(void)
{
    // i2c bus is created elsewhere
    i2c_bitaxe_get_bus(&i2c_bus_handle);

    ESP_LOGI(TAG, "Install panel IO");
    esp_lcd_panel_io_handle_t io_handle = NULL;
    esp_lcd_panel_io_i2c_config_t io_config = {
        .scl_speed_hz = 100000, // TODO: get value from constant in i2c_bitaxe.c
        .dev_addr = EXAMPLE_I2C_HW_ADDR,
        .control_phase_bytes = 1,
        .lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS,
        .lcd_param_bits = EXAMPLE_LCD_PARAM_BITS,
        .dc_bit_offset = 6                     
    };
    
    ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus_handle, &io_config, &io_handle));

    ESP_LOGI(TAG, "Install SSD1306 panel driver");
    esp_lcd_panel_handle_t panel_handle = NULL;
    esp_lcd_panel_dev_config_t panel_config = {
        .bits_per_pixel = 1,
        .reset_gpio_num = -1,
        .color_space = ESP_LCD_COLOR_SPACE_MONOCHROME,
    };

    esp_lcd_panel_ssd1306_config_t ssd1306_config = {
        .height = EXAMPLE_LCD_V_RES,
    };
    panel_config.vendor_config = &ssd1306_config;

    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_swap_xy(panel_handle, false));
    ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, true, true));
    ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));

    ESP_LOGI(TAG, "Initialize LVGL");
    const lvgl_port_cfg_t lvgl_cfg = ESP_LVGL_PORT_INIT_CONFIG();
    lvgl_port_init(&lvgl_cfg);

    const lvgl_port_display_cfg_t disp_cfg = {
        .io_handle = io_handle,
        .panel_handle = panel_handle,
        .buffer_size = EXAMPLE_LCD_H_RES * EXAMPLE_LCD_V_RES,
        .double_buffer = true,
        .hres = EXAMPLE_LCD_H_RES,
        .vres = EXAMPLE_LCD_V_RES,
        .monochrome = true,
        .rotation = {
            .swap_xy = false,
            .mirror_x = true,
            .mirror_y = true,
        }
    };
    lv_disp_t *disp = lvgl_port_add_disp(&disp_cfg);

    ESP_LOGI(TAG, "Display LVGL Scroll Text");
    // Lock the mutex due to the LVGL APIs are not thread-safe
    if (lvgl_port_lock(0)) {
        lv_disp_set_rotation(disp, LV_DISPLAY_ROTATION_180);
        example_lvgl_demo_ui(disp);
        // Release the mutex
        lvgl_port_unlock();
    }

    return ESP_OK;
}

Debug Logs.

No response

More Information.

Picture:
image
the pixels are actually moving, garbled from left to right, which I assume should be the scrolling label text. The bottom line is flickering on and off.

The screen used is a 0.91" SSD1306 OLED I2C Display Module

@mutatrum mutatrum added the Type: Bug bugs in IDF label Oct 25, 2024
@github-actions github-actions bot changed the title SSD1306 128x32 display garbled SSD1306 128x32 display garbled (IDFGH-13950) Oct 25, 2024
@espressif-bot espressif-bot added the Status: Opened Issue is new label Oct 25, 2024
@atanisoft
Copy link

This looks like a bug in the driver code, can you try adjusting this line to use width instead of height?

@mutatrum
Copy link
Author

mutatrum commented Oct 26, 2024

With that change the noise looks slightly different, a bit more spread out, but otherwise identical.

I have a hunch it's in the i2c layer itself, as even if I mimic the initialisation from the current (working) device-purpose SSD1306 driver, it shows exactly the same noise. See this code: https://github.com/skot/ESP-Miner/blob/35855358ada2af5710302cfdc06f4eb05fb1080f/main/oled.c#L40

A short clip to show what I mean, this is without your code change:
https://github.com/user-attachments/assets/673c41a4-72fd-44b8-a954-c1e44290b31e

It's as if there are random pixels missing whenever the buffer is sent over to the display. So part of the data is there, it's roughtly in the right spot, and it doesn't cover the whole screen.

It's clear there is something scrolling from left to right, and the bottom 1/3rd is garbled noise going back and forth between two frames, which corresponds to the double buffering.

I will test the example code as a clean project, to see if any other code in my codebase is interfering, but that will be tomorrow.

@atanisoft
Copy link

That is very odd, I'd also wonder if it might be something in the LVGL side that is interfering somehow. I've not used LVGL on the SSD1306 but have used basic text output (and supporting SH1106 which is nearly identical code), you can read my init script here, it leverages the older I2C APIs to build a large I2C transfer to configure the display in a single shot.

The height / width issue is still a bug though, from the references I've seen it should be width in that config field.

@mutatrum
Copy link
Author

To verify the i2c code, I made a direct call to esp_lcd_panel_draw_bitmap after the initialisation, and drew a buffer with increasing byte pattern:

image

It also showed that horizontal addressing is supported by this display, the pattern is visibly different if I change it to vertical or paging.

So it looks like it's somewhere in the LVGL part indeed.

@mutatrum
Copy link
Author

mutatrum commented Oct 27, 2024

Addendum: running the i2c_oled_example code works on the target hardware, at least with LVGL 8!

If I build the example project with LVGL 9.2 and fix the compiler warnings, it first triggers a WDT when calling lv_disp_set_rotation. I had the same issue when I added the code to my project.

If I move the set_rotation call into the LVGL lock in the main, the example runs but shows similar noisy garbage on the display. So something broke when going from LVGL 8 to 9.2.

I can't test with 9.0 or 9.1, due to monochrome displays not being supported yet? https://forum.lvgl.io/t/how-to-configure-lvgl-9-for-monochrome-displays/16944

Not sure if the ticket is on the correct repo btw, as lvg_esp_port is part of espressif/esp-bsp.

Furthermore, I tested my own project with LVGL 8.4, and that also works!

@mutatrum
Copy link
Author

Duplicate of espressif/esp-bsp#392

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Opened Issue is new Type: Bug bugs in IDF
Projects
None yet
Development

No branches or pull requests

3 participants