From 88f80a071574a0cf2f7fd98356e9ae3567687fe7 Mon Sep 17 00:00:00 2001 From: Krzysztof Mazur Date: Tue, 26 Nov 2024 20:41:34 +0100 Subject: [PATCH] Add flushing PIO data [Problem] When providing data fast enough, multiple frames could be concatenated since we only waited 60 microseconds after the last bytes were pushed to the PIO, not since the last bytes were actually pushed to the neopixels. [Solution] "Flush" the PIO after pushing the last bytes, by waiting until it's empty. --- src/frame.rs | 3 ++- src/ws2812.rs | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/frame.rs b/src/frame.rs index ac791aa..64ce02c 100644 --- a/src/frame.rs +++ b/src/frame.rs @@ -42,7 +42,8 @@ where for (r, g, b) in cons.pop_iter().skip(2).take(len).tuples() { ws2812.write(r, g, b); } - + // wait for the state machine to write all bytes + ws2812.flush(); // let the neopixels latch on Timer::after_micros(60).await; } diff --git a/src/ws2812.rs b/src/ws2812.rs index 10884cd..da277d5 100644 --- a/src/ws2812.rs +++ b/src/ws2812.rs @@ -96,6 +96,15 @@ impl<'d, P: Instance, const S: usize> Ws2812<'d, P, S> { self.sm.tx().dma_push(self.dma.reborrow(), data).await; } + // see https://github.com/rp-rs/ws2812-pio-rs/blob/944494ca9dad73933f700408c3054c8f14c78998/src/lib.rs#L262-L263 + pub fn flush(&mut self) { + // clear stalled flag first + self.sm.tx().stalled(); + while !self.sm.tx().empty() && !self.sm.tx().stalled() { + cortex_m::asm::nop(); + } + } + pub fn write(&mut self, r: u8, g: u8, b: u8) { let word = convert_colors_to_word(r, g, b); // we need to watch out not to overflow the FIFO, see: