lvgl / lv_binding_micropython

LVGL binding for MicroPython
MIT License
250 stars 161 forks source link

Support ESP32-S2, ESP32-C3, ESP32-S3 #227

Open amirgon opened 2 years ago

amirgon commented 2 years ago

Micropython already supports ESP32, ESP32-S2, ESP32-C3, ESP32-S3. However lv_micropython only supports ESP32 today.

The goal is to add support for ESP32-S2, ESP32-C3, ESP32-S3 in lv_binding_micropython and lv_micropython.

This includes:

Related issues:


This is a sponsored issue, meaning that if someone implements it he or she gets a payment from the Accumulated donations of LVGL. Learn more HERE.

We can give 100 USD for fully implementing this.

CC: @kisvegabor @embeddedt

424778940z commented 1 year ago

Run in to this issue while I was looking for support for imxrt11xx platforms, since the main repo already supported them.

I would like to do it my own, but I could not find any detailed document for what exactly need to be done.

The readme of this repo is all about how to use this lvgl as a mp module, but mothing about porting.

Another article I could find is this https://blog.lvgl.io/2019-02-20/micropython-bindings "Can I use LittlevGL binding on XXXX Micropython fork? Probably yes! You would need to add Micropython Binding for LittlevGL as a submodule in your fork, and make some small changes to the Makefile and mpconfigport.h in your port, but that’s about it. For more details please have a look at the README."

The readme link is link to this repo's readme, bruh... And about "make some small changes", sure, but what? This is the same felling of MS error messages says "Something went wrong" My honest suggestion, better use that $100 hire someone for documentation on and create some examples, that allows people who want help could help right the way, instad of read all sources and scripts to understand what to do first.

amirgon commented 1 year ago

@424778940z - See https://github.com/lvgl/lv_binding_micropython/pull/242. That PR still needs some work, but when it's merged you will be able to add LVGL as a Micropython external C module, so porting to new architectures will be much easier.

This issue is about supporting ESP32-S2, ESP32-C3, ESP32-S3 because ESP ports have an extra complication where in addition to LVGL, the ESP BSP library API (ESP-IDF) is automatically converted too, so users can use it directly in Python code. (See Pure Micropython Display Driver in the blog).

You are right that the documentation focuses mostly on how to use the Micropython bindings. That's what interest most users. Advanced users who want to port to new architectures are welcome to diff micropython repo with lv_micropython and learn from the differences.

Remember that all the work, including the documentation, was done by volunteers on their spare time. So comparing this to Microsoft error message is not really fair.
If you are unhappy with the documentation or any other part, feel free to contribute by submitting a PR!

ruihua-code commented 1 year ago

I have been using esp32s3 for a whole day, and I keep reporting errors. It turns out that esp32s3 chip is not supported yet!!

amirgon commented 1 year ago

It turns out that esp32s3 chip is not supported yet!!

Correct. See https://github.com/lvgl/lv_binding_micropython/pull/243

jd3096-mpy commented 1 year ago

Waiting for Support ESP32-S2, ESP32-C3, ESP32-S3! Lvgl docs has a lot of micropython examples codes, that's cool! Especially ESP32-S3,many borads use it instead of ESP32, but they can't be used in micropython yet, what's pity

amirgon commented 1 year ago

Especially ESP32-S3,many borads use it instead of ESP32, but they can't be used in micropython yet,

@jd3096-mpy see https://github.com/lvgl/lv_binding_micropython/pull/243 - this adds ESP32-S3 support. Could you try this PR on your side and see if it works for you?

kdschlosser commented 1 year ago

I hope this gets added soon. I just wrote a python driver for the ili934 using an 8bit parallel interface. all of the work functions are decorated with micropython.viper so it should run with ample speed.

I am not able to test it because I only have s3's on hand at the moment. It looks like it should work without an issue.

There are a couple of things that I have forced like setting the d0-d7 pins sequentially to GPIO pins that are also sequential and are all in the same GPIO register. Makes setting the state of the GPIOs easier to deal with. I still have to tie in the touch interface and this is going to be a tad more challenging to do because of the shared pins. I need to know more about the mechanics of how the input side of things works in lvgl to be able to do this. Or if a Python driver can be written for a touch interface. I don't know how the loop in lvgl works.

I am hoping that the use of viper code isn't going to mess with lvgl either. I am making an assumption that the viper code runs in the same manner as the native code and when the code is running things like ISRs don't break into the running code. The parallel interface should offer a HUGE speed increase because there is no need to swap the high and low bytes for the colors. I am also directly accessing the registers for the GPIOs through pointers and not using the built in machine.Pin class.

Maybe there is someone that would be willing to lend a hand with getting the touch interface working.

kdschlosser commented 1 year ago

On a side note I will match the 100.00 already being given to get this done.

kdschlosser commented 1 year ago

There is a choice to make here. Code can either be duplicated from the latest micropython esp32 port in the drivers for the esp32 port in lv_binding_micropython OR there can be a minimum micropython version that gets set into place for the esp32 port and includes from micropython can be made in the drivers for lvgl so the code isn't duplicated.

with the esp32s3 there is no adc_gpio_init function available and the way the adc blocks are handled is different. micropython has already sorted out the mechanics of this and created helper functions to deal with it. I think that setting a minimum version of micropython that lv_binding_micropython is allowed to use would the cleanest and also the easiest way to get it working with all of the different esp32 variants.

Most of the issues are differences in the macro names or some macros not being defined all together.

I corrected the errors in the gpio_to_adc array in the modrtch.c file using the following code

