Firmware: RIOv4_2_patched_125000.bin — max-speed science build (13x)
make_patch.py generalized: baud flags 31250/62500/125000, each holding the byte-clocked ACK-wait at ~12.8ms wall time (40/80/160 ticks; the widen is implied for 62500/125000 since stock 4 ticks would be 0.6/0.3ms there). All historical hashes reproduce unchanged; the 125000 image (sha256 d22c8d85..., 25 bytes) diffs from 31250v2 by exactly the BAUD and CMPA operands. Predictions on record for the bench run: FTDI side exact (3M/24); the MAX232-class level shifter is AT its 120kbps rating so edge-rounding may surface as noise flags; and the 2MHz HC11 has ~160 E-cycles/byte - back-to-back inbound bytes likely outrun the RX ISR (the firmware sets its overrun flag $3186 but never reads it), so expect dropped bytes -> NAK/retry churn and a dirtier profile than v2's. Wedges should stay 0. 62500 is one flag away as the fallback sweet spot. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
+34
-15
@@ -22,15 +22,34 @@ aborts instead of corrupting the image. Address == file offset.
|
||||
"""
|
||||
import sys, hashlib
|
||||
|
||||
BAUD31250 = "--baud31250" in sys.argv
|
||||
WIDEN_ACKWAIT = "--widen-ackwait" in sys.argv
|
||||
assert not WIDEN_ACKWAIT or BAUD31250, \
|
||||
"--widen-ackwait only makes sense with --baud31250 (the wait is byte-scaled)"
|
||||
# Baud retunes: flag -> (BAUD register value, ACK-wait ticks for ~12.8ms, name).
|
||||
# The ACK-wait loop self-clocks in byte times (see edit 4), so each rate needs
|
||||
# its own tick count to hold the same ~12.8ms wall-clock ACK grace window.
|
||||
BAUD_OPTS = {
|
||||
"--baud31250": (0x02, 0x28, "31250"), # /1 /4 -> 31250 (40 ticks)
|
||||
"--baud62500": (0x01, 0x50, "62500"), # /1 /2 -> 62500 (80 ticks)
|
||||
"--baud125000": (0x00, 0xA0, "125000"), # /1 /1 -> 125000 (160 ticks)
|
||||
}
|
||||
selected = [f for f in BAUD_OPTS if f in sys.argv]
|
||||
assert len(selected) <= 1, f"pick one baud flag, got {selected}"
|
||||
BAUD_VAL, ACKWAIT_VAL, BAUD_NAME = BAUD_OPTS[selected[0]] if selected else (None, None, None)
|
||||
|
||||
# --widen-ackwait: required semantics for 62500/125000 (implied there); optional
|
||||
# for 31250 to keep the historical v1 image reproducible.
|
||||
WIDEN_ACKWAIT = "--widen-ackwait" in sys.argv or BAUD_NAME in ("62500", "125000")
|
||||
assert not ("--widen-ackwait" in sys.argv) or selected, \
|
||||
"--widen-ackwait only makes sense with a baud retune (the wait is byte-scaled)"
|
||||
|
||||
args = [a for a in sys.argv[1:] if not a.startswith("--")]
|
||||
SRC = args[0] if len(args) > 0 else "RIOv4_2.bin"
|
||||
DST = args[1] if len(args) > 1 else (
|
||||
"RIOv4_2_patched_31250v2.bin" if WIDEN_ACKWAIT else
|
||||
"RIOv4_2_patched_31250.bin" if BAUD31250 else "RIOv4_2_patched.bin")
|
||||
if len(args) > 1:
|
||||
DST = args[1]
|
||||
elif BAUD_NAME == "31250":
|
||||
DST = "RIOv4_2_patched_31250v2.bin" if WIDEN_ACKWAIT else "RIOv4_2_patched_31250.bin"
|
||||
elif BAUD_NAME:
|
||||
DST = f"RIOv4_2_patched_{BAUD_NAME}.bin"
|
||||
else:
|
||||
DST = "RIOv4_2_patched.bin"
|
||||
|
||||
d = bytearray(open(SRC, "rb").read())
|
||||
assert len(d) == 0x10000, f"expected 64KB image, got {len(d)}"
|
||||
@@ -71,22 +90,22 @@ assert d[0xDA2E] == 0x39, "RTS at $DA2E must be intact"
|
||||
# --- edit 3 (--baud31250 only): SCI 9600 -> 31250 --------------------------
|
||||
# $D62A 86 30 LDAA #$30 (SCP=/13, SCR=/1) -> 86 02 (SCP=/1, SCR=/4)
|
||||
# then STAA $102B (BAUD). 2MHz E-clock: 2e6/(16*13)=9615 -> 2e6/(16*4)=31250.
|
||||
if BAUD31250:
|
||||
if BAUD_VAL is not None:
|
||||
assert d[0xD62A] == 0x86 and bytes(d[0xD62C:0xD62F]) == bytes([0xB7,0x10,0x2B]), \
|
||||
"expected LDAA #imm ; STAA $102B at $D62A"
|
||||
patch(0xD62B, [0x30], [0x02])
|
||||
patch(0xD62B, [0x30], [BAUD_VAL])
|
||||
|
||||
# --- edit 4 (--widen-ackwait, 31250 only): reply ACK-wait 4 -> 40 ticks -----
|
||||
# --- edit 4 (--widen-ackwait; implied for 62500/125000): scale the ACK-wait --
|
||||
# The no-ACK wait loop at $D9E0 self-clocks in BYTE TIMES: each tick transmits
|
||||
# an IDLE ($FF) keep-alive and re-enters on that byte's TX-complete interrupt.
|
||||
# 4 ticks = ~5.2ms at 9600 (USB ACK wins) but ~1.6ms at 31250 (USB loses ->
|
||||
# retry storm; bench 2026-07-18: framing 5655, Abandon 65). $28 = 40 ticks
|
||||
# = ~12.8ms at 31250, clearing FTDI worst-case turnaround with margin.
|
||||
# $D9E6 81 04 CMPA #$04 -> 81 28 CMPA #$28
|
||||
# The stock limit (4 ticks) = ~5.2ms at 9600 (USB ACK wins) but shrinks with
|
||||
# baud (retry storm at 31250; bench 2026-07-18: framing 5655, Abandon 65).
|
||||
# Each retune holds the window at ~12.8ms wall clock: 40/80/160 ticks.
|
||||
# $D9E6 81 04 CMPA #$04 -> 81 <ticks>
|
||||
if WIDEN_ACKWAIT:
|
||||
assert d[0xD9E6] == 0x81 and bytes(d[0xD9E3:0xD9E6]) == bytes([0xB6,0x31,0x7B]), \
|
||||
"expected LDAA $317B ; CMPA #imm at $D9E3"
|
||||
patch(0xD9E7, [0x04], [0x28])
|
||||
patch(0xD9E7, [0x04], [ACKWAIT_VAL])
|
||||
|
||||
open(DST, "wb").write(d)
|
||||
new_sha = hashlib.sha256(d).hexdigest()
|
||||
|
||||
Reference in New Issue
Block a user