Expand description
§epdsi — E-Paper Display Serial Interface Framework
A no_std, embedded-hal 1.0 compatible driver framework for Electronic Paper
Displays (EPDs), covering seven driver ICs and ten panels behind one API.
Most EPD crates bind one driver IC to one panel. epdsi separates the two, so adding
a panel to an existing controller is a single new file, and adding a controller does
not disturb the panels already supported.
§Architecture
Four pieces compose into a driver:
EpdPanel— a zero-sized type holding static physical facts about one panel:WIDTH,HEIGHT,COLOR_MODE, plus optionalvcom,custom_lutandgate_voltageoverrides. Seepanels.EpdController— the driver IC’s command and register logic: init sequence, window and cursor addressing, frame writes, refresh, sleep. Seecontrollers.SpiBusWrapper— the physical transport, wrapping anembedded-halSpiDeviceplus DC, RST and BUSY pins. Seebus. Panels needing OTP register reads over a bit-banged 3-wire link useSpi3Businstead (seebus3).EpdDriver— the orchestrator, built withEpdBuilder, exposing the public API:init,set_window,write_frame,clear_frame,refresh,sleep.
Colour is unified across all panels by ColorMode and ColorChannel, so
multi-buffer COGs (Pervasive’s separate black/white and red RAM, for instance) are
always addressed explicitly rather than implicitly. Panels using the 4 bpp ACeP /
Spectra palette pack two pixels per byte through SevenColor::pack.
§Supported controllers and panels
| Controller | Panels | Resolution | Colour mode |
|---|---|---|---|
Ssd1681Controller | GDEM0154Z90 | 200 × 200 | Tri-Color |
Ssd1680Controller | GDEM0213B74 | 122 × 250 | Monochrome |
Jd79661Controller | ZJY122250_0213AJH_E5 / GDEY0213F51 | 122 × 250 | Quad-Color |
Uc8253Controller | GDEY037T03 | 240 × 416 | Monochrome |
Ssd1677Controller | GDEQ0426T82 | 800 × 480 | Monochrome |
Ed2208Controller | GDEP073E01 | 800 × 480 | Spectra 6 (4 bpp) |
PervasiveBwController | E2266KS0C1, E2290KS0F1 | 152 × 296, 168 × 384 | Monochrome |
PervasiveBwryController | E2154QS0F1, E2417QS0A3 | 152 × 152, 400 × 300 | Quad-Color (Spectra-4) |
Ssd1680Controller and Ssd1681Controller are thin wrappers over the shared
Ssd168xController. Many panels also carry vendor-parity aliases, such as
EPD_266_KS_0C for E2266KS0C1 or GxEPD2_370_GDEY037T03 for GDEY037T03.
§Quick start
use epdsi::prelude::*;
use embedded_graphics::{
prelude::*, primitives::{Rectangle, PrimitiveStyle},
pixelcolor::BinaryColor, geometry::{Point, Size},
};
// Wrap the SPI device and its control pins.
let epd_bus = SpiBusWrapper::new(spi_device, dc_pin, rst_pin, busy_pin);
let controller = Ssd1681Controller::new(GDEM0154Z90::WIDTH, GDEM0154Z90::HEIGHT);
// Bind controller and panel into a driver.
let mut epd = EpdBuilder::<_, GDEM0154Z90>::new(controller).build(epd_bus);
epd.init(&mut delay).unwrap();
// Both RAM channels must be primed on a tri-colour panel.
epd.clear_frame(ColorChannel::BlackWhite, 0xFF).unwrap();
epd.clear_frame(ColorChannel::RedYellow, 0x00).unwrap();
// Draw through embedded-graphics into a PageBuffer.
let mut bw_buf = [0xFFu8; 200 * 200 / 8];
let mut display = PageBuffer::new(&mut bw_buf, 200, 200, 0);
Rectangle::new(Point::new(10, 10), Size::new(50, 50))
.into_styled(PrimitiveStyle::with_fill(BinaryColor::On))
.draw(&mut display)
.unwrap();
epd.write_frame(ColorChannel::BlackWhite, display.as_slice()).unwrap();
epd.refresh(&mut delay).unwrap();prelude re-exports everything above and is the intended single import.
§Low-RAM paged rendering
A full 800 × 480 monochrome frame is 48 KB — more than many targets have. Rather than
buffering a whole frame, render_paged sweeps the panel one
horizontal band at a time, handing a small stack-allocated PageBuffer to a closure
for each band, writing it, and refreshing once at the end. This is the GxEPD2 paged
pattern; RAM use is set by the page height you choose, not by panel size.
§Colour panels refresh slowly, and that is physics
Tri-Color and Quad-Color panels have no fast differential waveform. The coloured
pigment is a heavier particle needing the full OTP waveform to migrate, so every
update takes seconds — roughly 14 s on GDEM0154Z90. Partial refresh modes select a
controller LUT that only exists for monochrome panels; on a colour panel it produces
wrong output rather than a fast update. Partial window updates still work, at full
refresh speed.
§Cargo features
graphics(default) — implementsembedded-graphics-core’sDrawTargetandDimensionsforPageBuffer. Disable to drop the dependency; the buffer and paged rendering still work, you just fill pixels yourself.defmt— derivesdefmt::Formaton the public error and mode enums for logging on embedded targets.
§Hardware note
On EXT3-1 extension boards, the J3 jumper must be OPEN (10 µH path) for panels 3.7“ and smaller. Closed (47 µH) the DC-DC booster sags during current bursts, which shows up as BUSY-pin hangs that look like driver bugs but are not.
§Complete examples
Runnable, flashable programs for every supported controller live in
rust-rpico2-discovery (RP2350 Pico 2, rp-hal) and
rust-reterminal-e1002-examples (XIAO ESP32-S3, Embassy + esp-hal).
The minimum supported Rust version is 1.75.
Re-exports§
pub use bus::SpiBusWrapper;pub use bus3::Spi3Bus;pub use driver::EpdBuilder;pub use driver::EpdDriver;pub use traits::ColorChannel;pub use traits::ColorMode;pub use traits::EpdController;pub use traits::EpdPanel;pub use traits::SevenColor;
Modules§
- bus
- SPI communication bus wrapper compatible with
embedded-hal1.0. - bus3
- Bit-banged “3-wire” half-duplex SPI bus for the Pervasive Displays BWRY COG family’s OTP register read handshake.
- controllers
- Controller IC module for various EPD display drivers.
- driver
- Display driver orchestrator and builder implementation.
- graphics
- Graphics and paged rendering framework module.
- panels
- Hardware panel specifications module.
- prelude
- Prelude re-exporting common traits, drivers, controllers, and helpers.
- traits
- Core trait definitions for E-Paper Display Serial Interface (
epdsi).