embassy_stm32/timer/
pwm_input.rs1use super::low_level::{CountingMode, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource};
4use super::{Ch1, Ch2, Channel, GeneralInstance4Channel, TimerPin};
5use crate::gpio::{AfType, Pull};
6use crate::time::Hertz;
7use crate::Peri;
8
9pub struct PwmInput<'d, T: GeneralInstance4Channel> {
15 channel: Channel,
16 inner: Timer<'d, T>,
17}
18
19impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
20 pub fn new_ch1(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch1>>, pull: Pull, freq: Hertz) -> Self {
22 pin.set_as_af(pin.af_num(), AfType::input(pull));
23
24 Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2)
25 }
26
27 pub fn new_ch2(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch2>>, pull: Pull, freq: Hertz) -> Self {
29 pin.set_as_af(pin.af_num(), AfType::input(pull));
30
31 Self::new_inner(tim, freq, Channel::Ch2, Channel::Ch1)
32 }
33
34 fn new_inner(tim: Peri<'d, T>, freq: Hertz, ch1: Channel, ch2: Channel) -> Self {
35 let mut inner = Timer::new(tim);
36
37 inner.set_counting_mode(CountingMode::EdgeAlignedUp);
38 inner.set_tick_freq(freq);
39 inner.enable_outputs(); inner.start();
41
42 inner.set_input_ti_selection(ch1, InputTISelection::Normal);
46 inner.set_input_capture_mode(ch1, InputCaptureMode::Rising);
47
48 inner.set_input_ti_selection(ch2, InputTISelection::Alternate);
49 inner.set_input_capture_mode(ch2, InputCaptureMode::Falling);
50
51 inner.set_trigger_source(match ch1 {
52 Channel::Ch1 => TriggerSource::TI1FP1,
53 Channel::Ch2 => TriggerSource::TI2FP2,
54 _ => panic!("Invalid channel for PWM input"),
55 });
56
57 inner.set_slave_mode(SlaveMode::RESET_MODE);
58
59 Self { channel: ch1, inner }
62 }
63
64 pub fn enable(&mut self) {
66 self.inner.enable_channel(Channel::Ch1, true);
67 self.inner.enable_channel(Channel::Ch2, true);
68 }
69
70 pub fn disable(&mut self) {
72 self.inner.enable_channel(Channel::Ch1, false);
73 self.inner.enable_channel(Channel::Ch2, false);
74 }
75
76 pub fn is_enabled(&self) -> bool {
78 self.inner.get_channel_enable_state(Channel::Ch1)
79 }
80
81 pub fn get_period_ticks(&self) -> u32 {
83 self.inner.get_capture_value(self.channel)
84 }
85
86 pub fn get_width_ticks(&self) -> u32 {
88 self.inner.get_capture_value(match self.channel {
89 Channel::Ch1 => Channel::Ch2,
90 Channel::Ch2 => Channel::Ch1,
91 _ => panic!("Invalid channel for PWM input"),
92 })
93 }
94
95 pub fn get_duty_cycle(&self) -> f32 {
97 let period = self.get_period_ticks();
98 if period == 0 {
99 return 0.;
100 }
101 100. * (self.get_width_ticks() as f32) / (period as f32)
102 }
103}