Files
portal/leds/backends/rpi5_ws2812.py
Jimmy 5094c7bcee Add portal web simulator, SPI bridges, and Pico firmware updates.
Bring the five-panel hex portal online with a browser 3D/schematic preview, Pi SPI backends, and renamed multi-panel Pico UDP firmware.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-30 14:54:51 +12:00

55 lines
1.4 KiB
Python

"""WS2812 over SPI via the rpi5-ws2812 package (Pi 5, GPIO 10)."""
from __future__ import annotations
import numpy as np
from rpi5_ws2812.ws2812 import WS2812SpiDriver
from leds.backends.spi import spidev_bufsize_hint
class Rpi5Ws2812Backend:
def __init__(
self,
led_count: int,
*,
spi_bus: int = 0,
spi_device: int = 0,
max_speed_hz: int = 4_200_000,
) -> None:
hint = spidev_bufsize_hint(led_count)
if hint:
raise OSError(hint)
self._led_count = led_count
self._driver = WS2812SpiDriver(spi_bus, spi_device, led_count)
self._driver._device.max_speed_hz = max_speed_hz
@property
def led_count(self) -> int:
return self._led_count
def write_grb(self, rgb_bytes: bytes) -> None:
"""RGB bytes passed through to SPI unchanged."""
if len(rgb_bytes) != self._led_count * 3:
raise ValueError(
f"expected {self._led_count * 3} bytes, got {len(rgb_bytes)}"
)
buf = np.frombuffer(rgb_bytes, dtype=np.uint8).reshape(self._led_count, 3)
self._driver.write(buf)
def clear(self) -> None:
self._driver.clear()
def close(self) -> None:
try:
self.clear()
finally:
self._driver._device.close()
def __enter__(self) -> Rpi5Ws2812Backend:
return self
def __exit__(self, *_exc) -> None:
self.close()