#define GPIO_TO_ADC_ELEMENT(adc, x) [x] = CONCAT3(CONCAT3(ADC, adc, _GPIO), x, _CHANNEL)
static const int gpio_to_adc[] = {
#if CONFIG_IDF_TARGET_ESP32
    GPIO_TO_ADC_ELEMENT(2, 0),
#elif CONFIG_IDF_TARGET_ESP32C3
    GPIO_TO_ADC_ELEMENT(1, 0),
#endif
#if CONFIG_IDF_TARGET_ESP32
    GPIO_TO_ADC_ELEMENT(2, 2),
    GPIO_TO_ADC_ELEMENT(2, 4),
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
    GPIO_TO_ADC_ELEMENT(1, 1),
    GPIO_TO_ADC_ELEMENT(1, 2),
    GPIO_TO_ADC_ELEMENT(1, 3),
    GPIO_TO_ADC_ELEMENT(1, 4),
#endif
#if CONFIG_IDF_TARGET_ESP32C3
    GPIO_TO_ADC_ELEMENT(2, 5),
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2
    GPIO_TO_ADC_ELEMENT(1, 5),
#endif
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
    GPIO_TO_ADC_ELEMENT(1, 6),
    GPIO_TO_ADC_ELEMENT(1, 7),
    GPIO_TO_ADC_ELEMENT(1, 8),
    GPIO_TO_ADC_ELEMENT(1, 9),
    GPIO_TO_ADC_ELEMENT(1, 10),
    GPIO_TO_ADC_ELEMENT(2, 11),
#endif
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
    GPIO_TO_ADC_ELEMENT(2, 12),
    GPIO_TO_ADC_ELEMENT(2, 13),
    GPIO_TO_ADC_ELEMENT(2, 14),
    GPIO_TO_ADC_ELEMENT(2, 15),
#endif
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
    GPIO_TO_ADC_ELEMENT(2, 16),
    GPIO_TO_ADC_ELEMENT(2, 17),
    GPIO_TO_ADC_ELEMENT(2, 18),
    GPIO_TO_ADC_ELEMENT(2, 19),
    GPIO_TO_ADC_ELEMENT(2, 20),
#endif
#if CONFIG_IDF_TARGET_ESP32
    GPIO_TO_ADC_ELEMENT(2, 25),
    GPIO_TO_ADC_ELEMENT(2, 26),
    GPIO_TO_ADC_ELEMENT(2, 27),
    GPIO_TO_ADC_ELEMENT(1, 32),
    GPIO_TO_ADC_ELEMENT(1, 33),
    GPIO_TO_ADC_ELEMENT(1, 34),
    GPIO_TO_ADC_ELEMENT(1, 35),
    GPIO_TO_ADC_ELEMENT(1, 36),
    GPIO_TO_ADC_ELEMENT(1, 37),
    GPIO_TO_ADC_ELEMENT(1, 38),
    GPIO_TO_ADC_ELEMENT(1, 39)
#endif
};

and that has left me with the following compilation errors.

/home/***/lv_micropython/lib/lv_bindings/driver/esp32/modrtch.c: In function 'measure_axis':
/home/***/lv_micropython/lib/lv_bindings/driver/esp32/modrtch.c:440:5: error: implicit declaration of function 'adc_gpio_init'; did you mean 'gpio_init'? [-Werror=implicit-function-declaration]
     adc_gpio_init(ADC_UNIT_1, adc_channel);
     ^~~~~~~~~~~~~
     gpio_init
/home/***/lv_micropython/lib/lv_bindings/driver/esp32/espidf.h:85:18: error: implicit declaration of function 'I2S_TIMING_REG'; did you mean 'I2S_RX_TIMING_REG'? [-Werror=implicit-function-declaration]
     REG_SET_BIT( I2S_TIMING_REG(i2s_num), BIT(9));
                  ^~~~~~~~~~~~~~
/home/***/esp/components/soc/esp32s3/include/soc/soc.h:151:36: note: in definition of macro 'REG_SET_BIT'
             (*(volatile uint32_t*)(_r) |= (_b));                                                                       \
                                    ^~
/home/***/lv_micropython/lib/lv_bindings/driver/esp32/espidf.h:86:18: error: implicit declaration of function 'I2S_CONF_REG'; did you mean 'I2S_TX_CONF_REG'? [-Werror=implicit-function-declaration]
     REG_SET_BIT( I2S_CONF_REG(i2s_num), I2S_RX_MSB_SHIFT);
                  ^~~~~~~~~~~~
/home/***/esp/components/soc/esp32s3/include/soc/soc.h:151:36: note: in definition of macro 'REG_SET_BIT'
             (*(volatile uint32_t*)(_r) |= (_b));                                                                       \
                                    ^~
In file included from /home/***/lv_micropython/lib/lv_bindings/driver/esp32/espidf.c:7:
/home/***/lv_micropython/lib/lv_bindings/driver/esp32/espidf.h: At top level:
/home/***/lv_micropython/lib/lv_bindings/driver/esp32/espidf.h:180:21: error: 'SPI_HOST' undeclared here (not in a function); did you mean 'SPI3_HOST'?
     ENUM_SPI_HOST = SPI_HOST,
                     ^~~~~~~~
                     SPI3_HOST
/home/***/lv_micropython/lib/lv_bindings/driver/esp32/espidf.h:181:22: error: 'HSPI_HOST' undeclared here (not in a function); did you mean 'SPI3_HOST'?
     ENUM_HSPI_HOST = HSPI_HOST,
                      ^~~~~~~~~
                      SPI3_HOST
/home/***/lv_micropython/lib/lv_bindings/driver/esp32/espidf.h:182:22: error: 'VSPI_HOST' undeclared here (not in a function); did you mean 'SPI3_HOST'?
     ENUM_VSPI_HOST = VSPI_HOST,
                      ^~~~~~~~~
                      SPI3_HOST

as you can see most of the issues at this point are simple macro naming problems. the only one that is a big hang up is the missing adc_gpio_init function and that function is not so simple to replicate what it does.

If a decision is made to use the already written functions to handle this issue in the esp32 port of micropython ass new esp32 boards get released changes will be made to micropython to handle those boards and little to no changes will need to be made in lv_binding_micropython to support the newer boards.

kdschlosser commented 1 year ago

is there someone willing to give this a try?

decompress the attached file into driver/esp32

driver.esp32.zip

I was using this command to compile it

make -C ports/esp32 LV_CFLAGS="-DLV_COLOR_DEPTH=16 -DLV_COLOR_16_SWAP=1" BOARD=GENERIC_S3_SPIRAM IDF_TARGET=esp32s3

I am getting this error and it might be something in my setup and not with the code changes I have made.

