kedei 3.5 inch spi tft lcd version 6.3 supplier
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),
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.
I can confirm that the 3.5 inch LCD touch screen from kedei works with raspbian stretch. I have to use the latest driver at http://en.kedei.net/raspberry/v6_1/LCD_show_v6_1_3.tar.gz
I have a KeDei 3.5 ich SPI TFT LCD Display. I attached to Raspberry Pi with Android Things Image. When I boot the RPi, nothing is shown, only displays a black screen. The display is getting powered up, and I can differentiate between it"s on and off state. But when I try remote display (followed steps from this post), I can see the display properly.
I tried latest Raspbian Image and dev preview 0.4.1 as mentioned here. Tried with HDMI config given in the same link. Nothing works except the rpi_35_v6.3_ubuntu_mate_15_kedei image from KeDei vendor.
3) pls try to install the image with raspbian and 3.5 driver and try it again: https://osoyoo.com/2016/05/26/osoyoo-lcd-touch-screen-for-raspberry-pi-installation-guide/
Hey Nikeron, is the used module really an ILI9325? Maybe we could then traceback the display connection and reverse-engineer it. From that point on when the schematics are released for everyone to build those displays themselfes, we could hack it then and create a free driver?
I downloaded RetroPie from https://retropie.org.uk/docs/First-Installation/ and have been trying to get my 3.5″ LCD to work. I downloaded the driver from http://kedei.net/raspberry/raspberry.html as described, but whenever I try and extract it with the “tar xzvf LCD_show_v6_1_3.tar.gz” around 50 lines are executed and then the Pi crashes. When I restart it, it goes into a kernel panic every time. I’ve reinstalled my OS multiple times. I cannot download the raspbian distro with the driver because I have been unable to install RetroPie on top of it and have been unable to display it on the LCD.
Do you mean you don’t want to install the LCD driver but just install OS? If so, this LCD can’t work, but you can search a 3.5 HDMI LCD in our store and it works with just OS for display function.
Hi, I got version 6.3 of the screen. I tried installing it on the latest Raspbian with latest drivers from kedei.net. But when the Raspberry starts booting, the screen only works for a few seconds before being frozen. ( Raspberry works, only screen is frozen ).
I had this happen initially. To resolve it I DISABLED SPI under raspi-config and then also set the bootup settings to be Desktop. I have a weird keyboard and the CTRL-ALT Fn keys didn’t work right, but normally CTRL-ALT-F1 or F7 change you from terminal to desktop virtual sessions in Linux.
Hi Smat, Please install the version 4.9 raspbian firstly, and then install the suitable version driver according to the isntruction. Please don’t update raspbian directly, as the driver can’t update for this
Hola buenas tengo un problema es que compre esta pantalla Raspberry PI 3 Modelo B 3.5 “pulgadas TFT Lcd con Pantalla Táctil de la interfaz SPI. 480*320 píxeles con lápiz táctil para PI 2
4).I copied the file >>>LCD_show_v6_1_3.tar.gz<<>/home/pi<>> RASPBIAN STRETCH WITH DESKTOP<<>tar xzvf LCD*.tar.gz<>cd LCD_show_v6_1_3<> ./LCD35_v <>R-pi display to HDMI<> cd LCD_show_v6_1_3 <> ./LCD_hdmi <>./LCD_dhmi<>HDMI to R-pi display<>R-pi display to HDMI<>HDMI to R-pi display<>>!! #I feel like I want to return my display now#.
https://www.aliexpress.com/item/Raspberry-PI-3-Model-B-3-5-inch-TFT-LCD-Display-with-Touch-Screen-by-SPI/32804087006.html?shortkey=iABj6neU&addresstype=600
4).I copied the file >>>LCD_show_v6_1_3.tar.gz<<>/home/pi<>> RASPBIAN STRETCH WITH DESKTOP<<>tar xzvf LCD*.tar.gz<>cd LCD_show_v6_1_3<> ./LCD35_v <>R-pi display to HDMI<> cd LCD_show_v6_1_3 <> ./LCD_hdmi <>./LCD_dhmi<>HDMI to R-pi display<>R-pi display to HDMI<>HDMI to R-pi display<>>!! #I feel like I want to return my display now#.
https://www.aliexpress.com/item/Raspberry-PI-3-Model-B-3-5-inch-TFT-LCD-Display-with-Touch-Screen-by-SPI/32804087006.html?shortkey=iABj6neU&addresstype=600
“ATTENTION” in the instructions they wrote >>./LCD_dhmi<>HDMI to R-pi display<<: it is just to reinstall the driver again, I need to execute the point 5) through the point 7) again.
https://www.aliexpress.com/item/Raspberry-PI-3-Model-B-3-5-inch-TFT-LCD-Display-with-Touch-Screen-by-SPI/32804087006.html?shortkey=iABj6neU&addresstype=600
https://www.aliexpress.com/item/Raspberry-PI-3-Model-B-3-5-inch-TFT-LCD-Display-with-Touch-Screen-by-SPI/32804087006.html?shortkey=iABj6neU&addresstype=600
Hello, I have been able to install the driver and play/switch between LCD & HDMI, now is there any way to turn off the white screed or turn off LCD when Im not using it? Thanks
The LCD doesn’t do anything else. Initially I had the Memory split set to 16MB – but this through up a memory error on the LCD. Setting it higher removes this error – but still nothing else.
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!
The old patch isn’t particularly confidence inspiring. It is also implemented as a platform driver. It patches the bcm2708/bcm2709 file mostly to add ili9341 as platform hardware so the driver will start. It should have been entirely unnecessary to touch that file.
The old patch isn’t particularly confidence inspiring. It is also implemented as a platform driver. It patches the bcm2708/bcm2709 file mostly to add ili9341 as platform hardware so the driver will start. It should have been entirely unnecessary to touch that file.
Ive gone through the steps 4 different times already and i cant seem to get my display to work, ive ran the tft setup utility a few different times and i start getting more errors and the display still shows nothing
When you say you installed the normal osoyoo image and it works fine do you mean one of the images osoyoo offers for download? And if so which one? I can’t seem to get the osoyoo images to work at all. I tried the Kali, Ubuntu and raspbian versions.
mine says version 1.1 and that doesnt seem to be listed anywhere. so far ive been able to get the kernel to work, just not after doing the setup. after some research ive decided my next attempt will be installing the sticky fingers kernel,then choosing either wave35 or wave35h during tft setup. Im not sure but i think the wave35c isnt for screens with the hdmi attachement. if wave and wave35h dont work i will probably just start going down the list of available drivers and trying each one with a fresh install. I’ll let you know if i have any luck
I also have a 5inch screen with hdmi and that can you fix bij the config.txt file i must look for the toutch screen because thats not working at the moment.
yea thats the difference i think. My screen is a version 1.1 but the date is only like six months old. i havent been able to find info for the 1.1 but apparently most of the kedei screen are version 6.x. mine is 3.5 inch and apparently very similiar to the 6.x models
@kogel013 have you tried configuring a realtek or other wireless driver on the manufacture OS? seems that the version of kali from osoyoo is too old for me to get the right dependencies so i can run make, or else i get a series of errors im assuming because of dist-upgrade, with the upgrade the screen stops working ! ive been at it 4 days today im taking a break and tomorrow im back at it !
Ok, it’s Works! If somebody want to install osoyoo 3.5 (Non HDMI) TFT display: Download The LCD_show_v_6_1_3.tar.gz driver, copy to the /root/ and extract it in terminal with command tar -xvzf LCD_show_v6_1_3.tar.gz
Than in terminal type kalipi-tft-config select in the menu 5. Kali-Pi Config, Than 03. Boot Options, select B1. Desktop/CLI and select B3 or B4 Desktop…
Than select 05. Interfacing Options and P3 SPI Disable if is it enabled… Than select 09 Update and go Finish… In terminal find The driver what you extracted:
Ok, it’s Works! If somebody want to install osoyoo 3.5 (Non HDMI) TFT display: Download The LCD_show_v_6_1_3.tar.gz driver, copy to the /root/ and extract it in terminal with command tar -xvzf LCD_show_v6_1_3.tar.gz
Than in terminal type kalipi-tft-config select in the menu 5. Kali-Pi Config, Than 03. Boot Options, select B1. Desktop/CLI and select B3 or B4 Desktop…
Than select 05. Interfacing Options and P3 SPI Disable if is it enabled… Than select 09 Update and go Finish… In terminal find The driver what you extracted:
Thanks! No, whan I chose the Osoyoo 3.5 in kalipi-tft-config Didn’t work… After reboot, white screen on the TFT and HDMI display was black… I think this Osoyoo 3.5 setup in `kalipi-tft-config’ is for the Osoyoo 3.5 480×320 HDMI Version…
I didn’t try The Kuman… May next time… I have already installed the full-kali… The Kali-PI launcher is Very good too, I can easily switch between The TFT and HDMI…:)
Hi again! I tried it with Kuman, does not working… The boot starts on HDMI, but it stops “without [failed] line”, and nothing happen… I tried it with unpluged HDMI cable too, but the TFT nothing shows… My 32GB SD card with installed Full-Kali is still Works perfectly on the TFT and on HDMI too…
This LCD Touchscreen HAT fits snuggly on top of the Raspberry Pi, practically form fitting on top of it so as not to compromise the overall dimensions of the credit card sized single board computer. The resistive touchscreen provides you with an easy way to display information coming off of the Raspberry Pi and the OS currently running on it.
The 4:3 aspect ratio backlit LCD equipped on this HAT possesses a resolution of 480 by 320 pixels with over 65 thousand colors and an SPI interface with a 16MHz driver speed. Simply plug the 13x2 GPIO header into your desired Raspberry Pi and you"ll be able to start using your new resistive touch screen!
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.
-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.
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).
-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.
-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.
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 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.
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=
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.
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)
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.
The codebase captures screen framebuffers by snapshotting via the VideoCore vc_dispmanx_snapshot() API, and the obtained pixels are then routed on to the SPI-based display. This kind of polling is performed, since there does not exist an event-based mechanism to get new frames from the GPU as they are produced. The result is inefficient and can easily cause stuttering, since different applications produce frames at different paces. Ideally the code would ask the VideoCore API to receive finished frames in callback notifications immediately after they are rendered, but this kind of functionality does not exist in the current GPU driver stack. In the absence of such event delivery mechanism, the code has to resort to polling snapshots of the display framebuffer using carefully timed heuristics to balance between keeping latency and stuttering low, while not causing excessive power consumption. These heuristics keep continuously guessing the update rate of the animation on screen, and they have been tuned to ensure that CPU usage goes down to 0% when there is no detected activity on screen, but it is certainly not perfect. This GPU limitation is discussed at raspberrypi/userland#440. If you"d like to see fbcp-ili9341 operation reduce latency, stuttering and power consumption, please throw a (kind!) comment or a thumbs up emoji in that bug thread to share that you care about this, and perhaps Raspberry Pi engineers might pick the improvement up on the development roadmap. If this issue is resolved, all of the #define USE_GPU_VSYNC, #define SAVE_BATTERY_BY_PREDICTING_FRAME_ARRIVAL_TIMES and #define SELF_SYNCHRONIZE_TO_GPU_VSYNC_PRODUCED_NEW_FRAMES hacks from the previous section could be deleted from the driver, hopefully leading to a best of all worlds scenario without drawbacks.
The speed of the SPI bus is linked to the BCM2835 core frequency. This frequency is at 250MHz by default (on e.g. Pi Zero, 3B and 3B+), and under CPU load, the core turbos up to 400MHz. This turboing directly scales up the SPI bus speed by 400/250=+60% as well. Therefore when choosing the SPI CDIV value to use, one has to pick one that works for both idle and turbo clock speeds. Conversely, the BCM core reverts to non-turbo speed when there is only light CPU load active, and this slows down the display, so if an application is graphically intensive but light on CPU, the SPI display bus does not get a chance to run at maximum speeds. A way to work around this is to force the BCM core to always stay in its turbo state with force_turbo=1 option in /boot/config.txt, but this has an unfortunate effect of causing the ARM CPU to always run in turbo speed as well, consuming excessive amounts of power. At the time of writing, there does not yet exist a good solution to have both power saving and good performance. This limitation is being discussed in more detail at raspberrypi/firmware#992.
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.
The fbcp part in the name means framebuffer copy; specifically for the ILI9341 controller. fbcp-ili9341 is not actually a framebuffer copying driver, it does not create a secondary framebuffer that it would copy bytes across to from the primary framebuffer. It is also no longer a driver only for the ILI9341 controller. A more appropriate name might be userland-raspi-spi-display-driver or something like that, but the original name stuck.
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 the display controller is one of the currently tested ones (see the list above), and it is wired up to run using 4-line SPI, then it should work. Pay attention to configure the Data/Control GPIO pin number correctly, and also specify the Reset GPIO pin number if the device has one.
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.
This has only been tested on my Adafruit SSD1351 128x96 RGB OLED display, which can be soldered to operate in 3-wire SPI mode, so testing has not been particularly extensive.
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.
make sure the display is configured to run 4-wire SPI mode, and not in parallel mode or 3-wire SPI mode. You may need to solder or desolder some connections or set a jumper to configure the specific driving mode. Support for 3-wire SPI displays does exist, but it is more limited and a bit experimental.
This suggests that the power line or the backlight line might not be properly connected. Or if the backlight connects to a GPIO pin on the Pi (and not a voltage pin), then it may be that the pin is not in correct state for the backlight to turn on. Most of the LCD TFT displays I have immediately light up their backlight when they receive power. The Tontec one has a backlight GPIO pin that boots up high but must be pulled low to activate the backlight. OLED displays on the other hand seem to stay all black even after they do get power, while waiting for their initialization to be performed, so for OLEDs it may be normal for nothing to show up on the screen immediately after boot.
If the backlight connects to a GPIO pin, you may need to define -DGPIO_TFT_BACKLIGHT=
fbcp-ili9341 runs a clear screen command at low speed as first thing after init, so if that goes through, it is a good sign. Try increasing -DSPI_BUS_CLOCK_DIVISOR= CMake option to a higher number to see if the display driving rate was too fast. Or try disabling DMA with -DUSE_DMA_TRANSFERS=OFF to see if this might be a DMA conflict.
This suggests same as above, increase SPI bus divisor or troubleshoot disabling DMA. If DMA is detected to be the culprit, try changing up the DMA channels. Double check that /boot/config.txt does not have any dtoverlays regarding other SPI display drivers or touch screen controllers, and that it does NOT have a dtparam=spi=on line in it - fbcp-ili9341 does not use the Linux kernel SPI driver.
Double check the Data/Command (D/C) GPIO pin physically, and in CMake command line. Whenever fbcp-ili9341 refers to pin numbers, they are always specified in BCM pin numbers. Try setting a higher -DSPI_BUS_CLOCK_DIVISOR= value to CMake. Make sure no other fbcp programs or SPI drivers or dtoverlays are enabled.
If the colors looks off in some other fashion, it is possible that the display is just being driven at a too high SPI bus speed, in which case try making the display run slower by choosing a higher -DSPI_BUS_CLOCK_DIVISOR= option to CMake. Especially on ILI9486 displays it has been observed that the colors on the display can become distorted if the display is run too fast beyond its maximum capability.
As the number of supported displays, Raspberry Pi device models, Raspbian/Retropie/Lakka OS versions, accompanied C++ compiler versions and fbcp-ili9341 build options have grown in number, there is a combinatorial explosion of all possible build modes that one can put the codebase through, so it is not easy to keep every possible combo tested all the time. Something may have regressed or gotten outdated. Stay calm, and report a bug.
First, make sure the display is a 4-wire SPI and not a 3-wire one. A display is 4-wire SPI if it has a Data/Control (DC) GPIO line that needs connecting. Sometimes the D/C pin is labeled RS (Register Select). Support for 3-wire SPI displays does exist, but it is experimental and not nearly as well tested as 4-wire displays.
In this list, Rated SPI Bus Speed is the maximum clock speed that the display controller is rated to run at. The Obtained Bus Speed column lists the fastest SPI bus speed that was achieved in practice, and the core_freq BCM Core speed and SPI Clock Divider CDIV setting that was used to achieve that rate. Note how most display controllers can generally be driven much faster than what they are officially rated at in their spec sheets.
All the ILI9341 displays work nice and super fast at ~70-80MHz. My WaveShare 3.5" 320x480 ILI9486 display runs really slow compared to its pixel resolution, ~32MHz only. See fbcp-ili9341 ported to ILI9486 WaveShare 3.5" (B) SpotPear 320x480 SPI display for a video of this display in action. Adafruit"s 320x480 3.5" HX8357D PiTFTs is ~64% faster in comparison.
The ILI9486L controller based maithoga display runs a bit faster than ILI9486 WaveShare, 50MHz versus 31.88MHz, i.e. +56.8% bandwidth increase. However fps-wise maithoga reaches only 13.56 vs WaveShare 12.97 fps, because the bandwidth advantage is fully lost in pixel format differences: ILI9486L requires transmitting 24 bits per each pixel (R6G6B6 mode), whereas ILI9486 supports 16 bits per pixel R5G6B5 mode. This is reflected in the above chart refresh rate for the maithoga display (marked with a star).
The KeDei v6.3 display with MPI3501 controller takes the crown of being horrible, in all aspects imaginable. It is able to run at 33.33 MHz, but due to technical design limitations of the display (see #40), effective bus speed is halved, and only about 72% utilization of the remaining bus rate is achieved. DMA cannot be used, so CPU usage will be off the charts. Even though fbcp-ili9341 supports this display, level of support is expected to be poor, because the hardware design is a closed secret without open documentation publicly available from the manufacturer. Stay clear of KeDei or MPI3501 displays.
The Tontec MZ61581 controller based 320x480 3.5" display on the other hand can be driven insanely fast at up to 140MHz! These seem to be quite hard to come by though and they are expensive. Tontec seems to have gone out of business and for example the domain itontec.com from which the supplied instructions sheet asks to download original drivers from is no longer registered. I was able to find one from eBay for testing.
Search around, or ask the manufacturer of the display what the maximum SPI bus speed is for the device. This is the most important aspect to getting good frame rates, but unfortunately most web links never state the SPI speed rating, or they state it ridiculously low like in the spec sheets. Try and buy to see, or ask in some community forums from people who already have a particular display to find out what SPI bus speed it can achieve.
One might think that since Pi Zero is slower than a Pi 3, the SPI bus speed might not matter as much when running on a Pi Zero, but the effect is rather the opposite. To get good framerates on a Pi Zero, it should be paired with a display with as high SPI bus speed capability as possible. This is because the higher the SPI bus speed is, the more autonomously a DMA controller can drive it without CPU intervention. For the same reason, the interlacing technique does not (currently at least) perform well on a Pi Zero, so it is disabled there by default. ILI9341s run well on Pi Zero, ILI9486 on the other hand is quite difficult to combine with a Pi Zero.
Ultimately, it should be noted that parallel displays (DPI) are the proper method for getting fast framerates easily. SPI displays should only be preferred if display form factor is important and a desired product might only exist as SPI and not as DPI, or the number of GPIO pins that are available on the Pi is scarce that sacrificing dozens of pins to RGB data is not feasible.
Tomáš Suk, Cyril Höschl IV, and Jan Flusser, Rectangular Decomposition of Binary Images., a useful research paper about merging monochrome bitmap images to rectangles, which gave good ideas for optimizing SPI span merges across multiple scan lines,
If you would like to help push Raspberry Pi SPI display support further, there are always more things to do in the project. Here is a list of ideas and TODOs for recognized work items to contribute, roughly rated in order of increasing difficulty.
Vote up issue raspberrypi/userland/#440 if you would like to see Raspberry Pi Foundation improve CPU performance and reduce latency of the Pi when used with SPI displays.
Vote up issue raspberrypi/firmware/#992 if you would like to see Raspberry Pi SPI bus to have high throughput even when the Pi CPU is not under heavy CPU load (better SPI throughput with lower power consumption), a performance feature only SDHOST on the Pi currently enjoys.
If you have access to a high frequency scope/logic analyzer (~128MHz), audit the utilization of the SPI MOSI bus to find any remaining idle times on the bus, and analyze their sources.
Improve support for 3-wire displays, e.g. for 1) "17-bit" 3-wire communication, 2) fix up SPI_3WIRE_PROTOCOL + ALL_TASKS_SHOULD_DMA to work together, or 3) fix up SPI_3WIRE_PROTOCOL + OFFLOAD_PIXEL_COPY_TO_DMA_CPP to work together.
Port the high performance DMA-based SPI communication technique from fbcp-ili9341 over to another project that uses the SPI bus for something else, for close to 100% saturation of the SPI bus in the project.
If you are knowledgeable with BCM2835 DMA, investigate whether the hacky dance where two DMA channels need to be used to reset and resume DMA SPI transfers when chaining, can be avoided?
If you have contacts with Broadcom, ask them to promote use of the SoC hardware with DMA chaining + mixed SPI & non-SPI tasks as a first class tested use case. Current DMA SPI hardware behavior of BCM2835 is, to say the least, surprising.