ILI9488 display issues using ESP32S3 parallel 3.5 touch

There could be a syntax error in the change I made. C is not my first language so I don’t remember 100% of the syntax. so you may have to fix it.

the assertion error was stemming from the flush function

specifically this

offsetx2 + 1, offsety2 + 1

it is adding a 1 to the width and height which makes the “color_size” larger. So I offset it by adding that additional row/column (whichever is larger) to the transfer size… Not a biggie to do. I forgot the flush function adds to the width and height.

1 Like

Ok, i just uploaded the new file, but I will have to re run C-make and rebuild the project(1000ish files) so it will take a second on this dinosaur of a laptop. I appreciate your help, I will let you know the results once I have it compiled/built

Edit: at most it will take 20-30 minutes… at most

1 Like

You may not need to use that offset I added to the code if you have the buffer sizes set properly. Take a look at the changes I made I am sure you will see where the problem was once you look at it.

chances are you can use the attached source file and it will also work.

esp32_s3.c (8.9 KB)

1 Like

If my main PC didn’t go down I would have let you compile using it. Threadripper pro with 32 logical processors with 128GB of RAM. I can compile LVGL in about 10 seconds. Power Supply went to shit on me, I am waiting for the new one from SuperMicro. They are dragging their feet getting me this thing and it starting to get me annoyed. It’s been a week already and they haven’t even shipped it yet.

I want to note that this :

size_t buffer_size = (((BSP_LCD_H_RES) * (BSP_LCD_V_RES) / 10 ) * sizeof(uint16_t);
esp_lcd_new_panel_ili9488(io_handle, &panel_config, buffer_size, &panel_handle);

does not really matter. Since it is 16 bit, the buffer_size is ignored. This is noted here:

NOTE: For parallel IO (Intel 8080) interface 16-bit color mode should
be used and @param buffer_size will be ignored.

OK I see where it is irrelevant in the component for the display. just pass a zero as the parameter then.

Hmmm… curious as to what your problem is.

1 Like

unfortunately that did not work :frowning: this is the output


I am completely defeated at this point… I’ve been at this for two weeks haha. Losing sanity quickly

1 Like

it’s the compiling that is killin ya.

as in compiling time? yes, it doesn’t help that everytime i have to clean/build or change Cmake it takes about an hour

what OS are you running?

I am working on rewriting this thing so you don’t have that additional lvgl_port layer. what I did not care for is the config structures being local variables and not global. without going digging in the IDF to check and see if copies of the structures are being made or if it is using pointers it is easier to just make them global to ensure they are available after the function exits.

also what is the display you are using? what brand and model?

1 Like

Maybe better is try run display firstly on Arduino + tested libs for first i recom ArduinoGFX. When this work ok go around.
This port is as 2month baby…

this is the device: ESP32-S3 Parallel TFT with Touch 3.5'' ILI9488 | Makerfabs Uses a ili9488 lcd driver. I am using windows 10 OS. I have already got it working using LGFX in both arduino and vscode + extention. I am just trying to make a board so I can upload it to squareline without using LGFX library.

edit: I am somewhat modeling the library after: esp-bsp/SquareLine/boards/custom_waveshare_7inch at master · espressif/esp-bsp · GitHub, but I have changed virtually everything about it at this point, such as pins and drivers, just using this structure so I can export it to squareline

1 Like

I have already attempted that, I might have missed something tho so here is my code that I created :

/*
 * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: CC0-1.0
 */

#include "esp_log.h"
#include "bsp/esp32_s3.h"
#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_vendor.h"
#include "esp_lcd_panel_ops.h"
#include "driver/gpio.h"
#include "esp_err.h"
#include "lvgl.h"
#include "esp_lcd_touch_ft5x06.h"
#include "esp_lcd_ili9488.h"
//#include "ui/ui.h"
#include "../ui.h"


#define TAG "ESP-EXAMPLE"

/*******************************************************************************
* Private functions
*******************************************************************************/

// *INDENT-OFF*
void app_lvgl_display(void)
{

    ui_init();

}
#define EXAMPLE_LCD_PIXEL_CLOCK_HZ     (20 * 1000 * 1000)
#define EXAMPLE_LCD_BK_LIGHT_ON_LEVEL  1
#define EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL !EXAMPLE_LCD_BK_LIGHT_ON_LEVEL
#define EXAMPLE_PIN_NUM_DATA0          47 // 47? or 33 
#define EXAMPLE_PIN_NUM_DATA1          21
#define EXAMPLE_PIN_NUM_DATA2          14
#define EXAMPLE_PIN_NUM_DATA3          13
#define EXAMPLE_PIN_NUM_DATA4          12
#define EXAMPLE_PIN_NUM_DATA5          11
#define EXAMPLE_PIN_NUM_DATA6          10
#define EXAMPLE_PIN_NUM_DATA7          9
#define EXAMPLE_PIN_NUM_DATA8          3
#define EXAMPLE_PIN_NUM_DATA9          8
#define EXAMPLE_PIN_NUM_DATA10         16
#define EXAMPLE_PIN_NUM_DATA11         15
#define EXAMPLE_PIN_NUM_DATA12         7
#define EXAMPLE_PIN_NUM_DATA13         6
#define EXAMPLE_PIN_NUM_DATA14         5
#define EXAMPLE_PIN_NUM_DATA15         4
#define EXAMPLE_PIN_NUM_PCLK           35
#define EXAMPLE_PIN_NUM_CS             37
#define EXAMPLE_PIN_NUM_DC             36
#define EXAMPLE_PIN_NUM_RST            -1
#define EXAMPLE_PIN_NUM_BK_LIGHT       45

// The pixel number in horizontal and vertical
#define EXAMPLE_LCD_H_RES              320
#define EXAMPLE_LCD_V_RES              480

#define EXAMPLE_LCD_CMD_BITS           8
#define EXAMPLE_LCD_PARAM_BITS         8

#define EXAMPLE_I2C_NUM                 0   // I2C number
#define EXAMPLE_I2C_SCL                 39
#define EXAMPLE_I2C_SDA                 38

#define EXAMPLE_LVGL_TICK_PERIOD_MS    2

// Supported alignment: 16, 32, 64. A higher alignment can enables higher burst transfer size, thus a higher i80 bus throughput.
#define EXAMPLE_PSRAM_DATA_ALIGNMENT   64


static bool example_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_drv_t *disp_driver = (lv_disp_drv_t *)user_ctx;
    lv_disp_flush_ready(disp_driver);
    return false;
}

