lvgl-micropython / lvgl_micropython

LVGL module for MicroPython
MIT License
88 stars 28 forks source link

BGR585 on ST7735 #85

Closed dcmcshan closed 4 months ago

dcmcshan commented 4 months ago

Is there a way to get BGR565 on ST7735?

AttributeError: type object 'LV_COLOR_FORMAT' has no attribute 'BGR565'

kdschlosser commented 4 months ago

yes... add rgb565_byte_swap=True when you construct the display driver...

import st7735

... 

display = st7735.ST7735(
    bus,
    width,
    height,
    ...
    color_space=lv.COLOR_FORMAT.RGB565,
    rgb565_byte_swap=True
)
kdschlosser commented 4 months ago

If you are using an I8080 or an SPI bus interface for the display then doing the above should fix the color issue. There are occasions where the byte order in which the display write the data to it's internal GRAM is reversed. In those cases you would do the following...

import st7735

... python

display = st7735.ST7735(
    bus,
    width,
    height,
    ...
    color_space=lv.COLOR_FORMAT.RGB565,
    color_byte_order=st7735.BYTE_ORDER_BGR
)

You might still have to use rgb565_byte_swap even when doing this. Things that come into play when dealing with the color_byte_order is the edianess of the display and the MCU you are using. If they are flip flop from each other then you use this setting to correct that. If the display works in MSB but your MCU works in LSB then you will end up with the bytes being in the wrong order. by setting the color_byte_order you instruct the display to write the data to GRAM so it is in reverse order on a per pixel basis.

Now the color_byte_order and the rgb565_byte_swap settings differ is this...

RGB is the following..

r7, r6, r5, r4, r3, r2, r1, r0 | g7, g6, g5, g4, g3, g2, g1, g0 | b7, b6, b5, b4, b3, b2, b1, b0

and RGB565 is this..

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

internally the display takes the RGB565 and adds the missing bits for each color to make RGB888. The data stored in it's internal GRAM is always RGB888...

When we use the rgb565_byte_swap what it does it it transmits the data like this...

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

It literally swaps the 2 bytes... Where as using color_byte_order doesn't change how the data is sent. It instead tells the display to store the bytes in GRAM in reverse order. This is done after the conversion from RGB585 to RGB888 is done internally in the display IC.

dcmcshan commented 4 months ago
color_space=lv.COLOR_FORMAT.RGB565,
rgb565_byte_swap=True,,
color_byte_order=ST7735.BYTE_ORDER_BGR

solved it for me.

I've still not tried the invert parameter, but am using display.set_params(self.display._INVON)as well.

kdschlosser commented 4 months ago

display.invert_colors(True)

You have to remember that st7735.ST7735 is a subclass of display_driver_framework.DisplayDriver so all methods and attributes in display_driver_framework.DisplayDriver are available in st7735.ST7735

You can view the API for the display_driver_framework module in the display_driver_framework.pyi file that is located in the root of the repository. You can view the file here. https://github.com/kdschlosser/lvgl_micropython/blob/main/display_driver_framework.pyi

The actual source code for the display_driver_framework module is located here. https://github.com/kdschlosser/lvgl_micropython/blob/main/api_drivers/py_api_drivers/frozen/display/display_driver_framework.py

kdschlosser commented 4 months ago

If you are working in an IDE you can copy the display_driver_framework.pyi file and the st7735.py file into the root of you project and all of the methods and attributes should become visible in the IDE.

kdschlosser commented 4 months ago

Here is a script to add after your driver setup to make sure the colors are correct. The color changes every second. You will see red, green and blue in that order. There should also be black or white, I don't remember what the default color is for the background.. so you will see one of those in the beginning.

import task_handler
import time

th = task_handler.TaskHandler()

scrn = lv.screen_active()

colors = [
    lv.color_hex(0xFF0000),
    lv.color_hex(0x00FF00),
    lv.color_hex(0x0000FF)
]

start_time = time.ticks_ms()

count = 0
while count != 2:
    end_time = time.ticks_ms()
    if time.ticks_diff(end_time, start_time) >= 1000:
        scrn.set_style_bg_color(colors[i], 0)
        count += 1
        start_time = end_time