mirror of
https://github.com/openglow-org/forgefirm.git
synced 2026-10-19 02:51:42 -07:00
motion.jog-roundtrip gets a check after its hold/resume segment, with the head at the start and the machine at rest: a 60 mm +X G1 at F3000, and a ^X 0.3 s after the kernel starts to play it. At a soft reset during motion the grblHAL driver stops the kernel with its ramp, reads the position back from the kernel's step counters, and keeps the core's reference. No other catalog test sends a ^X while the head moves, and the null-sink harness cannot read real counters: its residue is zero by construction. The check fails when: - the controller is not in Alarm within 2 s of the ^X, or is Idle with no alarm (the move had ended before the ^X); - cnc/state does not leave running within 1.0 s, or leaves it for a state other than idle, or cnc/underruns or cnc/faults change across the check; - the kernel did not decelerate: over the run's last 25 to 50 ms, the bytes played (the position record, polled at 5 ms) are more than 70% of cnc/step_freq; - the ring holds bytes after the reset; - after $X, MPos X in steps ($100) and the kernel's X count differ by more than one step, or Y or Z moved; - the homed mask changes, or the sender gets a [MSG:] line that the position cannot be read back; - the jog back by the MPos distance leaves the kernel's X counter more than one step from its start. The head is jogged back before these judgments, so a failure of one of them leaves the head at the start. The ramp witness is the tail rate because of the arithmetic. At the stop the ring holds about 110 ms of ticks: the 200 ms queue and the 10 ms lead, less the 100 ms that the core's alarm hold plays. The ramp to the kernel's 900 Hz floor uses 112.6 ms of ticks, in every mode, because the ramp scales with the tick. So the run ends at the floor or runs out of data part of the way down the ramp, and the steps that never played can be zero. A minimum of unplayed steps in the driver's read-back log line, the bytes played after the ^X, and the time to leave running cannot tell the ramp from a run-out with a 20% margin. The log line is also an INFO line, which the log level setting can remove. The tail rate is 21% to 56% of the tick for 90 to 110 ms of queue at the stop, and 100% for a run-out. The other readings and the log line go to the evidence. The homed mask comes from the controller port's state record (forgectrl /motion/state): $# prints [HOME:...:mask] only with $22 on, and the driver's default is off. Before the reset the mask must hold the Z bit (the lens hold), because a mask without it cannot show a dropped reference. The test also requires kernel.k1-k2, the kernel's controlled stop on the SoC. The title and the description say what the test proves now. est_min stays 3. Proof: compile and pyflakes 4.0.3 give no message on suite/motion.py and no undefined name in forgetest or tests. forgetest unit tests, python3 -B -m unittest discover -s tests -p test_<name>.py, in a private PID namespace: test_manifest.py 39 OK, test_queue.py 15 OK, test_campaign.py 13 OK. Coverage lint on the tree manifest from scripts/manifest-from-tree.py (python3 -B -m forgetest.coverage --manifest ../tree-manifest.json --enforce): 0 uncovered, 0 empty, 0 host-tested row problems, 43 tests. A host dry run of the whole test against the null-sink build of grblHAL-glowforge f3158d3: the head accelerometer, the kernel's state and bytes-played counter, and forgectrl are stand-ins; the step counters are the steps of the shipped stream; /motion/state is the controller's own control port. With a model kernel that ramps from the controller's cnc/stop write, the test passes: tail 23% of the tick, MPos X 3496.1 steps against 3496, mask 4 kept, the read-back log line found, the X counter back at its start, drift 0.000 mm. With a model kernel that plays its queue to the end at the tick, the ramp check fails at 100%. Against the null-sink build of the parent (eb8eb61), the check fails on the mask (4 -> 0) and on the read-back (MPos X 3483.1 steps against 3482). The real counters, the ramp, and the machine's timing are read on the machine only. Acceptance: the change is inside the test's own function, so the shared text of suite/motion.py does not change. The fingerprint of motion.jog-roundtrip moves, and no other test's: of the implementation hashes of the 43 catalog tests, before and after, only that one differs. The new check runs on the bench in the next campaign as part of motion.jog-roundtrip.