static void example_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;
    int offsetx1 = area->x1;
    int offsetx2 = area->x2;
    int offsety1 = area->y1;
    int offsety2 = area->y2;
    // copy a buffer's content to a specific area of the display
    esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, color_map);
}


static void example_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;

    /* Read touch controller data */
    esp_lcd_touch_read_data(drv->user_data);

    /* Get coordinates */
    bool touchpad_pressed = esp_lcd_touch_get_coordinates(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;
    }
}


static void example_increase_lvgl_tick(void *arg)
{
    /* Tell LVGL how many milliseconds has elapsed */
    lv_tick_inc(EXAMPLE_LVGL_TICK_PERIOD_MS);
}


void app_main(void)
{
    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, "Turn off LCD backlight");
    gpio_config_t bk_gpio_config = {
        .mode = GPIO_MODE_OUTPUT,
        .pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_BK_LIGHT
    };
    ESP_ERROR_CHECK(gpio_config(&bk_gpio_config));
    gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL);

     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 = LCD_CLK_SRC_DEFAULT,
        .dc_gpio_num = EXAMPLE_PIN_NUM_DC,
        .wr_gpio_num = EXAMPLE_PIN_NUM_PCLK,
        .data_gpio_nums = {
            EXAMPLE_PIN_NUM_DATA0,
            EXAMPLE_PIN_NUM_DATA1,
            EXAMPLE_PIN_NUM_DATA2,
            EXAMPLE_PIN_NUM_DATA3,
            EXAMPLE_PIN_NUM_DATA4,
            EXAMPLE_PIN_NUM_DATA5,
            EXAMPLE_PIN_NUM_DATA6,
            EXAMPLE_PIN_NUM_DATA7,
            EXAMPLE_PIN_NUM_DATA8,
            EXAMPLE_PIN_NUM_DATA9,
            EXAMPLE_PIN_NUM_DATA10,
            EXAMPLE_PIN_NUM_DATA11,
            EXAMPLE_PIN_NUM_DATA12,
            EXAMPLE_PIN_NUM_DATA13,
            EXAMPLE_PIN_NUM_DATA14,
            EXAMPLE_PIN_NUM_DATA15,

        },
        .bus_width = 16,
        .max_transfer_bytes = EXAMPLE_LCD_H_RES * 100 * sizeof(uint16_t),
        .psram_trans_align = EXAMPLE_PSRAM_DATA_ALIGNMENT,
        .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 = EXAMPLE_PIN_NUM_CS,
        .pclk_hz = EXAMPLE_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 = example_notify_lvgl_flush_ready,
        .user_ctx = &disp_drv,
        .lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS,
        .lcd_param_bits = EXAMPLE_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;

    // (essential registers are identical). A few lines further down in this code,
    // it's shown how to issue additional device-specific commands.
    ESP_LOGI(TAG, "Install LCD driver of ili9341 (st7789 compatible)");
    esp_lcd_panel_dev_config_t panel_config = {
        .reset_gpio_num = EXAMPLE_PIN_NUM_RST,
        .rgb_endian = LCD_RGB_ENDIAN_BGR,
        .bits_per_pixel = 16,
    };
    const size_t buffer_size = 1; 
    // buff_size will not be used since it is a 16 bit 
    ESP_ERROR_CHECK(esp_lcd_new_panel_ili9488(io_handle, &panel_config,buffer_size, &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_swap_xy(panel_handle, true);
    esp_lcd_panel_invert_color(panel_handle, false);



      // user can flush pre-defined pattern to the screen before we turn on the screen or backlight
    ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));

    ESP_LOGI(TAG, "Turn on LCD backlight");
    gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL);

     esp_lcd_touch_handle_t tp = NULL;
    esp_lcd_panel_io_handle_t tp_io_handle = NULL;

    ESP_LOGI(TAG, "Initialize I2C");

    const i2c_config_t i2c_conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = EXAMPLE_I2C_SDA,
        .scl_io_num = EXAMPLE_I2C_SCL,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = 400000,
    };
    /* Initialize I2C */
    ESP_ERROR_CHECK(i2c_param_config(EXAMPLE_I2C_NUM, &i2c_conf));
    ESP_ERROR_CHECK(i2c_driver_install(EXAMPLE_I2C_NUM, i2c_conf.mode, 0, 0, 0));

     esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_FT5x06_CONFIG();

      ESP_LOGI(TAG, "Initialize touch IO (I2C)");

    /* Touch IO handle */
    ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)EXAMPLE_I2C_NUM, &tp_io_config, &tp_io_handle));

    esp_lcd_touch_config_t tp_cfg = {
        .x_max = EXAMPLE_LCD_V_RES,
        .y_max = EXAMPLE_LCD_H_RES,
        .rst_gpio_num = -1,
        .int_gpio_num = -1,
        .flags = {
            .swap_xy = 1,
            .mirror_x = 1,
            .mirror_y = 0,
        },
    };

        ESP_LOGI(TAG, "Initialize touch controller FT5X06");
    ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_ft5x06(tp_io_handle, &tp_cfg, &tp));


    /*************************************LVGL PART ****************************************************/
    
     ESP_LOGI(TAG, "Initialize LVGL library");
    lv_init();
    // 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;

   bool CONFIG_EXAMPLE_LCD_I80_COLOR_IN_PSRAM = true; 