/home/****/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-patch5-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_lldesc_num2link_mpobj+0xc): undefined reference to `lldesc_num2link'

I want to rule out the code changes I have made.

kdschlosser commented 1 year ago

ok I figured out what functions need to be removed from lv_espidf.c so the compiling completes without error. I need to figure out how to keep gen_mpy from creating those functions. The majority of lv_espidf.c doesn't even need to be created. There is no reason to expose the entire espidf to the python interpreter. The availability of running viper code pretty much negates exposing it all together. Using viper code the GPIO registers can be accessed directly which would allow for fast updates to the GPIO pins.

I am not sure what other need there is to expose any of the espidf other than being able to manipulate the GPIOs

kdschlosser commented 1 year ago

If anyone wants to give this a go to see if it works I would appreciate it.

It should compile without errors. I do not have an SPI display to test it with.

https://github.com/kdschlosser/lv_binding_micropython/tree/esp32-s-c-h_support

jd3096-mpy commented 1 year ago

If anyone wants to give this a go to see if it works I would appreciate it.

It should compile without errors. I do not have an SPI display to test it with.

https://github.com/kdschlosser/lv_binding_micropython/tree/esp32-s-c-h_support

Good job! I tried your ways, like this: git clone https://github.com/lvgl/lv_micropython.git cd lv_micropython git submodule update --init --recursive lib/lv_bindings download your dirvers.esp32.zip ,unzip the files and overwrite it. try make -C ports/esp32 LV_CFLAGS="-DLV_COLOR_DEPTH=16 -DLV_COLOR_16_SWAP=1" BOARD=GENERIC_S3_SPIRAM IDF_TARGET=esp32s3

but report errors in the last stage: [1497/1499] Linking CXX executable micropython.elf FAILED: micropython.elf

/home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/driver/libdriver.a(gpio.c.obj):(.literal.gpio_force_hold_all+0x0): undefined reference tortc_gpio_force_hold_all' /home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/driver/libdriver.a(gpio.c.obj): in function gpio_force_hold_all': /home/jd3096/esp/esp-idf/components/driver/gpio.c:685: undefined reference tortc_gpio_force_hold_all' /home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.literal.esp_eth_phy_new_lan8720+0x0): undefined reference to esp_eth_phy_new_lan87xx' /home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj): in functionesp_eth_phy_new_lan8720': /home/jd3096/esp/esp-idf/components/esp_eth/include/esp_eth_phy.h:271: undefined reference to esp_eth_phy_new_lan87xx' /home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_xt_clock_freq_mpobj+0xc): undefined reference toxt_clock_freq' /home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_lldesc_build_chain_mpobj+0xc): undefined reference to lldesc_build_chain' /home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_gpio_input_get_high_mpobj+0xc): undefined reference togpio_input_get_high' /home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_gpio_output_set_high_mpobj+0xc): undefined reference to gpio_output_set_high' /home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_esp_eth_phy_new_ksz8081_mpobj+0xc): undefined reference toesp_eth_phy_new_ksz8081' /home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_esp_eth_phy_new_ksz8041_mpobj+0xc): undefined reference to esp_eth_phy_new_ksz8041' /home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_esp_eth_phy_new_dp83848_mpobj+0xc): undefined reference toesp_eth_phy_new_dp83848' /home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_esp_eth_phy_new_lan87xx_mpobj+0xc): undefined reference to esp_eth_phy_new_lan87xx' /home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_esp_eth_phy_new_rtl8201_mpobj+0xc): undefined reference toesp_eth_phy_new_rtl8201' /home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_esp_eth_phy_new_ip101_mpobj+0xc): undefined reference to esp_eth_phy_new_ip101' /home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_lldesc_set_owner_mpobj+0xc): undefined reference tolldesc_set_owner' /home/jd3096/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld: esp-idf/main/libmain.a(lv_espidf.c.obj):(.rodata.mp_lldesc_num2link_mpobj+0xc): undefined reference to lldesc_num2link' collect2: error: ld returned 1 exit status ninja: build stopped: subcommand failed. ninja failed with exit code 1 make: *** [Makefile:34: all] Error 2 make: Leaving directory '/home/jd3096/Desktop/01/lv_micropython/ports/esp32' the same error as yours?

kdschlosser commented 1 year ago

did you use the repo I linked to or did you use the files I attached in a zip?? If you used the zipped files don't, use the linked repo instead

jd3096-mpy commented 1 year ago

did you use the repo I linked to or did you use the files I attached in a zip?? If you used the zipped files don't, use the linked repo instead

Sorry,I git the wrong repo branch. Now it can be compiled without errors,I will test it later.

jd3096-mpy commented 1 year ago

did you use the repo I linked to or did you use the files I attached in a zip?? If you used the zipped files don't, use the linked repo instead

I think there is still something wrong with SPI, Init the screen there is a mistake: ("Failed initializing SPI bus") I tried to trace the source code in ili9XXX ret = esp.spi_bus_initialize(self.spihost, buscfg, 1) ret return value:258 that's not right. I change to ret = esp.spi_bus_initialize(self.spihost, buscfg, 0) it works,but the screen show like this: 7182ed39be5a68ab10226ff8d583ac7

I use lilygo t embed the screen is st7798v3 170x320 or mabey the screen driver init is not corrent

kdschlosser commented 1 year ago

OK so there is a result at least. That's a good thing. going to have to hammer out any kinks in it.

Can you post the exact Micropython code you are using?

And do you have the exact model number of the Lillygo piece you are using? I want to see if everything is aligning properly between the screen the Micropython code and the c code.. Gotta develop a data path to see what is happening.

kdschlosser commented 1 year ago

and that returned value is ESP_ERR_INVALID_ARG

hmmm... Time to go digging.

jd3096-mpy commented 1 year ago

spi_bus_initialize

and that returned value is ESP_ERR_INVALID_ARG

hmmm... Time to go digging.

Yes,here is the error code form esp-idf WIKI ESP_ERR_INVALID_ARG (0x102): Invalid argument(258)

ESP_ERR_INVALID_STATE (0x103): Invalid state(259) Sometimes return 259,when I changed to esp.spi_bus_initialize(self.spihost, buscfg, 0) rutern 0 that's right 0 means dma_channel

here's my mpy code: `import machine import espidf as esp from machine import Pin from fbdriver import st7789 import lvgl as lv power=machine.Pin(46, machine.Pin.OUT) power.value(1) bl=machine.Pin(15, machine.Pin.OUT) bl.value(1)

disp = st7789( mosi=11, clk=12, cs=10, dc=13, rst=9,width=135, height=240, rot=-1, factor=4,spihost=esp.VSPI_HOST)

lv.init() scr = lv.obj() btn = lv.btn(scr) label = lv.label(btn) label.set_text("Button")

Load the screen

