480x320 LCD w/ SPI is rather slow at drawing bitmaps

I have this TFT: https://www.waveshare.com/wiki/4inch_TFT_Touch_Shield

It is a shield for the Arduino UNO. I have the sample code successfully working as well.

I was experiencing some remarkable slowness when trying to draw bitmaps, and just generally the display is rather slow. I know I should expect this when trying to use larger displays, but I still can't help but feel like there's some optimization I could make here.

For benchmarking purposes, I made a small loop that draws a 32x32 bitmap in a 4x4 grid and prints the time it takes.

void loop()
{
  LCD_SetArealColor(0, 0, 128, 128, WHITE);

  unsigned long start_time = millis();

  for( uint8_t ii = 0; ii < 4; ii++ )
  for ( uint8_t jj = 0; jj < 4; jj++ ) {
    GUI_DisColorMap( ii*32, jj*32, testData, 32, 32 );
  }

  unsigned long end_time = millis();

  char str[8];

  sprintf( str, "%d\0", end_time - start_time );

  LCD_SetArealColor( 40, 120, 140, 150, WHITE );
  GUI_DisString_EN(40, 120, str, &Font24, LCD_BACKGROUND, BLUE);
}

This 128x128 draw takes a whopping 4.2 seconds to complete. And this is where I suspect something must be very unoptimized or flat-out wrong. But whatever I tried, I couldn't get my performance to change noticeably. So if anyone can offer advice about what in my setup or library could be so slow, that would be useful! :slight_smile:

More details:
Clock: 16MHz
SPI Clock: SPI_CLOCK_DIV2 (library's default. Is there a way to use /1 instead?)

As for optimizations, I tried:

  • Changing my compiler settings to -O3 from -Os
  • inlining the frequently called functions
  • partially unrolling the draw bitmap function
  • fixing an apparent bug in LCD_WriteData which writes two bytes out when it should only write one

None of those changes seemed to provide any large-scale improvements, perhaps shaving off 10% at the most. I made some of those improvements before I was using the benchmark, so I don't have real figures for those though, just subjective measures. Anyway, I figure the real culprit is something else. Any thoughts?

Bump.

I'm bumping again. Is there any further information I should provide that would be useful?

Thanks.

Your Display is basically a parallel 8080-16 bit screen. The Waveshare board contains some shift registers that are driven by SPI. It is a horrible hack. The shift register is far slower than the native TFT SPI interface.

Bodmer supports these "RaspberryPi" abortions but I don't know if his library runs on a Uno.

In theory, the display should work reasonably well on a Uno. The Uno SPI is only 8MHz. So it is not too fast for the shift registers.
The Waveshare demo code is not organised like a proper Arduino library. It is not practical for real Arduino projects.

I would try Bodmer's libraries. Let us know how you get on.

David.

The only library in my Github repository that suppoerts the RPi display is TFT_eSPI and this only runs on an ESP32 or ESP8266.

Bodmer

Yes, I tried a library that looked like the closest match (TFT_ILI9341). I wasn't able to get anything working, but I was going to dabble into that further to see if there were any obvious differences in the interface.

But I hear loud and clear the larger design-level concerns with this type of TFT. So in the interest of performance, I might try moving to another based on similar criteria. They are:

  • Pixel resolution (480x320. Due to existing code, I wouldn't like to change this)
  • Color
  • Backlight
  • Of course, support for Arduino. Also support with a suite for fonts/shapes similar to Adafruit_GFX
  • Size (anywhere from 4" to 7" on the diagonal)
  • If parallel, 16-bit or less (I don't have unlimited pins). And I don't know about it enough, but if HDMI or something similar is supported by a TFT (+an IC and Arduino library to interface with it), that route would be fine too

Of course, I could search for something like this on the internet, and have. But when it comes to Arduino compatibility, I'm more hazy on potential candidates. So if anyone knows something that meets or is near these criteria and is known to be compatible with Arduino, let me know.

Buy an ESP8266 or ESP32 from Ebay. They come in Uno-format boards as well as DIL modules.

Personally, I prefer the Uno-shape boards. They are not expensive. You can run Bodmer's TFT_eSPI library(s). You will get good performance from your "shift-register" display.

David.

Perhaps I'm not following you entirely. The ESPXXXX seems to be a microcontroller/SOC, not a screen.

You said:

You will get good performance from your "shift-register" display.

Are you saying that the microcontroller interfaces better with this existing 'shift-register' screen (confers better performance + works with bodmer's library)? I'm using an Arudino Uno to interface with this screen, and I actually have an atmega1284p with the Uno core on it that is my final target. What advantages does an ESPXXXX confer here?

My point was that you can buy Uno-shape boards with controllers that are a lot more powerful e.g, 32-bit @ 200MHz. And the boards are very cheap.

Yes, you should be able to run your shift-register display abortion from a regular Uno. It looks as if the 74HC4040 and 74HC4094 chips are input voltage tolerant for your 5V GPIO.

However, I am not aware that anyone has written an Arduino library compatible with the Uno.
The Waveshare examples make no attempt to be Arduino friendly.
The shift register abortion was originally aimed at the 3.3V RaspberryPi market. Plenty of CPU power and sensible GPIO voltage levels.

Bodmer said that his libraries do not run on a Uno. I have no intention of buying one of these displays. Nor do I want to write a library.

I was just suggesting that you don't have to pay much for ESP32 board or ESP8266 board

Note that these boards can store multiple JPEG images or several BMP files on their own Flash memory. You do not need an SD card.
They can also read a regular SD card much faster than a Uno.

David.