1#![cfg_attr(not(feature = "std"), no_std)]
14
15use embedded_hal as hal;
16
17#[cfg(feature = "std")]
18pub mod hosted;
19pub mod prerendered;
20
21use hal::spi::{Mode, Phase, Polarity, SpiBus};
22
23use core::marker::PhantomData;
24use core::slice::from_ref;
25
26use smart_leds_trait::{SmartLedsWrite, RGB8, RGBW};
27
28pub const MODE: Mode = Mode {
33 polarity: Polarity::IdleLow,
34 phase: Phase::CaptureOnFirstTransition,
35};
36
37pub mod devices {
38 pub struct Ws2812;
39 pub struct Sk6812w;
40}
41
42pub struct Ws2812<SPI, DEVICE = devices::Ws2812> {
43 spi: SPI,
44 device: PhantomData<DEVICE>,
45}
46
47impl<SPI, E> Ws2812<SPI>
48where
49 SPI: SpiBus<u8, Error = E>,
50{
51 pub fn new(spi: SPI) -> Self {
60 Self {
61 spi,
62 device: PhantomData {},
63 }
64 }
65}
66
67impl<SPI, E> Ws2812<SPI, devices::Sk6812w>
68where
69 SPI: SpiBus<u8, Error = E>,
70{
71 pub fn new_sk6812w(spi: SPI) -> Self {
82 Self {
83 spi,
84 device: PhantomData {},
85 }
86 }
87}
88
89impl<SPI, D, E> Ws2812<SPI, D>
90where
91 SPI: SpiBus<u8, Error = E>,
92{
93 fn write_byte(&mut self, mut data: u8) -> Result<(), E> {
95 let patterns = [0b1000_1000, 0b1000_1110, 0b11101000, 0b11101110];
99 for _ in 0..4 {
100 let bits = (data & 0b1100_0000) >> 6;
101 self.spi.write(from_ref(&patterns[bits as usize]))?;
102 data <<= 2;
103 }
104 Ok(())
105 }
106
107 fn reset(&mut self) -> Result<(), E> {
108 for _ in 0..140 {
110 self.spi.write(from_ref(&0))?;
111 }
112 Ok(())
113 }
114}
115
116impl<SPI, E> SmartLedsWrite for Ws2812<SPI>
117where
118 SPI: SpiBus<u8, Error = E>,
119{
120 type Error = E;
121 type Color = RGB8;
122 fn write<T, I>(&mut self, iterator: T) -> Result<(), E>
124 where
125 T: IntoIterator<Item = I>,
126 I: Into<Self::Color>,
127 {
128 if cfg!(feature = "mosi_idle_high") {
129 self.reset()?;
130 }
131
132 for item in iterator {
133 let item = item.into();
134 self.write_byte(item.g)?;
135 self.write_byte(item.r)?;
136 self.write_byte(item.b)?;
137 }
138 self.reset()?;
139 Ok(())
140 }
141}
142
143impl<SPI, E> SmartLedsWrite for Ws2812<SPI, devices::Sk6812w>
144where
145 SPI: SpiBus<u8, Error = E>,
146{
147 type Error = E;
148 type Color = RGBW<u8, u8>;
149 fn write<T, I>(&mut self, iterator: T) -> Result<(), E>
151 where
152 T: IntoIterator<Item = I>,
153 I: Into<Self::Color>,
154 {
155 if cfg!(feature = "mosi_idle_high") {
156 self.reset()?;
157 }
158
159 for item in iterator {
160 let item = item.into();
161 self.write_byte(item.g)?;
162 self.write_byte(item.r)?;
163 self.write_byte(item.b)?;
164 self.write_byte(item.a.0)?;
165 }
166 self.reset()?;
167 Ok(())
168 }
169}