pwm_input.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. //! This module allows Timer peripherals to be configured as pwm input.
  2. //! In this mode, the timer sample a squared signal to find it's frequency and duty cycle.
  3. use core::marker::PhantomData;
  4. use core::mem;
  5. use crate::pac::DBGMCU as DBG;
  6. #[cfg(any(feature = "stm32f100", feature = "stm32f103", feature = "connectivity",))]
  7. use crate::pac::TIM1;
  8. #[cfg(feature = "medium")]
  9. use crate::pac::TIM4;
  10. use crate::pac::{TIM2, TIM3};
  11. use crate::afio::MAPR;
  12. use crate::gpio::{self, Floating, Input};
  13. use crate::rcc::{sealed::RccBus, Clocks, GetBusFreq};
  14. use crate::time::Hertz;
  15. use crate::timer::Timer;
  16. pub trait Pins<REMAP> {}
  17. use crate::timer::sealed::{Ch1, Ch2, Remap};
  18. impl<TIM, REMAP, P1, P2> Pins<REMAP> for (P1, P2)
  19. where
  20. REMAP: Remap<Periph = TIM>,
  21. P1: Ch1<REMAP> + gpio::Mode<Input<Floating>>,
  22. P2: Ch2<REMAP> + gpio::Mode<Input<Floating>>,
  23. {
  24. }
  25. /// PWM Input
  26. pub struct PwmInput<TIM, REMAP, PINS> {
  27. _timer: PhantomData<TIM>,
  28. _remap: PhantomData<REMAP>,
  29. _pins: PhantomData<PINS>,
  30. }
  31. /// How the data is read from the timer
  32. pub enum ReadMode {
  33. /// Return the latest captured data
  34. Instant,
  35. /// Wait for one period of the signal before computing the frequency and the duty cycle
  36. /// The microcontroller will be halted for at most two period of the input signal.
  37. WaitForNextCapture,
  38. }
  39. /// The error returned when reading a frequency from a timer
  40. #[derive(Debug)]
  41. pub enum Error {
  42. /// The signal frequency is too low to be sampled by the current timer configuration
  43. FrequencyTooLow,
  44. }
  45. /// Which frequency the timer will try to sample
  46. pub enum Configuration<T>
  47. where
  48. T: Into<Hertz>,
  49. {
  50. /// In this mode an algorithm calculates the optimal value for the autoreload register and the
  51. /// prescaler register in order to be able to sample a wide range of frequency, at the expense
  52. /// of resolution.
  53. ///
  54. /// The minimum frequency that can be sampled is 20% the provided frequency.
  55. ///
  56. /// Use this mode if you do not know what to choose.
  57. Frequency(T),
  58. /// In this mode an algorithm calculates the optimal value for the autoreload register and the
  59. /// prescaler register in order to sample the duty cycle with a high resolution.
  60. /// This will limit the frequency range where the timer can operate.
  61. ///
  62. /// The minimum frequency that can be sampled is 90% the provided frequency
  63. DutyCycle(T),
  64. /// In this mode an algorithm calculates the optimal value for the autoreload register and the
  65. /// prescaler register in order to be able to sample signal with a frequency higher than the
  66. /// provided value : there is no margin for lower frequencies.
  67. RawFrequency(T),
  68. /// In this mode, the provided arr and presc are directly programmed in the register.
  69. RawValues { arr: u16, presc: u16 },
  70. }
  71. #[cfg(any(feature = "stm32f100", feature = "stm32f103", feature = "connectivity",))]
  72. impl Timer<TIM1> {
  73. pub fn pwm_input<REMAP, PINS, T>(
  74. mut self,
  75. pins: PINS,
  76. mapr: &mut MAPR,
  77. dbg: &mut DBG,
  78. mode: Configuration<T>,
  79. ) -> PwmInput<TIM1, REMAP, PINS>
  80. where
  81. REMAP: Remap<Periph = TIM1>,
  82. PINS: Pins<REMAP>,
  83. T: Into<Hertz>,
  84. {
  85. mapr.modify_mapr(|_, w| unsafe { w.tim1_remap().bits(REMAP::REMAP) });
  86. self.stop_in_debug(dbg, false);
  87. let Self { tim, clk } = self;
  88. tim1(tim, pins, clk, mode)
  89. }
  90. }
  91. impl Timer<TIM2> {
  92. pub fn pwm_input<REMAP, PINS, T>(
  93. mut self,
  94. pins: PINS,
  95. mapr: &mut MAPR,
  96. dbg: &mut DBG,
  97. mode: Configuration<T>,
  98. ) -> PwmInput<TIM2, REMAP, PINS>
  99. where
  100. REMAP: Remap<Periph = TIM2>,
  101. PINS: Pins<REMAP>,
  102. T: Into<Hertz>,
  103. {
  104. mapr.modify_mapr(|_, w| unsafe { w.tim2_remap().bits(REMAP::REMAP) });
  105. self.stop_in_debug(dbg, false);
  106. let Self { tim, clk } = self;
  107. tim2(tim, pins, clk, mode)
  108. }
  109. }
  110. impl Timer<TIM3> {
  111. pub fn pwm_input<REMAP, PINS, T>(
  112. mut self,
  113. pins: PINS,
  114. mapr: &mut MAPR,
  115. dbg: &mut DBG,
  116. mode: Configuration<T>,
  117. ) -> PwmInput<TIM3, REMAP, PINS>
  118. where
  119. REMAP: Remap<Periph = TIM3>,
  120. PINS: Pins<REMAP>,
  121. T: Into<Hertz>,
  122. {
  123. mapr.modify_mapr(|_, w| unsafe { w.tim3_remap().bits(REMAP::REMAP) });
  124. self.stop_in_debug(dbg, false);
  125. let Self { tim, clk } = self;
  126. tim3(tim, pins, clk, mode)
  127. }
  128. }
  129. #[cfg(feature = "medium")]
  130. impl Timer<TIM4> {
  131. pub fn pwm_input<REMAP, PINS, T>(
  132. mut self,
  133. pins: PINS,
  134. mapr: &mut MAPR,
  135. dbg: &mut DBG,
  136. mode: Configuration<T>,
  137. ) -> PwmInput<TIM4, REMAP, PINS>
  138. where
  139. REMAP: Remap<Periph = TIM4>,
  140. PINS: Pins<REMAP>,
  141. T: Into<Hertz>,
  142. {
  143. mapr.modify_mapr(|_, w| w.tim4_remap().bit(REMAP::REMAP == 1));
  144. self.stop_in_debug(dbg, false);
  145. let Self { tim, clk } = self;
  146. tim4(tim, pins, clk, mode)
  147. }
  148. }
  149. /// Courtesy of @TeXitoi (https://github.com/stm32-rs/stm32f1xx-hal/pull/10#discussion_r259535503)
  150. fn compute_arr_presc(freq: u32, clock: u32) -> (u16, u16) {
  151. if freq == 0 {
  152. return (core::u16::MAX, core::u16::MAX);
  153. }
  154. let presc = clock / freq.saturating_mul(core::u16::MAX as u32 + 1);
  155. let arr = clock / freq.saturating_mul(presc + 1);
  156. (core::cmp::max(1, arr as u16), presc as u16)
  157. }
  158. macro_rules! hal {
  159. ($($TIMX:ident: ($timX:ident),)+) => {
  160. $(
  161. fn $timX<REMAP, PINS,T>(
  162. tim: $TIMX,
  163. _pins: PINS,
  164. clk: Hertz,
  165. mode : Configuration<T>,
  166. ) -> PwmInput<$TIMX, REMAP, PINS>
  167. where
  168. REMAP: Remap<Periph = $TIMX>,
  169. PINS: Pins<REMAP>,
  170. T : Into<Hertz>
  171. {
  172. use crate::pwm_input::Configuration::*;
  173. // Disable capture on both channels during setting
  174. // (for Channel X bit is CCXE)
  175. tim.ccer.modify(|_,w| w.cc1e().clear_bit().cc2e().clear_bit()
  176. .cc1p().clear_bit().cc2p().set_bit());
  177. // Define the direction of the channel (input/output)
  178. // and the used input
  179. tim.ccmr1_input().modify( |_,w| w.cc1s().ti1().cc2s().ti1());
  180. tim.dier.write(|w| w.cc1ie().set_bit());
  181. // Configure slave mode control register
  182. // Selects the trigger input to be used to synchronize the counter
  183. // 101: Filtered Timer Input 1 (TI1FP1)
  184. // ---------------------------------------
  185. // Slave Mode Selection :
  186. // 100: Reset Mode - Rising edge of the selected trigger input (TRGI)
  187. // reinitializes the counter and generates an update of the registers.
  188. tim.smcr.modify( |_,w| unsafe {w.ts().bits(0b101).sms().bits(0b100)});
  189. match mode {
  190. Frequency(f) => {
  191. let freq = f.into().0;
  192. let max_freq = if freq > 5 {freq/5} else {1};
  193. let (arr,presc) = compute_arr_presc(max_freq, clk.0);
  194. tim.arr.write(|w| w.arr().bits(arr));
  195. tim.psc.write(|w| w.psc().bits(presc) );
  196. },
  197. DutyCycle(f) => {
  198. let freq = f.into().0;
  199. let max_freq = if freq > 2 {freq/2 + freq/4 + freq/8} else {1};
  200. let (arr,presc) = compute_arr_presc(max_freq, clk.0);
  201. tim.arr.write(|w| w.arr().bits(arr));
  202. tim.psc.write(|w| w.psc().bits(presc) );
  203. },
  204. RawFrequency(f) => {
  205. let freq = f.into().0;
  206. let (arr,presc) = compute_arr_presc(freq, clk.0);
  207. tim.arr.write(|w| w.arr().bits(arr));
  208. tim.psc.write(|w| w.psc().bits(presc) );
  209. }
  210. RawValues{arr, presc} => {
  211. tim.arr.write(|w| w.arr().bits(arr));
  212. tim.psc.write(|w| w.psc().bits(presc) );
  213. }
  214. }
  215. // Enable Capture on both channels
  216. tim.ccer.modify(|_,w| w.cc1e().set_bit().cc2e().set_bit());
  217. tim.cr1.modify(|_,w| w.cen().set_bit());
  218. unsafe { mem::MaybeUninit::uninit().assume_init() }
  219. }
  220. impl<REMAP, PINS> PwmInput<$TIMX, REMAP, PINS>
  221. where
  222. REMAP: Remap<Periph = $TIMX>,
  223. PINS: Pins<REMAP>,
  224. {
  225. /// Return the frequency sampled by the timer
  226. pub fn read_frequency(&self, mode : ReadMode, clocks : &Clocks) -> Result<Hertz,Error> {
  227. if let ReadMode::WaitForNextCapture = mode {
  228. self.wait_for_capture();
  229. }
  230. let presc = unsafe { (*$TIMX::ptr()).psc.read().bits() as u16};
  231. let ccr1 = unsafe { (*$TIMX::ptr()).ccr1.read().bits() as u16};
  232. // Formulas :
  233. //
  234. // F_timer = F_pclk / (PSC+1)*(ARR+1)
  235. // Frac_arr = (CCR1+1)/(ARR+1)
  236. // F_signal = F_timer/Frac_arr
  237. // <=> F_signal = [(F_plck)/((PSC+1)*(ARR+1))] * [(ARR+1)/(CCR1+1)]
  238. // <=> F_signal = F_pclk / ((PSC+1)*(CCR1+1))
  239. //
  240. // Where :
  241. // * PSC is the prescaler register
  242. // * ARR is the auto-reload register
  243. // * F_timer is the number of time per second where the timer overflow under normal
  244. // condition
  245. //
  246. if ccr1 == 0 {
  247. Err(Error::FrequencyTooLow)
  248. } else {
  249. let clk : u32 = <$TIMX as RccBus>::Bus::get_timer_frequency(&clocks).0;
  250. Ok(Hertz(clk/((presc+1) as u32*(ccr1 + 1)as u32)))
  251. }
  252. }
  253. /// Return the duty in the form of a fraction : (duty_cycle/period)
  254. pub fn read_duty(&self, mode : ReadMode) -> Result<(u16,u16),Error> {
  255. if let ReadMode::WaitForNextCapture = mode {
  256. self.wait_for_capture();
  257. }
  258. // Formulas :
  259. // Duty_cycle = (CCR2+1)/(CCR1+1)
  260. let ccr1 = unsafe { (*$TIMX::ptr()).ccr1.read().bits() as u16};
  261. let ccr2 = unsafe { (*$TIMX::ptr()).ccr2.read().bits() as u16};
  262. if ccr1 == 0 {
  263. Err(Error::FrequencyTooLow)
  264. } else {
  265. Ok((ccr2,ccr1))
  266. }
  267. }
  268. /// Wait until the timer has captured a period
  269. fn wait_for_capture(&self) {
  270. unsafe { (*$TIMX::ptr()).sr.write(|w| w.uif().clear_bit().cc1if().clear_bit().cc1of().clear_bit())};
  271. while unsafe { (*$TIMX::ptr()).sr.read().cc1if().bit_is_clear()} {}
  272. }
  273. }
  274. )+
  275. }
  276. }
  277. #[cfg(any(feature = "stm32f100", feature = "stm32f103", feature = "connectivity",))]
  278. hal! {
  279. TIM1: (tim1),
  280. }
  281. hal! {
  282. TIM2: (tim2),
  283. TIM3: (tim3),
  284. }
  285. #[cfg(feature = "medium")]
  286. hal! {
  287. TIM4: (tim4),
  288. }