Assigning Absolute (UTC) Timestamps to Time Tags
Learn why Time Tagger timestamps are relative rather than absolute, and how to align them to UTC using the ReferenceClock and a 1PPS signal.
Time Tagger timestamps have no built-in absolute (e.g. UTC) meaning. This article explains why, and how to align your own timestamps to UTC if your application needs it.
Timestamps Are Relative, Not Absolute
The timestamp of every event is relative to the moment the Time Tagger object is created in software (when
createTimeTagger() is called), not to any physical event. This origin, sometimes called t0, therefore has no
absolute meaning on its own. What matters for almost every application is the difference between timestamps, not
their value relative to t0.
Some applications do need an absolute notion of time, though. In satellite laser ranging and space-based LiDAR, for example, a low-Earth-orbit satellite moves fast enough (on the order of 10 km/s) that it shifts position by about 1 cm every microsecond; since ground stations compute the satellite’s position from its orbit model as a function of UTC, a timestamp offset from true UTC by even a few microseconds makes the satellite appear shifted along its orbit. In large distributed timing networks, such as CERN’s White Rabbit protocol, which disciplines widely separated systems to a common, often GNSS-referenced time base, an external device may already operate on this absolute time base, and the Time Tagger needs to share that same notion of time, for example to gate events, so that only events within a specific absolute time window are kept and the rest discarded. The following sections describe how to align Time Tagger timestamps to UTC for cases like these.
Why the API Cannot Report Absolute UTC Directly
Time tags are stored as signed 64-bit integers in picoseconds, which span approximately ±107 days (about 213 days in total) before rolling over. An absolute UTC timestamp, for example seconds since 1970 expressed in picoseconds, is on the order of 10²¹, far beyond what a 64-bit integer can represent. Reporting absolute UTC directly in this format would overflow and roll over constantly, so the device only ever reports time relative to its own start.
One option could be to split timestamps into a seconds part and a picoseconds part internally. However, this approach raises two concerns:
- Performance: nearly every measurement class compares and subtracts timestamps directly as single 64-bit integers. Splitting the value into two fields would double storage and require a two-part comparison and subtraction instead of one native integer operation.
- Precision: it is tempting to recombine such a split value into a single floating-point number, e.g. “seconds + picoseconds × 1e-12”. This silently drops a significant fraction of the precision, on the order of a quarter of a microsecond, because a standard double-precision float does not have enough mantissa bits to hold both a present-day Unix second count and picosecond-level resolution at the same time. Integer overflows tend to be obvious and easy to catch; this kind of silent precision loss is not.
There is a further complication: even while synchronized to an external reference, the 64-bit picosecond counter can still roll over roughly every 213 days, and that rollover can happen at any moment, including between two separate API calls. Any conversion to absolute time therefore has to read the relevant timestamp and compute the corresponding UTC value together, in one step, rather than querying “the current epoch” separately from “the current timestamp”.
Aligning Timestamps to UTC
Aligning to UTC has two independent parts: matching the rate at which time advances (frequency), and determining the absolute offset (which UTC second a given timestamp corresponds to).
Frequency: the ReferenceClock
The recommended way to discipline the Time Tagger’s time base to an external frequency reference, for instance a
10 MHz signal disciplined to UTC/GPS, is the software-defined
ReferenceClock.
The reference signal is connected to one of the regular input channels (not the CLK input) and declared via
setReferenceClock(); a software PLL then rescales the entire time-tag stream to match it. Once locked, a fixed
number of picoseconds (e.g. 1e12) corresponds exactly to one second of the reference.
The dedicated CLK input found on Time Tagger Ultra and Time Tagger X only accepts specific frequencies (10 MHz or 500 MHz) and locks the hardware directly to that reference. It is a separate, less flexible mechanism, mainly useful when the reference is not correlated with the signals you are measuring, since correlated signals interfere with the device’s self-calibration. For UTC alignment, the software-defined ReferenceClock on a regular input channel is the recommended approach.
For Time Tagger 20, a phase error of about 200 ps needs to be taken into account when using the ReferenceClock;
see the
setReferenceClock()
documentation for details.
Offset: aligning to the correct UTC second
Locking the frequency alone tells you the rate at which time advances, not which specific UTC second a given timestamp falls in. For that, feed a 1PPS (one-pulse-per-second) signal referenced to UTC into another input channel.
If the ReferenceClock is already locked to a UTC-disciplined frequency (e.g. a 10 MHz reference), you only need to
determine this offset once: set up a TimeTagStream measurement, call getData() until you capture the first
1PPS edge, and immediately read the host PC’s UTC time (synchronized via NTP; accuracy of tens of milliseconds is
normally sufficient) to determine the offset between that edge and the corresponding UTC second. Since the
frequency is already disciplined, this single offset stays valid for the rest of the session. Over USB3, transfer
latency is only a few milliseconds, short enough that the data transfer delay does not cause the wrong UTC second
to be attributed. If you need to tighten this further,
setStreamBlockSize()
lets you reduce the block latency at the cost of smaller data blocks. Applying the resulting constant offset to all
subsequent timestamps keeps them aligned to UTC.
If you do not have a frequency-locked reference and only a 1PPS signal is available, the time base is not disciplined, so a single fixed offset is not enough. Instead, you need to continuously interpolate the UTC value from each newly measured 1PPS event, since the free-running internal clock will drift relative to true UTC seconds between edges.