mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-22 14:53:03 +00:00
RP235x: add example for encoder with status register
This commit is contained in:
parent
bda9715f51
commit
d2f959cdac
116
examples/rp23/src/bin/pio_rotary_encoder_rxf.rs
Normal file
116
examples/rp23/src/bin/pio_rotary_encoder_rxf.rs
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
//! This example shows how to use the PIO module in the RP235x to read a quadrature rotary encoder.
|
||||||
|
//! It differs from the other example in that it uses the RX FIFO as a status register
|
||||||
|
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use defmt::info;
|
||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_rp::block::ImageDef;
|
||||||
|
use embassy_rp::gpio::Pull;
|
||||||
|
use embassy_rp::peripherals::PIO0;
|
||||||
|
use embassy_rp::{bind_interrupts, pio};
|
||||||
|
use embassy_time::Timer;
|
||||||
|
use fixed::traits::ToFixed;
|
||||||
|
use pio::{Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftDirection, StateMachine};
|
||||||
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
#[link_section = ".start_block"]
|
||||||
|
#[used]
|
||||||
|
pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe();
|
||||||
|
|
||||||
|
// Program metadata for `picotool info`
|
||||||
|
#[link_section = ".bi_entries"]
|
||||||
|
#[used]
|
||||||
|
pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [
|
||||||
|
embassy_rp::binary_info::rp_program_name!(c"example_pio_rotary_encoder_rxf"),
|
||||||
|
embassy_rp::binary_info::rp_cargo_version!(),
|
||||||
|
embassy_rp::binary_info::rp_program_description!(c"Rotary encoder (RXF)"),
|
||||||
|
embassy_rp::binary_info::rp_program_build_attribute!(),
|
||||||
|
];
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
PIO0_IRQ_0 => InterruptHandler<PIO0>;
|
||||||
|
});
|
||||||
|
|
||||||
|
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!(
|
||||||
|
"start:"
|
||||||
|
// encoder count is stored in X
|
||||||
|
"mov isr, x"
|
||||||
|
// and then moved to the RX FIFO register
|
||||||
|
"mov rxfifo[0], isr"
|
||||||
|
|
||||||
|
// wait for encoder transition
|
||||||
|
"wait 1 pin 1"
|
||||||
|
"wait 0 pin 1"
|
||||||
|
|
||||||
|
"set y, 0"
|
||||||
|
"mov y, pins[1]"
|
||||||
|
|
||||||
|
// update X depending on pin 1
|
||||||
|
"jmp !y decr"
|
||||||
|
|
||||||
|
// this is just a clever way of doing x++
|
||||||
|
"mov x, ~x"
|
||||||
|
"jmp x--, incr"
|
||||||
|
"incr:"
|
||||||
|
"mov x, ~x"
|
||||||
|
"jmp start"
|
||||||
|
|
||||||
|
// and this is x--
|
||||||
|
"decr:"
|
||||||
|
"jmp x--, start"
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut cfg = Config::default();
|
||||||
|
cfg.set_in_pins(&[&pin_a, &pin_b]);
|
||||||
|
cfg.fifo_join = FifoJoin::RxAsStatus;
|
||||||
|
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 }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn read(&mut self) -> u32 {
|
||||||
|
self.sm.get_rxf_entry(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
info!("Count: {}", encoder.read().await);
|
||||||
|
Timer::after_millis(1000).await;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user