TFT_eSPI is engineered from the ground up for speed, and Direct Memory Access (DMA) is its most powerful performance tool. DMA lets the processor hand off a block of pixel data to the SPI peripheral and immediately return to application code — the pixel transfer continues in the background without occupying the CPU. Combined with double-buffering, this enables the CPU to compose the next frame while the previous one is still being sent to the display, eliminating the CPU idle time that would otherwise be wasted waiting for SPI transfers to complete.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Marcussacapuces91/doc-TFT_eSPI/llms.txt
Use this file to discover all available pages before exploring further.
DMA Support Matrix
DMA availability depends on both the processor family and the interface type in use. Parallel interfaces on ESP32 do not support DMA through this library.| Processor | SPI DMA | 8-bit Parallel DMA | 16-bit Parallel DMA |
|---|---|---|---|
| RP2040 | ✅ Yes | ✅ Yes | ✅ Yes |
| ESP32 | ✅ Yes | ❌ No | ❌ N/A |
| ESP32-S3 | ✅ Yes | ❌ No | ❌ N/A |
| ESP32-C3 / S2 | ❌ No | ❌ N/A | ❌ N/A |
| STM32Fxxx | ✅ Yes | ❌ No | ❌ N/A |
| ESP8266 | ❌ No | ❌ N/A | ❌ N/A |
| Other / Generic | ❌ No | ❌ N/A | ❌ N/A |
Some ILI9xxx display controllers (ILI9481, ILI9486, ILI9488) do not support DMA even over SPI due to their 18-bit pixel format requirement.
DMA API
Initializing and Releasing DMA
initDMA() once in setup() before any DMA transfer. When ctrl_cs is true, the library manages the chip-select pin automatically during DMA transfers (recommended for most setups). Returns true on success.
deInitDMA() to release DMA resources (rarely needed in normal use).
Checking and Waiting for DMA Completion
dmaBusy() returns true while a DMA transfer is in progress. dmaWait() blocks until the current transfer completes. Always call dmaWait() (or check dmaBusy()) before modifying the buffer that was handed to a DMA transfer — the DMA controller is still reading from it until the transfer finishes.
DMA_Enabled public boolean reflects whether DMA has been successfully initialised:
Transferring Pixel Data via DMA
-
pushImageDMA(x, y, w, h, data, buffer)— transfers a rectangular pixel array to the display at position(x, y). The optionalbufferargument enables double-buffering: whiledatais transferred by DMA, your code can write the next frame intobuffer. On the next call, swapdataandbuffer. -
pushPixelsDMA(image, len)— streamslenraw 16-bit pixels to the current CGRAM window without repositioning the address window first. Use aftersetAddrWindow().
Double-Buffering Pattern
The key to maximum frame rates is overlapping CPU rendering with DMA transfer. Allocate two buffers of equal size and alternate between them each frame:SPI Transaction Wrappers
startWrite / endWrite
drawLine(), fillRect(), etc.) internally calls startWrite() and endWrite() to assert the chip-select and begin/end the SPI transaction. When you call multiple drawing functions in sequence, this repeated CS toggling adds measurable overhead.
Wrap a batch of drawing calls between a single startWrite() / endWrite() pair to assert CS once and hold the SPI bus for the entire sequence:
writeColor(color, len) writes len pixels of the same colour to the current CGRAM window directly, without any bounds checking overhead. It must be called between startWrite() and endWrite().
Bulk Pixel Transfer
Two additional low-level methods bypass the higher-level drawing machinery entirely:pushBlock(color, len)— fills the current CGRAM window withlenpixels of a single colour. Faster than callingwriteColorin a loop because it uses optimised SPI burst code.pushPixels(data, len)— streams arbitrary pixel data from a buffer. Byte swap behaviour is controlled bysetSwapBytes().
setAddrWindow() first) and must be called inside a startWrite() / endWrite() block.
SPI Frequency Configuration
SPI clock speed is the single biggest factor in raw throughput. SetSPI_FREQUENCY in User_Setup.h to the highest stable rate your wiring supports. The read frequency is set separately because most displays require a slower clock for reading back data:
- ESP32 — SPI clock is derived from the 80 MHz APB clock; 40 MHz is the highest setting, but electrical effects often limit the reliable rate to ~26–27 MHz.
- RP2040 — The PIO-based SPI can run higher; 62.5 MHz has been demonstrated on short PCB traces.
- STM32 — Depends on the specific variant and APB2 prescaler.
Library Attribute Control
setAttribute() and getAttribute() configure boolean library capabilities at runtime. Three IDs are defined:
| ID | Constant | Effect when true |
|---|---|---|
| 1 | CP437_SWITCH | Applies CP437 glyph correction for GLCD font |
| 2 | UTF8_SWITCH | Decodes multi-byte UTF-8 sequences in print() |
| 3 | PSRAM_ENABLE | Sprite createSprite() may allocate from PSRAM |
ESP32 Transfer Buffer Checking
On ESP32, the DMA-backed SPI peripheral uses a set of internal transfer buffers. ThespiBusyCheck member controls how many of those buffers are checked for completion before a new transfer begins. In practice this is managed automatically by dmaWait(), but it is exposed for advanced tuning via the SPI_BUSY_CHECK compile-time define in User_Setup.h.