SatCat5
ptp_simclock.cc
1 // Copyright 2024 The Aerospace Corporation.
3 // This file is a part of SatCat5, licensed under CERN-OHL-W v2 or later.
5 
6 #include <hal_test/ptp_simclock.h>
7 #include <satcat5/utils.h>
8 
11 using satcat5::ptp::Time;
15 
16 SimulatedClock::SimulatedClock(double nominal_hz, double actual_hz)
17  : m_scale_nominal(nominal_hz, TICK_SCALE_NSEC)
18  , m_rate_actual(actual_hz)
19  , m_nco_rate(round_s64(TICKS_PER_SEC / nominal_hz))
20  , m_nco_accum(satcat5::util::UINT128_ZERO)
21  , m_count_coarse(0)
22  , m_count_fine(0)
23  , m_rtc(0)
24 {
25  // Nothing else to initialize.
26 }
27 
29  return m_rtc;
30 }
31 
33  ++m_count_coarse;
34  m_rtc += amount;
35  return Time(0);
36 }
37 
38 void SimulatedClock::clock_set(const Time& t) {
39  ++m_count_coarse;
40  m_rtc = t;
41 }
42 
43 void SimulatedClock::clock_rate(s64 offset) {
44  ++m_count_fine;
45  m_offset = offset;
46  m_stats.add(offset);
47 }
48 
49 double SimulatedClock::clock_offset_ppm() const {
50  return double(m_offset) / double(satcat5::ptp::RATE_ONE_PPM);
51 }
52 
53 void SimulatedClock::run(const Time& dt) {
54  // Advance the NCO in discrete steps.
55  double dt_secs = dt.delta_subns() / double(satcat5::ptp::SUBNS_PER_SEC);
56  u64 num_clocks = round_u64(dt_secs * m_rate_actual);
57 
58  // Increment internal counter at full precision.
59  s64 delta = m_scale_nominal.convert(m_offset);
60  const uint128_t incr(num_clocks);
61  const uint128_t rate(u64(m_nco_rate + delta));
62  m_nco_accum += incr * rate;
63 
64  // Internal resolution is higher than RTC; retain leftovers.
65  const uint128_t scale(TICKS_PER_SUBNS);
66  m_rtc += Time(s64(m_nco_accum / scale));
67  m_nco_accum = m_nco_accum % scale;
68 }
69 
70 SimulatedTimer::SimulatedTimer()
71  : m_treg(0), m_timer(&m_treg, 1000000)
72 {
73  satcat5::poll::timekeeper.set_clock(&m_timer);
74 }
75 
76 void SimulatedTimer::run(const Time& dt) {
77  m_treg += dt.delta_usec();
78  satcat5::poll::timekeeper.request_poll();
79 }
void request_poll()
Call this method to request polling at a later time.
Definition: polling.cc:208
void set_clock(satcat5::util::TimeRef *timer)
Immediately set the system time reference.
Definition: polling.cc:250
s64 convert(s64 offset) const
Forward conversion (normalized rate ==> ticks-per-clock)
Definition: ptp_filters.cc:495
Simulated clock mimics operation of "ptp_realtime.vhd".
Definition: ptp_simclock.h:18
static constexpr u64 TICKS_PER_SUBNS
Convert from internal ticks to engineering units.
Definition: ptp_simclock.h:25
satcat5::ptp::Time clock_now() override
Return the current time if available, TIME_ZERO otherwise.
Definition: ptp_simclock.cc:28
void run(const satcat5::ptp::Time &dt)
Run simulation for X seconds.
Definition: ptp_simclock.cc:53
void clock_rate(s64 offset) override
Adjust rate by a normalized frequency offset.
Definition: ptp_simclock.cc:43
satcat5::ptp::Time clock_adjust(const satcat5::ptp::Time &amount) override
Make a one-time adjustment of the specified magnitude.
Definition: ptp_simclock.cc:32
Helper object for tracking simulation time.
Definition: ptp_simclock.h:78
void run(const satcat5::ptp::Time &dt)
Advance simulation by X seconds.
Definition: ptp_simclock.cc:76
High-precision timestamp for use with PTP / IEEE1588.
Definition: ptp_time.h:41
s64 delta_subns() const
Convert time-differences to the designated unit.
Definition: ptp_time.cc:55
s64 delta_usec() const
Convert time-differences to the designated unit.
Definition: ptp_time.cc:59
void add(double x)
Add a new data point.
Definition: sim_utils.cc:330
constexpr s64 SUBNS_PER_SEC
Define commonly used scaling factors.
Definition: ptp_time.h:31
Miscellaneous mathematical utility functions.
constexpr u64 round_u64(T x)
Round a floating-point value to the nearest integer.
Definition: utils.h:229
constexpr s64 round_s64(T x)
Round a floating-point value to the nearest integer.
Definition: utils.h:226