Skip to content

Instantly share code, notes, and snippets.

What would you like to do?

Is it possible to hit the theoretical max display update speed on PineTime's display controller?

PineTime is based on the nRF52 microcontroller, and it's connected via SPI to the ST7789 display controller. Details here:

ST7789 uses a non-standard SPI interface: There is an additional Data/Command pin that needs to be flipped to indicate whether we are sending SPI commands (e.g. set X and Y coordinates) or data (e.g. the bitmap to be rendered).

This means we can't send a continuous stream of SPI commands and data. Our program needs to intervene and flip the Data/Command pin, which slows down the rendering throughput. DMA wouldn't work here.

Unless... We have the entire bitmap already in RAM, and we are doing one huge DMA from RAM to ST7789, in a single SPI command. But ST7789 doesn't have RAM to hold the entire screen (see the article). And it's a bad use of RAM anyway.

We could put the bitmap into the external SPI Flash and do DMA from the external flash to ST7789. This is good for static bitmaps, like a black screen or a startup logo. Not good for dynamic UIs like ours.

So for interactive UIs it's hard to hit the theoretical max display update speed. Even if we tried, the RAM would be better used for other application functions.

Copy link

kwakeham commented Feb 3, 2020

I'm working on using the same st7789 screen for another project. I'm not sure of your driver implementation, but according to this post there are a few tricks that can be employed for speedups. Writing a 4 pixels is slower than writing a defined 2x2 area as there is more switching. The Nordic nrf_gfx library for text writes pixels which is very inefficient. Each pixel requires a command and data, while the rectangle requires only one command and a stream of data.

Andy Cruz in the post implemented "fast_spi driver" but I couldn't make it work in his SDK 14.2 and spent hours trying to port it to 15.3 (I haven't migrated project to SDK16 yet due to not believing S332 was supported, which I was wrong).

EDIT: read post, you've done all of Andy's suggestions it seems

Copy link

lupyuen commented Feb 5, 2020

Thanks for the tip! Is this similar to the pixel and row batching that I mentioned in this article...

During my tests the batching seemed to improve rendering speed... Though some parameters need to be tuned, e.g. how much memory should we allocate for the batching.

Another problem we have is that the embedded-graphics driver will always rasterise graphical objects left to right, then top to bottom. That means I can't always batch the rendering into 2x2 pixels... I need to batch by entire row, say 16x2, if I'm rendering a graphical object that's 16 pixels wide.

Interesting challenges :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment