Standalone binary .mpy module for lvgl (so we can "just use it" in micropython)

That’s a really long list, but we don’t need to support all controllers in the world. Making 95% of people could be great trade off. And we should be able to identify 10-15 really popular controllers which will cover most of the use cases. Besides some of these controllers are very similar. I haven’t checked but I’m pretty sure that on driver level:

    HX8232-A: TFT Display
    HX8238-A: TFT Display
    HX8238-D: TFT Display
    HX8249: TFT Display
    HX8250: TFT Display
    HX8257: TFT Display
    HX8264: TFT Display
    HX8278-A-LT: TFT Display
    HX8282: TFT Display
    HX8288: TFT Display

could be HX82xx.

This is not able to be done with MicroPython. You have to supply the bus drivers because MicroPython doesn’t expose the full API of the bus drivers to the python side of things. You can have display drivers all day but without the ability to send the information from the display driver to the physical display having display drivers becomes pointless.

Then you also have things like STM32 only supplying heir version of an RGB bus driver, no other parallel drivers are available in their SDK. There is in the ESP-IDF. I have not checked any other MCU’s yet. The hoops I had to jump though to check STM32’s burnt me out last night and chewed up 20 gb of disk space in the process. and I thought the ESP-IDF was a pain to use. WOW, Not even close in comparison.

Oh a lot of the driver IC’s made by the same manufacturer will have a lot of common parts to them that can be reused. But there will be variations between some of them. Some will be identical I am sure

I’m not convinced you understand the discussion? zero display (or any other) controller drivers will be included in the flash. Only the one you need will exist, and it will be placed into the vfs (or SD card). Same with LVGL itself - not in the flash.

keep in mind that flash and ram are different things - vastly more important not to waste the RAM

raw hardware is exposed to .mpy modules of course.

I’m reasonably confident that if a user passed a python SPI structure into a “C” .mpy module, the “C” will have enough info it needs to identify which SPI clocks etc got used, and make use of the full capabilities of the MCU directly?

My point is that once we will have the most popular display controller drivers supported in LVGL, it would be great to not duplicating them in MicroPython. So there could be 2 options:

  1. Use LVGL display drivers if they support the given display and add only the SPI/I2C/etc specific drivers
  2. Write a custom display.py as you have suggested. It can be done by the user or the display manufacturer (assuming that this feature really gets enough traction) but not by us, as it would be a duplication between the LVGL and MicroPython built in drivers.

nope. There are limitations that are coded into MicroPython SPI itself. The inability to register a callback for when transferring is done, for the ESP32 a hard limit of 4096 bytes being sent which again doesn’t need to exist. The transferring using SPI is a blocking call in MicroPython…

There are the same kinds of issues with STM32 as well. The built in SPI cannot be used. MicroPython has nothing built in for i8080 or RGB interfaces. Those would have to be made as well. I have started working on an SPI driver, I8080 driver and RGB driver for esp32 and also for the STM32. have to put something together for the rest of the MCU’s again this is only the BUS drivers i am working on. The actual display drivers will be able to be written in Python code and can be written in a manner that makes them pretty efficient to use. The python source files for the display drivers can be made into MPY files but I don’t really see the point to doing that as there are no benefits to be had from it.

Interesting: so what’s to stop your code taking the input micropython SPI structure, using that to identify which one and its clock, then kicking off DMA and returning? Give the “users” a .done() or .wait() method so they know when it’s safe to write again into the DMA region (where “users” is really the display driver of course; and if it has double-buffering, .done()/.wait() will in practice never block). disclaimer: I’m a bit out of my depth here - it’s been over a decade since I last played with DMA, and that wasn’t on any MCU.

I still think you don’t understand? LVGL will not have any drivers whatsoever for anything. None. Zero.
MicroPython (excluding the files on vfs) will also not have any display/touch drivers whatsoever either.

If anyone wants to use an LCD, they import hardware; import display; import touch; use screen directly. If they want to use LVGL, they import hardware; import display; import touch; import lvgl; use screen through lvgl.

Do you have an MCU with a screen at your place? What exact kind is it ?(what MCU?, What display?, What touch?). When my collection of screens arrive in a week or two, I’ll build all the hardware/display/touch drivers for myself, plus one more for you, so you can experience what I mean :slight_smile:

waste of resources.

There is no point to creating a MicroPython SPI object only for it to be passed to an SPI bus constructor for a display only for the purposes of being a container and data collected from it. Why not just pass what is needed directly to the constructor of the display bus? That same data needs to be passed to the constructor for MicroPython SPI. It really isn’t needed.

ALSO hen you have something like the ESP32 a display SPI bus is not the same thing as what is sued in the MicroPython SPI. It is a completely different set of API calls that are made to the SDK.

This is what makes it block

            if (offset > 0) {
                // wait for previously queued transaction
                MP_THREAD_GIL_EXIT();
                spi_device_get_trans_result(self->spi, &result, portMAX_DELAY);
                MP_THREAD_GIL_ENTER();
            }

and this

        // wait for last transaction
        MP_THREAD_GIL_EXIT();
        spi_device_get_trans_result(self->spi, &result, portMAX_DELAY);
        MP_THREAD_GIL_ENTER();
        spi_device_release_bus(self->spi);

I agree with @gitcnd about not having any display drivers packaged with LVGL. LVGL is a low level graphics framework. You don’t see drivers being packaged with QT or with wxWidgets or any of the other graphics frameworks that are kicking about.

A framework might have some kind of an add-on package that provides drivers but they are not typically included in the main library. MicroPython is an odd animal and there needs to be some mechanism to be able to access the underlying busses on the MCU’s When using the Arduino IDE this is provided using add-on libraries like tft-eSPI. Those do not exist for MicroPython. So they need to be included for the binding but not for LVGL.

People are fickle beasts, and I have come to understand that most do not want to read extensive API documentation. they prefer to read one page at most and look at examples of how it is done. I believe that this is the best thing that LVGL can do is provide some examples of how to do it and also have a single page showing how to do it.

If you look at the readme page for the MicroPython binding not only are there things that are incorrect on it, it is far from complete. It only touches bases on how to compile it for Unix and for the ESP32. nothing about stm32 or RPI. A person has to go hunting the internet to locate that information. I have had to instruct several people on the forum on how to get it to compile for the RP2 board.

Provide enough information to get it running and something displayed then the person will be willing to spend more time learning about it. If they have to spend hours scoring the internet to figure out how to even get it to display a simple “Hello World!” it’s not going to get used.

That would be where Squareline Studio could step in. It could be the easy to use tool that writes complete code including the touch and display driver integration. It could download the needed drivers from whatever repository and write the proper code needed for it to run. Give the user the option of selecting the MCU and the display driver ic and touch driver ic give the user selection choices on the connection types the display ic supports and let them select the one they wish to use and they can then define how it is connected to that MCU. This is where that database I mentioned before would come in damned handy!!!.. That would provide the ease of use aspect. LVGL itself shouldn’t be easy to use for the person that has no experience that is what Squareline Studio is for, to make LVGL easy to use!!!

I am almost done with the ESP32 drivers and then it is on to the STM32 ones. and from there it will be RPI. I would like to keep the API the same across the board between the bus drivers so even if things are not used they will still be defined as do nothing parts. Easier to manage the API documentation because there will be no differences between the different MCU’s.

I will have, that’s the point. :slight_smile: Not only because MicroPython, but in general to make it easier to get started for people in C or any language. And once we will have it we can use it.

But I don’t want to stop the positive energies by forcing you to use the LVGL drivers, so let’s go with your suggestion and we will see how things shape.

OK so the direction that we should be headed is writing the bus drivers?? Those 100% have to be available in the binding no matter what. The display drivers can be added by the user/developer or if it is so decided they would be supplied by the binding.

The bus drivers need to be there no matter what. We need people that have knowledge and experience using specific MCU SDK’s. I am able to work my way around the ESP-IDF and I have a large portion of the bus drivers already written. only one left is for I2C. SPI, RGB and I8080 are done. The ESP-IDF does not have support for more than a single data lane for SPI. It will be added in the future or so the comment states in the source file.

I am going to drop a line with the folks over at MicroPython because there is a glitch in the build system that would need to be fixed in order to be able to compile the drivers as a user C module and having it self contained. Meaning no alterations would have to be made to the MicroPython build system in order for it to work.

OK I have the code written for the ESP32 bus drivers. I8080, SPI, I2C and RGB. I am going to peek at the STM32 stuff and see what I can come up with for a common API between the 2. I think that I might be able to use STM32’s built in driver for their displays to handle RGB. probably going to have do make a software based I8080. I2C and SPI I imagine will both use the STM32 SDK as well. … I have to do a little research.

1 Like

ok so the STM stuff is beyond me. maybe someone that has more knowledge about STM32 would be able to write it. I can provide the ESP32 stuff so it can be used as to keep the API the same .Even if parameters are not used they should still be available.

