Fastest possible SPI speed/refresh rate on a ST7789?

Status
Not open for further replies.

arkitekt

Member
Hello! I am looking for insight from folks familiar with TFT displays:

What is the fastest possible frame rate that a person can achieve using a Teensy 3.6, an Adafruit ST7789 TFT, and Paul's ST7735_t3 graphics library? I have an SPI camera that outputs a rather fast video feed, so I am looking for any settings that would help bring my draw times down. I'm currently sitting around 20FPS, but I see that page 133 of the ST7789 datasheet lists a 60Hz framerate, so I know there is potential for improvement - I'm just not sure how to set it up with a Teensy.

There are a few parts of the ST7735_t3 library that I am unsure of:
  1. How exactly do these registers(?) work? I added print statements to my own local copy of the .cpp file and I can confirm that using the setBitrate() function changes which CTAR value is selected. However, there is no discernible difference in frame rate between the lowest CTAR_4MHz value and the highest CTAR_24MHz value (50ms either way). Is there something else that has to happen in order to make full use of these bitrates?
  2. If I enable the ST77XX_FRAMEBUFFER and show images using the updateScreenAsync() function, the draw time shows a value of 2ms (as opposed to 50ms), however it doesn't look any visually faster. I have a feeling that the async operation halts the clock that the micros() function relies on, so this is not a great measurement. Will the framebuffer provide any speed boost as compared to running a direct writeRect() and passing in a global static uint16_t array?

Here is a sample .ino that provides some of my benchmarks:
https://github.com/SoftwareArkitekt...tion/blob/master/arduino_tft_optimization.ino

The first thing I did to speed things up was to tie the TFT pins to the dedicated Teensy pins that were recommended in code examples. (See my .ino above for my own pin definitions.) This helped enormously, but is still not fast enough for my needs. As mentioned above, the fullscreen_test() currently sits at around 50ms (20FPS) for 240x240 updates.

Maybe I have just been staring at this for too long and am missing something obvious, so any help would be greatly appreciated. Thanks!
 
Please keep in mind the ST7789 chip supports many different data interfaces. The 8 and 16 bit interfaces are (theoretically) much faster and 1 bit serial.

Hey Paul! Thanks for taking the time to look. Also, that ST7735 library is fantastic! :)

That makes sense; my primary concern really centers on the fact that the draw time looks identical no matter what CTAR value I pick. I am wondering if:
1) The setting is being ignored because 4MHz is as fast as the 1-bit interface can go,
2) There is some other variable I have to set in order to use the new CTAR_24MHz value properly,
3) If CTAR has no bearing on draw times and I am completely missing the point.
 
Last edited:
It you are using the ST7789_t3 code, the SPI clock speed is setup by using SPI Transactions, And the actual speed is currently controlled by the setting in ST7735_t3.h file
#define ST7735_SPICLOCK 24000000

In several of these libraries we added an easy way to change this default, often on the begin or init method... I don't see in here... Not hard to add.
As we create and hold on to a _spiSettings setup, so just need to update that...

As for how fast you can drive the ST7789 chip, you can experiment. Often times it will be dictated by things liike how long and good your wires are connecting it up.
I know that others have been able to increase the speed.

First advice stay away from the CTAR stuff, that is old style pre SPI transaction stuff... Just try updating that define...

Understanding things like Frame Rates and the like gets sort of complicated,
But you can for example compute some simple upper limits:
That is suppose you can run the larger 320x240 display at 30mhz SPI speed.
You know that you need to send at least 320*240*2 bytes to the display and each byte takes at least 10 SPI clocks, probably closer to 11 as there are gaps between bytes/words...
so (320*240*2*11)/30000000 = .04928 which 1/x of that comes out to a little over 20 frame per second. assuming I typed in everything correctly...

Now question is, is updateScreen or updateScreenAsync faster?
It is a wash. Why? UpdateScreenAsync uses DMA to transfer from the buffer to the screen as fast as the SPI can send it out, Likewise the updateScreen sits in a loop pushing data into the SPI FIFO queue as soon as their are open slots in the queue, and as long as the queue never go empty, the SPI will output as fast as it can (or more specifically as fast as it is configured to)

What is the difference? with updateScreen, your code will sit there waiting for the transfer to complete before it can do anything else. With the Async version, your code simply starts up the operation and then allows you sketch to do other things, with some limitations. That is if you update the screen while it is still outputting data you could get part new part old...

There is also a version of the async that says keep the screen updates going. And a way you can query a frame count and partial frame count, such that in theory you can setup your code to lets say update the top half of the frame buffer while the screen is outputting the bottom part...


But again back to Max Frame counts... It depends on things like: Do you need to update the whole display each time? Or can you deduce a bounding rectangle of where your data changed? If so you can setup and use a clip rectangle to tell the screen to only update within that region... Again depending on how big this rectangle is will influence how long it takes to update.


I hope that helps some.

Kurt
 
First advice stay away from the CTAR stuff...
...If you are using the ST7789_t3 code, the SPI clock speed is setup by using SPI Transactions, And the actual speed is currently controlled by the setting in ST7735_t3.h file
#define ST7735_SPICLOCK 24000000

Oh good to know! I'll avoid touching CTAR then. Changing ST7735_SPICLOCK to 26000000 and 28000000 didn't do anything, but there is a significant improvement (50ms down to 35ms) when I set it to 30000000+:
  • 26000000: 50ms
  • 28000000: 50ms
  • 30000000: 35ms
  • 48000000: 35ms
  • 96000000: 35ms
I do not see a change beyond the 30000000 value.

But again back to Max Frame counts... It depends on things like: Do you need to update the whole display each time? Or can you deduce a bounding rectangle of where your data changed? If so you can setup and use a clip rectangle to tell the screen to only update within that region... Again depending on how big this rectangle is will influence how long it takes to update.

The video feed I am using is only 240x180 (instead of 240x240) which saves me some time. I am very close now - if I could bring the draw speed down from 35ms to something closer to 25 ms I think it would be fast enough for the live video. Do you have any other suggestions for improvements?
 
Status
Not open for further replies.
Back
Top