Skip to content

hal::display

The contract between a display panel driver and the interface that moves its bytes.

A MIPI-style display (ILI9342C, ILI9341, ST7789, …) is driven as a stream of command bytes and pixel data over some transport — SPI with a data/command line, an 8/16-bit parallel bus, whatever. A panel driver knows the command set and the pixel format; it does not know, and should not care, whether the bytes leave over polled SPI, DMA, or a parallel bus. [DisplayInterface] is that seam: the panel driver (Layer 3, portable) calls it, and a concrete implementation (built by the board from its SPI + GPIO + DMA) makes the bytes move as fast as the hardware allows.

The single biggest determinant of display throughput is not the clock — it is how many SPI transactions a screen update costs. A naive driver toggles chip-select around every command and every pixel run; a fast one asserts CS once, streams a whole windowed fill, and deasserts. So the trait is built around an explicit transaction (start / end) with the command, data and pixel calls in between running under one held CS — the same shape TFT_eSPI’s startWrite/endWrite and LovyanGFX’s bus lock use, for the same reason.

Pixels are 16-bit RGB565. The interface owns the on-the-wire byte order (MIPI displays take the high byte first), so a panel driver hands it native u16 values and never byte-swaps itself — which lets the interface fold the swap into the same copy that fills its DMA buffer, at no extra cost.

enum DisplayError {
Interface,
OutOfBounds,
SizeMismatch,
}

Why a display operation failed.

Implements: Clone, Copy, Debug, Eq, PartialEq, StructuralPartialEq

trait DisplayInterface {
fn start(&mut self) -> Result<(), DisplayError>
fn end(&mut self) -> Result<(), DisplayError>
fn command(&mut self, cmd: u8) -> Result<(), DisplayError>
fn data(&mut self, bytes: &[u8]) -> Result<(), DisplayError>
fn fill(&mut self, color: u16, count: usize) -> Result<(), DisplayError>
fn pixels(&mut self, pixels: &[u16]) -> Result<(), DisplayError>
}

The transport a panel driver streams command and pixel bytes through.

Every method between a start and an end runs with chip-select held, so a windowed fill or blit is one SPI transaction. Implementations own chip-select, the data/command line, byte order, and any DMA — see the module docs.