lvgl-micropython / lvgl_micropython

LVGL module for MicroPython
MIT License
80 stars 25 forks source link

Downloadable standard builds? #26

Open TecDroiD opened 7 months ago

TecDroiD commented 7 months ago

As far as I understand, you already build lvgl_micropython automatically for several computer architectures. Sadly, I can't build it and don't understand why. I suppose that I have some environment, your automatic builder has.

Is it possible to make them downloadable, at least for esp32 and esp32s3 architectures?

kdschlosser commented 7 months ago

It's broken at the moment and I am working on getting it fixed. This project is still very much under development and is in an alpha test state and is going to have problems.

What are you wanting to compile for it for? What display, touch screen and MCU?

TecDroiD commented 7 months ago

I need it for those yellow chinese boards. ESP32-S3 with an 800/480 ST7262 TFT and GT911 touch: https://de.aliexpress.com/item/1005005100043791.html

kdschlosser commented 7 months ago

The build should be fixed now. Those yellow Chinese boards can be fickle to get going depending on the bus type that is being used.

TecDroiD commented 7 months ago

this compiled but I see the problem you talked about. Seems, I have to find or build some driver for the ST72xx since it is parallel..

Kevin Schlosser @.***> schrieb am Mi., 10. Apr. 2024, 11:58:

It's broken at the moment and I am working on getting it fixed. This project is still very much under development and is in an alpha test state and is going to have problems.

What are you wanting to compile for it for? What display, touch screen and MCU?

— Reply to this email directly, view it on GitHub https://github.com/kdschlosser/lvgl_micropython/issues/26#issuecomment-2047088450, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAA535XAHFWFGBQLWUTKZ5DY4UEMPAVCNFSM6AAAAABF75L2O2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDANBXGA4DQNBVGA . You are receiving this because you authored the thread.Message ID: @.***>

kdschlosser commented 7 months ago

what is the display IC model number? What is the bus connection between the ESP32 and the display IC?

TecDroiD commented 7 months ago

that's what i'm currently trying to figure out. I suppose it's ST7262. But for the last few days, I couldn't download the files from jcnz1688.com. As far as I know, it supports parallel, I2C and SPI. Sadly, without Schematic's, I don't know which pins are used and connected where.. In worst case, i'll have to "ring" them out..

kdschlosser commented 7 months ago

OH... it doesn't matter. It's an RGB display. So the display IC is moot anywho.

This is the command line you want to use to build it.

python3 make.py esp32 mpy_cross submodules clean BOARD=ESP32_GENERIC_S3 BOARD_VARIANT=SPIRAM_OCT DISPLAY=rgb_display INDEV=gt911

At the end of the built it will tell you how to flash the MCU. make sure you run BOTH commands when flashing. The first command erases the memory and the second writes the firmware. for the second command you are going to have to change the -b 921600 to -b 460800 this is because of the lower grade UART IC that was used.

kdschlosser commented 7 months ago

Here is some test code you can run. This should have all of the correct pinouts set for your MCU

from micropython import const  # NOQA
import i2c

_WIDTH = const(800)
_HEIGHT = const(480)

_CTP_SCL = const(9)
_CTP_SDA = const(8)
_CTP_IRQ = const(4)

_SD_MOSI = const(11)
_SD_SCK = const(12)
_SD_MISO = const(13)

_LCD_FREQ = const(13000000)
_PCLK_ACTIVE_NEG = const(0)

_HSYNC_PULSE_WIDTH = const(10)
_HSYNC_BACK_PORCH = const(10)
_HSYNC_FRONT_PORCH = const(10)

_VSYNC_PULSE_WIDTH = const(10)
_VSYNC_BACK_PORCH = const(10)
_VSYNC_FRONT_PORCH = const(20)

_PCLK = const(7)
_HSYNC = const(46)
_VSYNC = const(3)
_DE = const(5)
_DISP = const(-1)
_BCKL = None
_DRST = None
_DPWR = None

I2C_BUS = i2c.I2CBus(
    scl=_CTP_SCL,
    sda=_CTP_SDA,
    freq=400000,
    use_locks=False
)

_DATA15 = const(10)  # B7
_DATA14 = const(17)  # B6
_DATA13 = const(18)  # B5
_DATA12 = const(38)  # B4
_DATA11 = const(14)  # B3
_DATA10 = const(21)  # G7
_DATA9 = const(47)  # G6
_DATA8 = const(48)  # G5
_DATA7 = const(45)  # G4
_DATA6 = const(0)  # G3
_DATA5 = const(39)  # G2
_DATA4 = const(40)  # R7
_DATA3 = const(41)  # R6
_DATA2 = const(42)  # R5
_DATA1 = const(2)  # R4
_DATA0 = const(1)  # R3