lv.scr_load(scr)`

fbdriver is the copy of ili9XXX.py so I can test the driver.

jd3096-mpy commented 1 year ago

OK so there is a result at least. That's a good thing. going to have to hammer out any kinks in it.

Can you post the exact Micropython code you are using?

And do you have the exact model number of the Lillygo piece you are using? I want to see if everything is aligning properly between the screen the Micropython code and the c code.. Gotta develop a data path to see what is happening.

Here is the offical repo: https://github.com/Xinyuan-LilyGO/T-Embed

The GPIO marked in the picture is wrong, I am sure. I tried to use other st7789 driver on this board,it works normally. You can find the right GPIO in source code .h they defined.

https://github.com/Xinyuan-LilyGO/T-Embed/blob/main/example/tft/pin_config.h

define PIN_LCD_BL 15

define PIN_LCD_DC 13

define PIN_LCD_CS 10

define PIN_LCD_CLK 12

define PIN_LCD_MOSI 11

define PIN_LCD_RES 9

kdschlosser commented 1 year ago

I believe I found the issue.

I committed the changes to that same branch on my fork that I linked to in a previous post.

Give it a try again. It has to do with the DMA channel being used. If you have the repl open when you boot the ESP it will spit out any error codes if one does show up.

kdschlosser commented 1 year ago

Use the script below to run the test with

import machine
import ili9XXX
import lvgl as lv

disp = ili9XXX.st7789(
    mosi=11, 
    clk=12, 
    cs=10, 
    dc=13, 
    rst=9,
    power=46,
    backlight=15,
    backlight_on=0,
    power_on=0,
    width=170, 
    height=240,
    rot=ili9XXX.LANDSCAPE
)

lv.init()
scr = lv.obj()
btn = lv.btn(scr)
label = lv.label(btn)
label.set_text("Button")
jd3096-mpy commented 1 year ago

Traceback (most recent call last): File "", line 2, in File "ili9XXX.py", line 64, in AttributeError: 'module' object has no attribute 'ENUM_SPI_HOST'

Also no attribute: SPI_DMA_DISABLED ENUM_VSPI_HOST ENUM_HSPI_HOST

import espidf as esp help(esp)

SPI_HOST -- 0 VSPI_HOST -- 1 HSPI_HOST -- 2 SPI1_HOST -- 0 SPI2_HOST -- 1 SPI3_HOST -- 2 portMAX_DELAY -- -1 I2S_PIN_NO_CHANGE -- -1

only these const are defined

I try to chagne these const with value instead

It shows the same screen. I think mabey I should change another st7789 screen 320x240 That's more easy to use.

jd3096-mpy commented 1 year ago

Especially ESP32-S3,many borads use it instead of ESP32, but they can't be used in micropython yet,

@jd3096-mpy see #243 - this adds ESP32-S3 support. Could you try this PR on your side and see if it works for you?

Oh my god ,this repo works!!! Here is my mpy code: import machine import ili9XXX import lvgl as lv

power=machine.Pin(46, machine.Pin.OUT) power.value(1) bl=machine.Pin(15, machine.Pin.OUT) bl.value(1)

disp = ili9XXX.st7789( mosi=11, clk=12, cs=10, dc=13, rst=9, width=320, height=170, start_x=0, start_y=35, rot=-2 )

lv.init()

style_base = lv.style_t() style_base.init() style_base.set_bg_color(lv.palette_main(lv.PALETTE.LIGHT_BLUE)) style_base.set_border_color(lv.palette_darken(lv.PALETTE.LIGHT_BLUE, 3)) style_base.set_border_width(2) style_base.set_radius(10) style_base.set_shadow_width(10) style_base.set_shadow_ofs_y(5) style_base.set_shadow_opa(lv.OPA._50) style_base.set_text_color(lv.color_white()) style_base.set_width(100) style_base.set_height(lv.SIZE_CONTENT)

Set only the properties that should be different

style_warning = lv.style_t() style_warning.init() style_warning.set_bg_color(lv.palette_main(lv.PALETTE.YELLOW)) style_warning.set_border_color(lv.palette_darken(lv.PALETTE.YELLOW, 3)) style_warning.set_text_color(lv.palette_darken(lv.PALETTE.YELLOW, 4))

Create an object with the base style only

obj_base = lv.obj(lv.scr_act()) obj_base.add_style(style_base, 0) obj_base.align(lv.ALIGN.LEFT_MID, 20, 0)

label = lv.label(obj_base) label.set_text("Base") label.center()

Create another object with the base style and earnings style too

obj_warning = lv.obj(lv.scr_act()) obj_warning.add_style(style_base, 0) obj_warning.add_style(style_warning, 0) obj_warning.align(lv.ALIGN.RIGHT_MID, -20, 0)

label = lv.label(obj_warning) label.set_text("Warning") label.center()

screen: 0aa98da879ff9222534de6bde4bebaa

jd3096-mpy commented 1 year ago

If anyone wants to give this a go to see if it works I would appreciate it.

It should compile without errors. I do not have an SPI display to test it with.

https://github.com/kdschlosser/lv_binding_micropython/tree/esp32-s-c-h_support

GOD,I just found this repo works! https://github.com/imliubo/lv_binding_micropython/tree/dev_esp32_s3

Thanks for you working,too.

kdschlosser commented 1 year ago

Alot of the same changes I made except the adc blocks that can be used for the touch interfaces. With my changes all of the adc blocks are available.

ste7anste7an commented 1 year ago

I have a board with esp32s3 N16R8 which I would like to use with lv_micropython. I am glad to read that you guys are developing patches for the lvgl implementation to work with the esp32s3. However, I fail in trying to compile the lv_micropython code for esp32-s3. It is not clear to me which repository to use. I tried the following:

then 1) cloning the esp32-s-c-h_support branch from https://github.com/kdschlosser/lv_binding_micropython

2- cloning the https://github.com/imliubo/lv_binding_micropython/tree/dev_esp32_s3 repository. Trying same steps as above, results in the same error.

Question: can someone describe all the steps (including which branch of which repository) I have to follow to compile a correct version of lv_micropython for the esp32s3. I would be glad to test the firmware on my board and comment on the results.

kdschlosser commented 1 year ago

It's all still a work in progress I don't have an SPI TFT to test with and only having an esp32-s3 makes it a bit harder for me to make changes ans test because I don't know what would be broken the 8 bit parallel side of things or the esp32-s3 side of things.

I am going to order up an SPI screen pretty soon tho and that will make it easier for me to get running.

ste7anste7an commented 1 year ago

If I only could get a firmware that would run on my 16MB flash/8MBpsram, I could test it on my self-developed s3 board. Would it be possible to build one that I test?

Here is what I developed: an ESP32-s3 board with an SPI ili9341 touch display. The tft and touch share the same SPI. 20221226_225134 20221226_225209

kdschlosser commented 1 year ago

Here is a compiled firmware for the ESP32-S3 That has modified partitions to support the larger firmware and also supports SPIRAM.

Everything should be good to go with it you just need to upload it to your ESP32-S3 and then create a main.py file with the code for the display.

lvgl.zip

uncompress that into a folder and navigate to that folder and run the following command. You have to replace {port} with the serial port that you have the ESP attached to

You need to have the esptool python library installed.

esptool -p {PORT} -b 460800 --before default_reset --after no_reset --chip esp32s3  write_flash --flash_mode dio --flash_size detect --flash_freq 80m 0x0 bootloader.bin 0x8000 partition-table.bin 0x10000 micropython.bin
ste7anste7an commented 1 year ago

I uploaded the firmware (after a full erase) using your suggested esptool parameters, but unfortunately, I do not see the USB-CDC serial device being activated. On my board, I only use the native USB interface to the ESP32-S3, so the firmware should instantiate the USB serial port. Using one of the latest micropython firmwares, that works great and I can use REPL over the USB-CDC port. Would it be possible to share the whole patched lv_micropython tree that you currently are using for building this firmware?

kdschlosser commented 1 year ago

I linked to it in an earlier post

ste7anste7an commented 1 year ago

Found the problem with my ESP32S3-N16R8 module. It uses octal spi psram esp32. In the latest micropython distribution, a board called `GENERIC_S3_SPIRAM_OCT' is added. By dropping that board in the lv_micopython boards directory solved at least the booting problem. Now everything builds fine. This is what I have done:

