diff --git a/src/bin/lockin-external.rs b/src/bin/lockin-external.rs index f3717bb..1d3f11d 100644 --- a/src/bin/lockin-external.rs +++ b/src/bin/lockin-external.rs @@ -117,8 +117,14 @@ const APP: () = { let iir_state = c.resources.iir_state; let lockin = c.resources.lockin; + let t = c + .resources + .timestamper + .latest_timestamp() + .unwrap_or_else(|t| t) // Ignore timer capture overflows. + .map(|t| t as i32); let (pll_phase, pll_frequency) = c.resources.pll.update( - c.resources.timestamper.latest_timestamp().map(|t| t as i32), + t, 22, // frequency settling time (log2 counter cycles), TODO: expose 22, // phase settling time, TODO: expose ); diff --git a/src/hardware/digital_input_stamper.rs b/src/hardware/digital_input_stamper.rs index 9cda62b..6bd8629 100644 --- a/src/hardware/digital_input_stamper.rs +++ b/src/hardware/digital_input_stamper.rs @@ -62,15 +62,12 @@ impl InputStamper { /// Get the latest timestamp that has occurred. /// /// # Note - /// This function must be called sufficiently often. If an over-capture event occurs, this - /// function will panic, as this indicates a timestamp was inadvertently dropped. - /// - /// To prevent timestamp loss, the batch size and sampling rate must be adjusted such that at - /// most one timestamp will occur in each data processing cycle. + /// This function must be called at least as often as timestamps arrive. + /// If an over-capture event occurs, this function will clear the overflow, + /// and return a new timestamp of unknown recency an `Err()`. + /// Note that this indicates at least one timestamp was inadvertently dropped. #[allow(dead_code)] - pub fn latest_timestamp(&mut self) -> Option { - self.capture_channel - .latest_capture() - .expect("DI0 timestamp overrun") + pub fn latest_timestamp(&mut self) -> Result, Option> { + self.capture_channel.latest_capture() } } diff --git a/src/hardware/timers.rs b/src/hardware/timers.rs index 7199730..b686220 100644 --- a/src/hardware/timers.rs +++ b/src/hardware/timers.rs @@ -281,28 +281,26 @@ macro_rules! timer_channels { impl [< Channel $index InputCapture >] { /// Get the latest capture from the channel. #[allow(dead_code)] - pub fn latest_capture(&mut self) -> Result, ()> { + pub fn latest_capture(&mut self) -> Result, Option<$size>> { // Note(unsafe): This channel owns all access to the specific timer channel. // Only atomic operations on completed on the timer registers. let regs = unsafe { &*<$TY>::ptr() }; - let sr = regs.sr.read(); - let result = if sr.[< cc $index if >]().bit_is_set() { + let result = if regs.sr.read().[< cc $index if >]().bit_is_set() { // Read the capture value. Reading the captured value clears the flag in the // status register automatically. - let ccx = regs.[< ccr $index >].read(); - Some(ccx.ccr().bits()) + Some(regs.[< ccr $index >].read().ccr().bits()) } else { None }; // Read SR again to check for a potential over-capture. If there is an // overcapture, return an error. - if regs.sr.read().[< cc $index of >]().bit_is_clear() { - Ok(result) - } else { + if regs.sr.read().[< cc $index of >]().bit_is_set() { regs.sr.modify(|_, w| w.[< cc $index of >]().clear_bit()); - Err(()) + Err(result) + } else { + Ok(result) } }