FastLED 3.9.15
Loading...
Searching...
No Matches
fl::SPITransposer Class Reference

Detailed Description

Unified stateless bit-interleaving transposer for multi-lane SPI parallel LED transmission.

This provides a unified functional approach to bit-interleaving for multi-lane SPI transmission. All state is managed by the caller - the transposer only performs the conversion.

Supported Widths

How Bit-Interleaving Works

Traditional SPI sends one byte at a time on a single data line (MOSI). Multi-lane SPI uses N data lines (D0-DN) to send N bits in parallel per clock cycle.

The transposer converts per-lane data into interleaved format:

Example: 2-way SPI

Input (2 separate lanes):
Lane 0: [0xAB, ...] → Strip 1 (D0 pin)
Lane 1: [0x12, ...] → Strip 2 (D1 pin)
Output (interleaved): Each input byte becomes 2 output bytes
Input: Lane0=0xAB (10101011), Lane1=0x12 (00010010)
Out[0] = 0x2A (bits 7:4 from each lane, 4 bits per lane)
Out[1] = 0x2B (bits 3:0 from each lane, 4 bits per lane)
uint8_t byte
Definition midi_Defs.h:36
@ Output
Digital output (push-pull)
Definition pin.h:43
@ Input
Digital input (high impedance)
Definition pin.h:42

Synchronized Latching with Black LED Padding

LED strips often have different lengths. To ensure all strips latch simultaneously (updating LEDs at the same time), shorter strips are padded with black LED frames at the BEGINNING of the data stream.

Common padding patterns:

  • APA102/SK9822: {0xE0, 0x00, 0x00, 0x00} (brightness=0, RGB=0)
  • LPD8806: {0x80, 0x80, 0x80} (7-bit GRB with MSB=1, all colors 0)
  • WS2801: {0x00, 0x00, 0x00} (RGB all zero)
  • P9813: {0xFF, 0x00, 0x00, 0x00} (flag byte + BGR all zero)

These invisible black LEDs are prepended so all strips finish transmitting simultaneously, providing synchronized visual updates across all parallel strips.

Usage Example

using namespace fl;
// Prepare lane data
vector<uint8_t> lane0_data = {0xAB, 0xCD, ...};
vector<uint8_t> lane1_data = {0x12, 0x34, ...};
// Setup lanes (optional for unused lanes)
optional<SPITransposer::LaneData> lane0 = SPITransposer::LaneData{lane0_data, apa102_padding};
optional<SPITransposer::LaneData> lane1 = SPITransposer::LaneData{lane1_data, apa102_padding};
// Allocate output buffer (caller manages memory)
size_t max_size = fl::max(lane0_data.size(), lane1_data.size());
vector<uint8_t> output(max_size * 2); // 2× for 2-way, 4× for 4-way, 8× for 8-way
// Perform transpose
const char* error = nullptr;
bool success = SPITransposer::transpose2(lane0, lane1, output, &error);
if (!success) {
FL_WARN("Transpose failed: " << error);
}
static fl::span< const fl::u8 > getPaddingLEDFrame()
Get padding LED frame for synchronized latching in quad-SPI Returns a black LED frame to prepend to s...
Definition apa102.h:239
static bool transpose2(const fl::optional< LaneData > &lane0, const fl::optional< LaneData > &lane1, fl::span< u8 > output, const char **error=nullptr) FL_NOEXCEPT
Transpose 2 lanes of data into interleaved dual-SPI format.
Lane data structure: payload + padding frame.
fl::size size() const FL_NOEXCEPT
#define FL_WARN(X)
Definition log.h:276
constexpr common_type_t< T, U > max(T a, U b) FL_NOEXCEPT
Definition math.h:75
Optional< T > optional
Definition optional.h:16
Base definition for an LED controller.
Definition crgb.hpp:179

Performance

  • CPU overhead: Minimal - just the transpose operation (runs once per frame)
  • Transpose time: ~25-100µs depending on lane count and data size
  • Transmission time: Hardware DMA, zero CPU usage during transfer
  • Optimization: Direct bit extraction provides optimal performance

Definition at line 583 of file transposition.h.

#include <transposition.h>

Classes

struct  LaneData
 Lane data structure: payload + padding frame. More...
 

Static Public Member Functions

static bool transpose16 (const fl::optional< LaneData > lanes[16], fl::span< u8 > output, const char **error=nullptr) FL_NOEXCEPT
 Transpose 16 lanes of data into interleaved hex-SPI format.
 
static bool transpose2 (const fl::optional< LaneData > &lane0, const fl::optional< LaneData > &lane1, fl::span< u8 > output, const char **error=nullptr) FL_NOEXCEPT
 Transpose 2 lanes of data into interleaved dual-SPI format.
 
static bool transpose4 (const fl::optional< LaneData > &lane0, const fl::optional< LaneData > &lane1, const fl::optional< LaneData > &lane2, const fl::optional< LaneData > &lane3, fl::span< u8 > output, const char **error=nullptr) FL_NOEXCEPT
 Transpose 4 lanes of data into interleaved quad-SPI format.
 
static bool transpose8 (const fl::optional< LaneData > lanes[8], fl::span< u8 > output, const char **error=nullptr) FL_NOEXCEPT
 Transpose 8 lanes of data into interleaved octal-SPI format.
 

Static Private Member Functions

static u8 getLaneByte (const LaneData &lane, size_t byte_idx, size_t max_size) FL_NOEXCEPT
 Get byte from lane at given index, handling padding automatically.
 

The documentation for this class was generated from the following files: