ws2812_blocking_spi/lib.rs
1//! # Use ws2812 leds via the `embedded_hal::blocking::spi::Write` trait
2//!
3//! - For usage with `smart-leds`
4//! - Implements the `SmartLedsWrite` trait
5//!
6//! Needs a type implementing the `blocking::spi::Write` trait.
7
8#![no_std]
9
10use embedded_hal::blocking::spi::Write;
11use smart_leds_trait::{SmartLedsWrite, RGB8};
12use ws2812_spi_write_constants::ws2812_constants;
13
14ws2812_constants!(WRITE_4_BYTE_CONSTANTS);
15
16/// Wraps a SPI Writer to represent a WS2821 LED array.
17///
18/// # Examples:
19///
20/// ```
21/// use ws2812_blocking_spi::Ws2812BlockingWriter;
22///
23/// use embedded_hal::blocking::spi::Write;
24/// use smart_leds_trait::{RGB8, SmartLedsWrite};
25///
26/// //
27/// // Displays 3 LEDs: red, green and blue
28/// //
29/// fn show<SPI: Write<u8>>(spi: SPI) {
30/// let mut leds = Ws2812BlockingWriter::new(spi);
31///
32/// let mut data = [RGB8::default(); 3];
33///
34/// data[0] = [0xFF_u8, 0_u8, 0_u8].into(); // Full RED
35/// data[1] = [0_u8, 0xFF_u8, 0_u8].into(); // Full GREEN
36/// data[2] = [0_u8, 0_u8, 0xFF_u8].into(); // Full BLUE
37///
38/// leds.write(data.iter().cloned());
39/// }
40///
41/// ```
42///
43pub struct Ws2812BlockingWriter<SPI> {
44 spi: SPI,
45}
46
47impl<SPI: Write<u8>> Ws2812BlockingWriter<SPI> {
48 pub fn new(spi: SPI) -> Self {
49 Ws2812BlockingWriter { spi }
50 }
51
52 fn flush(&mut self) -> Result<(), SPI::Error> {
53 // Should be > 300μs, so for an SPI Freq. of 3.8MHz, we have to send at least 1140 low bits or 140 low bytes
54 self.spi.write(&[0u8; 140])
55 }
56}
57
58impl<SPI: Write<u8>> SmartLedsWrite for Ws2812BlockingWriter<SPI> {
59 type Error = SPI::Error;
60 type Color = RGB8;
61
62 /// Write all the items of an iterator to a ws2812 strip
63 fn write<T, I>(&mut self, iterator: T) -> Result<(), SPI::Error>
64 where
65 T: Iterator<Item = I>,
66 I: Into<Self::Color>,
67 {
68 let mut buffer = [0u8; 12];
69 for item in iterator {
70 let item = item.into();
71
72 buffer[0..4].copy_from_slice(&WRITE_4_BYTE_CONSTANTS[item.g as usize]);
73 buffer[4..8].copy_from_slice(&WRITE_4_BYTE_CONSTANTS[item.r as usize]);
74 buffer[8..12].copy_from_slice(&WRITE_4_BYTE_CONSTANTS[item.b as usize]);
75
76 self.spi.write(&buffer)?
77 }
78 self.flush()?;
79
80 Ok(())
81 }
82}