aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkalkyl <[email protected]>2023-11-02 21:54:20 +0100
committerkalkyl <[email protected]>2023-11-02 21:54:20 +0100
commit44486c5b397e8f8f14a1b79825c9b4e611d1528f (patch)
treeaf26f4d8a02aec4afb64bd593581f63d36ea476d
parentd6f42eafad5582963a6d4c266f79425ed9b812e0 (diff)
rp: Add PIO rotary encoder example
-rw-r--r--examples/rp/src/bin/pio_rotary_encoder.rs91
1 files changed, 91 insertions, 0 deletions
diff --git a/examples/rp/src/bin/pio_rotary_encoder.rs b/examples/rp/src/bin/pio_rotary_encoder.rs
new file mode 100644
index 000000000..589f38a7b
--- /dev/null
+++ b/examples/rp/src/bin/pio_rotary_encoder.rs
@@ -0,0 +1,91 @@
1//! This example shows how to use the PIO module in the RP2040 to read a quadrature rotary encoder.
2
3#![no_std]
4#![no_main]
5#![feature(type_alias_impl_trait)]
6
7use defmt::info;
8use embassy_executor::Spawner;
9use embassy_rp::gpio::Pull;
10use embassy_rp::peripherals::PIO0;
11use embassy_rp::{bind_interrupts, pio};
12use fixed::traits::ToFixed;
13use pio::{Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftDirection, StateMachine};
14use {defmt_rtt as _, panic_probe as _};
15
16bind_interrupts!(struct Irqs {
17 PIO0_IRQ_0 => InterruptHandler<PIO0>;
18});
19
20pub struct PioEncoder<'d, T: Instance, const SM: usize> {
21 sm: StateMachine<'d, T, SM>,
22}
23
24impl<'d, T: Instance, const SM: usize> PioEncoder<'d, T, SM> {
25 pub fn new(
26 pio: &mut Common<'d, T>,
27 mut sm: StateMachine<'d, T, SM>,
28 pin_a: impl PioPin,
29 pin_b: impl PioPin,
30 ) -> Self {
31 let mut pin_a = pio.make_pio_pin(pin_a);
32 let mut pin_b = pio.make_pio_pin(pin_b);
33 pin_a.set_pull(Pull::Up);
34 pin_b.set_pull(Pull::Up);
35 sm.set_pin_dirs(pio::Direction::In, &[&pin_a, &pin_b]);
36
37 let prg = pio_proc::pio_asm!(
38 r#"
39 wait 1 pin 1
40 .wrap_target
41 wait 0 pin 1
42 in pins, 2
43 push
44 wait 1 pin 1
45 .wrap
46 "#
47 );
48
49 let mut cfg = Config::default();
50 cfg.set_in_pins(&[&pin_a, &pin_b]);
51 cfg.fifo_join = FifoJoin::RxOnly;
52 cfg.use_program(&pio.load_program(&prg.program), &[]);
53 cfg.shift_in.direction = ShiftDirection::Left;
54 cfg.clock_divider = 10_000.to_fixed();
55 sm.set_config(&cfg);
56 sm.set_enable(true);
57 Self { sm }
58 }
59
60 pub async fn read(&mut self) -> Direction {
61 loop {
62 match self.sm.rx().wait_pull().await {
63 0 => return Direction::CounterClockwise,
64 1 => return Direction::Clockwise,
65 _ => {}
66 }
67 }
68 }
69}
70
71pub enum Direction {
72 Clockwise,
73 CounterClockwise,
74}
75
76#[embassy_executor::main]
77async fn main(_spawner: Spawner) {
78 let p = embassy_rp::init(Default::default());
79 let Pio { mut common, sm0, .. } = Pio::new(p.PIO0, Irqs);
80
81 let mut encoder = PioEncoder::new(&mut common, sm0, p.PIN_4, p.PIN_5);
82
83 let mut count = 0;
84 loop {
85 info!("Count: {}", count);
86 count += match encoder.read().await {
87 Direction::Clockwise => 1,
88 Direction::CounterClockwise => -1,
89 };
90 }
91}