lvgl-micropython / lvgl_micropython

LVGL module for MicroPython
MIT License
86 stars 28 forks source link

How to use image cache in version 9.1.0? #135

Open zjalen opened 1 month ago

zjalen commented 1 month ago

I'm using the ESP32S3, but when loading multiple images, the animation becomes very choppy. In version v8.3, I could use image cache img.cache_set_size(10), but this method was removed in version v9. I can't find a way to use it in version v9.1. I tried img.cache_resize(2000), but it's uselsess.

Can anyone guide me? Thanks.

kdschlosser commented 1 month ago

I believe the issue is with the DMA transfer buffer size for sending parameters on the I80 bus. in the ESP-IDF this is defaulted to 32 we are dealing with a single transfer max size of 192. I believe that we need to increase that. This is done by using the command below.

python3 make.py esp32 BOARD=ESP32_GENERIC_S3 BOARD_VARIANT=SPIRAM_OCT --flash-size=16 DISPLAY=hx8369 INDEV=gt911 CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE = 192

This is actually seen in that sdkconfig file you sent me...

# LCD Peripheral Configuration
#
CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE=192
# CONFIG_LCD_RGB_ISR_IRAM_SAFE is not set
# end of LCD Peripheral Configuration
# end of LCD and Touch Panel
zjalen commented 1 month ago

python3 make.py esp32 BOARD=ESP32_GENERIC_S3 BOARD_VARIANT=SPIRAM_OCT --flash-size=16 DISPLAY=hx8369 INDEV=gt911 CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE = 192

因此将其用于您的构建命令...

python3 make.py esp32 BOARD=ESP32_GENERIC_S3 BOARD_VARIANT=SPIRAM_OCT --flash-size=16 DISPLAY=hx8369 INDEV=gt911 CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=8192

I have tried this,but it didn't help.I will try CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE = 192 now.

zjalen commented 1 month ago

@kdschlosser The crash issue has been resolved, but the display is still not functioning correctly.

image
kdschlosser commented 1 month ago

I am using the exact same initialization commands and I am also using the exact same parameters for the I80 interface. At this point I am not sure what could be wrong.

try swapping the width and height.

zjalen commented 1 month ago

Yes, I swaped and the display now run perfectly. Thank you very much.I appreciate your professionalism and patience.

kdschlosser commented 1 month ago

no worries m8.

I wanted to let you know that I just pushed ma commit so you are no longer going to need to add CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE to the build command. It is all handled automatically now.

zjalen commented 1 month ago

I have another question. After I swapped the width and height parameters, my screen can display content now.But all the text and images are mirrored, and it seems that the image loading speed is very slow. I tried creating an image,it loaded line by line, taking more than 5 seconds to fully display.

I checked my demo code and found the following part.I'm not sure if these parts are the key to my issue.What should I do?

// hx8369.c
...
void    hx8369_init(void)
{

    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,LCD_CLK_SRC_PLL160M
        .clk_src = LCD_CLK_SRC_PLL160M,
        .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 = 8,
        .max_transfer_bytes = LCD_V_RES * 100 * sizeof(uint16_t),
        //.max_transfer_bytes = DISP_BUF_SIZE,
        .psram_trans_align = 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 = 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,
        },
        .on_color_trans_done = notify_lvgl_flush_ready,
        .user_ctx = &disp_drv,
        .lcd_cmd_bits = LCD_CMD_BITS,
        .lcd_param_bits = LCD_PARAM_BITS,
        .flags.swap_color_bytes = true,
    };
    ESP_ERROR_CHECK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle));

    //esp_lcd_panel_handle_t panel_handle = NULL;
    panel_handle = NULL;

    ESP_LOGI(TAG, "Install LCD driver of hx8369");
    esp_lcd_panel_dev_config_t panel_config = {
        .reset_gpio_num = PIN_NUM_RST,
        .color_space = ESP_LCD_COLOR_SPACE_RGB,
        .bits_per_pixel = 16,
    };
    ESP_ERROR_CHECK(esp_lcd_new_panel_hx8369(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
    // esp_lcd_panel_invert_color(panel_handle, false);
    esp_lcd_panel_swap_xy(panel_handle, true);   //----------> 1
    esp_lcd_panel_mirror(panel_handle, true, false);  // -----------> 2

    // the gap is LCD panel specific, even panels with the same driver IC, can have different gap value
    // esp_lcd_panel_set_gap(panel_handle, 0, 20);

    // 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));panel_hx8369_disp_on_off
    ESP_ERROR_CHECK(panel_hx8369_disp_on_off(panel_handle, true));
}

static esp_err_t panel_hx8369_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y)
{
    hx8369_panel_t *hx8369 = __containerof(panel, hx8369_panel_t, base);
    esp_lcd_panel_io_handle_t io = hx8369->io;
    if (mirror_x)
    {
        hx8369->madctl_val |= LCD_CMD_MX_BIT;
    }
    else
    {
        hx8369->madctl_val &= ~LCD_CMD_MX_BIT;
    }
    if (mirror_y)
    {
        hx8369->madctl_val |= LCD_CMD_MY_BIT;
    }
    else
    {
        hx8369->madctl_val &= ~LCD_CMD_MY_BIT;
    }
    esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]){hx8369->madctl_val}, 1);
    return ESP_OK;
}

static esp_err_t panel_hx8369_swap_xy(esp_lcd_panel_t *panel, bool swap_axes)
{
    hx8369_panel_t *hx8369 = __containerof(panel, hx8369_panel_t, base);
    esp_lcd_panel_io_handle_t io = hx8369->io;
    if (swap_axes)
    {
        hx8369->madctl_val |= LCD_CMD_MV_BIT;
    }
    else
    {
        hx8369->madctl_val &= ~LCD_CMD_MV_BIT;
    }
    esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]){hx8369->madctl_val}, 1);
    return ESP_OK;
}

static esp_err_t panel_hx8369_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap)
{
    hx8369_panel_t *hx8369 = __containerof(panel, hx8369_panel_t, base);
    hx8369->x_gap = x_gap;
    hx8369->y_gap = y_gap;
    return ESP_OK;
}
kdschlosser commented 1 month ago

give it a try now. I updated the orientation table so hopefully it will display correctly.

zjalen commented 1 month ago

@kdschlosser The text direction is displaying correctly now, but my image loading speed is still very slow. What adjustments should I make to improve it?

kdschlosser commented 1 month ago

how are you loading the images?

zjalen commented 1 month ago
class Demo:
...
    def draw_image2(self):
        self.bg_img = lv.image(self.screen)
        self.bg_img.set_src('S:m1.jpg')

I'm using the most basic example, with an image resolution of 800x480, which matches the screen resolution. I used the same code on another board I have (8048S043, rgb_display), and its speed is much faster.

zjalen commented 1 month ago

I just retried compiling the firmware and found that the compilation failed.

python3 make.py esp32 BOARD=ESP32_GENERIC_S3 BOARD_VARIANT=SPIRAM_OCT --flash-size=16 DISPLAY=hx8369 INDEV=gt911

...
[1088/1956] Generating /Users/jalen/GitHub/lvgl_micropython/lib/micropython/mpy-cross/build/mpy-cross
Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.
make[1]: warning: jobserver unavailable: using -j1.  Add `+' to parent make rule.
GEN build/genhdr/moduledefs.collected
Module registrations not updated
GEN build/genhdr/root_pointers.collected
Root pointer registrations not updated
[1122/1956] Generating ../../genhdr/root_pointers.collected
Root pointer registrations updated
[1125/1956] Generating ../../genhdr/qstrdefs.collected.h
QSTR updated
[1128/1956] cd /Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/build-ESP32_GENERIC_S3-SPIRAM_OCT/esp-idf/main_esp32s3 && /Users/jalen/.espressif/python_env/idf5.2_py3.10_env/bin/python /Users/jalen/GitHub/lvgl_micropython/lib/micropython/tools/makemanifest.py -o /Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/build-ESP32_GENERIC_S3-SPIRAM_OCT/frozen_content.c -v BOARD_DIR=/Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/boards/ESP32_GENERIC_S3 -v MPY_DIR=/Users/jalen/GitHub/lvgl_micropython/lib/micropython -v MPY_LIB_DIR=/Users/jalen/GitHub/lvgl_micropython/lib/micropython/lib/micropython-lib -v PORT_DIR=/Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32 -b /Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/build-ESP32_GENERIC_S3-SPIRAM_OCT -f-march=xtensawin --mpy-tool-flags= /Users/jalen/GitHub/lvgl_micropython/build/manifest.py
FAILED: esp-idf/main_esp32s3/CMakeFiles/BUILD_FROZEN_CONTENT frozen_content.c /Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/build-ESP32_GENERIC_S3-SPIRAM_OCT/esp-idf/main_esp32s3/CMakeFiles/BUILD_FROZEN_CONTENT /Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/build-ESP32_GENERIC_S3-SPIRAM_OCT/frozen_content.c
cd /Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/build-ESP32_GENERIC_S3-SPIRAM_OCT/esp-idf/main_esp32s3 && /Users/jalen/.espressif/python_env/idf5.2_py3.10_env/bin/python /Users/jalen/GitHub/lvgl_micropython/lib/micropython/tools/makemanifest.py -o /Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/build-ESP32_GENERIC_S3-SPIRAM_OCT/frozen_content.c -v BOARD_DIR=/Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/boards/ESP32_GENERIC_S3 -v MPY_DIR=/Users/jalen/GitHub/lvgl_micropython/lib/micropython -v MPY_LIB_DIR=/Users/jalen/GitHub/lvgl_micropython/lib/micropython/lib/micropython-lib -v PORT_DIR=/Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32 -b /Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/build-ESP32_GENERIC_S3-SPIRAM_OCT -f-march=xtensawin --mpy-tool-flags= /Users/jalen/GitHub/lvgl_micropython/build/manifest.py
freeze error executing "/Users/jalen/GitHub/lvgl_micropython/build/manifest.py": Error in manifest file: /Users/jalen/GitHub/lvgl_micropython/build/manifest.py: Cannot stat /Users/jalen/GitHub/lvgl_micropython/build/hx8369
ninja: build stopped: subcommand failed.
ninja failed with exit code 1, output of the command is in the /Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/build-ESP32_GENERIC_S3-SPIRAM_OCT/log/idf_py_stderr_output_76418 and /Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/build-ESP32_GENERIC_S3-SPIRAM_OCT/log/idf_py_stdout_output_76418
-e See https://github.com/micropython/micropython/wiki/Build-Troubleshooting
make: *** [all] Error 1
zjalen commented 1 month ago

fd85fd1b This version can compile successfully, but the subsequent ones cannot.

image
kdschlosser commented 1 month ago

I fixed the error you were having when building.

zjalen commented 1 month ago

@kdschlosser thank you, it did work.However, the issue with image loading still exists. I tried adjusting lv_conf.h, but it didn't help much.Do you have any ideas on this issue?

kdschlosser commented 1 month ago

I do not understand what you mean bu it's loading slow.

you can try timing it by adding this code right before you add your UI elements.

import task_handler
import time

th = task_handler.TaskHandler()

start_time = time.ticks_ms()

def handler_start_cb(*_):
    global start_time
    start_time = time.ticks_ms()
    return True

def handler_stop_cb(*_):
    end_time = time.ticks_ms()
    diff = time.ticks_diff(end_time, start_time)
    print(f'task handler took {diff}ms to complete.')

th.add_event_cb(handler_start_cb, task_handler.TASK_HANDLER_STARTED)
th.add_event_cb(handler_stop_cb, task_handler.TASK_HANDLER_FINISHED)

That will tell you how many milliseconds it is taking for LVGL to render and flush the buffer

zjalen commented 1 month ago

This is my demo code and output result.The first time was took 45ms to complete., then it got stuck for a while. After that, it output results around 40ms to complete at a crazy rate.

import time, os, urandom, lcd_bus, lvgl as lv
import task_handler
import fs_driver
import sys
from micropython import const

class Demo(object):

    def __init__(self):
        # init display
        self.init_8369_disp()

        self.task_handler = task_handler.TaskHandler()
        self.start_time = time.ticks_ms()
        self.task_handler.add_event_cb(self.handler_start_cb, task_handler.TASK_HANDLER_STARTED)
        self.task_handler.add_event_cb(self.handler_stop_cb, task_handler.TASK_HANDLER_FINISHED)

        # display test
        self.screen = lv.screen_active()

        fd = lv.fs_drv_t()
        fs_driver.fs_register(fd, 'S')

    def init_8369_disp(self):
        import hx8369
        _CS = const(12)
        _DC = const(11)
        _WR = const(10)
        _RESET = const(9)
        _DB0 = const(46)
        _DB1 = const(3)
        _DB2 = const(8)
        _DB3 = const(18)
        _DB4 = const(17)
        _DB5 = const(16)
        _DB6 = const(15)
        _DB7 = const(7)
        _BL = const(6)

        i80bus = lcd_bus.I80Bus(
            wr=_WR,
            dc=_DC,
            cs=_CS,
            data0=_DB0,
            data1=_DB1,
            data2=_DB2,
            data3=_DB3,
            data4=_DB4,
            data5=_DB5,
            data6=_DB6,
            data7=_DB7,
            freq=20 * 1000 * 1000,
            swap_color_bytes=True
        )

        self.display = hx8369.HX8369(
            data_bus=i80bus,
            display_width=480,
            display_height=800,
            reset_pin=9,
            reset_state=hx8369.STATE_LOW,
            backlight_pin=6,
            color_space=lv.COLOR_FORMAT.RGB565,  # NOQA
        )

        self.display.init(hx8369.TYPE_A)
        self.display.set_backlight(100)
        self.screen = lv.screen_active()
        self.display.set_rotation(lv.DISPLAY_ROTATION._270)

    def draw_image2(self):
        self.bg_img = lv.image(self.screen)
        self.bg_img.set_src('S:m1.jpg')

    def handler_start_cb(self, *_):
        self.start_time = time.ticks_ms()
        return True

    def handler_stop_cb(self, *_):
        end_time = time.ticks_ms()
        diff = time.ticks_diff(end_time, self.start_time)
        print(f'task handler took {diff}ms to complete.')

d=Demo()
d.draw_image2()
>>> task handler took 45ms to complete.
// a few seconds later
task handler took 1ms to complete.
task handler took 0ms to complete.
task handler took 37ms to complete.
task handler took 40ms to complete.
....

https://github.com/user-attachments/assets/00426220-30f6-48f9-af1b-85dcd32510e3

zjalen commented 1 month ago

If I try to use the reset button (RST) on the board, the image loads quickly, but the REPL gets stuck and is unusable for a long time. If I unplug the USB power to start it, it loads slowly, just like shown in the video above.

kdschlosser commented 1 month ago

holy geesh you are loading an 800 x 600 32 bit JPG file from quad flash and rendering it to an 8 channel i8080 display. No wonder why it is taking a long time.

Send me the image file and let me do some work to it.

kdschlosser commented 1 month ago

also try upping the display frequency to 40mhz and then to 80mhz see if the display will play nice at those speeds.

zjalen commented 1 month ago

Here is the JPG file.It displays correctly on my other board (rgb_display). I tried setting the frequency to 80,000,000, but it didn't display properly. 40,000,000 works, but there's no noticeable improvement.

m1.jpg

kdschlosser commented 1 month ago

OK so here is the skinny. It's not going to work. You are displaying an image that is simply way to large and you are reading it from a slow ass media. You have an image that has a size of 800 x 480 x 3 = 1152000 bytes and you have compressed it down to 60203 bytes in size. that is a 19.13:1 compression ratio. That means you have the compression set at it's maximum amount. well that data needs to be uncompressed and the higher the compression level the more work is going to need to be done to uncompress it. The math is a lot more complex.

I would use a PNG file as it is far less compressed than a JPG, yes it is going to be larger but that is the price you are going to have to pay for better performance. less compression = faster to load.

The other thing is I want you to make a change to your startup code. change swap_color_bytes=True to swap_color_bytes=False and see how the performance is. I know the colors are going to be off and that's OK. It is something I can fix.

I also want to make sure DMA memory is working properly as well. Use the code below with swap_color_bytes=True and then do it again with swap_color_bytes=False. I want to see what the times are for both of them.

import time
import lcd_bus
import lvgl as lv
import task_handler
import fs_driver
from micropython import const
import hx8369

_CS = const(12)
_DC = const(11)
_WR = const(10)
_RESET = const(9)
_DB0 = const(46)
_DB1 = const(3)
_DB2 = const(8)
_DB3 = const(18)
_DB4 = const(17)
_DB5 = const(16)
_DB6 = const(15)
_DB7 = const(7)
_BL = const(6)

stored_times = []

class HX8369(hx8369.HX8369):

    def _flush_cb(self, disp, area, color_p):
        start_time = time.ticks_ms()
        stored_times.append(start_time)
        hx8369.HX8369._flush_cb(self, disp, area, color_p)
        end_time = time.ticks_ms()

        print('flush time:', time.ticks_diff(end_time, start_time), 'ms')

    def _flush_ready_cb(self, *_):
        end_time = time.ticks_ms()
        start_time = stored_times.pop(0)
        print('buffer transmit time:', time.ticks_diff(end_time, start_time), 'ms')
        hx8369.HX8369._flush_ready_cb(self)

class Demo(object):

    def __init__(self):
        # init display
        self.init_8369_disp()

        self.task_handler = task_handler.TaskHandler()

        # display test
        self.screen = lv.screen_active()

        fd = lv.fs_drv_t()
        fs_driver.fs_register(fd, 'S')

    def init_8369_disp(self):
        i80bus = lcd_bus.I80Bus(
            wr=_WR,
            dc=_DC,
            cs=_CS,
            data0=_DB0,
            data1=_DB1,
            data2=_DB2,
            data3=_DB3,
            data4=_DB4,
            data5=_DB5,
            data6=_DB6,
            data7=_DB7,
            freq=40 * 1000 * 1000,
            swap_color_bytes=True
        )

        self.display = HX8369(
            data_bus=i80bus,
            display_width=480,
            display_height=800,
            reset_pin=9,
            reset_state=hx8369.STATE_LOW,
            backlight_pin=6,
            color_space=lv.COLOR_FORMAT.RGB565,  # NOQA
        )

        self.display.init(hx8369.TYPE_A)
        self.display.set_backlight(100)
        self.screen = lv.screen_active()
        self.display.set_rotation(lv.DISPLAY_ROTATION._270)

    def draw_image2(self):
        self.bg_img = lv.image(self.screen)
        self.bg_img.set_src('S:m1.jpg')

d=Demo()
d.draw_image2()
zjalen commented 1 month ago

I tried converting the JPG to PNG, but I found that the loading is still very slow, and the screen is black.

// jpg+swap_color_bytes=True
>>> flush time: 1 ms
buffer transmit time: 3 ms
flush time: 1 ms
buffer transmit time: 3 ms
flush time: 0 ms
buffer transmit time: 2 ms
flush time: 0 ms
buffer transmit time: 2 ms
flush time: 1 ms
buffer transmit time: 3 ms
flush time: 0 ms
buffer transmit time: 2 ms
flush time: 0 ms
buffer transmit time: 2 ms
flush time: 0 ms
buffer transmit time: 2 ms
flush time: 1 ms
buffer transmit time: 3 ms
flush time: 0 ms
buffer transmit time: 2 ms
// jpg+swap_color_bytes=False
>>> flush time: 0 ms
buffer transmit time: 2 ms
flush time: 0 ms
buffer transmit time: 2 ms
flush time: 0 ms
buffer transmit time: 2 ms
flush time: 1 ms
buffer transmit time: 3 ms
flush time: 1 ms
buffer transmit time: 3 ms
flush time: 0 ms
buffer transmit time: 2 ms
flush time: 0 ms
buffer transmit time: 2 ms
flush time: 1 ms
buffer transmit time: 3 ms
flush time: 0 ms
buffer transmit time: 2 ms
flush time: 0 ms
buffer transmit time: 2 ms
// png+swap_color_bytes=True
>>> flush time: 1 ms
buffer transmit time: 3 ms
flush time: 0 ms
buffer transmit time: 2 ms
flush time: 0 ms
buffer transmit time: 3 ms
flush time: 0 ms
buffer transmit time: 2 ms
flush time: 1 ms
buffer transmit time: 3 ms
flush time: 1 ms
buffer transmit time: 3 ms
flush time: 1 ms
buffer transmit time: 3 ms
flush time: 0 ms
buffer transmit time: 2 ms
flush time: 1 ms
buffer transmit time: 3 ms
flush time: 0 ms
buffer transmit time: 2 ms

m1.png

m1

kdschlosser commented 1 month ago

OK then problem is not in the bus drivers. as you can see the amount of time it is taking to write the data to the display is 2-3 milliseconds per buffer chunk. Each chunk is 1/10th the size of the display so the total amount of time the bus driver would take to update the entire diosplay is 20 to 30 milliseconds.

BUT.. if we looK at the total amount of time that gets used when calling lv_task_handler() which is what I had you do the timing tests for the first time around we are seeing times of...

task handler took 37ms to complete.
task handler took 40ms to complete.

there is something goofed in LVGL which is causing this issue. It's not rendering the entire image in a single go. It is only rendering when the task handler gets called and it is only filling the buffer flushing and then exiting the task handler.. it should be doing a continuous run until everything on the display is updated.

I am going to bring this up with the head guy over at LVGL to see what he thinks about it...

kdschlosser commented 1 month ago

I just double checked to see if those last times were some kind of an oddity.

800 x 480 x 2 = 768000 bytes for the whole display. the buffer is 1/10th the size of the display... 768000 / 10 = 76800 bytes per buffer

speeds are measures in bits per second so the number of bits in the buffer is... 76800 x 8 = 614400 bits

The clock speed is set to 40mhz which is 40000000 bits per second. and there are 8 lanes running at that speed. 40000000 x 8 = 320000000 bits per second that can be transferred.

There are 1000 milliseconds in a second so how many bits can be sent per millisecond.. 320000000 / 1000 = 320000 bits

if the buffer is 614400 bits in size how many milliseconds would it take to send?

614400 / 320000 = 1.92..

There is some overhead which is why you are seeing it blip between 2 and 3 milliseconds.

My code is running how it should be running. LVGL's code however is not running how it should be running. It should not be taking as long as it is to render the data to the display.

OH!! and the reason why you are not able to push to 80mhz for the bus speed is because the ram is being written to and read from at the same time. If you had octal SPI for both the ram and the flash we could overclock the SPI for the ram and flash so it would run at an effective speed of 240mhz which would then remove the bottleneck that is limiting the display bus speed to 40mhz. What this means in terms of performance... instead of it taking 20 to 30 milliseconds to write the entire display it would take 10 to 15 milliseconds. This is on the bus side of things and it has nothing to do with LVGL at all. With the time it is taking LVGL to render it wouldn't really matter. gotta get LVGL fixed.

zjalen commented 1 month ago

Thank you. I also want to report another situation that I'm not sure is related to this issue. When I use pyboard.py or ampy.py to transfer files, I have to unplug and replug the USB cable for it to work. After replugging, the first file can be transferred, but then it gets stuck or fails after a long time, as if a program is running and blocking the transfer (even if I haven't transferred any files to the board yet). This issue rarely occurs on my other board models.

kdschlosser commented 1 month ago

I have fixed the problems with ampy to transfer files. It is actually an issue in the script it's self and not with the binding or anything like that.

zjalen commented 1 month ago

build failed.

...
[1362/1956] Building C object esp-idf/main_esp32s3/CMakeFiles/__idf_main_esp32s3.dir/Users/jalen/GitHub/lvgl_micropython/ext_mod/lcd_bus/esp32_src/rgb_bus.c.obj
FAILED: esp-idf/main_esp32s3/CMakeFiles/__idf_main_esp32s3.dir/Users/jalen/GitHub/lvgl_micropython/ext_mod/lcd_bus/esp32_src/rgb_bus.c.obj
...
/Users/jalen/GitHub/lvgl_micropython/ext_mod/lcd_bus/esp32_src/rgb_bus.c: In function 'mp_lcd_rgb_bus_make_new':
/Users/jalen/GitHub/lvgl_micropython/ext_mod/lcd_bus/esp32_src/rgb_bus.c:166:57: error: 'ARG_disp' undeclared (first use in this function); did you mean 'ARG_de'?
166 |         self->panel_io_config.disp_gpio_num = (int)args[ARG_disp].u_int;
|                                                         ^~~~~~~~
|                                                         ARG_de
/Users/jalen/GitHub/lvgl_micropython/ext_mod/lcd_bus/esp32_src/rgb_bus.c:166:57: note: each undeclared identifier is reported only once for each function it appears in
[1364/1956] Building C object esp-idf/main_esp32s3/CMakeFiles/__idf_main_esp32s3.dir/Users/jalen/GitHub/lvgl_micro[1365/1956] Building C object esp-idf/main_esp32s3/CMakeFiles/__idf_main_esp32s3.dir/Users/jalen/GitHub/lvgl_micro[1366/1956] Building C object esp-idf/main_esp32s3/CMakeFiles/__idf_main_esp32s3.dir/Users/jalen/GitHub/lvgl_micro[1367/1956] Building C object esp-idf/main_esp32s3/CMakeFiles/__idf_main_esp32s3.dir/Users/jalen/GitHub/lvgl_micro[1368/1956] Building C object esp-idf/main_esp32s3/CMakeFiles/__idf_main_esp32s3.dir/Users/jalen/GitHub/lvgl_micro[1369/1956] Building C object esp-idf/main_esp32s3/CMakeFiles/__idf_main_esp32s3.dir/Users/jalen/GitHub/lvgl_micro[1370/1956] Building C object esp-idf/main_esp32s3/CMakeFiles/__idf_main_esp32s3.dir/Users/jalen/GitHub/lvgl_micro[1371/1956] Building C object esp-idf/main_esp32s3/CMakeFiles/__idf_main_esp32s3.dir/__/__/lv_mp.c.obj
ninja: build stopped: subcommand failed.
ninja failed with exit code 1, output of the command is in the /Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/build-ESP32_GENERIC_S3-SPIRAM_OCT/log/idf_py_stderr_output_87776 and /Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/build-ESP32_GENERIC_S3-SPIRAM_OCT/log/idf_py_stdout_output_87776
-e See https://github.com/micropython/micropython/wiki/Build-Troubleshooting
kdschlosser commented 1 month ago

heh ooops I removed some but not all of the disp stuff.

kdschlosser commented 1 month ago

should now be fixed

zjalen commented 1 month ago

Okay, I’ve finished compiling, but how should I define the new I80Bus parameters? I tried doing it this way, but it crashed.

        # i80bus = lcd_bus.I80Bus(
        #     wr=_WR,
        #     dc=_DC,
        #     cs=_CS,
        #     data0=_DB0,
        #     data1=_DB1,
        #     data2=_DB2,
        #     data3=_DB3,
        #     data4=_DB4,
        #     data5=_DB5,
        #     data6=_DB6,
        #     data7=_DB7,
        #     freq=40 * 1000 * 1000,
        #     swap_color_bytes=True
        # )
        i80bus = lcd_bus.I80Bus(
            wr=_WR,
            dc=_DC,
            cs=_CS,
            data_pins=(_DB0, _DB1, _DB2, _DB3, _DB4, _DB5, _DB6, _DB7,),
            freq=40 * 1000 * 1000,
            # swap_color_bytes=True
        )
A fatal error occurred. The crash dump printed below may be used to help
determine what caused it. If you are not already running the most recent
version of MicroPython, consider upgrading. New versions often fix bugs.

To learn more about how to debug and/or report this crash visit the wiki
page at: https://github.com/micropython/micropython/wiki/ESP32-debugging

LVGL MPY version : 1.23.0 on 2024-10-06
IDF version : v5.2
Machine     : Generic ESP32S3 module with Octal-SPIRAM with ESP32S3

Guru Meditation Error: Core  1 panic'ed (Interrupt wdt timeout on CPU1). 
kdschlosser commented 1 month ago

try removing the comma after the last data pin.

zjalen commented 1 month ago

try removing the comma after the last data pin.

I've tried.It didn't work.

zjalen commented 1 month ago

@kdschlosser I just tried to compile the latest code, and it still crashes when initializing the hx8369.

        i80bus = lcd_bus.I80Bus(
            wr=_WR,
            dc=_DC,
            cs=_CS,
            data0=_DB0,
            data1=_DB1,
            data2=_DB2,
            data3=_DB3,
            data4=_DB4,
            data5=_DB5,
            data6=_DB6,
            data7=_DB7,
            freq=40 * 1000 * 1000,
            # swap_color_bytes=True
        )

        display = HX8369(
            data_bus=i80bus,
            display_width=480,
            display_height=800,
            reset_pin=9,
            reset_state=hx8369.STATE_LOW,
            backlight_pin=6,
            color_space=lv.COLOR_FORMAT.RGB565,  # NOQA
        )

A fatal error occurred. The crash dump printed below may be used to help
determine what caused it. If you are not already running the most recent
version of MicroPython, consider upgrading. New versions often fix bugs.

To learn more about how to debug and/or report this crash visit the wiki
page at: https://github.com/micropython/micropython/wiki/ESP32-debugging

LVGL MPY version : 1.23.0 on 2024-10-08
IDF version : v5.2
Machine     : Generic ESP32S3 module with Octal-SPIRAM with ESP32S3

Guru Meditation Error: Core  1 panic'ed (Interrupt wdt timeout on CPU1). 

Core  1 register dump:
PC      : 0x40387dc5  PS      : 0x00060234  A0      : 0x80388ed4  A1      : 0x3fcbe8c0  
A2      : 0x3fca606c  A3      : 0x3fcbeb8c  A4      : 0x00060223  A5      : 0x00060223  
A6      : 0x00000004  A7      : 0x0000abab  A8      : 0x3fcbeb8c  A9      : 0x00000018