|
| 1 | +#![no_std] |
| 2 | + |
| 3 | +use embedded_hal as hal; |
| 4 | + |
| 5 | +use crate::hal::digital::OutputPin; |
| 6 | +use crate::hal::timer::{CountDown, Periodic}; |
| 7 | +use smart_leds_trait::{Color, SmartLedsWrite}; |
| 8 | + |
| 9 | +use nb; |
| 10 | +use nb::block; |
| 11 | + |
| 12 | +pub struct Ws2812<'a, TIMER, PIN> { |
| 13 | + timer: TIMER, |
| 14 | + pin: &'a mut PIN, |
| 15 | +} |
| 16 | + |
| 17 | +impl<'a, TIMER, PIN> Ws2812<'a, TIMER, PIN> |
| 18 | +where |
| 19 | + TIMER: CountDown + Periodic, |
| 20 | + PIN: OutputPin, |
| 21 | +{ |
| 22 | + /// The timer has to already run at with a frequency of 3 MHz |
| 23 | + pub fn new(timer: TIMER, pin: &'a mut PIN) -> Ws2812<'a, TIMER, PIN> { |
| 24 | + pin.set_low(); |
| 25 | + Self { timer, pin } |
| 26 | + } |
| 27 | + /// Write a single color for ws2812 devices |
| 28 | + fn write_color(&mut self, data: Color) { |
| 29 | + let mut serial_bits = (data.g as u32) << 16 | (data.r as u32) << 8 | (data.b as u32) << 0; |
| 30 | + // Wait until a timer period has gone by, so we have clean timing |
| 31 | + block!(self.timer.wait()).ok(); |
| 32 | + for _ in 0..24 { |
| 33 | + self.pin.set_high(); |
| 34 | + block!(self.timer.wait()).ok(); |
| 35 | + if (serial_bits & 0x00800000) != 0 { |
| 36 | + self.pin.set_high(); |
| 37 | + } else { |
| 38 | + self.pin.set_low(); |
| 39 | + } |
| 40 | + block!(self.timer.wait()).ok(); |
| 41 | + self.pin.set_low(); |
| 42 | + serial_bits <<= 1; |
| 43 | + block!(self.timer.wait()).ok(); |
| 44 | + } |
| 45 | + } |
| 46 | +} |
| 47 | + |
| 48 | +impl<TIMER, PIN> SmartLedsWrite for Ws2812<'_, TIMER, PIN> |
| 49 | +where |
| 50 | + TIMER: CountDown + Periodic, |
| 51 | + PIN: OutputPin, |
| 52 | +{ |
| 53 | + type Error = (); |
| 54 | + |
| 55 | + /// Write all the items of an iterator to a ws2812 strip |
| 56 | + fn write<T>(&mut self, iterator: T) -> Result<(), ()> |
| 57 | + where |
| 58 | + T: Iterator<Item = Color>, |
| 59 | + { |
| 60 | + for item in iterator { |
| 61 | + self.write_color(item); |
| 62 | + } |
| 63 | + // Get a timeout period of 300 ns |
| 64 | + for _ in 0..900 { |
| 65 | + block!(self.timer.wait()).ok(); |
| 66 | + } |
| 67 | + Ok(()) |
| 68 | + } |
| 69 | +} |
0 commit comments