# TFT Driver ST7789 Works on H7 not on RT1062

**URL:** <https://forums.openmv.io/t/tft-driver-st7789-works-on-h7-not-on-rt1062/10234>\
**Category:** OpenMV Boards\
**Created:** [November 22, 2024, 5:38am UTC](https://forums.openmv.io/t/tft-driver-st7789-works-on-h7-not-on-rt1062/10234 "2024-11-22T05:38:47Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![ajacobs](https://avatars.discourse-cdn.com/v4/letter/a/7c8e57/32.png) [@ajacobs](https://forums.openmv.io/u/ajacobs)\
**Post date:** [November 22, 2024, 5:38am UTC](https://forums.openmv.io/t/tft-driver-st7789-works-on-h7-not-on-rt1062/10234/1 "2024-11-22T05:38:47Z")

</div>

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.

[Test\_TFT\_ST7789\_V1.py](https://forums.openmv.io/uploads/short-url/if1wiweOrvx8uDY14IVgp1qGQYv.py) (2.1 KB)  
[TFT\_ST7789VI.py](https://forums.openmv.io/uploads/short-url/kHSPLwTzyjR8lijCLOZSfAGithC.py) (4.1 KB)

---

<div class="post-metadata">

**Author:** ![kwagyeman](https://yyz1.discourse-cdn.com/flex029/user_avatar/forums.openmv.io/kwagyeman/32/4_2.png) [@kwagyeman](https://forums.openmv.io/u/kwagyeman)\
**Post date:** [November 22, 2024, 6:01am UTC](https://forums.openmv.io/t/tft-driver-st7789-works-on-h7-not-on-rt1062/10234/2 "2024-11-22T06:01:06Z")

</div>

Hi, the SPI display driver was explicity extended to resolve the need for anyone to have to write their own display driver for any SPI bus displays.

[class SPIDisplay – SPI Display Driver — MicroPython 1.23 documentation](https://docs.openmv.io/library/omv.display.spidisplay.html)

We added a [bus\_write()](https://docs.openmv.io/library/omv.display.spidisplay.html#display.SPIDisplay.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.

The default setup otherwise is very minimal: [openmv/src/omv/modules/py\_spi\_display.c at master · openmv/openmv](https://github.com/openmv/openmv/blob/master/src/omv/modules/py_spi_display.c#L403)

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:

```auto
#define OMV_SPI_MAX_8BIT_XFER (32768U - 32U)
#define OMV_SPI_MAX_16BIT_XFER (32768U - 16U)

```

---

<div class="post-metadata">

**Author:** ![ajacobs](https://avatars.discourse-cdn.com/v4/letter/a/7c8e57/32.png) [@ajacobs](https://forums.openmv.io/u/ajacobs)\
**Post date:** [November 22, 2024, 6:51am UTC](https://forums.openmv.io/t/tft-driver-st7789-works-on-h7-not-on-rt1062/10234/3 "2024-11-22T06:51:49Z")

</div>

Is there a maximum image size for SPIDisplay.write? Will it write a 320x240 RGB image?

---

<div class="post-metadata">

**Author:** ![ajacobs](https://avatars.discourse-cdn.com/v4/letter/a/7c8e57/32.png) [@ajacobs](https://forums.openmv.io/u/ajacobs)\
**Post date:** [November 22, 2024, 6:53am UTC](https://forums.openmv.io/t/tft-driver-st7789-works-on-h7-not-on-rt1062/10234/4 "2024-11-22T06:53:10Z")

</div>

> [@kwagyeman](#):
>
> so, you’ll need to breakup the transaction into chunks less than this:

How do I break the image into smaller chunks for SPI transmission?

---

<div class="post-metadata">

**Author:** ![ajacobs](https://avatars.discourse-cdn.com/v4/letter/a/7c8e57/32.png) [@ajacobs](https://forums.openmv.io/u/ajacobs)\
**Post date:** [November 22, 2024, 6:57am UTC](https://forums.openmv.io/t/tft-driver-st7789-works-on-h7-not-on-rt1062/10234/5 "2024-11-22T06:57:03Z")

</div>

Also, same error as in other thread … AttributeError: ‘module’ object has no attribute ‘SPIDisplay’

 ![image](https://canada1.discourse-cdn.com/flex029/uploads/openmv1/original/2X/6/6b1e57b878bc67380a06242239d6f321c76dffd0.jpeg)

---

<div class="post-metadata">

**Author:** ![kwagyeman](https://yyz1.discourse-cdn.com/flex029/user_avatar/forums.openmv.io/kwagyeman/32/4_2.png) [@kwagyeman](https://forums.openmv.io/u/kwagyeman)\
**Post date:** [November 22, 2024, 7:32am UTC](https://forums.openmv.io/t/tft-driver-st7789-works-on-h7-not-on-rt1062/10234/6 "2024-11-22T07:32:26Z")

</div>

Something very weird is going on for it not to work. I can install the latest dev release and the firmware posted in the other thread and it works.

---

<div class="post-metadata">

**Author:** ![ajacobs](https://avatars.discourse-cdn.com/v4/letter/a/7c8e57/32.png) [@ajacobs](https://forums.openmv.io/u/ajacobs)\
**Post date:** [November 22, 2024, 8:27pm UTC](https://forums.openmv.io/t/tft-driver-st7789-works-on-h7-not-on-rt1062/10234/7 "2024-11-22T20:27:36Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![kwagyeman](https://yyz1.discourse-cdn.com/flex029/user_avatar/forums.openmv.io/kwagyeman/32/4_2.png) [@kwagyeman](https://forums.openmv.io/u/kwagyeman)\
**Post date:** [November 22, 2024, 8:56pm UTC](https://forums.openmv.io/t/tft-driver-st7789-works-on-h7-not-on-rt1062/10234/8 "2024-11-22T20:56:56Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![ajacobs](https://avatars.discourse-cdn.com/v4/letter/a/7c8e57/32.png) [@ajacobs](https://forums.openmv.io/u/ajacobs)\
**Post date:** [November 22, 2024, 9:31pm UTC](https://forums.openmv.io/t/tft-driver-st7789-works-on-h7-not-on-rt1062/10234/9 "2024-11-22T21:31:34Z")

</div>

Thanks for your help. I’m a bit confused by your eariler reply regarding chunking the image.

Will the SPIDisplay module work with a 320x240 TFT display on the RT1062 with this?

```auto
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)  
lcd = display.SPIDisplay(width = 240, height = 320)
while True:
    lcd.write(sensor.snapshot())

```

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.”

---

<div class="post-metadata">

**Author:** ![kwagyeman](https://yyz1.discourse-cdn.com/flex029/user_avatar/forums.openmv.io/kwagyeman/32/4_2.png) [@kwagyeman](https://forums.openmv.io/u/kwagyeman)\
**Post date:** [November 22, 2024, 9:49pm UTC](https://forums.openmv.io/t/tft-driver-st7789-works-on-h7-not-on-rt1062/10234/10 "2024-11-22T21:49:58Z")

</div>

Yes, it’s that easy!

As for the controller. It would look something like this:

[openmv/scripts/libraries/st7701.py at master · openmv/openmv](https://github.com/openmv/openmv/blob/master/scripts/libraries/st7701.py)

You’d just pass whatever class you make as the controller argument. In the above case:

```auto
display.DSIDisplay(controller=ST7701())

```

Then, the controller class just is just:

```auto
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](https://docs.openmv.io/library/omv.display.spidisplay.html). 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.

---

<div class="post-metadata">

**Author:** ![ajacobs](https://avatars.discourse-cdn.com/v4/letter/a/7c8e57/32.png) [@ajacobs](https://forums.openmv.io/u/ajacobs)\
**Post date:** [November 22, 2024, 10:01pm UTC](https://forums.openmv.io/t/tft-driver-st7789-works-on-h7-not-on-rt1062/10234/11 "2024-11-22T22:01:12Z")

</div>

Great! One last question before I implement, what are the display driver chip connections for each of the “Uses pins P0, P2, P3, P6, P7, and P8”?

---

<div class="post-metadata">

**Author:** ![kwagyeman](https://yyz1.discourse-cdn.com/flex029/user_avatar/forums.openmv.io/kwagyeman/32/4_2.png) [@kwagyeman](https://forums.openmv.io/u/kwagyeman)\
**Post date:** [November 22, 2024, 10:12pm UTC](https://forums.openmv.io/t/tft-driver-st7789-works-on-h7-not-on-rt1062/10234/12 "2024-11-22T22:12:08Z")

</div>

See the LCD shield pinout: [LCD Shield – OpenMV](https://openmv.io/collections/openmv-cam-shields/products/lcd-shield?variant=16525320513)

---

<div class="post-metadata">

**Author:** ![ajacobs](https://avatars.discourse-cdn.com/v4/letter/a/7c8e57/32.png) [@ajacobs](https://forums.openmv.io/u/ajacobs)\
**Post date:** [November 22, 2024, 11:28pm UTC](https://forums.openmv.io/t/tft-driver-st7789-works-on-h7-not-on-rt1062/10234/13 "2024-11-22T23:28:14Z")

</div>

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.

[Test\_TFT\_ST7789\_V2.py](https://forums.openmv.io/uploads/short-url/yGyy9v5ZZQadUDfr80MQ35jhEh.py) (2.0 KB)

---

<div class="post-metadata">

**Author:** ![kwagyeman](https://yyz1.discourse-cdn.com/flex029/user_avatar/forums.openmv.io/kwagyeman/32/4_2.png) [@kwagyeman](https://forums.openmv.io/u/kwagyeman)\
**Post date:** [November 23, 2024, 12:28am UTC](https://forums.openmv.io/t/tft-driver-st7789-works-on-h7-not-on-rt1062/10234/14 "2024-11-23T00:28:32Z")

</div>

You can rotate the image during the [display.write()](https://docs.openmv.io/library/omv.display.spidisplay.html#display.SPIDisplay.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.

---

<div class="post-metadata">

**Author:** ![ajacobs](https://avatars.discourse-cdn.com/v4/letter/a/7c8e57/32.png) [@ajacobs](https://forums.openmv.io/u/ajacobs)\
**Post date:** [November 23, 2024, 2:22am UTC](https://forums.openmv.io/t/tft-driver-st7789-works-on-h7-not-on-rt1062/10234/15 "2024-11-23T02:22:48Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![ajacobs](https://avatars.discourse-cdn.com/v4/letter/a/7c8e57/32.png) [@ajacobs](https://forums.openmv.io/u/ajacobs)\
**Post date:** [November 23, 2024, 2:25am UTC](https://forums.openmv.io/t/tft-driver-st7789-works-on-h7-not-on-rt1062/10234/16 "2024-11-23T02:25:52Z")

</div>

The ST7789 does not require the P7 RESET line and works without it. Can P7 be reassigned after display.SPIDisplay without breaking display.write?

---

<div class="post-metadata">

**Author:** ![kwagyeman](https://yyz1.discourse-cdn.com/flex029/user_avatar/forums.openmv.io/kwagyeman/32/4_2.png) [@kwagyeman](https://forums.openmv.io/u/kwagyeman)\
**Post date:** [November 23, 2024, 3:01am UTC](https://forums.openmv.io/t/tft-driver-st7789-works-on-h7-not-on-rt1062/10234/17 "2024-11-23T03:01:37Z")

</div>

The clock is just width_height_2\*refresh.

The pins are hardcoded, only P6 can be freed. Otherwise, you need to modify the firmware.

---

<div class="post-metadata">

**Author:** ![ajacobs](https://avatars.discourse-cdn.com/v4/letter/a/7c8e57/32.png) [@ajacobs](https://forums.openmv.io/u/ajacobs)\
**Post date:** [November 23, 2024, 3:23am UTC](https://forums.openmv.io/t/tft-driver-st7789-works-on-h7-not-on-rt1062/10234/18 "2024-11-23T03:23:18Z")

</div>

It looks to me like P7 OMV\_SPI\_DISPLAY\_RST\_PIN is only toggled in mp\_obj\_t spi\_display\_make\_new. Is it used anywhere else?

I did the following quick test and saw nothing abnormal on the TFT display.

lcd = display.SPIDisplay(width = 240, height = 320, refresh = 45, bgr = False, byte\_swap = False, controller=ST7789())  
pin7 = Pin(“P7”, Pin.OUT, Pin.PULL\_UP)

while True:  
img = sensor.snapshot()  
lcd.write(img, hint=image.ROTATE\_90)  
pin7.toggle()

---

<div class="post-metadata">

**Author:** ![kwagyeman](https://yyz1.discourse-cdn.com/flex029/user_avatar/forums.openmv.io/kwagyeman/32/4_2.png) [@kwagyeman](https://forums.openmv.io/u/kwagyeman)\
**Post date:** [November 23, 2024, 3:54am UTC](https://forums.openmv.io/t/tft-driver-st7789-works-on-h7-not-on-rt1062/10234/19 "2024-11-23T03:54:52Z")

</div>

Yeah, it’s used just for that to reset the display.
