led_strip
What an addressable LED strip promises, and code written against it.
A lib/ crate: no registers, no part numbers, no pins. It defines the
contract that LED drivers keep, and the effects worth writing once rather
than once per chip.
The promises are small on purpose
Section titled “The promises are small on purpose”One fat trait forces all-or-nothing. A chip either implements everything — faking whatever it lacks — or it implements nothing and looks unsupported. Both are lies.
Split up, a driver states exactly what its hardware does:
| Trait | Meaning | WS2812 | APA102 |
|---|---|---|---|
[LedStrip] |
set a pixel, push the frame | yes | yes |
[Dimmable] |
a global brightness the hardware applies | no | yes, 5 bits |
WS2812 has no brightness register — dimming it means scaling the colour
before sending, which costs colour depth. APA102 has one. If both
implemented a single LedStrip with set_brightness on it, one of them
would have to pretend, and a caller could not tell which.
Not implementing a trait is therefore a real statement, and
make device-matrix prints who implements what so a gap is visible rather
than merely absent.
Structs
Section titled “Structs”struct Rgb { pub r: u8, pub g: u8, pub b: u8,}A colour.
Lives here rather than in a driver because a colour is not a property of
any part number — it was in ws2812, which meant using an APA102 would
have meant depending on a WS2812 driver to name a colour.
Implements: Clone, Copy, Debug, Default, Eq, PartialEq, StructuralPartialEq
StripError
Section titled “StripError”enum StripError { OutOfRange, Transport,}Something went wrong talking to the strip.
Implements: Clone, Copy, Debug, Eq, PartialEq, StructuralPartialEq
Traits
Section titled “Traits”Dimmable
Section titled “Dimmable”trait Dimmable { fn set_brightness(&mut self, level: u8) -> Result<(), StripError>}A strip whose hardware applies a global brightness.
Separate from [LedStrip] because WS2812 has no such register. A chip that
does not implement this is saying so, rather than silently scaling colours
and losing depth — the caller can then choose [Rgb::dim] knowingly.
LedStrip
Section titled “LedStrip”trait LedStrip { fn len(&self) -> usize fn is_empty(&self) -> bool fn set(&mut self, index: usize, colour: Rgb) -> Result<(), StripError> fn show(&mut self) -> Result<(), StripError> fn fill(&mut self, colour: Rgb) -> Result<(), StripError> fn clear(&mut self) -> Result<(), StripError>}The minimum an addressable strip must do.
Deliberately does not include brightness, colour order, or timing — those are either the chip’s business or a separate promise.
Functions
Section titled “Functions”gradient
Section titled “gradient”fn gradient<S>(strip: &mut S, start_hue: u8) -> Result<(), StripError>Paint a hue gradient across the whole strip. Does not show.
Written once here rather than once per chip, which is the entire reason
[LedStrip] exists.
References: StripError