ST7789 TFT driver tearing problem in horizontal position with ESP32-S3 LVGL

ersinkaralioglu
Posts: 1
Joined: Thu May 23, 2024 12:56 pm

ST7789 TFT driver tearing problem in horizontal position with ESP32-S3 LVGL

Postby ersinkaralioglu » Thu May 23, 2024 1:37 pm

I am driving a 320*240 TFT with ESP32 S3 and ST7789 driver, there is no problem when I drive the screen without rotating the screen. However, when I rotate the screen horizontally with swap and mirror commands, I see a tearing problem on the screen.

/**
*
* 8080 BUS Initialize
*
**/
static lv_disp_draw_buf_t disp_buf; // contains internal graphic buffer(s) called draw buffer(s)
static lv_disp_drv_t disp_drv; // contains callback functions
ESP_LOGI(TAG, "Initialize Intel 8080 bus");
esp_lcd_i80_bus_handle_t i80_bus = NULL;
esp_lcd_i80_bus_config_t bus_config = {
.clk_src = SOC_MOD_CLK_PLL_D2,
.dc_gpio_num = PIN_NUM_DC,
.wr_gpio_num = PIN_NUM_PCLK,
.data_gpio_nums = {
PIN_NUM_DATA0,
PIN_NUM_DATA1,
PIN_NUM_DATA2,
PIN_NUM_DATA3,
PIN_NUM_DATA4,
PIN_NUM_DATA5,
PIN_NUM_DATA6,
PIN_NUM_DATA7,
},
.bus_width = CONFIG_EXAMPLE_LCD_I80_BUS_WIDTH,
.max_transfer_bytes = LCD_H_RES * LCD_V_RES * sizeof(uint16_t),
.psram_trans_align = 64,
.sram_trans_align = 4,



};
ESP_ERROR_CHECK(esp_lcd_new_i80_bus(&bus_config, &i80_bus));
esp_lcd_panel_io_handle_t io_handle = NULL;

esp_lcd_panel_io_i80_config_t io_config = {
.cs_gpio_num = PIN_NUM_CS,
.pclk_hz = LCD_PIXEL_CLOCK_HZ,
.trans_queue_depth = 10,
.dc_levels = {
.dc_idle_level = 0,
.dc_cmd_level = 0,
.dc_dummy_level = 0,
.dc_data_level = 1,

},
.flags = {
.swap_color_bytes = !LV_COLOR_16_SWAP, // Swap can be done in LvGL (default) or DMA

},
.on_color_trans_done = notify_lvgl_flush_ready,
.user_ctx = &disp_drv,
.lcd_cmd_bits = LCD_CMD_BITS,
.lcd_param_bits = LCD_PARAM_BITS,


};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle));

esp_lcd_panel_handle_t panel_handle = NULL;

ESP_LOGI(TAG, "Install LCD driver of st7789");
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = PIN_NUM_RST,
.rgb_endian = LCD_RGB_ENDIAN_RGB,
.bits_per_pixel = 16,



};
ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));

esp_lcd_panel_reset(panel_handle);
esp_lcd_panel_init(panel_handle);
// Set inversion, x/y coordinate order, x/y mirror according to your LCD module spec
// the gap is LCD panel specific, even panels with the same driver IC, can have different gap value
esp_lcd_panel_invert_color(panel_handle, true);
esp_lcd_panel_set_gap(panel_handle, 0, 0);

// user can flush pre-defined pattern to the screen before we turn on the screen or backlight


esp_lcd_panel_swap_xy(panel_handle, true);
esp_lcd_panel_mirror(panel_handle, true,false);


ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));

ESP_LOGI(TAG, "Initialize LVGL library");
lv_init();
//lv_disp_set_rotation(disp, LV_DISP_ROT_90);
// alloc draw buffers used by LVGL
// it's recommended to choose the size of the draw buffer(s) to be at least 1/10 screen sized

lv_color_t *buf1 = NULL;
lv_color_t *buf2 = NULL;
// static lv_color_t buf1[655 * 100];
// static lv_color_t buf2[655 * 100];

buf1 = heap_caps_malloc(LCD_H_RES * LCD_V_RES * sizeof(lv_color_t), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
//
//assert(buf1);
//
buf2 = heap_caps_malloc(LCD_H_RES * LCD_V_RES * sizeof(lv_color_t), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
//
assert(buf2);
ESP_LOGI(TAG, "buf1@%p, buf2@%p", buf1, buf2);
// initialize LVGL draw buffers
lv_disp_draw_buf_init(&disp_buf, buf1, NULL,LCD_H_RES * LCD_V_RES);

ESP_LOGI(TAG, "Register display driver to LVGL");
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = LCD_H_RES;
disp_drv.ver_res = LCD_V_RES;
disp_drv.flush_cb = lvgl_flush_cb;
disp_drv.draw_buf = &disp_buf;
disp_drv.user_data = panel_handle;
disp_drv.full_refresh =1;
disp_drv.sw_rotate = 1;
//disp_drv.rotated = LV_DISP_ROT_90;
//lv_disp_set_rotation(&disp_drv,1);
disp = lv_disp_drv_register(&disp_drv);

ESP_LOGI(TAG, "Install LVGL tick timer");
// Tick interface for LVGL (using esp_timer to generate 2ms periodic event)
const esp_timer_create_args_t lvgl_tick_timer_args = {
.callback = &increase_lvgl_tick,
.name = "lvgl_tick"
};
esp_timer_handle_t lvgl_tick_timer = NULL;
ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, LVGL_TICK_PERIOD_MS * 1000));
Attachments
tearing.jpg
tearing.jpg (9.21 KiB) Viewed 1500 times

ESP_Sprite
Posts: 9775
Joined: Thu Nov 26, 2015 4:08 am

Re: ST7789 TFT driver tearing problem in horizontal position with ESP32-S3 LVGL

Postby ESP_Sprite » Fri May 24, 2024 2:06 am

That can't really be helped. The ST7789 always refreshes the screen in one direction; if you rotate the display, you change how the image is written to the ST7789s internal memory but it will still refresh in the same direction. This leads to very obvious tearing, as you've noticed. Ideally, you'd do the rotation inside the ESP32, either in LVGL or in an intermediate framebuffer, and write the image to the display in portrait format, but I don't think there's software support for that at the moment.

Who is online

Users browsing this forum: Google [Bot] and 89 guests