kedei 3.5 inch spi tft lcd version 6.3 made in china

While googling for any info about lcd controller I came across this page: http://heikki.virekunnas.fi/2015/raspberry-pi-tft/, author managed to get from manufacturer patch file for kernel sources and tested it with 4.1.y - on which lcd worked. But still LCD replace HDMI, but I want to use this screen as additional for user interaction, while the bigger on HDMI as presentation monitor.

Since, fbtft has been merged with rpi kernel, so the fb drivers (including ili9341.c) was moved to fbtft_device driver (so the author of page can"t compile latest kernel with driver+patch).

So something about hardware, which I reverse engineered by the "hard way" - "grab multimeter and run through all LCD FPC pins and shift register pins"

Now I noticed there is "9486L" which can suggest that LCD screen is controlled by ILI9486L, I found this LCD on taobao too but I can"t contact seller.

I"m pretty sure about D/C (Pin 37 on LCD) and Reset (Pin 19 on LCD) pins by looking into driver code, but I can"t identify other signals (WR/RD/CS/etc...)

[ 0.000000] Linux version 3.18.9-v7 (lgh@lgh-ThinkPad-X200) (gcc version 4.7.1 20120402 (prerelease) (crosstool-NG 1.15.2) ) #7 SMP PREEMPT Sun Jun 28 09:33:18 CST 2015

- Controller is not ILI9341/ILI9325 - those are for smaller displays (320x240, etc...), I guess this might be ILI9486/9488 because they are for 480x320 displays. But when I compared init with DS it does not fit right so LCD can have a clone of ILI9486/9488 ...

- Module use only SPI interface and two CE signals (CE0 for touch controller, CE1 for LCD shift registers - compared to others lcd modules, in KeDei module this is swapped),

kedei 3.5 inch spi tft lcd version 6.3 made in china

As far as dual-monitor use, I had last looked into dual (or split) LCD and HDMI monitor use, but could not get that working. Long story short, I would not recommend wasting too much time on this LCD screen, it is mostly for static displays, not active gaming.

The screen refresh rate across the SPI (serial peripheral interface) is too slow for retropie. It will result in "screen tearing" and choppy video, with a frame rate of about 2-3 per second. This is unacceptable for games.

kedei 3.5 inch spi tft lcd version 6.3 made in china

Thanks for donating the display @Vvvsebastar . Got it now to work, uploaded first working version of code up at a backup branch https://github.com/juj/fbcp-ili9341/tree/kedei_v6_3_mpi3501 - that gets pixels showing on screen, although far from ready.

It looks like according to https://github.com/goodtft/LCD-show the display is a "MPI3501" controller. That is a new one, have not encountered this before. The implementation was done by by sniffing the data bus from the working binary driver.

Something that took two nights of debugging to figure out, is that there is a peculiar interplay of the touch controller and the LCD display in play. The two pieces are not separate, i.e. it is not possible to just initialize the display, but one must initialize both, they communicate internally somehow. Another head scratcher is that the T_CS and L_CS lines have some kind of interaction as well. After sending each 32-bit frame to the LCD display, one must do a dummy "pump" the Chip Select line of the Touch Controller to be enabled for a fraction of a microsecond (with no actual communication taking place), after which the LCD display CS line needs to be disabled likewise for a ~50ns period. That is, one cannot ignore the T_CS line if touch is not in use, but the LCD display is unable to receive/process commands if the Touch Controller is not flipped after each sent 32-bit frame. This hurts bandwidth and CPU usage, and also prevents use of DMA, because it would mean that the DMA controller should write to three data lines simultaneously in a synchronized manner, instead of just pumping bytes out the SPI MOSI bus, something that the DMA controller on the Pi cannot do (without resorting to bit banging). It is not yet certain if pixel color data writes have the same requirement as well, or if this peculiar LCD+Touch pumping is only needed for initialization and/or bus commands though.

Brief speed testing suggests that the controller can reliably handle a 33.333MHz SPI bus speed, but it was not able to do 40MHz. Because of the CS line juggling, effective bus speed remains lower, about 22mbps (22/33 ~ 67% utilization). Tallying up the above protocol framing with -75% / -50% wastage, the effective pixel bandwidth is something around 5.5mbps - 11mbps. The design choices lose around ~66%-85% of the bandwidth they could have had.

kedei 3.5 inch spi tft lcd version 6.3 made in china

This is a modified version of the official PJRC ILI9341_t3 library (https://github.com/PaulStoffregen/ILI9341_t3) to work with KeDei Raspberry Pi displays.

And it is always a Work In Progress. Also using a lot of work from the the Raspberry Pi implementation: https://github.com/cnkz111/RaspberryPi_KeDei_35_lcd_v62

This library was created to allow extended use on the KeDei Raspberry Pi display and supports T3.5, t3.6 T4 and beyond. It also has support for other T3.x boards as well as TLC.

Your SPI communications on this board does not go directly to display but instead go to three shift registers. There are also two SPI Chip select pins, one labeled, which looks like it is for the Display and the other looks like it is for the touch controller. This is partially true.

However the SPI communications with the display are a lot different than any other I have seen. For example there are no reset pins, nor a Data/Command(DC) pin. Instead this information is encoded into the SPI data that you send to the display.

We figured it out, as the RPI startup code, did several strange SPI transfers at the beginning, which appeared like they were directed to the XPT2046 Touch controller.

So if you send the byte E7 to the display with Touch CS asserted, it starts a AtoD conversion on that AUX pin, and transfer of two more zeros, will return you the AtoD value from AUX,

This library borrows some concepts and functionality from another ILI9341 library, https://github.com/KurtE/ILI9341_t3n. It also incorporates functionality from the TFT_ILI9341_ESP, https://github.com/Bodmer/TFT_ILI9341_ESP, for additional functions:

The teensy 3.6 and now 3.5 have a lot more memory than previous Teensy processors, so on these boards, I borrowed some ideas from the ILI9341_t3DMA library and added code to be able to use a logical Frame Buffer. To enable this I added a couple of API"s

kedei 3.5 inch spi tft lcd version 6.3 made in china

I orderer a 3.5″ SPI touchscreen with a Raspberry Pi 2 and a case, thinking it would be easy to set up, as it seemed to be like the one here. Unfortunately that was not the case.

With some googling I found out it was made by KeDei LCD and exactly this screen. Identifying strings on the screens were “Madei in KeDei of china”, “3.5 linch SPI TFTLCD”, “480*320 16bit/18bit” and “vision 1.0 2015/6/11”. I hope the guys who made this screen can write code better than english… Seems like it requires custom drivers by KeDei. Drivers could be downloaded from Baidu and they include the diff to compile your custom kernel. I haven’t compiled kernels before, so lets see if I could manage without doing that.

The drivers replaced current kernel with a custom 3.18.x version with drivers in it, so you can’t update kernel if using that method. Perhaps I should try to compile more recent kernel with drivers.

I installed Ubuntu on my Macbook Pro on an external hard drive (which is a whole another story, thanks to EFI), so I could follow instructions on Raspberry Pi pages. Compiling on RPi is quite slow (tried that overnight), so cross compiling is the way to go. Following the instructions worked pretty well, however I cloned tools to my home directory and added /home/heikki/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin to my path. After that everything worked as expected. After cloning and changing branch to rpi-4.1.y I patched semi-manually from the supplied diff from KeDei, however I have uploaded my updated diff to make it easier for you. There’s instructions on patching too, but long story short it’s “cat | patch -p1” in the base directory of the clone. The version I used was branch rpi-4.1.y, commit 785cea66a709eddb9858799192a7b7da566b44b0.

You should now have two framebuffer devices, /dev/fb0 and /dev/fb1. I’m not quite sure how the fbtft library interferes with the patch, as it seems to be activated too, but it works so no problem. (Actually I first activated module fb_ili9341, so you can try that too, if it contributed to my success). You can change to console to fb1 by command “con2fbmap 1 1” and back with “con2fbmap 1 0“, or on boot by editing /boot/cmdline.txt: add “fbcon=map:1” to the line somewhere. You can also change the font with “fbcon=font:ProFont6x11“. More things like this here.

kedei 3.5 inch spi tft lcd version 6.3 made in china

When surfing for information on 3.5 ” TFT touchscreens for the Raspberry Pi,to improve the TinyLCD experience, I stumbled upon AliExpress where several shops offer a 3.5″ LCD TFT Touch Screen Display for incredible low prices.

Update June 2016: There is now a download/information page at http://osoyoo.com/driver/rpiscreen.php. Images for more versions (mine i 2.0, latest is 6.2)  are available there. Alternative ishttp://kedei.net/raspberry/raspberry.html with Kali Ubuntu drivers too for version 3.0 and up.

The archive contains an image of Raspbian with the LCD driver installed. The image is quite current, and fit for B, B+ or 2 B. When I bought the screen an older image, build in augustus 2015,  was downloadable, the kernel is quite fresh built, early October 2015.

The image supplied is wheezy,  3.18.9-v7 #27 SMP PREEMPT Sun Oct 4 23:57:41 CST 2015 armv7l. So quite a recent system! Also the Model 1 B and B+ kernel is present, also just current wheezy.

The system uses SPI to copy the screen contents to the LCD screen, and some GPIO’s for the touchscreen. Other GPIOs are free, and the connector construction  leaves these pins indeed accessible!

kedei 3.5 inch spi tft lcd version 6.3 made in china

Is there a chance of getting it working with an Arduino Uno R3 or Mega2560? The graphics libraries that use SPI that I"ve found keep mentioning the RST and DC lines, which aren"t present on this board.

I haven"t had the opportunity to try it on a Raspberry Pi yet. From pinouts of raspi (googled images) they only have one long strip of GPIO/etc connectors, do they not? Even if plugging this board onto the 40-pin connector, where the two 5V pins match up, on the raspi the opposing two aren"t GND, they"re listed as "+3,3V" and "SDA". Something tells me that.. well, either I"m missing something, or this display needs some form of connector between itself and the raspi it"s meant to run off originally. (Oddly enough, they came with raspi-with-TFT-on-top plastic enclosures, which wouldn"t leave any space for rewiring pins.)

I doubt it. It would be a lot cleaner with regular SPI for both. You just change mode each time. e.g. 9-bit mode #3 for TFT. 8-bit mode #0 for the XPT.

Ah-ha. The HC595 is a shift register. They might use them to produce 16-bit parallel to drive the TFT. If they do, it will be a nightmare. Even worse than 9-bit SPI.

Well, it"ll be interesting to see if I get this to work eventually. A quick guess would be that with L_CS pulled low, the LCD chip gets to talk with the MISO/MOSI lines. After initializing it, I suppose the next step will be to (read datasheet..) and see if the MISO/MOSI-lines are used to clock out display data with L_CS high so the LCD chip doesn"t listen to that garbage, or if it is meant to be fed through the LCD chip aswell.

16-bit modules are cheaper than SPI display modules. So it is quite possible that he has crippled the display with shift registers instead of buying a proper SPI module.

Oh, this makes it easier - googling for the tarball I needed (lcd_show_v6 for my board since it"s got "v6.1" printed on it) got me to OsoYooTFT/README.md at master · jgamblin/OsoYooTFT · GitHub and http://en.kedei.net/raspberry/raspberry.html

Hrmm.. I don"t think source is included. In the lcd_show_xx blobs are just kernels and modules, with a couple of very small scripts to copy the LED or HDMI kernel to the /boot place of the filesystem. (And no error checking, if you try copying the LED kernel, it backups the original kernel, but if you then run the copy-LED-kernel command again, it happily overwrites your original kernel, leaving you with two LED-enabled kernels and no original. hrrf..)

Well, I downloaded the whole 35MB .GZ file. Unpacked it and found 3402 .ko files. I presume that these are kernel object files. Nothing that looked remotely like source files for your TFT display.

Since the ILI9481 can be driven directly by SPI, this seems a crazy way to do things. Especially since a HC595 might be clockable at 100MHz but you need to wiggle all 24-bits. And an AVR can only manage 8MHz on a good day.

Not when you consider that once you have loaded an 18 bit colour all you need to do is toggle the T_CS pin at say 10MHz and you can load the same pixels sequentially at 10Mpixels/s (=180Mbps) i.e. clear the screen faster than it is refreshed. With SPI you have to keep serially sending the same pixel N bits of colour over and over again, which is very inefficient. In the worst case (where sequential pixels are different colours) the shift register still wins if you can clock it faster than an SPI link maximum rate (easy on higher performance computers) because the same number of bits need to be clocked whatever interface is used.

This suggests more control bit are shifted in than is actually needed, but my hunch of an 18 bit + control parallel interface to the TFT seems to be correct.

While easy to identify the tarball to get for just my board (v6.1), indeed, it"s a bit unsettling that every board rev 2,3,4,5,6,6.1 has its own tarball available. Disseminating one version board may not help with the others then.

Yes, I expect that bodmer or myself could probably get you working if we made some inspired guessing with the schematic. You could always email Kedei and ask him for the genuine schematic. Make sure that you tell him the Revision number(s) on the pcb.

I had success with downloading Kedei"s 4GB images specific for the 6.1 board and putting on an SD card. Now the raspi boots up, and I see the boot messages scroll by. The original article said "expect about 6fps from the display" and that seems right - it"s jerky, but works.

kedei 3.5 inch spi tft lcd version 6.3 made in china

I picked up a few of these KeDei screens from AliExpress when they were on sale for about $10 each: https://www.aliexpress.com/item/High-en ... 20356.html

In both cases I"ve been able to get the screens working, up until Emulation Station starts to run. At that point, emulationstation only outputs to HDMI, and the RetroPie logo on the TFT fades to black. If I kill emulationstation, focus switches back to the TFT.

kedei 3.5 inch spi tft lcd version 6.3 made in china

The 3.5 inch LCD Display is directly pluggable into a Raspberry Pi and perfectly fits various Pi models from B+ to Raspberry Pi 3B+. It is a brilliant alternative for an HDMI monitor. When set up, it behaves as a human-machine interface enabling the user to prototype with the Raspberry Pi device anywhere at any time.

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:

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.

-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.

-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.

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 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.

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.

To get tearing free updates, you should use a DPI display, or a good quality HDMI display. Beware that cheap small 3.5" HDMI displays such as KeDei do also tear - that is, even if they are controlled via HDMI, they don"t actually seem to implement VSYNC timed internal operation.

Having no vsync is not all bad though, since with the lack of vsync, SPI displays have the opportunity to obtain smoother animation on content that is not updating at 60Hz. It is possible that content on the SPI display will stutter even less than what DPI or HDMI displays on the Pi can currently provide (although I have not been able to test this in detail, except for the KeDei case above).

If USE_GPU_VSYNC is disabled, then a busy spinning GPU frame snapshotting thread is used to drive the updates. This will produce smoother animation in content that does not maintain a fixed 60Hz rate. Especially in OpenTyrian, a game that renders at a fixed 36fps and has slowly scrolling scenery, the stuttering caused by USE_GPU_VSYNC is particularly visible. Running on Pi 3B without USE_GPU_VSYNC enabled produces visually smoother looking scrolling on an Adafruit 2.8" ILI9341 PiTFT set to update at 119Hz, compared to enabling USE_GPU_VSYNC on the same setup. Without USE_GPU_VSYNC, the dedicated frame polling loop thread "finds" the 36Hz update rate of the game, and then pushes pixels to the display at this exact rate. This works nicely since SPI displays disregard vsync - the result is that frames are pushed out to the SPI display immediately as they become available, instead of pulling them at a fixed 60Hz rate like HDMI does.

By default fbcp-ili9341 builds with a statistics overlay enabled. See the video fbcp-ili9341 ported to ILI9486 WaveShare 3.5" (B) SpotPear 320x480 SPI display to find details on what each field means. Build with CMake option -DSTATISTICS=0 to disable displaying the statistics. You can also try building with CMake option -DSTATISTICS=2 to show a more detailed frame delivery timings histogram view, see screenshot and video above.

Enable the option #define DISPLAY_ROTATE_180_DEGREES in config.h. This should rotate the SPI display to show up the other way around, while keeping the HDMI connected display orientation unchanged. Another option is to utilize a /boot/config.txt option display_rotate=2, which rotates both the SPI output and the HDMI output.

If fbcp-ili9341 does not support your display controller, you will have to write support for it. fbcp-ili9341 does not have a "generic SPI TFT driver routine" that might work across multiple devices, but needs specific code for each. If you have the spec sheet available, you can ask for advice, but please do not request to add support to a display controller "blind", that is not possible.

Perhaps. This is a more recent experimental feature that may not be as stable, and there are some limitations, but 3-wire ("9-bit") SPI display support is now available. If you have a 3-wire SPI display, i.e. one that does not have a Data/Control (DC) GPIO pin to connect, configure it via CMake with directive -DGPIO_TFT_DATA_CONTROL=-1 to tell fbcp-ili9341 that it should be driving the display with 3-wire protocol.

Yes, fbcp-ili9341 shows the output of the HDMI display on the SPI screen, and both can be attached at the same time. A HDMI display does not have to be connected however, although fbcp-ili9341 operation will still be affected by whatever HDMI display mode is configured. Check out tvservice -s on the command line to check what the current DispmanX HDMI output mode is.

At the moment fbcp-ili9341 has been developed to only display the contents of the main DispmanX GPU framebuffer over to the SPI display. That is, the SPI display will show the same picture as the HDMI output does. There is no technical restriction that requires this though, so if you know C/C++ well, it should be a manageable project to turn fbcp-ili9341 to operate as an offscreen display library to show a completely separate (non-GPU-accelerated) image than what the main HDMI display outputs. For example you could have two different outputs, e.g. a HUD overlay, a dashboard for network statistics, weather, temps, etc. showing on the SPI while having the main Raspberry Pi desktop on the HDMI.

kedei 3.5 inch spi tft lcd version 6.3 made in china

This git project constitutes a Raspberry Pi Clock & Weather display (rpi_clock), based on https://github.com/goodtft/LCD-show and the Quimat 3.5" TFT Touch Screen with a 320x480 resolution and it uses the Open Weather Map API (https://openweathermap.org/api).

In addition to the TFT environment, I have run this project with Xubuntu on Raspberry Pi 3 model B with a standard display connected with HDMI cable. See the configuration file for controlling whether or not rpi_clock uses the full screen or a windowed display.

Admittedly, there seems to be other 3.5" TFT display products which claim to NOT require special drivers as of the latest Raspbian during 2017 (more desirable IMO). In fact, the Quimat TFT might work this way too. I just got caught in the middle! Some time in the future, I might try it without the Quimat-supplied driver software. If that effort is successful, I will update this project.

This is a 2.8inch TFT LCD with resistive touch panel, has 320x240 resolution. It can support any revision of Raspberry Pi. Driver is provided for Raspbian/Ubuntu Mate/kali.

This is a 3.2inch TFT LCD with resistive touch panel, has 320x240 resolution. Can support any revision of Raspberry Pi. Driver is provided for Raspbian/Ubuntu Mate/kali.

This is a 3.2inch TFT LCD with resistive touch panel, has 320x240 hardware resolution.Support up to 125MHz high-speed SPI signal transmission provide you a clear and stable display effect.. Can directly plug to any revision of Raspberry Pi. Driver is provided for Raspbian/Ubuntu Mate/kali and Retropie(Can only display when working with Retropie).

This is a 3.5inch TFT LCD with resistive touch panel, has 480x320 resolution. Can support any revision of Raspberry Pi. Driver is provided for Raspbian/Ubuntu Mate/kali.

This is a 3.5inch TFT LCD with resistive touch panel, has 480x320 resolution. Can support any revision of Raspberry Pi. Driver is provided for Raspbian/Ubuntu Mate/kali. And this is an IPS screen which has wider viewing angle.

This is a 3.5inch TFT LCD with resistive touch panel, has 480x320 resolution. Support up to 125MHz high-speed SPI signal transmission provide you a clear and stable display effect.. Can directly plug to any revision of Raspberry Pi. Driver is provided for Raspbian/Ubuntu Mate/kali and Retropie(Can only display when working with Retropie).

This is a 3.5inch IPS screen with resistive touch panel, has 480x320 hardware resolution, use HDMI interface for displaying and GPIO for touching. Touch driver is provide for Raspbian, Ubuntu Mate,Kali and Retropie(Can only display when working with Retropie).

This is a 4inch TFT LCD with resistive touch panel, has 480x320 resolution. Support up to 125MHz high-speed SPI signal transmission provide you a clear and stable display effect. Can directly plug to any revision of Raspberry Pi. Driver is provided for Raspbian/Ubuntu Mate/kali and Retropie(Can only display when working with Retropie).

This is a 4.3inch IPS screens, 800x480 resolution, HDMI display. Designed for Raspberry Pi. Driver is required for touching. Note that this LCD can only support Raspberry Pi

This is a 5inch Resistive Touch Screen LCD, 800x480 resolution, HDMI interface. Designed for Raspberry Pi. Note that this LCD can only support Raspberry Pi.

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)

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.

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.

-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.

-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.