Errors building LVGL micropython for esp32-s3, but esp32 works

This might help: GitHub - tobozo/ESP32-USB-Soft-Host: An Arduino wrapper to @sdima1357's usb_soft_host esp-idf example

This is from circuit python

The usb_hid module allows you to output data as a HID device.

https://docs.circuitpython.org/en/latest/shared-bindings/usb_hid/index.html

That link is for connecting a USB device to GPIO pins and not the internal jtag the ESP32-S3 has available. It also only works with low sped USB devices which I am not sure if any devices even use that anymore thus it would cause an issue.

Thanks!
This uses regular IO pins, not the native USB port however, and is not tested on esp32-S3.

Yes, this is what I need (Have the ESP emulate a USB keyboard).
This works well from Arduino and CP (using the native USB port of the ESP32-S3).
But CP has a completely different organization and build system for that, with USB being a core feature. It’s not compatible with MP. For another project using a rpi pico, I had to switch to CP just because of this limitation.
So, even though I’m pretty sure it’s technically possible - CP does it -, porting over the feature to MP is far from straightforward, if possible at all without large changes to MP core.

so what you want to do is have the esp look like a keyboard or a mouse to a PC when you plug it into a PC via the USB???

I am talking about plugging a mouse or keyboard into the USB so you can use the mouse and the keyboard as input devices to control the GUI that is made.

2 wildly different things.

circuit python might be great for beginners but it is a fat cow. Too many things added to it to make it a good tool for beginners. It would gobble up too much in the way of resources with LVGL combined with it.

But to answer your questions as far as emulation is concerned…

It doesn’t look like the usb component has been added so it gets compiled and exposed to micropython. I can add it but it might not work without having to do a bunch of other things. I tried adding the esp_lcd component to get it exposed and it didn’t work so I am not holding my breath on the usb working either. It has something to do with callback functions and them needing to get redefined. I have not spent much timing to figure it out.

well I’ll be damned… It compiles when exposing the the usb features…

I also added exposing the esp_lcd component as well and got it to compile. Don’t know what I did differently this time around.

I will mess about with adding that USB emulation for the keyboard if that is what you want?

Yep, precisely. Just a keyboard.
Arduino demo for the MF Board: ESP32-S3-Parallel-TFT-with-Touch-4.3inch/examples/hid_keyboard at main · Makerfabs/ESP32-S3-Parallel-TFT-with-Touch-4.3inch · GitHub

Here you go. Make sure you initialize the display first and then the touch interface.

gt911.zip (2.6 KB)

OK I got the esp_lcd component exposed to micropython and I wrote a generic parallel display driver that supports both 8 and 16 bit interfaces.

This generic driver should work with the HX8264 driver IC right out of the box with nothing additional needing to be added. This generic driver is the base for other displays that have 8 bit and 16 bit interfaces. I will be adding support for the displays that are currently supported in the binding. I do not believe that any funky bye reordering needs to be done when parallel is used. I will have to dig into that a little bit more to find out.

I also still have to add a way to set the color space that is going to be used. when it be RGB565 (16 bit) or RGB8888 (32 bit) currently there is no 24 bit support in LVGL

Here is the repo with the modifications.

The module to import is generic_parallel_display. and the class is GenericParallelDisplay The parameters for the constructor is as follows.

width, 
height, 
de,
vsync, 
hsync,
pclk,
speed,
hsync_pulse_width, 
hsync_back_porch, 
hsync_front_porch, 
hsync_polarity,
vsync_pulse_width, 
vsync_back_porch, 
vsync_front_porch, 
vsync_polarity, 
pclk_active_neg,
d0, # red0
d1,  # red1
d2, # red2
d3, # red3
d4, # red4
d5, # green0
d6, # green1
d7, # green2
d8=None, # green3
d9=None, # green4
d10=None, # green5
d11=None, # blue0
d12=None, # blue1
d13=None, # blue2
d14=None, # blue3
d15=None, # blue4
init=True,
backlight=None,
backlight_pwm=False

