RPBP — LED subsystem (subsys = 0x07)¶
Addressable LED strips driven by a PIO state machine on PIO2. Currently supports WS2812 / WS2812B / SK6812-RGB (3 bytes/pixel, GRB byte order) plus the WS2811 RGB variant. SK6812-RGBW is reserved on the wire (4 bytes/pixel) but the v1 firmware sends only the top 24 bits — the white channel byte is preserved in the framebuffer for forward-compat.
Access path: vendor RPBP. Linux exposes the universe via rpbridge.ko
once an upstream LED-multicolor R4L wrapper exists; until then the
driver attaches the wire client and userspace can talk to the
firmware over the vendor pipe via libusb.
Capabilities¶
buses.led[*] carries:
| key | type | meaning |
|---|---|---|
idx |
uint | universe index (always 0 in v1) |
data_pin |
uint | GPIO carrying the strip's data line |
max_pixels |
uint | compile-time framebuffer ceiling |
chipset |
text | "ws2812" (advisory) |
Feature flag advertised when the build includes LED support:
led.ws2812.
Opcodes¶
0x00 GET_INFO¶
Request: empty.
Response (8 bytes):
c(u8) — universe count (1 if available).p(u8) — GPIO carrying the data line.f(u8) — current pixel format (0GRB,1RGB,2GRBW).r(u8) — reserved, must be 0.pix(LE u16) — currently configured pixel count.max(LE u16) — compile-time ceiling (RPBRIDGE_LED_MAX_PIXELS).
0x01 CONFIGURE¶
Request (4 bytes): [idx u8][format u8][pixel_count LE u16].
idxMUST be0(single universe in v1; non-zero →ENOENT).format∈{0, 1, 2}. Other values →EINVAL.pixel_count∈[1, max_pixels]. Out of range →EINVAL.
The framebuffer is implicitly cleared and a latch pulse is emitted.
0x02 WRITE¶
Request: [idx u8][offset LE u16][bytes …]. The byte stream is
copied into the framebuffer at offset (in bytes from slot 0). The
firmware shifts the entire frame to the strip after the partial
update and holds the latch pulse for ≥ 50 µs.
Constraints:
offset + lenMUST NOT exceedpixel_count * bytes_per_pixel.- Total wire payload ≤ MTU (4 KiB) — chunk into multiple WRITEs for larger updates; the framebuffer persists between calls.
- Byte order on the wire matches the configured format. For GRB,
the canonical pixel triple is
G R B.
0x03 CLEAR¶
Request: [idx u8]. Fills the framebuffer with zeros and latches.
Examples¶
Single red pixel on a 1-LED strip¶
GET_INFO → max=256, format=GRB, count=1
CONFIGURE idx=0, format=GRB, pixel_count=1
WRITE idx=0, offset=0, bytes=[0x00, 0xFF, 0x00] # G=0 R=255 B=0
16-LED RGB rainbow¶
CONFIGURE idx=0, format=GRB, pixel_count=16
WRITE idx=0, offset=0, bytes=<48 GRB bytes for 16 pixels>
Clear after demo¶
Error semantics¶
| Status | Cause |
|---|---|
ENOENT |
idx ≠ 0 |
EINVAL |
unknown format, pixel_count out of range, oversized |
EAGAIN |
strip not initialised (subsystem disabled at build) |
EBUSY |
pin/PIO conflict at firmware boot (very rare) |
ENOTSUP |
board built without RPBRIDGE_HAVE_LED |
Performance notes¶
A 256-pixel WS2812 frame takes ~7.7 ms to shift out at 800 kHz
(24 bits × 1.25 µs × 256 + 80 µs latch). The blocking WRITE reply
arrives after the latch completes, so a host that issues frames at
100 Hz on a 256-pixel strip will saturate the link. For continuous animation, prefer the partial-WRITE pattern (only the changed bytes) or step down
pixel_count.