qei.rs 6.0 KB

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