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 self.led_high();
73 self.delay_ns(Self::t1h());
74 self.led_low();
75 self.delay_ns(Self::t1l());
76 } else {
77 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 self.led_high();
98 delay.delay_ns(Self::t1h());
99 self.led_low();
100 delay.delay_ns(Self::t1l());
101 } else {
102 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]) }
127
128 pub const fn blue() -> Self {
129 Self([0, 0, 255]) }
131
132 pub const fn cyan() -> Self {
133 Self([0, 255, 255]) }
135
136 pub const fn magenta() -> Self {
137 Self([255, 0, 255]) }
139
140 pub const fn yellow() -> Self {
141 Self([255, 255, 0]) }
143
144 pub const fn white() -> Self {
145 Self([255, 255, 255]) }
147
148 pub const fn orange() -> Self {
149 Self([255, 165, 0]) }
151
152 pub const fn purple() -> Self {
153 Self([128, 0, 128]) }
155
156 pub const fn pink() -> Self {
157 Self([255, 192, 203]) }
159
160 pub const fn brown() -> Self {
161 Self([165, 42, 42]) }
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 }
170 fn t1h() -> u32 {
171 700 }
173 fn t0l() -> u32 {
174 800 }
176 fn t1l() -> u32 {
177 600 }
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 }
198 fn t1h() -> u32 {
199 700 }
201 fn t0l() -> u32 {
202 800 }
204 fn t1l() -> u32 {
205 600 }
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 }
228 fn t1h() -> u32 {
229 700 }
231 fn t0l() -> u32 {
232 800 }
234 fn t1l() -> u32 {
235 600 }
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}