qei.rs 3.7 KB

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