1use core::future::Future;
8use core::marker::PhantomData;
9use core::pin::Pin;
10use core::task::{Context, Poll};
11
12use embassy_hal_internal::{into_ref, PeripheralRef};
13
14use super::low_level::{CountingMode, FilterValue, InputCaptureMode, InputTISelection, Timer};
15use super::{
16 CaptureCompareInterruptHandler, Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin,
17 GeneralInstance4Channel,
18};
19use crate::gpio::{AfType, AnyPin, Pull};
20use crate::interrupt::typelevel::{Binding, Interrupt};
21use crate::time::Hertz;
22use crate::Peripheral;
23
24pub enum Ch1 {}
26pub enum Ch2 {}
28pub enum Ch3 {}
30pub enum Ch4 {}
32
33pub struct CapturePin<'d, T, C> {
37 _pin: PeripheralRef<'d, AnyPin>,
38 phantom: PhantomData<(T, C)>,
39}
40
41macro_rules! channel_impl {
42 ($new_chx:ident, $channel:ident, $pin_trait:ident) => {
43 impl<'d, T: GeneralInstance4Channel> CapturePin<'d, T, $channel> {
44 #[doc = concat!("Create a new ", stringify!($channel), " capture pin instance.")]
45 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, pull: Pull) -> Self {
46 into_ref!(pin);
47 pin.set_as_af(pin.af_num(), AfType::input(pull));
48 CapturePin {
49 _pin: pin.map_into(),
50 phantom: PhantomData,
51 }
52 }
53 }
54 };
55}
56
57channel_impl!(new_ch1, Ch1, Channel1Pin);
58channel_impl!(new_ch2, Ch2, Channel2Pin);
59channel_impl!(new_ch3, Ch3, Channel3Pin);
60channel_impl!(new_ch4, Ch4, Channel4Pin);
61
62pub struct InputCapture<'d, T: GeneralInstance4Channel> {
64 inner: Timer<'d, T>,
65}
66
67impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
68 pub fn new(
70 tim: impl Peripheral<P = T> + 'd,
71 _ch1: Option<CapturePin<'d, T, Ch1>>,
72 _ch2: Option<CapturePin<'d, T, Ch2>>,
73 _ch3: Option<CapturePin<'d, T, Ch3>>,
74 _ch4: Option<CapturePin<'d, T, Ch4>>,
75 _irq: impl Binding<T::CaptureCompareInterrupt, CaptureCompareInterruptHandler<T>> + 'd,
76 freq: Hertz,
77 counting_mode: CountingMode,
78 ) -> Self {
79 Self::new_inner(tim, freq, counting_mode)
80 }
81
82 fn new_inner(
83 tim: impl Peripheral<P = T> + 'd,
84 freq: Hertz,
85 counting_mode: CountingMode,
86 ) -> Self {
87 let mut this = Self {
88 inner: Timer::new(tim),
89 };
90
91 this.inner.set_counting_mode(counting_mode);
92 this.inner.set_tick_freq(freq);
93 this.inner.enable_outputs(); this.inner.start();
95
96 T::CaptureCompareInterrupt::unpend();
98 unsafe { T::CaptureCompareInterrupt::enable() };
99
100 this
101 }
102
103 pub fn enable(&mut self, channel: Channel) {
105 self.inner.enable_channel(channel, true);
106 }
107
108 pub fn disable(&mut self, channel: Channel) {
110 self.inner.enable_channel(channel, false);
111 }
112
113 pub fn is_enabled(&self, channel: Channel) -> bool {
115 self.inner.get_channel_enable_state(channel)
116 }
117
118 pub fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
120 self.inner.set_input_capture_mode(channel, mode);
121 }
122
123 pub fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
125 self.inner.set_input_ti_selection(channel, tisel)
126 }
127
128 pub fn get_capture_value(&self, channel: Channel) -> u32 {
130 self.inner.get_capture_value(channel)
131 }
132
133 pub fn get_input_interrupt(&self, channel: Channel) -> bool {
135 self.inner.get_input_interrupt(channel)
136 }
137
138 fn new_future(
139 &self,
140 channel: Channel,
141 mode: InputCaptureMode,
142 tisel: InputTISelection,
143 ) -> InputCaptureFuture<T> {
144 self.inner.set_input_ti_selection(channel, tisel);
147 self.inner
148 .set_input_capture_filter(channel, FilterValue::NOFILTER);
149 self.inner.set_input_capture_mode(channel, mode);
150 self.inner.set_input_capture_prescaler(channel, 0);
151 self.inner.enable_channel(channel, true);
152 self.inner.enable_input_interrupt(channel, true);
153
154 InputCaptureFuture {
155 channel,
156 phantom: PhantomData,
157 }
158 }
159
160 pub async fn wait_for_rising_edge(&mut self, channel: Channel) -> u32 {
162 self.new_future(channel, InputCaptureMode::Rising, InputTISelection::Normal)
163 .await
164 }
165
166 pub async fn wait_for_falling_edge(&mut self, channel: Channel) -> u32 {
168 self.new_future(channel, InputCaptureMode::Falling, InputTISelection::Normal)
169 .await
170 }
171
172 pub async fn wait_for_any_edge(&mut self, channel: Channel) -> u32 {
174 self.new_future(
175 channel,
176 InputCaptureMode::BothEdges,
177 InputTISelection::Normal,
178 )
179 .await
180 }
181
182 pub async fn wait_for_rising_edge_alternate(&mut self, channel: Channel) -> u32 {
184 self.new_future(
185 channel,
186 InputCaptureMode::Rising,
187 InputTISelection::Alternate,
188 )
189 .await
190 }
191
192 pub async fn wait_for_falling_edge_alternate(&mut self, channel: Channel) -> u32 {
194 self.new_future(
195 channel,
196 InputCaptureMode::Falling,
197 InputTISelection::Alternate,
198 )
199 .await
200 }
201
202 pub async fn wait_for_any_edge_alternate(&mut self, channel: Channel) -> u32 {
204 self.new_future(
205 channel,
206 InputCaptureMode::BothEdges,
207 InputTISelection::Alternate,
208 )
209 .await
210 }
211}
212
213#[must_use = "futures do nothing unless you `.await` or poll them"]
214struct InputCaptureFuture<T: GeneralInstance4Channel> {
215 channel: Channel,
216 phantom: PhantomData<T>,
217}
218
219impl<T: GeneralInstance4Channel> Drop for InputCaptureFuture<T> {
220 fn drop(&mut self) {
221 critical_section::with(|_| {
222 let regs = unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) };
223
224 regs.dier()
226 .modify(|w| w.set_ccie(self.channel.index(), false));
227 });
228 }
229}
230
231impl<T: GeneralInstance4Channel> Future for InputCaptureFuture<T> {
232 type Output = u32;
233
234 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
235 T::state().cc_waker[self.channel.index()].register(cx.waker());
236
237 let regs = unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) };
238
239 let dier = regs.dier().read();
240 if !dier.ccie(self.channel.index()) {
241 let val = regs.ccr(self.channel.index()).read().0;
242 Poll::Ready(val)
243 } else {
244 Poll::Pending
245 }
246 }
247}