Skip to content

3.1r1: 8.12.2, collision avoidance - #56

Merged
jadamcrain merged 3 commits into
mainfrom
collision-avoidance
Oct 14, 2026
Merged

jadamcrain merged 3 commits into
mainfrom
collision-avoidance

Conversation

@jadamcrain

Copy link
Copy Markdown
Member

3.1r1's 8.12.2 over the serial transport from #54. 3.1r1 is now implemented in full.

Steps (each set of delays runs them all):

  • Steps 1–2: generate class 1 events, then read class 1 with link control block 0xC4. The DUT must answer with data. The time from the end of the read to the start of the answer gives its turnaround.
  • Step 3: size the noise as a whole number of frames that ends within the window from the later of the turnaround and the fixed delay, to the turnaround plus both delays. It aims for the frame count nearest the middle. If no count fits, the run aborts as a bench problem.
  • Steps 4–6: send the read followed at once by the noise. The answer must start no sooner than the fixed delay after the noise ends, and no later than both delays after it.
  • Step 7: repeat that ten times in all. The delays must spread over more than the tolerance. Where the maximum random delay is at least four times the tolerance, at most 6 of the 10 may be within a quarter of the tolerance of any one; a truly random device trips that well under 1% of the time. Where the random delay is too short to tell its values apart, the result notes that this wasn't verified.
  • Steps 8–9: send noise, a gap of half the fixed delay, then noise again, so the DUT must back off twice. The harness measures an upper bound on the gap it made; if that isn't shorter than the fixed delay, the run aborts as a bench problem.
  • Steps 10–11: set the other delays through the plugin (setCollisionDelays) and repeat. The usual delays are restored at the end, even after a failure.

The answer and the noise

  • The answer counted is the first frame of a response to the master, with the read's sequence number, not unsolicited, carrying objects. The harness's own echoed frames are skipped.
  • The noise is REQUEST LINK STATUS frames to a reserved address, which no device answers.
  • For a DUT that watches carrier, the harness asserts RTS while it sends noise.
  • The answers aren't confirmed, so the events stay for every read.

Timing. All times are measured on the host:

  • The serial channel now reads the port on a background thread, which timestamps bytes as they arrive whatever the harness is doing. The frame parser keeps the first byte's time for each frame (readFrameTimed).
  • Writes block until the bytes are sent. The noise's end is the later of when the write returned and the write's start plus its bytes' time on the line.
  • serial.timingToleranceMs allows for what the adapter adds, both ways, e.g. a USB adapter's latency timer.

Options

  • serial.collisionAvoidance
  • serial.collisionDetection (data or carrier)
  • serial.fixedDelayMs and serial.maxRandomDelayMs
  • serial.otherFixedDelayMs and serial.otherMaxRandomDelayMs
  • serial.timingToleranceMs

The configuration check requires a fixed delay above 0, and other delays that change both values.

Tests:

  • a simulated line on virtual time, with a device that backs off as it should, one that answers over the noise, ones whose delays don't vary or mostly repeat, and one that watches carrier;
  • the parser's arrival times;
  • a pty test showing that bytes are timed when they arrive, not when they're read.

The timing hasn't been run against a real serial device.

2.7's 8.12.2 stays not implemented, and its -describe output is unchanged.

Over serial: a class 1 read with link control block 0xC4, timed to
measure the DUT's turnaround; then the read followed at once by noise
that ends midway between the turnaround and fixed delay and the
turnaround plus both delays, after which the answer must start no sooner
than the fixed delay and no later than both delays after the noise ends,
ten times, with delays that vary by more than the tolerance where the
random delay is long enough to tell; then noise, a gap of half the fixed
delay and noise again, which makes the DUT back off twice; then all of it
with the other delays, set through the plugin (setCollisionDelays), and
the usual ones restored at the end.

The noise is REQUEST LINK STATUS frames to a reserved address. Times are
measured on this host: a write's start plus its bytes' time on the line
at the port's speed, and the arrival of the answer's first byte, which
the frame parser now records for each frame (readFrameTimed). For a DUT
that watches carrier, the harness asserts RTS while it sends noise.
serial.timingToleranceMs allows for the adapter's latency.

Options: serial.collisionAvoidance, serial.collisionDetection (data or
carrier), serial.fixedDelayMs and serial.maxRandomDelayMs, the other
pair for step 10, serial.timingToleranceMs. The configuration check
requires delays to test and different ones to change them to.

The driver gives a message's frame bytes (frameBytes) for one timed
write with the noise.
@jadamcrain
jadamcrain merged commit 47b845d into main Oct 14, 2026
5 checks passed
@jadamcrain
jadamcrain deleted the collision-avoidance branch October 14, 2026 15:32
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