LVGL and ESP-IDF + ILI9341 wrong

I need the help for using LVGL and ESP-IDF 5

There were many difficulties for me to make it work.

However, I managed to get it to work but the driver is not correct.

Does anyone know what it could be?

What am I doing wrong?

I will post the code, board and details

It works fine on the Arduino, look at the screen and the letters. Perfect screen.

Using the TFT_eSPI library

But in ESP IDF 5 it looks bad and ugly and with the colors changed, instead of blue it becomes green. What’s wrong?

image

Below is the code used with esp idf 5

Main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "esp_err.h"
#include "esp_log.h"

#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "freertos/semphr.h"
#include "freertos/task.h"

#include "driver/gpio.h"
#include "driver/spi_master.h"

#include "esp_lcd_ili9341.h"
#include "esp_lcd_panel_ops.h"
#include "esp_lcd_touch_xpt2046.h"
#include "lvgl.h"
#include "lcd.h"
#include "touch.h"
#include "f_test.h"
#include "ui.h"

#include "hardware.h"
#include "sdkconfig.h"
#define TAG "Main:"

void InitBacklight(void){
        gpio_set_direction(CONFIG_LCD_BACKLIGHT, GPIO_MODE_OUTPUT);
        gpio_set_level(CONFIG_LCD_BACKLIGHT, 1);
}

void lvUpdateTask(void *ptr){
    while (true)    {
        vTaskDelay(pdMS_TO_TICKS(20));
        if (pdTRUE == xSemaphoreTake(xGuiSemaphore, portMAX_DELAY)){
            lv_task_handler();
            printf(".");
            xSemaphoreGive(xGuiSemaphore);
        }
    }
}

void ui_event_Screen(lv_event_t *e){
    lv_event_code_t event_code = lv_event_get_code(e);
    // GuiData_t *gd = (GuiData_t *)lv_event_get_user_data(e);
    if (event_code == LV_EVENT_CLICKED){
        ESP_LOGI(TAG, "clicked");
        // lv_obj_t *object = lv_event_get_target(e);
        // lv_obj_add_flag(object, LV_OBJ_FLAG_HIDDEN);
    }
}

void app_main(void){

        static lv_disp_drv_t disp_drv;
        InitBacklight();

        esp_lcd_panel_handle_t display = InitDisplay(&disp_drv);
        esp_lcd_touch_handle_t touchpanel = InitTouchPanel();

        xGuiSemaphore = xSemaphoreCreateMutex();
        InitLVGL(display, touchpanel, &disp_drv);
        
        ui_init();
        xTaskCreatePinnedToCore(&lvUpdateTask, "lv_update", 8192, NULL, 6, &g_lvgl_task_handle, 1);

}

LCD.C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "esp_err.h"
#include "esp_log.h"

#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "freertos/semphr.h"
#include "freertos/task.h"

#include "driver/gpio.h"
#include "driver/spi_master.h"

#include "esp_lcd_ili9341.h"
#include "esp_lcd_panel_ops.h"
#include "esp_lcd_touch_xpt2046.h"
#include "lvgl.h"
#include "lcd.h"
#include "hardware.h"
#include "sdkconfig.h"


#define CONFIG_LCD_HRES     240
#define CONFIG_LCD_VRES     320
#define CONFIG_LCD_BUF_SIZE (CONFIG_LCD_HRES * 90)

SemaphoreHandle_t xGuiSemaphore = NULL;
TaskHandle_t g_lvgl_task_handle = NULL;

void lvgl_acquire(void);
void lvgl_release(void);

static bool lvgl_notify_flush_ready(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx){
        lv_disp_drv_t *disp_driver = (lv_disp_drv_t *)user_ctx;
        lv_disp_flush_ready(disp_driver);
        return false;
}

esp_lcd_panel_handle_t InitDisplay(lv_disp_drv_t *disp_drv){
            
            esp_lcd_panel_io_handle_t lcd_io_handle = NULL;
            esp_lcd_panel_handle_t lcd_panel = NULL;

            esp_lcd_panel_io_spi_config_t lcd_io_config = { 
                .cs_gpio_num = (gpio_num_t)CONFIG_LCD_CS,
                .dc_gpio_num = CONFIG_LCD_DC,
                .spi_mode = 0,
                .pclk_hz = CONFIG_LCD_PIXEL_CLOCK_HZ,
                .trans_queue_depth = 3,
                .on_color_trans_done = lvgl_notify_flush_ready,
                .user_ctx = disp_drv,
                .lcd_cmd_bits = CONFIG_LCD_CMD_BITS,
                .lcd_param_bits = CONFIG_LCD_PARAM_BITS,
                .flags = { .dc_low_on_data = 0, .octal_mode = 0, .sio_mode = 0, .lsb_first = 0, .cs_high_active = 0 } };

            const spi_bus_config_t lcd_spi_buscfg = { 
                .mosi_io_num = CONFIG_LCD_SPI_MOSI,
                .miso_io_num = CONFIG_LCD_SPI_MISO,
                .sclk_io_num = CONFIG_LCD_SPI_CLK,
                .quadwp_io_num = GPIO_NUM_NC,
                .quadhd_io_num = GPIO_NUM_NC,
                .data4_io_num = GPIO_NUM_NC,
                .data5_io_num = GPIO_NUM_NC,
                .data6_io_num = GPIO_NUM_NC,
                .data7_io_num = GPIO_NUM_NC,
                .max_transfer_sz = CONFIG_LCD_BUF_SIZE * sizeof(uint16_t),
                .flags = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_GPIO_PINS,
                //.intr_flags = ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM 
                };

            const esp_lcd_panel_dev_config_t lcd_panel_devcfg
                = { 
                    .reset_gpio_num = GPIO_NUM_NC, 
                    .rgb_endian = LCD_RGB_ENDIAN_RGB, 
                    //.rgb_endian = LCD_RGB_ENDIAN_BGR,
                    .bits_per_pixel = 16, 
                    .flags = { 
                        .reset_active_high = 1 }, 
                        .vendor_config = NULL 
                };

            ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_LCD_SPI, &lcd_spi_buscfg, SPI_DMA_CH_AUTO));
            ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)CONFIG_LCD_SPI, &lcd_io_config, &lcd_io_handle));
            ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(lcd_io_handle, &lcd_panel_devcfg, &lcd_panel));
            ESP_ERROR_CHECK(esp_lcd_panel_reset(lcd_panel));
            ESP_ERROR_CHECK(esp_lcd_panel_init(lcd_panel));
            
            esp_lcd_panel_swap_xy(lcd_panel, false);
            esp_lcd_panel_mirror(lcd_panel, true, false);

            
            ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(lcd_panel, true));
            

            return lcd_panel;
}

void lvgl_acquire(void){
        TaskHandle_t task = xTaskGetCurrentTaskHandle();
        if (g_lvgl_task_handle != task){
            xSemaphoreTake(xGuiSemaphore, portMAX_DELAY);
        }
}

void lvgl_release(void){
        TaskHandle_t task = xTaskGetCurrentTaskHandle();
        if (g_lvgl_task_handle != task){
            xSemaphoreGive(xGuiSemaphore);
        }
}

void lcd_lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map) {
    esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t)drv->user_data;
    int32_t offsetx1 = area->x1;
    int32_t offsetx2 = area->x2;
    int32_t offsety1 = area->y1;
    int32_t offsety2 = area->y2;
    esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, color_map);
    lv_disp_flush_ready(drv);
}


static void lvgl_touch_cb(lv_indev_drv_t *drv, lv_indev_data_t *data){
        uint16_t touchpad_x[1] = { 0 };
        uint16_t touchpad_y[1] = { 0 };
        uint8_t touchpad_cnt = 0;
        esp_lcd_touch_read_data((esp_lcd_touch_handle_t)drv->user_data);
        bool touchpad_pressed = esp_lcd_touch_get_coordinates((esp_lcd_touch_handle_t)drv->user_data, touchpad_x, touchpad_y, NULL, &touchpad_cnt, 1);
        if (touchpad_pressed && touchpad_cnt > 0){
            data->point.x = touchpad_x[0];
            data->point.y = touchpad_y[0];
            data->state = LV_INDEV_STATE_PRESSED;
        }else{
            data->state = LV_INDEV_STATE_RELEASED;
        }
}

void InitLVGL(esp_lcd_panel_handle_t panel_handle, esp_lcd_touch_handle_t touch_handle, lv_disp_drv_t *disp_drv){
        static lv_disp_draw_buf_t disp_buf;
        lv_init();
        static lv_color_t buf1[CONFIG_LCD_BUF_SIZE];
        static lv_color_t buf2[CONFIG_LCD_BUF_SIZE];
        lv_disp_draw_buf_init(&disp_buf, buf1, buf2, CONFIG_LCD_BUF_SIZE);
        lv_disp_drv_init(disp_drv);
        disp_drv->hor_res = CONFIG_LCD_HRES;
        disp_drv->ver_res = CONFIG_LCD_VRES;
        disp_drv->flush_cb = lcd_lvgl_flush_cb;
        disp_drv->draw_buf = &disp_buf;
        disp_drv->user_data = panel_handle;
        lv_disp_t *disp = lv_disp_drv_register(disp_drv);
        static lv_indev_drv_t indev_drv; // Input device driver (Touch)
        lv_indev_drv_init(&indev_drv);
        indev_drv.type = LV_INDEV_TYPE_POINTER;
        indev_drv.disp = disp;
        indev_drv.read_cb = lvgl_touch_cb;
        indev_drv.user_data = touch_handle;
        lv_indev_drv_register(&indev_drv);
}

Hardware.h

#pragma once


//#define CONFIG_LCD_PIXEL_CLOCK_HZ (40 * 1000 * 1000)
#define CONFIG_LCD_PIXEL_CLOCK_HZ (80000000)

#define CONFIG_LCD_CMD_BITS       (8)
#define CONFIG_LCD_PARAM_BITS     (8)

#define CONFIG_LCD_SPI            SPI2_HOST
#define CONFIG_LCD_BACKLIGHT      (gpio_num_t) GPIO_NUM_27
#define CONFIG_LCD_SPI_CLK        (gpio_num_t) GPIO_NUM_14
#define CONFIG_LCD_SPI_MOSI       (gpio_num_t) GPIO_NUM_13
#define CONFIG_LCD_SPI_MISO       (gpio_num_t) GPIO_NUM_12
#define CONFIG_LCD_DC             (gpio_num_t) GPIO_NUM_2
#define CONFIG_LCD_CS             (gpio_num_t) GPIO_NUM_15
#define CONFIG_LCD_RESET          (gpio_num_t) GPIO_NUM_NC /* GPIO_NUM_4 */
#define CONFIG_LCD_BUSY           (gpio_num_t) GPIO_NUM_NC /* GPIO_NUM_35 */



//#define CONFIG_TOUCH_CLOCK_HZ ESP_LCD_TOUCH_SPI_CLOCK_HZ
#define CONFIG_TOUCH_CLOCK_HZ 2500000
#define CONFIG_TOUCH_SPI      SPI2_HOST
// #define CONFIG_TOUCH_SPI_CLK  (gpio_num_t) GPIO_NUM_25
// #define CONFIG_TOUCH_SPI_MOSI (gpio_num_t) GPIO_NUM_32
// #define CONFIG_TOUCH_SPI_MISO (gpio_num_t) GPIO_NUM_39
#define CONFIG_TOUCH_CS       (gpio_num_t) GPIO_NUM_33
#define CONFIG_TOUCH_DC       (gpio_num_t) GPIO_NUM_NC
#define CONFIG_TOUCH_RST      (gpio_num_t) GPIO_NUM_NC
#define CONFIG_TOUCH_IRQ      (gpio_num_t) GPIO_NUM_36 /* GPIO_NUM_36 */

#define TOUCH_X_RES_MIN 17
#define TOUCH_X_RES_MAX 291

#define TOUCH_Y_RES_MIN 15
#define TOUCH_Y_RES_MAX 218

where am I going wrong?

What can I change?

Hello,

Looks like a classic case of your RGB values needing to be swapped.
See this post for example: Lv_draw_sw_rgb565_swap - #2 by yuri-ncs

1 Like

I agree, that’s probably the issue. We have also added support for LV_COLOR_16_SWAP for backward compatibility.

1 Like

Hey, any good news?

I Solved!!

@kisvegabor Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks, Thanks,

3 Likes

You are welcome :smiley: