aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2023-05-02 18:03:00 +0000
committerGitHub <[email protected]>2023-05-02 18:03:00 +0000
commit2afa08c9236d386cae7920d9e7f20803a2c6b433 (patch)
tree9b744a8435eabd338109f44fd2c69ec6b06eb5c3 /examples
parentb2047c435133c6bd11918e89af81cab75c3354f1 (diff)
parent7a36072a15b2164a903ae3f36ee251eaf311216d (diff)
Merge #1425
1425: rp pio, round 2 r=Dirbaio a=pennae another round of bugfixes for pio, and some refactoring. in the end we'd like to make pio look like all the other modules and not expose traits that provide all the methods of a type, but put them onto the type itself. traits only make much sense, even if we added an AnyPio and merged the types for the member state machines (at the cost of at least a u8 per member of Pio). Co-authored-by: pennae <[email protected]>
Diffstat (limited to 'examples')
-rw-r--r--examples/rp/src/bin/pio_async.rs34
-rw-r--r--examples/rp/src/bin/pio_dma.rs10
-rw-r--r--examples/rp/src/bin/pio_hd44780.rs243
-rw-r--r--examples/rp/src/bin/ws2812-pio.rs15
4 files changed, 276 insertions, 26 deletions
diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs
index 1b075b8fd..5fea7034b 100644
--- a/examples/rp/src/bin/pio_async.rs
+++ b/examples/rp/src/bin/pio_async.rs
@@ -4,15 +4,13 @@
4use defmt::info; 4use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_rp::gpio::{AnyPin, Pin}; 6use embassy_rp::gpio::{AnyPin, Pin};
7use embassy_rp::pio::{ 7use embassy_rp::peripherals::PIO0;
8 Pio0, PioCommon, PioCommonInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0, 8use embassy_rp::pio::{Pio, PioCommon, PioStateMachine, PioStateMachineInstance, ShiftDirection};
9 Sm1, Sm2,
10};
11use embassy_rp::pio_instr_util; 9use embassy_rp::pio_instr_util;
12use embassy_rp::relocate::RelocatedProgram; 10use embassy_rp::relocate::RelocatedProgram;
13use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
14 12
15fn setup_pio_task_sm0(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachineInstance<Pio0, Sm0>, pin: AnyPin) { 13fn setup_pio_task_sm0(pio: &mut PioCommon<PIO0>, sm: &mut PioStateMachineInstance<PIO0, 0>, pin: AnyPin) {
16 // Setup sm0 14 // Setup sm0
17 15
18 // Send data serially to pin 16 // Send data serially to pin
@@ -40,7 +38,7 @@ fn setup_pio_task_sm0(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachin
40} 38}
41 39
42#[embassy_executor::task] 40#[embassy_executor::task]
43async fn pio_task_sm0(mut sm: PioStateMachineInstance<Pio0, Sm0>) { 41async fn pio_task_sm0(mut sm: PioStateMachineInstance<'static, PIO0, 0>) {
44 sm.set_enable(true); 42 sm.set_enable(true);
45 43
46 let mut v = 0x0f0caffa; 44 let mut v = 0x0f0caffa;
@@ -51,7 +49,7 @@ async fn pio_task_sm0(mut sm: PioStateMachineInstance<Pio0, Sm0>) {
51 } 49 }
52} 50}
53 51
54fn setup_pio_task_sm1(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachineInstance<Pio0, Sm1>) { 52fn setup_pio_task_sm1(pio: &mut PioCommon<PIO0>, sm: &mut PioStateMachineInstance<PIO0, 1>) {
55 // Setupm sm1 53 // Setupm sm1
56 54
57 // Read 0b10101 repeatedly until ISR is full 55 // Read 0b10101 repeatedly until ISR is full
@@ -70,7 +68,7 @@ fn setup_pio_task_sm1(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachin
70} 68}
71 69
72#[embassy_executor::task] 70#[embassy_executor::task]
73async fn pio_task_sm1(mut sm: PioStateMachineInstance<Pio0, Sm1>) { 71async fn pio_task_sm1(mut sm: PioStateMachineInstance<'static, PIO0, 1>) {
74 sm.set_enable(true); 72 sm.set_enable(true);
75 loop { 73 loop {
76 let rx = sm.wait_pull().await; 74 let rx = sm.wait_pull().await;
@@ -78,7 +76,7 @@ async fn pio_task_sm1(mut sm: PioStateMachineInstance<Pio0, Sm1>) {
78 } 76 }
79} 77}
80 78
81fn setup_pio_task_sm2(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachineInstance<Pio0, Sm2>) { 79fn setup_pio_task_sm2(pio: &mut PioCommon<PIO0>, sm: &mut PioStateMachineInstance<PIO0, 2>) {
82 // Setup sm2 80 // Setup sm2
83 81
84 // Repeatedly trigger IRQ 3 82 // Repeatedly trigger IRQ 3
@@ -102,7 +100,7 @@ fn setup_pio_task_sm2(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachin
102} 100}
103 101
104#[embassy_executor::task] 102#[embassy_executor::task]
105async fn pio_task_sm2(mut sm: PioStateMachineInstance<Pio0, Sm2>) { 103async fn pio_task_sm2(mut sm: PioStateMachineInstance<'static, PIO0, 2>) {
106 sm.set_enable(true); 104 sm.set_enable(true);
107 loop { 105 loop {
108 sm.wait_irq(3).await; 106 sm.wait_irq(3).await;
@@ -115,11 +113,17 @@ async fn main(spawner: Spawner) {
115 let p = embassy_rp::init(Default::default()); 113 let p = embassy_rp::init(Default::default());
116 let pio = p.PIO0; 114 let pio = p.PIO0;
117 115
118 let (mut pio0, mut sm0, mut sm1, mut sm2, ..) = pio.split(); 116 let Pio {
119 117 mut common,
120 setup_pio_task_sm0(&mut pio0, &mut sm0, p.PIN_0.degrade()); 118 mut sm0,
121 setup_pio_task_sm1(&mut pio0, &mut sm1); 119 mut sm1,
122 setup_pio_task_sm2(&mut pio0, &mut sm2); 120 mut sm2,
121 ..
122 } = Pio::new(pio);
123
124 setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0.degrade());
125 setup_pio_task_sm1(&mut common, &mut sm1);
126 setup_pio_task_sm2(&mut common, &mut sm2);
123 spawner.spawn(pio_task_sm0(sm0)).unwrap(); 127 spawner.spawn(pio_task_sm0(sm0)).unwrap();
124 spawner.spawn(pio_task_sm1(sm1)).unwrap(); 128 spawner.spawn(pio_task_sm1(sm1)).unwrap();
125 spawner.spawn(pio_task_sm2(sm2)).unwrap(); 129 spawner.spawn(pio_task_sm2(sm2)).unwrap();
diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs
index 7d4919f75..0f1f6df12 100644
--- a/examples/rp/src/bin/pio_dma.rs
+++ b/examples/rp/src/bin/pio_dma.rs
@@ -4,7 +4,7 @@
4use defmt::info; 4use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_futures::join::join; 6use embassy_futures::join::join;
7use embassy_rp::pio::{PioCommon, PioPeripheral, PioStateMachine, ShiftDirection}; 7use embassy_rp::pio::{Pio, PioStateMachine, ShiftDirection};
8use embassy_rp::relocate::RelocatedProgram; 8use embassy_rp::relocate::RelocatedProgram;
9use embassy_rp::{pio_instr_util, Peripheral}; 9use embassy_rp::{pio_instr_util, Peripheral};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
@@ -19,7 +19,11 @@ fn swap_nibbles(v: u32) -> u32 {
19async fn main(_spawner: Spawner) { 19async fn main(_spawner: Spawner) {
20 let p = embassy_rp::init(Default::default()); 20 let p = embassy_rp::init(Default::default());
21 let pio = p.PIO0; 21 let pio = p.PIO0;
22 let (mut pio0, mut sm, ..) = pio.split(); 22 let Pio {
23 mut common,
24 sm0: mut sm,
25 ..
26 } = Pio::new(pio);
23 27
24 let prg = pio_proc::pio_asm!( 28 let prg = pio_proc::pio_asm!(
25 ".origin 0", 29 ".origin 0",
@@ -34,7 +38,7 @@ async fn main(_spawner: Spawner) {
34 ); 38 );
35 39
36 let relocated = RelocatedProgram::new(&prg.program); 40 let relocated = RelocatedProgram::new(&prg.program);
37 pio0.write_instr(relocated.origin() as usize, relocated.code()); 41 common.write_instr(relocated.origin() as usize, relocated.code());
38 pio_instr_util::exec_jmp(&mut sm, relocated.origin()); 42 pio_instr_util::exec_jmp(&mut sm, relocated.origin());
39 sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32); 43 sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32);
40 let pio::Wrap { source, target } = relocated.wrap(); 44 let pio::Wrap { source, target } = relocated.wrap();
diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs
new file mode 100644
index 000000000..59b4c1f52
--- /dev/null
+++ b/examples/rp/src/bin/pio_hd44780.rs
@@ -0,0 +1,243 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use core::fmt::Write;
6
7use embassy_executor::Spawner;
8use embassy_rp::dma::{AnyChannel, Channel};
9use embassy_rp::gpio::Pin;
10use embassy_rp::peripherals::PIO0;
11use embassy_rp::pio::{FifoJoin, Pio, PioStateMachine, PioStateMachineInstance, ShiftDirection};
12use embassy_rp::pwm::{Config, Pwm};
13use embassy_rp::relocate::RelocatedProgram;
14use embassy_rp::{into_ref, Peripheral, PeripheralRef};
15use embassy_time::{Duration, Instant, Timer};
16use {defmt_rtt as _, panic_probe as _};
17
18#[embassy_executor::main]
19async fn main(_spawner: Spawner) {
20 // this test assumes a 2x16 HD44780 display attached as follow:
21 // rs = PIN0
22 // rw = PIN1
23 // e = PIN2
24 // db4 = PIN3
25 // db5 = PIN4
26 // db6 = PIN5
27 // db7 = PIN6
28 // additionally a pwm signal for a bias voltage charge pump is provided on pin 15,
29 // allowing direct connection of the display to the RP2040 without level shifters.
30 let p = embassy_rp::init(Default::default());
31
32 let _pwm = Pwm::new_output_b(p.PWM_CH7, p.PIN_15, {
33 let mut c = Config::default();
34 c.divider = 125.into();
35 c.top = 100;
36 c.compare_b = 50;
37 c
38 });
39
40 let mut hd = HD44780::new(
41 p.PIO0, p.DMA_CH3, p.PIN_0, p.PIN_1, p.PIN_2, p.PIN_3, p.PIN_4, p.PIN_5, p.PIN_6,
42 )
43 .await;
44
45 loop {
46 struct Buf<const N: usize>([u8; N], usize);
47 impl<const N: usize> Write for Buf<N> {
48 fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
49 for b in s.as_bytes() {
50 if self.1 >= N {
51 return Err(core::fmt::Error);
52 }
53 self.0[self.1] = *b;
54 self.1 += 1;
55 }
56 Ok(())
57 }
58 }
59 let mut buf = Buf([0; 16], 0);
60 write!(buf, "up {}s", Instant::now().as_micros() as f32 / 1e6).unwrap();
61 hd.add_line(&buf.0[0..buf.1]).await;
62 Timer::after(Duration::from_secs(1)).await;
63 }
64}
65
66pub struct HD44780<'l> {
67 dma: PeripheralRef<'l, AnyChannel>,
68 sm: PioStateMachineInstance<'l, PIO0, 0>,
69
70 buf: [u8; 40],
71}
72
73impl<'l> HD44780<'l> {
74 pub async fn new(
75 pio: impl Peripheral<P = PIO0> + 'l,
76 dma: impl Peripheral<P = impl Channel> + 'l,
77 rs: impl Pin,
78 rw: impl Pin,
79 e: impl Pin,
80 db4: impl Pin,
81 db5: impl Pin,
82 db6: impl Pin,
83 db7: impl Pin,
84 ) -> HD44780<'l> {
85 into_ref!(dma);
86
87 let db7pin = db7.pin();
88 let Pio {
89 mut common, mut sm0, ..
90 } = Pio::new(pio);
91
92 // takes command words (<wait:24> <command:4> <0:4>)
93 let prg = pio_proc::pio_asm!(
94 r#"
95 .side_set 1 opt
96
97 loop:
98 out x, 24
99 delay:
100 jmp x--, delay
101 out pins, 4 side 1
102 out null, 4 side 0
103 jmp !osre, loop
104 irq 0
105 "#,
106 );
107
108 let rs = common.make_pio_pin(rs);
109 let rw = common.make_pio_pin(rw);
110 let e = common.make_pio_pin(e);
111 let db4 = common.make_pio_pin(db4);
112 let db5 = common.make_pio_pin(db5);
113 let db6 = common.make_pio_pin(db6);
114 let db7 = common.make_pio_pin(db7);
115
116 sm0.set_set_pins(&[&rs, &rw]);
117 embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b11);
118 sm0.set_set_pins(&[&e]);
119 embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b1);
120 sm0.set_set_pins(&[&db4, &db5, &db6, &db7]);
121 embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b11111);
122
123 let relocated = RelocatedProgram::new(&prg.program);
124 common.write_instr(relocated.origin() as usize, relocated.code());
125 embassy_rp::pio_instr_util::exec_jmp(&mut sm0, relocated.origin());
126 sm0.set_clkdiv(125 * 256);
127 let pio::Wrap { source, target } = relocated.wrap();
128 sm0.set_wrap(source, target);
129 sm0.set_side_enable(true);
130 sm0.set_out_pins(&[&db4, &db5, &db6, &db7]);
131 sm0.set_sideset_base_pin(&e);
132 sm0.set_sideset_count(2);
133 sm0.set_out_shift_dir(ShiftDirection::Left);
134 sm0.set_fifo_join(FifoJoin::TxOnly);
135 sm0.set_autopull(true);
136 sm0.set_pull_threshold(32);
137
138 sm0.set_enable(true);
139 // init to 8 bit thrice
140 sm0.push_tx((50000 << 8) | 0x30);
141 sm0.push_tx((5000 << 8) | 0x30);
142 sm0.push_tx((200 << 8) | 0x30);
143 // init 4 bit
144 sm0.push_tx((200 << 8) | 0x20);
145 // set font and lines
146 sm0.push_tx((50 << 8) | 0x20);
147 sm0.push_tx(0b1100_0000);
148
149 sm0.wait_irq(0).await;
150 sm0.set_enable(false);
151
152 // takes command sequences (<rs:1> <count:7>, data...)
153 // many side sets are only there to free up a delay bit!
154 let prg = pio_proc::pio_asm!(
155 r#"
156 .origin 7
157 .side_set 1
158
159 .wrap_target
160 pull side 0
161 out x 1 side 0 ; !rs
162 out y 7 side 0 ; #data - 1
163
164 ; rs/rw to e: >= 60ns
165 ; e high time: >= 500ns
166 ; e low time: >= 500ns
167 ; read data valid after e falling: ~5ns
168 ; write data hold after e falling: ~10ns
169
170 loop:
171 pull side 0
172 jmp !x data side 0
173 command:
174 set pins 0b00 side 0
175 jmp shift side 0
176 data:
177 set pins 0b01 side 0
178 shift:
179 out pins 4 side 1 [9]
180 nop side 0 [9]
181 out pins 4 side 1 [9]
182 mov osr null side 0 [7]
183 out pindirs 4 side 0
184 set pins 0b10 side 0
185 busy:
186 nop side 1 [9]
187 jmp pin more side 0 [9]
188 mov osr ~osr side 1 [9]
189 nop side 0 [4]
190 out pindirs 4 side 0
191 jmp y-- loop side 0
192 .wrap
193 more:
194 nop side 1 [9]
195 jmp busy side 0 [9]
196 "#
197 );
198
199 let relocated = RelocatedProgram::new(&prg.program);
200 common.write_instr(relocated.origin() as usize, relocated.code());
201 embassy_rp::pio_instr_util::exec_jmp(&mut sm0, relocated.origin());
202 let pio::Wrap { source, target } = relocated.wrap();
203 sm0.set_clkdiv(8 * 256); // ~64ns/insn
204 sm0.set_side_enable(false);
205 sm0.set_jmp_pin(db7pin);
206 sm0.set_wrap(source, target);
207 sm0.set_set_pins(&[&rs, &rw]);
208 sm0.set_out_pins(&[&db4, &db5, &db6, &db7]);
209 sm0.set_sideset_base_pin(&e);
210 sm0.set_sideset_count(1);
211 sm0.set_out_shift_dir(ShiftDirection::Left);
212 sm0.set_fifo_join(FifoJoin::TxOnly);
213
214 sm0.set_enable(true);
215
216 // display on and cursor on and blinking, reset display
217 sm0.dma_push(dma.reborrow(), &[0x81u8, 0x0f, 1]).await;
218
219 Self {
220 dma: dma.map_into(),
221 sm: sm0,
222 buf: [0x20; 40],
223 }
224 }
225
226 pub async fn add_line(&mut self, s: &[u8]) {
227 // move cursor to 0:0, prepare 16 characters
228 self.buf[..3].copy_from_slice(&[0x80, 0x80, 15]);
229 // move line 2 up
230 self.buf.copy_within(22..38, 3);
231 // move cursor to 1:0, prepare 16 characters
232 self.buf[19..22].copy_from_slice(&[0x80, 0xc0, 15]);
233 // file line 2 with spaces
234 self.buf[22..38].fill(0x20);
235 // copy input line
236 let len = s.len().min(16);
237 self.buf[22..22 + len].copy_from_slice(&s[0..len]);
238 // set cursor to 1:15
239 self.buf[38..].copy_from_slice(&[0x80, 0xcf]);
240
241 self.sm.dma_push(self.dma.reborrow(), &self.buf).await;
242 }
243}
diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs
index 041e8ae11..0975559d7 100644
--- a/examples/rp/src/bin/ws2812-pio.rs
+++ b/examples/rp/src/bin/ws2812-pio.rs
@@ -6,20 +6,19 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_rp::gpio::{self, Pin}; 7use embassy_rp::gpio::{self, Pin};
8use embassy_rp::pio::{ 8use embassy_rp::pio::{
9 FifoJoin, PioCommon, PioCommonInstance, PioInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance, 9 FifoJoin, Pio, PioCommon, PioInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection,
10 ShiftDirection, SmInstance,
11}; 10};
12use embassy_rp::pio_instr_util; 11use embassy_rp::pio_instr_util;
13use embassy_rp::relocate::RelocatedProgram; 12use embassy_rp::relocate::RelocatedProgram;
14use embassy_time::{Duration, Timer}; 13use embassy_time::{Duration, Timer};
15use smart_leds::RGB8; 14use smart_leds::RGB8;
16use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
17pub struct Ws2812<P: PioInstance, S: SmInstance> { 16pub struct Ws2812<'d, P: PioInstance, const S: usize> {
18 sm: PioStateMachineInstance<P, S>, 17 sm: PioStateMachineInstance<'d, P, S>,
19} 18}
20 19
21impl<P: PioInstance, S: SmInstance> Ws2812<P, S> { 20impl<'d, P: PioInstance, const S: usize> Ws2812<'d, P, S> {
22 pub fn new(mut pio: PioCommonInstance<P>, mut sm: PioStateMachineInstance<P, S>, pin: gpio::AnyPin) -> Self { 21 pub fn new(mut pio: PioCommon<'d, P>, mut sm: PioStateMachineInstance<'d, P, S>, pin: gpio::AnyPin) -> Self {
23 // Setup sm0 22 // Setup sm0
24 23
25 // prepare the PIO program 24 // prepare the PIO program
@@ -116,7 +115,7 @@ async fn main(_spawner: Spawner) {
116 info!("Start"); 115 info!("Start");
117 let p = embassy_rp::init(Default::default()); 116 let p = embassy_rp::init(Default::default());
118 117
119 let (pio0, sm0, _sm1, _sm2, _sm3) = p.PIO0.split(); 118 let Pio { common, sm0, .. } = Pio::new(p.PIO0);
120 119
121 // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit 120 // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit
122 // feather boards for the 2040 both have one built in. 121 // feather boards for the 2040 both have one built in.
@@ -125,7 +124,7 @@ async fn main(_spawner: Spawner) {
125 124
126 // For the thing plus, use pin 8 125 // For the thing plus, use pin 8
127 // For the feather, use pin 16 126 // For the feather, use pin 16
128 let mut ws2812 = Ws2812::new(pio0, sm0, p.PIN_8.degrade()); 127 let mut ws2812 = Ws2812::new(common, sm0, p.PIN_8.degrade());
129 128
130 // Loop forever making RGB values and pushing them out to the WS2812. 129 // Loop forever making RGB values and pushing them out to the WS2812.
131 loop { 130 loop {