Skip to content

fix: correct PCAN timestamps (uptime-based backends)#1087

Open
minoseigenheer wants to merge 2 commits into
collin80:QT6WIPfrom
minoseigenheer:fix/pcan-timestamps
Open

fix: correct PCAN timestamps (uptime-based backends)#1087
minoseigenheer wants to merge 2 commits into
collin80:QT6WIPfrom
minoseigenheer:fix/pcan-timestamps

Conversation

@minoseigenheer

Copy link
Copy Markdown

Problem

PCAN/PeakCAN hardware provides timestamps relative to device power-on (uptime), not the Unix epoch. The existing code subtracted timeBasis (a Unix epoch value in µs) from this small uptime value, causing unsigned integer underflow and producing large negative-looking timestamps (e.g. -1777429996593330 µs).

A secondary problem existed even after detecting the uptime clock: using a QDateTime wall-clock anchor to convert the PCAN uptime to session-relative time introduced a systematic ~3 ms bias (macOS monotonic vs. wall clock drift ~14 ppm). This made every Rx timestamp appear slightly after its corresponding Tx timestamp in override-mode delta calculations, breaking the expected request/response order.

A third problem: clicking Clear Frames while frames are arriving restarts mElapsedTimer, but frames already queued by the hardware thread carry timestamps from the old timer epoch. Those frames are drained ~20 ms later by the refresh tick and appear with incorrect (large) timestamps relative to subsequent frames.

Fix

Commit 1 — correct PCAN timestamps for uptime-based backends

  • Detect uptime-based hw timestamps by checking hwTimestamp < timeBasis.
  • For those backends, use CANConManager::getElapsedUs() directly instead of the PCAN hw clock. This is the identical QElapsedTimer monotonic source used for Tx timestamps, so Tx and Rx are always on the same clock with zero drift or bias.
  • Add CANConManager::getElapsedUs() helper (exposes mElapsedTimer.nsecsElapsed() / 1000).
  • Remove first-frame anchor members (mFirstHwTimestamp, mFirstElapsedUs) that are no longer needed.

Commit 2 — prevent incorrect timestamps after Clear Frames

  • resetTimeBasis() now flushes every connection's frame queue immediately after restarting mElapsedTimer, so pre-reset frames are discarded before the drain timer fires.

Files changed

  • connections/serialbusconnection.cpp — uptime detection + getElapsedUs() for Rx
  • connections/serialbusconnection.h — removed obsolete anchor members
  • connections/canconmanager.cpp — added getElapsedUs(), queue flush in resetTimeBasis()
  • connections/canconmanager.h — added getElapsedUs() declaration

Testing

Verified with a PCAN-USB on macOS:

  • Timestamps are now positive and start near 0 µs on session start.
  • Rx timestamps align with Tx timestamps (same monotonic source, no fixed bias).
  • Clicking Clear Frames while live traffic is flowing produces correct timestamps immediately after the clear.

PCAN provides hardware timestamps relative to device power-on (uptime),
not Unix epoch. Previous approaches tried to anchor this uptime clock to
the wall clock, but an unavoidable ~3ms software lag created a fixed bias
that made Rx timestamps appear after Tx in override-mode delta calculations,
breaking correct Tx/Rx alignment.

Fix:
- For uptime-based backends (hwTimestamp < timeBasis), use
  CANConManager::getElapsedUs() directly for Rx timestamps instead of
  the PCAN hw clock. This is the identical monotonic source used for Tx
  timestamps, so Tx and Rx are always on the same clock with no drift or
  bias.
- Add CANConManager::getElapsedUs() helper exposing mElapsedTimer.
- Remove the first-frame anchor members (mFirstHwTimestamp,
  mFirstElapsedUs) that are no longer needed.
- Revert the timestamp sort in refreshConnection() that was a workaround
  for the bias; natural emission order is now always correct.
When 'Clear Frames' is clicked while frames are arriving, resetTimeBasis()
restarts mElapsedTimer but frames already queued by the working thread
carry timestamps from the old (pre-reset) elapsed timer. These get drained
on the next 20ms tick and appear with large incorrect timestamps, breaking
timestamp alignment with subsequent frames.

Fix: flush every connection's queue inside resetTimeBasis() so all pre-reset
frames are discarded before the timer fires.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant