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 think you have to edit lib/lv_conf.h and in that file is going to be a macro that you can change.

Are you using the filesystem driver that is in LVGL? or are you loading the image from the file system yourself and keeping the data resident in memory?

zjalen commented 1 month ago

@kdschlosser Could you give me information. I'm trying to load image from sd card.

# v8.3
class Demo:
...
    def draw_img(self):
        try:
            with open('1.png', 'rb') as f:
                png_data = f.read()
        except:
            print("Could not find .png")
        wink_argb = lv.img_dsc_t({
            'data_size': len(png_data),
            'data': png_data
        })
        self.img1 = lv.img(lv.scr_act())
        # self.img1.cache_set_size(10)   # cache line
        self.img1.set_src(wink_argb)

d=Demo()
d.draw_img()
for i in range(5000):
    x,y=random.randint(0,350),random.randint(0,200)
    d.img1.move_to(x,y)
    time.sleep(0.2)

If I use this cache line, the animation will become smooth; otherwise, it will lag.Now in this project,lvgl version is v9.1. I want my animation to become smooth. Which part should I edit in lib/lv_conf.h? I can't find any examples or explanations on the official website.

kdschlosser commented 1 month ago

ok so first thing is this. deep six the use of classes and instance variables. The time it takes to search for the variable and return it to the user is fairly large and that amount of time is proportional to how many variables you have set.

What you have is not really an animation. You are just moving an image around the display into random locations. The PNG is loaded a single time...

an animation is where you have say 10 images and the images change. Just like the frames in a video. That is where "caching" the images would be helpful. They wouldn't be loaded and unloaded from memory which would require decoding the images.

The code you are using above would not work properly if you were changing images because the data for the image is going to get garbage collected.

Here is an example of image caching...

import lvgl as lv
import gc
import time

def load_png(filename):
    with open(filename, 'rb') as f:
        data = f.read()

    image_header = lv.image_header_t()

    lv.image_decoder_get_info(data, image_header)
    draw_image_dsc = lv.draw_image_dsc_t()
    draw_image_dsc.init()
    draw_image_dsc.src = data
    draw_image_dsc.header = image_header
    draw_image_dsc.image_area.x1 = 0
    draw_image_dsc.image_area.y1 = 0
    draw_image_dsc.image_area.x2 = image_header.w
    draw_image_dsc.image_area.y2 = image_header.h

    canvas = lv.canvas(None)

    size = image_header.w * image_header.h * 4

    buf = bytearray(size)
    canvas.set_buffer(buf, image_header.w, image_header.h, lv.COLOR_FORMAT_ARGB8888)

    layer = lv.layer_t()
    canvas.init_layer(layer)

    lv.draw_image(layer, draw_image_dsc, draw_image_dsc.image_area)

    canvas.finish_layer(layer)
    canvas_img = canvas.get_image()

    image_dsc = lv.image_dsc_t()
    image_dsc.header = canvas_img.header
    image_dsc.data_size = size

    canvas.delete()

    return image_dsc, buf

frame1_img_dsc, frame1_data = load_png('frame1.png')
frame1_mv = memoryview(frame1_data)
frame1_img_dsc.data = frame1_mv
gc.collect()

frame2_img_dsc, frame2_data = load_png('frame2.png')
frame2_mv = memoryview(frame2_data)
frame2_img_dsc.data = frame2_mv
gc.collect()

frame3_img_dsc, frame3_data = load_png('frame3.png')
frame3_mv = memoryview(frame3_data)
frame3_img_dsc.data = frame3_mv
gc.collect()

frame4_img_dsc, frame4_data = load_png('frame4.png')
frame4_mv = memoryview(frame4_data)
frame4_img_dsc.data = frame4_mv
gc.collect()

scrn = lv.screen_active()

img = lv.image(scrn)
img.set_src(frame1_img_dsc)
img.center()

current_frame = frame1_img_dsc
display = scrn.get_display()
while True:
    time.sleep(10)
    if current_frame == frame1_img_dsc:
        current_frame = frame2_img_dsc
    elif current_frame == frame2_img_dsc:
        current_frame = frame3_img_dsc
    elif current_frame == frame3_img_dsc:
        current_frame = frame4_img_dsc
    else:
        current_frame = frame1_img_dsc

    img.set_src(current_frame)
    lv.tick_inc(10)
    lv.refr_now(display)

in this example we open the image file and then using the canvas we decode the image and render it to a buffer... Now that portion of the work is not going to have to be done again. The buffer and also an image description get returned from the function. We create a memoryview of the data and that gets set into the image description. This portion of the work is done at the module level because it cannot go out of scope. Once a function closes any references to anything that was inside that function gets marked to be garbage collected. We do not want the data going out of scope so it needs to be returned from the function. We don't want the memoryview object going out of scope either since that is what is the link between the image description and the actual data.

The image data returned form the canvas should be raw RGBA data since the rendering to the canvas was done using a layer.

The work to load, decode and render the image to a buffer has been done ahead of time so the work is not going to have to be done when loading each "frame" into the image widget. all it has to do is copy the buffer data to the frame buffer when the images change. That's it.

That is what image caching is.

kdschlosser commented 1 month ago

That being said, by your example I am going to say your issue is not stemming from caching but instead it is stemming from something else. Without seeing how you are starting up the display I would be throwing darts at a dartboard while being blindfolded and spun around 10 times. The chances of me "guessing" what the problem is and that guess being correct are 1 in a billion.

I need to see all of the code to be able to assist further.

zjalen commented 1 month ago

@kdschlosser Thank you for your help. Here is my demo.I want to display a background image and a foreground object that moves back and forth.

class Demo(object):

    def __init__(self):
        # Display init
        self.rgb_bus = lcd_bus.RGBBus(de=40, vsync=41, hsync=39, pclk=42,
                                      data11=45, data12=48, data13=47, data14=21, data15=14,
                                      data5=5, data6=6, data7=7, data8=15, data9=16, data10=4,
                                      data0=8, data1=3, data2=46, data3=9, data4=1,
                                      freq=13000000, hsync_front_porch=8, disp=-1,
                                      hsync_pulse_width=4, hsync_back_porch=8, hsync_idle_low=True,
                                      vsync_front_porch=8, vsync_pulse_width=4, vsync_back_porch=8,
                                      vsync_idle_low=True, de_idle_high=False, pclk_idle_high=False,
                                      disp_active_low=False, refresh_on_demand=False, pclk_active_low=1)

        _BUF1 = self.rgb_bus.allocate_framebuffer(_WIDTH * _HEIGHT * 2, lcd_bus.MEMORY_SPIRAM)
        _BUF2 = self.rgb_bus.allocate_framebuffer(_WIDTH * _HEIGHT * 2, lcd_bus.MEMORY_SPIRAM)
        self.display = rgb_display.RGBDisplay(data_bus=self.rgb_bus, display_width=_WIDTH, display_height=_HEIGHT,
                                              frame_buffer1=_BUF1, frame_buffer2=_BUF2, backlight_pin=2,
                                              color_space=lv.COLOR_FORMAT.RGB565, rgb565_byte_swap=False)
        self.display.set_power(True)
        self.display.init()
        # self.display.set_rotation(lv.DISPLAY_ROTATION._180)
        self.display.set_backlight(100)
        self.task_handler = task_handler.TaskHandler()
        self.screen = lv.screen_active()

        # GT911 touch init
        self.init_touch()

        # SD Card init
        self.SD_CS = 10
        self.SD_FREQ = 1000000
        self.spi_bus = SPI.Bus(host=2, sck=12, mosi=11, miso=13)
        self._sd_ready = False
        self._sd_mounted = False
        self.mount_sd()

        # file driver. "S:/sd" is the path of sd card
        fd = lv.fs_drv_t()
        fs_driver.fs_register(fd, 'S')

...

    def load_background(self):
        self.bg_img = lv.image(self.screen)
        self.bg_img.set_src('S:m1.jpg')
        self.bg_img.align(lv.ALIGN.LEFT_MID, 0, 0)

    def load_foreground(self):
        try:
            with open('obj.png', 'rb') as f:
                png_data = f.read()
        except:
            print("Could not find obj.png")
            sys.exit()

        wink_argb = lv.image_dsc_t({
            'data_size': len(png_data),
            'data': png_data
        })

        self.obj_img = lv.image(self.screen)
        self.obj_img.set_src(wink_argb)
        self.obj_img.align(lv.ALIGN.RIGHT_MID, -350, 0)

        # animation
        a1 = lv.anim_t()
        a1.init()
        a1.set_var(self.obj_img)
        a1.set_values(-500, 0)
        a1.set_time(1000)
        a1.set_playback_delay(100)
        a1.set_playback_time(300)
        a1.set_repeat_delay(500)
        a1.set_repeat_count(lv.ANIM_REPEAT_INFINITE)
        a1.set_path_cb(lv.anim_t.path_linear)
        a1.set_custom_exec_cb(lambda a, val: self.set_x(self.obj_img, val))
        lv.anim_t.start(a1)

d=Demo()
d.load_background()
d.load_foreground()

I just want this animation to become smooth.

kdschlosser commented 1 month ago

OK so you are using an RGB display... what is the resolution of the display? You didn't provide that information.

zjalen commented 1 month ago

OK so you are using an RGB display... what is the resolution of the display? You didn't provide that information.

800*480

kdschlosser commented 1 month ago

Oh Geesh. You are using the wrong kind of display with an ESP32 if you are trying to get smooth animations. You need to be using a display that connects using an I8080 bus instead of the RGB display.

Look at it this way..

800 * 480 * 2 = 768,000

That's how many bytes have to be sent each time an update occurs.

Now lets break that down.

768,000 * 8 = 6,144,000

that's the number of bits that has to be sent. There is a limitation of 65,536 bytes (524,288 bits) for a DMA transfer. so the transfer has to get broken up into different transactions. That adds latency. If we don't even factory that latency in and only use the frequency as the number which is 13mhz that means that 13,000,000 bits per second is able to be transferred. knock 15% of that off for overhead due to GPIO switching and things of that nature. that brings the bits per second down to 11,050,000. You are using 16 lanes so the theoretical is 176,800,000 bits per second. Looks like a big number yes?... well if you are sending 6,144,000 bits how many times is that able to be sent in one second... 28.77 times. Now here is the real kick in the ass. The frame buffers are located in SPI RAM which is slow. IF you are using octal SPIRAM at 80MHZ you will only get 40mhz from it. Remember that speed has to be shared while the transfer is taking place. so 40mhz across 4 lanes. We are going to say you are using quad SPI for the ram... 40,000,000 4 = 160,000,000 0.85 (15% losses) so now we are down to 136,000,000 bits per second. Now we are down to 22.13 frame per second.. Remember this is not factoring rendering times. The more data on the display that is changing the longer it is going to take to render. If the background image is the entire display size expect it to take at least 20 milliseconds to render. Each time a DMA transaction completes a callback gets called via an ISR and that stops everything from running until the next DMA transaction starts. That's the latency that gets added in.

Those are theoretical numbers and you will not see those kinds of speeds. Not even close to those speeds. when you get down into the teens for frames per second it is not going to be smooth. You are going to end up with choppy animations.

I have been working on a new RGB driver. This driver is going to use a little more memory but it should be able to perform updates a lot faster.

Things you can do to help improve the speeds if you want to stick with the RGB display. Get a board that has an ESP32-S3 that has octal flash and octal ram. I say this because we can overclock the ram to get an effective clock speed of 240mhz instead of the 80mhz. This will help a massive amount in terms of updating the display.

If you can get an I8080 display that is the size and resolution you want that would make for faster updating of the display.

stop using the LVGL build in file system driver and get the images decoded before creating the widgets. Pass the decoded images to the widgets instead. This will eliminate having to decode the image each time it is moved...

kdschlosser commented 1 month ago

Do this as a test...

IDK now much memory you have and if you have enough do the following.

Edit lib/lv_conf.h and change the MICROPY_CACHE_SIZE to 768000 also change LV_IMAGE_HEADER_CACHE_DEF_CNT to 10

zjalen commented 1 month ago

Do this as a test...

IDK now much memory you have and if you have enough do the following.

Edit lib/lv_conf.h and change the MICROPY_CACHE_SIZE to 768000 also change LV_IMAGE_HEADER_CACHE_DEF_CNT to 10

@kdschlosser I am very grateful for your help. I am a beginner and not very familiar with this module. My board has an ESP32-S3-WROOM and an integrated screen.According to the information, the display driver chip is ILI9485. I have tried modifying the lv_conf.h file, and there was some improvement, but not significant. Could you please help me with how to make the most improvements, such as modifying the configuration driver or how to adjust settings for overclocking ram?

kdschlosser commented 1 month ago

You cannot overclock the memory unless you have Octal SPI RAM and Octal SPI Flash.

If you can give me a link to the datasheet for the board you have I can determine what is the best route to go.

kdschlosser commented 1 month ago

are you using the Sunton ESP32-8048S070C board? If you are this board is using quad SPI flash not octal.

I have in development a new RGB Bus driver that will hopefully improve the performance. I have written the code and it compiles but I have not tested it yet to see if it works or how it does performance wise.

My suggestion to you is to use an I8080 display. The problem with that is there are none that have an ESP32-S3 onboard in a 7: display with a resolution of 800x480. All the ones I am able to locate are RGB displays which is what you really need to stay away from.

If you are not opposed to wiring the ESP32 to the display yourself you can do this..

You can buy this display... https://www.buydisplay.com/7-tft-screen-touch-lcd-display-module-w-ssd1963-controller-board-mcu

and this ESP32 devkit... https://www.mouser.com/ProductDetail/Espressif-Systems/ESP32-S3-DevKitC-1-N32R8V?qs=Li%252BoUPsLEnvTvWIWLPCZ4g%3D%3D

You will need to get some 2.54mm female jumper wires to make the connections between the display and the ESP32-S3. It's not hard to do. you will need to design a board using a program like KiCad if you want something that you don't have to wire yourself. I can design the board for you but you would need to have the board made. The cost to make the board isn't bad if you do the assembly yourself. the price goes up if you have the board assembled with all of the needed components.

zjalen commented 1 month ago

You cannot overclock the memory unless you have Octal SPI RAM and Octal SPI Flash.

If you can give me a link to the datasheet for the board you have I can determine what is the best route to go.

It's ESP32-8048S043C. Here is a link: https://wiki.makerfabs.com/Sunton_ESP32_S3_4.3_inch_800x400_IPS_with_Touch.html

zjalen commented 1 month ago

I have another board with the display IC HX8369-A. According to the seller, it supports 8080. I tried to use I80Bus and RGBDisplay for display initialization, but it crashed immediately. I'm not sure if it’s a configuration error on my part.The esp module is ESP32-S3-WROOM-1-N16R8.

class Demo:
...
        i80bus = lcd_bus.I80Bus(
            dc=6,
            wr=11,
            cs=9,
            freq=13000000,
            data0=17,
            data1=18,
            data2=19,
            data3=20,
            data4=21,
            data5=22,
            data6=23,
            data7=24,
            data8=25
        )
        _BUF1 = self.rgb_bus.allocate_framebuffer(_WIDTH * _HEIGHT * 2, lcd_bus.MEMORY_SPIRAM)
        _BUF2 = self.rgb_bus.allocate_framebuffer(_WIDTH * _HEIGHT * 2, lcd_bus.MEMORY_SPIRAM)
        self.display = rgb_display.RGBDisplay(data_bus=i80bus, display_width=800, display_height=480,
                                              frame_buffer1=_BUF1, frame_buffer2=_BUF2, backlight_pin=2,
                                              color_space=lv.COLOR_FORMAT.RGB565, rgb565_byte_swap=False)

1727584415994

1727584444070 HX8369-A_DS_preliminary_v01_100713.pdf

kdschlosser commented 1 month ago

I just added the driver for the HX8369

kdschlosser commented 1 month ago

Here is an example of how to use the driver...


from micropython import const
import lcd_bus

_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)

bus = 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=40000000
)

import hx8369
import lvgl as lv

driver = hx8369.HX8369(
    data_bus=bus,
    display_width=480,
    display_height=800,
    reset_pin=_RESET,
    reset_state=hx8369.STATE_LOW,
    backlight_pin=_BL,
    # backlight_on_state=hx8369.STATE_LOW,
    color_space=lv.COLOR_FORMAT.RGB565,  # NOQA
    # rgb565_byte_swap=True
)

driver.init(hx8369.TYPE_A)
driver.set_backlight(100)

scrn = lv.screen_active()

slider = lv.slider(scrn)
slider.center()

import task_handler
task_handler.TaskHandler()
zjalen commented 1 month ago

@kdschlosser I've tried. There are 2 bugs.

# hx8369.py
# line 23  need `import time`
time.sleep_ms(25)  # NOQA

# line 54 should be`if value>= 255` and the variable `mapped_level` needs to be initialized.
        if value > 255:

I tried to fix the code.There are no output error messages at the moment; my screen just isn't displaying anything. It seems like the backlight turns on as soon as it's powered, regardless of any code being executed.

kdschlosser commented 1 month ago

ok so the schematic you sent is not correct...

zjalen commented 1 month ago

@kdschlosser I tried compiling the project examples that came with the board I purchased. I found that it can display and run normally. I found the definition of the hx8369 driver in the examples, which is consistent with what you provided. So, is there a problem with the driver here? I will provide the example for your reference.

