adafruit 1.44 color tft lcd display raspberry pi free sample

{"id":6570888986742,"title":"Adafruit 1.44\" Color TFT LCD Display with MicroSD Card breakout - ST7735R","handle":"adafruit-1-44-color-tft-lcd-display-with-microsd-card-breakout-st7735r","description":"\u003cp\u003eThis lovely little display breakout is the best way to add a small, colorful and bright display to any project. Since the display uses 4-wire SPI to communicate and has its own pixel-addressable frame buffer, it can be used with every kind of microcontroller. Even a very small one with low memory and few pins available!\u003c\/p\u003e\u003cp\u003eThe 1.44\" display has 128x128 color pixels. Unlike the low cost \"Nokia 6110\" and similar LCD displays, which are CSTN type and thus have poor color and slow refresh, this display is a true TFT! The TFT driver (ST7735R) can display full 16-bit color using our library code.\u003c\/p\u003e\u003cp\u003eThe breakout has the TFT display soldered on (it uses a delicate flex-circuit connector) as well as a ultra-low-dropout 3.3V regulator and a 3\/5V level shifter so you can use it with 3.3V or 5V power and logic. We also had a little space so we placed a microSD card holder so you can easily load full color bitmaps from a FAT16\/FAT32 formatted microSD card. The microSD card is not included, \u003ca href=\"http:\/\/www.adafruit.com\/products\/102\" target=\"_blank\"\u003ebut you can pick one up here\u003c\/a\u003e.\u003c\/p\u003e\u003cp\u003eOf course, we wouldn"t just leave you with a datasheet and a \"good luck!\" - \u003ca href=\"https:\/\/learn.adafruit.com\/adafruit-1-44-color-tft-with-micro-sd-socket\" target=\"_blank\"\u003ewe"ve written a full open source graphics library that can draw pixels, lines, rectangles, circles, text and bitmaps as well as example code and a wiring tutorial\u003c\/a\u003e. The code is written for Arduino but can be easily ported to your favorite microcontroller!\u003c\/p\u003e","published_at":"2021-06-08T17:00:30-04:00","created_at":"2021-06-08T16:59:37-04:00","vendor":"Adafruit","type":"Adafruit","tags":[],"price":1490,"price_min":1490,"price_max":1490,"available":true,"price_varies":false,"compare_at_price":1495,"compare_at_price_min":1495,"compare_at_price_max":1495,"compare_at_price_varies":false,"variants":[{"id":39340495372406,"title":"Default Title","option1":"Default Title","option2":null,"option3":null,"sku":"K710","requires_shipping":true,"taxable":true,"featured_image":null,"available":true,"name":"Adafruit 1.44\" Color TFT LCD Display with MicroSD Card breakout - ST7735R","public_title":null,"options":["Default Title"],"price":1490,"weight":0,"compare_at_price":1495,"inventory_quantity":4,"inventory_management":"shopify","inventory_policy":"deny","barcode":"","requires_selling_plan":false,"selling_plan_allocations":[]}],"images":["\/\/cdn.shopify.com\/s\/files\/1\/1749\/9663\/products\/2088-00.jpg?v=1623185977","\/\/cdn.shopify.com\/s\/files\/1\/1749\/9663\/products\/2088-10.jpg?v=1623186055","\/\/cdn.shopify.com\/s\/files\/1\/1749\/9663\/products\/2088-07.jpg?v=1623186062","\/\/cdn.shopify.com\/s\/files\/1\/1749\/9663\/products\/2088-01.jpg?v=1623186070"],"featured_image":"\/\/cdn.shopify.com\/s\/files\/1\/1749\/9663\/products\/2088-00.jpg?v=1623185977","options":["Title"],"media":[{"alt":null,"id":20499319521398,"position":1,"preview_image":{"aspect_ratio":1.332,"height":728,"width":970,"src":"https:\/\/cdn.shopify.com\/s\/files\/1\/1749\/9663\/products\/2088-00.jpg?v=1623185977"},"aspect_ratio":1.332,"height":728,"media_type":"image","src":"https:\/\/cdn.shopify.com\/s\/files\/1\/1749\/9663\/products\/2088-00.jpg?v=1623185977","width":970},{"alt":null,"id":20499321520246,"position":2,"preview_image":{"aspect_ratio":1.332,"height":728,"width":970,"src":"https:\/\/cdn.shopify.com\/s\/files\/1\/1749\/9663\/products\/2088-10.jpg?v=1623186055"},"aspect_ratio":1.332,"height":728,"media_type":"image","src":"https:\/\/cdn.shopify.com\/s\/files\/1\/1749\/9663\/products\/2088-10.jpg?v=1623186055","width":970},{"alt":null,"id":20499321651318,"position":3,"preview_image":{"aspect_ratio":1.332,"height":728,"width":970,"src":"https:\/\/cdn.shopify.com\/s\/files\/1\/1749\/9663\/products\/2088-07.jpg?v=1623186062"},"aspect_ratio":1.332,"height":728,"media_type":"image","src":"https:\/\/cdn.shopify.com\/s\/files\/1\/1749\/9663\/products\/2088-07.jpg?v=1623186062","width":970},{"alt":null,"id":20499321782390,"position":4,"preview_image":{"aspect_ratio":1.332,"height":728,"width":970,"src":"https:\/\/cdn.shopify.com\/s\/files\/1\/1749\/9663\/products\/2088-01.jpg?v=1623186070"},"aspect_ratio":1.332,"height":728,"media_type":"image","src":"https:\/\/cdn.shopify.com\/s\/files\/1\/1749\/9663\/products\/2088-01.jpg?v=1623186070","width":970}],"requires_selling_plan":false,"selling_plan_groups":[],"content":"\u003cp\u003eThis lovely little display breakout is the best way to add a small, colorful and bright display to any project. Since the display uses 4-wire SPI to communicate and has its own pixel-addressable frame buffer, it can be used with every kind of microcontroller. Even a very small one with low memory and few pins available!\u003c\/p\u003e\u003cp\u003eThe 1.44\" display has 128x128 color pixels. Unlike the low cost \"Nokia 6110\" and similar LCD displays, which are CSTN type and thus have poor color and slow refresh, this display is a true TFT! The TFT driver (ST7735R) can display full 16-bit color using our library code.\u003c\/p\u003e\u003cp\u003eThe breakout has the TFT display soldered on (it uses a delicate flex-circuit connector) as well as a ultra-low-dropout 3.3V regulator and a 3\/5V level shifter so you can use it with 3.3V or 5V power and logic. We also had a little space so we placed a microSD card holder so you can easily load full color bitmaps from a FAT16\/FAT32 formatted microSD card. The microSD card is not included, \u003ca href=\"http:\/\/www.adafruit.com\/products\/102\" target=\"_blank\"\u003ebut you can pick one up here\u003c\/a\u003e.\u003c\/p\u003e\u003cp\u003eOf course, we wouldn"t just leave you with a datasheet and a \"good luck!\" - \u003ca href=\"https:\/\/learn.adafruit.com\/adafruit-1-44-color-tft-with-micro-sd-socket\" target=\"_blank\"\u003ewe"ve written a full open source graphics library that can draw pixels, lines, rectangles, circles, text and bitmaps as well as example code and a wiring tutorial\u003c\/a\u003e. The code is written for Arduino but can be easily ported to your favorite microcontroller!\u003c\/p\u003e"}

