aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpennae <[email protected]>2023-05-05 19:49:34 +0200
committerpennae <[email protected]>2023-05-06 11:44:04 +0200
commit41ec4170a5ae9920fe31327252ba1bba754b6d9f (patch)
tree17a090cda266286958fe0ef5d32281cf647d4744
parent5f7ef8bed0d665c2f59351194fbc155203321d24 (diff)
rp/pio: add load_program, use_program
programs contain information we could pull from them directly and use to validate other configuration of the state machine instead of asking the user to pull them out and hand them to us bit by bit. unfortunately programs do not specify how many in or out bits they use, so we can only handle side-set and wrapping jumps like this. it's still something though.
-rw-r--r--embassy-rp/src/pio.rs128
-rw-r--r--examples/rp/src/bin/pio_async.rs25
-rw-r--r--examples/rp/src/bin/pio_dma.rs7
-rw-r--r--examples/rp/src/bin/pio_hd44780.rs16
-rw-r--r--examples/rp/src/bin/ws2812-pio.rs13
5 files changed, 74 insertions, 115 deletions
diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs
index ea6814fb8..f835fc8d9 100644
--- a/embassy-rp/src/pio.rs
+++ b/embassy-rp/src/pio.rs
@@ -9,12 +9,14 @@ use embassy_cortex_m::interrupt::{Interrupt, InterruptExt};
9use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; 9use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
10use embassy_sync::waitqueue::AtomicWaker; 10use embassy_sync::waitqueue::AtomicWaker;
11use pac::io::vals::Gpio0ctrlFuncsel; 11use pac::io::vals::Gpio0ctrlFuncsel;
12use pio::{SideSet, Wrap};
12 13
13use crate::dma::{Channel, Transfer, Word}; 14use crate::dma::{Channel, Transfer, Word};
14use crate::gpio::sealed::Pin as SealedPin; 15use crate::gpio::sealed::Pin as SealedPin;
15use crate::gpio::{self, AnyPin, Drive, Pull, SlewRate}; 16use crate::gpio::{self, AnyPin, Drive, Pull, SlewRate};
16use crate::pac::dma::vals::TreqSel; 17use crate::pac::dma::vals::TreqSel;
17use crate::{interrupt, pac, peripherals, RegExt}; 18use crate::relocate::RelocatedProgram;
19use crate::{interrupt, pac, peripherals, pio_instr_util, RegExt};
18 20
19struct Wakers([AtomicWaker; 12]); 21struct Wakers([AtomicWaker; 12]);
20 22
@@ -460,6 +462,13 @@ impl<'d, PIO: Instance, const SM: usize> Drop for StateMachine<'d, PIO, SM> {
460 } 462 }
461} 463}
462 464
465fn assert_consecutive<'d, PIO: Instance>(pins: &[&Pin<'d, PIO>]) {
466 for (p1, p2) in pins.iter().zip(pins.iter().skip(1)) {
467 // purposely does not allow wrap-around because we can't claim pins 30 and 31.
468 assert!(p1.pin() + 1 == p2.pin(), "pins must be consecutive");
469 }
470}
471
463impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> { 472impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> {
464 #[inline(always)] 473 #[inline(always)]
465 fn this_sm() -> crate::pac::pio::StateMachine { 474 fn this_sm() -> crate::pac::pio::StateMachine {
@@ -504,26 +513,26 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> {
504 } 513 }
505 } 514 }
506 515
507 pub fn set_side_enable(&self, enable: bool) { 516 /// Configures this state machine to use the given program, including jumping to the origin
508 unsafe { 517 /// of the program. The state machine is not started.
509 Self::this_sm().execctrl().modify(|w| w.set_side_en(enable)); 518 pub fn use_program(&mut self, prog: &LoadedProgram<'d, PIO>, side_set: &[&Pin<'d, PIO>]) {
510 } 519 assert!((prog.side_set.bits() - prog.side_set.optional() as u8) as usize == side_set.len());
511 } 520 assert_consecutive(side_set);
512
513 pub fn is_side_enabled(&self) -> bool {
514 unsafe { Self::this_sm().execctrl().read().side_en() }
515 }
516
517 pub fn set_side_pindir(&mut self, pindir: bool) {
518 unsafe { 521 unsafe {
519 Self::this_sm().execctrl().modify(|w| w.set_side_pindir(pindir)); 522 Self::this_sm().execctrl().modify(|w| {
523 w.set_side_en(prog.side_set.optional());
524 w.set_side_pindir(prog.side_set.pindirs());
525 w.set_wrap_bottom(prog.wrap.target);
526 w.set_wrap_top(prog.wrap.source);
527 });
528 Self::this_sm().pinctrl().modify(|w| {
529 w.set_sideset_count(prog.side_set.bits());
530 w.set_sideset_base(side_set.first().map_or(0, |p| p.pin()));
531 });
532 pio_instr_util::exec_jmp(self, prog.origin);
520 } 533 }
521 } 534 }
522 535
523 pub fn is_side_pindir(&self) -> bool {
524 unsafe { Self::this_sm().execctrl().read().side_pindir() }
525 }
526
527 pub fn set_jmp_pin(&mut self, pin: u8) { 536 pub fn set_jmp_pin(&mut self, pin: u8) {
528 unsafe { 537 unsafe {
529 Self::this_sm().execctrl().modify(|w| w.set_jmp_pin(pin)); 538 Self::this_sm().execctrl().modify(|w| w.set_jmp_pin(pin));
@@ -534,23 +543,6 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> {
534 unsafe { Self::this_sm().execctrl().read().jmp_pin() } 543 unsafe { Self::this_sm().execctrl().read().jmp_pin() }
535 } 544 }
536 545
537 pub fn set_wrap(&self, source: u8, target: u8) {
538 unsafe {
539 Self::this_sm().execctrl().modify(|w| {
540 w.set_wrap_top(source);
541 w.set_wrap_bottom(target)
542 });
543 }
544 }
545
546 /// Get wrapping addresses. Returns (source, target).
547 pub fn get_wrap(&self) -> (u8, u8) {
548 unsafe {
549 let r = Self::this_sm().execctrl().read();
550 (r.wrap_top(), r.wrap_bottom())
551 }
552 }
553
554 pub fn set_fifo_join(&mut self, join: FifoJoin) { 546 pub fn set_fifo_join(&mut self, join: FifoJoin) {
555 let (rx, tx) = match join { 547 let (rx, tx) = match join {
556 FifoJoin::Duplex => (false, false), 548 FifoJoin::Duplex => (false, false),
@@ -667,28 +659,6 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> {
667 pub fn get_addr(&self) -> u8 { 659 pub fn get_addr(&self) -> u8 {
668 unsafe { Self::this_sm().addr().read().addr() } 660 unsafe { Self::this_sm().addr().read().addr() }
669 } 661 }
670 pub fn set_sideset_count(&mut self, count: u8) {
671 unsafe {
672 Self::this_sm().pinctrl().modify(|w| w.set_sideset_count(count));
673 }
674 }
675
676 pub fn get_sideset_count(&self) -> u8 {
677 unsafe { Self::this_sm().pinctrl().read().sideset_count() }
678 }
679
680 pub fn set_sideset_base_pin(&mut self, base_pin: &Pin<PIO>) {
681 unsafe {
682 Self::this_sm().pinctrl().modify(|w| w.set_sideset_base(base_pin.pin()));
683 }
684 }
685
686 pub fn get_sideset_base(&self) -> u8 {
687 unsafe {
688 let r = Self::this_sm().pinctrl().read();
689 r.sideset_base()
690 }
691 }
692 662
693 /// Set the range of out pins affected by a set instruction. 663 /// Set the range of out pins affected by a set instruction.
694 pub fn set_set_range(&mut self, base: u8, count: u8) { 664 pub fn set_set_range(&mut self, base: u8, count: u8) {
@@ -799,8 +769,35 @@ pub struct InstanceMemory<'d, PIO: Instance> {
799 pio: PhantomData<&'d mut PIO>, 769 pio: PhantomData<&'d mut PIO>,
800} 770}
801 771
772pub struct LoadedProgram<'d, PIO: Instance> {
773 pub used_memory: InstanceMemory<'d, PIO>,
774 origin: u8,
775 wrap: Wrap,
776 side_set: SideSet,
777}
778
802impl<'d, PIO: Instance> Common<'d, PIO> { 779impl<'d, PIO: Instance> Common<'d, PIO> {
803 pub fn write_instr<I>(&mut self, start: usize, instrs: I) -> InstanceMemory<'d, PIO> 780 pub fn load_program<const SIZE: usize>(&mut self, prog: &RelocatedProgram<SIZE>) -> LoadedProgram<'d, PIO> {
781 match self.try_load_program(prog) {
782 Ok(r) => r,
783 Err(at) => panic!("Trying to write already used PIO instruction memory at {}", at),
784 }
785 }
786
787 pub fn try_load_program<const SIZE: usize>(
788 &mut self,
789 prog: &RelocatedProgram<SIZE>,
790 ) -> Result<LoadedProgram<'d, PIO>, usize> {
791 let used_memory = self.try_write_instr(prog.origin() as _, prog.code())?;
792 Ok(LoadedProgram {
793 used_memory,
794 origin: prog.origin(),
795 wrap: prog.wrap(),
796 side_set: prog.side_set(),
797 })
798 }
799
800 pub fn try_write_instr<I>(&mut self, start: usize, instrs: I) -> Result<InstanceMemory<'d, PIO>, usize>
804 where 801 where
805 I: Iterator<Item = u16>, 802 I: Iterator<Item = u16>,
806 { 803 {
@@ -808,11 +805,9 @@ impl<'d, PIO: Instance> Common<'d, PIO> {
808 for (i, instr) in instrs.enumerate() { 805 for (i, instr) in instrs.enumerate() {
809 let addr = (i + start) as u8; 806 let addr = (i + start) as u8;
810 let mask = 1 << (addr as usize); 807 let mask = 1 << (addr as usize);
811 assert!( 808 if self.instructions_used & mask != 0 {
812 self.instructions_used & mask == 0, 809 return Err(addr as usize);
813 "Trying to write already used PIO instruction memory at {}", 810 }
814 addr
815 );
816 unsafe { 811 unsafe {
817 PIO::PIO.instr_mem(addr as usize).write(|w| { 812 PIO::PIO.instr_mem(addr as usize).write(|w| {
818 w.set_instr_mem(instr); 813 w.set_instr_mem(instr);
@@ -821,15 +816,14 @@ impl<'d, PIO: Instance> Common<'d, PIO> {
821 used_mask |= mask; 816 used_mask |= mask;
822 } 817 }
823 self.instructions_used |= used_mask; 818 self.instructions_used |= used_mask;
824 InstanceMemory { 819 Ok(InstanceMemory {
825 used_mask, 820 used_mask,
826 pio: PhantomData, 821 pio: PhantomData,
827 } 822 })
828 } 823 }
829 824
830 /// Free instruction memory previously allocated with [`Common::write_instr`]. 825 /// Free instruction memory. This is always possible but unsafe if any
831 /// This is always possible but unsafe if any state machine is still using this 826 /// state machine is still using this bit of memory.
832 /// bit of memory.
833 pub unsafe fn free_instr(&mut self, instrs: InstanceMemory<PIO>) { 827 pub unsafe fn free_instr(&mut self, instrs: InstanceMemory<PIO>) {
834 self.instructions_used &= !instrs.used_mask; 828 self.instructions_used &= !instrs.used_mask;
835 } 829 }
diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs
index 461ea3ff9..9f47c2316 100644
--- a/examples/rp/src/bin/pio_async.rs
+++ b/examples/rp/src/bin/pio_async.rs
@@ -5,11 +5,10 @@ use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_rp::peripherals::PIO0; 6use embassy_rp::peripherals::PIO0;
7use embassy_rp::pio::{Common, Irq, Pio, PioPin, ShiftDirection, StateMachine}; 7use embassy_rp::pio::{Common, Irq, Pio, PioPin, ShiftDirection, StateMachine};
8use embassy_rp::pio_instr_util;
9use embassy_rp::relocate::RelocatedProgram; 8use embassy_rp::relocate::RelocatedProgram;
10use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
11 10
12fn setup_pio_task_sm0(pio: &mut Common<PIO0>, sm: &mut StateMachine<PIO0, 0>, pin: impl PioPin) { 11fn setup_pio_task_sm0<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, PIO0, 0>, pin: impl PioPin) {
13 // Setup sm0 12 // Setup sm0
14 13
15 // Send data serially to pin 14 // Send data serially to pin
@@ -22,15 +21,12 @@ fn setup_pio_task_sm0(pio: &mut Common<PIO0>, sm: &mut StateMachine<PIO0, 0>, pi
22 ); 21 );
23 22
24 let relocated = RelocatedProgram::new(&prg.program); 23 let relocated = RelocatedProgram::new(&prg.program);
24 sm.use_program(&pio.load_program(&relocated), &[]);
25 let out_pin = pio.make_pio_pin(pin); 25 let out_pin = pio.make_pio_pin(pin);
26 let pio_pins = [&out_pin]; 26 let pio_pins = [&out_pin];
27 sm.set_out_pins(&pio_pins); 27 sm.set_out_pins(&pio_pins);
28 pio.write_instr(relocated.origin() as usize, relocated.code());
29 pio_instr_util::exec_jmp(sm, relocated.origin());
30 sm.set_clkdiv((125e6 / 20.0 / 2e2 * 256.0) as u32); 28 sm.set_clkdiv((125e6 / 20.0 / 2e2 * 256.0) as u32);
31 sm.set_set_range(0, 1); 29 sm.set_set_range(0, 1);
32 let pio::Wrap { source, target } = relocated.wrap();
33 sm.set_wrap(source, target);
34 30
35 sm.set_autopull(true); 31 sm.set_autopull(true);
36 sm.set_out_shift_dir(ShiftDirection::Left); 32 sm.set_out_shift_dir(ShiftDirection::Left);
@@ -48,20 +44,16 @@ async fn pio_task_sm0(mut sm: StateMachine<'static, PIO0, 0>) {
48 } 44 }
49} 45}
50 46
51fn setup_pio_task_sm1(pio: &mut Common<PIO0>, sm: &mut StateMachine<PIO0, 1>) { 47fn setup_pio_task_sm1<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, PIO0, 1>) {
52 // Setupm sm1 48 // Setupm sm1
53 49
54 // Read 0b10101 repeatedly until ISR is full 50 // Read 0b10101 repeatedly until ISR is full
55 let prg = pio_proc::pio_asm!(".origin 8", "set x, 0x15", ".wrap_target", "in x, 5 [31]", ".wrap",); 51 let prg = pio_proc::pio_asm!(".origin 8", "set x, 0x15", ".wrap_target", "in x, 5 [31]", ".wrap",);
56 52
57 let relocated = RelocatedProgram::new(&prg.program); 53 let relocated = RelocatedProgram::new(&prg.program);
58 pio.write_instr(relocated.origin() as usize, relocated.code()); 54 sm.use_program(&pio.load_program(&relocated), &[]);
59 pio_instr_util::exec_jmp(sm, relocated.origin());
60 sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); 55 sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32);
61 sm.set_set_range(0, 0); 56 sm.set_set_range(0, 0);
62 let pio::Wrap { source, target } = relocated.wrap();
63 sm.set_wrap(source, target);
64
65 sm.set_autopush(true); 57 sm.set_autopush(true);
66 sm.set_in_shift_dir(ShiftDirection::Right); 58 sm.set_in_shift_dir(ShiftDirection::Right);
67} 59}
@@ -75,7 +67,7 @@ async fn pio_task_sm1(mut sm: StateMachine<'static, PIO0, 1>) {
75 } 67 }
76} 68}
77 69
78fn setup_pio_task_sm2(pio: &mut Common<PIO0>, sm: &mut StateMachine<PIO0, 2>) { 70fn setup_pio_task_sm2<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, PIO0, 2>) {
79 // Setup sm2 71 // Setup sm2
80 72
81 // Repeatedly trigger IRQ 3 73 // Repeatedly trigger IRQ 3
@@ -89,12 +81,7 @@ fn setup_pio_task_sm2(pio: &mut Common<PIO0>, sm: &mut StateMachine<PIO0, 2>) {
89 ".wrap", 81 ".wrap",
90 ); 82 );
91 let relocated = RelocatedProgram::new(&prg.program); 83 let relocated = RelocatedProgram::new(&prg.program);
92 pio.write_instr(relocated.origin() as usize, relocated.code()); 84 sm.use_program(&pio.load_program(&relocated), &[]);
93
94 let pio::Wrap { source, target } = relocated.wrap();
95 sm.set_wrap(source, target);
96
97 pio_instr_util::exec_jmp(sm, relocated.origin());
98 sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); 85 sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32);
99} 86}
100 87
diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs
index c664482e5..1c4e127c7 100644
--- a/examples/rp/src/bin/pio_dma.rs
+++ b/examples/rp/src/bin/pio_dma.rs
@@ -6,7 +6,7 @@ use embassy_executor::Spawner;
6use embassy_futures::join::join; 6use embassy_futures::join::join;
7use embassy_rp::pio::{Pio, ShiftDirection}; 7use embassy_rp::pio::{Pio, ShiftDirection};
8use embassy_rp::relocate::RelocatedProgram; 8use embassy_rp::relocate::RelocatedProgram;
9use embassy_rp::{pio_instr_util, Peripheral}; 9use embassy_rp::Peripheral;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12fn swap_nibbles(v: u32) -> u32 { 12fn swap_nibbles(v: u32) -> u32 {
@@ -38,11 +38,8 @@ async fn main(_spawner: Spawner) {
38 ); 38 );
39 39
40 let relocated = RelocatedProgram::new(&prg.program); 40 let relocated = RelocatedProgram::new(&prg.program);
41 common.write_instr(relocated.origin() as usize, relocated.code()); 41 sm.use_program(&common.load_program(&relocated), &[]);
42 pio_instr_util::exec_jmp(&mut sm, relocated.origin());
43 sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32); 42 sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32);
44 let pio::Wrap { source, target } = relocated.wrap();
45 sm.set_wrap(source, target);
46 sm.set_autopull(true); 43 sm.set_autopull(true);
47 sm.set_autopush(true); 44 sm.set_autopush(true);
48 sm.set_pull_threshold(32); 45 sm.set_pull_threshold(32);
diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs
index 17b2440cf..c3466b554 100644
--- a/examples/rp/src/bin/pio_hd44780.rs
+++ b/examples/rp/src/bin/pio_hd44780.rs
@@ -123,15 +123,9 @@ impl<'l> HD44780<'l> {
123 embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b11111); 123 embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b11111);
124 124
125 let relocated = RelocatedProgram::new(&prg.program); 125 let relocated = RelocatedProgram::new(&prg.program);
126 common.write_instr(relocated.origin() as usize, relocated.code()); 126 sm0.use_program(&common.load_program(&relocated), &[&e]);
127 embassy_rp::pio_instr_util::exec_jmp(&mut sm0, relocated.origin());
128 sm0.set_clkdiv(125 * 256); 127 sm0.set_clkdiv(125 * 256);
129 let pio::Wrap { source, target } = relocated.wrap();
130 sm0.set_wrap(source, target);
131 sm0.set_side_enable(true);
132 sm0.set_out_pins(&[&db4, &db5, &db6, &db7]); 128 sm0.set_out_pins(&[&db4, &db5, &db6, &db7]);
133 sm0.set_sideset_base_pin(&e);
134 sm0.set_sideset_count(2);
135 sm0.set_out_shift_dir(ShiftDirection::Left); 129 sm0.set_out_shift_dir(ShiftDirection::Left);
136 sm0.set_fifo_join(FifoJoin::TxOnly); 130 sm0.set_fifo_join(FifoJoin::TxOnly);
137 sm0.set_autopull(true); 131 sm0.set_autopull(true);
@@ -199,17 +193,11 @@ impl<'l> HD44780<'l> {
199 ); 193 );
200 194
201 let relocated = RelocatedProgram::new(&prg.program); 195 let relocated = RelocatedProgram::new(&prg.program);
202 common.write_instr(relocated.origin() as usize, relocated.code()); 196 sm0.use_program(&common.load_program(&relocated), &[&e]);
203 embassy_rp::pio_instr_util::exec_jmp(&mut sm0, relocated.origin());
204 let pio::Wrap { source, target } = relocated.wrap();
205 sm0.set_clkdiv(8 * 256); // ~64ns/insn 197 sm0.set_clkdiv(8 * 256); // ~64ns/insn
206 sm0.set_side_enable(false);
207 sm0.set_jmp_pin(db7pin); 198 sm0.set_jmp_pin(db7pin);
208 sm0.set_wrap(source, target);
209 sm0.set_set_pins(&[&rs, &rw]); 199 sm0.set_set_pins(&[&rs, &rw]);
210 sm0.set_out_pins(&[&db4, &db5, &db6, &db7]); 200 sm0.set_out_pins(&[&db4, &db5, &db6, &db7]);
211 sm0.set_sideset_base_pin(&e);
212 sm0.set_sideset_count(1);
213 sm0.set_out_shift_dir(ShiftDirection::Left); 201 sm0.set_out_shift_dir(ShiftDirection::Left);
214 sm0.set_fifo_join(FifoJoin::TxOnly); 202 sm0.set_fifo_join(FifoJoin::TxOnly);
215 203
diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs
index 2e6860d8b..889970541 100644
--- a/examples/rp/src/bin/ws2812-pio.rs
+++ b/examples/rp/src/bin/ws2812-pio.rs
@@ -5,7 +5,6 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_rp::pio::{Common, FifoJoin, Instance, Pio, PioPin, ShiftDirection, StateMachine}; 7use embassy_rp::pio::{Common, FifoJoin, Instance, Pio, PioPin, ShiftDirection, StateMachine};
8use embassy_rp::pio_instr_util;
9use embassy_rp::relocate::RelocatedProgram; 8use embassy_rp::relocate::RelocatedProgram;
10use embassy_time::{Duration, Timer}; 9use embassy_time::{Duration, Timer};
11use smart_leds::RGB8; 10use smart_leds::RGB8;
@@ -45,15 +44,11 @@ impl<'d, P: Instance, const S: usize> Ws2812<'d, P, S> {
45 44
46 let prg = a.assemble_with_wrap(wrap_source, wrap_target); 45 let prg = a.assemble_with_wrap(wrap_source, wrap_target);
47 46
48 let relocated = RelocatedProgram::new(&prg);
49 pio.write_instr(relocated.origin() as usize, relocated.code());
50 pio_instr_util::exec_jmp(&mut sm, relocated.origin());
51
52 // Pin config 47 // Pin config
53 let out_pin = pio.make_pio_pin(pin); 48 let out_pin = pio.make_pio_pin(pin);
54 sm.set_set_pins(&[&out_pin]); 49
55 sm.set_sideset_base_pin(&out_pin); 50 let relocated = RelocatedProgram::new(&prg);
56 sm.set_sideset_count(1); 51 sm.use_program(&pio.load_program(&relocated), &[&out_pin]);
57 52
58 // Clock config 53 // Clock config
59 // TODO CLOCK_FREQ should come from embassy_rp 54 // TODO CLOCK_FREQ should come from embassy_rp
@@ -70,8 +65,6 @@ impl<'d, P: Instance, const S: usize> Ws2812<'d, P, S> {
70 } 65 }
71 66
72 sm.set_clkdiv((int << 8) | frac); 67 sm.set_clkdiv((int << 8) | frac);
73 let pio::Wrap { source, target } = relocated.wrap();
74 sm.set_wrap(source, target);
75 68
76 // FIFO config 69 // FIFO config
77 sm.set_autopull(true); 70 sm.set_autopull(true);