pwm_input.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  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 = "stm32f105",))]
  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 = "stm32f105",))]
  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. match mode {
  228. ReadMode::WaitForNextCapture => self.wait_for_capture(),
  229. _ => (),
  230. }
  231. let presc = unsafe { (*$TIMX::ptr()).psc.read().bits() as u16};
  232. let ccr1 = unsafe { (*$TIMX::ptr()).ccr1.read().bits() as u16};
  233. // Formulas :
  234. //
  235. // F_timer = F_pclk / (PSC+1)*(ARR+1)
  236. // Frac_arr = (CCR1+1)/(ARR+1)
  237. // F_signal = F_timer/Frac_arr
  238. // <=> F_signal = [(F_plck)/((PSC+1)*(ARR+1))] * [(ARR+1)/(CCR1+1)]
  239. // <=> F_signal = F_pclk / ((PSC+1)*(CCR1+1))
  240. //
  241. // Where :
  242. // * PSC is the prescaler register
  243. // * ARR is the auto-reload register
  244. // * F_timer is the number of time per second where the timer overflow under normal
  245. // condition
  246. //
  247. if ccr1 == 0 {
  248. Err(Error::FrequencyTooLow)
  249. } else {
  250. let clk : u32 = <$TIMX as RccBus>::Bus::get_timer_frequency(&clocks).0;
  251. Ok(Hertz(clk/((presc+1) as u32*(ccr1 + 1)as u32)))
  252. }
  253. }
  254. /// Return the duty in the form of a fraction : (duty_cycle/period)
  255. pub fn read_duty(&self, mode : ReadMode) -> Result<(u16,u16),Error> {
  256. match mode {
  257. ReadMode::WaitForNextCapture => self.wait_for_capture(),
  258. _ => (),
  259. }
  260. // Formulas :
  261. // Duty_cycle = (CCR2+1)/(CCR1+1)
  262. let ccr1 = unsafe { (*$TIMX::ptr()).ccr1.read().bits() as u16};
  263. let ccr2 = unsafe { (*$TIMX::ptr()).ccr2.read().bits() as u16};
  264. if ccr1 == 0 {
  265. Err(Error::FrequencyTooLow)
  266. } else {
  267. Ok((ccr2,ccr1))
  268. }
  269. }
  270. /// Wait until the timer has captured a period
  271. fn wait_for_capture(&self) {
  272. unsafe { (*$TIMX::ptr()).sr.write(|w| w.uif().clear_bit().cc1if().clear_bit().cc1of().clear_bit())};
  273. while unsafe { (*$TIMX::ptr()).sr.read().cc1if().bit_is_clear()} {}
  274. }
  275. }
  276. )+
  277. }
  278. }
  279. #[cfg(any(feature = "stm32f100", feature = "stm32f103", feature = "stm32f105",))]
  280. hal! {
  281. TIM1: (tim1),
  282. }
  283. hal! {
  284. TIM2: (tim2),
  285. TIM3: (tim3),
  286. }
  287. #[cfg(feature = "medium")]
  288. hal! {
  289. TIM4: (tim4),
  290. }