STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
BoardClockSync.hpp File Reference

Per-board clock sync for DAQ sample timestamping. More...

#include <cstdint>
#include <deque>
#include <map>
#include <string>
#include <vector>
Include dependency graph for BoardClockSync.hpp:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  fsw::time::TimeSyncConfig
class  fsw::time::BoardClockSync
struct  fsw::time::BoardClockSync::BoardStats
struct  fsw::time::BoardClockSync::BoardState

Namespaces

namespace  fsw
 Motorized ball valve position: raw ADC counts -> % open.
namespace  fsw::time

Detailed Description

Per-board clock sync for DAQ sample timestamping.

Boards stamp each sensor chunk with uint32 millis() from a cheap local crystal: accurate RELATIVE spacing, meaningless absolute value, wraps at 2^32 ms (~49.7 days; faster on other firmware). The bridge historically stamped every sample in a UDP packet with one receive time, flattening a multi-chunk batch onto one instant and leaking network jitter into the recorded timeline.

This module reconstructs true sample times server-side, one instance per source board:

  • UNWRAP: uint32 board ms extended to 64-bit via modular forward deltas. A forward step beyond max_plausible_gap is a reboot (or long stall) → resync. A wrap is just a small modular step → seamless, no resync.
  • OFFSET: sliding-window MINIMUM of residual = arrival − board_time. Network delay is one-sided noise (a packet can't arrive before it was sent), so residuals scatter ABOVE the true offset and the window floor is the best estimate; congestion cannot drag it. The window bounds drift staleness to ~window_seconds × crystal-ppm (≈0.5 ms at defaults).
  • SPREADING: each chunk stamped at board_time + offset, so batched scans keep their true spacing instead of collapsing onto arrival time.
  • INVARIANTS: because the current packet's residual participates in the window min, offset ≤ residual and the newest chunk never stamps in the future. Every stamp is additionally clamped to [arrival − max_batch_age, arrival] (violation → flat arrival fallback + counter: worst case equals the old behavior), and per-board emitted chunk timestamps are forced non-decreasing.

Mode "arrival" reproduces the historical behavior exactly (revert switch, config.toml [time_sync]).

Pure and deterministic: no sockets, no real clock — arrival times are inputs, so unit tests drive every edge case (see lib/test/ test_board_clock_sync.cpp).

Definition in file BoardClockSync.hpp.