1#[allow(unused)]
4use crate::hal;
5
6use crate::hal::{
7 gpio::{Level, Output, Pin, PushPull},
8 pac,
9};
10
11use core::sync::atomic::{compiler_fence, Ordering};
12
13use smart_leds_trait::{SmartLedsWrite, RGB8};
14
15pub fn fill_buf(color: &RGB8, buf: &mut [u16]) -> Result<(), ()> {
19 if buf.len() < 24 {
20 return Err(());
21 }
22
23 let red = color.r.reverse_bits();
24 let green = color.g.reverse_bits();
25 let blue = color.b.reverse_bits();
26
27 for g in 0..8 {
28 if ((green >> g) & 0b1) == 0b1 {
29 buf[g] = 0x8000 | 13;
30 } else {
31 buf[g] = 0x8000 | 5;
32 }
33 }
34
35 for r in 0..8 {
36 if ((red >> r) & 0b1) == 0b1 {
37 buf[8 + r] = 0x8000 | 13;
38 } else {
39 buf[8 + r] = 0x8000 | 5;
40 }
41 }
42
43 for b in 0..8 {
44 if ((blue >> b) & 0b1) == 0b1 {
45 buf[16 + b] = 0x8000 | 13;
46 } else {
47 buf[16 + b] = 0x8000 | 5;
48 }
49 }
50
51 Ok(())
52}
53
54pub struct Pwm<T: sealed::Instance> {
56 pwm: T,
57 _gpio: Pin<Output<PushPull>>,
58}
59
60impl<T> Pwm<T>
61where
62 T: sealed::Instance,
63{
64 pub fn new<Mode>(pwm: T, pin: Pin<Mode>) -> Pwm<T> {
66 let pin = pin.into_push_pull_output(Level::Low);
67
68 pwm.psel.out[0].write(|w| {
69 #[cfg(feature = "52840")]
70 match pin.port() {
71 hal::gpio::Port::Port0 => w.port().clear_bit(),
72 hal::gpio::Port::Port1 => w.port().set_bit(),
73 };
74 unsafe {
75 w.pin().bits(pin.pin());
76 }
77 w.connect().connected()
78 });
79
80 pwm.enable.write(|w| w.enable().enabled());
81 pwm.mode.write(|w| w.updown().up());
82 pwm.prescaler.write(|w| w.prescaler().div_1());
83 pwm.countertop.write(|w| unsafe { w.countertop().bits(20) });
84 pwm.loop_.write(|w| w.cnt().disabled());
85 pwm.decoder.write(|w| {
86 w.load().common();
87 w.mode().refresh_count()
88 });
89 pwm.seq0.refresh.write(|w| unsafe { w.bits(0) });
90 pwm.seq0.enddelay.write(|w| unsafe { w.bits(0) });
91 pwm.seq1.refresh.write(|w| unsafe { w.bits(0) });
92 pwm.seq1.enddelay.write(|w| unsafe { w.bits(0) });
93
94 Pwm { pwm, _gpio: pin }
95 }
96
97 pub unsafe fn start_send_raw(&mut self, buf: *const [u16]) -> Result<(), ()> {
104 if (*buf).is_empty() {
106 return Err(());
107 }
108
109 if (((*buf).as_ptr() as usize) < hal::target_constants::SRAM_LOWER)
110 || (((*buf).as_ptr() as usize) > hal::target_constants::SRAM_UPPER)
111 {
112 return Err(());
113 }
114
115 compiler_fence(Ordering::SeqCst);
116
117 self.pwm.seq0.ptr.write(|w| w.bits((*buf).as_ptr() as u32));
118 self.pwm.seq0.cnt.write(|w| w.bits((*buf).len() as u32));
119 self.pwm.events_seqend[0].write(|w| w.bits(0));
120 self.pwm.tasks_seqstart[0].write(|w| w.bits(1));
121
122 Ok(())
123 }
124
125 pub unsafe fn set_seq1_raw(&mut self, buf: *const [u16]) -> Result<(), ()> {
130 if (*buf).is_empty() {
132 return Err(());
133 }
134
135 if (((*buf).as_ptr() as usize) < hal::target_constants::SRAM_LOWER)
136 || (((*buf).as_ptr() as usize) > hal::target_constants::SRAM_UPPER)
137 {
138 return Err(());
139 }
140
141 compiler_fence(Ordering::SeqCst);
142
143 self.pwm.seq1.ptr.write(|w| w.bits((*buf).as_ptr() as u32));
144 self.pwm.seq1.cnt.write(|w| w.bits((*buf).len() as u32));
145
146 Ok(())
147 }
148
149 pub fn is_done_raw(&self) -> bool {
154 self.pwm.events_seqend[0].read().bits() == 1
155 }
156
157 pub fn send_full_buf(&mut self, colors: &[RGB8], scratch: &mut [u16]) -> Result<(), ()> {
164 if scratch.len() < u16s_needed_slice(colors) {
165 return Err(());
166 }
167
168 for (color, buf) in colors.iter().zip(scratch.chunks_exact_mut(24)) {
169 fill_buf(color, buf)?;
170 }
171
172 let start = colors.len() * 24;
173 let end = start + 40;
174
175 for by in &mut scratch[start..end] {
176 *by = 0x8000;
177 }
178
179 self.pwm.loop_.write(|w| w.cnt().disabled());
181
182 unsafe {
184 self.start_send_raw(&scratch[..end])?;
185 }
186 while !self.is_done_raw() {}
187
188 Ok(())
189 }
190}
191
192pub fn u16s_needed_slice(slice: &[RGB8]) -> usize {
196 u16s_needed_ct(slice.len())
197}
198
199pub const fn u16s_needed_ct(leds: usize) -> usize {
203 leds * 24 + 40
204}
205
206impl<T> SmartLedsWrite for Pwm<T>
207where
208 T: sealed::Instance,
209{
210 type Error = ();
211 type Color = RGB8;
212 fn write<Iter, I>(&mut self, mut iterator: Iter) -> Result<(), ()>
214 where
215 Iter: Iterator<Item = I>,
216 I: Into<Self::Color>,
217 {
218 let mut buf_a = [0u16; 24];
220 let mut buf_b = [0u16; 24];
221
222 let mut blanks_fed = 0;
223 let mut toggle = false;
224
225 match (iterator.next(), iterator.next()) {
226 (Some(a), Some(b)) => {
227 fill_buf(&a.into(), &mut buf_a)?;
229 fill_buf(&b.into(), &mut buf_b)?;
230 }
231 (Some(a), None) => {
232 fill_buf(&a.into(), &mut buf_a)?;
234 buf_b.copy_from_slice(&[0x8000u16; 24]);
235 blanks_fed = 1;
236 }
237 (None, Some(_)) => {
238 return Err(());
240 }
241 _ => {
242 return Ok(());
244 }
245 }
246
247 unsafe {
248 self.pwm.loop_.write(|w| w.cnt().bits(1));
250 self.pwm.events_loopsdone.write(|w| w.bits(0));
251 self.set_seq1_raw(&buf_b)?;
252 self.start_send_raw(&buf_a)?;
253 }
254
255 #[derive(Copy, Clone)]
256 enum Data {
257 Pixel(RGB8),
258 Blank,
259 }
260
261 let new_iter = iterator
270 .map(|seq| Data::Pixel(seq.into()))
271 .chain([Data::Blank; 3].iter().cloned());
272
273 for seq in new_iter {
276 if !toggle {
277 while !self.is_done_raw() {}
282
283 match seq {
285 Data::Pixel(p) => {
286 fill_buf(&p, &mut buf_a)?;
287 }
288 Data::Blank => {
289 buf_a.copy_from_slice(&[0x8000u16; 24]);
290 blanks_fed += 1;
291 }
292 }
293
294 compiler_fence(Ordering::SeqCst);
295 } else {
296 while self.pwm.events_loopsdone.read().bits() == 0 {}
312
313 unsafe {
315 self.pwm.tasks_seqstart[0].write(|w| w.bits(1));
316 self.pwm.events_seqend[0].write(|w| w.bits(0));
317 self.pwm.events_loopsdone.write(|w| w.bits(0));
318 }
319
320 compiler_fence(Ordering::SeqCst);
321
322 match seq {
324 Data::Pixel(p) => {
325 fill_buf(&p, &mut buf_b)?;
326 }
327 Data::Blank => {
328 buf_b.copy_from_slice(&[0x8000u16; 24]);
329 blanks_fed += 1;
330 }
331 }
332 compiler_fence(Ordering::SeqCst);
333
334 if blanks_fed >= 2 {
336 break;
337 }
338 }
339 toggle = !toggle;
340 }
341
342 while self.pwm.events_loopsdone.read().bits() == 0 {}
344
345 Ok(())
346 }
347}
348
349mod sealed {
353 use core::ops::Deref;
354 pub trait Instance: Deref<Target = crate::hal::pac::pwm0::RegisterBlock> {}
355}
356
357impl sealed::Instance for pac::PWM0 {}
358
359#[cfg(not(any(feature = "52810")))]
360impl sealed::Instance for pac::PWM1 {}
361
362#[cfg(not(any(feature = "52810")))]
363impl sealed::Instance for pac::PWM2 {}
364
365#[cfg(not(any(feature = "52810", feature = "52832")))]
366impl sealed::Instance for pac::PWM3 {}