// hx8369.c
/*
 * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stdlib.h>
#include <sys/cdefs.h>
#include "sdkconfig.h"
#if CONFIG_LCD_ENABLE_DEBUG_LOG
// The local log level must be defined before including esp_log.h
// Set the maximum log level for this source file
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#endif
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_lcd_panel_interface.h"
#include "esp_lcd_panel_io.h"
#include "esp_lcd_panel_vendor.h"
#include "esp_lcd_panel_ops.h"
#include "esp_lcd_panel_commands.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "esp_check.h"
#include "lvgl_helpers.h"
#include "hx8369.h"
static const char *TAG = "lcd_panel.hx8369";

#define PIN_NUM_DATA0 46
#define PIN_NUM_DATA1 3
#define PIN_NUM_DATA2 8
#define PIN_NUM_DATA3 18
#define PIN_NUM_DATA4 17
#define PIN_NUM_DATA5 16
#define PIN_NUM_DATA6 15
#define PIN_NUM_DATA7 7

#define PIN_NUM_PCLK 10
#define PIN_NUM_CS 12
#define PIN_NUM_DC 11
#define PIN_NUM_RST 9
#define PIN_NUM_BK_LIGHT 6

// Bit number used to represent command and parameter
#define LCD_CMD_BITS 8
#define LCD_PARAM_BITS 8

static esp_err_t panel_hx8369_del(esp_lcd_panel_t *panel);
static esp_err_t panel_hx8369_reset(esp_lcd_panel_t *panel);
static esp_err_t panel_hx8369_init(esp_lcd_panel_t *panel);
static esp_err_t panel_hx8369_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data);
static esp_err_t panel_hx8369_invert_color(esp_lcd_panel_t *panel, bool invert_color_data);
static esp_err_t panel_hx8369_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y);
static esp_err_t panel_hx8369_swap_xy(esp_lcd_panel_t *panel, bool swap_axes);
static esp_err_t panel_hx8369_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap);
//static 
esp_err_t panel_hx8369_disp_on_off(esp_lcd_panel_t *panel, bool off);

typedef struct
{
    esp_lcd_panel_t base;
    esp_lcd_panel_io_handle_t io;
    int reset_gpio_num;
    bool reset_level;
    int x_gap;
    int y_gap;
    unsigned int bits_per_pixel;
    uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register
    uint8_t colmod_cal; // save surrent value of LCD_CMD_COLMOD register
} hx8369_panel_t;

esp_err_t esp_lcd_new_panel_hx8369(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel)
{
#if CONFIG_LCD_ENABLE_DEBUG_LOG
    esp_log_level_set(TAG, ESP_LOG_DEBUG);
#endif
    esp_err_t ret = ESP_OK;
    hx8369_panel_t *hx8369 = NULL;
    ESP_GOTO_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
    hx8369 = calloc(1, sizeof(hx8369_panel_t));
    ESP_GOTO_ON_FALSE(hx8369, ESP_ERR_NO_MEM, err, TAG, "no mem for hx8369 panel");

    if (panel_dev_config->reset_gpio_num >= 0)
    {
        gpio_config_t io_conf = {
            .mode = GPIO_MODE_OUTPUT,
            .pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num,
        };
        ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed");
    }

    switch (panel_dev_config->color_space)
    {
    case ESP_LCD_COLOR_SPACE_RGB:
        hx8369->madctl_val = 0;
        break;
    case ESP_LCD_COLOR_SPACE_BGR:
        hx8369->madctl_val |= LCD_CMD_BGR_BIT;
        break;
    default:
        ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color space");
        break;
    }

    switch (panel_dev_config->bits_per_pixel)
    {
    case 16:
        hx8369->colmod_cal = 0x55;
        break;
    case 18:
        hx8369->colmod_cal = 0x66;
        break;
    default:
        ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width");
        break;
    }

    hx8369->io = io;
    hx8369->bits_per_pixel = panel_dev_config->bits_per_pixel;
    hx8369->reset_gpio_num = panel_dev_config->reset_gpio_num;
    hx8369->reset_level = panel_dev_config->flags.reset_active_high;
    hx8369->base.del = panel_hx8369_del;
    hx8369->base.reset = panel_hx8369_reset;
    hx8369->base.init = panel_hx8369_init;
    hx8369->base.draw_bitmap = panel_hx8369_draw_bitmap;
    hx8369->base.invert_color = panel_hx8369_invert_color;
    hx8369->base.set_gap = panel_hx8369_set_gap;
    hx8369->base.mirror = panel_hx8369_mirror;
    hx8369->base.swap_xy = panel_hx8369_swap_xy;
    //hx8369->base.disp_on_off = panel_hx8369_disp_on_off;
    hx8369->base.disp_off = panel_hx8369_disp_on_off;
    *ret_panel = &(hx8369->base);
    ESP_LOGD(TAG, "new hx8369 panel @%p", hx8369);

    return ESP_OK;

err:
    if (hx8369)
    {
        if (panel_dev_config->reset_gpio_num >= 0)
        {
            gpio_reset_pin(panel_dev_config->reset_gpio_num);
        }
        free(hx8369);
    }
    return ret;
}

static esp_err_t panel_hx8369_del(esp_lcd_panel_t *panel)
{
    hx8369_panel_t *hx8369 = __containerof(panel, hx8369_panel_t, base);

    if (hx8369->reset_gpio_num >= 0)
    {
        gpio_reset_pin(hx8369->reset_gpio_num);
    }
    ESP_LOGD(TAG, "del hx8369 panel @%p", hx8369);
    free(hx8369);
    return ESP_OK;
}

static esp_err_t panel_hx8369_reset(esp_lcd_panel_t *panel)
{
    hx8369_panel_t *hx8369 = __containerof(panel, hx8369_panel_t, base);
    esp_lcd_panel_io_handle_t io = hx8369->io;

    // perform hardware reset
    if (hx8369->reset_gpio_num >= 0)
    {
        gpio_set_level(hx8369->reset_gpio_num, hx8369->reset_level);
        vTaskDelay(pdMS_TO_TICKS(10));
        gpio_set_level(hx8369->reset_gpio_num, !hx8369->reset_level);
        vTaskDelay(pdMS_TO_TICKS(10));
    }
    else
    { // perform software reset
        esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0);
        vTaskDelay(pdMS_TO_TICKS(20)); // spec, wait at least 5m before sending new command
    }

    return ESP_OK;
}

static esp_err_t panel_hx8369_init(esp_lcd_panel_t *panel)
{
    hx8369_panel_t *hx8369 = __containerof(panel, hx8369_panel_t, base);
    esp_lcd_panel_io_handle_t io = hx8369->io;
    // Init LCD

    // Set_EXTC
    esp_lcd_panel_io_tx_param(io, 0xB9, (uint8_t[]){0xFF, 0x83, 0x69}, 3);
    // Set Power
    esp_lcd_panel_io_tx_param(io, 0xB1, (uint8_t[]){0x01, 0x00, 0x34, 0x06, 0x00, 0x0f, 0x0f, 0x2a, 0x32, 0x3f, //
                                                    0x3f, 0x07, 0x23, 0x01, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6},
                              19);

    // SET Display 480x800
    // 0x2b;0x20-MCU;0x29-DPI;RM,DM; RM=0:DPI IF;  RM=1:RGB IF;
    esp_lcd_panel_io_tx_param(io, 0xB2, (uint8_t[]){0x00, 0x20, 0x03, 0x03, 0x70, 0x00, 0xff, 0x00, 0x00, 0x00, //
                                                    0x00, 0x03, 0x03, 0x00, 0x01},
                              15);
    // SET Display CYC
    esp_lcd_panel_io_tx_param(io, 0xb4, (uint8_t[]){0x00, 0x0C, 0xA0, 0x0E, 0x06},
                              5);
    // SET VCOM
    esp_lcd_panel_io_tx_param(io, 0xb6, (uint8_t[]){0x2C, 0x2C},
                              2);

    // SET GIP
    esp_lcd_panel_io_tx_param(io, 0xD5, (uint8_t[]){0x00, 0x05, 0x03, 0x00, 0x01, 0x09, 0x10, 0x80, 0x37, 0x37, 0x20, 0x31, 0x46, //
                                                    0x8a, 0x57, 0x9b, 0x20, 0x31, 0x46, 0x8a, 0x57, 0x9b, 0x07, 0x0f, 0x02, 0x00},
                              26);

    //  SET GAMMA
    esp_lcd_panel_io_tx_param(io, 0xE0, (uint8_t[]){0x00, 0x08, 0x0d, 0x2d, 0x34, 0x3f, 0x19, 0x38, 0x09, 0x0e, 0x0e, 0x12, 0x14, 0x12, 0x14, 0x13, 0x19, //
                                                    0x00, 0x08, 0x0d, 0x2d, 0x34, 0x3f, 0x19, 0x38, 0x09, 0x0e, 0x0e, 0x12, 0x14, 0x12, 0x14, 0x13, 0x19},
                              34);

    // set DGC
    esp_lcd_panel_io_tx_param(io, 0xC1, (uint8_t[]){0x01, 0x02, 0x08, 0x12, 0x1a, 0x22, 0x2a, 0x31, 0x36, 0x3f, 0x48, 0x51, 0x58, 0x60, 0x68, 0x70, //
                                                    0x78, 0x80, 0x88, 0x90, 0x98, 0xa0, 0xa7, 0xaf, 0xb6, 0xbe, 0xc7, 0xce, 0xd6, 0xde, 0xe6, 0xef, //
                                                    0xf5, 0xfb, 0xfc, 0xfe, 0x8c, 0xa4, 0x19, 0xec, 0x1b, 0x4c, 0x40, 0x02, 0x08, 0x12, 0x1a, 0x22, //
                                                    0x2a, 0x31, 0x36, 0x3f, 0x48, 0x51, 0x58, 0x60, 0x68, 0x70, 0x78, 0x80, 0x88, 0x90, 0x98, 0xa0, //
                                                    0xa7, 0xaf, 0xb6, 0xbe, 0xc7, 0xce, 0xd6, 0xde, 0xe6, 0xef, 0xf5, 0xfb, 0xfc, 0xfe, 0x8c, 0xa4, //
                                                    0x19, 0xec, 0x1b, 0x4c, 0x40, 0x02, 0x08, 0x12, 0x1a, 0x22, 0x2a, 0x31, 0x36, 0x3f, 0x48, 0x51, //
                                                    0x58, 0x60, 0x68, 0x70, 0x78, 0x80, 0x88, 0x90, 0x98, 0xa0, 0xa7, 0xaf, 0xb6, 0xbe, 0xc7, 0xce, //
                                                    0xd6, 0xde, 0xe6, 0xef, 0xf5, 0xfb, 0xfc, 0xfe, 0x8c, 0xa4, 0x19, 0xec, 0x1b, 0x4c, 0x40},
                              127);

    //  Colour Set
    uint8_t cmd_192[192];
    for (size_t i = 0; i <= 63; i++)
    {
        cmd_192[i] = i * 8;
    }
    for (size_t i = 64; i <= 127; i++)
    {
        cmd_192[i] = i * 4;
    }
    for (size_t i = 128; i <= 191; i++)
    {
        cmd_192[i] = i * 8;
    }
    esp_lcd_panel_io_tx_param(io, 0x2D, cmd_192,
                              192);

    // LCD goes into sleep mode and display will be turned off after power on reset, exit sleep mode first
    esp_lcd_panel_io_tx_param(io, LCD_CMD_SLPOUT, NULL, 0);
    vTaskDelay(pdMS_TO_TICKS(100));
    esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]){
                                                      hx8369->madctl_val,
                                                  },
                              1);
    esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD, (uint8_t[]){
                                                      hx8369->colmod_cal,
                                                  },
                              1);

    return ESP_OK;
}

static esp_err_t panel_hx8369_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data)
{
    hx8369_panel_t *hx8369 = __containerof(panel, hx8369_panel_t, base);
    assert((x_start < x_end) && (y_start < y_end) && "start position must be smaller than end position");
    esp_lcd_panel_io_handle_t io = hx8369->io;

    x_start += hx8369->x_gap;
    x_end += hx8369->x_gap;
    y_start += hx8369->y_gap;
    y_end += hx8369->y_gap;

    // define an area of frame memory where MCU can access
    esp_lcd_panel_io_tx_param(io, LCD_CMD_CASET, (uint8_t[]){
                                                     (x_start >> 8) & 0xFF,
                                                     x_start & 0xFF,
                                                     ((x_end - 1) >> 8) & 0xFF,
                                                     (x_end - 1) & 0xFF,
                                                 },
                              4);
    esp_lcd_panel_io_tx_param(io, LCD_CMD_RASET, (uint8_t[]){
                                                     (y_start >> 8) & 0xFF,
                                                     y_start & 0xFF,
                                                     ((y_end - 1) >> 8) & 0xFF,
                                                     (y_end - 1) & 0xFF,
                                                 },
                              4);
    // transfer frame buffer
    size_t len = (x_end - x_start) * (y_end - y_start) * hx8369->bits_per_pixel / 8;
    esp_lcd_panel_io_tx_color(io, LCD_CMD_RAMWR, color_data, len);

    return ESP_OK;
}

static esp_err_t panel_hx8369_invert_color(esp_lcd_panel_t *panel, bool invert_color_data)
{
    hx8369_panel_t *hx8369 = __containerof(panel, hx8369_panel_t, base);
    esp_lcd_panel_io_handle_t io = hx8369->io;
    int command = 0;
    if (invert_color_data)
    {
        command = LCD_CMD_INVON;
    }
    else
    {
        command = LCD_CMD_INVOFF;
    }
    esp_lcd_panel_io_tx_param(io, command, NULL, 0);
    return ESP_OK;
}

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;
}

//static 
esp_err_t panel_hx8369_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
{
    hx8369_panel_t *hx8369 = __containerof(panel, hx8369_panel_t, base);
    esp_lcd_panel_io_handle_t io = hx8369->io;
    int command = 0;
    if (on_off)
    {
        command = LCD_CMD_DISPON;
    }
    else
    {
        command = LCD_CMD_DISPOFF;
    }
    esp_lcd_panel_io_tx_param(io, command, NULL, 0);
    return ESP_OK;
}
extern esp_err_t esp_lcd_new_panel_hx8369(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel);
extern  esp_err_t panel_hx8369_disp_on_off(esp_lcd_panel_t *panel, bool on_off);
static bool 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;
}

void 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);
}

    esp_lcd_panel_handle_t panel_handle;    
     lv_disp_drv_t disp_drv;      // contains callback functions
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);
    esp_lcd_panel_mirror(panel_handle, true, false);

    // 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));
}
// hx8369.h
/**
 * @file lv_templ.h
 *
 */

