Increase the Frame Rate on Your Raspberry Pi LCD Screen – SPI based LCD Panels
24th April 2021RetroPie on a Raspberry Pi Zero at 50FPS on an SPI LCD Screen With ILI9341 Driver
3rd May 2021Fastest FPS on Your Raspberry Pi SPI LCD Screen – Make RetroPie playable on a cheap LCD panel
You can connect an LCD panel to your Raspberry Pi using several different connections. HDMI and DSI panels plug straight into dedicated connectors on the board to give a full speed display without any need for setup. But these types of displays can be expensive and tend to be slightly larger screen sizes. If you want a cheap, small LCD panel you’ll probably end up using an SPI based device.
What Is SPI And Why Is It Not as Good?
SPI stands for Serial Peripheral Interface. The important bit here is serial. When the Raspberry Pi send data to the screen it has to send it one binary digit (bit) at a time. If you think about a small LCD screen with 480 pixels across and 320 down, that’s 153,600 pixels. Most of the small LCD screens use 16 bits per pixel so that gives you 2,457,600 binary digits of data to create one frame on your screen. Many of these small SPI screens are quoted as running up to 10 Mbits per second. If we divide that by the data required for one frame, we end up with only four frames per second.
This is a slideshow, not a video!
The Simple Way to Increase Frame Rate
The simplest way to get more frames per second is to simply send the data faster. Although the controller chips on the LCD screens might only be rated at 10 MHz you can usually push them quite a bit faster.
In my previous project we did just that. Using the standard drivers, we were able to increase the data bandwidth to 24 MHz on my particular screen. This gave us around 10 frames per second which was sort of playable. Pushing the speed beyond 24 MHz started to introduce colour errors where the data was being corrupted. The screen was still usable up to about 50 MHz and the colours weren’t terrible, but they were not correct.
So simply increasing the data bandwidth might be okay for some applications such as a project control panel or use of the mobile desktop, but if you want to set up RetroPie to emulate arcade and games consoles, it’s not that great.
Other Ways to Increase the Frame Rate
The other way to increase the frame rate rather than simply sending the data faster is to send less data per frame. If we don’t have to send as many bits per screen, we can then fit more frames per second into the same data bandwidth.
There are a couple of ways to help us reduce the amount of data needed to update each frame.
If we look at consecutive frames in any computer game, we’ll usually see that there are fairly large areas of the screen that don’t change between frames. Even on full-screen scrolling games, there are usually blocks of the background that are uniform block colour. If we can identify which pixels have changed and which have stayed the same between frames, we can simply send the data for the changed pixels and thereby reduce the overall amount of data required for that frame update.
This adaptive screen updating will of course give us variable results depending on how fast the colour data on the screen is changing. For a game like space invaders where the majority of the screen doesn’t move will get very large savings in screen data. For a 3D driving game where the scenery is flashing by, we might get very little savings.
A second technique to reduce the amount of data is to use interlacing. This is where we divide the screen into sets of horizontal rows, for example, odd and even rows. On the first frame update, we only send the odd-numbered rows to the LCD panel and on the second frame update, we only send the even. This does however mean that our LCD screen will always be showing half of one frame sliced up with half of another frame. This can make the image seem a little blurred or distorted, but it’s usually not very noticeable, and does give us a consistent 50% saving in data.
The FBCP-ILI9341 Driver
To get this all working on our LCD panel were going to need a new set of driver software. The FBCP-ILI9341 project combines the faster data rate solution with the adaptive screen update algorithm so we should get the fastest possible frame rates.
The ILI9341 in the project name refers to the driver chip used in one of the very common formats of LCD screen. Luckily this project has been expanded to not only cover this specific driver chip, but a whole range of driver chips so whatever SPI LCD screen you’re using it should be able to display your video output.
Installing the Driver
Installing the project is slightly more complicated than installing the default LCD drivers that come with your screen. Not only do we have to download the software, but we have to compile it with a specific set of options tailored to the LCD screen were using. All of this needs to be done through the Linux terminal. If you’re not familiar with using this, don’t worry, just type in the commands as I explain them.
Removing Any Existing Drivers
Before we install the new driver, we have to make sure that any existing drivers are removed. If we don’t the two will interfere with each other and our screen won’t work.
Two files control the drivers and services used by the LCD screen. The first is /boot/config/.txt. This file allows you to turn on various hardware services unload the LCD driver software. If you’re using RetroPie use the menu button and quit Emulation Station or if you’re just on a standard Raspberry Pi open a terminal window.
sudo nano /boot/config.txt
Typing in the above command will open the file for editing. We first need to make sure that the standard SPI drivers aren’t loaded. Look for the line
dtparam=spi=on
and comment it out by putting a # in front of it. Next we need to remove the LCD and touch panel drivers. Look for lines like
dtoverlay=waveshare32a
or something relevant to your LCD panel. Again, that out using a # symbol. Touch panel lines will look something like
dtoverlay=ads7846
or mention
penirq=
somewhere in the command. Again, comment these out.
Once you’ve edited this file press ctrl X to quit nano, Y to tell it to save the file and enter to accept the filename.
The second file we need to edit is /etc/rc.local which controls some of the start-up command options on the Raspberry Pi. Look for a command that mentions fbcp and comment that out. It may well have done & at the end of the line and that needs to be commented out.
change fbcp &
to
#fbcp &
You’ll now need to reboot the Raspberry Pi but make sure you’ve either got it connected to a monitor or that you’re able to use SSH to remotely access the device. We’ll need to make some more changes using the Linux terminal.
Installing the FBCP-ILI9341 Software
The software is stored as a GIT repository. Will first need to download the code onto our Raspberry Pi. Make sure you are in your home directory
cd ~
and then clone the software repository with the following command.
git clone https://github.com/juj/fbcp-ili9341.git
This should copy all the files into a folder in your home directory. We then need to make sure that the cmake application is installed on your computer.
sudo apt-get install cmake
It’s probably already installed but this will make sure it is and that it’s up to date. We are now ready to build a compile the software. Change directory to the project folder.
cd fbcp-ili9341
We then need to create a folder where we’ll build the actual software. It doesn’t matter what you call this directory but the convention is to call build.
mkdir build
Then change directory into this folder.
cd build
We now need to use the cmake application to create the build files with the correct options for our particular LCD screen.
cmake [options] ..
We’ll discuss what options you need to add but notice that there are two full stops at the end of the line. This ensures that our project is built using the files in the folder above where we are. Once this command is finished we need to compile the software.
make -j
This will create a file fbcp-ili9341 in our build directory which is the compiled driver for our LCD screen. We can check that works by typing the following command.
sudo ./fbcp-ili9341
You should see your monitor display mimicked on your LCD screen. Just press ctrl C to exit the driver.
Setting Your Build Options
In the above set of commands, we need to set some options when we ran the cmake application. These tell the driver software how the LCD screen is connected to our Raspberry Pi, what speed we want to run the SPI channel at and various other options.
For a complete list of options please have a look at the get hub repository README file at
https://github.com/juj/fbcp-ili9341
The first option we need to choose is to set up the connection. The software package has quite a few built-in settings for popular LCD screens. If like me, you’re using a generic screen that plugs onto the GPIO connector it will probably be compatible with one of the Waveshare setups. Although my screen in the video above match the Waveshare 35a, in this driver software it matches the resolution of the WaveShare 35b. So for me, my first option was
-DWAVESHARE35B_ILI9486=ON
The second option we need to set is with the SPI bus speed. This is generated from one of the internal clocks in the Raspberry Pi and we specify the bus speed as a divisor value, i.e. what number we divide the internal clock by to get the SPI bus clock speed. This must be an even number. The default internal bus speed is 400 MHz. It’s best to start with a large divisor, which gives a slower SPI bus speed and then decrease the divider, thereby increasing the bus speed, until we get the maximum stable value. To begin with, the repository programmer suggests a value of 30.
-DSPI_BUS_CLOCK_DIVISOR=30
So using an internal bus speed of 400 MHz gives us an SPI bus speed of 13.3 MHz.
There are several other options we can set but most of these are not needed as the software will automatically detect the best values and insert those for you.
Changing Your Options
As I mentioned above you need to play around with the make options to get the best setup for your device. Unfortunately, to change the options you need to rebuild the software. To do this make sure you’re in your terminal and in the repository directory ~/fbcp-ili9341. You then need to completely remove the build folder that we created earlier.
rm -r build
This is why we built it in a separate folder so that we can easily remove it. You then just need to return to the original build process, recreate the build folder and continue from there with your new set of options.
Automatically Starting the Driver When the Raspberry Pi Boots
To get the driver to automatically start when the Raspberry Pi boots up we need to add a command to your rc.local file.
sudo nano /etc/rc.local
Just before the exit 0 line, you need to add the following command.
sudo /home/pi/fbcp-ili9341/build/fbcp-ili9341 &
If you now reboot the Raspberry Pi you should find that your LCD panel starts up automatically. It does take a bit of time during the boot sequence before the LCD panel is activated so don’t worry that you don’t see the normal Raspberry Pi splash screen on the LCD.
On-Screen Statistics
When you initially build the software using the options above you will find there are some numbers at the top of the LCD screen. These are very useful while you are fine-tuning your settings as they show you how well the driver is performing. The most important set of numbers is in the very top left of the statistics panel. This tells you how many frames per second the display is running at.
The first number is the frames per second. This can be followed by either and i or p which tells us whether the driver is using interlacing (displaying half a frame followed by half of the next frame) or progressive (whole frames). Sometimes you might see a mixture of interlaced frames and progressive frames. After this you might see a number in red which indicates that some frames have been dropped, i.e. there wasn’t enough time to display them at all.
As you tune your setup you should aim to get the frame rate as high as possible, trying to keep it mostly progressive display, and trying to minimise the number of dropped frames. This does require a bit of playing around but using the statistics panel along with simply looking at how the game is displaying will help you get to the best setup.
Once you’re happy with your display you can turn the statistics panel off by adding a new option to your build settings and recompiling the software.
-DSTATISTICS=0
The Next Step
I’ve been looking at using an LCD panel with my Raspberry Pi to build a handheld retro games machine. For me, the next step is to try using this driver with a basic ILI9341 based LCD panel, identical to the ones used in my Arduino projects. These LCD panels use a separate connector with the various SPI connections so I will have to work out the connections to the Raspberry Pi and how to tell FBCP-ILI9341 what those connections are.
Make sure you subscribe to my YouTube channel to find out how I got on.