Expand description
Framebuffer implementation for HUB75 LED matrix displays.
§How HUB75 LED Displays Work
HUB75 RGB LED matrix panels are scanned, time-multiplexed displays that behave like a long daisy-chained shift register rather than a random-access framebuffer.
§Signal names
- R1 G1 B1 / R2 G2 B2 – Serial colour data for the upper and lower halves of the active scan line
- CLK – Shift-register clock; every rising edge pushes the six colour bits one pixel to the right
- LAT / STB – Latch; copies the shift-register contents to the LED drivers for the row currently selected by the address lines
- OE – Output-Enable (active LOW): LEDs are lit while OE is LOW and blanked when it is HIGH
- A B C D (E) – Row-address select lines (choose which pair of rows is lit)
- VCC & GND – 5 V power for panel logic and LED drivers
§Row-pair scanning workflow (e.g., 1/16-scan panel)
- While the panel is still displaying row pair N − 1, the controller shifts the six-bit colour data for row pair N into the chain (OE remains LOW so row N − 1 stays visible).
- After the last pixel is clocked in, the controller raises OE HIGH to blank the LEDs.
- With the panel blanked, it first changes the address lines to select row pair N, lets them settle for a few nanoseconds, and then pulses LAT to latch the freshly shifted data into the output drivers for that newly selected row.
- OE is immediately driven LOW again, lighting row pair N.
- Steps 1–4 repeat for every row pair fast enough (hundreds of Hz) that the human eye sees a steady image.
- If the first row pair is being shifted, the panel continues showing the last row pair of the previous frame until the first blank-address-latch sequence occurs.
§Brightness and colour depth (Binary Code Modulation)
- Full colour is typically achieved using Binary Code Modulation (BCM), also known as Bit-Angle Modulation (BAM). Each bit-plane is displayed for a period proportional to its binary weight (1, 2, 4, 8 …), yielding 2ⁿ intensity levels per channel. See Batsocks – LED dimming using Binary Code Modulation for a deeper explanation.
- Because each LED is on for only a fraction of the total frame time, the driver can use relatively high peak currents without overheating while average brightness is preserved.
§Implications for software / hardware drivers
- You don’t simply “write a pixel” once; you must continuously stream the complete refresh data at MHz-range clock rates.
- Precise timing of CLK, OE, address lines, and LAT is critical—especially the order: blank (OE HIGH) → set address → latch → un-blank (OE LOW).
- Microcontrollers typically employ DMA, PIO, or parallel GPIO tricks, and FPGAs use dedicated logic, to sustain the data throughput while leaving processing resources free.
In short: a HUB75 panel is a high-speed shift-register chain that relies on rapid row-pair scanning and Binary Code Modulation (BCM) to create a bright, full-colour image. Keeping OE LOW almost all the time—blanking only long enough to change the address and pulse LAT—maximises brightness without visible artefacts.
§Framebuffer Implementations
This module provides two different framebuffer implementations optimized for HUB75 LED matrix displays:
-
Plain Implementation (
plain
module)- No additional hardware requirements
- Simpler implementation suitable for basic displays
-
Latched Implementation (
latched
module)- Requires external latch hardware for address lines
Both implementations:
- Have configurable row and column dimensions
- Support different color depths through Binary Code Modulation (BCM)
- Implement the
ReadBuffer
trait for DMA compatibility
§Available Feature Flags
§skip-black-pixels
Feature (disabled by default)
When enabled, calls to set_pixel()
with Color::BLACK
return early without
writing to the framebuffer. This provides a significant performance boost for
UI applications that frequently draw black pixels (backgrounds, clearing, etc.)
by assuming the framebuffer was already cleared.
Important: This optimization assumes that black pixels represent “no change” rather than “explicitly set to black”. By default, black pixels are written normally to ensure correct overwrite behavior. To enable the optimization:
[dependencies]
hub75-framebuffer = { version = "0.2.0", features = ["skip-black-pixels"] }
§esp-hal-dma
Feature (required when using esp-hal
)
Required when using the esp-hal
crate for ESP32 development. This feature
switches the ReadBuffer
trait implementation from embedded-dma
to esp-hal::dma
.
If you’re targeting ESP32 devices with esp-hal
, you must enable this feature
for DMA compatibility.
[dependencies]
hub75-framebuffer = { version = "0.2.0", features = ["esp-hal-dma"] }
esp-hal = "0.20"
§esp32-ordering
Feature (required for original ESP32 only)
Required when targeting the original ESP32 chip (not ESP32-S3 or other variants). This feature adjusts byte ordering to accommodate the quirky requirements of the ESP32’s I²S peripheral in 8-bit and 16-bit modes. The original ESP32 has different byte ordering requirements compared to other ESP32 variants (S2, S3, C3, etc.), which do not need this feature.
[dependencies]
hub75-framebuffer = { version = "0.2.0", features = ["esp32-ordering"] }
§defmt
Feature
Implements defmt::Format
for framebuffer types so they can be emitted with
the defmt
logging framework. No functional changes; purely adds a trait impl.
§doc-images
Feature
Embeds documentation images when building docs on docs.rs. Not needed for normal usage.
Modules§
- latched
- DMA-friendly framebuffer implementation for HUB75 LED panels with external latch circuit support.
- plain
- DMA-friendly framebuffer implementation for HUB75 LED panels.
Enums§
- Word
Size - Word size configuration for the framebuffer
Traits§
- Frame
Buffer - Trait for read-only framebuffers
- Mutable
Frame Buffer - Trait for mutable framebuffers
Functions§
- compute_
frame_ count - Computes the number of frames needed for a given bit depth
- compute_
rows - Computes the NROWS value from ROWS for
DmaFrameBuffer
Type Aliases§
- Color
- Color type used in the framebuffer