How to display video at 25FPS?Rp2350 based LCD

Hi ,

I am trying to display a video(Mp4) , the screen size is 240*240 pixels. the display I am using is attached below

currently I am trying to display a few frames of a video just to check if I am able to run it at 25 FPS. I tried changing the delay() and millis() , I even removed it. But it still doesn't seem to improve the FPS.

I am unsure how to optimise the process to be able to display at 25fps.

UWORD *BlackImage;

void setup() {
  // put your setup code here, to run once:
  if(DEV_Module_Init() != 0)
    Serial.println("GPIO Init Fail!");
  else
    Serial.println("GPIO Init successful!");
 
  LCD_1IN28_Init(HORIZONTAL);
  DEV_SET_PWM(50);
  LCD_1IN28_Clear(BLACK);
  UDOUBLE Imagesize = LCD_1IN28_HEIGHT * LCD_1IN28_WIDTH * 2;
  
  if ((BlackImage = (UWORD *)malloc(Imagesize)) == NULL)
  {
      Serial.println("Failed to apply for black memory...");
      exit(0);
  }
  // /*1.Create a new image cache named IMAGE_RGB and fill it with white*/
  Paint_NewImage((UBYTE*)BlackImage, LCD_1IN28.WIDTH, LCD_1IN28.HEIGHT, 0, WHITE); 
  Paint_SetScale(65);
  Paint_Clear(BLACK);
  Paint_SetRotate(ROTATE_0);
  Paint_Clear(WHITE);
  
}

void loop() {
//run through frames and display them
 for (int i = 1; i < 12; i++)
 {
  
 Paint_DrawImage(images[i], 0, 0, 240, 240);
 LCD_1IN28_Display(BlackImage);
 //millis(40);
 delay(40);
  
  }
     
}```


Any help is appreciated.

What is the source image dimension (w * h) in pixels and what is the format of the images?
Where you stored the images?

I store them in an array as attached below, I have about 10-12 arrays like these, they are big so I have attached a small snippet. Source image dimension is 240240, The video was for a round 240240 display. Its a custom video. Currently I have stored them in flash memory. The display has 4mb flash.

What is the LCD interface? SPI ? QSPI? Parallel?

LCD interface is SPI. It uses a GC9A01A driver.

Lets try to calculate what is needed just to transfer the video to the screen via SPI.
Frame size is 240*240 pixels, each pixel is 16 bits = total 921600 bits.
To display the frames at 25 fps, you need to transfer 23 Mbit per second, that is, you need to run SPI at 25 MHz.
And this will only be writing to the screen, but you also need to read data from flash and execute the main code - so I think it will not be an exaggeration to say that for 25 fps video you must run SPI to transfer data at least at 50 MHz.

Now look at the default SPI speed - in Arduino - it is only 4 MHz,

Taking this into account, it looks funny that your code is written as if the transfer of the image to the screen happens instantly. You even inserted a delay :slight_smile:

Even without a delay, your program simply won't have time to transfer this data to the display in time.

Thanks for the detailed explanation. Much appreciated!! My hardware is my limitation. If I used a processor with 3MB ram and 120Mhz clock speed. Do you think then GC9A01A driver could be a limitation ?

Is the display library capable of displaying an image directly from flash memory? If not, save the buffer for each frame of the video in flash, and do a direct copy to the ram buffer, bypassing the bitmap to buffer processing.

You might be able to get the speeds @b707 is talking about using a PIO module and DMA. This would be a non trivial exercise since you would be rewriting a significant part of the driver.

I checked the datasheets, I can go up to 100Mhz, I tried increasing the speed but no improvement.

I am using a custom library built by waveshare. Hence I am unsure on how to do what youre saying. I am adding a snippet of the function I use to display the image. I am also attaching other functions that we use.

/******************************************************************************
function :	Sends the image buffer in RAM to displays
parameter:
******************************************************************************/
void LCD_1IN28_Display(UWORD *Image)
{
    UWORD j;
    LCD_1IN28_SetWindows(0, 0, LCD_1IN28_WIDTH, LCD_1IN28_HEIGHT);
    DEV_Digital_Write(LCD_DC_PIN, 1);
    for (j = 0; j < LCD_1IN28_HEIGHT; j++) {
        DEV_SPI_Write_nByte((uint8_t *)&Image[j*LCD_1IN28_WIDTH], LCD_1IN28_WIDTH*2);
    }
}

void DEV_SPI_Write_nByte(uint8_t pData[], uint32_t Len)
{
     SPI1.transfer(pData, Len);
}

Probably a bug, if you like, in the arduino-pico support, the SPIClass slowing down the speed as internally it sends byte by byte.
Luckily one can use the SDK spi functions...
My board 172x320 updated in 106ms with Waveshare library for the display.
Now using SDK, (still in arduino), it refreshes a screen in 15ms. (75MHz spi clock)
Here is what in my DEV_Config.cpp goes:

uint8_t DEV_Module_Init(void)
{
    Serial.begin(115200);
    DEV_Delay_ms(100);

    // GPIO Config
    DEV_GPIO_Init();
    
    // SPI Config

    // Initialize SPI using SDK functions (instead of Arduino SPI.begin())
    // Ensure pins are correctly set for SPI0
    // Example default pins: SCK (GPIO18), MOSI (GPIO19), MISO (GPIO16)
    // You must know which SPI instance you're using (spi0 or spi1)
    spi_init(spi0, 75 * 1000 * 1000); // Initialize spi0 at 60MHz (or 50MHz, etc.)
    gpio_set_function(LCD_CLK_PIN, GPIO_FUNC_SPI); // SCK
    gpio_set_function(LCD_MOSI_PIN, GPIO_FUNC_SPI); // MOSI
    gpio_set_function(LCD_MISO_PIN, GPIO_FUNC_SPI); // MISO (even if not used for TX-only)
    uint spi_baud = spi_get_baudrate(spi0);
    Serial.printf("SPI baudrate: %d\n", spi_baud);


    // Set up CS and DC pins as GPIO outputs
    pinMode(LCD_CS_PIN, OUTPUT);
    // Ensure they are initially deselected/correct state
    DEV_Digital_Write(LCD_CS_PIN, 1); // CS high (deselected)
    return 0;
}

/**
 * SPI
 **/
void DEV_SPI_WriteByte(uint8_t Value)
{
    // SPI.transfer(Value);
    spi_write_blocking(spi0, &Value, 1);
}

void DEV_SPI_Write_nByte(uint8_t pData[], uint32_t Len)
{
    //  SPI.transfer(pData, Len);
    spi_write_blocking(spi0, pData, Len);
}

Then make sure you don't use the SPI.xxxx function anywhere in your project. (only use the SDK spi functions to access your spi)
Note: my board uses spi0, so you will need to adapt for spi1.
Good luck,
Karelv.