use core::u16; use hal::{self, Direction}; use stm32::{TIM2, TIM3, TIM4}; use afio::MAPR; use gpio::gpioa::{PA0, PA1, PA6, PA7}; use gpio::gpiob::{PB6, PB7}; use gpio::{Floating, Input}; use rcc::APB1; pub trait Pins { const REMAP: u8; } impl Pins for (PA0>, PA1>) { const REMAP: u8 = 0b00; } impl Pins for (PA6>, PA7>) { const REMAP: u8 = 0b00; } impl Pins for (PB6>, PB7>) { const REMAP: u8 = 0b00; } pub struct Qei { tim: TIM, pins: PINS, } impl Qei { pub fn tim2(tim: TIM2, pins: PINS, mapr: &mut MAPR, apb: &mut APB1) -> Self where PINS: Pins, { mapr.mapr() .modify(|_, w| unsafe { w.tim2_remap().bits(PINS::REMAP) }); Qei::_tim2(tim, pins, apb) } } impl Qei { pub fn tim3(tim: TIM3, pins: PINS, mapr: &mut MAPR, apb: &mut APB1) -> Self where PINS: Pins, { mapr.mapr() .modify(|_, w| unsafe { w.tim3_remap().bits(PINS::REMAP) }); Qei::_tim3(tim, pins, apb) } } impl Qei { pub fn tim4(tim: TIM4, pins: PINS, mapr: &mut MAPR, apb: &mut APB1) -> Self where PINS: Pins, { mapr.mapr() .modify(|_, w| w.tim4_remap().bit(PINS::REMAP == 1)); Qei::_tim4(tim, pins, apb) } } macro_rules! hal { ($($TIMX:ident: ($timX:ident, $timXen:ident, $timXrst:ident),)+) => { $( impl Qei<$TIMX, PINS> { fn $timX(tim: $TIMX, pins: PINS, apb: &mut APB1) -> Self { // enable and reset peripheral to a clean slate state apb.enr().modify(|_, w| w.$timXen().set_bit()); apb.rstr().modify(|_, w| w.$timXrst().set_bit()); apb.rstr().modify(|_, w| w.$timXrst().clear_bit()); // Configure TxC1 and TxC2 as captures tim.ccmr1_output .write(|w| unsafe { w.bits({ (0b01 << 0) | (0b01 << 8) }) }); // enable and configure to capture on rising edge tim.ccer.write(|w| { w.cc1e() .set_bit() .cc1p() .clear_bit() .cc2e() .set_bit() .cc2p() .clear_bit() }); // configure as quadrature encoder tim.smcr.write(|w| w.sms().bits(3)); tim.arr.write(|w| w.arr().bits(u16::MAX)); tim.cr1.write(|w| w.cen().set_bit()); Qei { tim, pins } } pub fn release(self) -> ($TIMX, PINS) { (self.tim, self.pins) } } impl hal::Qei for Qei<$TIMX, PINS> { type Count = u16; fn count(&self) -> u16 { self.tim.cnt.read().cnt().bits() } fn direction(&self) -> Direction { if self.tim.cr1.read().dir().bit_is_clear() { hal::Direction::Upcounting } else { hal::Direction::Downcounting } } } )+ } } hal! { TIM2: (_tim2, tim2en, tim2rst), TIM3: (_tim3, tim3en, tim3rst), TIM4: (_tim4, tim4en, tim4rst), }