Source:
Hub75Slots.h
Hub75Slots¶
HUB75 encode: the contract between the driver and a HUB75 port, named for the wire unit it builds.
One pixel clock is one SLOT. Sibling of [ParallelSlots.h], which does the same job for WS2812. A pure data transform with no platform include, so unit_Hub75Slots.cpp pins it without an ESP32.
Classes¶
| Name | Description |
|---|---|
Hub75Layout |
Which bus bit each HUB75 line occupies. |
Hub75Geometry |
The geometry one encode needs. scanRate is the panel's own and is NOT derivable from the height. Two panels of identical dimensions can scan differently, which is why it is a control rather than a calculation. |
Functions¶
| Return | Name | Description |
|---|---|---|
size_t |
hub75Encode inline |
Encode one rendered [RGB] frame into a HUB75 bit-plane buffer. |
hub75Encode¶
inline
inline size_t hub75Encode(const uint8_t * rgb, uint8_t * out, const Hub75Geometry & geo, const Hub75Layout & lay = {})
Encode one rendered [RGB] frame into a HUB75 bit-plane buffer.
Hub75Layout¶
src/light/drivers/Hub75Slots.h:53Which bus bit each HUB75 line occupies.
The peripheral drives one 16-bit bus word per slot. Every line is a bit position rather than a GPIO here, and the platform layer maps bit to GPIO.
Defaults are the conventional order and cost nothing to override. A board that wires the panel differently changes these, and the encoder is unchanged.
Public Attributes¶
uint8_t r1 = 0
: Color bits for the upper half-panel.
uint8_t g1 = 1
uint8_t b1 = 2
uint8_t r2 = 3
: Color bits for the lower half-panel.
uint8_t g2 = 4
uint8_t b2 = 5
uint8_t a = 8
: Row address bits; a 1/8 panel uses only a, b and c.
uint8_t b = 9
uint8_t c = 10
uint8_t d = 11
uint8_t e = 12
uint8_t lat = 13
: Latch: moves the shift register to the output drivers.
uint8_t oe = 14
: Output enable, active LOW, so high is dark.
Hub75Geometry¶
src/light/drivers/Hub75Slots.h:67The geometry one encode needs. scanRate is the panel's own and is NOT derivable from the height. Two panels of identical dimensions can scan differently, which is why it is a control rather than a calculation.
Public Attributes¶
uint16_t width = 64
: Panel width in pixels.
uint16_t height = 64
: Panel height in pixels.
uint8_t scanRate = 16
: The panel's own scan rate: 8, 16 or 32, meaning 1/8, 1/16 or 1/32.
uint8_t bitDepth = 4
: Bit planes per frame, 2 to 4. Every plane costs a full scan pass.
Public Methods¶
inline uint16_t scanRows() const
: Address steps one plane walks.
inline uint16_t rowsPerScan() const
: Rows driven per address step.
inline bool valid() const
: Is this geometry encodable?
inline size_t frameSlots() const
: Slots one encoded frame occupies.
inline size_t frameBytes() const
: Bytes one encoded frame occupies.
Public Static Attributes¶
constexpr size_t kBytesPerSlot = 2
: Bytes on the wire per pixel clock: one 16-bit bus word.
More info¶
The wire layout¶
One encoded frame, outermost first:
for each bit plane p (0 = least significant) for each scan row r for each column x -> one bus word per column: the six color bits for (x, r) and (x, r + rows), lit, ADDRESSED TO THE PREVIOUS ROW one blanking word -> OE high (dark), latch high, addressed to row r: the row that data belongs to
The address lags the data by one row¶
A panel lights where three things meet: output-enable low, the row the address lines select, and the row held in the output LATCH. The latch holds the row last strobed, which is the previous one. So while row r's color bits clock in, the address must still name row r - 1, or the previous row's data lights on row r's LEDs. The blanking word is where the address moves to r: dark, and latching r at the same time. Row 0's data words therefore name the LAST scan row, which is what lets the frame loop through the DMA wrap with every row lit exactly once. Addressing the data words to their own row displaced the whole picture one scan row down and put the last row on the first. On a wall that reads as one bright line.
Address rides with the data¶
The row address and the control lines share the bus word that carries the color bits. The peripheral clocks one word per slot, and a panel wants address and data at once. Hub75Layout says which bus bit each line sits on, the one thing a board's wiring changes. How a panel scans, and why brightness is time, is on the driver's page under "HUB75, details".
Prior art¶
mrcodetastic/ESP32-HUB75-MatrixPanel-DMA, hzeller/rpi-rgb-led-matrix and ESPHome's hub75. The scan and bit-plane structure is the panel's, and the encoder is written from that behavior.