I am new to LVGL. I have followed all the instructions on the github and believe my IDF install is good.
When I build lvgl micropython for the esp32 target, I don’t get any errors and end up with a bootable micropython.
But I am getting build errors when I try to build an esp32s3 version. I have run ‘./install.sh esp32,esp32s3’ in the esp-idf directory before trying to build. The version of esp-idf I’m using is release/v4.4.
What am I missing or doing wrong when building LVGL for esp32s3?
In file included from /home/me/esp/esp-idf/components/esp_rom/include/esp32s3/rom/ets_sys.h:19,
/home/me/Repos/lv_micropython/lib/lv_bindings/driver/esp32/espidf.h: In function ‘SPH0645_WORKAROUND’:
/home/me/Repos/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/me/esp/esp-idf/components/soc/esp32s3/include/soc/soc.h:151:36: note: in definition of macro ‘REG_SET_BIT’
((volatile uint32_t)(_r) |= (_b));
/home/me/Repos/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/me/esp/esp-idf/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/me/Repos/lv_micropython/lib/lv_bindings/driver/esp32/espidf.c:7:
/home/me/Repos/lv_micropython/lib/lv_bindings/driver/esp32/espidf.h: At top level:
/home/me/Repos/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,
/home/me/Repos/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,
/home/me/Repos/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,
cc1: some warnings being treated as errors
I have been working on getting lv_bindings to work properly with the ESP32-S2, ESP32-S3, ESP32-C3 and ESP32-H2. I also made it so that any of the ADC pins can be used for the touch interface for all ESP32 variants. The current form only allows using specific pins.
I have also written a driver for using an 8 bit parallel interface for a screen. It’s written to use the viper code emitter so it should get a speed boost that is close to C code.
I still have to hammer out the touch interface for the parallel screens. They have shared pins with the display so care needs to be taken to not read and write from the pins at the same time. It doesn’t look like there is a simple bridge between the display drivers and the touch drivers. I have to dig into the code to see if there is an easy way to be able to have the 2 drivers talk to each other.
If anyone wants to do some testing for me with the esp32-S2/3 here is a link to the repository where the changes are made. I don’t have an SPI display to test with.
but I’m not sure if that is correct. When I try to build, the first error I get is:
-- Found Python3: /home/me/.espressif/python_env/idf4.4_py3.10_env/bin/python3.10 (found version "3.10.9") found components: Interpreter
CMake Error at /home/me/esp/esp-idf/tools/cmake/component.cmake:301 (message):
not a directory.
Call Stack (most recent call first):
LVGL does not have support for parallel displays. only SPI displays. Parallel displays are a whole different animal and I would need to spend some time to get a driver coded up for it. This is mostly due to getting the best possible performance which is the goal when using a parallel interface. If the screen is 8 bit parallel I could use the driver that comes with the espidf. if it is a 16 bit parallel I would have to write a driver from the ground up.
I’m confused as the board linked above comes with an LVGL demo pre-installed - the source code is linked from that page. I guess you mean that LVGL-micropython does not support parallel displays yet, right?
The driver chip used is an ILI9485 driving an 800 x 480 display so I believe it is an 8-bit interface? This youtube video illustrated the performance difference between the parallel display and SPI: https://www.youtube.com/watch?v=mXMKWrwlb5I
@yaconsult where do you see that this board uses a parallel interface to the LCD ?
The ILI9485 can work in SPI mode as well as in parallel mode, that is one point.
I did not access the schematics of the board you are using, but i presume you did and this is where you saw it is using a parallel interface, right ?
I am new to this stuff so I’m learning as we go along. Yes, it is parallel and I have uploaded the page of the schematic that shows it here:
And this is from the LvglWidgets.ino demo that is installed on the board:
Anyone is able to make a driver for a specific interface to work with LVGL. In your specific use case LVGL is not running inside of MicroPython. It is instead running directly as the firmware. This is done by writing whatever it is you need in C code and that code gets compiled and uploaded to the ESP using the Arduino IDE. Because that is how it is being done there is a library that is available called “TFT_eSPI” that is used as the driver for your display. don’t let the “SPI” in the name trick you. That library contains software to handle SPI, 8bit parallel and 16bit parallel interfaces.
There is no such library available for MicroPython and the drivers that are included with LVGL and have been updated to work with Micropython are the ones that work. I hate to say that I do not believe there are any parallel drivers available for use using MicroPython and LVGL. not that there will not be able in the future. there just isn’t any available at this time.
Thank you for the explanation. So driving a parallel display like this is not yet supported in micropython because there is no parallel driver. There is a similar board with an SPI display and touchscreen so I may pick up one of those to play with.
While searching, I found what appears to be a pure python micropython parallel display driver implementation, but I presume that this would have very, very slow display writing?
While the display you got I am sure is pretty decent the manufacturers kind of missed the point. Makerfabs also did the same thing. jumping from SPI right into a 16 lane serial interface is crazy. Too many pins get used up on the ESP and it leaves you with only 3 GPIO pins to mess about with. Maker fabs for some unknown reason ties up pins for things that may never get used.
I just got a WT32-SCO1 which has an ESP32-WROVER-B so 8mb SPIRAM and 4mb of flash. I did not get the pro version as that one shares the same fate as the parallel makerfabs and the one that you bought. Get the non pro version. They only make it in a 3.5" screen and that may be a deal breaker for you.
16 lane parallel interfaces for displays take up more than 16 GPIOs. If the touch screen is SPI that’s another 4. then you have the Backlighting, WR RST RD RS and CS pins that also have to be connected. 26 pins used on just the display and touch interface. HOLY CRAP!!
Unless you are going to be watching videos on the thing there is no need for a 16 lane interface. I have not been able to locate anyone that makes a setup that uses an 8 lane parallel interface. That gives you a speed boost but doesn’t take up all of the GPIO pins.
The 3.5" that I got has 13 GPIOs available for use which is nice. The only thing that sucks about it is they used a 2.0mm header to break the pins out instead of the industry standard 2.54mm. Not a complete deal breaker, more of an annoyance than anything.
I am working on the driver of that screen. I should be done with it in a few days. I have the touch interface working and the display works, the colors are off and I have to sort that out I also want to add support for 18 bit color (242k colors) which is a decent jump up from 16bit color (64k colors)
those 3.5" screens can be bought on amazon for 30 to 40 bucks
That implementation should actually be pretty fast, A lot of the code is running in viper code which is almost as fast as C code. The problem with it is it’s not a GUI framework. You would have to literally draw everything you wanted to see. Being as that would be done in python it would slow things down, I have another ESP32-WROVER-B and an 8 lane parallel display. OH. No you cannot use that library. It’s for an 8 lane not a 16 lane, which is what you have. I can more than likely port the code over to make it work with LVGL. I am sure I could add the other 8 lanes too. I would need to know what is attached to what pin and because the board you got doesn’t have a huge amount of information on it mapping out the pins would require me to have the board in hand.
LVGL currently has no support for any displays that have a parallel interface, MicroPython or otherwise.
I have a screen that has a parallel interface but 2 times now I ordered the wrong ESP32. I ordered ones that did not have the additional memory only the additional flash. I can more than likely hammer out getting the display to work in 8 bit parallel (that is what I have for a display) using one of the ESP32’s that I already have. as that is what I am using. Adding the additional 8 channels is not hard to do.
I had already written a driver for Micropython for the display that I have I have not tested it yet. Because my display and ESP are not on the same board I had control of the pinning for the display and for speed as well as ease of writing the code I had the pins connected in a manner where I did not need to iterate over the bytes reorganizing the bits in the bytes to write to the registers. Everything was nice and aligned so I could bitshift the entire byte and apply it to the register block without having to reorganize the bits at all. I highly doubt that the pinout that has been done for your display has the pins aligned in this manner.
I am not sure how the pins are set up for the display you have or the esp32 chip you are running but those things can be hammered out. The touch screen driver should be pretty easy to write a driver for. It is either going to share pins with the display or it is going to use I2C or SPI. I do not remember exactly how makerfabs has theirs set up.
The MF board I have has an ESP32-S3N16R8.
The working LVGL demo is built with Arduino and works. It uses the new esp_lcd component from esp_idf.
As far as I understood, lvgl “just” needs a framebufffer to write into, and a flush call.
The “stream” mode of the esp_lcd components takes care of sending the fb to the screen in the background for the RGB parallel lcds.
My issues are currently with micropython. For now, not even lvgl, I’m merely trying to init the screen with C code called from python.
It seems I run into the same issue you ran into
I used part of your fork of lv_micropython to have it properly compile for esp32-s3
Then, when adding the esp_lcd components, I ran into the same “panel->del” naming issue you had, I solved by renaming the function on the esp_idf side.
I used arduino_gfx code as basis, since the current version has config to support my board, among many others, including parallel displays. It uses ESP32RGBPanel and RGB_Display.
the gfx object is compatible with lvgl.
The interface of these is a bit different from the older one MF demo uses. It would seem this is still a fast evolving area.
The order of the pins does not seem an issue (I have the schematic if needed), since it is handled by the espidf internal API, and we have the arduino version working nice.
I finally got the micropython firmware to compile. The display handle is created, display is reset and init, but now the ESP panicks when I call the draw_bitmap function
ESP_ERROR_CHECK(_panel_handle->draw_bitmap(_panel_handle, 0, 0, 1, 1, &color));
This function is from esp_idf and makes use of things above my head, dma aso.
As I understand it, the esp_lcd has all the low level work done already, including fb allocation and sending to hardware screen with proper timings. The API however seems incomplete (some struct had to be re-declared) and varies a lot between versions.
Since it works well on arduino (Arduino_GFX) with the very same calls to esp_lcd and minimal code around, I have hope this would work in micropython as well. Could be just a missing dma initialization maybe.
See also LCD driver framework, some gotchas · Issue #3706 · lvgl/lvgl · GitHub for the esp s3 hw accelerated functions.
My current code is not published atm, it’s not generic but tied to my MF board.
I can publish my notes, reference links and snippets if this help, but I feel I’m not familiar enough with micropython build and C to get it done alone.
Quick update here, since it’s the most relevant place I found so far for parallel rgb lcds and esp32-s3.
I was able to solve the various crashes I experimented, learned about a few things along the way but still miss a proper debugger.
I ported over core code from arduino_gfx, that creates the various esp_lcd instances, fb in psram,
panel, then reset and init.
(This requires CONFIG_SPIRAM_USE_MALLOC=y to be set in sdkconfig.board)
No more crashes, even when trying to draw.
Once init, the screen now goes white and flickers a bit.
However, what I copy into the fb - I tried with simple rect and single pixels - is not reflected onto the display.
I suppose I may have some config still to dig, since the code itself does not crash and is basically the same as in arduino gfx.
I find it kind of funny that makerfabs doesn’t even know what driver IC was sued for the display. That’s funny.
I was looking at the example code for the “performance test”
OMG what a cluster f that is.
So there is a frame buffer that is allocated by the bus driver of Arduino_GFX. then there is yet another frame buffer allocated for LVGL. Mind you that neither of these buffers are DMA memory. and I believe that the buffer allocation is HUGE as in the full size of the screen. For both of them… One of them is set to use PSRAM if available which is going to be a lot slower.
So here comes the funny. So LVGL calls the flush function and the flush function calls the writeRGBBitmap function for the gfx driver and the gfx driver iterates pixel over pixel and moves it into the frame buffer that was created by the bus driver. then the buffer the bus driver created is used to transfer the data.
need to set this thing up so there is a single frame buffer using the callback to tell us when the frame buffer is empty. Otherwise what is going to end up happening is the PSRAM is going to have to get used and that will more than likely cause a slowdown because it is on a shard SPI with the CPU. even tho the access might be “DMA” which will not require intervention from the CPU to transfer data the transfer is going to happen in the background while the CPU is doing other things. It has the potential to really slow things down. if we keep the frame buffer small maybe 1/4 of the size of the screen it won’t be waiting very long for the callback to get called so the buffer can get reloaded. Using a single buffer means that we have to keep it from getting corrupted by it getting written to at the same time it is being read from.
The binding already has code on how this is done. we can simply duplicate that code. As far as getting the parallel to work, I already have that hammered out. I will work on it more later today to get it finalized up for ya and to make sure it compiles.
Thanks for looking into it, you seem way more experienced than I am, just tinkering what I can myself.
In my code (no lvgl yet), I had to use PSRAM for the fb by adjusting the config, or there was not enough memory and the malloc failed. Yes, it needs 800x480x2 =780 000 bytes.
Also, from what I understood of these RGB displays, they have no onboard ram and need the full fb to be sent “often enough”. Yes, this uses cpu and I saw reports (with circuit python maybe) of significant cpu
use messing with the display.
Why the hardware accelerated functions from esp seem essential to mitigate.
And yes, from what I understood, the fb is in ps ram and modified parts are then “synced back” to the cpu for sending…
Those are the data sheets for the touch interface and also the driver ic for the display on that Makerfabs display. The display can actually support 24bit color but seeing as how the ESP doesn’t have enough pins due to them wastefully using up pins for things like having the touch work for both SPI and also I2C and also burning up pins for the ESP32 USB support. there wasn’t enough left to get the 24bit color. It doesn’t really matter anyhow because LVGL doesn’t support 24bit color it jumps from 16 bit to 32 bit.
I also dumped the schematic of the screen you have to a pdf file for ya as well. This way you know what goes to where and what you can use