diff options
| author | kalkyl <[email protected]> | 2023-11-02 21:54:20 +0100 |
|---|---|---|
| committer | kalkyl <[email protected]> | 2023-11-02 21:54:20 +0100 |
| commit | 44486c5b397e8f8f14a1b79825c9b4e611d1528f (patch) | |
| tree | af26f4d8a02aec4afb64bd593581f63d36ea476d /examples | |
| parent | d6f42eafad5582963a6d4c266f79425ed9b812e0 (diff) | |
rp: Add PIO rotary encoder example
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/rp/src/bin/pio_rotary_encoder.rs | 91 |
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 | |||
| 7 | use defmt::info; | ||
| 8 | use embassy_executor::Spawner; | ||
| 9 | use embassy_rp::gpio::Pull; | ||
| 10 | use embassy_rp::peripherals::PIO0; | ||
| 11 | use embassy_rp::{bind_interrupts, pio}; | ||
| 12 | use fixed::traits::ToFixed; | ||
| 13 | use pio::{Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftDirection, StateMachine}; | ||
| 14 | use {defmt_rtt as _, panic_probe as _}; | ||
| 15 | |||
| 16 | bind_interrupts!(struct Irqs { | ||
| 17 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 18 | }); | ||
| 19 | |||
| 20 | pub struct PioEncoder<'d, T: Instance, const SM: usize> { | ||
| 21 | sm: StateMachine<'d, T, SM>, | ||
| 22 | } | ||
| 23 | |||
| 24 | impl<'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 | |||
| 71 | pub enum Direction { | ||
| 72 | Clockwise, | ||
| 73 | CounterClockwise, | ||
| 74 | } | ||
| 75 | |||
| 76 | #[embassy_executor::main] | ||
| 77 | async 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 | } | ||
