Skip to main content

SPI

SPI (Serial Peripheral Interface) is the communication protocol used by the e-ink display. It is fast, full-duplex, and synchronous.


The Four Wires

SignalDirectionPurpose
MOSIController → PeripheralMaster Out Slave In — data sent from ESP32 to device
MISOPeripheral → ControllerMaster In Slave Out — data returned from device to ESP32
SCLKController → PeripheralClock — the ESP32 drives this to synchronise both sides
CSController → PeripheralChip Select — pulled LOW to address a specific device

The software analogy: SPI is like a synchronous function call where both sides exchange data in the same transaction. The caller (ESP32) controls the clock, exactly like a function caller controls when execution proceeds.


Chip Select and the Shared Bus

Multiple devices can share the same MOSI, MISO, and SCLK wires. Each device gets its own CS (Chip Select) pin — the controller pulls a device's CS pin LOW to address it and HIGH to release it. Only one device should have its CS pulled LOW at a time.

In this project the display is the only SPI device, so the CS pin (GPIO10) is the only one on the bus. If you ever add a second SPI device in the future, you would give it its own CS pin and ensure only one is active at a time.


E-ink Display: Extra Signals

The GDEY042T81-FL02 uses SPI for data, but also requires three extra GPIO pins:

SignalGPIOFunction
DCGPIO5Data/Command — LOW to send a command byte, HIGH to send data
RSTGPIO4Reset — pulse LOW for ≥10 ms on init to reset the controller
BUSYGPIO3Active HIGH while the display is refreshing; poll until LOW before next command

The BUSY pin is effectively a semaphore. If you send a new command while BUSY is HIGH, the display controller ignores it or behaves unpredictably.

// Wait for display to finish refreshing
while (gpio_get_level(GPIO_NUM_3) == 1) {
vTaskDelay(pdMS_TO_TICKS(10));
}

SPI Modes

SPI has four clock polarity/phase modes (CPOL/CPHA: 0–3). The SSD1683 (e-ink controller) uses Mode 0 (CPOL=0, CPHA=0). You rarely need to think about this unless a device is not responding and you need to check the datasheet.


ESP-IDF SPI Setup

In ESP-IDF v5, the SPI host to use is SPI2_HOST. The bus is configured once at startup, and each device registers its own handle with its CS pin:

// 1. Configure the bus (shared wires)
spi_bus_config_t bus_cfg = {
.mosi_io_num = GPIO_NUM_11,
.miso_io_num = GPIO_NUM_13,
.sclk_io_num = GPIO_NUM_12,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
};
spi_bus_initialize(SPI2_HOST, &bus_cfg, SPI_DMA_CH_AUTO);

// 2. Add device (display) with its own CS pin
spi_device_interface_config_t display_cfg = {
.clock_speed_hz = 10 * 1000 * 1000, // 10 MHz
.mode = 0,
.spics_io_num = GPIO_NUM_10, // CS_DISPLAY
.queue_size = 7,
};
spi_device_handle_t display_handle;
spi_bus_add_device(SPI2_HOST, &display_cfg, &display_handle);

The display is the only device on SPI2_HOST in this project. No additional spi_bus_add_device calls are needed at startup.