ws281x_rpi/
lib.rs

1use std::mem;
2use std::slice::from_raw_parts_mut;
3
4mod bindings;
5mod channel_builder;
6mod error;
7mod strip_type;
8
9use channel_builder::ChannelBuilder;
10use error::WS2811Error;
11use strip_type::StripType;
12
13use smart_leds_trait::{SmartLedsWrite, RGB8};
14
15pub struct Ws2812Rpi {
16    c_struct: bindings::ws2811_t,
17}
18
19impl Ws2812Rpi
20{
21    /// Use ws2812 devices via rpi-ws281x library
22    pub fn new(led_count: i32, pin: i32) -> Result<Self, WS2811Error> {
23        unsafe {
24            let mut ret = Self { c_struct: mem::zeroed() };
25
26            ret.c_struct.freq = 800_000;
27            ret.c_struct.dmanum = 10;
28            ret.c_struct.channel[0] = ChannelBuilder::new()
29                                     .pin(pin)
30                                     .count(led_count)
31                                     .strip_type(StripType::Ws2811Rgb)
32                                     .brightness(255)
33                                     .build();
34            let res: Result<(), WS2811Error> = bindings::ws2811_init(&mut ret.c_struct).into();
35
36            match res {
37                Ok(_) => {}
38                Err(e) => return Err(e),
39            }
40            return Ok(ret);
41        }
42
43    }
44
45}
46
47impl Drop for Ws2812Rpi {
48    fn drop(&mut self) {
49        /*
50         * Unsafe used here because we need to call an externed
51         * function during the drop process.  Unfortunately,
52         * I don't have a better way of dealing with this.
53         */
54        unsafe {
55            bindings::ws2811_fini(&mut self.c_struct);
56        }
57    }
58}
59
60impl SmartLedsWrite for Ws2812Rpi
61{
62    type Error = error::WS2811Error;
63    type Color = RGB8;
64    // Write all the items of an iterator to a ws2812 strip
65    fn write<T, I>(&mut self, iterator: T) -> Result<(), Self::Error>
66    where
67        T: Iterator<Item = I>,
68        I: Into<Self::Color>,
69    {
70        let mut i = 0;
71
72        let mut colors = unsafe {
73            from_raw_parts_mut(
74                self.c_struct.channel[0].leds as *mut [u8; 4],
75                self.c_struct.channel[0].count as usize,
76            )
77        };
78
79        for c in iterator {
80            let c_rgb: Self::Color = c.into();
81            colors[i] = [c_rgb.b, c_rgb.r, c_rgb.g, 0];
82            i = i + 1;
83        }
84
85        unsafe {
86            return bindings::ws2811_render(&mut self.c_struct).into();
87        }
88
89        Ok(())
90    }
91}