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}