qei.rs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. use core::u16;
  2. use hal::{self, Direction};
  3. use stm32::{TIM2, TIM3, TIM4};
  4. use afio::MAPR;
  5. use gpio::gpioa::{PA0, PA1, PA6, PA7};
  6. use gpio::gpiob::{PB6, PB7};
  7. use gpio::{Floating, Input};
  8. use rcc::APB1;
  9. pub trait Pins<TIM> {
  10. const REMAP: u8;
  11. }
  12. impl Pins<TIM2> for (PA0<Input<Floating>>, PA1<Input<Floating>>) {
  13. const REMAP: u8 = 0b00;
  14. }
  15. impl Pins<TIM3> for (PA6<Input<Floating>>, PA7<Input<Floating>>) {
  16. const REMAP: u8 = 0b00;
  17. }
  18. impl Pins<TIM4> for (PB6<Input<Floating>>, PB7<Input<Floating>>) {
  19. const REMAP: u8 = 0b00;
  20. }
  21. pub struct Qei<TIM, PINS> {
  22. tim: TIM,
  23. pins: PINS,
  24. }
  25. impl<PINS> Qei<TIM2, PINS> {
  26. pub fn tim2(tim: TIM2, pins: PINS, mapr: &mut MAPR, apb: &mut APB1) -> Self
  27. where
  28. PINS: Pins<TIM2>,
  29. {
  30. mapr.mapr()
  31. .modify(|_, w| unsafe { w.tim2_remap().bits(PINS::REMAP) });
  32. Qei::_tim2(tim, pins, apb)
  33. }
  34. }
  35. impl<PINS> Qei<TIM3, PINS> {
  36. pub fn tim3(tim: TIM3, pins: PINS, mapr: &mut MAPR, apb: &mut APB1) -> Self
  37. where
  38. PINS: Pins<TIM3>,
  39. {
  40. mapr.mapr()
  41. .modify(|_, w| unsafe { w.tim3_remap().bits(PINS::REMAP) });
  42. Qei::_tim3(tim, pins, apb)
  43. }
  44. }
  45. impl<PINS> Qei<TIM4, PINS> {
  46. pub fn tim4(tim: TIM4, pins: PINS, mapr: &mut MAPR, apb: &mut APB1) -> Self
  47. where
  48. PINS: Pins<TIM4>,
  49. {
  50. mapr.mapr()
  51. .modify(|_, w| w.tim4_remap().bit(PINS::REMAP == 1));
  52. Qei::_tim4(tim, pins, apb)
  53. }
  54. }
  55. macro_rules! hal {
  56. ($($TIMX:ident: ($timX:ident, $timXen:ident, $timXrst:ident),)+) => {
  57. $(
  58. impl<PINS> Qei<$TIMX, PINS> {
  59. fn $timX(tim: $TIMX, pins: PINS, apb: &mut APB1) -> Self {
  60. // enable and reset peripheral to a clean slate state
  61. apb.enr().modify(|_, w| w.$timXen().set_bit());
  62. apb.rstr().modify(|_, w| w.$timXrst().set_bit());
  63. apb.rstr().modify(|_, w| w.$timXrst().clear_bit());
  64. // Configure TxC1 and TxC2 as captures
  65. tim.ccmr1_output
  66. .write(|w| unsafe { w.bits({ (0b01 << 0) | (0b01 << 8) }) });
  67. // enable and configure to capture on rising edge
  68. tim.ccer.write(|w| {
  69. w.cc1e()
  70. .set_bit()
  71. .cc1p()
  72. .clear_bit()
  73. .cc2e()
  74. .set_bit()
  75. .cc2p()
  76. .clear_bit()
  77. });
  78. // configure as quadrature encoder
  79. tim.smcr.write(|w| w.sms().bits(3));
  80. tim.arr.write(|w| w.arr().bits(u16::MAX));
  81. tim.cr1.write(|w| w.cen().set_bit());
  82. Qei { tim, pins }
  83. }
  84. pub fn release(self) -> ($TIMX, PINS) {
  85. (self.tim, self.pins)
  86. }
  87. }
  88. impl<PINS> hal::Qei for Qei<$TIMX, PINS> {
  89. type Count = u16;
  90. fn count(&self) -> u16 {
  91. self.tim.cnt.read().cnt().bits()
  92. }
  93. fn direction(&self) -> Direction {
  94. if self.tim.cr1.read().dir().bit_is_clear() {
  95. hal::Direction::Upcounting
  96. } else {
  97. hal::Direction::Downcounting
  98. }
  99. }
  100. }
  101. )+
  102. }
  103. }
  104. hal! {
  105. TIM2: (_tim2, tim2en, tim2rst),
  106. TIM3: (_tim3, tim3en, tim3rst),
  107. TIM4: (_tim4, tim4en, tim4rst),
  108. }