/** * @file TimeBase.h * @brief Producer-clock to wall-clock reconstruction. * * Framework-free. A UDPS stream's accurate timestamps come from a producer * clock — either a declared time signal or the packet's embedded hrt — and both * need mapping onto the client's wall clock before they can be plotted. */ #pragma once #include #include #include namespace udpscope { /** * @brief Seconds per count of a time signal, from its type code. * * The protocol carries uint64 time signals in nanoseconds and everything else * in microseconds; this mirrors UDPSourceSession so the two agree on a stream. */ double TimeSignalScale(uint8_t typeCode); /** * @brief A latched producer-to-wall offset. * * Established from the first sample and then held, so network jitter does not * wobble the trace. Only a drift beyond kRecalibThresholdS — a producer restart * or re-phase, not delivery noise — forces a new calibration. */ class ClockOffset { public: static constexpr double kRecalibThresholdS = 0.5; /** @return producerSec mapped onto wall clock. */ double map(double producerSec, double wallSec); bool valid() const { return valid_; } void reset() { valid_ = false; offset_ = 0.0; } double offset() const { return offset_; } private: double offset_ = 0.0; bool valid_ = false; }; /** * @brief Recovers the producer's hrt tick rate by least squares against arrival * time. * * The protocol does not carry the tick rate, and StreamHub's approach of using * the local MARTe HighResolutionTimer frequency is only valid when the client * runs on the producer's host. A remote bench scope cannot assume that, so the * rate is measured: hrt against recv_time is a straight line whose slope is * ticks per second. */ class HrtRateFit { public: static constexpr size_t kMinSamples = 32; static constexpr size_t kWindow = 256; void add(uint64_t hrt, double wallSec); bool ready() const { return n_ >= kMinSamples && rate_ > 0.0; } double ticksPerSecond() const { return rate_; } double toSeconds(uint64_t hrt) const; void reset(); private: void refit(); struct Sample { double hrt; double wall; }; std::deque samples_; size_t n_ = 0; double rate_ = 0.0; }; } /* namespace udpscope */