This lovely little display breakout is the best way to add a small, colorful and bright display to any project. Since the display uses 4-wire SPI to communicate and has its own pixel-addressable frame buffer, it can be used with every kind of microcontroller. Even a very small one with low memory and few pins available!

The 1.44" display has 128x128 color pixels. Unlike the low cost "Nokia 6110" and similar LCD displays, which are CSTN type and thus have poor color and slow refresh, this display is a true TFT! The TFT driver (ST7735R) can display full 16-bit color using our library code.

The breakout has the TFT display soldered on (it uses a delicate flex-circuit connector) as well as a ultra-low-dropout 3.3V regulator and a 3/5V level shifter so you can use it with 3.3V or 5V power and logic. We also had a little space so we placed a microSD card holder so you can easily load full color bitmaps from a FAT16/FAT32 formatted microSD card. The microSD card is not included, but you can pick one up here.

Of course, we wouldn"t just leave you with a datasheet and a "good luck!" - we"ve written a full open source graphics library that can draw pixels, lines, rectangles, circles, text and bitmaps as well as example code and a wiring tutorial. The code is written for Arduino but can be easily ported to your favorite microcontroller!

adafruit 1.44 color tft lcd display raspberry pi free sample

This lovely little display breakout is the best way to add a small, colorful and bright display to any project. Since the display uses 4-wire SPI to communicate and has its own pixel-addressable frame buffer, it can be used with every kind of microcontroller. Even a very small one with low memory and few pins available!

The 1.44" display has 128x128 color pixels. Unlike the low cost "Nokia 6110" and similar LCD displays, which are CSTN type and thus have poor color and slow refresh, this display is a true TFT! The TFT driver (ST7735R) can display full 16-bit color using our library code.

The breakout has the TFT display soldered on (it uses a delicate flex-circuit connector) as well as a ultra-low-dropout 3.3V regulator and a 3/5V level shifter so you can use it with 3.3V or 5V power and logic. We also had a little space so we placed a microSD card holder so you can easily load full color bitmaps from a FAT16/FAT32 formatted microSD card. The microSD card is not included, but you can pick one up here.

adafruit 1.44 color tft lcd display raspberry pi free sample

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 following is now deprecated due to the number of issues it can cause in certain circumstances. For ESP32 ONLY, 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 RP2040, STM32, ESP8266 and ESP32 types, other processors may be used but will use the slower generic Arduino interface calls. 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 (8 and 16 bit parallel) is only supported with the RP2040.

For other processors only SPI interface displays are supported and the slower Arduino SPI library functions are used by the library. Higher clock speed processors such as used for the Teensy 3.x and 4.x boards will still provide a very good performance with the generic Arduino SPI functions.

"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 (125MHz with overclocked RP2040, 55MHz with STM32 and 40MHz with ESP8266). The MHS-3.5 inch RPi ILI9486 based display is also supported, however the MHS ILI9341 based display of the same type does NOT work with this library.

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.

Drawing graphics into a sprite is very fast, for those familiar with the Adafruit "graphicstest" example, this whole test completes in 18ms in a 160x128 sprite. Examples of sprite use can be found in the "examples/Sprite" folder.

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.

adafruit 1.44 color tft lcd display raspberry pi free sample

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=: Specifies a GPIO pin that can be polled to get the battery state. By default, when this is set, a low battery icon will be displayed if the pin is pulled low (see config.h for ways in which this can be tweaked).

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= and -DDMA_RX_CHANNEL= CMake options.

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 . Setting this to a smaller value, such as 30, will trade refresh rate to reduce CPU consumption.

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 tearing modes to see in slow motion videos how these two tearing modes look like.

Another option that is known to affect how the tearing artifact looks like is the internal panel refresh rate. For ILI9341 displays this refresh rate can be adjusted in ili9341.h, and this can be set to range between ILI9341_FRAMERATE_61_HZ and ILI9341_FRAMERATE_119_HZ (default). Slower refresh rates produce less tearing, but have higher input-to-display latency, whereas higher refresh rates will result in the opposite. Again visually the resulting effect is a bit subjective.

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

The main option that affects smoothness of display updates is the #define USE_GPU_VSYNC line in config.h. If this is enabled, then the internal Pi GPU HDMI vsync clock is used to drive frames onto the display. The Pi GPU clock runs at a fixed rate that is independent of the content. This rate can be discovered by running tvservice -s on the Pi console, and is usually 59Hz or 60Hz. If your application renders at this rate, animation will look smooth, but if not, there will be stuttering. For example playing a PAL NES game that updates at 50Hz with HDMI clock set at 60Hz will cause bad microstuttering in video output if #define USE_GPU_VSYNC is enabled.

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.

A drawback is that this kind of polling consumes more CPU time than the vsync option. The extra overhead is around +34% of CPU usage compared to the vsync method. It also requires using a background thread, and because of this, it is not feasible to be used on a single core Pi Zero. If this polling was unnecessary, this mode would also work on a Pi Zero, and without the added +34% CPU overhead on Pi 3B. See the Known Issues section below for more details.

There are two other main options that affect frame delivery timings, #define SELF_SYNCHRONIZE_TO_GPU_VSYNC_PRODUCED_NEW_FRAMES and #define SAVE_BATTERY_BY_PREDICTING_FRAME_ARRIVAL_TIMES. Check out the video fbcp-ili9341 frame delivery smoothness test on Pi 3B and Adafruit ILI9341 at 119Hz for a detailed side by side comparison of these different modes. The conclusions drawn from the four tested scenarios in the video are:

This mode uses the GPU vsync signal, but also aims to find and synchronize to the edge trigger when content is producing frames. This is the default build mode on Pi Zero.

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.

Currently if one resizes the video frame size at runtime, this causes DispmanX API to go sideways. See raspberrypi/userland#461 for more information. Best workaround is to set the desired screen resolution in /boot/config.txt and configure all applications to never change that at runtime.

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.

Yes, it does, although not quite as well as on Pi 3B. If you"d like it to run better on a Pi Zero, leave a thumbs up at raspberrypi/userland#440 - hard problems are difficult to justify prioritizing unless it is known that many people care about them.

Edit the file config.h and comment out the line #define DISPLAY_OUTPUT_LANDSCAPE. This will make the display output in portrait mode, effectively rotating it by 90 degrees. Note that this only affects the pixel memory reading mode of the display. It is not possible to change the panel scan order to run between landscape and portrait, the SPI displays typically always scan in portrait mode. The result is that it will change the panel vsync tearing mode from "straight line tearing" over to "diagonal tearing" (see the section About Tearing above).

