1#![no_std]
2use core::marker::PhantomData;
3
4use embedded_hal_async::spi::{ErrorType, SpiBus};
5use smart_leds_trait::{SmartLedsWriteAsync, RGB8};
6
7const PATTERNS: [u8; 4] = [0b1000_1000, 0b1000_1110, 0b1110_1000, 0b1110_1110];
8
9pub trait OrderedColors {
11 fn order(color: RGB8) -> [u8; 3];
12}
13
14pub struct Rgb;
16
17pub struct Grb;
19
20impl OrderedColors for Rgb {
21 fn order(color: RGB8) -> [u8; 3] {
22 [color.r, color.g, color.b]
23 }
24}
25
26impl OrderedColors for Grb {
27 fn order(color: RGB8) -> [u8; 3] {
28 [color.g, color.r, color.b]
29 }
30}
31
32pub struct Ws2812<SPI: SpiBus<u8>, C: OrderedColors, const N: usize> {
34 spi: SPI,
35 data: [u8; N],
36 _color_order: PhantomData<C>,
37}
38
39impl<SPI: SpiBus<u8>, C: OrderedColors, const N: usize> Ws2812<SPI, C, N> {
40 pub fn new(spi: SPI) -> Self {
43 Self {
44 spi,
45 data: [0; N],
46 _color_order: PhantomData,
47 }
48 }
49}
50
51impl<SPI, E, C: OrderedColors, const N: usize> SmartLedsWriteAsync for Ws2812<SPI, C, N>
52where
53 SPI: SpiBus<u8, Error = E>,
54{
55 type Error = E;
56 type Color = RGB8;
57
58 async fn write<T, I>(&mut self, iter: T) -> Result<(), <SPI as ErrorType>::Error>
59 where
60 T: IntoIterator<Item = I>,
61 I: Into<Self::Color>,
62 {
63 for (led_bytes, rgb8) in self.data.chunks_mut(12).zip(iter) {
64 let colors = C::order(rgb8.into());
65 for (i, mut color) in colors.into_iter().enumerate() {
66 for ii in 0..4 {
67 led_bytes[i * 4 + ii] = PATTERNS[((color & 0b1100_0000) >> 6) as usize];
68 color <<= 2;
69 }
70 }
71 }
72 self.spi.write(&self.data).await?;
73 let blank = [0_u8; 140];
74 self.spi.write(&blank).await
75 }
76}