aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/rp/src/bin/pio_ws2812.rs (renamed from examples/rp/src/bin/ws2812-pio.rs)44
1 files changed, 33 insertions, 11 deletions
diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/pio_ws2812.rs
index f4c2d6313..26422421f 100644
--- a/examples/rp/src/bin/ws2812-pio.rs
+++ b/examples/rp/src/bin/pio_ws2812.rs
@@ -4,18 +4,30 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_rp::dma::{AnyChannel, Channel};
7use embassy_rp::pio::{Common, Config, FifoJoin, Instance, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine}; 8use embassy_rp::pio::{Common, Config, FifoJoin, Instance, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine};
8use embassy_rp::relocate::RelocatedProgram; 9use embassy_rp::relocate::RelocatedProgram;
10use embassy_rp::{clocks, into_ref, Peripheral, PeripheralRef};
9use embassy_time::{Duration, Timer}; 11use embassy_time::{Duration, Timer};
12use fixed::types::U24F8;
10use fixed_macro::fixed; 13use fixed_macro::fixed;
11use smart_leds::RGB8; 14use smart_leds::RGB8;
12use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
13pub struct Ws2812<'d, P: Instance, const S: usize> { 16
17pub struct Ws2812<'d, P: Instance, const S: usize, const N: usize> {
18 dma: PeripheralRef<'d, AnyChannel>,
14 sm: StateMachine<'d, P, S>, 19 sm: StateMachine<'d, P, S>,
15} 20}
16 21
17impl<'d, P: Instance, const S: usize> Ws2812<'d, P, S> { 22impl<'d, P: Instance, const S: usize, const N: usize> Ws2812<'d, P, S, N> {
18 pub fn new(mut pio: Common<'d, P>, mut sm: StateMachine<'d, P, S>, pin: impl PioPin) -> Self { 23 pub fn new(
24 pio: &mut Common<'d, P>,
25 mut sm: StateMachine<'d, P, S>,
26 dma: impl Peripheral<P = impl Channel> + 'd,
27 pin: impl PioPin,
28 ) -> Self {
29 into_ref!(dma);
30
19 // Setup sm0 31 // Setup sm0
20 32
21 // prepare the PIO program 33 // prepare the PIO program
@@ -48,13 +60,15 @@ impl<'d, P: Instance, const S: usize> Ws2812<'d, P, S> {
48 60
49 // Pin config 61 // Pin config
50 let out_pin = pio.make_pio_pin(pin); 62 let out_pin = pio.make_pio_pin(pin);
63 cfg.set_out_pins(&[&out_pin]);
64 cfg.set_set_pins(&[&out_pin]);
51 65
52 let relocated = RelocatedProgram::new(&prg); 66 let relocated = RelocatedProgram::new(&prg);
53 cfg.use_program(&pio.load_program(&relocated), &[&out_pin]); 67 cfg.use_program(&pio.load_program(&relocated), &[&out_pin]);
54 68
55 // Clock config, measured in kHz to avoid overflows 69 // Clock config, measured in kHz to avoid overflows
56 // TODO CLOCK_FREQ should come from embassy_rp 70 // TODO CLOCK_FREQ should come from embassy_rp
57 let clock_freq = fixed!(125_000: U24F8); 71 let clock_freq = U24F8::from_num(clocks::clk_sys_freq() / 1000);
58 let ws2812_freq = fixed!(800: U24F8); 72 let ws2812_freq = fixed!(800: U24F8);
59 let bit_freq = ws2812_freq * CYCLES_PER_BIT; 73 let bit_freq = ws2812_freq * CYCLES_PER_BIT;
60 cfg.clock_divider = clock_freq / bit_freq; 74 cfg.clock_divider = clock_freq / bit_freq;
@@ -70,14 +84,22 @@ impl<'d, P: Instance, const S: usize> Ws2812<'d, P, S> {
70 sm.set_config(&cfg); 84 sm.set_config(&cfg);
71 sm.set_enable(true); 85 sm.set_enable(true);
72 86
73 Self { sm } 87 Self {
88 dma: dma.map_into(),
89 sm,
90 }
74 } 91 }
75 92
76 pub async fn write(&mut self, colors: &[RGB8]) { 93 pub async fn write(&mut self, colors: &[RGB8; N]) {
77 for color in colors { 94 // Precompute the word bytes from the colors
78 let word = (u32::from(color.g) << 24) | (u32::from(color.r) << 16) | (u32::from(color.b) << 8); 95 let mut words = [0u32; N];
79 self.sm.tx().wait_push(word).await; 96 for i in 0..N {
97 let word = (u32::from(colors[i].g) << 24) | (u32::from(colors[i].r) << 16) | (u32::from(colors[i].b) << 8);
98 words[i] = word;
80 } 99 }
100
101 // DMA transfer
102 self.sm.tx().dma_push(self.dma.reborrow(), &words).await;
81 } 103 }
82} 104}
83 105
@@ -101,7 +123,7 @@ async fn main(_spawner: Spawner) {
101 info!("Start"); 123 info!("Start");
102 let p = embassy_rp::init(Default::default()); 124 let p = embassy_rp::init(Default::default());
103 125
104 let Pio { common, sm0, .. } = Pio::new(p.PIO0); 126 let Pio { mut common, sm0, .. } = Pio::new(p.PIO0);
105 127
106 // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit 128 // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit
107 // feather boards for the 2040 both have one built in. 129 // feather boards for the 2040 both have one built in.
@@ -110,7 +132,7 @@ async fn main(_spawner: Spawner) {
110 132
111 // For the thing plus, use pin 8 133 // For the thing plus, use pin 8
112 // For the feather, use pin 16 134 // For the feather, use pin 16
113 let mut ws2812 = Ws2812::new(common, sm0, p.PIN_8); 135 let mut ws2812 = Ws2812::new(&mut common, sm0, p.DMA_CH0, p.PIN_16);
114 136
115 // Loop forever making RGB values and pushing them out to the WS2812. 137 // Loop forever making RGB values and pushing them out to the WS2812.
116 loop { 138 loop {