1#![no_std]
11
12use embedded_hal as hal;
13
14pub mod prerendered;
15
16use hal::spi::{FullDuplex, Mode, Phase, Polarity};
17
18use core::marker::PhantomData;
19
20use smart_leds_trait::{SmartLedsWrite, RGB8};
21
22use nb;
23use nb::block;
24
25pub const MODE: Mode = Mode {
30 polarity: Polarity::IdleLow,
31 phase: Phase::CaptureOnFirstTransition,
32};
33
34pub mod devices {
35 pub struct Ws2811Rgb;
36 pub struct Ws2811Rbg;
37}
38
39pub struct Ws2811<SPI, DEVICE = devices::Ws2811Rgb> {
40 spi: SPI,
41 device: PhantomData<DEVICE>,
42}
43
44impl<SPI, E> Ws2811<SPI>
45where
46 SPI: FullDuplex<u8, Error = E>,
47{
48 pub fn new_rgb(spi: SPI) -> Self {
57 Self {
58 spi,
59 device: PhantomData {},
60 }
61 }
62}
63
64impl<SPI, E> Ws2811<SPI, devices::Ws2811Rbg>
65where
66 SPI: FullDuplex<u8, Error = E>,
67{
68 pub fn new_rbg(spi: SPI) -> Self {
77 Self {
78 spi,
79 device: PhantomData {},
80 }
81 }
82}
83
84impl<SPI, D, E> Ws2811<SPI, D>
85where
86 SPI: FullDuplex<u8, Error = E>,
87{
88 fn write_byte(&mut self, mut data: u8) -> Result<(), E> {
90 let patterns = [0b1000_1000, 0b1000_1110, 0b11101000, 0b11101110];
94 for _ in 0..4 {
95 let bits = (data & 0b1100_0000) >> 6;
96 block!(self.spi.send(patterns[bits as usize]))?;
97 block!(self.spi.read()).ok();
98 data <<= 2;
99 }
100 Ok(())
101 }
102
103 fn flush(&mut self) -> Result<(), E> {
104 for _ in 0..140 {
106 block!(self.spi.send(0))?;
107 block!(self.spi.read()).ok();
108 }
109 Ok(())
110 }
111}
112
113impl<SPI, E> SmartLedsWrite for Ws2811<SPI>
114where
115 SPI: FullDuplex<u8, Error = E>,
116{
117 type Error = E;
118 type Color = RGB8;
119 fn write<T, I>(&mut self, iterator: T) -> Result<(), E>
121 where
122 T: Iterator<Item = I>,
123 I: Into<Self::Color>,
124 {
125 block!(self.spi.send(0))?;
129
130 if cfg!(feature = "mosi_idle_high") {
131 self.flush()?;
132 }
133
134 for item in iterator {
135 let item = item.into();
136 self.write_byte(item.r)?;
137 self.write_byte(item.g)?;
138 self.write_byte(item.b)?;
139 }
140 self.flush()?;
141 if cfg!(feature = "fifo_stm32f1") {
143 self.spi.read().ok();
144 } else {
145 block!(self.spi.read())?;
146 }
147
148 Ok(())
149 }
150}
151
152impl<SPI, E> SmartLedsWrite for Ws2811<SPI, devices::Ws2811Rbg>
153where
154 SPI: FullDuplex<u8, Error = E>,
155{
156 type Error = E;
157 type Color = RGB8;
158 fn write<T, I>(&mut self, iterator: T) -> Result<(), E>
160 where
161 T: Iterator<Item = I>,
162 I: Into<Self::Color>,
163 {
164 block!(self.spi.send(0))?;
168 if cfg!(feature = "mosi_idle_high") {
169 self.flush()?;
170 }
171
172 for item in iterator {
173 let item = item.into();
174 self.write_byte(item.r)?;
175 self.write_byte(item.b)?;
176 self.write_byte(item.g)?;
177 }
178 self.flush()?;
179 if cfg!(feature = "fifo_stm32f1") {
181 self.spi.read().ok();
182 } else {
183 block!(self.spi.read())?;
184 }
185 Ok(())
186 }
187}