#ifndef HX8369_H
#define HX8369_H

#ifdef __cplusplus
extern "C" {
#endif

/*********************
 *      INCLUDES
 *********************/
#include <stdbool.h>

#include "esp_lcd_panel_interface.h"
#include "esp_lcd_types.h"
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif

#include "sdkconfig.h"

#define LCD_H_RES 800
#define LCD_V_RES 480
/*********************
 *      DEFINES
 *********************/
#define PIN_NUM_DATA0 46
#define PIN_NUM_DATA1 3
#define PIN_NUM_DATA2 8
#define PIN_NUM_DATA3 18
#define PIN_NUM_DATA4 17
#define PIN_NUM_DATA5 16
#define PIN_NUM_DATA6 15
#define PIN_NUM_DATA7 7

#define PIN_NUM_PCLK 10
#define PIN_NUM_CS 12
#define PIN_NUM_DC 11
#define PIN_NUM_RST 9
#define PIN_NUM_BK_LIGHT 6

// Bit number used to represent command and parameter
#define LCD_CMD_BITS 8
#define LCD_PARAM_BITS 8

#define LCD_PIXEL_CLOCK_HZ (20 * 1000 * 1000)
// Supported alignment: 16, 32, 64. A higher alignment can enables higher burst transfer size, thus a higher i80 bus throughput.
#define PSRAM_DATA_ALIGNMENT 64
/**********************
 *      TYPEDEFS
 **********************/

/**********************
 * GLOBAL PROTOTYPES
 **********************/
extern      lv_disp_drv_t disp_drv;      // contains callback functions
extern      esp_lcd_panel_handle_t panel_handle;
void lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map);
void    hx8369_init(void);

