I’m porting code from an Cam H7 R2 FW 4.3.3 to RT1062 FW 4.5.9.
My code to initialze and write 320x240 grayscale images to a TFT display with ST7789 driver works on the H7 FW 4.3.3, while on the RT1062 FW 4.5.9 the images on the display are jumbled up. Attached is my code that recreates the issue. Thanks in advance for your help.
We added a bus_write() method which lets you execute commands to setup the display. Using this, you can send whatever custom initialization commands you need. Otherwise, you can tell the SPI display module the width/height, byte swap, and bgr required.
Whatever the case, it should be much faster than having to manually byteswap data in python like I see you are doing in your module.
…
while on the RT1062 FW 4.5.9 the images on the display are jumbled
Can’t really debug this code for you. But, the RT1062 has a different maximum SPI bus transfer length than the STM32H7. I had to manually patch the H7 micropython driver to allow it to write more than 65KB at a time in one spi transaction. The RT1062 can’t do more than 32KB. The upstream MicroPython SPI bus driver for this doesn’t look to be patched… so, you’ll need to breakup the transaction into chunks less than this:
The no attribute ‘SPIDisplay’ error resolved itself after erasing the SD card, rebooting computer and reloading firmware onto RT1062. The lcd_1.py example is working now with the LED Shield.
I’m looking to implement a 320x240 TFT display with the ST7789 driver on the RT1062. How do I break the image into smaller chunks in python for SPI transmission to this display?
Use the bytearray() method on the image and then a memory view to access parts of the image.
However, this will be very slow if you need to byte reverse things. I recommend just using our SPI display module and using the bus_write method to send the commands to setup the display as required.
Also, what are the options for “controller field”. I don’t see this in the documentation.
“controller Pass the controller chip class here to initialize it along with the display.”
You’d just pass whatever class you make as the controller argument. In the above case:
display.DSIDisplay(controller=ST7701())
Then, the controller class just is just:
import time
class ST7701:
def __init__(self):
pass
def init(self, dc):
self.dc = dc
dc.bus_write(REG, b"<BYTES_TO_WRITE>")
This allows you to fully customize setting up the display. Note that the dc object passed is the display object itself. So, you can query it for whatever info you think you need.
Note that there’s no register reading implemented for SPI displays. So, you can just write settings.
bus_write() does the command byte write followed by a bytestring for the argument for that command.
…
We implemented this system so that folks could use custom displays while still achieving high performance with triple buffering and etc. from our driver.
Put it all together and it works great at 18-19 FPS. My display is rotated 90 deg to sensor and IDE. WIthout the rotate image, it runs at 20-21 FPS. There may be a way with ST77XX_CASET and ST77XX_RASET to adjust for this without having to rotate the image in the framebuffer.
Here’s my code for a 320x240 TFT with the ST7789 Driver on the RT1062.
You can rotate the image during the display.write() call. This will be faster than doing it on the image directly as this avoids a write back to SRAM of the rotated image.
We’ve been slowly adding the draw_image() GPU backend to functions. Please take advantage of it as it will save you writebacks, which cost speed.
Generally, you should avoid transposing an image except for writing it to a final display buffer as the operation is really hard on the CPU. This is kinda why there’s no transpose() unary op. As it should not be something you do.
Great to know. Increased 1 FPS using lcd.write(img, hint=image.ROTATE_90). How is the clock rate for the SPI determined from refresh. It seems to max out with refresh=45?