aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/timer/input_capture.rs
diff options
context:
space:
mode:
authorBruno Bousquet <[email protected]>2024-05-05 21:58:54 -0400
committerBruno Bousquet <[email protected]>2024-05-05 21:58:54 -0400
commitad66dc3aabe6ac11dd0f3aa4d9f403e3aac7e8f4 (patch)
tree2c62239324aefb1515ae122b16b9be4297e6c1a2 /embassy-stm32/src/timer/input_capture.rs
parent15c3ae8ef6abaf37704e3278a1de6b2ae259aa15 (diff)
create input_capture
Diffstat (limited to 'embassy-stm32/src/timer/input_capture.rs')
-rw-r--r--embassy-stm32/src/timer/input_capture.rs141
1 files changed, 141 insertions, 0 deletions
diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs
new file mode 100644
index 000000000..6401656c8
--- /dev/null
+++ b/embassy-stm32/src/timer/input_capture.rs
@@ -0,0 +1,141 @@
1//! Input capture driver.
2
3use core::marker::PhantomData;
4
5use embassy_hal_internal::{into_ref, PeripheralRef};
6use embassy_sync::channel;
7
8use super::low_level::{CountingMode, InputCaptureMode, InputTISelection, Timer};
9use super::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance4Channel};
10use crate::gpio::{AFType, AnyPin, Pull};
11use crate::time::Hertz;
12use crate::Peripheral;
13
14/// Channel 1 marker type.
15pub enum Ch1 {}
16/// Channel 2 marker type.
17pub enum Ch2 {}
18/// Channel 3 marker type.
19pub enum Ch3 {}
20/// Channel 4 marker type.
21pub enum Ch4 {}
22
23/// Capture pin wrapper.
24///
25/// This wraps a pin to make it usable with capture.
26pub struct CapturePin<'d, T, C> {
27 _pin: PeripheralRef<'d, AnyPin>,
28 phantom: PhantomData<(T, C)>,
29}
30
31macro_rules! channel_impl {
32 ($new_chx:ident, $channel:ident, $pin_trait:ident) => {
33 impl<'d, T: GeneralInstance4Channel> CapturePin<'d, T, $channel> {
34 #[doc = concat!("Create a new ", stringify!($channel), " capture pin instance.")]
35 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, pull_type: Pull) -> Self {
36 into_ref!(pin);
37 critical_section::with(|_| {
38 pin.set_as_af_pull(pin.af_num(), AFType::Input, pull_type);
39 #[cfg(gpio_v2)]
40 pin.set_speed(crate::gpio::Speed::VeryHigh);
41 });
42 CapturePin {
43 _pin: pin.map_into(),
44 phantom: PhantomData,
45 }
46 }
47 }
48 };
49}
50
51channel_impl!(new_ch1, Ch1, Channel1Pin);
52channel_impl!(new_ch2, Ch2, Channel2Pin);
53channel_impl!(new_ch3, Ch3, Channel3Pin);
54channel_impl!(new_ch4, Ch4, Channel4Pin);
55
56/// Input capture driver.
57pub struct InputCapture<'d, T: GeneralInstance4Channel> {
58 inner: Timer<'d, T>,
59}
60
61impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
62 /// Create a new input capture driver.
63 pub fn new(
64 tim: impl Peripheral<P = T> + 'd,
65 _ch1: Option<CapturePin<'d, T, Ch1>>,
66 _ch2: Option<CapturePin<'d, T, Ch2>>,
67 _ch3: Option<CapturePin<'d, T, Ch3>>,
68 _ch4: Option<CapturePin<'d, T, Ch4>>,
69 freq: Hertz,
70 counting_mode: CountingMode,
71 ) -> Self {
72 Self::new_inner(tim, freq, counting_mode)
73 }
74
75 fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz, counting_mode: CountingMode) -> Self {
76 let mut this = Self { inner: Timer::new(tim) };
77
78 this.inner.set_counting_mode(counting_mode);
79 this.set_tick_freq(freq);
80 this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details
81 this.inner.start();
82
83 [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4]
84 .iter()
85 .for_each(|&channel| {
86 this.inner.set_input_capture_mode(channel, InputCaptureMode::Rising);
87
88 this.inner.set_input_ti_selection(channel, InputTISelection::Normal);
89 });
90
91 this
92 }
93
94 /// Enable the given channel.
95 pub fn enable(&mut self, channel: Channel) {
96 self.inner.enable_channel(channel, true);
97 }
98
99 /// Disable the given channel.
100 pub fn disable(&mut self, channel: Channel) {
101 self.inner.enable_channel(channel, false);
102 }
103
104 /// Check whether given channel is enabled
105 pub fn is_enabled(&self, channel: Channel) -> bool {
106 self.inner.get_channel_enable_state(channel)
107 }
108
109 /// Set tick frequency.
110 ///
111 /// Note: when you call this, the max period value changes
112 pub fn set_tick_freq(&mut self, freq: Hertz) {
113 let f = freq;
114 assert!(f.0 > 0);
115 let timer_f = self.inner.get_clock_frequency();
116
117 let pclk_ticks_per_timer_period = timer_f / f;
118 let psc: u16 = unwrap!((pclk_ticks_per_timer_period - 1).try_into());
119
120 let regs = self.inner.regs_core();
121 regs.psc().write_value(psc);
122
123 // Generate an Update Request
124 regs.egr().write(|r| r.set_ug(true));
125 }
126
127 /// Set the input capture mode for a given channel.
128 pub fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
129 self.inner.set_input_capture_mode(channel, mode);
130 }
131
132 /// Set input TI selection.
133 pub fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
134 self.inner.set_input_ti_selection(channel, tisel)
135 }
136
137 /// Get capture value for a channel.
138 pub fn get_capture_value(&self, channel: Channel) -> u32 {
139 self.inner.get_capture_value(channel)
140 }
141}