on some displays the d0 - d15 pins might be labeled red, green and blue. This would be the mapping for those displays

d0 = red3
d1 = red4
d2 = red5
d3 = red6
d4 = red7
d5 = green2
d6 = green3
d7 = green4
d8 = green5
d9 = green6
d10 = green7
d11 = blue3
d12 = blue4
d13 = blue5
d14 = blue6
d15 = blue7

I added in back light control with PWM support. with or without pwm added the property back light_brightness gets used to get and set the back light. If pwn is supported you can pass a value from 0.0 to 100 .0 and it will set the brightness accordingly. If pwm is not supported any value >= 50 is considered as 100% or “on” and anything < 50 is considered to be 0 or off. The returned value is going to be either 0 or 100 if pwm is not supported. If you know your display has back light brightness control then set the backlight_pwm parameter to True constructing the display. the back light parameter is the integer for the GPIO that is used for the back light or None if there is no back light control for the display.

power support has not been added at this time

Thanks,
I’ll have a look and test in my context.

From what I saw in the esp idf code, they use core “matrix” functions inside, so this is routed in the right place behind the scenes.

I am messing about with adding parallel support for st7789, st7796 and the ili drivers that also have parallel interfaces. I did add the GT911 touch driver and also the FT6x36 touch driver as well as the st7796 SPI driver to it as well. I know the latter 2 work. Need to get confirmation on the GT911 driver.

did another large code change. I added an SPI base class that is able to be set for normal SPI and also octal SPI if the display supports it. I added a parallel base class as well. I made 2 new classes for the ST7789 driver IC, one for SPI and the other for parallel (8 or 16). I did the ST7789 classes because the espidf has direct support the ST7789 display in version 4.x. I am pretty sure I know how to add support for displays that are not built into the espidf and have initialization commands that have to be sent. I have been looking over the component repository for the espidf and there are several other displays and because of exposing the esp_lcd component I am going to be able to port the code to python.

I also fixed the GT911 driver

@angainor

What is left to do? we need to test the GT911 driver and if that all pans out then we have to get the keyboard emulator functioning for you correct?

Yes. I have to test your latest fork with the generic screen driver for once.
I think a few things may be missing, like the alloc of the lvgl work buffer before its init, but I’ll be able to fix if needed.
Then test the GT911.

From there, the last thing for me should be the KB emulator, indeed.
I may need a few days to be able to work on these, sorry for the delay.

Congrats for your work!
I myself several times stumbled upon a particular combo of MCU / display / development environment / LVGL release to use with LVGL.

I´ve found easy to use LVGL with Micropython on a supported board, but everytime I wanted to use one of the displays i had around with one of the currently micropython supported MCU I had, I systematically ran into trouble.

For example, a driver for a given display runs on one variant (ESP32 i´m looking at you) of a MCU but not another. Or an MCU has actually a very narrow list of tested and working display drivers.

Maybe a great resource could be a compatibility matrix for display / MCU / type of driver used, in a prominent place like https://docs.lvgl.io ,
with ideally pinouts and a code snippet ?

I am going to make this as simple to use as possible. for SPI based displays I will be writing in code so that if specific GPIO numbers are not passed and only the spi host is then the default pins for that host will be used. It will be up to the use to lookup the pinout for their specific board to see what the mappings are for those SPI numbers. There are simply far to many boards out there to keep an accurate list of what pins map to what GPIOs. it is easier for the user to pull up the pinout.

I am working on the ILI9488, ILI9341, GC9A01, RA8875, SH1107 and ST7796 displays using SPI, SPI octal, 8bit parallel and 16 bit parallel. I am also working on the FT5x06, GT1151, STMPE610 and TT21101 touch drivers. I have created a base class for the SPI, SPI octal, 8bit parallel and 16 bit parallel as well as one for the touch interface. Having that boiler plate code in place is going to make development time pretty fast. Just need to subclass the base class and fill in the blanks. The base class code takes care of the rest.

