aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/timer
diff options
context:
space:
mode:
authorBruno Bousquet <[email protected]>2024-05-28 22:30:10 -0400
committerBruno Bousquet <[email protected]>2024-05-28 22:30:10 -0400
commit7c1e1ee288bc46dbf030749c242d60e222d1fbe5 (patch)
tree011486c29352fda98ac6e43a05d91ec4ff8fa0df /embassy-stm32/src/timer
parent41b9a12574f9ad992ca986b87926838fbe1f1775 (diff)
example is working now
Diffstat (limited to 'embassy-stm32/src/timer')
-rw-r--r--embassy-stm32/src/timer/input_capture.rs63
1 files changed, 52 insertions, 11 deletions
diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs
index a1c1486f9..ab6f10a1d 100644
--- a/embassy-stm32/src/timer/input_capture.rs
+++ b/embassy-stm32/src/timer/input_capture.rs
@@ -26,6 +26,10 @@ pub enum Ch3 {}
26/// Channel 4 marker type. 26/// Channel 4 marker type.
27pub enum Ch4 {} 27pub enum Ch4 {}
28 28
29fn regs_gp16(ptr: *mut ()) -> crate::pac::timer::TimGp16 {
30 unsafe { crate::pac::timer::TimGp16::from_ptr(ptr) }
31}
32
29/// Capture pin wrapper. 33/// Capture pin wrapper.
30/// 34///
31/// This wraps a pin to make it usable with capture. 35/// This wraps a pin to make it usable with capture.
@@ -76,10 +80,6 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
76 freq: Hertz, 80 freq: Hertz,
77 counting_mode: CountingMode, 81 counting_mode: CountingMode,
78 ) -> Self { 82 ) -> Self {
79 Self::new_inner(tim, freq, counting_mode)
80 }
81
82 fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz, counting_mode: CountingMode) -> Self {
83 let mut this = Self { inner: Timer::new(tim) }; 83 let mut this = Self { inner: Timer::new(tim) };
84 84
85 this.inner.set_counting_mode(counting_mode); 85 this.inner.set_counting_mode(counting_mode);
@@ -148,11 +148,52 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
148 } 148 }
149 149
150 fn new_future(&self, channel: Channel, mode: InputCaptureMode, tisel: InputTISelection) -> InputCaptureFuture<T> { 150 fn new_future(&self, channel: Channel, mode: InputCaptureMode, tisel: InputTISelection) -> InputCaptureFuture<T> {
151 self.inner.enable_channel(channel, true); 151 use stm32_metapac::timer::vals::*;
152 self.inner.set_input_capture_mode(channel, mode); 152
153 self.inner.set_input_ti_selection(channel, tisel); 153 let regs = regs_gp16(T::regs());
154 self.inner.clear_input_interrupt(channel); 154 let idx = channel.index();
155 self.inner.enable_input_interrupt(channel, true); 155
156 // Select the active input: TIMx_CCR1 must be linked to the TI1 input, so write the CC1S
157 // bits to 01 in the TIMx_CCMR1 register. As soon as CC1S becomes different from 00,
158 // the channel is configured in input and the TIMx_CCR1 register becomes read-only.
159 regs.ccmr_input(idx / 2)
160 .modify(|r| r.set_ccs(idx % 2, CcmrInputCcs::from(tisel)));
161
162 // Program the appropriate input filter duration in relation with the signal connected to the
163 // timer (by programming the ICxF bits in the TIMx_CCMRx register if the input is one of
164 // the TIx inputs). Let’s imagine that, when toggling, the input signal is not stable during at
165 // must 5 internal clock cycles. We must program a filter duration longer than these 5
166 // clock cycles. We can validate a transition on TI1 when 8 consecutive samples with the
167 // new level have been detected (sampled at fDTS frequency). Then write IC1F bits to
168 // 0011 in the TIMx_CCMR1 register.
169 regs.ccmr_input(idx / 2)
170 .modify(|r| r.set_icf(idx % 2, FilterValue::NOFILTER));
171
172 // Select the edge of the active transition on the TI1 channel by writing the CC1P and
173 // CC1NP bits to 00 in the TIMx_CCER register (rising edge in this case).
174 let ccpnp = match mode {
175 InputCaptureMode::Rising => (false, false),
176 InputCaptureMode::Falling => (false, true),
177 InputCaptureMode::BothEdges => (true, true),
178 };
179 regs.ccer().modify(|r| {
180 r.set_ccp(idx, ccpnp.0);
181 r.set_ccnp(idx, ccpnp.1);
182 });
183
184 // Program the input prescaler. In our example, we wish the capture to be performed at
185 // each valid transition, so the prescaler is disabled (write IC1PS bits to 00 in the
186 // TIMx_CCMR1 register).
187 regs.ccmr_input(idx / 2).modify(|r| r.set_icpsc(idx % 2, 0));
188
189 // Enable capture from the counter into the capture register by setting the CC1E bit in the
190 // TIMx_CCER register.
191 regs.ccer().modify(|r| r.set_cce(idx, true));
192
193 // If needed, enable the related interrupt request by setting the CC1IE bit in the
194 // TIMx_DIER register, and/or the DMA request by setting the CC1DE bit in the
195 // TIMx_DIER register.
196 regs.dier().modify(|r| r.set_ccie(idx, true));
156 197
157 InputCaptureFuture { 198 InputCaptureFuture {
158 channel, 199 channel,
@@ -206,7 +247,7 @@ struct InputCaptureFuture<T: GeneralInstance4Channel> {
206impl<T: GeneralInstance4Channel> Drop for InputCaptureFuture<T> { 247impl<T: GeneralInstance4Channel> Drop for InputCaptureFuture<T> {
207 fn drop(&mut self) { 248 fn drop(&mut self) {
208 critical_section::with(|_| { 249 critical_section::with(|_| {
209 let regs = unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) }; 250 let regs = regs_gp16(T::regs());
210 251
211 // disable interrupt enable 252 // disable interrupt enable
212 regs.dier().modify(|w| w.set_ccie(self.channel.index(), false)); 253 regs.dier().modify(|w| w.set_ccie(self.channel.index(), false));
@@ -220,7 +261,7 @@ impl<T: GeneralInstance4Channel> Future for InputCaptureFuture<T> {
220 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 261 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
221 T::state().cc_waker[self.channel.index()].register(cx.waker()); 262 T::state().cc_waker[self.channel.index()].register(cx.waker());
222 263
223 let regs = unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) }; 264 let regs = regs_gp16(T::regs());
224 265
225 let dier = regs.dier().read(); 266 let dier = regs.dier().read();
226 if !dier.ccie(self.channel.index()) { 267 if !dier.ccie(self.channel.index()) {