aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/timer/input_capture.rs
diff options
context:
space:
mode:
authorBruno Bousquet <[email protected]>2024-05-06 02:47:42 -0400
committerBruno Bousquet <[email protected]>2024-05-06 02:47:42 -0400
commit55c8d3f4743bc653c1659dc3e961df86afe7d3db (patch)
tree3ec6a5afaf16d4a7aa38fd532a661e597a832acd /embassy-stm32/src/timer/input_capture.rs
parentb662dfb1838a72d243e939da9349c68c8fef5bdc (diff)
add async capture
Diffstat (limited to 'embassy-stm32/src/timer/input_capture.rs')
-rw-r--r--embassy-stm32/src/timer/input_capture.rs100
1 files changed, 93 insertions, 7 deletions
diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs
index bc7614cda..e5ec2505a 100644
--- a/embassy-stm32/src/timer/input_capture.rs
+++ b/embassy-stm32/src/timer/input_capture.rs
@@ -1,12 +1,17 @@
1//! Input capture driver. 1//! Input capture driver.
2 2
3use core::future::Future;
3use core::marker::PhantomData; 4use core::marker::PhantomData;
5use core::pin::Pin;
6use core::task::{Context, Poll};
4 7
5use embassy_hal_internal::{into_ref, PeripheralRef}; 8use embassy_hal_internal::{into_ref, PeripheralRef};
6 9
7use super::low_level::{CountingMode, InputCaptureMode, InputTISelection, Timer}; 10use super::low_level::{CountingMode, InputCaptureMode, InputTISelection, Timer};
11use super::CaptureCompareInterruptHandler;
8use super::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance4Channel}; 12use super::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance4Channel};
9use crate::gpio::{AFType, AnyPin, Pull}; 13use crate::gpio::{AFType, AnyPin, Pull};
14use crate::interrupt::typelevel::{Binding, Interrupt};
10use crate::time::Hertz; 15use crate::time::Hertz;
11use crate::Peripheral; 16use crate::Peripheral;
12 17
@@ -65,6 +70,7 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
65 _ch2: Option<CapturePin<'d, T, Ch2>>, 70 _ch2: Option<CapturePin<'d, T, Ch2>>,
66 _ch3: Option<CapturePin<'d, T, Ch3>>, 71 _ch3: Option<CapturePin<'d, T, Ch3>>,
67 _ch4: Option<CapturePin<'d, T, Ch4>>, 72 _ch4: Option<CapturePin<'d, T, Ch4>>,
73 _irq: impl Binding<T::CaptureCompareInterrupt, CaptureCompareInterruptHandler<T>> + 'd,
68 freq: Hertz, 74 freq: Hertz,
69 counting_mode: CountingMode, 75 counting_mode: CountingMode,
70 ) -> Self { 76 ) -> Self {
@@ -79,13 +85,9 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
79 this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details 85 this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details
80 this.inner.start(); 86 this.inner.start();
81 87
82 [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4] 88 // enable NVIC interrupt
83 .iter() 89 T::CaptureCompareInterrupt::unpend();
84 .for_each(|&channel| { 90 unsafe { T::CaptureCompareInterrupt::enable() };
85 this.inner.set_input_capture_mode(channel, InputCaptureMode::Rising);
86
87 this.inner.set_input_ti_selection(channel, InputTISelection::Normal);
88 });
89 91
90 this 92 this
91 } 93 }
@@ -142,4 +144,88 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
142 pub fn get_input_interrupt(&self, channel: Channel) -> bool { 144 pub fn get_input_interrupt(&self, channel: Channel) -> bool {
143 self.inner.get_input_interrupt(channel) 145 self.inner.get_input_interrupt(channel)
144 } 146 }
147
148 fn new_future(&self, channel: Channel, mode: InputCaptureMode, tisel: InputTISelection) -> InputCaptureFuture<T> {
149 self.inner.enable_channel(channel, true);
150 self.inner.set_input_capture_mode(channel, mode);
151 self.inner.set_input_ti_selection(channel, tisel);
152 self.inner.clear_input_interrupt(channel);
153 self.inner.enable_input_interrupt(channel, true);
154
155 InputCaptureFuture {
156 channel,
157 phantom: PhantomData,
158 }
159 }
160
161 /// Asynchronously wait until the pin sees a rising edge.
162 pub async fn wait_for_rising_edge(&mut self, channel: Channel) -> u32 {
163 self.new_future(channel, InputCaptureMode::Rising, InputTISelection::Normal)
164 .await
165 }
166
167 /// Asynchronously wait until the pin sees a falling edge.
168 pub async fn wait_for_falling_edge(&mut self, channel: Channel) -> u32 {
169 self.new_future(channel, InputCaptureMode::Falling, InputTISelection::Normal)
170 .await
171 }
172
173 /// Asynchronously wait until the pin sees any edge.
174 pub async fn wait_for_any_edge(&mut self, channel: Channel) -> u32 {
175 self.new_future(channel, InputCaptureMode::BothEdges, InputTISelection::Normal)
176 .await
177 }
178
179 /// Asynchronously wait until the (alternate) pin sees a rising edge.
180 pub async fn wait_for_rising_edge_alternate(&mut self, channel: Channel) -> u32 {
181 self.new_future(channel, InputCaptureMode::Rising, InputTISelection::Alternate)
182 .await
183 }
184
185 /// Asynchronously wait until the (alternate) pin sees a falling edge.
186 pub async fn wait_for_falling_edge_alternate(&mut self, channel: Channel) -> u32 {
187 self.new_future(channel, InputCaptureMode::Falling, InputTISelection::Alternate)
188 .await
189 }
190
191 /// Asynchronously wait until the (alternate) pin sees any edge.
192 pub async fn wait_for_any_edge_alternate(&mut self, channel: Channel) -> u32 {
193 self.new_future(channel, InputCaptureMode::BothEdges, InputTISelection::Alternate)
194 .await
195 }
196}
197
198#[must_use = "futures do nothing unless you `.await` or poll them"]
199struct InputCaptureFuture<T: GeneralInstance4Channel> {
200 channel: Channel,
201 phantom: PhantomData<T>,
202}
203
204impl<T: GeneralInstance4Channel> Drop for InputCaptureFuture<T> {
205 fn drop(&mut self) {
206 critical_section::with(|_| {
207 let regs = unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) };
208
209 // disable interrupt enable
210 regs.dier().modify(|w| w.set_ccie(self.channel.index(), false));
211 });
212 }
213}
214
215impl<T: GeneralInstance4Channel> Future for InputCaptureFuture<T> {
216 type Output = u32;
217
218 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
219 T::state().cc_waker[self.channel.index()].register(cx.waker());
220
221 let regs = unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) };
222
223 let dier = regs.dier().read();
224 if !dier.ccie(self.channel.index()) {
225 let val = regs.ccr(self.channel.index()).read().0;
226 Poll::Ready(val)
227 } else {
228 Poll::Pending
229 }
230 }
145} 231}