timestamp: pass overflows to the top and ignore them there
This commit is contained in:
parent
4475a2d040
commit
854ed29b1a
|
@ -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
|
||||
);
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue