qei.rs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /**
  2. # Quadrature Encoder Interface
  3. NOTE: In some cases you need to specify remap you need, especially for TIM2
  4. (see [Alternate function remapping](super::timer)):
  5. */
  6. use core::u16;
  7. use core::marker::PhantomData;
  8. use crate::hal::{self, Direction};
  9. #[cfg(any(feature = "stm32f100", feature = "stm32f103", feature = "stm32f105",))]
  10. use crate::pac::TIM1;
  11. #[cfg(feature = "medium")]
  12. use crate::pac::TIM4;
  13. use crate::pac::{TIM2, TIM3};
  14. use crate::afio::MAPR;
  15. use crate::pwm_input::Pins;
  16. use crate::timer::{sealed::Remap, Timer};
  17. /// SMS (Slave Mode Selection) register
  18. pub enum SlaveMode {
  19. /// Counter counts up/down on TI2FP1 edge depending on TI1FP2 level.
  20. EncoderMode1 = 0b001,
  21. /// Encoder mode 2 - Counter counts up/down on TI1FP2 edge depending on TI2FP1 level.
  22. EncoderMode2 = 0b010,
  23. /// Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2 edges depending on the
  24. /// level of the other input.
  25. EncoderMode3 = 0b011,
  26. /// Reset Mode - Rising edge of the selected trigger input (TRGI) reinitializes the counter and
  27. /// generates an update of the registers.
  28. ResetMode = 0b100,
  29. /// Trigger Mode - The counter starts at a rising edge of the trigger TRGI (but it is not
  30. /// reset). Only the start of the counter is controlled.
  31. TriggerMode = 0b110,
  32. /// External Clock Mode 1 - Rising edges of the selected trigger (TRGI) clock the counter.
  33. ExternalClockMode1 = 0b111,
  34. }
  35. pub struct QeiOptions {
  36. slave_mode: SlaveMode,
  37. }
  38. impl Default for QeiOptions {
  39. fn default() -> Self {
  40. Self {
  41. slave_mode: SlaveMode::EncoderMode3,
  42. }
  43. }
  44. }
  45. pub struct Qei<TIM, REMAP, PINS> {
  46. tim: TIM,
  47. pins: PINS,
  48. _remap: PhantomData<REMAP>,
  49. }
  50. #[cfg(any(feature = "stm32f100", feature = "stm32f103", feature = "stm32f105",))]
  51. impl Timer<TIM1> {
  52. pub fn qei<REMAP, PINS>(
  53. self,
  54. pins: PINS,
  55. mapr: &mut MAPR,
  56. options: QeiOptions,
  57. ) -> Qei<TIM1, REMAP, PINS>
  58. where
  59. REMAP: Remap<Periph = TIM1>,
  60. PINS: Pins<REMAP>,
  61. {
  62. mapr.modify_mapr(|_, w| unsafe { w.tim1_remap().bits(REMAP::REMAP) });
  63. let Self { tim, clk: _ } = self;
  64. Qei::_tim1(tim, pins, options)
  65. }
  66. }
  67. impl Timer<TIM2> {
  68. pub fn qei<REMAP, PINS>(
  69. self,
  70. pins: PINS,
  71. mapr: &mut MAPR,
  72. options: QeiOptions,
  73. ) -> Qei<TIM2, REMAP, PINS>
  74. where
  75. REMAP: Remap<Periph = TIM2>,
  76. PINS: Pins<REMAP>,
  77. {
  78. mapr.modify_mapr(|_, w| unsafe { w.tim2_remap().bits(REMAP::REMAP) });
  79. let Self { tim, clk: _ } = self;
  80. Qei::_tim2(tim, pins, options)
  81. }
  82. }
  83. impl Timer<TIM3> {
  84. pub fn qei<REMAP, PINS>(
  85. self,
  86. pins: PINS,
  87. mapr: &mut MAPR,
  88. options: QeiOptions,
  89. ) -> Qei<TIM3, REMAP, PINS>
  90. where
  91. REMAP: Remap<Periph = TIM3>,
  92. PINS: Pins<REMAP>,
  93. {
  94. mapr.modify_mapr(|_, w| unsafe { w.tim3_remap().bits(REMAP::REMAP) });
  95. let Self { tim, clk: _ } = self;
  96. Qei::_tim3(tim, pins, options)
  97. }
  98. }
  99. #[cfg(feature = "medium")]
  100. impl Timer<TIM4> {
  101. pub fn qei<REMAP, PINS>(
  102. self,
  103. pins: PINS,
  104. mapr: &mut MAPR,
  105. options: QeiOptions,
  106. ) -> Qei<TIM4, REMAP, PINS>
  107. where
  108. REMAP: Remap<Periph = TIM4>,
  109. PINS: Pins<REMAP>,
  110. {
  111. mapr.modify_mapr(|_, w| w.tim4_remap().bit(REMAP::REMAP == 1));
  112. let Self { tim, clk: _ } = self;
  113. Qei::_tim4(tim, pins, options)
  114. }
  115. }
  116. macro_rules! hal {
  117. ($($TIMX:ident: ($timX:ident, $timXen:ident, $timXrst:ident),)+) => {
  118. $(
  119. impl<REMAP, PINS> Qei<$TIMX, REMAP, PINS> {
  120. fn $timX(tim: $TIMX, pins: PINS, options: QeiOptions) -> Self {
  121. // Configure TxC1 and TxC2 as captures
  122. tim.ccmr1_input().write(|w| w.cc1s().ti1().cc2s().ti2());
  123. // enable and configure to capture on rising edge
  124. tim.ccer.write(|w| {
  125. w.cc1e()
  126. .set_bit()
  127. .cc1p()
  128. .clear_bit()
  129. .cc2e()
  130. .set_bit()
  131. .cc2p()
  132. .clear_bit()
  133. });
  134. // configure as quadrature encoder
  135. tim.smcr.write(|w| w.sms().bits(options.slave_mode as u8));
  136. tim.arr.write(|w| w.arr().bits(u16::MAX));
  137. tim.cr1.write(|w| w.cen().set_bit());
  138. Qei { tim, pins, _remap: PhantomData }
  139. }
  140. pub fn release(self) -> ($TIMX, PINS) {
  141. (self.tim, self.pins)
  142. }
  143. }
  144. impl<REMAP, PINS> hal::Qei for Qei<$TIMX, REMAP, PINS> {
  145. type Count = u16;
  146. fn count(&self) -> u16 {
  147. self.tim.cnt.read().cnt().bits()
  148. }
  149. fn direction(&self) -> Direction {
  150. if self.tim.cr1.read().dir().bit_is_clear() {
  151. hal::Direction::Upcounting
  152. } else {
  153. hal::Direction::Downcounting
  154. }
  155. }
  156. }
  157. )+
  158. }
  159. }
  160. #[cfg(any(feature = "stm32f100", feature = "stm32f103", feature = "stm32f105",))]
  161. hal! {
  162. TIM1: (_tim1, tim1en, tim1rst),
  163. }
  164. hal! {
  165. TIM2: (_tim2, tim2en, tim2rst),
  166. TIM3: (_tim3, tim3en, tim3rst),
  167. }
  168. #[cfg(feature = "medium")]
  169. hal! {
  170. TIM4: (_tim4, tim4en, tim4rst),
  171. }