Go Down

Topic: Fast ST7735R SPI rendering via Uno. (Read 144 times) previous topic - next topic

clbri

May 08, 2015, 02:32 am Last Edit: May 08, 2015, 09:39 pm by clbri
Hi there,

I got into Arduino about a week ago, and found some nice recreational programming from digging into the depths of the TFT screen that I got with it. The result is a test repository of different rendering samples that try to drive the screen as fast as possible. See here:

https://github.com/juj/ST7735R

I presume this is a common topic among Arduino developers since the reference implementations are not particularly optimized, so I decided to give it a closer look, and found it to be quite an educational weekend project and an intro to Arduino.

If there are experienced developers out there who'd be able to improve the SD card and TFT library performance further from that of what is posted in the github repository code, I'd be very interested to know! As of now, I seem to find myself being stuck with the limits of the 8MHz/divider 2 hardware SPI communication, and I wonder if it could be made any faster? Is there a computable theoretical limit on how much data can be transferred via SPI to a device? Or is that device specific? Is there a way to remove the divider, and drive the SPI bus at 16MHz?

As of now I seem to be able to peak 160*128*2 bytes/frame * 18.5 frames/second = 740 KBytes/second worth of SPI communication to the TFT screen when filling the screen with a single color. How does that sound like? I wonder if there are any low level knobs that could be leveraged to squeeze the bandwidth even higher?

jboyton

#1
May 08, 2015, 04:41 am Last Edit: May 08, 2015, 07:22 pm by jboyton
I'm not really sure what your benchmark does exactly. Maximum SPI clock on an Uno is half the master oscillator frequency, which is usally 16MHz. So you're limited to 8MHz SPI clock which in turn sets an upper limit of 1000 976 kbytes/sec transfer rate. Of course there is overhead so you'll never reach that level.

With the monochrome display I've been using it takes 2.08ms to clear the 1K of screen memory. That works out to about 480 kbytes/sec.

You could use a different processor (or overclock an Uno) to get a higher SPI clock frequency but you're ultimately limited by the SPI interface specifications of the ST7735 itself. It requires a minimum clock period of 66ns, which is about 15MHz.

The ST7735 supports an 8-bit parallel interface which would be faster. But an Uno doesn't lend itself to that sort of connection.

I'm not very experienced though; I only discovered Arduino on a random internet search about nine months ago. I'm still enjoying a steep learning curve.

clbri

Thanks for the reply. It does sounds like I'm pretty close to the limit then.

I'm interested in the knowing more about the 8-bit parallel interface. There are a lot of pins on the Uno, so physically I could wire those up even to a 8-bit wide data communication (not using them for anything else really). Do you know if there are other limitations what would make that infeasible with the Uno? Would some other Arduino board be able to do a parallel interface?

jboyton

How did you do your benchmark? I'm wondering what you're doing that is so much more efficient than the simple code I have to clear a screen. Surely pulling data from an SD card and writing it to a color TFT is more complicated than sending out a sequence of zeros. So what is the reason for this difference?

I'm interested in the knowing more about the 8-bit parallel interface.
Start reading the datasheet.

The parallel interfaces (ST7735R supports a number of them) are intended for processors that expose their data buses. The Uno doesn't do this; with the Atmega328 you interface with the outside world only through port data pins. It's possible to use digital output pins to mimic the D0-D7, RD and WR lines. You'd have to toggle the WR line yourself but on the other hand you'd be writing 8 bits at a time so I it would probably be faster. The ST7735 actually supports 8, 9, 16 and 18 bit parallel interfaces. But with only 20 digital pins on an Uno you're not going to be able to take advantage of all of those, unless you add some external hardware. There are other Arduino processors that have more digital pins though.

Another consideration is the display itself. Are the parallel interface lines accessible? There are also pins on the controller for setting the interface. Can you get to those on whatever TFT board you have?

I'm probably missing something though.

clbri

In the Github URL, every test is a benchmark of its own. The benchmark structure is a simple

   uint32_t x = micros();
   // do the drawing in the test.
   uint32_t y = micros();
   totalTime = (y-x);

The first test (Test1_FillScreen) fills the whole screen with a single color. That test takes about 54 msecs to do the clear. The code for the test is here: https://github.com/juj/ST7735R/blob/master/Test1_FillScreen.h and the underlying fill implementation is here: https://github.com/juj/ST7735R/blob/master/ST7735R_TFT.h#L448

For the SD card streaming case, the test code is here: https://github.com/juj/ST7735R/blob/master/Test7_Draw565.h#L47, and the underlying implementation here: https://github.com/juj/ST7735R/blob/master/ST7735R_TFT.h#L963 . Streaming a full screen image takes about 187 milliseconds.

Not sure if I do anything special in either of the benchmarks there, the code in both cases boils down to a hot loop that does the per-pixel work. There is the "NOP trick" with the SPI, which is documented here: https://github.com/juj/ST7735R/blob/master/ST7735R_TFT.h#L102, although it's probably not particularly new (some code snippets I googled off the web gave the idea).

It sounds like using the 8 bit parallel interface might then be technically feasible, except that instead of having a hardware to run the SPI, it would be effectively the same as the software bit banging on SPI is, except it'd be run 8-wide instead. Indeed the physical packaging may be of some trouble. The display looks like this on the front: https://dl.dropboxusercontent.com/u/40949268/dump/IMG_20150508_221839.jpg, and on the back: https://dl.dropboxusercontent.com/u/40949268/dump/IMG_20150508_221908.jpg. The parallel interface from the data sheet is not visibly accessible, although the whole left column of pins is unlabeled and undocumented as far as I can tell (they do not clone the right column of pins at least e.g. for symmetry, that I tried). Not sure if those are there just for structure, or if those are connected to somewhere.

jboyton

#5
May 08, 2015, 09:41 pm Last Edit: May 08, 2015, 09:56 pm by jboyton
Thanks for the response. I had just finished figuring out what the difference is. Not waiting for SPI completion -- that's something I had thought about but hadn't pursued. I had already improved the speed so much and didn't really need more. But it was still in the back of my mind.

I just tried it quick and dirty with my display code and with little effort bumped it up from 480 kb/sec to 668 kb/sec. But I think there is some nuance to how this is done that I would have to understand better. Nice work.

There may be naked TFT modules available that you could play with. If you like soldering, that is. Something like this perhaps.

clbri

Heh, I think I fried an Adafruit 0.96" monochrome OLED display just earlier today by soldering. I've touched a soldering iron last time some 20 years ago, and now I realize that's not a learn-once skill like driving a bicycle! Probably should practice this out on some old circuitry first..  o_O

jboyton

#7
May 08, 2015, 10:45 pm Last Edit: May 08, 2015, 10:45 pm by jboyton
Check out NewhavenDisplay. They have TFTs with bare cables for parallel interface. It looks like they use a different controller, but it appears very similar. They also sell adapter boards with ZIF connectors so you don't have to try your luck with soldering 0.5mm pitch connectors. Mouser carries their products with what I presume is less expensive shipping.

clbri

Thanks, NewhavenDisplay has some very interesting items. I think I'll check out the parallel interface route once I find a nice display to try it on.

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy