raspberry pi tft display projects free sample
Rather than plug your Raspberry Pi into a TV, or connect via SSH (or remote desktop connections via VNC or RDP), you might have opted to purchase a Raspberry Pi touchscreen display.
Straightforward to set up, the touchscreen display has so many possibilities. But if you"ve left yours gathering dust in a drawer, there"s no way you"re going to experience the full benefits of such a useful piece of kit.
The alternative is to get it out of the drawer, hook your touchscreen display to your Raspberry Pi, and reformat the microSD card. It"s time to work on a new project -- one of these ideas should pique your interest.
Let"s start with perhaps the most obvious option. The official Raspberry Pi touchscreen display is seven inches diagonal, making it an ideal size for a photo frame. For the best results, you"ll need a wireless connection (Ethernet cables look unsightly on a mantelpiece) as well as a Raspberry Pi-compatible battery pack.
Several options are available to create a Raspberry Pi photo frame, mostly using Python code. You might opt to script your own, pulling images from a pre-populated directory. Alternatively, take a look at our guide to making your own photo frame with beautiful images and inspiring quotes. It pulls content from two Reddit channels -- images from /r/EarthPorn and quotes from /r/ShowerThoughts -- and mixes them together.
Rather than wait for the 24th century, why not bring the slick user interface found in Star Trek: The Next Generation to your Raspberry Pi today? While you won"t be able to drive a dilithium crystal powered warp drive with it, you can certainly control your smart home.
In the example above, Belkin WeMo switches and a Nest thermostat are manipulated via the Raspberry Pi, touchscreen display, and the InControlHA system with Wemo and Nest plugins. ST:TNG magic comes from an implementation of the Library Computer Access and Retrieval System (LCARS) seen in 1980s/1990s Star Trek. Coder Toby Kurien has developed an LCARS user interface for the Pi that has uses beyond home automation.
Building a carputer has long been the holy grail of technology DIYers, and the Raspberry Pi makes it far more achievable than ever before. But for the carputer to really take shape, it needs a display -- and what better than a touchscreen interface?
Setting up a Raspberry Pi carputer also requires a user interface, suitable power supply, as well as working connections to any additional hardware you employ. (This might include a mobile dongle and GPS for satnav, for instance.)
Now here is a unique use for the Pi and its touchscreen display. A compact, bench-based tool for controlling hardware on your bench (or kitchen or desk), this is a build with several purposes. It"s designed to help you get your home automation projects off the ground, but also includes support for a webcam to help you record your progress.
The idea here is simple. With just a Raspberry Pi, a webcam, and a touchscreen display -- plus a thermal printer -- you can build a versatile photo booth!
Various projects of this kind have sprung up. While the versions displayed above uses a thermal printer outputting a low-res image, you might prefer to employ a standard color photo printer. The wait will be longer, but the results better!
Projects along these lines can also benefit from better use of the touchscreen. Perhaps you could improve on this, and introduce some interesting photo effects that can be tweaked via the touchscreen prior to printing?
How about a smart mirror for your Raspberry Pi touchscreen display project? This is basically a mirror that not only shows your reflection, but also useful information. For instance, latest news and weather updates.
Naturally, a larger display would deliver the best results, but if you"re looking to get started with a smart mirror project, or develop your own from scratch, a Raspberry Pi combined with a touchscreen display is an excellent place to start.
Many existing projects are underway, and we took the time to compile six of them into a single list for your perusal. Use this as inspiration, a starting point, or just use someone else"s code to build your own information-serving smart mirror.
Want to pump some banging "toons" out of your Raspberry Pi? We"ve looked at some internet radio projects in the past, but adding in a touchscreen display changes things considerably. For a start, it"s a lot easier to find the station you want to listen to!
This example uses a much smaller Adafruit touchscreen display for the Raspberry Pi. You can get suitable results from any compatible touchscreen, however.
Alternatively, you might prefer the option to integrate your Raspberry Pi with your home audio setup. The build outlined below uses RuneAudio, a Bluetooth speaker, and your preferred audio HAT or shield.
Requiring the ProtoCentral HealthyPi HAT (a HAT is an expansion board for the Raspberry Pi) and the Windows-only Atmel software, this project results in a portable device to measure yours (or a patient"s) health.
With probes and electrodes attached, you"ll be able to observe and record thanks to visualization software on the Pi. Whether this is a system that can be adopted by the medical profession remains to be seen. We suspect it could turn out to be very useful in developing nations, or in the heart of infectious outbreaks.
We were impressed by this project over at Hackster.io, but note that there are many alternatives. Often these rely on compact LCD displays rather than the touchscreen solution.
Many home automation systems have been developed for, or ported to, the Raspberry Pi -- enough for their own list. Not all of these feature a touchscreen display, however.
One that does is the Makezine project below, that hooks up a Raspberry Pi running OpenHAB, an open source home automation system that can interface with hundreds of smart home products. Our own guide shows how you can use it to control some smart lighting. OpenHAB comes with several user interfaces. However, if they"re not your cup of tea, an LCARS UI theme is available.
Another great build, and the one we"re finishing on, is a Raspberry Pi-powered tablet computer. The idea is simple: place the Pi, the touchscreen display, and a rechargeable battery pack into a suitable case (more than likely 3D printed). You might opt to change the operating system; Raspbian Jessie with PIXEL (nor the previous desktop) isn"t really suitable as a touch-friendly interface. Happily, there are versions of Android available for the Raspberry Pi.
This is one of those projects where the electronics and the UI are straightforward. It"s really the case that can pose problems, if you don"t own a 3D printer.
LCD, DPI, SPI, HDMI, NTSC/PAL, TFT, OLED, ePaper, etc. this is part of the jargon you will need some appreciation of in order to be able to choose the right display for your project.The first part covered HDMI, DSI and Composite Video. This second part will focus on displays that utilise GPIO and USB as a mean to connect the screen to you Raspberry Pi. Hopefully as we look at the various options some of the jargon will be clearer. We will also venture into some additional considerations and alternative approaches to complete the “picture” (pun intended).
GPIO is the acronym for General Purpose Input Output and the main bonus that comes with it is that you can reconfigure each pin as either an Input and Output but also deem them to provide a different type of interface for the various types of displays and boards in general.
You can find displays that use DPI, SPI, I2C and even UART or an ad-hoc interface. Some Interfaces like DPI are particularly fast but will require lots of GPIO to interface with the screen, others like SPI and I2C need very few pins but won’t be as fast as DPI. Ultimately choosing between them will be down to your projects requirements. Let’s look at examples for each.
As a reference for the pins we can use the invaluable pinout.xyz website with alink to the DPI interface. As you can see the interface can use up to 28 pins and therefore should only if can allocate the GPIO pretty much just for the display. A lotmore informationcan be found at the Raspberry Pi website.
Pimoroni’s HyperPixelis a 4.0″ high speed display with a resolution of 800×480 and 18 bit per pixel. It also features aversion with the a capacitive touchand has a breakout port for the I2C interface. There is also aGithub repositorywhere you can find its drivers.
TheGert VGA 666 brainchild of Gert Van Looproducedby Pi Supplyand distributed by many is a very nice and cheap way of reusing an old VGA monitor. It doesn’t use all of the DPI pins because, as it says on the tin, it only use the 6 bits per colour mode or RGB666 and unlike the HyperPixel leave some pins free to be reused. As it becomes more and more rare to find VGA monitors in lofts I suppose this board will become eventually obsolete but it is still worth considering especially when working on legacy projects.
TheAdafruit DPI Kippahoffers in a similar way to the HyperPixel an 18 bit per pixel with 800×480 resolution but this time the screen is an LVDS display with choice between 5″ and 7″. This board also comes with or without the capacitive touch. Additional resources can be found ontheir Github repository. An earlier breakout board that Adafruit offered led to aninteresting detailed project documented on this blogworth having a look if you want to know more about venturing the DPI way.
As the author of the blog also stresses out this approach is not straightforward and simply might not work in many cases. Fun to explore I’d imagine but wouldn’t think it would take on any time soon also because, as I said int my previous article, these LVDS displays are not any laptop display, one shouldn’t get the wrong idea that all of a sudden your long gone laptop getting dust in the loft can with these have a second life; it probably won’t. That’s why Adafruit offers asmall selection of compatible displays.
SPI and I2C are amongst the favourite by vendors as they offer pretty much what’s needed for most use cases, utilise few pins and can be used by other hardware platforms quite easily. So no surprise to see the likes of Waveshare having quite a selection covering pretty much all the various interfaces.
WithSPIthe amount of pins required is much less, it only requires 4-5 pins and that’s why vendors are often adding additional hardware to their displays. SPI allows to control more than one device on its bus but it’s generally not used for more than one.
As for SPI evenI2Crequires few pins, in fact it only needs 2 which makes this interface very light in terms of GPIO usage. One additional advantage is that it’s very easy to use other peripherals in parallel to the same I2C bus making this option quite versatile.
One of the main downsides of these technologies is that you will end up with fairly small displays which provide good graphic support but very low resolutions and with modern OSs unless you come up with your own custom made GUI it will make using the display very difficult indeed.
A good bonus in getting an SPI or I2C display is that in general they come with additional hardware like buttons, LEDs and others due to the availability of many spare pins.
This is anSPI display I found on Conrad, it is a 4.57 cm (1.8″) TFT display and can provide 262, 000 colours with a resolution of 128×160 pixels. This is not a HAT and can easily be used for other platforms.
In the middle theRPi Display from Watterottavailable fromtheir own shopis a 2.8″ TFT with touchscreen with a resolution of 240×320, dimmable backlight, 3 buttons and full HAT compliance.
Thelast one is from Adafruitand similarly to the Watterott comes with additional buttons, 4 in this case. The TFT screen resolution is 320×240, features a resistive touchscreen and the backlight is dimmable via PWM.Adafruit offers a number of these screenssome with higher resolution and screen size.
The first from the left is a monochromaticAdafruit OLED0.96″ display with a resolution of 128×64. It comes with a breakout connector and can therefore be used with Arduino and other platforms. Even in this caseAdafruit has more to offerin terms of this type of screens with colour ones and bonnets designs (a type of pHAT essentially. That goes to show that in the absence of a standard chaos reigns, thanks God we now have theuHAT). This particular display can also be driven via SPI.
The middlesdisplay is from Pimoroni, it is also an OLED, it measures 1.12″, has a resolution of 128×128 and offers a breakout connector specifically designed to easily interface to a Raspberry Pi. As they also recommend there is anice libraryyou can use with your Pi.
Thelast one is again from Adafruitand it is one of my favourites. It shows how tiny and useful these OLED screen can be. The form factor is a SHIM which is a small pHAT.In Yorkshire accent” “Shove Hardware In’t Middle”— pimoroni (@pimoroni)February 20, 2019
As pHAT the SHIM is not a standard either and in fact it’s only used by Pimoroni but it’s a nice way to identify this size of PCBs and I vote for IEEE to adopt the term officially! The display is monochrome and has a resolution of 128×23 and it’s just a great addition to your headless Pi. Adafruit offer many good quality tutorials and there isone also for this display.
LCD displays like theHD44780 16×2are very common and widely used, they are cheap, well known and there are plenty of resources available. When all you need is just a bit of feedback and text is sufficient then these are the go-to technology also due to their low power requirements. There is a reallynice article from the RaspberryPi Spywhich shows how to use the I2C backpack that allows to indeed use the HD44780 via I2C thereby saving many pins and allow for a more modular approach for your project. The backpack also controls the dimmable backlight.
There are several versions of these displays with coloured backlight or more lines of text, evenOLEDnaturally but in general the principle and purpose are the same.
ePaper displays get featured here as the ones I found all use SPI. ePapers are truly nice when you are tight with power i.e. running off batteries and when you don’t need the picture refreshed often, you’ll still need to refresh it periodically but you will not risk getting ghosting effects due to always displaying the same image for days or months. You will in fact be able to display something then power-off your Raspberry Pi for a week and still keep the image on the display. It’s nothing new as the Amazon Kindle got us used to but it’s great to get this technology in our project. The screens come in very many different sizes to fit anybody’s need. A word of caution though, be careful with these screens as they are very, very delicate to the touch and brake easily.
Repaper, Pi Supply, Pimoroni, Waveshare, Adafruit are the biggest players getting a slice of the ePaper market. They all offer different screen sizes and features. This type of display offers such a variety that it would require a series of articles in itself. The ePaper screens are coming from one or two manufactures but each vendor tries to create a different product by leveraging on the features that the controller board offers as well as the software resources that come with it.
Waveshare has probably the largest selection of screens ranging from 1.54″ to 9.7″, monochromatic and colour, and resolutions between 200×200 to 1200×825, they even havea new generation of flexiblescreens. They all appear to use the sameSPI driver boardwhich can either be connected to the Raspberry Pi’s GPIO or to other hardware platforms via a breakout connector. TheirWiki pagesoffer additional information and resources like demos and videos.
PaPiRus from Pi Supply was the first ePaper for the Raspberry Pi to get on the market after a very successfulkickstarter campaignwhich produced the HAT version of PaPiRus featuring 4 buttons, a breakout connector but most importantly an RTC circuit notoriously missing on the Raspberry Pi. ThePaPiRus HATsupports 1.44″, 1.9″, 2.0″, 2.6″ and 2.7″ ePaper screens whereas thePaPiRus Zerosupports 1.44″ and 2.0″. Pi Supply, now called Nebra Ltd, joined forces withRePapera couple of year ago and I’m sure we will soon see more from them in terms of offer. There is a buzzing community of people working onPaPiRus Github repositorywhich over the years added a lot of features to these boards.
A couple of years ago Pimoroni came out with their own ePaper boards. TheInky pHATfollowed by theInky wHATcalled this way as it exceeds the dimension of a HAT and lacks some of the features the HATs requires. (they have a tendency to coin new standards anyway :). The Inky pHAT is a 212×104 pixel e-paper display whereas the Inky wHAT has a resolution on 400×300. They are available in red/black/white, yellow/black/white or black/white for the pHAT only. More information on resources on theirGithub repository.
Adafruit has also got some ePaper displays. TheAdafruit SHARP Memory LCDdoesn’t seem to be supported for the Raspberry Pi nor I could find any resources that would indicate that but it is an interesting display for which at some point a library could be made available. It has an SPI interface, has a resolution of 168×144, it is ultra low power but most importantly has a fast-refresh rate comparable to an LCD. Although this is technically not an e-Ink display it is still worth considering for a specific set of use cases where it is important to be able to read the display in broad daylight and also refresh the images particularly fast.
Thelast display from Adafruitis in fact three SPI, Tri-Color (Red, Black, White) eInk / ePaper Displays with SRAM with screen sizes of 1.54″, 2.13″ and 2.7″ and resolutions of 152×152, 212×104 and 264×176. They come with a small SRAM chip in order to be able to store the buffer whilst a microcontroller fills it up essentially. This is particularly useful with small Arduino like boards. Once again there is no support for the Raspberry Pi but worth looking at if anything to see how much investment there is on the market for this type of technology.
This is somewhat a limited case and doesn’t really provide a “display” as you would expect it to be. I thought though that it would be worth covering this product as it will be useful under some use cases. UART allows for example for the display to be quite far from the Raspberry Pi distance wise and it is such a ubiquitous standard that it will find support in many if not all programming languages and it will certainly be something you can use on other hardware platforms too.
I came across theNextion displaysduring a Meetup in London and within half an hour someone had already created a nice interface to presumably order more beer by selecting the right amount with a slider. The bottom line was though that the time it took to have something “useful” of these displays was really short. Productivity come in mind!
These aren’t displays in a traditional sense, you have to think of them as displays with their own graphics which you can sort of drive and customise to your needs via UART.NEXTION is a Human Machine Interface (HMI) solution combining a TFT touch display with an onboard processor and memory, developing by a free and downloadable NEXTION Editor software. Using the NEXTION Editor software, you can quickly develop the HMI GUI by drag-and-drop components (graphics, text, button, slider etc.) and ASCII text based instructions for coding how components interact at display side. With just 2 wires (RX, TX), NEXTION display quickly connects to MCU via 5V TTL Serial to provide event notifications that MCU can act on, and utilizes simple ASCII text based instructions so the MCU can easily provide progress and status updates back to your HMI user.
The TFT screens with integrated 4-wire resistive Touch Panel feature RGB 65K true to life colours, 4M flash memory and an on board micro-SD card for firmware upgrade. A lot more information can be found viatheir Wiki.
Thisarticle from Random Nerd Tutorialsexplains a bit more what to do and how using an Arduino but it shouldn’t be too far off using a Raspberry Pi instead.
In searching material for these articles I came across some exotic approaches and some other less uncommon ones like driving a HD44780 directly from the GPIO. There are several articles describing the connections and the programming here a small selection:
This way of using the HD44780 display won’t be as straight forward as using it with the I2C interface showed above and won’t use as few pins either but it is nevertheless an easy option to add a display in a headless configuration or in any case where graphics is not required and characters are possibly used to navigate through a menu and show some limited output for your program.
USB can offer good performances and similarly to what HDMI or Video Composite could offer a fairly long leash for the the screen to be located away from the Raspberry Pi. There aren’t many displays that offer support for the Raspberry Pi although there could be more to come.
This2.8″ USB TFT Touch DisplayfromRoboPeakhas a resolution of 320×240 with 16bpp and supports USB2.0 Full-Speed. It can work with several other hardware platforms boards and has a niceWiki pageand aGithub repositoryalthough neither have been recently updated. It feels as though this product might have been abandoned.
Some of the technologies deal with how the display is connected to the Raspberry Pi, some are to do with how the images are actually displayed. In both cases you will have differences in performances and that will be one of the parameters to factor in your requirements i.e. Do you display static pictures or videos? Do you need colours? How many? Is power consumption an important factor?
Ultimately choosing a display is finding something that satisfies your requirements and you will have to look at the display’s specifications against your project’s requirements. There are though other factors you should be looking at:
These things are IMO more important than the cost of the display itself and you should check the quality of the resources available no matter how pretty was the Ad for the product you intend to buy or how much cheaper it was compared to a better resourced alternative.
After you’ve chosen the right display for your project you might also need a case for your Raspberry Pi, your display and whatever else you need for your idea to work in a nice enclosure.
There are several vendors which offer general purpose cases some of which I showed in the previous article. Of particular note isModMyPi which has a huge selection of casesmany of which designed by them.
Some displays don’t come with aFrame Bufferoption which allows your OS to output to the screen for example during boot time. Seeing what happens during boot or more generally be able to use the display as a standard output for you OS is very useful. Many projects will then integrate this functionality in their drivers and request the OS maintainers to natively include it for ease of installation.
One example of these is provided byNotro whose Github repositoryoffers drivers for small TFT displays. These things aren’t at all straight forward but it is still interesting to always dig a bit deeper and get an appreciation of how many skilled people are sharing their knowledge for free often improving commercial products beyond their original purpose.
SPI and I2C are interfaces on which vendors are rather productive and the choice here is much wider than with DPI. The answer I believe is that hopefully DSI but certainly already the HDMI interfaces render using the DPI less of a need and more of a luxury, SPI and I2C are enough when it comes to provide some feedback to the end user and in some cases even pretty good graphical contents.
AtThe Things Network in Amsterdam Pi Supply now Nebra Ltdhas officially presented a new Pocket Projector which comes either standalone or as HAT for the Raspberry Pi.
I guess pico projectors as maybe OLED, flexible and foldable, bigger ePaper displays, screen cast or mirroring are what we could see in the near future for the Raspberry Pi. Some of these are already there if using the right OS but whatever it’s going to be hopefully now you have a better understanding of how to choose the best display for your Raspberry Pi.
The TFT LCD class provides basic firmware functionalities like Init, ResetDevice, WriteDevice, WriteDataToDevice, WriteBlock and FillRectangle.
DISPLAY_FUNCTION_CONTROL = const(0xb6);ENABLE_3G = const(0xf2);POS_GAMMA_CONTROL = const(0xe0)MEMORY_BUFFER = const(1024) # SPI Write Bufferclass ILI9488:
bpl(loopstart)SCR_WIDTH,SCR_HEIGHT,SCR_ROT = const(480),const(320),const(5)TFT_CLK_PIN,TFT_MOSI_PIN,TFT_MISO_PIN,TFT_CS_PIN = const(6),const(7),const(4),const(0)
display = ILI9488(spi,cs=Pin(TFT_CS_PIN),dc=Pin(TFT_DC_PIN),rst=Pin(TFT_RST_PIN),w=SCR_WIDTH,h=SCR_HEIGHT,r=SCR_ROT)display.SetPosition(0,0);display.FillRectangle(0,0,480,320,0xBDF7)# Read files.
Raspberry Pi is a Palm Size computer that comes in very handy when prototyping stuff that requires high computational power. It is being extensively used for IOT hardware development and robotics application and much more memory hunger applications. In most of the projects involving the Pi it would be extremely useful if the Pi had a display through which we can monitor the vitals of our project.
The pi itself has a HDMI output which can be directly connected to a Monitor, but in projects where space is a constrain we need smaller displays. So in this tutorial we will learn how we can interface the popular 3.5 inch Touch Screen TFT LCD screen from waveshare with Raspberry pi. At the end of this tutorial you will have a fully functional LCD display with touch screen on top of your Pi ready to be used for your future projects.
It is assumed that your Raspberry Pi is already flashed with an operating system and is able to connect to the internet. If not, follow the Getting started with Raspberry Pi tutorial before proceeding.
It is also assumed that you have access to the terminal window of your raspberry pi. In this tutorial we will be using Putty in SSH mode to connect to the Raspberry Pi. You can use any method but you should somehow be able to have access to your Pi’s terminal window.
Connecting your 3.5” TFT LCD screen with Raspberry pi is a cake walk. The LCD has a strip of female header pins which will fit snug into the male header pins. You just have to align the pins and press the LCD on top of the Pi to make the connection. Once fixed properly you Pi and LCD will look something like this below. Note that I have used a casing for my Pi so ignore the white box.
For people who are curious to know what these pins are! It is used to establish a SPI communication between the Raspberry Pi and LCD and also to power the LCD from the 5V and 3.3V pin of the raspberry Pi. Apart from that it also has some pins dedicated for the touch screen to work. Totally there are 26 pins, the symbol and description of the pins are shown below
Now, after connecting the LCD to PI, power the PI and you will see a blank white screen on the LCD. This is because there are no drivers installed on our PI to use the connected LCD. So let us open the terminal window of Pi and start making the necessary changes. Again, I am using putty to connect to my Pi you can use your convenient method.
Step 2: Navigate to Boot Options -> Desktop/CLI and select option B4 Desktop Autologin Desktop GUI, automatically logged in as ‘pi’ user as highlighted in below image. This will make the PI to login automatically from next boot without the user entering the password.
Step 3: Now again navigate to interfacing options and enable SPI as show in the image below. We have to enable the SPI interface because as we discussed the LCD and PI communicates through SPI protocol
Step 4: Click on this waveshare driver link to download the driver as a ZIP file. Then move the ZIP file to you PI OS. I used Filezilla to do this, but you can also use a pen drive and simple copy paste work. Mine was placed in the path /home/pi.
Step 7: Now use the below command to restart your Pi. This will automatically end the terminal window. When the PI restarts you should notice the LCD display also showing the boot information and finally the desktop will appear as shown below.
Hope you understood the tutorial and were successful in interfacing your LCD with PI and got it working. If otherwise state your problem in the comment section below or use the forums for more technical quires.
An excellent new compatible library is available which can render TrueType fonts on a TFT screen (or into a sprite). This has been developed by takkaO and is available here. I have been reluctant to support yet another font format but this is an amazing library which is very easy to use. It provides access to compact font files, with fully scaleable anti-aliased glyphs. Left, middle and right justified text can also be printed to the screen. I have added TFT_eSPI specific examples to the OpenFontRender library and tested on RP2040 and ESP32 processors, however the ESP8266 does not have sufficient RAM. Here is a demo screen where a single 12kbyte font file binary was used to render fully anti-aliased glyphs of gradually increasing size on a 320x480 TFT screen:
The TFT configuration (user setup) can now be included inside an Arduino IDE sketch providing the instructions in the example Generic->Sketch_with_tft_setup are followed. See ReadMe tab in that sketch for the instructions. If the setup is not in the sketch then the library settings will be used. This means that "per project" configurations are possible without modifying the library setup files. Please note that ALL the other examples in the library will use the library settings unless they are adapted and the "tft_setup.h" header file included. Note: there are issues with this approach, #2007 proposes an alternative method.
Support has been added in v2.4.70 for the RP2040 with 16 bit parallel displays. This has been tested and the screen update performance is very good (4ms to clear 320 x 480 screen with HC8357C). The use of the RP2040 PIO makes it easy to change the write cycle timing for different displays. DMA with 16 bit transfers is also supported.
Smooth fonts can now be rendered direct to the TFT with very little flicker for quickly changing values. This is achieved by a line-by-line and block-by-block update of the glyph area without drawing pixels twice. This is a "breaking" change for some sketches because a new true/false parameter is needed to render the background. The default is false if the parameter is missing, Examples:
New anti-aliased graphics functions to draw lines, wedge shaped lines, circles and rounded rectangles. Examples are included. Examples have also been added to display PNG compressed images (note: requires ~40kbytes RAM).
Frank Boesing has created an extension library for TFT_eSPI that allows a large range of ready-built fonts to be used. Frank"s library (adapted to permit rendering in sprites as well as TFT) can be downloaded here. More than 3300 additional Fonts are available here. The TFT_eSPI_ext library contains examples that demonstrate the use of the fonts.
Users of PowerPoint experienced with running macros may be interested in the pptm sketch generator here, this converts graphics and tables drawn in PowerPoint slides into an Arduino sketch that renders the graphics on a 480x320 TFT. This is based on VB macros created by Kris Kasprzak here.
The RP2040 8 bit parallel interface uses the PIO. The PIO now manages the "setWindow" and "block fill" actions, releasing the processor for other tasks when areas of the screen are being filled with a colour. The PIO can optionally be used for SPI interface displays if #define RP2040_PIO_SPI is put in the setup file. Touch screens and pixel read operations are not supported when the PIO interface is used.
The use of PIO for SPI allows the RP2040 to be over-clocked (up to 250MHz works on my boards) in Earle"s board package whilst still maintaining high SPI clock rates.
DMA can now be used with the Raspberry Pi Pico (RP2040) when used with both 8 bit parallel and 16 bit colour SPI displays. See "Bouncy_Circles" sketch.
The library now supports the Raspberry Pi Pico with both the official Arduino board package and the one provided by Earle Philhower. The setup file "Setup60_RP2040_ILI9341.h" has been used for tests with an ILI9341 display. At the moment only SPI interface displays have been tested. SPI port 0 is the default but SPI port 1 can be specifed in the setup file if those SPI pins are used.
The library now provides a "viewport" capability. See "Viewport_Demo" and "Viewport_graphicstest" examples. When a viewport is defined graphics will only appear within that window. The coordinate datum by default moves to the top left corner of the viewport, but can optionally remain at top left corner of TFT. The GUIslice library will make use of this feature to speed up the rendering of GUI objects (see #769).
An Arduino IDE compatible graphics and fonts library for 32 bit processors. The library is targeted at 32 bit processors, it has been performance optimised for STM32, ESP8266 and ESP32 types. The library can be loaded using the Arduino IDE"s Library Manager. Direct Memory Access (DMA) can be used with the ESP32, RP2040 and STM32 processors with SPI interface displays to improve rendering performance. DMA with a parallel interface is only supported with the RP2040.
For other processors the generic only SPI interface displays are supported and slower non-optimised standard Arduino SPI functions are used by the library.
"Four wire" SPI and 8 bit parallel interfaces are supported. Due to lack of GPIO pins the 8 bit parallel interface is NOT supported on the ESP8266. 8 bit parallel interface TFTs (e.g. UNO format mcufriend shields) can used with the STM32 Nucleo 64/144 range or the UNO format ESP32 (see below for ESP32).
The library supports some TFT displays designed for the Raspberry Pi (RPi) that are based on a ILI9486 or ST7796 driver chip with a 480 x 320 pixel screen. The ILI9486 RPi display must be of the Waveshare design and use a 16 bit serial interface based on the 74HC04, 74HC4040 and 2 x 74HC4094 logic chips. Note that due to design variations between these displays not all RPi displays will work with this library, so purchasing a RPi display of these types solely for use with this library is not recommended.
A "good" RPi display is the MHS-4.0 inch Display-B type ST7796 which provides good performance. This has a dedicated controller and can be clocked at up to 80MHz with the ESP32 (55MHz with STM32 and 40MHz with ESP8266). The MHS-3.5 inch RPi ILI9486 based display is also supported.
Some displays permit the internal TFT screen RAM to be read, a few of the examples use this feature. The TFT_Screen_Capture example allows full screens to be captured and sent to a PC, this is handy to create program documentation.
The library supports Waveshare 2 and 3 colour ePaper displays using full frame buffers. This addition is relatively immature and thus only one example has been provided.
The library includes a "Sprite" class, this enables flicker free updates of complex graphics. Direct writes to the TFT with graphics functions are still available, so existing sketches do not need to be changed.
A Sprite is notionally an invisible graphics screen that is kept in the processors RAM. Graphics can be drawn into the Sprite just as they can be drawn directly to the screen. Once the Sprite is completed it can be plotted onto the screen in any position. If there is sufficient RAM then the Sprite can be the same size as the screen and used as a frame buffer. Sprites by default use 16 bit colours, the bit depth can be set to 8 bits (256 colours) , or 1 bit (any 2 colours) to reduce the RAM needed. On an ESP8266 the largest 16 bit colour Sprite that can be created is about 160x128 pixels, this consumes 40Kbytes of RAM. On an ESP32 the workspace RAM is more limited than the datasheet implies so a 16 bit colour Sprite is limited to about 200x200 pixels (~80Kbytes), an 8 bit sprite to 320x240 pixels (~76kbytes). A 1 bit per pixel Sprite requires only 9600 bytes for a full 320 x 240 screen buffer, this is ideal for supporting use with 2 colour bitmap fonts.
One or more sprites can be created, a sprite can be any pixel width and height, limited only by available RAM. The RAM needed for a 16 bit colour depth Sprite is (2 x width x height) bytes, for a Sprite with 8 bit colour depth the RAM needed is (width x height) bytes. Sprites can be created and deleted dynamically as needed in the sketch, this means RAM can be freed up after the Sprite has been plotted on the screen, more RAM intensive WiFi based code can then be run and normal graphics operations still work.
If an ESP32 board has SPIRAM (i.e. PSRAM) fitted then Sprites will use the PSRAM memory and large full screen buffer Sprites can be created. Full screen Sprites take longer to render (~45ms for a 320 x 240 16 bit Sprite), so bear that in mind.
The "Animated_dial" example shows how dials can be created using a rotated Sprite for the needle. To run this example the TFT interface must support reading from the screen RAM (not all do). The dial rim and scale is a jpeg image, created using a paint program.
The XPT2046 touch screen controller is supported for SPI based displays only. The SPI bus for the touch controller is shared with the TFT and only an additional chip select line is needed. This support will eventually be deprecated when a suitable touch screen library is available.
The library supports SPI overlap on the ESP8266 so the TFT screen can share MOSI, MISO and SCLK pins with the program FLASH, this frees up GPIO pins for other uses. Only one SPI device can be connected to the FLASH pins and the chips select for the TFT must be on pin D3 (GPIO0).
The library contains proportional fonts, different sizes can be enabled/disabled at compile time to optimise the use of FLASH memory. Anti-aliased (smooth) font files in vlw format stored in SPIFFS are supported. Any 16 bit Unicode character can be included and rendered, this means many language specific characters can be rendered to the screen.
The library is based on the Adafruit GFX and Adafruit driver libraries and the aim is to retain compatibility. Significant additions have been made to the library to boost the speed for the different processors (it is typically 3 to 10 times faster) and to add new features. The new graphics functions include different size proportional fonts and formatting features. There are lots of example sketches to demonstrate the different features and included functions.
Configuration of the library font selections, pins used to interface with the TFT and other features is made by editing the User_Setup.h file in the library folder, or by selecting your own configuration in the "User_Setup_Selet,h" file. Fonts and features can easily be enabled/disabled by commenting out lines.
The .vlw files must be uploaded to the processors FLASH filing system (SPIFFS, LittleFS or SD card) for use. Alternatively the .vlw files can be converted to C arrays (see "Smooth Font -> FLASH_Array" examples) and stored directly in FLASH as part of the compile process. The array based approach is convenient, provides performance improvements and is suitable where: either use of a filing system is undesirable, or the processor type (e.g. STM32) does not support a FLASH based filing system.
It would be possible to compress the vlw font files but the rendering performance to a TFT is still good when storing the font file(s) in SPIFFS, LittleFS or FLASH arrays.
Anti-aliased fonts can also be drawn over a gradient background with a callback to fetch the background colour of each pixel. This pixel colour can be set by the gradient algorithm or by reading back the TFT screen memory (if reading the display is supported).
The common 8 bit "Mcufriend" shields are supported for the STM Nucleo 64/144 boards and ESP32 UNO style board. The STM32 "Blue/Black Pill" boards can also be used with 8 bit parallel displays.
Unfortunately the typical UNO/mcufriend TFT display board maps LCD_RD, LCD_CS and LCD_RST signals to the ESP32 analogue pins 35, 34 and 36 which are input only. To solve this I linked in the 3 spare pins IO15, IO33 and IO32 by adding wires to the bottom of the board as follows:
If the display board is fitted with a resistance based touch screen then this can be used by performing the modifications described here and the fork of the Adafruit library:
If you load a new copy of TFT_eSPI then it will overwrite your setups if they are kept within the TFT_eSPI folder. One way around this is to create a new folder in your Arduino library folder called "TFT_eSPI_Setups". You then place your custom setup.h files in there. After an upgrade simply edit the User_Setup_Select.h file to point to your custom setup file e.g.:
The library was intended to support only TFT displays but using a Sprite as a 1 bit per pixel screen buffer permits support for the Waveshare 2 and 3 colour SPI ePaper displays. This addition to the library is experimental and only one example is provided. Further examples will be added.
In these videos, the SPI (GPIO) bus is referred to being the bottleneck. SPI based displays update over a serial data bus, transmitting one bit per clock cycle on the bus. A 320x240x16bpp display hence requires a SPI bus clock rate of 73.728MHz to achieve a full 60fps refresh frequency. Not many SPI LCD controllers can communicate this fast in practice, but are constrained to e.g. a 16-50MHz SPI bus clock speed, capping the maximum update rate significantly. Can we do anything about this?
The fbcp-ili9341 project started out as a display driver for the Adafruit 2.8" 320x240 TFT w/ Touch screen for Raspberry Pi display that utilizes the ILI9341 controller. On that display, fbcp-ili9341 can achieve a 60fps update rate, depending on the content that is being displayed. Check out these videos for examples of the driver in action:
Given that the SPI bus can be so constrained on bandwidth, how come fbcp-ili9341 seems to be able to update at up to 60fps? The way this is achieved is by what could be called adaptive display stream updates. Instead of uploading each pixel at each display refresh cycle, only the actually changed pixels on screen are submitted to the display. This is doable because the ILI9341 controller, as many other popular controllers, have communication interface functions that allow specifying partial screen updates, down to subrectangles or even individual pixel levels. This allows beating the bandwidth limit: for example in Quake, even though it is a fast pacing game, on average only about 46% of all pixels on screen change each rendered frame. Some parts, such as the UI stay practically constant across multiple frames.
A hybrid of both Polled Mode SPI and DMA based transfers are utilized. Long sequential transfer bursts are performed using DMA, and when DMA would have too much latency, Polled Mode SPI is applied instead.
Undocumented BCM2835 features are used to squeeze out maximum bandwidth: SPI CDIV is driven at even numbers (and not just powers of two), and the SPI DLEN register is forced in non-DMA mode to avoid an idle 9th clock cycle for each transferred byte.
Good old interlacing is added into the mix: if the amount of pixels that needs updating is detected to be too much that the SPI bus cannot handle it, the driver adaptively resorts to doing an interlaced update, uploading even and odd scanlines at subsequent frames. Once the number of pending pixels to write returns to manageable amounts, progressive updating is resumed. This effectively doubles the maximum display update rate. (If you do not like the visual appearance that interlacing causes, it is easy to disable this by uncommenting the line #define NO_INTERLACING in file config.h)
A number of other micro-optimization techniques are used, such as batch updating rectangular spans of pixels, merging disjoint-but-close spans of pixels on the same scanline, and latching Column and Page End Addresses to bottom-right corner of the display to be able to cut CASET and PASET messages in mid-communication.
The result is that the SPI bus can be kept close to 100% saturation, ~94-97% usual, to maximize the utilization rate of the bus, while only transmitting practically the minimum number of bytes needed to describe each new frame.
although not all boards are actively tested on, so ymmv especially on older boards. (Bug fixes welcome, use https://elinux.org/RPi_HardwareHistory to identify which board you are running on)
This driver does not utilize the notro/fbtft framebuffer driver, so that needs to be disabled if active. That is, if your /boot/config.txt file has lines that look something like dtoverlay=pitft28r, ..., dtoverlay=waveshare32b, ... or dtoverlay=flexfb, ..., those should be removed.
This program neither utilizes the default SPI driver, so a line such as dtparam=spi=on in /boot/config.txt should also be removed so that it will not cause conflicts.
If you have been running existing fbcp driver, make sure to remove that e.g. via a sudo pkill fbcp first (while running in SSH prompt or connected to a HDMI display), these two cannot run at the same time. If /etc/rc.local or /etc/init.d contains an entry to start up fbcp at boot, that directive should be deleted.
When using one of the displays that stack on top of the Pi that are already recognized by fbcp-ili9341, you don"t need to specify the GPIO pin assignments, but fbcp-ili9341 code already has those. Pass one of the following CMake directives for the hats:
-DFREEPLAYTECH_WAVESHARE32B=ON: If you are running on the Freeplay CM3 or Zero device, pass this flag. (this is not a hat, but still a preconfigured pin assignment)
-DPIRATE_AUDIO_ST7789_HAT=ON: If specified, targets a Pirate Audio 240x240, 1.3inch IPS LCD display HAT for Raspberry Pi with ST7789 display controller
-DKEDEI_V63_MPI3501=ON: If specified, targets a KeDei 3.5 inch SPI TFTLCD 480*320 16bit/18bit version 6.3 2018/4/9 display with MPI3501 display controller.
If you connected wires directly on the Pi instead of using a Hat from the above list, you will need to use the configuration directives below. In addition to specifying the display, you will also need to tell fbcp-ili9341 which GPIO pins you wired the connections to. To configure the display controller, pass one of:
-DILI9341=ON: If you are running on any other generic ILI9341 display, or on Waveshare32b display that is standalone and not on the FreeplayTech CM3/Zero device, pass this flag.
-DILI9340=ON: If you have a ILI9340 display, pass this directive. ILI9340 and ILI9341 chipsets are very similar, but ILI9340 doesn"t support all of the features on ILI9341 and they will be disabled or downgraded.
-DILI9486L=ON: If you have a ILI9486L display, pass this directive. Note that ILI9486 and ILI9486L are quite different, mutually incompatible controller chips, so be careful here identifying which one you have. (or just try both, should not break if you misidentified)
-DGPIO_TFT_DATA_CONTROL=number: Specifies/overrides which GPIO pin to use for the Data/Control (DC) line on the 4-wire SPI communication. This pin number is specified in BCM pin numbers. If you have a 3-wire SPI display that does not have a Data/Control line, set this value to -1, i.e. -DGPIO_TFT_DATA_CONTROL=-1 to tell fbcp-ili9341 to target 3-wire ("9-bit") SPI communication.
-DGPIO_TFT_RESET_PIN=number: Specifies/overrides which GPIO pin to use for the display Reset line. This pin number is specified in BCM pin numbers. If omitted, it is assumed that the display does not have a Reset pin, and is always on.
-DGPIO_TFT_BACKLIGHT=number: Specifies/overrides which GPIO pin to use for the display backlight line. This pin number is specified in BCM pin numbers. If omitted, it is assumed that the display does not have a GPIO-controlled backlight pin, and is always on. If setting this, also see the #define BACKLIGHT_CONTROL option in config.h.
fbcp-ili9341 always uses the hardware SPI0 port, so the MISO, MOSI, CLK and CE0 pins are always the same and cannot be changed. The MISO pin is actually not used (at the moment at least), so you can just skip connecting that one. If your display is a rogue one that ignores the chip enable line, you can omit connecting that as well, or might also be able to get away by connecting that to ground if you are hard pressed to simplify wiring (depending on the display).
To get good performance out of the displays, you will drive the displays far out above the rated speed specs (the rated specs yield about ~10fps depending on display). Due to this, you will need to explicitly configure the target speed you want to drive the display at, because due to manufacturing variances each display copy reaches a different maximum speed. There is no "default speed" that fbcp-ili9341 would use. Setting the speed is done via the option
-DSPI_BUS_CLOCK_DIVISOR=even_number: Sets the clock divisor number which along with the Pi core_freq= option in /boot/config.txt specifies the overall speed that the display SPI communication bus is driven at. SPI_frequency = core_freq/divisor. SPI_BUS_CLOCK_DIVISOR must be an even number. Default Pi 3B and Zero W core_freq is 400MHz, and generally a value -DSPI_BUS_CLOCK_DIVISOR=6 seems to be the best that a ILI9341 display can do. Try a larger value if the display shows corrupt output, or a smaller value to get higher bandwidth. See ili9341.h and waveshare35b.h for data points on tuning the maximum SPI performance. Safe initial value could be something like -DSPI_BUS_CLOCK_DIVISOR=30.
There are a couple of options to explicitly say which Pi board you want to target. These should be autodetected for you and generally are not needed, but e.g. if you are cross compiling for another Pi board from another system, or want to be explicit, you can try:
-DSINGLE_CORE_BOARD=ON: Pass this option if you are running on a Pi that has only one hardware thread (Pi Model A, Pi Model B, Compute Module 1, Pi Zero/Zero W). If not present, autodetected.
-DARMV8A=ON: Pass this option to specifically optimize for ARMv8-A instruction set (Pi 2B >= rev. 1.2, 3B, 3B+, CM3, CM3 lite, 4B, CM4, Pi400). If not present, autodetected.
-DBACKLIGHT_CONTROL=ON: If set, enables fbcp-ili9341 to control the display backlight in the given backlight pin. The display will go to sleep after a period of inactivity on the screen. If not, backlight is not touched.
-DDISPLAY_CROPPED_INSTEAD_OF_SCALING=ON: If set, and source video frame is larger than the SPI display video resolution, the source video is presented on the SPI display by cropping out parts of it in all directions, instead of scaling to fit.
-DDISPLAY_BREAK_ASPECT_RATIO_WHEN_SCALING=ON: When scaling source video to SPI display, scaling is performed by default following aspect ratio, adding letterboxes/pillarboxes as needed. If this is set, the stretching is performed breaking aspect ratio.
-DDISPLAY_SWAP_BGR=ON: If this option is passed, red and blue color channels are reversed (RGB<->BGR) swap. Some displays have an opposite color panel subpixel layout that the display controller does not automatically account for, so define this if blue and red are mixed up.
-DDISPLAY_INVERT_COLORS=ON: If this option is passed, pixel color value interpretation is reversed (white=0, black=31/63). Default: black=0, white=31/63. Pass this option if the display image looks like a color negative of the actual colors.
-DLOW_BATTERY_PIN=
Here is a full example of what to type to build and run, if you have the Adafruit 2.8" 320x240 TFT w/ Touch screen for Raspberry Pi with ILI9341 controller:
If the above does not work, try specifying -DSPI_BUS_CLOCK_DIVISOR=8 or =10 to make the display run a little slower, or try with -DUSE_DMA_TRANSFERS=OFF to troubleshoot if DMA might be the issue. If you are using another display controller than ILI9341, using a much higher value, like 30 or 40 may be needed. When changing CMake options, you can reissue the CMake directive line without having to reclone or recreate the build directory. However you may need to manually delete file CMakeCache.txt between changing options to avoid CMake remembering old settings.
If the user name of your Raspberry Pi installation is something else than the default pi, change the directory accordingly to point to the user"s home directory. (Use pwd to find out the current directory in terminal)
If the size of the default HDMI output /dev/fb0 framebuffer differs from the resolution of the display, the source video size will by default be rescaled to fit to the size of the SPI display. fbcp-ili9341 will manage setting up this rescaling if needed, and it will be done by the GPU, so performance should not be impacted too much. However if the resolutions do not match, small text will probably appear illegible. The resizing will be done in aspect ratio preserving manner, so if the aspect ratios do not match, either horizontal or vertical black borders will appear on the display. If you do not use the HDMI output at all, it is probably best to configure the HDMI output to match the SPI display size so that rescaling will not be needed. This can be done by setting the following lines in /boot/config.txt:
These lines hint native applications about the default display mode, and let them render to the native resolution of the TFT display. This can however prevent the use of the HDMI connector, if the HDMI connected display does not support such a small resolution. As a compromise, if both HDMI and SPI displays want to be used at the same time, some other compatible resolution such as 640x480 can be used. See Raspberry Pi HDMI documentation for the available options to do this.
The refresh speed of the display is dictated by the clock speed of the SPI bus that the display is connected to. Due to the way the BCM2835 chip on Raspberry Pi works, there does not exist a simple speed=xxx Mhz option that could be set to define the bus speed. Instead, the SPI bus speed is derived from two separate parameters: the core frequency of the BCM2835 SoC in general (core_freq in /boot/config.txt), and the SPI peripheral CDIV (Clock DIVider) setting. Together, the resulting SPI bus speed is then calculated with the formula SPI_speed=core_freq/CDIV.
Adjust the CDIV value by passing the directive -DSPI_BUS_CLOCK_DIVISOR=number in CMake command line. Possible values are even numbers 2, 4, 6, 8, .... Note that since CDIV appears in the denominator in the formula for SPI_speed, smaller values result in higher bus speeds, whereas higher values make the display go slower. Initially when you don"t know how fast your display can run, try starting with a safe high setting, such as -DSPI_BUS_CLOCK_DIVISOR=30, and work your way to smaller numbers to find the maximum speed the display can cope with. See the table at the end of the README for specific observed maximum bus speeds for different displays.
Ensure turbo speed. This is critical for good frame rates. On the Raspberry Pi 3 Model B, the BCM2835 core runs by default at 400MHz (resulting in 400/CDIV MHz SPI speed) if there is enough power provided to the Pi, and if the CPU temperature does not exceed thermal limits. If the CPU is idle, or voltage is low, the BCM2835 core will instead revert to non-turbo 250MHz state, resulting in 250/CDIV MHz SPI speed. This effect of turbo speed on performance is significant, since 400MHz vs non-turbo 250MHz comes out to +60% of more bandwidth. Getting 60fps in Quake, Sonic or Tyrian often requires this turbo frequency, but e.g. NES and C64 emulated games can often reach 60fps even with the stock 250MHz. If for some reason under-voltage protection is kicking in even when enough power should be fed, you can force-enable turbo when low voltage is present by setting the value avoid_warnings=2 in the file /boot/config.txt.
Perhaps a bit counterintuitively, underclock the core. Setting a smaller core frequency than the default turbo 400MHz can enable using a smaller clock divider to get a higher resulting SPI bus speed. For example, if with default core_freq=400 SPI CDIV=8 works (resulting in SPI bus speed 400MHz/8=50MHz), but CDIV=6 does not (400MHz/6=66.67MHz was too much), you can try lowering core_freq=360 and set CDIV=6 to get an effective SPI bus speed of 360MHz/6=60MHz, a middle ground between the two that might perhaps work. Balancing core_freq= and CDIV options allows one to find the maximum SPI bus speed up to the last few kHz that the display controller can tolerate. One can also try the opposite direction and overclock, but that does then of course have all the issues that come along when overclocking. Underclocking does have the drawback that it makes the Pi run slower overall, so this is certainly a tradeoff.
On the other hand, it is desirable to control how much CPU time fbcp-ili9341 is allowed to use. The default build settings are tuned to maximize the display refresh rate at the expense of power consumption on Pi 3B. On Pi Zero, the opposite is done, i.e. by default the driver optimizes for battery saving instead of maximal display update speed. The following options can be controlled to balance between these two:
The main option to control CPU usage vs performance aspect is the option #define ALL_TASKS_SHOULD_DMA in config.h. Enabling this option will greatly reduce CPU usage. If this option is disabled, SPI bus utilization is maximized but CPU usage can be up to 80%-120%. When this option is enabled, CPU usage is generally up to around 15%-30%. Maximal CPU usage occurs when watching a video, or playing a fast moving game. If nothing is changing on the screen, CPU consumption of the driver should go down very close to 0-5%. By default #define ALL_TASKS_SHOULD_DMA is enabled for Pi Zero, but disabled for Pi 3B.
The CMake option -DUSE_DMA_TRANSFERS=ON should always be enabled for good low CPU usage. If DMA transfers are disabled, the driver will run in Polled SPI mode, which generally utilizes a full dedicated single core of CPU time. If DMA transfers are causing issues, try adjusting the DMA send and receive channels to use for SPI communication with -DDMA_TX_CHANNEL=
Enabling #define USE_GPU_VSYNC reduces CPU consumption, but because of raspberrypi/userland#440 can cause stuttering. Disabling #defined USE_GPU_VSYNC produces less stuttering, but because of raspberrypi/userland#440, increases CPU power consumption.
The option #define SELF_SYNCHRONIZE_TO_GPU_VSYNC_PRODUCED_NEW_FRAMES can be used in conjunction with #define USE_GPU_VSYNC to try to find a middle ground between raspberrypi/userland#440 issues - moderate to little stuttering while not trying to consume too much CPU. Try experimenting with enabling or disabling this setting.
If your SPI display bus is able to run really fast in comparison to the size of the display and the amount of content changing on the screen, you can try enabling #define UPDATE_FRAMES_IN_SINGLE_RECTANGULAR_DIFF option in config.h to reduce CPU usage at the expense of increasing the number of bytes sent over the bus. This has been observed to have a big effect on Pi Zero, so is worth checking out especially there.
If the SPI display bus is able to run really really really fast (or you don"t care about frame rate, but just about low CPU usage), you can try enabling #define UPDATE_FRAMES_WITHOUT_DIFFING option in config.h to forgo the adaptive delta diffing option altogether. This will revert to naive full frame updates for absolutely minimum overall CPU usage.
In display.h there is an option #define TARGET_FRAME_RATE
A pleasing aspect of fbcp-ili9341 is that it introduces very little latency overhead: on a 119Hz refreshing ILI9341 display, fbcp-ili9341 gets pixels as response from GPIO input to screen in well less than 16.66 msecs time. I only have a 120fps recording camera, so can"t easily measure delays shorter than that, but rough statistical estimate of slow motion video footage suggests this delay could be as low as 2-3 msecs, dominated by the ~8.4msecs panel refresh rate of the ILI9341.
This does not mean that overall input to display latency in games would be so immediate. Briefly testing a NES emulated game in Retropie suggests a total latency of about 60-80 msecs. This latency is caused by the NES game emulator overhead and extra latency added by Linux, DispmanX and GPU rendering, and GPU framebuffer snapshotting. (If you ran fbcp-ili9341 as a static library bypassing DispmanX and the GPU stack, directly linking your GPIO input and application logic into fbcp-ili9341, you would be able to get down to this few msecs of overall latency, like shown in the above GPIO input video)
Interestingly, fbcp-ili9341 is about ~33msecs faster than a cheap 3.5" KeDei HDMI display. I do not know if this is a result of the KeDei HDMI display specifically introducing extra latency, or if all HDMI displays connected to the Pi would have similar latency overhead. An interesting question is also how SPI would compare with DPI connected displays on the Pi.
Unfortunately a limitation of SPI connected displays is that the VSYNC line signal is not available on the display controllers when they are running in SPI mode, so it is not possible to do vsync locked updates even if the SPI bus bandwidth on the display was fast enough. For example, the 4 ILI9341 displays I have can all be run faster than 75MHz so SPI bus bandwidth-wise all of them would be able to update a full frame in less than a vsync interval, but it is not possible to synchronize the updates to vsync since the display controllers do not report it. (If you do know of a display that does actually expose a vsync clock signal even in SPI mode, you can try implementing support to locking on to it)
You can however choose between two distinct types of tearing artifacts: straight line tearing and diagonal tearing. Whichever looks better is a bit subjective, which is why both options exist. I prefer the straight line tearing artifact, it seems to be less intrusive than the diagonal tearing one. To toggle this, edit the option #define DISPLAY_FLIP_ORIENTATION_IN_SOFTWARE in config.h. When this option is enabled, fbcp-ili9341 produces straight line tearing, and consumes a tiny few % more CPU power. By default Pi 3B builds with straight line tearing, and Pi Zero with the faster diagonal tearing. Check out the video Latency and tearing test #2: GPIO input to display latency in fbcp-ili9341 and