1use core::future::Future;
4use core::marker::PhantomData;
5use core::pin::Pin;
6use core::task::{Context, Poll};
7
8use super::low_level::{CountingMode, FilterValue, InputCaptureMode, InputTISelection, Timer};
9use super::{CaptureCompareInterruptHandler, Channel, GeneralInstance4Channel, TimerPin};
10pub use super::{Ch1, Ch2, Ch3, Ch4};
11use crate::gpio::{AfType, AnyPin, Pull};
12use crate::interrupt::typelevel::{Binding, Interrupt};
13use crate::time::Hertz;
14use crate::timer::TimerChannel;
15use crate::Peri;
16
17pub struct CapturePin<'d, T, C> {
21 _pin: Peri<'d, AnyPin>,
22 phantom: PhantomData<(T, C)>,
23}
24impl<'d, T: GeneralInstance4Channel, C: TimerChannel> CapturePin<'d, T, C> {
25 pub fn new(pin: Peri<'d, impl TimerPin<T, C>>, pull: Pull) -> Self {
27 pin.set_as_af(pin.af_num(), AfType::input(pull));
28 CapturePin {
29 _pin: pin.into(),
30 phantom: PhantomData,
31 }
32 }
33}
34
35pub struct InputCapture<'d, T: GeneralInstance4Channel> {
37 inner: Timer<'d, T>,
38}
39
40impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
41 pub fn new(
43 tim: Peri<'d, T>,
44 _ch1: Option<CapturePin<'d, T, Ch1>>,
45 _ch2: Option<CapturePin<'d, T, Ch2>>,
46 _ch3: Option<CapturePin<'d, T, Ch3>>,
47 _ch4: Option<CapturePin<'d, T, Ch4>>,
48 _irq: impl Binding<T::CaptureCompareInterrupt, CaptureCompareInterruptHandler<T>> + 'd,
49 freq: Hertz,
50 counting_mode: CountingMode,
51 ) -> Self {
52 Self::new_inner(tim, freq, counting_mode)
53 }
54
55 fn new_inner(tim: Peri<'d, T>, freq: Hertz, counting_mode: CountingMode) -> Self {
56 let mut this = Self { inner: Timer::new(tim) };
57
58 this.inner.set_counting_mode(counting_mode);
59 this.inner.set_tick_freq(freq);
60 this.inner.enable_outputs(); this.inner.start();
62
63 T::CaptureCompareInterrupt::unpend();
65 unsafe { T::CaptureCompareInterrupt::enable() };
66
67 this
68 }
69
70 pub fn enable(&mut self, channel: Channel) {
72 self.inner.enable_channel(channel, true);
73 }
74
75 pub fn disable(&mut self, channel: Channel) {
77 self.inner.enable_channel(channel, false);
78 }
79
80 pub fn is_enabled(&self, channel: Channel) -> bool {
82 self.inner.get_channel_enable_state(channel)
83 }
84
85 pub fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
87 self.inner.set_input_capture_mode(channel, mode);
88 }
89
90 pub fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
92 self.inner.set_input_ti_selection(channel, tisel)
93 }
94
95 pub fn get_capture_value(&self, channel: Channel) -> u32 {
97 self.inner.get_capture_value(channel)
98 }
99
100 pub fn get_input_interrupt(&self, channel: Channel) -> bool {
102 self.inner.get_input_interrupt(channel)
103 }
104
105 fn new_future(&self, channel: Channel, mode: InputCaptureMode, tisel: InputTISelection) -> InputCaptureFuture<T> {
106 self.inner.set_input_ti_selection(channel, tisel);
109 self.inner.set_input_capture_filter(channel, FilterValue::NO_FILTER);
110 self.inner.set_input_capture_mode(channel, mode);
111 self.inner.set_input_capture_prescaler(channel, 0);
112 self.inner.enable_channel(channel, true);
113 self.inner.enable_input_interrupt(channel, true);
114
115 InputCaptureFuture {
116 channel,
117 phantom: PhantomData,
118 }
119 }
120
121 pub async fn wait_for_rising_edge(&mut self, channel: Channel) -> u32 {
123 self.new_future(channel, InputCaptureMode::Rising, InputTISelection::Normal)
124 .await
125 }
126
127 pub async fn wait_for_falling_edge(&mut self, channel: Channel) -> u32 {
129 self.new_future(channel, InputCaptureMode::Falling, InputTISelection::Normal)
130 .await
131 }
132
133 pub async fn wait_for_any_edge(&mut self, channel: Channel) -> u32 {
135 self.new_future(channel, InputCaptureMode::BothEdges, InputTISelection::Normal)
136 .await
137 }
138
139 pub async fn wait_for_rising_edge_alternate(&mut self, channel: Channel) -> u32 {
141 self.new_future(channel, InputCaptureMode::Rising, InputTISelection::Alternate)
142 .await
143 }
144
145 pub async fn wait_for_falling_edge_alternate(&mut self, channel: Channel) -> u32 {
147 self.new_future(channel, InputCaptureMode::Falling, InputTISelection::Alternate)
148 .await
149 }
150
151 pub async fn wait_for_any_edge_alternate(&mut self, channel: Channel) -> u32 {
153 self.new_future(channel, InputCaptureMode::BothEdges, InputTISelection::Alternate)
154 .await
155 }
156}
157
158#[must_use = "futures do nothing unless you `.await` or poll them"]
159struct InputCaptureFuture<T: GeneralInstance4Channel> {
160 channel: Channel,
161 phantom: PhantomData<T>,
162}
163
164impl<T: GeneralInstance4Channel> Drop for InputCaptureFuture<T> {
165 fn drop(&mut self) {
166 critical_section::with(|_| {
167 let regs = unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) };
168
169 regs.dier().modify(|w| w.set_ccie(self.channel.index(), false));
171 });
172 }
173}
174
175impl<T: GeneralInstance4Channel> Future for InputCaptureFuture<T> {
176 type Output = u32;
177
178 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
179 T::state().cc_waker[self.channel.index()].register(cx.waker());
180
181 let regs = unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) };
182
183 let dier = regs.dier().read();
184 if !dier.ccie(self.channel.index()) {
185 let val = regs.ccr(self.channel.index()).read().0;
186 Poll::Ready(val)
187 } else {
188 Poll::Pending
189 }
190 }
191}