aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorChuck Davis <[email protected]>2023-05-03 21:07:28 -0500
committerGitHub <[email protected]>2023-05-03 21:07:28 -0500
commit91d1fff4edf41a251044ccde03af4ccf8a135f65 (patch)
treef76426657679c7a400894f71278086ac83dfd554 /examples
parent629e0ea595b28d89aad3f953b7190b04d78ff9d3 (diff)
parent374c92a4f0fda2932a0a86e5dcc3dc33651a48c7 (diff)
Merge branch 'embassy-rs:master' into master
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 {