From 44486c5b397e8f8f14a1b79825c9b4e611d1528f Mon Sep 17 00:00:00 2001 From: kalkyl Date: Thu, 2 Nov 2023 21:54:20 +0100 Subject: [PATCH 1/2] rp: Add PIO rotary encoder example --- examples/rp/src/bin/pio_rotary_encoder.rs | 91 +++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 examples/rp/src/bin/pio_rotary_encoder.rs 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 00000000..589f38a7 --- /dev/null +++ b/examples/rp/src/bin/pio_rotary_encoder.rs @@ -0,0 +1,91 @@ +//! This example shows how to use the PIO module in the RP2040 to read a quadrature rotary encoder. + +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::info; +use embassy_executor::Spawner; +use embassy_rp::gpio::Pull; +use embassy_rp::peripherals::PIO0; +use embassy_rp::{bind_interrupts, pio}; +use fixed::traits::ToFixed; +use pio::{Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftDirection, StateMachine}; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + +pub struct PioEncoder<'d, T: Instance, const SM: usize> { + sm: StateMachine<'d, T, SM>, +} + +impl<'d, T: Instance, const SM: usize> PioEncoder<'d, T, SM> { + pub fn new( + pio: &mut Common<'d, T>, + mut sm: StateMachine<'d, T, SM>, + pin_a: impl PioPin, + pin_b: impl PioPin, + ) -> Self { + let mut pin_a = pio.make_pio_pin(pin_a); + let mut pin_b = pio.make_pio_pin(pin_b); + pin_a.set_pull(Pull::Up); + pin_b.set_pull(Pull::Up); + sm.set_pin_dirs(pio::Direction::In, &[&pin_a, &pin_b]); + + let prg = pio_proc::pio_asm!( + r#" + wait 1 pin 1 + .wrap_target + wait 0 pin 1 + in pins, 2 + push + wait 1 pin 1 + .wrap + "# + ); + + let mut cfg = Config::default(); + cfg.set_in_pins(&[&pin_a, &pin_b]); + cfg.fifo_join = FifoJoin::RxOnly; + cfg.use_program(&pio.load_program(&prg.program), &[]); + cfg.shift_in.direction = ShiftDirection::Left; + cfg.clock_divider = 10_000.to_fixed(); + sm.set_config(&cfg); + sm.set_enable(true); + Self { sm } + } + + pub async fn read(&mut self) -> Direction { + loop { + match self.sm.rx().wait_pull().await { + 0 => return Direction::CounterClockwise, + 1 => return Direction::Clockwise, + _ => {} + } + } + } +} + +pub enum Direction { + Clockwise, + CounterClockwise, +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let Pio { mut common, sm0, .. } = Pio::new(p.PIO0, Irqs); + + let mut encoder = PioEncoder::new(&mut common, sm0, p.PIN_4, p.PIN_5); + + let mut count = 0; + loop { + info!("Count: {}", count); + count += match encoder.read().await { + Direction::Clockwise => 1, + Direction::CounterClockwise => -1, + }; + } +} From ec744558b200aebbb05e4d0db89197fea86a25f4 Mon Sep 17 00:00:00 2001 From: kalkyl Date: Thu, 2 Nov 2023 22:37:03 +0100 Subject: [PATCH 2/2] Cleanup --- examples/rp/src/bin/pio_rotary_encoder.rs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/examples/rp/src/bin/pio_rotary_encoder.rs b/examples/rp/src/bin/pio_rotary_encoder.rs index 589f38a7..6d9d59df 100644 --- a/examples/rp/src/bin/pio_rotary_encoder.rs +++ b/examples/rp/src/bin/pio_rotary_encoder.rs @@ -34,24 +34,14 @@ impl<'d, T: Instance, const SM: usize> PioEncoder<'d, T, SM> { pin_b.set_pull(Pull::Up); sm.set_pin_dirs(pio::Direction::In, &[&pin_a, &pin_b]); - let prg = pio_proc::pio_asm!( - r#" - wait 1 pin 1 - .wrap_target - wait 0 pin 1 - in pins, 2 - push - wait 1 pin 1 - .wrap - "# - ); + let prg = pio_proc::pio_asm!("wait 1 pin 1", "wait 0 pin 1", "in pins, 2", "push",); let mut cfg = Config::default(); cfg.set_in_pins(&[&pin_a, &pin_b]); cfg.fifo_join = FifoJoin::RxOnly; - cfg.use_program(&pio.load_program(&prg.program), &[]); cfg.shift_in.direction = ShiftDirection::Left; cfg.clock_divider = 10_000.to_fixed(); + cfg.use_program(&pio.load_program(&prg.program), &[]); sm.set_config(&cfg); sm.set_enable(true); Self { sm }