/**********************
 *      MACROS
 **********************/

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif /*HX8369_H*/
kdschlosser commented 1 month ago

I need to tweak it a little bit and then it will be good to go.

kdschlosser commented 1 month ago

OK I just pushed a commit to the repo. delete what you have and clone it again.

Here is the updated code to run..

from micropython import const
import lcd_bus

_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)

bus = 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
)

import hx8369
import lvgl as lv

driver = hx8369.HX8369(
    data_bus=bus,
    display_width=800,
    display_height=480,
    reset_pin=_RESET,
    reset_state=hx8369.STATE_LOW,
    backlight_pin=_BL,
    # backlight_on_state=hx8369.STATE_LOW,
    color_space=lv.COLOR_FORMAT.RGB565,  # NOQA
    # rgb565_byte_swap=True
)

driver.init(hx8369.TYPE_A)
driver.set_backlight(100)

scrn = lv.screen_active()

slider = lv.slider(scrn)
slider.center()

import task_handler
task_handler.TaskHandler()
zjalen commented 1 month ago

@kdschlosser I tried it, but it directly caused a crash.

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-09-30
IDF version : v5.2
Machine     : Generic ESP32S3 module with Octal-SPIRAM with ESP32S3

***ERROR*** A stack overflow in task IDLE0 has been detected.

Backtrace: 0x40376472:0x3fcafee0 0x40386321:0x3fcaff00 0x40386d0e:0x3fcaff20 0x403882a5:0x3fcaffa0 0x40386e64:0x3fcaffc0 0x40386e5a:0xa5a5a5a5 |<-CORRUPTED

ELF file SHA256: 9076df473

Rebooting...
kdschlosser commented 1 month ago

It did provide a stack trace. we need to decode it tho...

how you do that is running this command..

~/.espressif/tools/xtensa-esp32s3-elf/esp-12.2.0_20230208/xtensa-esp32s3-elf/bin/xtensa-esp32s3-elf-addr2line -aspCfire "~/lvgl_micropython/lib/micropython/ports/esp32/build-ESP32_GENERIC_S3-SPIRAM_OCT/micropython.elf" 0x40376472:0x3fcafee0 0x40386321:0x3fcaff00 0x40386d0e:0x3fcaff20 0x403882a5:0x3fcaffa0 0x40386e64:0x3fcaffc0 0x40386e5a:0xa5a5a5a5
zjalen commented 1 month ago

do you mean this?

~/.espressif/tools/xtensa-esp32s3-elf/esp-2022r1-11.2.0/xtensa-esp32s3-elf/bin/xtensa-esp32s3-elf-addr2line -aspCfire ~/GitHub/lvgl_micropython/lib/micropython/ports/esp32/build-ESP32_GENERIC_S3-SPIRAM_OCT/micropython.elf 0x40376472:0x3fcafee0 0x40386321:0x3fcaff00 0x40386d0e:0x3fcaff20 0x403882a5:0x3fcaffa0 0x40386e64:0x3fcaffc0 0x40386e5a:0xa5a5a5a5
0x40376472: panic_abort at panic.c:472
0x40386321: esp_system_abort at esp_system_chip.c:93
0x40386d0e: vApplicationStackOverflowHook at port.c:553
0x403882a5: vTaskSwitchContext at tasks.c:3630 (discriminator 7)
0x40386e64: _frxt_dispatch at portasm.S:451
0x40386e5a: _frxt_int_exit at portasm.S:246
kdschlosser commented 1 month ago

