added pio-based rotary encoder reading.
This commit is contained in:
parent
6f6ecc833e
commit
c726ab4aa7
|
@ -20,6 +20,8 @@ panic-probe = { version = "0.3", features = ["print-defmt"] }
|
||||||
rp-pico = "0.8"
|
rp-pico = "0.8"
|
||||||
max31855 = "0.1.0"
|
max31855 = "0.1.0"
|
||||||
hd44780-driver = "0.4.0"
|
hd44780-driver = "0.4.0"
|
||||||
|
pio-proc = "0.2"
|
||||||
|
pio = "0.2"
|
||||||
|
|
||||||
# cargo build/run
|
# cargo build/run
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
|
|
51
src/encoder.pio
Normal file
51
src/encoder.pio
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
; from https://github.com/GitJer/Rotary_encoder/blob/master/pio_rotary_encoder.pio
|
||||||
|
.program pio_rotary_encoder
|
||||||
|
.wrap_target
|
||||||
|
.origin 0 ; The jump table has to start at 0
|
||||||
|
; it contains the correct jumps for each of the 16
|
||||||
|
; combination of 4 bits formed by A'B'AB
|
||||||
|
; A = current reading of pin_A of the rotary encoder
|
||||||
|
; A' = previous reading of pin_A of the rotary encoder
|
||||||
|
; B = current reading of pin_B of the rotary encoder
|
||||||
|
; B' = previous reading of pin_B of the rotary encoder
|
||||||
|
jmp read ; 0000 = from 00 to 00 = no change in reading
|
||||||
|
jmp CW ; 0001 = from 00 to 01 = clockwise rotation
|
||||||
|
jmp CCW ; 0010 = from 00 to 10 = counter clockwise rotation
|
||||||
|
jmp read ; 0011 = from 00 to 11 = error
|
||||||
|
|
||||||
|
jmp CCW ; 0100 = from 01 to 00 = counter clockwise rotation
|
||||||
|
jmp read ; 0101 = from 01 to 01 = no change in reading
|
||||||
|
jmp read ; 0110 = from 01 to 10 = error
|
||||||
|
jmp CW ; 0111 = from 01 to 11 = clockwise rotation
|
||||||
|
|
||||||
|
jmp CW ; 1000 = from 10 to 00 = clockwise rotation
|
||||||
|
jmp read ; 1001 = from 10 to 01 = error
|
||||||
|
jmp read ; 1010 = from 10 to 10 = no change in reading
|
||||||
|
jmp CCW ; 1011 = from 10 to 11 = counter clockwise rotation
|
||||||
|
|
||||||
|
jmp read ; 1100 = from 11 to 00 = error
|
||||||
|
jmp CCW ; 1101 = from 11 to 01 = counter clockwise rotation
|
||||||
|
jmp CW ; 1110 = from 11 to 10 = clockwise rotation
|
||||||
|
jmp read ; 1111 = from 11 to 11 = no change in reading
|
||||||
|
|
||||||
|
pc_start: ; this is the entry point for the program
|
||||||
|
in pins 2 ; read the current values of A and B and use
|
||||||
|
; them to initialize the previous values (A'B')
|
||||||
|
read:
|
||||||
|
mov osr isr ; the OSR is (after the next instruction) used to shift
|
||||||
|
; the two bits with the previous values into the ISR
|
||||||
|
out isr 2 ; shift the previous value into the ISR. This also sets
|
||||||
|
; all other bits in the ISR to 0
|
||||||
|
in pins 2 ; shift the current value into the ISR
|
||||||
|
; the 16 LSB of the ISR now contain 000000000000A'B'AB
|
||||||
|
; this represents a jmp instruction to the address A'B'AB
|
||||||
|
mov exec isr ; do the jmp encoded in the ISR
|
||||||
|
CW: ; a clockwise rotation was detected
|
||||||
|
irq 0 ; signal a clockwise rotation via an IRQ
|
||||||
|
jmp read ; jump to reading the current values of A and B
|
||||||
|
CCW: ; a counter clockwise rotation was detected
|
||||||
|
irq 1 ; signal a counter clockwise rotation via an IRQ
|
||||||
|
; jmp read ; jump to reading the current values of A and B.
|
||||||
|
; the jmp isn't needed because of the .wrap, and the first
|
||||||
|
; statement of the program happens to be a jmp read
|
||||||
|
.wrap
|
41
src/main.rs
41
src/main.rs
|
@ -28,14 +28,15 @@ mod app {
|
||||||
Gpio0, Gpio1, Gpio14, Gpio16, Gpio17, Gpio18, Gpio19, Gpio2, Gpio20, Gpio21,
|
Gpio0, Gpio1, Gpio14, Gpio16, Gpio17, Gpio18, Gpio19, Gpio2, Gpio20, Gpio21,
|
||||||
Gpio25, Gpio3, Gpio4, Gpio5,
|
Gpio25, Gpio3, Gpio4, Gpio5,
|
||||||
},
|
},
|
||||||
FunctionSio, FunctionSpi, FunctionUart, Pin, PullDown, SioOutput,
|
FunctionPio0, FunctionSio, FunctionSpi, FunctionUart, Pin, PullDown, SioOutput,
|
||||||
},
|
},
|
||||||
|
pio::PIOExt,
|
||||||
sio::Sio,
|
sio::Sio,
|
||||||
spi::{self, Spi},
|
spi::{self, Spi},
|
||||||
uart::{self, UartConfig, UartPeripheral},
|
uart::{self, UartConfig, UartPeripheral},
|
||||||
watchdog::Watchdog,
|
watchdog::Watchdog,
|
||||||
},
|
},
|
||||||
pac::{SPI0, UART0},
|
pac::{self, SPI0, UART0},
|
||||||
Pins,
|
Pins,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -119,6 +120,7 @@ mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(mut ctx: init::Context) -> (Shared, Local, init::Monotonics) {
|
fn init(mut ctx: init::Context) -> (Shared, Local, init::Monotonics) {
|
||||||
let mut watchdog = Watchdog::new(ctx.device.WATCHDOG);
|
let mut watchdog = Watchdog::new(ctx.device.WATCHDOG);
|
||||||
|
let mut pac = pac::Peripherals::take().unwrap();
|
||||||
let sio = Sio::new(ctx.device.SIO);
|
let sio = Sio::new(ctx.device.SIO);
|
||||||
|
|
||||||
// External high-speed crystal on the pico board is 12Mhz
|
// External high-speed crystal on the pico board is 12Mhz
|
||||||
|
@ -212,6 +214,25 @@ mod app {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let rotary_clk: Pin<_, FunctionPio0, _> = pins.gpio11.into_function();
|
||||||
|
let rotary_clk_id = rotary_clk.id().num;
|
||||||
|
let rotary_dt: Pin<_, FunctionPio0, _> = pins.gpio12.into_function();
|
||||||
|
let rotary_dt_id = rotary_dt.id().num;
|
||||||
|
let program = pio_proc::pio_file!("src/encoder.pio");
|
||||||
|
|
||||||
|
let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
|
||||||
|
pio.irq0().enable_sm_interrupt(0);
|
||||||
|
pio.irq1().enable_sm_interrupt(1);
|
||||||
|
let installed = pio.install(&program.program).unwrap();
|
||||||
|
let (mut sm, _, _) = rp_pico::hal::pio::PIOBuilder::from_program(installed)
|
||||||
|
.set_pins(rotary_clk_id, 2)
|
||||||
|
.build(sm0);
|
||||||
|
sm.set_pindirs([
|
||||||
|
(rotary_clk_id, rp_pico::hal::pio::PinDir::Output),
|
||||||
|
(rotary_dt_id, rp_pico::hal::pio::PinDir::Output),
|
||||||
|
]);
|
||||||
|
sm.start();
|
||||||
|
|
||||||
let mono = Rp2040Mono::new(ctx.device.TIMER);
|
let mono = Rp2040Mono::new(ctx.device.TIMER);
|
||||||
|
|
||||||
heartbeat::spawn().unwrap();
|
heartbeat::spawn().unwrap();
|
||||||
|
@ -234,6 +255,22 @@ mod app {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[task(binds = PIO0_IRQ_0, shared = [target_temp])]
|
||||||
|
fn inc_target(mut ctx: inc_target::Context) {
|
||||||
|
ctx.shared.target_temp.lock(|t| {
|
||||||
|
*t += 1.0;
|
||||||
|
});
|
||||||
|
update_display::spawn().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[task(binds = PIO0_IRQ_1, shared = [target_temp])]
|
||||||
|
fn dec_target(mut ctx: dec_target::Context) {
|
||||||
|
ctx.shared.target_temp.lock(|t| {
|
||||||
|
*t -= 1.0;
|
||||||
|
});
|
||||||
|
update_display::spawn().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[task(local = [thermocouple], shared = [recent_temp, uart])]
|
#[task(local = [thermocouple], shared = [recent_temp, uart])]
|
||||||
fn read_temp(mut ctx: read_temp::Context) {
|
fn read_temp(mut ctx: read_temp::Context) {
|
||||||
match ctx.local.thermocouple.read_temp() {
|
match ctx.local.thermocouple.read_temp() {
|
||||||
|
|
Loading…
Reference in a new issue