timestamping: full u32 range

The sampling timer and the timestamping timer have the same period.
The sampling interval and the batch size are powers of two.
If the timestamping timer wraps at a power of two larger than the
batch period, it will wrap in sync with the batch period.

Even if it didn't the RPLL would handle that. But it requires that the
timer wraps at the u32/i32 boundary (or be shifted left to wrap there).
This commit is contained in:
Robert Jördens 2021-02-02 11:36:10 +01:00
parent 299b443e5f
commit 4475a2d040
2 changed files with 1 additions and 38 deletions

View File

@ -218,8 +218,7 @@ pub fn setup(
// timer, but use a period that is longer. // timer, but use a period that is longer.
let mut timer = timers::TimestampTimer::new(timer5); let mut timer = timers::TimestampTimer::new(timer5);
let period = digital_input_stamper::calculate_timestamp_timer_period(); timer.set_period_ticks(u32::MAX);
timer.set_period_ticks(period);
timer timer
}; };

View File

@ -25,42 +25,6 @@
///! This module only supports DI0 for timestamping due to trigger constraints on the DIx pins. If ///! This module only supports DI0 for timestamping due to trigger constraints on the DIx pins. If
///! timestamping is desired in DI1, a separate timer + capture channel will be necessary. ///! timestamping is desired in DI1, a separate timer + capture channel will be necessary.
use super::{hal, timers}; use super::{hal, timers};
use crate::{ADC_SAMPLE_TICKS, SAMPLE_BUFFER_SIZE};
/// Calculate the period of the digital input timestamp timer.
///
/// # Note
/// The period returned will be 1 less than the required period in timer ticks. The value returned
/// can be immediately programmed into a hardware timer period register.
///
/// The period is calculated to be some power-of-two multiple of the batch size, such that N batches
/// will occur between each timestamp timer overflow.
///
/// # Returns
/// A 32-bit value that can be programmed into a hardware timer period register.
pub fn calculate_timestamp_timer_period() -> u32 {
// Calculate how long a single batch requires in timer ticks.
let batch_duration_ticks: u64 =
SAMPLE_BUFFER_SIZE as u64 * ADC_SAMPLE_TICKS as u64;
// Calculate the largest power-of-two that is less than or equal to
// `batches_per_overflow`. This is completed by eliminating the least significant
// bits of the value until only the msb remains, which is always a power of two.
let batches_per_overflow: u64 =
(1u64 + u32::MAX as u64) / batch_duration_ticks;
let mut j = batches_per_overflow;
while (j & (j - 1)) != 0 {
j = j & (j - 1);
}
// Once the number of batches per timestamp overflow is calculated, we can figure out the final
// period of the timestamp timer. The period is always 1 larger than the value configured in the
// register.
let period: u64 = batch_duration_ticks * j - 1u64;
assert!(period <= u32::MAX as u64);
period as u32
}
/// The timestamper for DI0 reference clock inputs. /// The timestamper for DI0 reference clock inputs.
pub struct InputStamper { pub struct InputStamper {