From df362306085f2d0984310dff1c32b4d55b18721c Mon Sep 17 00:00:00 2001 From: Andy Killorin <37423245+Speedy6451@users.noreply.github.com> Date: Thu, 2 May 2024 09:29:16 -0500 Subject: [PATCH] extracted encoder to module (hopefully interrupts work) --- src/encoder.rs | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 55 +++++-------------------------------------------- 2 files changed, 61 insertions(+), 50 deletions(-) create mode 100644 src/encoder.rs diff --git a/src/encoder.rs b/src/encoder.rs new file mode 100644 index 0000000..673e2d8 --- /dev/null +++ b/src/encoder.rs @@ -0,0 +1,56 @@ +use core::{cell::{Cell, OnceCell}, sync::atomic::AtomicU8}; + +use arduino_hal::{hal::port::{PD1, PD2}, pac::{exint::eicra::{ISC0_A, ISC1_A}, EXINT}, port::{mode::{Floating, Input}, Pin}}; +use avr_device::interrupt::{self, CriticalSection, Mutex}; +pub fn setup_encoder(d1: Pin, PD1>, d2: Pin, PD2>, int: EXINT) { + interrupt::free(|cs| { + let _ = ENCODER.borrow(cs).set((d1, d2)); + }); + + //dp.EXINT.pcifr.write(0b11); + int.eicra.write(|w| w.isc0().bits(ISC0_A::VAL_0X01 as u8)); // rising and falling edge + int.eimsk.write(|w| w.int0().set_bit()); + int.eicra.write(|w| w.isc1().bits(ISC1_A::VAL_0X01 as u8)); // rising and falling edge + int.eimsk.write(|w| w.int1().set_bit()); +} + +pub fn position() -> i64{ + interrupt::free(|cs| COUNTS.borrow(cs).get()) +} + +static ENCODER: Mutex, PD1>, Pin, PD2>)>> = Mutex::new(OnceCell::new()); +static LAST: AtomicU8 = AtomicU8::new(0); +pub static COUNTS: Mutex> = Mutex::new(Cell::new(0)); +pub const TICKS_PER_ROT: f32 = 90. * 4.; + +#[avr_device_macros::interrupt(atmega328p)] +fn INT0() { + interrupt::free(|cs| update_encoder(cs)) +} +#[avr_device_macros::interrupt(atmega328p)] +fn INT1() { + interrupt::free(|cs| update_encoder(cs)) +} + +fn update_encoder(cs: CriticalSection) { + let (d1,d2) = ENCODER.borrow(cs).get().unwrap(); + let d1 = d1.is_high() as u8; + let d2 = d2.is_high() as u8; + let curr = d2<<1 +d1; + let last = LAST.load(core::sync::atomic::Ordering::SeqCst); + + // could probably do this bitwise (subtract individual phases?) + let diff: i8 = match curr<<2 +last { + 0b0001 => 1, + 0b0111 => 1, + 0b1110 => 1, + 0b1000 => 1, + 0b0010 => -1, + 0b1011 => -1, + 0b1101 => -1, + 0b0100 => -1, + _ => 0, + }; + COUNTS.borrow(cs).update(|v| v+diff as i64); + LAST.store(curr, core::sync::atomic::Ordering::SeqCst); +} diff --git a/src/main.rs b/src/main.rs index c39fe82..5cfdd75 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,27 +2,19 @@ #![no_main] #![feature(abi_avr_interrupt, cell_update)] -use core::{cell::{Cell, OnceCell}, sync::atomic::AtomicU8}; - -use arduino_hal::{hal::port::{PD1, PD2}, pac::exint::eicra::{ISC0_A, ISC1_A}, port::{mode::{Floating, Input}, Pin}}; -use avr_device::interrupt::{self, CriticalSection, Mutex}; +use encoder::{setup_encoder, TICKS_PER_ROT}; use panic_halt as _; mod servo; use servo::{configure_timer_one, Servo}; +mod encoder; #[arduino_hal::entry] fn main() -> ! { let dp = arduino_hal::Peripherals::take().unwrap(); let pins = arduino_hal::pins!(dp); - interrupt::free(|cs| { - let _ = ENCODER.borrow(cs).set((pins.d1, pins.d2)); - }); - //dp.EXINT.pcifr.write(0b11); - dp.EXINT.eicra.write(|w| w.isc0().bits(ISC0_A::VAL_0X01 as u8)); // rising and falling edge - dp.EXINT.eimsk.write(|w| w.int0().set_bit()); - dp.EXINT.eicra.write(|w| w.isc1().bits(ISC1_A::VAL_0X01 as u8)); // rising and falling edge - dp.EXINT.eimsk.write(|w| w.int1().set_bit()); + // configure encoder + setup_encoder(pins.d1, pins.d2, dp.EXINT); // configure timer for servos pins.d9.into_output(); // carriage @@ -30,7 +22,7 @@ fn main() -> ! { let (carriage, claw) = configure_timer_one(&dp.TC1); loop { - let position = interrupt::free(|cs| COUNTS.borrow(cs).get()); + let position = encoder::position(); let gain = position as f32 / TICKS_PER_ROT; @@ -38,40 +30,3 @@ fn main() -> ! { arduino_hal::delay_ms(20); } } - -static ENCODER: Mutex, PD1>, Pin, PD2>)>> = Mutex::new(OnceCell::new()); -static LAST: AtomicU8 = AtomicU8::new(0); -static COUNTS: Mutex> = Mutex::new(Cell::new(0)); -const TICKS_PER_ROT: f32 = 90. * 4.; - -#[avr_device_macros::interrupt(atmega328p)] -fn INT0() { - interrupt::free(|cs| update_encoder(cs)) -} -#[avr_device_macros::interrupt(atmega328p)] -fn INT1() { - interrupt::free(|cs| update_encoder(cs)) -} - -fn update_encoder(cs: CriticalSection) { - let (d1,d2) = ENCODER.borrow(cs).get().unwrap(); - let d1 = d1.is_high() as u8; - let d2 = d2.is_high() as u8; - let curr = d2<<1 +d1; - let last = LAST.load(core::sync::atomic::Ordering::SeqCst); - - // could probably do this bitwise (subtract individual phases?) - let diff: i8 = match curr<<2 +last { - 0b0001 => 1, - 0b0111 => 1, - 0b1110 => 1, - 0b1000 => 1, - 0b0010 => -1, - 0b1011 => -1, - 0b1101 => -1, - 0b0100 => -1, - _ => 0, - }; - COUNTS.borrow(cs).update(|v| v+diff as i64); - LAST.store(curr, core::sync::atomic::Ordering::SeqCst); -}