|
13 | 13 | //! Bear in mind that you will have to take care of timing requirements |
14 | 14 | //! yourself then. |
15 | 15 |
|
16 | | -//use cortex_m; |
17 | 16 | use fugit::{ExtU32, HertzU32}; |
18 | 17 | use rp2040_hal::{ |
19 | | - gpio::{Function, Pin, PinId, PullType, *}, |
| 18 | + gpio::{Function, Pin, PinId, *}, |
20 | 19 | pio::{PIOExt, StateMachineIndex, Tx, UninitStateMachine, PIO}, |
21 | | - //timer::CountDown, |
| 20 | + timer::CountDown, |
22 | 21 | }; |
23 | | -//use smart_leds_trait::SmartLedsWrite; |
| 22 | +use smart_leds_trait::SmartLedsWrite; |
24 | 23 |
|
25 | | -///// This is the WS2812 PIO Driver. |
26 | | -///// |
27 | | -///// For blocking applications is recommended to use |
28 | | -///// the [Ws2812] struct instead of this raw driver. |
29 | | -///// |
30 | | -///// If you use this driver directly, you will need to |
31 | | -///// take care of the timing expectations of the [Ws2812Direct::write] |
32 | | -///// method. |
33 | | -///// |
34 | | -///// Typical usage example: |
35 | | -/////```ignore |
36 | | -///// use rp2040_hal::clocks::init_clocks_and_plls; |
37 | | -///// let clocks = init_clocks_and_plls(...); |
38 | | -///// let pins = rp2040_hal::gpio::pin::bank0::Pins::new(...); |
39 | | -///// |
40 | | -///// let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS); |
41 | | -///// let mut ws = Ws2812Direct::new( |
42 | | -///// pins.gpio4.into_mode(), |
43 | | -///// &mut pio, |
44 | | -///// sm0, |
45 | | -///// clocks.peripheral_clock.freq(), |
46 | | -///// ); |
47 | | -///// |
48 | | -///// // Then you will make sure yourself to not write too frequently: |
49 | | -///// loop { |
50 | | -///// use smart_leds::{SmartLedsWrite, RGB8}; |
51 | | -///// let color : RGB8 = (255, 0, 255).into(); |
52 | | -///// |
53 | | -///// ws.write([color].iter().copied()).unwrap(); |
54 | | -///// delay_for_at_least_60_microseconds(); |
55 | | -///// }; |
56 | | -/////``` |
| 24 | +/// This is the WS2812 PIO Driver. |
| 25 | +/// |
| 26 | +/// For blocking applications is recommended to use |
| 27 | +/// the [Ws2812] struct instead of this raw driver. |
| 28 | +/// |
| 29 | +/// If you use this driver directly, you will need to |
| 30 | +/// take care of the timing expectations of the [Ws2812Direct::write] |
| 31 | +/// method. |
| 32 | +/// |
| 33 | +/// Typical usage example: |
| 34 | +///```ignore |
| 35 | +/// use rp2040_hal::clocks::init_clocks_and_plls; |
| 36 | +/// let clocks = init_clocks_and_plls(...); |
| 37 | +/// let pins = rp2040_hal::gpio::pin::bank0::Pins::new(...); |
| 38 | +/// |
| 39 | +/// let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS); |
| 40 | +/// let mut ws = Ws2812Direct::new( |
| 41 | +/// pins.gpio4.into_mode(), |
| 42 | +/// &mut pio, |
| 43 | +/// sm0, |
| 44 | +/// clocks.peripheral_clock.freq(), |
| 45 | +/// ); |
| 46 | +/// |
| 47 | +/// // Then you will make sure yourself to not write too frequently: |
| 48 | +/// loop { |
| 49 | +/// use smart_leds::{SmartLedsWrite, RGB8}; |
| 50 | +/// let color : RGB8 = (255, 0, 255).into(); |
| 51 | +/// |
| 52 | +/// ws.write([color].iter().copied()).unwrap(); |
| 53 | +/// delay_for_at_least_60_microseconds(); |
| 54 | +/// }; |
| 55 | +///``` |
57 | 56 | pub struct Ws2812Direct<P, SM, I, F> |
58 | 57 | where |
59 | 58 | I: PinId, |
|
62 | 61 | SM: StateMachineIndex, |
63 | 62 | { |
64 | 63 | tx: Tx<(P, SM)>, |
65 | | - _pin: Pin<I, F, DynPullType> |
| 64 | + _pin: Pin<I, F, DynPullType>, |
66 | 65 | } |
67 | 66 |
|
68 | 67 | impl<P, SM, I, F> Ws2812Direct<P, SM, I, F> |
@@ -148,122 +147,122 @@ where |
148 | 147 | } |
149 | 148 | } |
150 | 149 |
|
151 | | -//impl<P, SM, I> SmartLedsWrite for Ws2812Direct<P, SM, I> |
152 | | -//where |
153 | | -// I: PinId, |
154 | | -// P: PIOExt + FunctionConfig, |
155 | | -// Function<P>: ValidPinMode<I>, |
156 | | -// SM: StateMachineIndex, |
157 | | -//{ |
158 | | -// type Color = smart_leds_trait::RGB8; |
159 | | -// type Error = (); |
160 | | -// /// If you call this function, be advised that you will have to wait |
161 | | -// /// at least 60 microseconds between calls of this function! |
162 | | -// /// That means, either you get hold on a timer and the timing |
163 | | -// /// requirements right your self, or rather use [Ws2812]. |
164 | | -// /// |
165 | | -// /// Please bear in mind, that it still blocks when writing into the |
166 | | -// /// PIO FIFO until all data has been transmitted to the LED chain. |
167 | | -// fn write<T, J>(&mut self, iterator: T) -> Result<(), ()> |
168 | | -// where |
169 | | -// T: Iterator<Item = J>, |
170 | | -// J: Into<Self::Color>, |
171 | | -// { |
172 | | -// for item in iterator { |
173 | | -// let color: Self::Color = item.into(); |
174 | | -// let word = |
175 | | -// (u32::from(color.g) << 24) | (u32::from(color.r) << 16) | (u32::from(color.b) << 8); |
176 | | -// |
177 | | -// while !self.tx.write(word) { |
178 | | -// cortex_m::asm::nop(); |
179 | | -// } |
180 | | -// } |
181 | | -// Ok(()) |
182 | | -// } |
183 | | -//} |
| 150 | +impl<P, SM, I, F> SmartLedsWrite for Ws2812Direct<P, SM, I, F> |
| 151 | +where |
| 152 | + I: PinId, |
| 153 | + P: PIOExt, |
| 154 | + F: Function, |
| 155 | + SM: StateMachineIndex, |
| 156 | +{ |
| 157 | + type Color = smart_leds_trait::RGB8; |
| 158 | + type Error = (); |
| 159 | + /// If you call this function, be advised that you will have to wait |
| 160 | + /// at least 60 microseconds between calls of this function! |
| 161 | + /// That means, either you get hold on a timer and the timing |
| 162 | + /// requirements right your self, or rather use [Ws2812]. |
| 163 | + /// |
| 164 | + /// Please bear in mind, that it still blocks when writing into the |
| 165 | + /// PIO FIFO until all data has been transmitted to the LED chain. |
| 166 | + fn write<T, J>(&mut self, iterator: T) -> Result<(), ()> |
| 167 | + where |
| 168 | + T: Iterator<Item = J>, |
| 169 | + J: Into<Self::Color>, |
| 170 | + { |
| 171 | + for item in iterator { |
| 172 | + let color: Self::Color = item.into(); |
| 173 | + let word = |
| 174 | + (u32::from(color.g) << 24) | (u32::from(color.r) << 16) | (u32::from(color.b) << 8); |
| 175 | + |
| 176 | + while !self.tx.write(word) { |
| 177 | + cortex_m::asm::nop(); |
| 178 | + } |
| 179 | + } |
| 180 | + Ok(()) |
| 181 | + } |
| 182 | +} |
| 183 | + |
| 184 | +/// Instance of a WS2812 LED chain. |
| 185 | +/// |
| 186 | +/// Use the [Ws2812::write] method to update the WS2812 LED chain. |
| 187 | +/// |
| 188 | +/// Typical usage example: |
| 189 | +///```ignore |
| 190 | +/// use rp2040_hal::clocks::init_clocks_and_plls; |
| 191 | +/// let clocks = init_clocks_and_plls(...); |
| 192 | +/// let pins = rp2040_hal::gpio::pin::bank0::Pins::new(...); |
| 193 | +/// |
| 194 | +/// let timer = Timer::new(pac.TIMER, &mut pac.RESETS); |
| 195 | +/// |
| 196 | +/// let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS); |
| 197 | +/// let mut ws = Ws2812::new( |
| 198 | +/// pins.gpio4.into_mode(), |
| 199 | +/// &mut pio, |
| 200 | +/// sm0, |
| 201 | +/// clocks.peripheral_clock.freq(), |
| 202 | +/// timer.count_down(), |
| 203 | +/// ); |
| 204 | +/// |
| 205 | +/// loop { |
| 206 | +/// use smart_leds::{SmartLedsWrite, RGB8}; |
| 207 | +/// let color : RGB8 = (255, 0, 255).into(); |
| 208 | +/// |
| 209 | +/// ws.write([color].iter().copied()).unwrap(); |
| 210 | +/// |
| 211 | +/// // Do other stuff here... |
| 212 | +/// }; |
| 213 | +///``` |
| 214 | +pub struct Ws2812<'timer, P, SM, I, F> |
| 215 | +where |
| 216 | + I: PinId, |
| 217 | + P: PIOExt, |
| 218 | + F: Function, |
| 219 | + SM: StateMachineIndex, |
| 220 | +{ |
| 221 | + driver: Ws2812Direct<P, SM, I, F>, |
| 222 | + cd: CountDown<'timer>, |
| 223 | +} |
| 224 | + |
| 225 | +impl<'timer, P, SM, I, F> Ws2812<'timer, P, SM, I, F> |
| 226 | +where |
| 227 | + I: PinId, |
| 228 | + P: PIOExt, |
| 229 | + F: Function, |
| 230 | + SM: StateMachineIndex, |
| 231 | +{ |
| 232 | + /// Creates a new instance of this driver. |
| 233 | + pub fn new( |
| 234 | + pin: Pin<I, F, DynPullType>, |
| 235 | + pio: &mut PIO<P>, |
| 236 | + sm: UninitStateMachine<(P, SM)>, |
| 237 | + clock_freq: fugit::HertzU32, |
| 238 | + cd: CountDown<'timer>, |
| 239 | + ) -> Ws2812<'timer, P, SM, I, F> { |
| 240 | + let driver = Ws2812Direct::new(pin, pio, sm, clock_freq); |
| 241 | + |
| 242 | + Self { driver, cd } |
| 243 | + } |
| 244 | +} |
184 | 245 |
|
185 | | -///// Instance of a WS2812 LED chain. |
186 | | -///// |
187 | | -///// Use the [Ws2812::write] method to update the WS2812 LED chain. |
188 | | -///// |
189 | | -///// Typical usage example: |
190 | | -/////```ignore |
191 | | -///// use rp2040_hal::clocks::init_clocks_and_plls; |
192 | | -///// let clocks = init_clocks_and_plls(...); |
193 | | -///// let pins = rp2040_hal::gpio::pin::bank0::Pins::new(...); |
194 | | -///// |
195 | | -///// let timer = Timer::new(pac.TIMER, &mut pac.RESETS); |
196 | | -///// |
197 | | -///// let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS); |
198 | | -///// let mut ws = Ws2812::new( |
199 | | -///// pins.gpio4.into_mode(), |
200 | | -///// &mut pio, |
201 | | -///// sm0, |
202 | | -///// clocks.peripheral_clock.freq(), |
203 | | -///// timer.count_down(), |
204 | | -///// ); |
205 | | -///// |
206 | | -///// loop { |
207 | | -///// use smart_leds::{SmartLedsWrite, RGB8}; |
208 | | -///// let color : RGB8 = (255, 0, 255).into(); |
209 | | -///// |
210 | | -///// ws.write([color].iter().copied()).unwrap(); |
211 | | -///// |
212 | | -///// // Do other stuff here... |
213 | | -///// }; |
214 | | -/////``` |
215 | | -//pub struct Ws2812<'timer, P, SM, I> |
216 | | -//where |
217 | | -// I: PinId, |
218 | | -// P: PIOExt + FunctionConfig, |
219 | | -// Function<P>: ValidPinMode<I>, |
220 | | -// SM: StateMachineIndex, |
221 | | -//{ |
222 | | -// driver: Ws2812Direct<P, SM, I>, |
223 | | -// cd: CountDown<'timer>, |
224 | | -//} |
225 | | -// |
226 | | -//impl<'timer, P, SM, I> Ws2812<'timer, P, SM, I> |
227 | | -//where |
228 | | -// I: PinId, |
229 | | -// P: PIOExt + FunctionConfig, |
230 | | -// Function<P>: ValidPinMode<I>, |
231 | | -// SM: StateMachineIndex, |
232 | | -//{ |
233 | | -// /// Creates a new instance of this driver. |
234 | | -// pub fn new( |
235 | | -// pin: Pin<I, Function<P>>, |
236 | | -// pio: &mut PIO<P>, |
237 | | -// sm: UninitStateMachine<(P, SM)>, |
238 | | -// clock_freq: fugit::HertzU32, |
239 | | -// cd: CountDown, |
240 | | -// ) -> Ws2812<'timer, P, SM, I> { |
241 | | -// let driver = Ws2812Direct::new(pin, pio, sm, clock_freq); |
242 | | -// |
243 | | -// Self { driver, cd } |
244 | | -// } |
245 | | -//} |
246 | | -// |
247 | | -//impl<'timer, P, SM, I> SmartLedsWrite for Ws2812<'timer, P, SM, rp2040_hal::timer::CountDown<'timer>, I> |
248 | | -//where |
249 | | -// I: PinId, |
250 | | -// P: PIOExt + FunctionConfig, |
251 | | -// Function<P>: ValidPinMode<I>, |
252 | | -// SM: StateMachineIndex, |
253 | | -//{ |
254 | | -// type Color = smart_leds_trait::RGB8; |
255 | | -// type Error = (); |
256 | | -// fn write<T, J>(&mut self, iterator: T) -> Result<(), ()> |
257 | | -// where |
258 | | -// T: Iterator<Item = J>, |
259 | | -// J: Into<Self::Color>, |
260 | | -// { |
261 | | -// self.driver.tx.clear_stalled_flag(); |
262 | | -// while !self.driver.tx.is_empty() && !self.driver.tx.has_stalled() {} |
263 | | -// |
264 | | -// self.cd.start(60u32.micros()); |
265 | | -// let _ = nb::block!(self.cd.wait()); |
266 | | -// |
267 | | -// self.driver.write(iterator) |
268 | | -// } |
269 | | -//} |
| 246 | +impl<'timer, P, SM, I, F> SmartLedsWrite for Ws2812<'timer, P, SM, I, F> |
| 247 | +where |
| 248 | + I: PinId, |
| 249 | + P: PIOExt, |
| 250 | + F: Function, |
| 251 | + SM: StateMachineIndex, |
| 252 | +{ |
| 253 | + type Color = smart_leds_trait::RGB8; |
| 254 | + type Error = (); |
| 255 | + fn write<T, J>(&mut self, iterator: T) -> Result<(), ()> |
| 256 | + where |
| 257 | + T: Iterator<Item = J>, |
| 258 | + J: Into<Self::Color>, |
| 259 | + { |
| 260 | + self.driver.tx.clear_stalled_flag(); |
| 261 | + while !self.driver.tx.is_empty() && !self.driver.tx.has_stalled() {} |
| 262 | + |
| 263 | + self.cd.start(60u32.micros()); |
| 264 | + let _ = nb::block!(self.cd.wait()); |
| 265 | + |
| 266 | + self.driver.write(iterator) |
| 267 | + } |
| 268 | +} |
0 commit comments