Because of how the RGB bus driver functions I made it so that the bus driver is what allocates the frame buffers. The RGB driver does this internally and provides a function to call to get the frame buffer. The SPI also requires knowing what the frame buffer size is in order to function properly so it really wasn’t that big a deal since the buffer size is known for both the SPI and the RGB to extend that to i2c and i80.

This works out because now the user doesn’t have to know the specifics of how to create a DMA buffer for their board using memory addresses. we are able to keep it all behind the scenes. Because the bus is going to be initialized as it’s own thing the bus can be done first thing to secure the frame buffer into sram for faster transfers.

The API is pretty simple. there are a couple of functions, that’s it. There is an init function that the display driver will call passing the display width and display height to the function. There is a deinit function to do the tear down. the deinit function is also tied to __del__ so if a reference to the bus instance is not kept it will do it’s tear down and get garbage collected. Then you have tx_param which is for sending commands and parameters, then there is rx_param which is for asking for something form the display. tx_color is for transmitting the frame buffer. register_callback is to register a callback with optional user data for when a DMA transfer has completed. It is recommended to pass the display structure from LVGL as the user data and in the callback function is were you would tell lvgl that the flush is ready. and lastly is get_frame_buffer. This function takes a single parameter and that is the buffer number. If double buffering is being used then you have buffer numbers 1 and 2, if not then there is only buffer 1. If 2 is specified and double buffering has not been used a NULL pointer will be returned. All of this should easily be able to be used when setting up the display with LVGL.

I will write a basic framework for the display drivers. It will handle the backlight, reset and sending parameter to the display as well ad receiving parameters from the display. There will be an empty flush function that is made that will have to be overridden by the display driver.

@kisvegabor does LVGL have built in handling of byte swapping and bit swapping the frame buffer data? If it doesn’t then I will write functions to handle this using the viper code emitter so it will execute close to as fast as C code.

If a user (developer) wants to they can optionally compile the python display drivers into MPY files. We will leave that up to them to do if they want. Then it can follow the whole import display and have everything loaded the way the dev board manufacturer wants things set up.

The bus drivers do have differences for the parameters passed to the constructor. All parameters are keyword parameters, no positional ones. This is done intentionally to make sure the user (developer) is passing the right thing to the right parameter. There are required parameters and there are some that have defaults. If using i8080 and only an 8-bit parallel connection is wanting to be used then only 8 pin numbers should get passed, or 9 if 9-bit or 16 if 16bit.

I did want to mention that data pins DO NOT get passed as an array. there is a parameter in the constructor for each pin. This is done so a user (developer) is able to use micropython.const to pass the pin numbers like using a macro in C code. Here is an example

from micropython import const
import lcd_bus

_DATA0 = const(5)
_DATA1 = const(6)
_DATA2 = const(7)
_DATA3 = const(8)
_DATA4 = const(9)
_DATA5 = const(10)
_DATA6 = const(11)
_DATA6 = const(12)
_DATA7 = const(13)


bus = lcd_bus.I8080Bus(
    data0=_DATA0,
    data1=_DATA1,
    data2=_DATA2,
    data3=_DATA3,
    data4=_DATA4,
    data5=_DATA5,
    data6=_DATA6,
    data7=_DATA7
)

in order for this to work property and not use up additional memory the constant name MUST begin with an underscore. If this is not done the constant ends up becoming a variable that has an integer in it. This will consume memory the they are not deleted after that have been used. By putting the underscore no additional memory gets used and no deleting needs to be done.

isn’t that just a convention that does nothing?
it’s the const() function that stores the value differently, nothing to do with its name ?

How is a 2nd display supported?

That’s 3am here in Melbourne; Too late even for me!

I could do as late as 10pm (local to me) - so noon CET; would that work? Otherwise, any time yellow/green in Melbourne is fine for me, though if it’s during work hours I may need to wiggle around pre-booked meetings…

CET | Melbourne Meeting Planner

Probably why we need a conversation. :stuck_out_tongue:

If you’re referring to your proposal to use native modules for drivers? Native modules are likely to be a poor fit; they have some significant limitations, particularly around the limited access to methods and firmware features. They also consume more RAM. Drivers are likely best to be built-in to the firmware (including only the appropriate drivers for the target hardware).

So you need to have a meeting for US-Europe-Australia. One of the greatest challenges of all times :smiley:

Anyway, in this case Tuesday would work better for me. Noun CET is fine as well. How about you @kdschlosser, @gitcnd?