If you do not want to have diagonal tearing, but would prefer straight line tearing, then additionally enable the option #define DISPLAY_FLIP_ORIENTATION_IN_SOFTWARE in config.h. That will restore straight line tearing, but it will also increase overall CPU consumption.

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.

Note that the setting DISPLAY_ROTATE_180_DEGREES only affects the pixel memory reading mode of the display. It is not possible to flip the panel scan to run inverted by 180 degrees. This means that adjusting these settings will also have effects of changing the visual appearance of the vsync tearing artifact. If you have the ability to mount the display 180 degrees around in your project, it is recommended to do that instead of using the DISPLAY_ROTATE_180_DEGREES option.

Edit the file config.h in a text editor (a command line one such as pico, vim, nano, or SSH map the drive to your host), and find the appropriate line in the file. Add comment lines // in front of that text to disable the option, or remove the // characters to enable it.

I don"t know, I don"t currently have any to test. Perhaps the code does need some model specific configuration, or perhaps it might work out of the box. I only have Pi 3B, Pi 3B+, Pi Zero W and a Pi 3 Compute Module based systems to experiment on. Pi 2 B has been reported to work by users (#17).

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 the display controller is not one of the tested ones, it may still work if it is similar to one of the existing ones. For example, ILI9340 and ILI9341 are practically the same controller. You can just try with a specific one to see how it goes.

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.

The performance option ALL_TASKS_SHOULD_DMA is currently not supported, there is an issue with DMA chaining that prevents this from being enabled. As result, CPU usage on 3-wire displays will be slightly higher than on 4-wire displays.

The performance option OFFLOAD_PIXEL_COPY_TO_DMA_CPP is currently not supported. As a result, 3-wire displays may not work that well on single core Pis like Pi Zero.

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.

Displays that have a 16-bit wide command word, such as ILI9486, do not currently work in 3-wire ("17-bit") mode. (But ILI9486L has 8-bit command word, so that does work)

I have done close to everything possible to my displays - cut power in middle of operation, sent random data and command bytes, set their operating voltage commands and clock timings to arbitrary high and low values, tested unspecified and reserved command fields, and driven the displays dozens of MHz faster than they managed to keep up with, and I have not yet done permanent damage to any of my displays or Pis.

Easiest way to do permanent damage is to fail at wiring, e.g. drive 5 volts if your display requires 3.3v, or short a connection, or something similar.

The one thing that fbcp-ili9341 stays clear off is that it does not program the non-volatile memory areas of any of the displays. Therefore a hard power off on a display should clear all performed initialization and reset the display to its initial state at next power on.

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.

double check that the display controller is really what you expected. Trying to drive with the display with wrong initialization code usually results in the display not reacting, and the screen stays white,

shut down and physically power off the Pi and the display in between multiple tests. Driving a display with a wrong initialization routine may put it in a bad state that needs a physical power off for it to reset,

if there is a reset pin on the display, make sure to pass it in CMake line. Or alternatively, try driving fbcp-ili9341 without specifying the reset pin,

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= in CMake command line or config.h, and edit config.h to enable #define BACKLIGHT_CONTROL.

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.

Check that the Pi is powered off of a power supply that can keep up with the voltage, and the low voltage icon is not showing up. (remove any avoid_warnings=1/2 directive from /boot/config.txt if that was used to get rid of warnings overlay, to check that voltage is good) It has been observed that if there is not enough power supplied, the display can be the first to starve, while the Pi might keep on running fine. Try removing turbo settings or lowering the clock speed if you have overclocked to verify that the display crash is not power usage related.

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 color channels are mixed (red is blue, blue is red, green is green) like shown on the left image, pass the CMake option -DDISPLAY_SWAP_BGR=ON to the build.

If the color intensities look wrong (white is black, black is white, color looks like a negative image) like seen in the middle image, pass the CMake option -DDISPLAY_INVERT_COLORS=ON to the build.

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.

fbcp-ili9341 needs a few megabytes of GPU memory to function if DMA transfers are enabled. The gpu_mem boot config option dictates how much of the Pi"s memory area is allocated to the GPU. By default this is 64MB, which has been observed to not leave enough memory for fbcp-ili9341 if HDMI is run at 1080p. If this error happens, try increasing GPU memory to e.g. 128MB by adding a line gpu_mem=128 in /boot/config.txt.

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.

You can also try looking through the commit history to find changes related to your configuration combo, to see if there"s a mention of a known good commit in time that should work for your case. If you get an odd compiler error on cmake or make lines, those will usually be very easy to fix, as they are most of the time a result of some configurational oversight.

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/Co