This is what a driver is going to end up looking like. I still have to add in the initialization commands on this but it gives you the basic idea.

import espidf as _espidf  # NOQA
import spi_driver_base as _spi_driver_base

from spi_driver_base import (
    COLOR_SPACE_BGR as _COLOR_SPACE_BGR,
    COLOR_FORMAT_NATIVE_REVERSE as _COLOR_FORMAT_NATIVE_REVERSE,
    PORTRAIT as _PORTRAIT,
    LANDSCAPE as _LANDSCAPE,
    REVERSE_PORTRAIT as _REVERSE_PORTRAIT,
    REVERSE_LANDSCAPE as _REVERSE_LANDSCAPE,
)

PORTRAIT = _PORTRAIT
LANDSCAPE = _LANDSCAPE
REVERSE_PORTRAIT = _REVERSE_PORTRAIT
REVERSE_LANDSCAPE = _REVERSE_LANDSCAPE


class ST7789SPI(_spi_driver_base.SPIDriverBase):
    _color_space = _COLOR_SPACE_BGR
    _color_format = _COLOR_FORMAT_NATIVE_REVERSE
    _panel_base = _espidf.esp_lcd_new_panel_st7789
    _lcd_cmd_bits = 8
    _lcd_param_bits = 8
    _dc_as_cmd_phase = 0
    _dc_low_on_data = 0
    _lsb_first = 0

    def __init__(
        self,
        width, height, dc, rst,
        clk, cs, mosi, miso=-1, d2=None, d3=None, d4=None, d5=None, d6=None,
        d7=None, spi_host=_espidf.HSPI_HOST, rot=PORTRAIT, init=True,
        double_buf=False, pclk_hz=(10 * 1000 * 1000),
        backlight=None, backlight_pwm=False
    ):
        super().__init__(
            width=width, height=height, dc=dc, rst=rst,
            clk=clk, cs=cs, mosi=mosi, miso=miso, d2=d2, d3=d3, d4=d4, d5=d5,
            d6=d6, d7=d7, spi_host=spi_host, rot=rot, init=init,
            double_buf=double_buf, pclk_hz=pclk_hz,
            backlight=backlight, backlight_pwm=backlight_pwm,
            color_space=self._color_space
        )

Not a whole lot there. which means adding drivers is going to be a breeze to do once this is done.

Getting crazy trying to understand what is missing.
I got it to compile, had to extend the app partition.
The python driver crashes, because of missing esp structs and funcs:

There is no espidf.esp_lcd_panel_handle_t exposed, likely this is self.panel_handle = espidf.esp_lcd_panel_t() ?

Then, there is no esp_lcd_new_rgb_panel() exposed to python.
The others with similar interfaces are exposed however

espidf.esp_lcd_new_
esp_lcd_new_panel_nt35510       esp_lcd_new_panel_ssd1306
esp_lcd_new_panel_io_spi        esp_lcd_new_panel_io_i2c
esp_lcd_new_panel_io_i80        esp_lcd_new_panel_st7789

The esp_lcd_panel_rgb.h that defines it is included among the other includes.
The other esp_lcd_ functions are properly exposed.

What am I missing?

Attach the esp_mp.c file to a post here. I will take a look to see what is happening. It will be located in your build folder. It’s called either esp_mp or espidf_mp. I don’t remember which one. Might even be idf_mp.

Crap I forgot to tell you that you would have to extend the app partition. That’s my fault…

I do have an idea tho. A script needs to be made that will make changes to the Micropython build system.

I also need to make some changes to gen_mpy so I can get rid of a script I made that comments out some stuff in the generated espidf C file. I don’t like having to use that script. I also have to fix a naming issue with “del” being used as a function name in some of the structures. The script that is made prepends an underscore and that is not what should be done. It needs to append an underscore to the function name. There is a problem with the naming convention used for one of the parameters that is passed and it not having the prepended underscore.