cd ~/esp32
git clone https://github.com/lvgl/lv_micropython.git
git clone --branch esp32-s-c-h_support https://github.com/kdschlosser/lv_binding_micropyth
on.git

cd ~/esp32/lv_micropython/
git submodule update --init --recursive lib/lv_bindings

cd ~/esp32/lv_binding_micropython
cp -a * ../lv_micropython/lib/lv_bindings/.

cd make -C mpy-cross
cd  ~/esp32/lv_micropython/ports/esp32
make submodules
# got some errors regarding git ownership, solved those with the suggestions in the error messages
make  LV_CFLAGS="-DLV_COLOR_DEPTH=16 -DLV_COLOR_16_SWAP=1" BOARD=GENERIC_S3_SPIRAM_OCT IDF_TARGET=esp32s3

I had to change the partition-16MiB.csv to get some more space for the program:

# Notes: the offset of the partition table itself is set in
# $IDF_PATH/components/partition_table/Kconfig.projbuild.
# Name,   Type, SubType, Offset,  Size, Flags
nvs,      data, nvs,     0x9000,  0x6000,
phy_init, data, phy,     0xf000,  0x1000,
factory,  app,  factory, 0x10000, 0x2F0000,
vfs,      data, fat,     0x300000, 0xD00000,

Using this program (which works with the same display on an ESP32-WROOM with 4MB PSRAM) and disabling the touch for this test:

import espidf as esp
import lvgl as lv
from ili9XXX import ili9341,LANDSCAPE
#from xpt2046 import xpt2046

#init display
disp = ili9341(miso=11, mosi=12, clk=13, cs=14, dc=8, rst=9,
               backlight=-1,power=-1,width=320, height=240,
               rot=LANDSCAPE,double_buffer=True)
# use same SPI as display, init touch
#touch = xpt2046(spihost=esp.HSPI_HOST,cs=2,transpose=False,cal_x0=3865, cal_y0=329, cal_x1=399, cal_y1=3870)

lv.init()
scr = lv.obj()
btn = lv.btn(scr)
label = lv.label(btn)
label.set_text("Button")
btn.center()
label.center()

results in the following:

Double buffer
ILI9341 initialization completed

and shows this on the screen: 20221231_091427

jd3096-mpy commented 1 year ago

Found the problem with my ESP32S3-N16R8 module. It uses octal spi psram esp32. In the latest micropython distribution, a board called `GENERIC_S3_SPIRAM_OCT' is added. By dropping that board in the lv_micopython boards directory solved at least the booting problem. Now everything builds fine. This is what I have done:

cd ~/esp32
git clone https://github.com/lvgl/lv_micropython.git
git clone --branch esp32-s-c-h_support https://github.com/kdschlosser/lv_binding_micropyth
on.git

cd ~/esp32/lv_micropython/
git submodule update --init --recursive lib/lv_bindings

cd ~/esp32/lv_binding_micropython
cp -a * ../lv_micropython/lib/lv_bindings/.

cd make -C mpy-cross
cd  ~/esp32/lv_micropython/ports/esp32
make submodules
# got some errors regarding git ownership, solved those with the suggestions in the error messages
make  LV_CFLAGS="-DLV_COLOR_DEPTH=16 -DLV_COLOR_16_SWAP=1" BOARD=GENERIC_S3_SPIRAM_OCT IDF_TARGET=esp32s3

I had to change the partition-16MiB.csv to get some more space for the program:

# Notes: the offset of the partition table itself is set in
# $IDF_PATH/components/partition_table/Kconfig.projbuild.
# Name,   Type, SubType, Offset,  Size, Flags
nvs,      data, nvs,     0x9000,  0x6000,
phy_init, data, phy,     0xf000,  0x1000,
factory,  app,  factory, 0x10000, 0x2F0000,
vfs,      data, fat,     0x300000, 0xD00000,

Using this program (which works with the same display on an ESP32-WROOM with 4MB PSRAM) and disabling the touch for this test:

import espidf as esp
import lvgl as lv
from ili9XXX import ili9341,LANDSCAPE
#from xpt2046 import xpt2046

#init display
disp = ili9341(miso=11, mosi=12, clk=13, cs=14, dc=8, rst=9,
               backlight=-1,power=-1,width=320, height=240,
               rot=LANDSCAPE,double_buffer=True)
# use same SPI as display, init touch
#touch = xpt2046(spihost=esp.HSPI_HOST,cs=2,transpose=False,cal_x0=3865, cal_y0=329, cal_x1=399, cal_y1=3870)

lv.init()
scr = lv.obj()
btn = lv.btn(scr)
label = lv.label(btn)
label.set_text("Button")
btn.center()
label.center()

results in the following:

Double buffer
ILI9341 initialization completed

and shows this on the screen: 20221231_091427

I found the problem,too. You can try these two ways: 1 change: disp = ili9341(miso=11, mosi=12, clk=13, cs=14, dc=8, rst=9, backlight=-1,power=-1,width=320, height=240, rot=LANDSCAPE,double_buffer=True) to

disp = ili9341(miso=11, mosi=12, clk=13, cs=14, dc=8, rst=9, backlight=-1,power=-1,width=320, height=200, rot=LANDSCAPE,double_buffer=True)

it can show normally 2 modify the drivers ili9XXX.py 156: self.disp_buf.init(self.buf1, self.buf2, self.buf_size // 10)

it can work normally,too

the problem is about fbbuf

But I can't let xpt2046 work,Can you try it?

ste7anste7an commented 1 year ago

@jd3096-mpy You 2nd suggestion works! Thanks for that. This is the result: buttons

As for the touch, it worked just once. The touch sensor shares the SPI of the TFT. I have to check the pin-outs once more.

kdschlosser commented 1 year ago

because the touch shares the SPI I believe there needs to be some work done on the display driver side of things and how it sets up the SPI, The SPI needs to be shared between the 2. I am running into the same kind of an issue with an 8bit parallel screen I have been dinking about with. 2 of the data pins are used for the touch so the pins need to be changed from output pins to input pins in order to read the touch data and then they need to get set back.

I think the best thing to do is possibly read the touch every time a screen write occurs. I am not sure how often the screen is redrawn or the mechanics behind it. Does it only perform a redraw if something on the screen changes? How does LVGL poll for touches being made? Those are things I am looking into.

ste7anste7an commented 1 year ago

I have exactly the same configuration with a ESP32-WROOM board with 4MByte of PSRAM. On that board the touch works just fine with the code below. Somehow, on the S3 platform something changed in sharing the SPI.:

# import libraries
from machine import I2S, Pin
import espidf as esp
import lvgl as lv
from ili9XXX import ili9341,LANDSCAPE
from xpt2046 import xpt2046

#init display
disp = ili9341( miso=12, mosi=13, clk=14, cs=15, dc=23, rst=25, backlight=-1,power=-1,width=320, height=240, rot=LANDSCAPE)
# use same SPI as display, init touch
touch = xpt2046(spihost=esp.HSPI_HOST,cs=26,transpose=False,cal_x0=3865, cal_y0=329, cal_x1=399, cal_y1=3870)
# enable backlight
l=Pin(2,Pin.OUT)
l.value(1)

def event_handler(evt):
    code = evt.get_code()

    if code == lv.EVENT.CLICKED:
            print("Clicked event seen")
    elif code == lv.EVENT.VALUE_CHANGED:
        print("Value changed seen")

# create a simple button
btn1 = lv.btn(lv.scr_act())

# attach the callback
btn1.add_event_cb(event_handler,lv.EVENT.ALL, None)

btn1.align(lv.ALIGN.CENTER,0,-40)
label=lv.label(btn1)
label.set_text("Button")

# create a toggle button
btn2 = lv.btn(lv.scr_act())

# attach the callback
#btn2.add_event_cb(event_handler,lv.EVENT.VALUE_CHANGED,None)
btn2.add_event_cb(event_handler,lv.EVENT.ALL, None)

btn2.align(lv.ALIGN.CENTER,0,40)
btn2.add_flag(lv.obj.FLAG.CHECKABLE)
#btn2.set_height(lv.SIZE_CONTENT)

label=lv.label(btn2)
label.set_text("Toggle")
label.center()

https://user-images.githubusercontent.com/51531682/210155254-72e513d4-05c1-47be-926e-4ffdea3d4b7f.mp4

PS. you can hear the fireworks going on outside ;)

jd3096-mpy commented 1 year ago

I have exactly the same configuration with a ESP32-WROOM board with 4MByte of PSRAM. On that board the touch works just fine with the code below. Somehow, on the S3 platform something changed in sharing the SPI.:

# import libraries
from machine import I2S, Pin
import espidf as esp
import lvgl as lv
from ili9XXX import ili9341,LANDSCAPE
from xpt2046 import xpt2046

#init display
disp = ili9341( miso=12, mosi=13, clk=14, cs=15, dc=23, rst=25, backlight=-1,power=-1,width=320, height=240, rot=LANDSCAPE)
# use same SPI as display, init touch
touch = xpt2046(spihost=esp.HSPI_HOST,cs=26,transpose=False,cal_x0=3865, cal_y0=329, cal_x1=399, cal_y1=3870)
# enable backlight
l=Pin(2,Pin.OUT)
l.value(1)

def event_handler(evt):
    code = evt.get_code()

    if code == lv.EVENT.CLICKED:
            print("Clicked event seen")
    elif code == lv.EVENT.VALUE_CHANGED:
        print("Value changed seen")

# create a simple button
btn1 = lv.btn(lv.scr_act())

# attach the callback
btn1.add_event_cb(event_handler,lv.EVENT.ALL, None)

btn1.align(lv.ALIGN.CENTER,0,-40)
label=lv.label(btn1)
label.set_text("Button")

# create a toggle button
btn2 = lv.btn(lv.scr_act())

# attach the callback
#btn2.add_event_cb(event_handler,lv.EVENT.VALUE_CHANGED,None)
btn2.add_event_cb(event_handler,lv.EVENT.ALL, None)

btn2.align(lv.ALIGN.CENTER,0,40)
btn2.add_flag(lv.obj.FLAG.CHECKABLE)
#btn2.set_height(lv.SIZE_CONTENT)

label=lv.label(btn2)
label.set_text("Toggle")
label.center()

lms_esp32_lvgl.mp4 PS. you can hear the fireworks going on outside ;)

I slove this problem,too. Just add half_duplex=False for touch init: touch = xpt2046(spihost=esp.HSPI_HOST,cs=26,transpose=False,cal_x0=3865, cal_y0=329, cal_x1=399, cal_y1=3870) touch = xpt2046(half_duplex=False,spihost=esp.HSPI_HOST,cs=26,transpose=False,cal_x0=3865, cal_y0=329, cal_x1=399, cal_y1=3870)

Just don't work on half_duplex mode! By the way,Can you tell me how to get ths cal valus for x0 y0 x1 y1?

kdschlosser commented 1 year ago

I could have sworn I changed the partition size already. Maybe I didn't commit/push the update.

If you run the following on your ESP

import micropython

micropython.mem_info()

what does it say for total memory?? I am wondering if it is 8mb or only 4mb.

kdschlosser commented 1 year ago

example touch calibration and the calibration gets stored in NVRAM so no need to worry about hard coding the calibration numbers. If the touchscreen has not been calibrated it will launch the calibration process anbd when the calibration process has completed the ESP32 will reboot and the calibrations will get used and the calibration screen will not get seen again.

# import libraries
import time
from machine import Pin
import espidf as esp
import lvgl as lv
from ili9XXX import ili9341, LANDSCAPE
from xpt2046 import xpt2046
import esp32
from micropython import const
import _thread
import machine

lv.init()

# init display
disp = ili9341(
    miso=12,
    mosi=13,
    clk=14,
    cs=15, dc=23,
    rst=25, backlight=-1,
    power=-1,
    width=320,
    height=240,
    rot=LANDSCAPE
)

HRES = lv.scr_act().get_disp().driver.hor_res
VRES = lv.scr_act().get_disp().driver.ver_res

# touch calibrations stored in NVRAM
class TouchCalibration(object):

    def __init__(self):
        self._config = esp32.NVS('touch_cal')

        try:
            self._x0 = self._config.get_i32('x0')
        except OSError:
            self._x0 = 0

        try:
            self._y0 = self._config.get_i32('y0')
        except OSError:
            self._y0 = 0

        try:
            self._x1 = self._config.get_i32('x1')
        except OSError:
            self._x1 = HRES

        try:
            self._y1 = self._config.get_i32('y1')
        except OSError:
            self._y1 = VRES

        self._is_dirty = False

    def save(self):
        if self._is_dirty:
            self._config.commit()
            self._is_dirty = False

    @property
    def x0(self):
        return self._x0

    @x0.setter
    def x0(self, value):
        self._x0 = value
        self._config.set_i32('x0', value)
        self._is_dirty = True

    @property
    def y0(self):
        return self._y0

    @y0.setter
    def y0(self, value):
        self._y0 = value
        self._config.set_i32('y0', value)
        self._is_dirty = True

    @property
    def x1(self):
        return self._x1

    @x1.setter
    def x1(self, value):
        self._x1 = value
        self._config.set_i32('x1', value)
        self._is_dirty = True

    @property
    def y1(self):
        return self._y1

    @y1.setter
    def y1(self, value):
        self._y1 = value
        self._config.set_i32('y1', value)
        self._is_dirty = True

    @property
    def is_calibrated(self):
        return not (
            self.x0 == 0 and
            self.y0 == 0 and
            self.x1 == HRES and
            self.y1 == VRES
        )

touch_calibration = TouchCalibration()

# use same SPI as display, init touch
touch = xpt2046(
    spihost=esp.HSPI_HOST,
    cs=26,
    transpose=False,
    cal_x0=touch_calibration.x0,
    cal_x1=touch_calibration.x1,
    cal_y0=touch_calibration.y0,
    cal_y1=touch_calibration.y1
)

# enable backlight
backlight = Pin(2, Pin.OUT)
backlight.value(1)

def main():

    def event_handler(evt):
        code = evt.get_code()

        if code == lv.EVENT.CLICKED:
            print("Clicked event seen")
        elif code == lv.EVENT.VALUE_CHANGED:
            print("Value changed seen")

    # create a simple button
    btn1 = lv.btn(lv.scr_act())

    # attach the callback
    btn1.add_event_cb(event_handler, lv.EVENT.ALL, None)

    btn1.align(lv.ALIGN.CENTER, 0, -40)
    label = lv.label(btn1)
    label.set_text("Button")

    # create a toggle button
    btn2 = lv.btn(lv.scr_act())

    # attach the callback
    # btn2.add_event_cb(event_handler,lv.EVENT.VALUE_CHANGED,None)
    btn2.add_event_cb(event_handler, lv.EVENT.ALL, None)

    btn2.align(lv.ALIGN.CENTER, 0, 40)
    btn2.add_flag(lv.obj.FLAG.CHECKABLE)
    # btn2.set_height(lv.SIZE_CONTENT)

    label = lv.label(btn2)
    label.set_text("Toggle")
    label.center()

if touch_calibration.is_calibrated:
    main()
else:
    # Run calibration
    class Tpcal_point:

        def __init__(self, x, y, name):
            self.display_coordinates = lv.point_t({'x': x, 'y': y})
            self.touch_coordinate = None
            self.name = name

        def __repr__(self):
            return "%s: (%d, %d)" % (
                self.name,
                self.touch_coordinate.x,
                self.touch_coordinate.y
            )

    CIRCLE_SIZE = const(20)
    CIRCLE_OFFSET = const(20)
    TP_MAX_VALUE = const(10000)
    LV_COORD_MAX = const((1 << (8 * 2 - 1)) - 1000)
    LV_RADIUS_CIRCLE = const(LV_COORD_MAX)

    class Tpcal:

        def __init__(self, points, calibrate_func, touch_count=5):
            self.points = points
            self.calibrate = calibrate_func
            self.touch_count = touch_count

            # Storage point to calculate median
            self.med = [lv.point_t() for _ in range(0, self.touch_count)]

            self.cur_point = 0
            self.cur_touch = 0

            self.scr = lv.obj(None)
            self.scr.set_size(TP_MAX_VALUE, TP_MAX_VALUE)
            lv.scr_load(self.scr)

            # Create a big transparent button screen to receive clicks
            style_transp = lv.style_t()
            style_transp.init()
            style_transp.set_bg_opa(lv.OPA.TRANSP)
            self.big_btn = lv.btn(lv.scr_act())
            self.big_btn.set_size(TP_MAX_VALUE, TP_MAX_VALUE)
            self.big_btn.add_style(style_transp, lv.PART.MAIN)
            self.big_btn.add_style(style_transp, lv.PART.MAIN)

            self.big_btn.add_event_cb(
                self.calibrate_clicked,
                lv.EVENT.CLICKED,
                None
            )

            # Create the screen, circle and label

            self.label_main = lv.label(lv.scr_act())

            style_circ = lv.style_t()
            style_circ.init()
            style_circ.set_radius(LV_RADIUS_CIRCLE)

            self.circ_area = lv.obj(lv.scr_act())
            self.circ_area.set_size(CIRCLE_SIZE, CIRCLE_SIZE)
            self.circ_area.add_style(style_circ, lv.STATE.DEFAULT)
            self.circ_area.clear_flag(
                lv.obj.FLAG.CLICKABLE
            )

            self.show_circle()

        def show_text(self, txt):
            self.label_main.set_text(txt)
            self.label_main.set_pos(
                (HRES - self.label_main.get_width()) // 2,
                (VRES - self.label_main.get_height()) // 2
            )

        def show_circle(self):
            point = self.points[self.cur_point]
            self.show_text(
                "Click the circle in\n" +
                point.name + "\n" +
                "%d left" % (self.touch_count - self.cur_touch)
            )

            if point.display_coordinates.x < 0:
                point.display_coordinates.x += HRES

            if point.display_coordinates.y < 0:
                point.display_coordinates.y += VRES

            self.circ_area.set_pos(
                point.display_coordinates.x - CIRCLE_SIZE // 2,
                point.display_coordinates.y - CIRCLE_SIZE // 2
            )

        def calibrate_clicked(self, event):
            point = self.points[self.cur_point]
            indev = lv.indev_get_act()
            indev.get_point(self.med[self.cur_touch])
            self.cur_touch += 1

            if self.cur_touch == self.touch_count:
                med_x = sorted([med.x for med in self.med])
                med_y = sorted([med.y for med in self.med])
                x = med_x[len(med_x) // 2]
                y = med_y[len(med_y) // 2]
                point.touch_coordinate = lv.point_t({'x': x, 'y': y})

                self.cur_point += 1
                self.cur_touch = 0

            if self.cur_point == len(self.points):
                self.calibrate(self.points)
                # letting the thread go so it is able to restart the ESP32
                self.show_text("Calibration Complete")
                t_lock.release()

                # self.big_btn.set_event_cb(
                #     self.check,
                #     lv.EVENT.PRESSING,
                #     None
                # )
            else:
                self.show_circle()

        def check(self, event):
            point = lv.point_t()
            indev = lv.indev_get_act()
            indev.get_point(point)
            self.circ_area.set_pos(
                point.x - CIRCLE_SIZE // 2,
                point.y - CIRCLE_SIZE // 2
            )

    # Calculate calibration, and calibrate

    def calibrate(points):
        visual_width = (
                points[1].display_coordinates.x -
                points[0].display_coordinates.x
        )
        visual_height = (
                points[1].display_coordinates.y -
                points[0].display_coordinates.y
        )
        touch_width = points[1].touch_coordinate.x - points[
            0].touch_coordinate.x
        touch_height = points[1].touch_coordinate.y - points[
            0].touch_coordinate.y

        pixel_width = touch_width / visual_width
        pixel_height = touch_height / visual_height

        x0 = (
                points[0].touch_coordinate.x -
                points[0].display_coordinates.x *
                pixel_width
        )
        y0 = (
                points[0].touch_coordinate.y -
                points[0].display_coordinates.y *
                pixel_height
        )

        x1 = (
                points[1].touch_coordinate.x +
                (HRES - points[1].display_coordinates.x) *
                pixel_width
        )
        y1 = (
                points[1].touch_coordinate.y +
                (VRES - points[1].display_coordinates.y) *
                pixel_height
        )

        print(
            "Calibration result: x0=%d, y0=%d, x1=%d, y1=%d" %
            (round(x0), round(y0), round(x1), round(y1))
        )
        touch.calibrate(round(x0), round(y0), round(x1), round(y1))
        touch_calibration.x0 = int(round(x0))
        touch_calibration.y0 = int(round(y0))
        touch_calibration.x1 = int(round(x1))
        touch_calibration.y1 = int(round(y1))
        touch_calibration.save()

    t_lock = _thread.allocate_lock()

    def _run():
        t_lock.acquire()
        tpcal = Tpcal([Tpcal_point(20, 20, "upper left-hand corner"), Tpcal_point(-40, -40, "lower right-hand corner")], calibrate)
        # we do a second acquire to hold the thread from exiting. once the
        # calibration has finished the lock will be released and then the module
        # will get rebooted
        t_lock.acquire()
        # sleep for 3 seconds so the user can see the 
        # calibration complete message
        time.sleep_ms(3000)
        machine.reset()

    _thread.start_new_thread(_run, ())

    # let the main thread run off back to a repl prompt. Doing this allows you
    # to upload new code to the board without needing to flash the firmware
    # again. We don't want to use a while statement because that is a
    # "spinning wheels" deal that will consume all of the available processor
    # time. We do not want to use sleep either because there is no way to force
    # the exit of a sleep statement other then supplying a timeout. So better
    # to let the main thread run off and do it's thing and once the calibration
    # is finished we just reboot the ESP which will force a reload of the stored
    # calibrations and the main program will run from that point.
ste7anste7an commented 1 year ago
import micropython

micropython.mem_info()
stack: 736 out of 31744
GC: total: 8196480, used: 9152, free: 8187328
 No. of 1-blocks: 186, 2-blocks: 27, max blk sz: 32, max free sz: 511698

I get the full 8MByte of PSRAM.

ste7anste7an commented 1 year ago

half_duplex=False,

That did the trick! Touch works fine now. Thanks.

ste7anste7an commented 1 year ago

I successfully compiled firmware for my Lilygo T-QT 128x128 ESP32-S3 module using the GENERIC_S# board option. The module uses a GC9107 driver which seems to be compatible with GC9A01. I can create buttons,etc, on the screen. Only, the text is slipped upside down. it looks like the y-coordinate is flipped. Do you have any idea how, or where in the source code, I can fix this?

amirgon commented 1 year ago

Only, the text is slipped upside down. it looks like the y-coordinate is flipped.

Did you try setting rot parameter of gc9a01 to REVERSE_PORTRAIT instead of PORTRAIT?

ste7anste7an commented 1 year ago

Only, the text is slipped upside down. it looks like the y-coordinate is flipped.

Did you try setting rot parameter of gc9a01 to REVERSE_PORTRAIT instead of PORTRAIT?

Yes, I tried all the different orientations and reverse. The text is still upside down.

antoniomolram commented 1 year ago

Hi any update on the issue? I would like to build on a ESP32-S2, and I am unsure about what branch should I use.

I currently I am trying to do it from master, and I can build sucessfully BOARD GENERIC, but not GENERIC_S2 or GENERIC_S3.

Some guidence and help would be lovely! Thank you in advance!

amirgon commented 1 year ago

Hi any update on the issue? I would like to build on a ESP32-S2, and I am unsure about what branch should I use.

As the maintainer of the Micropython Bindings for LVGL, I would love to see ESP32-S2 support integrated into the official lv_micropython repository. While I would have added this support myself if I were developing for the board, I am relying on the community for assistance.

There have been some community efforts, such as @imliubo fork and @kdschlosser fork. Please note that these forks are not officially maintained by LVGL and may not be up-to-date with the latest LVGL releases. Unfortunately, there have been no attempts to merge them back into lv_micropython.

An open PR exists, but it appears to be abandoned.

To merge ESP32-S2 support into lv_micropython, we need some testing and code cleanup. I would be happy to review any PRs from the community, and encourage anyone interested in contributing to this effort to do so.

antoniomolram commented 1 year ago

Hi @amirgon, thank you for your answer, I will try to bring this up in my free time, and maybe I will start asking around. Thank you for the overview on the different branches that are available. ;)

fvstory commented 1 year ago

I think we should make lvgl a extend module,the driver can use the micropython‘s c to reach. I have done the esp32s3_hal_lcd_i80 link to lvgl(lv_micropython), it also can use the micropython’s spi to do it,I will make the hal_RGB_LCD link the lv_micropython next. https://github.com/fvstory/lcd_bind_lv_micropython

fvstory commented 1 year ago

@kdschlosser here go!