Raspberry Pi Pico PIO proof of concept, 15M pixels/sec

If anybody is using LVGL with Raspberry Pico, I suggest looking considering the Pico PIO for high throughput interface with the display.

Below is a proof of concept that uses a PIO state machine and 8 bits parallel data path to a ILI9488 TFT controller. The byte rate is 30M/sec which results in 15M pixels/sec (two bytes per pixels).

The proof of concept supports both 8 and 16 bits color depths with on-the-fly 8 bit to 16 bits color mapping to meet the 16 bits requirement of the TFT controller. Using LVGL 8 bits allows to have RAM buffer than contains the entire 320x480 screen, which provides smooth display due to the short display update time.

The PIO uses an 8 entries FIFO, and supports single byte mode for commands and data and dual byte mode for the pixels, as required by the ILI9488. The strobe WR pulses are generated automatically and the state machine is fine tuned for proper setup and hold times.

The hardware FIFO is also supported by the DMA but since the firmware runs fast enough to keep it full, I didn’t bothered with DMA.


Wow, that great!

I’d be very curious how it runs v8’s widget demo with enabled FPS monitor. Would b complicated to try it out?

1 Like

I have on my todo list to convert the app to V8 but need to find time. Will update here once it happens.

With a simple fill screen test program, it does 100fps (320x480) but with LVGL we need to add the rendering time.

BTW, would you expect significant different in LVGL in-memory rendering time between 8bit and 16bit color depth? I use 8 bits to fit the entire screen in RAM and map to 16bits on the fly during screen updates which can still send to the screen 30MB/sec.


Using 8 bit color depth instead of 16 affects the fill rate and “copy” rate but its fast anyway. I’m sure you lose more on converting from 8 to 16 bit even if you use a lookup table. Besides with 8 bit you lose the color gradients and fine antialiasing.

Out of curiosity, I had a play with this board,


Unfortunately there is a hard speed limit of about 1.5M pixels/sec using 16 bit colors (due to the SPI to parallel conversion circuitry hardware, which maxes out at about 24Mb/s).

I am currently running the RP2040 at 267MHz and intend on tweaking the code to use the second core to do flushing, but I doubt it will result in any really meaningful performance improvement.

This is not a great performer speed wise but at the price, (around $30 all in, excluding the pico itself which should cost less than $5-00) a 3.5" 480x320 display with touch capability it is never the less usable and useful for some applications that are not performance critical.

1 Like

Also I was interested to see if such a board could meet LVGL certification requirements, in this case the second core seems to have made all the difference between doing so (Run the demo with at least 15 FPS in average) and not doing so… :slight_smile:

Single Core,

Hello, thank you for sharing this, this was a great insight for me…

I am new to RP2040 and its PIO, and I will try to do parallel 8 bit RGB interfacing in SYNC-DE mode (8080 I guess?). Have you ever worked on this mode?

I am not familiar with SYNC DE mode, but from what I just read on the internet it seems to be a low level interface to a TFT screen where the TFT buffer and controller resides on the microcontroller side (?).

What I used is a TFT module that contains a ILI9488 controller. This makes the TFT module ‘smarter’ in a sense and easier to interface to.