import lcd_bus  # NOQA

bus = lcd_bus.RGBBus(
    hsync=_HSYNC,
    vsync=_VSYNC,
    de=_DE,
    disp=_DISP,
    pclk=_PCLK,
    data0=_DATA0,
    data1=_DATA1,
    data2=_DATA2,
    data3=_DATA3,
    data4=_DATA4,
    data5=_DATA5,
    data6=_DATA6,
    data7=_DATA7,
    data8=_DATA8,
    data9=_DATA9,
    data10=_DATA10,
    data11=_DATA11,
    data12=_DATA12,
    data13=_DATA13,
    data14=_DATA14,
    data15=_DATA15,
    freq=_LCD_FREQ,
    hsync_front_porch=_HSYNC_FRONT_PORCH,
    hsync_back_porch=_HSYNC_BACK_PORCH,
    hsync_pulse_width=_HSYNC_PULSE_WIDTH,
    hsync_idle_low=False,
    vsync_front_porch=_VSYNC_FRONT_PORCH,
    vsync_back_porch=_VSYNC_BACK_PORCH,
    vsync_pulse_width=_VSYNC_PULSE_WIDTH,
    vsync_idle_low=False,
    de_idle_high=False,
    pclk_idle_high=False,
    pclk_active_low=_PCLK_ACTIVE_NEG,
    disp_active_low=False,
    refresh_on_demand=False
)

buf1 = bus.allocate_framebuffer(_WIDTH * _HEIGHT * 2, lcd_bus.MEMORY_SPIRAM)
buf2 = bus.allocate_framebuffer(_WIDTH * _HEIGHT * 2, lcd_bus.MEMORY_SPIRAM)

import lvgl as lv  # NOQA
import rgb_display  # NOQA

lv.init()

display = rgb_display.RGBDisplay(
    data_bus=bus,
    display_width=_WIDTH,
    display_height=_HEIGHT,
    frame_buffer1=buf1,
    frame_buffer2=buf2,
    reset_pin=_DRST,
    reset_state=rgb_display.STATE_HIGH,
    power_pin=_DPWR,
    power_on_state=rgb_display.STATE_HIGH,
    backlight_pin=_BCKL,
    backlight_on_state=rgb_display.STATE_HIGH,
    color_space=lv.COLOR_FORMAT.RGB565,
    rgb565_byte_swap=True
)

display.set_power(True)
display.init()
display.set_backlight(100)

import time  # NOQA
import gt911  # NOQA

indev = gt911.GT911(I2C_BUS)

scrn = lv.screen_active()
scrn.set_style_bg_color(lv.color_hex(0x000000), 0)

slider = lv.slider(scrn)
slider.set_size(500, 75)
slider.center()

while True:
    time.sleep_ms(1)
    lv.tick_inc(1)
    lv.task_handler()

If you have a problem with the touch not working properly lemme know I will tell you how to fix it.

TecDroiD commented 7 months ago

Wellllll... sadly, these pinouts aren't correct. But... I could download the correct documentation zip from jncz1688... (5.0inch_ESP32-8048S050.zip) hopefully... if so, this should be correct

bus = lcd_bus.RGBBus(
            hsync=const(39),
            vsync=const(41),
            de=const(40),
            disp=const(-1),
            pclk=const(42),
            data0=const(45),
            data1=const(48),
            data2=const(47),
            data3=const(21),
            data4=const(14),
            data5=const(5),
            data6=const(6),
            data7=const(7),
            data8=const(15),
            data9=const(16),
            data10=const(4),
            data11=const(8),
            data12=const(3),
            data13=const(46),
            data14=const(9),
            data15=const(1),
            )

but sadly, display stays black.. even if I try something like scr.set_style_bg_color(lv.color_hex(0xafafaf), 0)

kdschlosser commented 7 months ago

Those pinouts are for the exact board you are using. https://github.com/kdschlosser/lvgl_micropython/issues/20

kdschlosser commented 7 months ago

Try the cod exactly as I had it and see what happens. I am pretty sure those are the correct pinouts and the correct hsync and vsync settings.

TecDroiD commented 7 months ago

this one worked https://github.com/kdschlosser/lvgl_micropython/issues/20#issuecomment-2018132684 next is getting the gt911 working.. ... ... edit: works! I got the feeling that there is some minimal (or extremely fast) flickering.. well, i'll experiment with it a little.

kdschlosser commented 7 months ago

Are you using double buffering?

kdschlosser commented 7 months ago

If you are saying this code works...

import time, micropython
micropython.mem_info()

import lcd_bus
display_bus = lcd_bus.RGBBus(
    hsync = 39,
    vsync = 41,
    de = 40,
    disp = -1,
    pclk = 42,  # to TFT DCLK
    data0  = 8,  data1  = 3,  data2  = 46, data3  = 9,  data4  = 1,  # B
    data5  = 5,  data6  = 6,  data7  = 7,  data8  = 15, data9  = 16, data10 = 4,  # G
    data11 = 45, data12 = 48, data13 = 47, data14 = 21, data15 = 14,  # R
    freq = 12000000,
    hsync_front_porch = 8,
    hsync_back_porch = 8,
    hsync_pulse_width = 4,
    hsync_idle_low = True,
    vsync_front_porch = 8,
    vsync_back_porch = 8,
    vsync_pulse_width = 4,
    vsync_idle_low = True,
    de_idle_high = False,
    pclk_idle_high = False,
    pclk_active_low = True,
    disp_active_low = False,
)

import rgb_display
import lvgl as lv
display = rgb_display.RGBDisplay(
    data_bus = display_bus,
    display_width = 800,
    display_height = 480,
    backlight_pin = 2,
    color_byte_order = rgb_display.BYTE_ORDER_BGR,
    color_space = lv.COLOR_FORMAT.RGB565,
)

display.init()
display.set_backlight(100)

scrn = lv.screen_active()
scrn.set_style_bg_color(lv.color_hex(0x000000), 0)

slider = lv.slider(scrn)
slider.set_size(200, 50)
slider.center()

while True:
    time.sleep_ms(1)
    lv.tick_inc(1)
    lv.task_handler()

change it to this

from micropython import const  # NOQA
import i2c

_WIDTH = const(800)
_HEIGHT = const(480)

_CTP_SCL = const(20)
_CTP_SDA = const(19)

_LCD_FREQ = const(13000000)
_PCLK_ACTIVE_NEG = const(1)

_HSYNC_PULSE_WIDTH = const(4)
_HSYNC_BACK_PORCH = const(8)
_HSYNC_FRONT_PORCH = const(8)

_VSYNC_PULSE_WIDTH = const(4)
_VSYNC_BACK_PORCH = const(8)
_VSYNC_FRONT_PORCH = const(8)

_PCLK = const(42)
_HSYNC = const(39)
_VSYNC = const(41)
_DE = const(40)
_DISP = const(-1)
_BCKL = const(2)
_DRST = None
_DPWR = None

I2C_BUS = i2c.I2CBus(
    scl=_CTP_SCL,
    sda=_CTP_SDA,
    freq=400000,
    use_locks=False
)

_DATA15 = const(14)  # B7
_DATA14 = const(21)  # B6
_DATA13 = const(47)  # B5
_DATA12 = const(48)  # B4
_DATA11 = const(45)  # B3
_DATA10 = const(4)  # G7
_DATA9 = const(16)  # G6
_DATA8 = const(15)  # G5
_DATA7 = const(7)  # G4
_DATA6 = const(6)  # G3
_DATA5 = const(5)  # G2
_DATA4 = const(1)  # R7
_DATA3 = const(9)  # R6
_DATA2 = const(46)  # R5
_DATA1 = const(3)  # R4
_DATA0 = const(8)  # R3

import lcd_bus  # NOQA

bus = lcd_bus.RGBBus(
    hsync=_HSYNC,
    vsync=_VSYNC,
    de=_DE,
    disp=_DISP,
    pclk=_PCLK,
    data0=_DATA0,
    data1=_DATA1,
    data2=_DATA2,
    data3=_DATA3,
    data4=_DATA4,
    data5=_DATA5,
    data6=_DATA6,
    data7=_DATA7,
    data8=_DATA8,
    data9=_DATA9,
    data10=_DATA10,
    data11=_DATA11,
    data12=_DATA12,
    data13=_DATA13,
    data14=_DATA14,
    data15=_DATA15,
    freq=_LCD_FREQ,
    hsync_front_porch=_HSYNC_FRONT_PORCH,
    hsync_back_porch=_HSYNC_BACK_PORCH,
    hsync_pulse_width=_HSYNC_PULSE_WIDTH,
    hsync_idle_low=True,
    vsync_front_porch=_VSYNC_FRONT_PORCH,
    vsync_back_porch=_VSYNC_BACK_PORCH,
    vsync_pulse_width=_VSYNC_PULSE_WIDTH,
    vsync_idle_low=True,
    de_idle_high=False,
    pclk_idle_high=False,
    pclk_active_low=_PCLK_ACTIVE_NEG,
    disp_active_low=False
)

buf1 = bus.allocate_framebuffer(_WIDTH * _HEIGHT * 2, lcd_bus.MEMORY_SPIRAM)
buf2 = bus.allocate_framebuffer(_WIDTH * _HEIGHT * 2, lcd_bus.MEMORY_SPIRAM)

import lvgl as lv  # NOQA
import rgb_display  # NOQA

lv.init()

display = rgb_display.RGBDisplay(
    data_bus=bus,
    display_width=_WIDTH,
    display_height=_HEIGHT,
    frame_buffer1=buf1,
    frame_buffer2=buf2,
    reset_pin=_DRST,
    reset_state=rgb_display.STATE_HIGH,
    power_pin=_DPWR,
    power_on_state=rgb_display.STATE_HIGH,
    backlight_pin=_BCKL,
    backlight_on_state=rgb_display.STATE_HIGH,
    color_space=lv.COLOR_FORMAT.RGB565,
    rgb565_byte_swap=True
)

display.set_power(True)
display.init()
display.set_backlight(100)

import time  # NOQA
import gt911  # NOQA

indev = gt911.GT911(I2C_BUS)

scrn = lv.screen_active()
scrn.set_style_bg_color(lv.color_hex(0x000000), 0)

slider = lv.slider(scrn)
slider.set_size(500, 75)
slider.center()

while True:
    time.sleep_ms(1)
    lv.tick_inc(1)
    lv.task_handler()
TecDroiD commented 7 months ago

looks good to me. Short question. how is the color defined? my former experiment gave a blue slider, now it's yellow. I suppose its the byte order which was set to BGR in the former code. which one is right?

kdschlosser commented 7 months ago

delete this line from the code

    rgb565_byte_swap=True
TecDroiD commented 7 months ago

that way it's usable. thank you.

kdschlosser commented 7 months ago

which code are you using? If you are using the code I gave you 2-3 posts back try removing the byte swap and tell me what it comes out as.

TecDroiD commented 7 months ago

thats what i meant :) removing the byte swap in the double buffering code (https://github.com/kdschlosser/lvgl_micropython/issues/26#issuecomment-2049427760) gives me plausible colors :)

kdschlosser commented 7 months ago

There are many things that can effect the color when dealing with an RGB display. It could be the data pin assignments, it could be the color format that is passed to LVGL, to could be byte swapping and lastly it could be the order of the colors.

When dealing with RGB565 this gets a bit tricky. With RGB565 it is literally as it states, 5 bits for reg 6 bits for green and 5 bits for blue. The least signifigant bits are the ones that get cut off. If you change the color order from RGB to BGR you get this..

                    byte 1                |                byte 2
         ===================================================================
RGB      r3, r4, r5, r6, r7, g2, g3, g4   |   g5, g6, g7, b3, b4, b5, b6, b7

BGR      b3, b4, b5, b6, b7, g2, g3, g4   |   g5, g6, g7, r3, r4, r5, r6, r7

now if we "byte swap that you end up with this.

                    byte 1                |                byte 2
         ===================================================================
RGB      g5, g6, g7, b3, b4, b5, b6, b7   |   r3, r4, r5, r6, r7, g2, g3, g4

BGR      g5, g6, g7, r3, r4, r5, r6, r7   |   b3, b4, b5, b6, b7, g2, g3, g4 

Technically speaking when using an RGB display the number of pins is equal to the color depth being used. That is because each pin represents one bit of the color depth. IF and I am really stressing the IF here. IF the board manufacturer has proper documentation and they have mapped the pin to bit color properly then you should only have to instruct the driver of the color depth being used.

I have found that when using a 16 lane (pin) RGB display that this is not always the case. For whatever reason the documentation has the pin order messed up. Using the rgb565 byte swap corrects this problem. the byte swapping typically has to be done for SPI and I8080 connections and this is because of a difference in processor design between the MCU and the display driver IC and to correct the problem the frame buffer needs to be iterated over having the bytes flip flopped for each pixel. What I did for the 16 lane RGB displays was flip flopping the pins instead. This improves performance because the frame buffer doesn't have to be iterated over.

BGR is almost never used for RGB displays. As the name suggests for the RGB display the byte order is going to be RGB. The color format in LVGL needs to be set to RGB565 if the connection is 16 lanes. If the colors are not right when doing that then try setting the rgb565 byte swap to True. That would need to be done because of poor documentation which is not all that surprising to see from a Chinese manufacturer. This "glitch" in the documentation comes from the hardware designers not communicating with the people that write the documentation. If the display deals in MSB byte order but the MCU deals in LSB byte order you end up with this flip flop not being taken into account. The datasheet for the display refers to the pins as R0, R1, R2... etc and when connected to the MCU those same labels are when get used when they really shouldn't.

Make sense?

TecDroiD commented 7 months ago

well, yes. thank you.