"""Map logical RGB to WS2812 wire byte order.""" from __future__ import annotations from leds.array_config import WIRE_ORDER # wire[i] = rgb_channel[perm[i]] where rgb = (r, g, b) _PERM: dict[str, tuple[int, int, int]] = { "rgb": (0, 1, 2), "grb": (1, 0, 2), "rbg": (0, 2, 1), "brg": (2, 0, 1), "bgr": (2, 1, 0), "gbr": (1, 2, 0), } def normalize_wire_order(order: str | None = None) -> str: key = (order or WIRE_ORDER).lower() if key not in _PERM: raise ValueError(f"unknown wire order {key!r}; use one of {sorted(_PERM)}") return key def rgb_to_wire(r: int, g: int, b: int, order: str | None = None) -> tuple[int, int, int]: perm = _PERM[normalize_wire_order(order)] ch = (r, g, b) return ch[perm[0]], ch[perm[1]], ch[perm[2]] def rgb_bytes_to_wire(rgb: bytes, order: str | None = None) -> bytes: perm = _PERM[normalize_wire_order(order)] out = bytearray(len(rgb)) for i in range(0, len(rgb), 3): ch = rgb[i], rgb[i + 1], rgb[i + 2] out[i] = ch[perm[0]] out[i + 1] = ch[perm[1]] out[i + 2] = ch[perm[2]] return bytes(out) def swap_rg_bytes(rgb: bytes) -> bytes: """Swap R and G channels (hardware examples only — not the web simulator).""" out = bytearray(rgb) for i in range(0, len(out), 3): out[i], out[i + 1] = out[i + 1], out[i] return bytes(out)