timestamp: pass overflows to the top and ignore them there

master
Robert Jördens 2021-02-02 12:34:07 +01:00
parent 4475a2d040
commit 854ed29b1a
3 changed files with 20 additions and 19 deletions

View File

@ -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
);

View File

@ -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<u32> {
self.capture_channel
.latest_capture()
.expect("DI0 timestamp overrun")
pub fn latest_timestamp(&mut self) -> Result<Option<u32>, Option<u32>> {
self.capture_channel.latest_capture()
}
}

View File

@ -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<Option<$size>, ()> {
pub fn latest_capture(&mut self) -> Result<Option<$size>, 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)
}
}