ws2812_rs/
lib.rs

1#![no_std]
2
3use embedded_hal::digital::OutputPin;
4
5#[cfg(not(feature = "spinloop_delay"))]
6use embedded_hal::delay::DelayNs;
7
8#[cfg(feature = "own_delay")]
9pub struct WS2812<'a, LED: OutputPin, D: DelayNs> {
10    led: LED,
11    delay: &'a mut D,
12}
13
14#[cfg(feature = "manual_delay")]
15pub struct WS2812<LED: OutputPin> {
16    led: LED,
17}
18#[cfg(feature = "spinloop_delay")]
19pub struct WS2812<LED: OutputPin> {
20    led: LED,
21    cpu_freq: u64,
22}
23
24#[cfg(feature = "own_delay")]
25impl<'a, LED: OutputPin, D: DelayNs> WS2812<'a, LED, D> {
26    pub fn new(led: LED, delay: &'a mut D) -> Self {
27        Self { led, delay }
28    }
29    pub fn destroy(self) -> LED {
30        self.led
31    }
32}
33
34#[cfg(feature = "manual_delay")]
35impl<LED: OutputPin> WS2812<LED> {
36    pub fn new(led: LED) -> Self {
37        Self { led }
38    }
39    pub fn destroy(self) -> LED {
40        self.led
41    }
42}
43#[cfg(feature = "spinloop_delay")]
44impl<LED: OutputPin> WS2812<LED> {
45    pub fn new(led: LED, cpu_freq: u64) -> Self {
46        Self { led, cpu_freq }
47    }
48    pub fn destroy(self) -> LED {
49        self.led
50    }
51}
52
53pub trait GlowColor {
54    fn t0h() -> u32;
55    fn t1h() -> u32;
56    fn t0l() -> u32;
57    fn t1l() -> u32;
58    fn reset() -> u32;
59
60    #[cfg(not(feature = "manual_delay"))]
61    fn delay_ns(&mut self, ns: u32);
62    fn led_low(&mut self);
63    fn led_high(&mut self);
64
65    #[cfg(not(feature = "manual_delay"))]
66    fn send_color<const N: usize>(&mut self, color: [Color; N]) {
67        for each_color in color {
68            for byte in each_color.0 {
69                for bit in (0..8).rev() {
70                    if (byte & (1 << bit)) != 0 {
71                        // Logic 1
72                        self.led_high();
73                        self.delay_ns(Self::t1h());
74                        self.led_low();
75                        self.delay_ns(Self::t1l());
76                    } else {
77                        // Logic 0
78                        self.led_high();
79                        self.delay_ns(Self::t0h());
80                        self.led_low();
81                        self.delay_ns(Self::t0l());
82                    }
83                }
84            }
85        }
86        self.led_low();
87        self.delay_ns(Self::reset())
88    }
89
90    #[cfg(feature = "manual_delay")]
91    fn send_color<const N: usize, D: DelayNs>(&mut self, color: [Color; N], delay: &mut D) {
92        for each_color in color {
93            for byte in each_color.0 {
94                for bit in (0..8).rev() {
95                    if (byte & (1 << bit)) != 0 {
96                        // Logic 1
97                        self.led_high();
98                        delay.delay_ns(Self::t1h());
99                        self.led_low();
100                        delay.delay_ns(Self::t1l());
101                    } else {
102                        // Logic 0
103                        self.led_high();
104                        delay.delay_ns(Self::t0h());
105                        self.led_low();
106                        delay.delay_ns(Self::t0l());
107                    }
108                }
109            }
110        }
111        self.led_low();
112        delay.delay_ns(Self::reset())
113    }
114}
115
116#[derive(Default, Clone)]
117pub struct Color(pub [u8; 3]);
118
119impl Color {
120    pub const fn red() -> Self {
121        Self([255, 0, 0])
122    }
123
124    pub const fn green() -> Self {
125        Self([0, 255, 0]) // Green
126    }
127
128    pub const fn blue() -> Self {
129        Self([0, 0, 255]) // Blue
130    }
131
132    pub const fn cyan() -> Self {
133        Self([0, 255, 255]) // Cyan (Green + Blue)
134    }
135
136    pub const fn magenta() -> Self {
137        Self([255, 0, 255]) // Magenta (Red + Blue)
138    }
139
140    pub const fn yellow() -> Self {
141        Self([255, 255, 0]) // Yellow (Red + Green)
142    }
143
144    pub const fn white() -> Self {
145        Self([255, 255, 255]) // White (All colors)
146    }
147
148    pub const fn orange() -> Self {
149        Self([255, 165, 0]) // Orange (Red + some Green)
150    }
151
152    pub const fn purple() -> Self {
153        Self([128, 0, 128]) // Purple (Dimmed Magenta)
154    }
155
156    pub const fn pink() -> Self {
157        Self([255, 192, 203]) // Pink (Light Red)
158    }
159
160    pub const fn brown() -> Self {
161        Self([165, 42, 42]) // Brown
162    }
163}
164
165#[cfg(feature = "own_delay")]
166impl<'a, LED: OutputPin, D: DelayNs> GlowColor for WS2812<'a, LED, D> {
167    fn t0h() -> u32 {
168        350 // Time in nanoseconds (logic 0 high)
169    }
170    fn t1h() -> u32 {
171        700 // Time in nanoseconds (logic 1 high)
172    }
173    fn t0l() -> u32 {
174        800 // Time in nanoseconds (logic 0 low)
175    }
176    fn t1l() -> u32 {
177        600 // Time in nanoseconds (logic 1 low)
178    }
179    fn reset() -> u32 {
180        50
181    }
182    fn delay_ns(&mut self, ns: u32) {
183        self.delay.delay_ns(ns);
184    }
185    fn led_low(&mut self) {
186        self.led.set_low().ok();
187    }
188    fn led_high(&mut self) {
189        self.led.set_high().ok();
190    }
191}
192
193#[cfg(feature = "spinloop_delay")]
194impl<LED: OutputPin> GlowColor for WS2812<LED> {
195    fn t0h() -> u32 {
196        350 // Time in nanoseconds (logic 0 high)
197    }
198    fn t1h() -> u32 {
199        700 // Time in nanoseconds (logic 1 high)
200    }
201    fn t0l() -> u32 {
202        800 // Time in nanoseconds (logic 0 low)
203    }
204    fn t1l() -> u32 {
205        600 // Time in nanoseconds (logic 1 low)
206    }
207    fn reset() -> u32 {
208        50
209    }
210    fn led_low(&mut self) {
211        self.led.set_low().ok();
212    }
213    fn delay_ns(&mut self, ns: u32) {
214        let cycle = (self.cpu_freq * ns as u64) / 1_000_000_000;
215        for _ in 0..cycle as u32 {
216            core::hint::spin_loop();
217        }
218    }
219    fn led_high(&mut self) {
220        self.led.set_high().ok();
221    }
222}
223#[cfg(feature = "manual_delay")]
224impl<LED: OutputPin> GlowColor for WS2812<LED> {
225    fn t0h() -> u32 {
226        350 // Time in nanoseconds (logic 0 high)
227    }
228    fn t1h() -> u32 {
229        700 // Time in nanoseconds (logic 1 high)
230    }
231    fn t0l() -> u32 {
232        800 // Time in nanoseconds (logic 0 low)
233    }
234    fn t1l() -> u32 {
235        600 // Time in nanoseconds (logic 1 low)
236    }
237    fn reset() -> u32 {
238        50
239    }
240    fn led_low(&mut self) {
241        self.led.set_low().ok();
242    }
243    fn led_high(&mut self) {
244        self.led.set_high().ok();
245    }
246}