2020-12-09 20:44:26 +08:00
|
|
|
///! ADC sample timestamper using external Pounder reference clock.
|
2021-01-06 21:42:36 +08:00
|
|
|
///!
|
|
|
|
///! # Design
|
|
|
|
///!
|
|
|
|
///! The pounder timestamper utilizes the pounder SYNC_CLK output as a fast external reference clock
|
|
|
|
///! for recording a timestamp for each of the ADC samples.
|
|
|
|
///!
|
|
|
|
///! To accomplish this, a timer peripheral is configured to be driven by an external clock input.
|
|
|
|
///! Due to the limitations of clock frequencies allowed by the timer peripheral, the SYNC_CLK input
|
|
|
|
///! is divided by 4. This clock then clocks the timer peripheral in a free-running mode with an ARR
|
|
|
|
///! (max count register value) configured to overflow once per ADC sample batch.
|
|
|
|
///!
|
|
|
|
///! Once the timer is configured, an input capture is configured to record the timer count
|
|
|
|
///! register. The input capture is configured to utilize an internal trigger for the input capture.
|
|
|
|
///! The internal trigger is selected such that when a sample is generated on ADC0, the input
|
2021-06-04 16:45:22 +08:00
|
|
|
///! capture is simultaneously triggered. That trigger is prescaled (its rate is divided) by the
|
|
|
|
///! batch size. This results in the input capture triggering identically to when the ADC samples
|
|
|
|
///! the last sample of the batch. That sample is then available for processing by the user.
|
2021-06-03 15:57:18 +08:00
|
|
|
use crate::hardware::{design_parameters, timers};
|
|
|
|
use core::convert::TryFrom;
|
2020-12-09 20:44:26 +08:00
|
|
|
use stm32h7xx_hal as hal;
|
|
|
|
|
2021-01-06 21:42:36 +08:00
|
|
|
/// Software unit to timestamp stabilizer ADC samples using an external pounder reference clock.
|
2020-12-09 20:44:26 +08:00
|
|
|
pub struct Timestamper {
|
2020-12-10 01:19:33 +08:00
|
|
|
timer: timers::PounderTimestampTimer,
|
2021-06-03 16:31:11 +08:00
|
|
|
capture_channel: timers::tim8::Channel1InputCapture,
|
2020-12-09 20:44:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Timestamper {
|
2021-01-06 21:42:36 +08:00
|
|
|
/// Construct the pounder sample timestamper.
|
|
|
|
///
|
|
|
|
/// # Args
|
|
|
|
/// * `timestamp_timer` - The timer peripheral used for capturing timestamps from.
|
|
|
|
/// * `capture_channel` - The input capture channel for collecting timestamps.
|
|
|
|
/// * `sampling_timer` - The stabilizer ADC sampling timer.
|
|
|
|
/// * `_clock_input` - The input pin for the external clock from Pounder.
|
|
|
|
///
|
|
|
|
/// # Returns
|
|
|
|
/// The new pounder timestamper in an operational state.
|
2020-12-09 20:44:26 +08:00
|
|
|
pub fn new(
|
2020-12-10 01:19:33 +08:00
|
|
|
mut timestamp_timer: timers::PounderTimestampTimer,
|
|
|
|
capture_channel: timers::tim8::Channel1,
|
|
|
|
sampling_timer: &mut timers::SamplingTimer,
|
|
|
|
_clock_input: hal::gpio::gpioa::PA0<
|
|
|
|
hal::gpio::Alternate<hal::gpio::AF3>,
|
|
|
|
>,
|
2020-12-09 20:44:26 +08:00
|
|
|
) -> Self {
|
2020-12-10 01:19:33 +08:00
|
|
|
// The sampling timer should generate a trigger output when CH1 comparison occurs.
|
|
|
|
sampling_timer.generate_trigger(timers::TriggerGenerator::ComparePulse);
|
|
|
|
|
|
|
|
// The timestamp timer trigger input should use TIM2 (SamplingTimer)'s trigger, which is
|
|
|
|
// mapped to ITR1.
|
|
|
|
timestamp_timer.set_trigger_source(timers::TriggerSource::Trigger1);
|
|
|
|
|
|
|
|
// The capture channel should capture whenever the trigger input occurs.
|
2021-06-03 15:57:18 +08:00
|
|
|
let mut input_capture = capture_channel
|
2021-02-03 21:11:00 +08:00
|
|
|
.into_input_capture(timers::tim8::CaptureSource1::TRC);
|
2020-12-09 20:44:26 +08:00
|
|
|
|
2021-06-03 15:57:18 +08:00
|
|
|
// Capture at the batch period.
|
|
|
|
input_capture.configure_prescaler(
|
|
|
|
timers::Prescaler::try_from(
|
|
|
|
design_parameters::SAMPLE_BUFFER_SIZE_LOG2,
|
|
|
|
)
|
|
|
|
.unwrap(),
|
|
|
|
);
|
|
|
|
|
2020-12-09 20:44:26 +08:00
|
|
|
Self {
|
2020-12-10 01:19:33 +08:00
|
|
|
timer: timestamp_timer,
|
2021-06-03 16:31:11 +08:00
|
|
|
capture_channel: input_capture,
|
2020-12-09 20:44:26 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-03 16:31:11 +08:00
|
|
|
/// Start collecting timestamps.
|
2021-01-18 23:47:47 +08:00
|
|
|
pub fn start(&mut self) {
|
2021-06-03 16:31:11 +08:00
|
|
|
self.capture_channel.enable();
|
2021-01-18 23:47:47 +08:00
|
|
|
}
|
|
|
|
|
2021-01-06 21:42:36 +08:00
|
|
|
/// Update the period of the underlying timestamp timer.
|
2020-12-09 20:44:26 +08:00
|
|
|
pub fn update_period(&mut self, period: u16) {
|
2021-01-06 20:34:55 +08:00
|
|
|
self.timer.set_period_ticks(period);
|
2020-12-09 20:44:26 +08:00
|
|
|
}
|
|
|
|
|
2021-06-03 16:31:11 +08:00
|
|
|
/// Obtain a timestamp.
|
2020-12-09 20:44:26 +08:00
|
|
|
///
|
|
|
|
/// # Returns
|
2021-06-03 16:31:11 +08:00
|
|
|
/// A `Result` potentially indicating capture overflow and containing a `Option` of a captured
|
|
|
|
/// timestamp.
|
|
|
|
pub fn latest_timestamp(&mut self) -> Result<Option<u16>, Option<u16>> {
|
|
|
|
self.capture_channel.latest_capture()
|
2020-12-09 20:44:26 +08:00
|
|
|
}
|
|
|
|
}
|