use fixed::traits::LossyInto;
use super::{Filter, FilterUpdate};
#[allow(unused_imports)]
use crate::float_polyfill::FloatPolyfill;
use crate::{
port::Measurement,
time::{Duration, Time},
Clock,
};
#[derive(Debug)]
struct PrevStepData {
event_time: Time,
offset: Duration,
correction: Duration,
}
#[derive(Debug)]
pub struct BasicFilter {
last_step: Option<PrevStepData>,
offset_confidence: Duration,
freq_confidence: f64,
gain: f64,
cur_freq: f64,
}
impl Filter for BasicFilter {
type Config = f64;
fn new(gain: f64) -> Self {
Self {
last_step: None,
offset_confidence: Duration::from_nanos(1_000_000_000),
freq_confidence: 1e-4,
gain,
cur_freq: 0.0,
}
}
fn measurement<C: Clock>(&mut self, measurement: Measurement, clock: &mut C) -> FilterUpdate {
let mut update = FilterUpdate::default();
if let Some(delay) = measurement.delay {
update.mean_delay = Some(delay);
}
if let Some(peer_delay) = measurement.peer_delay {
update.mean_delay = Some(peer_delay);
}
let Some(offset) = measurement.offset else {
return update;
};
if offset.abs() > Duration::from_nanos(1_000_000_000) {
log::debug!("Offset too large, stepping {}", offset);
self.offset_confidence = Duration::from_nanos(1_000_000_000);
self.freq_confidence = 1e-4;
if let Err(error) = clock.step_clock(-offset) {
log::error!("Could not step clock: {:?}", error);
}
return update;
}
let mut clamped_offset = offset;
if offset.abs() > self.offset_confidence {
clamped_offset = offset.clamp(-self.offset_confidence, self.offset_confidence);
self.offset_confidence *= 2i32;
} else {
self.offset_confidence -= (self.offset_confidence - offset.abs()) * self.gain;
}
let correction = -clamped_offset * self.gain;
let freq_corr = if let Some(last_step) = &self.last_step {
let interval_local: f64 =
(measurement.event_time - last_step.event_time - last_step.correction)
.nanos()
.lossy_into();
let interval_master: f64 = ((measurement.event_time - offset)
- (last_step.event_time - last_step.offset))
.nanos()
.lossy_into();
let mut freq_diff = interval_local / interval_master;
if (freq_diff - 1.0).abs() > self.freq_confidence {
freq_diff = freq_diff.clamp(1.0 - self.freq_confidence, 1.0 + self.freq_confidence);
self.freq_confidence *= 2.0;
} else {
self.freq_confidence -=
(self.freq_confidence - (freq_diff - 1.0).abs()) * self.gain;
}
-(freq_diff - 1.0) * self.gain * 0.1 * 1e6
} else {
if let Err(error) = clock.set_frequency(0.0) {
log::error!("Could not initialize clock frequency: {:?}", error);
}
self.cur_freq = 0.0;
0.0
};
log::info!(
"Offset to master: {:e}ns, corrected with phase change {:e}ns and freq change {:e}ppm",
offset.nanos(),
correction.nanos(),
freq_corr
);
self.last_step = Some(PrevStepData {
event_time: measurement.event_time,
offset,
correction,
});
if let Err(error) = clock.step_clock(correction) {
log::error!("Could not step clock: {:?}", error);
}
if let Err(error) = clock.set_frequency(self.cur_freq + freq_corr) {
log::error!("Could not adjust clock frequency: {:?}", error);
} else {
self.cur_freq += freq_corr;
}
update
}
fn demobilize<C: Clock>(self, _clock: &mut C) {
}
fn update<C: Clock>(&mut self, _clock: &mut C) -> FilterUpdate {
Default::default()
}
}