pureboot.py: --scan walks a silent loader's rate; --info decodes the clock
The RC-oscillator answer's host half. --scan probes ±10 % around the built rate in 2 % steps, nearest first, one activation window (one reset) per probe: a fixed-baud loader whose oscillator drifted answers at the ratio, and the report gives the session workaround (--baud), the offset, the OSCCAL direction at ~1 %/step, and the autobaud way out. The walk and the advice are logic-tested (test_scan.py, red-proven on the trim direction) — a pty carries bytes at any rate, so the wire cannot arbitrate them. On an autobaud session --info now reads the measured bit period from ram_start — the geometry table gains that column — and undoes the unit's encoding ((cycles − 8) / 4, floored: libavr's spin granule and per-bit overhead), so the printed clock is the true one within a granule; --clock turns it into a stated drift. The autobaud end-to-end asserts the figure inside exactly that envelope at both clock points. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
53
test/test_scan.py
Normal file
53
test/test_scan.py
Normal file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python3
|
||||
"""--scan's walk and report logic, no simulator: the probe order, the rate
|
||||
arithmetic, and the advice's direction. The rate physics itself is not
|
||||
sim-testable — a pty carries bytes at any termios rate — so what the wire
|
||||
would arbitrate is pinned here as logic instead.
|
||||
|
||||
Usage: test_scan.py <tool_py>
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def fail(message):
|
||||
print(f"FAIL: {message}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def main():
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(sys.argv[1])))
|
||||
import pureboot as pb
|
||||
|
||||
walk = pb.scan_ratios()
|
||||
if walk != [0, -2, 2, -4, 4, -6, 6, -8, 8, -10, 10]:
|
||||
fail(f"probe walk is not built-rate-first, nearest-out: {walk}")
|
||||
|
||||
if pb.scan_rate(9600, 4) != 9984 or pb.scan_rate(9600, -4) != 9216:
|
||||
fail("probe rate arithmetic")
|
||||
if pb.scan_rate(115200, 0) != 115200:
|
||||
fail("the built rate must probe unchanged")
|
||||
|
||||
# A loader answering fast means a fast oscillator: the trim goes down.
|
||||
report = "\n".join(pb.scan_report(9600, 4, 6))
|
||||
for needle in ("9984", "+4 %", "--baud 9984", "4 steps lower", "pureboot 6"):
|
||||
if needle not in report:
|
||||
fail(f"+4 % report lacks {needle!r}:\n{report}")
|
||||
report = "\n".join(pb.scan_report(9600, -6, 6))
|
||||
if "6 steps higher" not in report:
|
||||
fail(f"-6 % report advises the wrong direction:\n{report}")
|
||||
|
||||
report = "\n".join(pb.scan_report(9600, 0, 6))
|
||||
if "none" not in report or "steps" in report:
|
||||
fail(f"an on-rate answer must advise no trim:\n{report}")
|
||||
|
||||
report = "\n".join(pb.scan_report(9600, 4, 6, clock=9600000))
|
||||
if "9984000" not in report:
|
||||
fail(f"the absolute clock must scale with the found ratio:\n{report}")
|
||||
|
||||
print("OK")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user