#if CONFIG_EXAMPLE_LCD_I80_COLOR_IN_PSRAM
    buf1 = heap_caps_aligned_alloc(EXAMPLE_PSRAM_DATA_ALIGNMENT, EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
#else
    buf1 = heap_caps_malloc(EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
#endif
    assert(buf1);
#if CONFIG_EXAMPLE_LCD_I80_COLOR_IN_PSRAM
    buf2 = heap_caps_aligned_alloc(EXAMPLE_PSRAM_DATA_ALIGNMENT, EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
#else
    buf2 = heap_caps_malloc(EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
#endif
    assert(buf2);
    ESP_LOGI(TAG, "buf1@%p, buf2@%p", buf1, buf2);
    // initialize LVGL draw buffers
    lv_disp_draw_buf_init(&disp_buf, buf1, buf2, EXAMPLE_LCD_H_RES * 100);

    ESP_LOGI(TAG, "Register display driver to LVGL");
    lv_disp_drv_init(&disp_drv);
    disp_drv.hor_res = EXAMPLE_LCD_H_RES;
    disp_drv.ver_res = EXAMPLE_LCD_V_RES;
    disp_drv.flush_cb = example_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);

    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 = &example_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, EXAMPLE_LVGL_TICK_PERIOD_MS * 1000));


    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 = example_lvgl_touch_cb;
    indev_drv.user_data = tp;

    lv_indev_drv_register(&indev_drv);


    ESP_LOGI(TAG, "Display LVGL animation");
   
   ui_init();
 //  rect(disp);

    while (1) {
        // raise the task priority of LVGL and/or reduce the handler period can improve the performance
        vTaskDelay(pdMS_TO_TICKS(10));
        // The task running lv_timer_handler should have lower priority than that running `lv_tick_inc`
        lv_timer_handler();







    }

    ESP_LOGI(TAG, "Example initialization done.");
}
void rect(lv_disp_t * display)
{
lv_obj_t *screen = lv_disp_get_scr_act(display);  // Get the active screen as the parent

    lv_obj_set_size(screen, LV_PCT(100),LV_PCT(100));
    lv_obj_set_style_pad_all(screen, 0, 0);
    lv_obj_align(screen, LV_ALIGN_TOP_MID, 0, 0);
    lv_obj_set_style_border_width(screen, 0, 0);

    
   lv_obj_set_style_bg_color(screen, lv_color_white(),0);

    lv_obj_t *rect = lv_obj_create(screen);  // Create a rectangle as a child of the screen
    lv_obj_set_size(rect, 100, 100);
    lv_obj_set_pos(rect, 100, 100);



    lv_color_t color = LV_COLOR_MAKE(255, 0, 0);
    lv_color_t color_white = LV_COLOR_MAKE(255, 255, 255);
    lv_obj_set_style_bg_color(rect, color, 0);
    

    

    lv_scr_load(screen); 
}


// *INDENT-ON*