From 7c1e1ee288bc46dbf030749c242d60e222d1fbe5 Mon Sep 17 00:00:00 2001
From: Bruno Bousquet <21108660+brunob45@users.noreply.github.com>
Date: Tue, 28 May 2024 22:30:10 -0400
Subject: [PATCH] example is working now

---
 embassy-stm32/src/timer/input_capture.rs | 63 +++++++++++++++++++-----
 examples/stm32f4/.vscode/launch.json     |  2 +-
 examples/stm32f4/.vscode/tasks.json      |  2 +-
 3 files changed, 54 insertions(+), 13 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 {}
 /// Channel 4 marker type.
 pub enum Ch4 {}
 
+fn regs_gp16(ptr: *mut ()) -> crate::pac::timer::TimGp16 {
+    unsafe { crate::pac::timer::TimGp16::from_ptr(ptr) }
+}
+
 /// Capture pin wrapper.
 ///
 /// This wraps a pin to make it usable with capture.
@@ -76,10 +80,6 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
         freq: Hertz,
         counting_mode: CountingMode,
     ) -> Self {
-        Self::new_inner(tim, freq, counting_mode)
-    }
-
-    fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz, counting_mode: CountingMode) -> Self {
         let mut this = Self { inner: Timer::new(tim) };
 
         this.inner.set_counting_mode(counting_mode);
@@ -148,11 +148,52 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
     }
 
     fn new_future(&self, channel: Channel, mode: InputCaptureMode, tisel: InputTISelection) -> InputCaptureFuture<T> {
-        self.inner.enable_channel(channel, true);
-        self.inner.set_input_capture_mode(channel, mode);
-        self.inner.set_input_ti_selection(channel, tisel);
-        self.inner.clear_input_interrupt(channel);
-        self.inner.enable_input_interrupt(channel, true);
+        use stm32_metapac::timer::vals::*;
+
+        let regs = regs_gp16(T::regs());
+        let idx = channel.index();
+
+        // Select the active input: TIMx_CCR1 must be linked to the TI1 input, so write the CC1S
+        // bits to 01 in the TIMx_CCMR1 register. As soon as CC1S becomes different from 00,
+        // the channel is configured in input and the TIMx_CCR1 register becomes read-only.
+        regs.ccmr_input(idx / 2)
+            .modify(|r| r.set_ccs(idx % 2, CcmrInputCcs::from(tisel)));
+
+        // Program the appropriate input filter duration in relation with the signal connected to the
+        // timer (by programming the ICxF bits in the TIMx_CCMRx register if the input is one of
+        // the TIx inputs). Let’s imagine that, when toggling, the input signal is not stable during at
+        // must 5 internal clock cycles. We must program a filter duration longer than these 5
+        // clock cycles. We can validate a transition on TI1 when 8 consecutive samples with the
+        // new level have been detected (sampled at fDTS frequency). Then write IC1F bits to
+        // 0011 in the TIMx_CCMR1 register.
+        regs.ccmr_input(idx / 2)
+            .modify(|r| r.set_icf(idx % 2, FilterValue::NOFILTER));
+
+        // Select the edge of the active transition on the TI1 channel by writing the CC1P and
+        // CC1NP bits to 00 in the TIMx_CCER register (rising edge in this case).
+        let ccpnp = match mode {
+            InputCaptureMode::Rising => (false, false),
+            InputCaptureMode::Falling => (false, true),
+            InputCaptureMode::BothEdges => (true, true),
+        };
+        regs.ccer().modify(|r| {
+            r.set_ccp(idx, ccpnp.0);
+            r.set_ccnp(idx, ccpnp.1);
+        });
+
+        // Program the input prescaler. In our example, we wish the capture to be performed at
+        // each valid transition, so the prescaler is disabled (write IC1PS bits to 00 in the
+        // TIMx_CCMR1 register).
+        regs.ccmr_input(idx / 2).modify(|r| r.set_icpsc(idx % 2, 0));
+
+        // Enable capture from the counter into the capture register by setting the CC1E bit in the
+        // TIMx_CCER register.
+        regs.ccer().modify(|r| r.set_cce(idx, true));
+
+        // If needed, enable the related interrupt request by setting the CC1IE bit in the
+        // TIMx_DIER register, and/or the DMA request by setting the CC1DE bit in the
+        // TIMx_DIER register.
+        regs.dier().modify(|r| r.set_ccie(idx, true));
 
         InputCaptureFuture {
             channel,
@@ -206,7 +247,7 @@ struct InputCaptureFuture<T: GeneralInstance4Channel> {
 impl<T: GeneralInstance4Channel> Drop for InputCaptureFuture<T> {
     fn drop(&mut self) {
         critical_section::with(|_| {
-            let regs = unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) };
+            let regs = regs_gp16(T::regs());
 
             // disable interrupt enable
             regs.dier().modify(|w| w.set_ccie(self.channel.index(), false));
@@ -220,7 +261,7 @@ impl<T: GeneralInstance4Channel> Future for InputCaptureFuture<T> {
     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
         T::state().cc_waker[self.channel.index()].register(cx.waker());
 
-        let regs = unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) };
+        let regs = regs_gp16(T::regs());
 
         let dier = regs.dier().read();
         if !dier.ccie(self.channel.index()) {
diff --git a/examples/stm32f4/.vscode/launch.json b/examples/stm32f4/.vscode/launch.json
index a9849e0da..20cd4d2e8 100644
--- a/examples/stm32f4/.vscode/launch.json
+++ b/examples/stm32f4/.vscode/launch.json
@@ -15,7 +15,7 @@
             "cwd": "${workspaceRoot}",
             "preLaunchTask": "Cargo Build (debug)",
             "runToEntryPoint": "main",
-            "executable": "./target/thumbv7em-none-eabihf/debug/pwm_input",
+            "executable": "./target/thumbv7em-none-eabihf/debug/input_capture",
             /* Run `cargo build --example itm` and uncomment this line to run itm example */
             // "executable": "./target/thumbv7em-none-eabihf/debug/examples/itm",
             "device": "STM32F446RET6",
diff --git a/examples/stm32f4/.vscode/tasks.json b/examples/stm32f4/.vscode/tasks.json
index de7013b12..e153722da 100644
--- a/examples/stm32f4/.vscode/tasks.json
+++ b/examples/stm32f4/.vscode/tasks.json
@@ -9,7 +9,7 @@
 			],
 			"args": [
 				"--bin",
-				"pwm_input"
+				"input_capture"
 			],
 			"group": {
 				"kind": "build",