Ideas for improving LCD speed

It’s disappointing, but I think I’ll stick with my idea of using the 8-colour (3-bit) mode for now… :confused:

spi_freq = clk_peri / (2 * clk_div) where clk_div is an integer >= 1 and spi_freq <= requested spi speed. Therefore your 240MHz should’ve theoretically resulted in 40MHz with clk_div=3. Setting 200MHz for your overclock should’ve given you your target spi clock value of 50MHz

RGB565 does work. You need to output 0x55 to register 0x3A when setting up the display. Here is an example: picocalc_lua/drivers/lcd.c at 180a58e6eff857f2106b8ce3fdfa2c3715b9e58c · benob/picocalc_lua · GitHub

1 Like

Knock yourself out trying. IT DOESN’T WORK. It can work on displays like some of the Waveshare ones that use an external shift register and actually connect to the display in parallel mode. In that case 0x55 is correct but RGB565 is not supported by straight 3 or 4 wire SPI. The ILI9488 datasheet is clear on this.


That’s just it… I personally don’t find the datasheet very clear about this point.
Admittedly, there is no example as there is for the others, but there is a line indicating this (only for 4-lanes SPI which is fortunately our case).
Nerds sometimes like to get hurt trying :slight_smile:

I’ve just tried more deeply, indeed 50 MHz can be reached with 200 clk_sys. I’ve tried 60 MHz too with 240 clk_sys, got some bad pixels just once.

So… Maybe the datasheet has underestimated performance or we are in a corner that is not stable depending on the environment (temperature, etc.).

In the case of full framebuffer copy, in 18-bits colors mode (666RGB), 320x320x24@50Mbps => ~20 FPS
And in the case of 16-bits colors mode (565RGB), if it works, 320x320x16@50Mbps => ~30 FPS.

1 Like

How do you set the freq of the LCD? I played with the baud rate passed to spi_init but I don’t get consistent results. The max I can set it is 105 million bauds with rp2350 at 210 MHz, which results in a 38 screen updates per second, but I don’t fully grasp this frequency source/divider business and I am not sure what the underlying LCD freq is.

Another advantage of 8 color mode is there’s enough VRAM for page flipping. There’s no way the 3 byte per pixel mode could work. Doesn’t sound like 2 byte per pixel mode will work over SPI either. If it did, there’s enough VRAM for 540 rows, which means you could probably do something weird with the “fixed” regions and have a centered double-buffered 320x240 region with page flipping.

2 Likes

I’m not sure what you mean. You’re talking about the FPS when saying “LCD freq”?

In a nutshell, the maximum SPI clock speed is equal to the “CPU/clk_sys” speed divided by 2.

Thanks. I am starting to get a better understanding.

1 Like

It’s works for sure I am using RGB565 with SPI with 16bits (2 bytes) transfers.
Also I am getting 25fps on lvgl app without any overclocking

1 Like

If the renderer supports partial updates instead of full buffer render it will be faster.
From lvgl docs

The “hard” part is the choice of when to redraw small areas or a single large one.I wanted to do some experimentation on this method at some point.

lvgl is doing it by itself in render engine, by marking the changed areas or like saving only diffs between the frames

2 Likes

Has anybody tried to use PIO to send a paletted framebuffer or to raster characters from a text framebuffer?

Ben, I just had a gander at the lcd driver in that Mac emulator you posted. Nice job! Seems like 565 really does work just fine. It looks like you were able to use DMA to copy data to the display? Did you find that was faster than bit-banging it from the CPU?

Just noticed only the fill routine uses DMA (and it looks like it won’t work correctly if you fill a region larger than 256 pixels that isn’t a multiple of 256). Any reason the general draw routine couldn’t use a blocking DMA to process the input data?

Thanks,

-Dave

Look like I need to eat humble pie on the RGB565 issue. I wonder if there may have been a ILI9488 update to allow this? My copy of the datasheet clearly says that 4-wire SPI only supports RGB111 and RGB666 and the ILI9488 displays I own simply don’t work in RGB565. Interesting.

They must have changed it at some point, some brief searching turned up a post from 2018:

The ILI9341 can be configured for 2 bytes (565) or 3 byte (666) in SPI mode. The ILI9481 / ILI9486 / ILI9488 can only use (666) mode.

And I’ve found other random bits of code out there

/* Interface mode

  • 0: SPI mode (the lcd does not work in 16bit/pixel mode in spi, so you have to write 24bit/pixel)
  • 1: paralell mode */
    #define ILI9488_INTERFACE 0

That back up your experiences.

DMA is work in progress :wink:
I was benchmarking the different techniques and forgot to remove the code.
In 16 bit mode, the difference with spi_write16_blocking is marginal. It is faster in 32 bit mode but doesn’t fill the whole screen. I suspect it eats half of the data.
For the Mac emu I wanted to give PIO a try to convert from 1bpp to 3bpp and free the CPU for something else or down clock it.

1 Like

To start getting familiar with the SDK, I picked a project that looked pretty simple — the SD flash boot loader — and got it to build properly on my setup.

It looks like it was based on the same lcd code that ships in the primary PicoCalc repo.

I hacked it up to write 565 colors directly, and changed the memory mode in the init function from 0x66 to 0x55 and it definitely works. I compared the init code to Ben’s Mac emulator and it was pretty close… the frame rate setup was different but I found I could comment that part out entirely and it was fine.

I did have to hack the rect fill function to just send the same pixel w*h times instead of messing with the pixel buffer… something in there wasn’t working properly for me.

-Dave

Just for fun been playing and easily getting 50FPS using the ILI9488 in RGB111 mode (320x320 or 480x320). The code works with a RGB111 framebuffer in RAM and the second processor core updating the screen in the background. Needs width*height / 8 * 3 bytes for the framebuffer so best on an RP2350. Would need a lot of work to properly integrate with MMBasic as SPI shared with touch and sdcard running on core0. And everything on core1 needs to be memory resident otherwise writing flash kills it.

2 Likes