That's not giving me a damned bit of useful information.

kdschlosser commented 1 month ago

try running just the firmware without uploading any code and see if you are able to get to a repl.

zjalen commented 1 month ago

Yes, I can get to a repl.And I know which line of code caused the crash.

>>> driver.init(hx8369.TYPE_A)

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-09-30
IDF version : v5.2
Machine     : Generic ESP32S3 module with Octal-SPIRAM with ESP32S3

***ERROR*** A stack overflow in task IDLE0 has been detected.

Backtrace: 0x40376472:0x3fcafee0 0x40386321:0x3fcaff00 0x40386d0e:0x3fcaff20 0x403882a5:0x3fcaffa0 0x40386e64:0x3fcaffc0 0x40386e5a:0xa5a5a5a5 |<-CORRUPTED

ELF file SHA256: 9076df473

Rebooting...
kdschlosser commented 1 month ago

ok so what line of code is causing the crash.. Don't keep me in the dark here

zjalen commented 1 month ago

sorry, I mean this driver.init(hx8369.TYPE_A).I will try to check _hx8369_init_type1.py and test to see if I can resolve the issue.

zjalen commented 1 month ago

ok so what line of code is causing the crash.. Don't keep me in the dark here

@kdschlosser This line cause the crash.

# _hx8369_init_type1.py   line 77
    self.set_params(0xC1, param_mv[:127])

I printed out the list data param_mv[:127] and compared it. It's correct.

['0x1', '0x2', '0x8', '0x12', '0x1a', '0x22', '0x2a', '0x31', '0x36', '0x3f', '0x48', '0x51', '0x58', '0x60', '0x68', '0x70', '0x78', '0x80', '0x88', '0x90', '0x98', '0xa0', '0xa7', '0xaf', '0xb6', '0xbe', '0xc7', '0xce', '0xd6', '0xde', '0xe6', '0xef', '0xf5', '0xfb', '0xfc', '0xfe', '0x8c', '0xa4', '0x19', '0xec', '0x1b', '0x4c', '0x40', '0x2', '0x8', '0x12', '0x1a', '0x22', '0x2a', '0x31', '0x36', '0x3f', '0x48', '0x51', '0x58', '0x60', '0x68', '0x70', '0x78', '0x80', '0x88', '0x90', '0x98', '0xa0', '0xa7', '0xaf', '0xb6', '0xbe', '0xc7', '0xce', '0xd6', '0xde', '0xe6', '0xef', '0xf5', '0xfb', '0xfc', '0xfe', '0x8c', '0xa4', '0x19', '0xec', '0x1b', '0x4c', '0x40', '0x2', '0x8', '0x12', '0x1a', '0x22', '0x2a', '0x31', '0x36', '0x3f', '0x48', '0x51', '0x58', '0x60', '0x68', '0x70', '0x78', '0x80', '0x88', '0x90', '0x98', '0xa0', '0xa7', '0xaf', '0xb6', '0xbe', '0xc7', '0xce', '0xd6', '0xde', '0xe6', '0xef', '0xf5', '0xfb', '0xfc', '0xfe', '0x8c', '0xa4', '0x19', '0xec', '0x1b', '0x4c', '0x40']
kdschlosser commented 1 month ago

line 77 is not the set_params it is the adding of the data to the buffer. Maybe it has some kind of an issue because of the amount of data that is being set at a single time. I am going to break it into 64 byte chunks.

kdschlosser commented 1 month ago

OK I broke it into 2 parts.

Lemme know if that fixes the problem.

zjalen commented 1 month ago

Very strange, it's still the same issue.Both of these 2 lines cause the crash. If I comment out these 2 lines, it doesn't crash. But of course the display doesn't run normaly.

    self.set_params(0xC1, param_mv[:127]) # line 85
...
    self.set_params(0x2D, param_mv[:192]) # line 97
kdschlosser commented 1 month ago

The issue is here.. ...

***ERROR*** A stack overflow in task IDLE0 has been detected.

the stack is too small. Lemme code in an adjustment for it.

kdschlosser commented 1 month ago

OK you are going to have to clone the repo again and rebuild. This time add --task-stack-size=22528 to your build command.

That will increase the stack size by an additional 4K of memory. That should be more than ample to allow the init commands to run without an issue.

I believe the reason why this may have happened is because of a change I made with the way the init commands import dynamically. It is allocating the memory for that import on the stack which is what I want because I want the init commands not staying resident in memory once they have been run. You can adjust the stack size if you want. It MUST be a multiple of 1024.

kdschlosser commented 1 month ago

I am going to do some reading on the display IC as I believe there are a shit load of params being set all at once in those 2 monster sends.

zjalen commented 1 month ago

Regardless of whether parameters --task-stack-size=22528 are added or not, the result is a build failure.

[1304/1960] Building C object esp-idf/main_esp32s3/CMakeFiles/__idf_main_esp32s3.dir/Users/jalen/GitHub/lvgl_micropython/lib/micropython/extmod/vfs.c.obj
In file included from /Users/jalen/GitHub/lvgl_micropython/lib/micropython/py/mpconfig.h:91,
from /Users/jalen/GitHub/lvgl_micropython/lib/micropython/py/mpstate.h:31,
from /Users/jalen/GitHub/lvgl_micropython/lib/micropython/py/runtime.h:29,
from /Users/jalen/GitHub/lvgl_micropython/lib/micropython/extmod/vfs.c:30:
/Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/mpconfigport.h:14: warning: "MICROPY_TASK_STACK_SIZE" redefined
14 | #define MICROPY_TASK_STACK_SIZE           (20 * 1024)
|
/Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/mpconfigport.h:13: note: this is the location of the previous definition
13 | #define MICROPY_TASK_STACK_SIZE           (22 * 1024)
|
/Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/mpconfigport.h:15: warning: "MICROPY_TASK_STACK_SIZE" redefined
15 | #define MICROPY_TASK_STACK_SIZE           (16 * 1024)
|
/Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/mpconfigport.h:14: note: this is the location of the previous definition
14 | #define MICROPY_TASK_STACK_SIZE           (20 * 1024)
|
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_41578 and /Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/build-ESP32_GENERIC_S3-SPIRAM_OCT/log/idf_py_stdout_output_41578
-e See https://github.com/micropython/micropython/wiki/Build-Troubleshooting
make: *** [all] Error 1
kdschlosser commented 1 month ago

OK I see where the issue is. Give me a minute to correct it.

kdschlosser commented 1 month ago

OK so as it turns out the default stack size is 6656 bytes. bump that up to 7168 and it should work fine. That adds 512 bytes for the stack.

kdschlosser commented 1 month ago

You will need to delete the repo and clone it again because of hot patching the MicroPython files.

kdschlosser commented 1 month ago

scratch that last comment about the default value. I was right the first go around. the default size is 16 * 1024.. so add an additional 512 bytes to that number and see how goes.

zjalen commented 1 month ago

I have pulled the latest code to ensure it is consistent with the repository. However, I'm still getting errors when I try to compile.

python3 make.py esp32 BOARD=ESP32_GENERIC_S3 BOARD_VARIANT=SPIRAM_OCT --flash-size=16 DISPLAY=hx8369 INDEV=gt911 PORT=/dev/cu.usbserial-14430
/Users/jalen/GitHub/lvgl_micropython/lib/micropython/extmod/modbluetooth.c:43:2: error: #error modbluetooth requires MICROPY_ENABLE_SCHEDULER
43 | #error modbluetooth requires MICROPY_ENABLE_SCHEDULER
|  ^~~~~
/Users/jalen/GitHub/lvgl_micropython/lib/micropython/extmod/vfs_fat.c:32:2: error: #error "MICROPY_VFS_FAT requires MICROPY_ENABLE_FINALISER"
32 | #error "MICROPY_VFS_FAT requires MICROPY_ENABLE_FINALISER"
|  ^~~~~
In file included from /Users/jalen/GitHub/lvgl_micropython/lib/micropython/extmod/vfs_lfs.c:140:
/Users/jalen/GitHub/lvgl_micropython/lib/micropython/extmod/vfs_lfsx.c:43:2: error: #error "MICROPY_VFS_LFS requires MICROPY_ENABLE_FINALISER"
43 | #error "MICROPY_VFS_LFS requires MICROPY_ENABLE_FINALISER"
|  ^~~~~
In file included from /Users/jalen/GitHub/lvgl_micropython/lib/micropython/extmod/vfs_lfs.c:141:
/Users/jalen/GitHub/lvgl_micropython/lib/micropython/extmod/vfs_lfsx_file.c:95:126: error: macro "mp_obj_malloc_var" requires 5 arguments, but only 4 given
95 |     MP_OBJ_VFS_LFSx_FILE *o = mp_obj_malloc_var_with_finaliser(MP_OBJ_VFS_LFSx_FILE, uint8_t, self->lfs.cfg->cache_size, type);
|                                                                                                                              ^
In file included from /Users/jalen/GitHub/lvgl_micropython/lib/micropython/py/mpstate.h:35,
from /Users/jalen/GitHub/lvgl_micropython/lib/micropython/py/runtime.h:29,
from /Users/jalen/GitHub/lvgl_micropython/lib/micropython/extmod/vfs_lfs.c:27:
/Users/jalen/GitHub/lvgl_micropython/lib/micropython/py/obj.h:919: note: macro "mp_obj_malloc_var" defined here
919 | #define mp_obj_malloc_var(struct_type, var_field, var_type, var_num, obj_type) ((struct_type *)mp_obj_malloc_helper(offsetof(struct_type, var_field) + sizeof(var_type) * (var_num), obj_type))
|
In file included from /Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/modespnow.c:49:
/Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/mpconfigport.h:16:35: warning: extra tokens at end of #undef directive
16 |     #undef MICROPY_TASK_STACK_SIZE#endif#define MICROPY_TASK_STACK_SIZE           (16384)#ifndef MICROPY_CONFIG_ROM_LEVEL
|                                   ^
/Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/mpconfigport.h:17: warning: "MICROPY_CONFIG_ROM_LEVEL" redefined
17 | #define MICROPY_CONFIG_ROM_LEVEL            (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES)
|
In file included from /Users/jalen/GitHub/lvgl_micropython/lib/micropython/py/mpstate.h:31,
from /Users/jalen/GitHub/lvgl_micropython/lib/micropython/py/runtime.h:29,
from /Users/jalen/GitHub/lvgl_micropython/lib/micropython/ports/esp32/modespnow.c:39:
/Users/jalen/GitHub/lvgl_micropython/lib/micropython/py/mpconfig.h:96: note: this is the location of the previous definition
96 | #define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_CORE_FEATURES)
|
kdschlosser commented 1 month ago

give it a try again

zjalen commented 1 month ago

Firmware build success.But it seems like the same crash issue persists.

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-01
IDF version : v5.2
Machine     : Generic ESP32S3 module with Octal-SPIRAM with ESP32S3

***ERROR*** A stack overflow in task IDLE0 has been detected.

Backtrace: 0x40376472:0x3fcafee0 0x40386321:0x3fcaff00 0x40386d0e:0x3fcaff20 0x403882a5:0x3fcaffa0 0x40386e64:0x3fcaffc0 0x40386e5a:0xa5a5a5a5 |<-CORRUPTED

ELF file SHA256: 6fbde6d1b

Rebooting...
ESP-ROM:esp32s3-202103
kdschlosser commented 1 month ago

and what are you upping the stack size to? try setting it at 32K...

zjalen commented 1 month ago

I tried using parameters python3 make.py esp32 BOARD=ESP32_GENERIC_S3 BOARD_VARIANT=SPIRAM_OCT --flash-size=16 DISPLAY=hx8369 INDEV=gt911 PORT=/dev/cu.usbserial-14430 --task-stack-size=32768.And I also tried directly modifying the file builder/esp32.py to set line 165 task_stack_size = 32 * 1024, but the results were the same.

I've attached the sdkconfig file from the demo code that I was able to run successfully. I hone it can help you identify the issue.

sdkconfig.zip

kdschlosser commented 1 month ago

awww shit... are you compiling under OSX??

zjalen commented 1 month ago

yes, macos 12.7.6.

kdschlosser commented 1 month ago

OK do this... Add this to your build command...

CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=8192

kdschlosser commented 1 month ago

so use this for your build command...

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