1112 lines
37 KiB
JSON
1112 lines
37 KiB
JSON
{
|
|
"bench_implications": [
|
|
"A standalone command 4 frame from idle should not hit BD0E; command 4 is continuation-only and initial dispatch does not accept it.",
|
|
"Command 5 is not a generic always-live ACK. It only performs ACK/session-clear work on the continuation path while FAA2 != 0.",
|
|
"A valid six-byte RX frame loads F9C5 with 0x14, which temporarily sets FAA5.7; when that window expires, loc_3FEF can clear queue/session state and call loc_400C.",
|
|
"The observed 07 retry/error family can be produced by BE4D from RX[1:4] after error/checksum retry conditions; it is not automatically proof of a table value or a command-4 continuation token.",
|
|
"To prove CONNECT OK through serial, the bench has to create or preserve FAA2 != 0 at the moment command 4 arrives, and ideally FAA2.3 if it expects queued-report advancement."
|
|
],
|
|
"caveats": [
|
|
"This is an address-driven static branch map, not proof of every runtime predicate value.",
|
|
"Semantic names are candidates; the branch destinations and RAM side effects are ROM evidence.",
|
|
"loc_BE70/F970 and loc_3E54/F870 are separate queues; this report names them separately because mixing them up changes the command-4/5 interpretation."
|
|
],
|
|
"commands": [
|
|
{
|
|
"availability": "initial path only: checksum valid, FAA2 == 0, RX[1].7 == 0",
|
|
"command": 0,
|
|
"command_hex": "0x00",
|
|
"evidence_addresses_hex": [
|
|
"H'BC69",
|
|
"H'BC75",
|
|
"H'BC79",
|
|
"H'BC82",
|
|
"H'BC86",
|
|
"H'BCB0",
|
|
"H'BCCD",
|
|
"H'BCD0"
|
|
],
|
|
"handler_address_hex": "H'BC69",
|
|
"name": "set_value_acked_candidate",
|
|
"response_candidate": "F850=0x04; F851-F854 mostly echo RX[1:4]; BA26 sends it",
|
|
"side_effects": [
|
|
"selector zero is special: the low byte is forced to 0x80 after the high byte is taken from RX[3]",
|
|
"nonzero selectors can mirror into an auxiliary table via a mapping table",
|
|
"clears FAA2.7 before exit"
|
|
],
|
|
"summary": "writes RX[3:4] into primary/current tables, flags the selector, calls BE70, and sends an echo-style 0x04 response"
|
|
},
|
|
{
|
|
"availability": "initial path only: checksum valid, FAA2 == 0, RX[1].7 == 0",
|
|
"command": 1,
|
|
"command_hex": "0x01",
|
|
"evidence_addresses_hex": [
|
|
"H'BCD7",
|
|
"H'BCE0",
|
|
"H'BCE8",
|
|
"H'BCEC",
|
|
"H'BCF0",
|
|
"H'BCF6",
|
|
"H'BCFA",
|
|
"H'BCFD"
|
|
],
|
|
"handler_address_hex": "H'BCD7",
|
|
"name": "read_value_candidate",
|
|
"response_candidate": "F850=0x04; F851 is overwritten with RX[2]; F853/F854 receive table high/low; F852 is not freshly written here",
|
|
"side_effects": [
|
|
"does not enter continuation command handling",
|
|
"clears FAA2.7 before exit"
|
|
],
|
|
"summary": "reads primary table E000 + 2*selector and stages a 0x04 response"
|
|
},
|
|
{
|
|
"availability": "initial path only: checksum valid, FAA2 == 0, RX[1].7 == 0",
|
|
"command": 2,
|
|
"command_hex": "0x02",
|
|
"evidence_addresses_hex": [
|
|
"H'BD04",
|
|
"H'BD08"
|
|
],
|
|
"handler_address_hex": "H'BD04",
|
|
"name": "initial_clear_or_noop_candidate",
|
|
"response_candidate": null,
|
|
"side_effects": [
|
|
"likely a quiet/session-clear style command on the initial path"
|
|
],
|
|
"summary": "clears FAA2.7 and returns without staging a response"
|
|
},
|
|
{
|
|
"availability": "continuation path only: checksum valid, FAA2 != 0, command bit2 set, RX[1].7 == 0",
|
|
"command": 4,
|
|
"command_hex": "0x04",
|
|
"evidence_addresses_hex": [
|
|
"H'BD0E",
|
|
"H'BD1A",
|
|
"H'BD1E",
|
|
"H'BD22",
|
|
"H'BD26",
|
|
"H'BD35",
|
|
"H'BD64",
|
|
"H'BD67",
|
|
"H'BD6D",
|
|
"H'BD75",
|
|
"H'BD79"
|
|
],
|
|
"handler_address_hex": "H'BD0E",
|
|
"name": "continuation_set_value_candidate",
|
|
"response_candidate": null,
|
|
"side_effects": [
|
|
"selector zero is special: RX[3] becomes the high byte and low byte is forced to 0x80",
|
|
"nonzero selectors write E000 and flag EC00.7; the matching E800 current/report write is not present in this handler",
|
|
"nonzero selectors can mirror/persist through F400/BFE0 when mapping and F76E.7 allow it",
|
|
"if FAA2.3 was set from a queued report, advances F9B5 to consume that report",
|
|
"clears FAA3 and FAA2 before exit"
|
|
],
|
|
"summary": "writes a value into the primary table without an immediate serial response; selector zero also updates the current/report table"
|
|
},
|
|
{
|
|
"availability": "continuation path only: checksum valid, FAA2 != 0, command bit2 set, RX[1].7 == 0",
|
|
"command": 5,
|
|
"command_hex": "0x05",
|
|
"evidence_addresses_hex": [
|
|
"H'BD80",
|
|
"H'BD85",
|
|
"H'BD94",
|
|
"H'BD9A",
|
|
"H'BDB5",
|
|
"H'BDBF",
|
|
"H'BDC2",
|
|
"H'BDC8",
|
|
"H'BDD0",
|
|
"H'BDD4"
|
|
],
|
|
"handler_address_hex": "H'BD80",
|
|
"name": "continuation_ack_or_clear_pending_candidate",
|
|
"response_candidate": null,
|
|
"side_effects": [
|
|
"selectors 0x006C, 0x006D, and 0x006E call BE70",
|
|
"with F731.7 set, selectors 0x006B, 0x0096, 0x0097, 0x00C6, and 0x00F8 clear F731.7/F790.7",
|
|
"if FAA2.3 was set from a queued report, advances F9B5",
|
|
"clears FAA3 and FAA2 before exit"
|
|
],
|
|
"summary": "ACK/session-clear path; usually no response, but selected logical indexes feed BE70 or clear connection latches"
|
|
},
|
|
{
|
|
"availability": "continuation path only: checksum valid, FAA2 != 0, command bit2 set, RX[1].7 == 0",
|
|
"command": 6,
|
|
"command_hex": "0x06",
|
|
"evidence_addresses_hex": [
|
|
"H'BDDB",
|
|
"H'BDE5",
|
|
"H'BDE9",
|
|
"H'BDED",
|
|
"H'BDF3",
|
|
"H'BDFB",
|
|
"H'BDFF"
|
|
],
|
|
"handler_address_hex": "H'BDDB",
|
|
"name": "continuation_set_secondary_candidate",
|
|
"response_candidate": null,
|
|
"side_effects": [
|
|
"if FAA2.3 was set from a queued report, advances F9B5",
|
|
"clears FAA3 and FAA2 before exit"
|
|
],
|
|
"summary": "writes RX[3:4] into the secondary table and sets flag-table bit 6"
|
|
},
|
|
{
|
|
"availability": "initial or continuation path",
|
|
"command": 7,
|
|
"command_hex": "0x07",
|
|
"evidence_addresses_hex": [
|
|
"H'BE05",
|
|
"H'BE09",
|
|
"H'BE0D",
|
|
"H'BE11",
|
|
"H'BE15",
|
|
"H'BE19",
|
|
"H'BE1D",
|
|
"H'BE22"
|
|
],
|
|
"handler_address_hex": "H'BE05",
|
|
"name": "retransmit_previous_tx_candidate",
|
|
"response_candidate": "previous TX frame retransmitted through BA26",
|
|
"side_effects": [
|
|
"loads F9C0 with 0x1F before sending"
|
|
],
|
|
"summary": "copies the previous finalized TX frame bytes back into staging and sends them again"
|
|
}
|
|
],
|
|
"downstream_traces": [
|
|
{
|
|
"present": true,
|
|
"steps": [
|
|
{
|
|
"effect": "F850=0x04 and F851-F854 mirror the accepted host fields before BA26",
|
|
"evidence_addresses_hex": [
|
|
"H'BCB0",
|
|
"H'BCB5",
|
|
"H'BCC1",
|
|
"H'BCC9",
|
|
"H'BCCD"
|
|
],
|
|
"name": "stage command-0 echo"
|
|
},
|
|
{
|
|
"effect": "F850=0x04, F853/F854 receive the E000 table word, and BA26 sends it",
|
|
"evidence_addresses_hex": [
|
|
"H'BCD7",
|
|
"H'BCEC",
|
|
"H'BCF0",
|
|
"H'BCF6",
|
|
"H'BCFA"
|
|
],
|
|
"name": "stage command-1 readback"
|
|
},
|
|
{
|
|
"effect": "BA26 copies F850-F854 to F858-F85C and computes F85D as 0x5A XOR bytes 0-4",
|
|
"evidence_addresses_hex": [
|
|
"H'BA36",
|
|
"H'BA3A",
|
|
"H'BA42",
|
|
"H'BA4A",
|
|
"H'BA4E",
|
|
"H'BA64"
|
|
],
|
|
"name": "finalize TX frame"
|
|
},
|
|
{
|
|
"effect": "BA26 waits for TDRE, writes F858 to SCI1_TDR, sets F9C2=1, clears TDRE, and enables TIE",
|
|
"evidence_addresses_hex": [
|
|
"H'BA68",
|
|
"H'BA72",
|
|
"H'BA76",
|
|
"H'BA7B",
|
|
"H'BA7F"
|
|
],
|
|
"name": "start SCI1 transmission"
|
|
},
|
|
{
|
|
"effect": "TXI indexes F858+F9C2 until six bytes are sent, then disables TIE",
|
|
"evidence_addresses_hex": [
|
|
"H'BAAB",
|
|
"H'BAB1",
|
|
"H'BAB5",
|
|
"H'BABF",
|
|
"H'BAC3",
|
|
"H'BACA"
|
|
],
|
|
"name": "finish SCI1 transmission"
|
|
}
|
|
],
|
|
"summary": "Command 0, command 1, command 7, and the retry/error path stage F850-F854, call BA26, copy that staging area to F858-F85C, compute F85D, send the first byte, then let TXI send bytes 1-5.",
|
|
"title": "immediate response staging through loc_BA26"
|
|
},
|
|
{
|
|
"present": true,
|
|
"steps": [
|
|
{
|
|
"effect": "BE70 scans from F9B9 to F9B4, skips duplicates, writes R5 to F970+2*cursor, and advances F9B4",
|
|
"evidence_addresses_hex": [
|
|
"H'BE70",
|
|
"H'BE78",
|
|
"H'BE84",
|
|
"H'BE91",
|
|
"H'BE95",
|
|
"H'BE99"
|
|
],
|
|
"name": "append unique selector"
|
|
},
|
|
{
|
|
"effect": "loc_2806 reads F970+2*F9B9, advances F9B9, masks the selector to 0x01FF, and keeps it in R5",
|
|
"evidence_addresses_hex": [
|
|
"H'2806",
|
|
"H'280C",
|
|
"H'2819",
|
|
"H'281D",
|
|
"H'2822",
|
|
"H'2826",
|
|
"H'282A"
|
|
],
|
|
"name": "consume selector"
|
|
},
|
|
{
|
|
"effect": "selectors matching F736/F738/F73A/F73C/F73E/F740/F742/F754 call loc_48FA before the jump table",
|
|
"evidence_addresses_hex": [
|
|
"H'2837",
|
|
"H'285E",
|
|
"H'2878",
|
|
"H'2892",
|
|
"H'2CAB",
|
|
"H'2CAD"
|
|
],
|
|
"name": "active-selector side path"
|
|
},
|
|
{
|
|
"effect": "the consumer jumps through table 28A6; selector zero is emulator-correlated with the CONNECT handler window",
|
|
"evidence_addresses_hex": [
|
|
"H'289F",
|
|
"H'28A3"
|
|
],
|
|
"name": "selector jump table"
|
|
}
|
|
],
|
|
"summary": "BE70 appends unique logical selectors into the F970 ring. The main loop later consumes that ring at loc_2806 and dispatches selector-specific behavior through the 28A6 jump table.",
|
|
"title": "selector-processing queue BE70/F970 into loc_2806"
|
|
},
|
|
{
|
|
"present": true,
|
|
"steps": [
|
|
{
|
|
"effect": "when R2.7 is set, loc_3E54 deduplicates R3 in F870 and advances F9B0",
|
|
"evidence_addresses_hex": [
|
|
"H'3E54",
|
|
"H'3E58",
|
|
"H'3E6C",
|
|
"H'3E76",
|
|
"H'3E7A",
|
|
"H'3E7E"
|
|
],
|
|
"name": "enqueue serial report"
|
|
},
|
|
{
|
|
"effect": "if the serial queue is nearly full, loc_3E54 calls loc_3FD3 until there is space",
|
|
"evidence_addresses_hex": [
|
|
"H'3E82",
|
|
"H'3E8B",
|
|
"H'3E91",
|
|
"H'3E93"
|
|
],
|
|
"name": "queue backpressure drain"
|
|
},
|
|
{
|
|
"effect": "when R2.6 is set, loc_3E54 deduplicates R3 in F970 and advances F9B4",
|
|
"evidence_addresses_hex": [
|
|
"H'3E9A",
|
|
"H'3E9E",
|
|
"H'3EB2",
|
|
"H'3EBF",
|
|
"H'3EC3",
|
|
"H'3EC7"
|
|
],
|
|
"name": "enqueue selector processing"
|
|
},
|
|
{
|
|
"effect": "loc_BAF2 compares F9B5/F9B0, reads F870+2*F9B5, builds a TX report from E800, and calls BA26",
|
|
"evidence_addresses_hex": [
|
|
"H'BAF2",
|
|
"H'BAF8",
|
|
"H'BB00",
|
|
"H'BB08",
|
|
"H'BB1C",
|
|
"H'BB35",
|
|
"H'BB43"
|
|
],
|
|
"name": "dequeue serial report"
|
|
},
|
|
{
|
|
"effect": "after a report send, loc_BAF2 sets FAA2.3, FAA3.7, F9C6, and F9C8; command 4/5/6 can then consume or ACK that report",
|
|
"evidence_addresses_hex": [
|
|
"H'BB00",
|
|
"H'BB46",
|
|
"H'BB4C",
|
|
"H'BB51"
|
|
],
|
|
"name": "open continuation latch"
|
|
}
|
|
],
|
|
"summary": "loc_3E54 is a shared enqueue helper. R2.bit7 queues serial-visible report indexes in F870, while R2.bit6 queues selector-processing work in F970. loc_BAF2 is the path that turns F870 entries into outbound 6-byte frames.",
|
|
"title": "serial-report queue loc_3E54/F870 into loc_BAF2"
|
|
},
|
|
{
|
|
"present": true,
|
|
"steps": [
|
|
{
|
|
"effect": "TXI tests FAA2.3, FAA5.7, and nonzero F9C3 before continuing the TX frame",
|
|
"evidence_addresses_hex": [
|
|
"H'BA84",
|
|
"H'BA8A",
|
|
"H'BA90"
|
|
],
|
|
"name": "detect overlap"
|
|
},
|
|
{
|
|
"effect": "on overlap it clears FAA2.3 and FAA3, disables TIE, and loads F9C0=0x1F",
|
|
"evidence_addresses_hex": [
|
|
"H'BA96",
|
|
"H'BA9A",
|
|
"H'BA9E",
|
|
"H'BAA2"
|
|
],
|
|
"name": "collapse continuation"
|
|
},
|
|
{
|
|
"effect": "without the overlap, TXI sends bytes until F9C2 reaches six and then starts the post-TX delay path",
|
|
"evidence_addresses_hex": [
|
|
"H'BAA9",
|
|
"H'BAB5",
|
|
"H'BAC3",
|
|
"H'BACA",
|
|
"H'BADA",
|
|
"H'BAED"
|
|
],
|
|
"name": "normal completion path"
|
|
}
|
|
],
|
|
"summary": "The TX interrupt handler has an interlock: if a queued report is awaiting continuation and RX bytes are already arriving, it clears the report/continuation state and stops TXI before the normal frame-finish path.",
|
|
"title": "TXI/RXI race and continuation collapse"
|
|
},
|
|
{
|
|
"present": true,
|
|
"steps": [
|
|
{
|
|
"effect": "F9C5==0 clears F9B5/F9B0 and clears FAA5.7",
|
|
"evidence_addresses_hex": [
|
|
"H'3FEF",
|
|
"H'3FF5",
|
|
"H'3FF9",
|
|
"H'3FFD"
|
|
],
|
|
"name": "expire RX session"
|
|
},
|
|
{
|
|
"effect": "if clearing FAA5.7 changed the bit, loc_3FEF calls loc_400C",
|
|
"evidence_addresses_hex": [
|
|
"H'4001",
|
|
"H'4003"
|
|
],
|
|
"name": "call reset side path"
|
|
},
|
|
{
|
|
"effect": "loc_400C clears F730/F756-F759/F732/F75C/FB03/F791/F795/F76E and calls follow-on display/session refresh routines",
|
|
"evidence_addresses_hex": [
|
|
"H'400C",
|
|
"H'4010",
|
|
"H'4020",
|
|
"H'4028",
|
|
"H'4034",
|
|
"H'403C",
|
|
"H'4040",
|
|
"H'4042"
|
|
],
|
|
"name": "clear connection state"
|
|
}
|
|
],
|
|
"summary": "When F9C5 reaches zero, loc_3FEF clears queue cursors and FAA5.7; if FAA5.7 had been set, loc_400C clears connection/session RAM and refreshes the inactive display state.",
|
|
"title": "session expiry into reset/not-active state"
|
|
}
|
|
],
|
|
"feedback_loops": [
|
|
{
|
|
"bench_read": "a command-0 probe is stateful: it both writes table state and spends time in the post-TX delay, so it can disturb the continuation window being tested",
|
|
"evidence_addresses_hex": [
|
|
"H'BC69",
|
|
"H'BC75",
|
|
"H'BC86",
|
|
"H'BCB0",
|
|
"H'BCCD",
|
|
"H'BA2C",
|
|
"H'BA31",
|
|
"H'BE70",
|
|
"H'2819",
|
|
"H'28A3"
|
|
],
|
|
"name": "command-0 write echo and selector-processing loop",
|
|
"path": "RX validation -> BC69 table write -> BE70 appends selector to F970 -> BCB0/BA26 sends immediate 0x04 echo -> later loc_2806 consumes F970",
|
|
"present": true,
|
|
"timing_gate": "BA26 sets F9C0=0x64 and F9C4=0x07, temporarily delaying queued TX and heartbeat enqueue",
|
|
"trigger": "valid command 0 while FAA2 == 0",
|
|
"tx_outcome": "immediate command-4-style echo frame plus possible later selector-driven reports/display work"
|
|
},
|
|
{
|
|
"bench_read": "command 7 after command 1 proves what was last finalized, but does not prove a hidden continuation token by itself",
|
|
"evidence_addresses_hex": [
|
|
"H'BCD7",
|
|
"H'BCEC",
|
|
"H'BCFA",
|
|
"H'BA36",
|
|
"H'BA64",
|
|
"H'BE05",
|
|
"H'BE09",
|
|
"H'BE22"
|
|
],
|
|
"name": "command-1 readback and previous-frame loop",
|
|
"path": "RX validation -> BCD7 reads E000[selector] -> BA26 finalizes TX in F858-F85D -> BE05 can copy F858-F85C back to F850-F854",
|
|
"present": true,
|
|
"timing_gate": "command 1 clears FAA2.7 and never enters continuation handling; it is a readback path, not an ACK path",
|
|
"trigger": "valid command 1 while FAA2 == 0, followed by optional command 7",
|
|
"tx_outcome": "direct 0x04 readback, then command 7 can retransmit the exact last finalized TX frame"
|
|
},
|
|
{
|
|
"bench_read": "visible 07 frames in a noisy/tight timing run can be retry echoes, not necessarily device status or a continuation token",
|
|
"evidence_addresses_hex": [
|
|
"H'BE29",
|
|
"H'BE2D",
|
|
"H'BE33",
|
|
"H'BE37",
|
|
"H'BE3E",
|
|
"H'BE43",
|
|
"H'BE47",
|
|
"H'BE4D",
|
|
"H'BE6A"
|
|
],
|
|
"name": "retry/error 07 echo loop",
|
|
"path": "RX validation error -> BE29 retry gate -> BE4D stages F850=0x07 and copies RX[1:4] into F851-F854 -> BA26 sends",
|
|
"present": true,
|
|
"timing_gate": "after two retries, the ROM loads F9C0=0x1F and clears FAA3/FAA2 instead of sending another echo",
|
|
"trigger": "physical RX error or checksum mismatch while FAA5.7 is set and retry count FAA6 is below two",
|
|
"tx_outcome": "a 0x07 frame that can echo the host payload bytes, independent of E000/E800 table contents"
|
|
},
|
|
{
|
|
"bench_read": "the actual ACK/write target is not just the selector; it is the report that is live under FAA2.3 before TXI/RXI or BE9E clears it",
|
|
"evidence_addresses_hex": [
|
|
"H'3E54",
|
|
"H'3E76",
|
|
"H'3E7A",
|
|
"H'3FD3",
|
|
"H'3FE5",
|
|
"H'3FEB",
|
|
"H'BAF2",
|
|
"H'BB00",
|
|
"H'BB35",
|
|
"H'BB43",
|
|
"H'BB46",
|
|
"H'BB51",
|
|
"H'BD67",
|
|
"H'BDC2",
|
|
"H'BDED"
|
|
],
|
|
"name": "autonomous report to host continuation loop",
|
|
"path": "loc_3E54 appends report selector to F870 -> loc_3FD3 allows BAF2 when FAA2/F9C0 gates are clear -> BAF2 sends report -> command 4/5/6 continuation can advance F9B5",
|
|
"present": true,
|
|
"timing_gate": "F9C0 must count down before BAF2 can send, and F9C6/F9C8/BE9E control repeated sends while FAA3.7 remains live",
|
|
"trigger": "firmware enqueues a serial-visible report via loc_3E54 with R2.7 set",
|
|
"tx_outcome": "autonomous 6-byte report frame built from E800[selector], with FAA2.3/FAA3.7 left set to await host continuation or ACK"
|
|
},
|
|
{
|
|
"bench_read": "selector-zero CONNECT work and visible serial reports can be separated in time; lack of immediate TX does not mean the selector queue did nothing",
|
|
"evidence_addresses_hex": [
|
|
"H'BE70",
|
|
"H'BE91",
|
|
"H'2806",
|
|
"H'2819",
|
|
"H'2CAD",
|
|
"H'48FA",
|
|
"H'490F",
|
|
"H'4921",
|
|
"H'4923",
|
|
"H'4926"
|
|
],
|
|
"name": "selector-processing to report loop",
|
|
"path": "BE70/F970 selector queue -> loc_2806 selector dispatch -> active-selector side path loc_48FA -> loc_3E54 can enqueue report 0x00F6 when E1EC.13 is set",
|
|
"present": true,
|
|
"timing_gate": "loc_48FA is gated by FB03.7, F732 values, E1EC.13, and F76E.6 before reaching its indirect table",
|
|
"trigger": "command 0/4/selected command 5 calls BE70, or loc_3E54 is called with R2.6 set",
|
|
"tx_outcome": "possible later serial report produced through the F870/BAF2 loop rather than an immediate response to the original RX frame"
|
|
},
|
|
{
|
|
"bench_read": "this is a concrete ROM reason why bench timing might see latches/retries while a too-polite emulator reaches cleaner continuation paths",
|
|
"evidence_addresses_hex": [
|
|
"H'BA84",
|
|
"H'BA8A",
|
|
"H'BA90",
|
|
"H'BA96",
|
|
"H'BA9A",
|
|
"H'BA9E",
|
|
"H'BAA2"
|
|
],
|
|
"name": "TXI/RXI overlap cancellation loop",
|
|
"path": "TXI observes FAA2.3 + FAA5.7 + F9C3 != 0 -> clears FAA2.3/FAA3 -> disables TIE -> loads F9C0=0x1F",
|
|
"present": true,
|
|
"timing_gate": "this depends on byte timing relative to TXI and F9C3, so polite emulator injection can miss it",
|
|
"trigger": "host RX bytes begin while a report TX is active, FAA2.3 is set, and FAA5.7 is set",
|
|
"tx_outcome": "the pending report/continuation state can be canceled before the host command reaches the continuation dispatcher"
|
|
},
|
|
{
|
|
"bench_read": "the common CONNECT NOT ACT after arbitrary six-byte traffic is consistent with this expiry/reset loop",
|
|
"evidence_addresses_hex": [
|
|
"H'BB9E",
|
|
"H'BF31",
|
|
"H'BF37",
|
|
"H'3FEF",
|
|
"H'3FFD",
|
|
"H'4003",
|
|
"H'400C",
|
|
"H'4046",
|
|
"H'4067",
|
|
"H'BA31"
|
|
],
|
|
"name": "session-expiry to heartbeat/not-active loop",
|
|
"path": "RX complete -> F9C5=0x14 -> FRT2 decrements F9C5 -> loc_3FEF clears session/queues and calls 400C -> loc_4046 can later enqueue heartbeat selector 0",
|
|
"present": true,
|
|
"timing_gate": "F9C4 gates heartbeat enqueue; BA26 reloads it to 0x07 after each send, matching the roughly 700 ms heartbeat cadence",
|
|
"trigger": "any complete six-byte RX frame loads F9C5, then FRT2 decrements it to zero",
|
|
"tx_outcome": "eventual return to idle heartbeat/report behavior and inactive-session display state"
|
|
}
|
|
],
|
|
"frame_model": {
|
|
"capture_buffer": {
|
|
"end": 63597,
|
|
"end_hex": "H'F86D",
|
|
"range_hex": "H'F868-H'F86D",
|
|
"start": 63592,
|
|
"start_hex": "H'F868"
|
|
},
|
|
"channel": "SCI1",
|
|
"checksum_seed": 90,
|
|
"checksum_seed_hex": "0x5A",
|
|
"command_expression": "RX[0] & 0x07",
|
|
"frame_length": 6,
|
|
"index_expression_candidate": "loc_622B(RX[1], RX[2])",
|
|
"tx_staging_buffer": {
|
|
"end": 63572,
|
|
"end_hex": "H'F854",
|
|
"range_hex": "H'F850-H'F854",
|
|
"start": 63568,
|
|
"start_hex": "H'F850"
|
|
},
|
|
"validation_buffer": {
|
|
"end": 63589,
|
|
"end_hex": "H'F865",
|
|
"range_hex": "H'F860-H'F865",
|
|
"start": 63584,
|
|
"start_hex": "H'F860"
|
|
},
|
|
"value_expression_candidate": "RX[3:4]"
|
|
},
|
|
"kind": "rx_branch_trace",
|
|
"selector_decode": {
|
|
"implications": [
|
|
"RX[1].7 is not part of the selector here because the dispatcher rejects byte1 bit7 before command handling.",
|
|
"Commands shaped as 01 80 xx ... are rejected before loc_622B-derived command handling even if the low byte looks useful.",
|
|
"Page 4-7 encodings appear to alias the page-0 decode path unless the low byte is out of range."
|
|
],
|
|
"input_expression_candidate": "raw = (RX[1] << 8) | RX[2]; page = RX[1] & 0x07; low = RX[2]",
|
|
"present": true,
|
|
"rules": [
|
|
{
|
|
"condition": "page 0, or pages 4-7, and low <= 0x7F",
|
|
"evidence_addresses_hex": [
|
|
"H'6234",
|
|
"H'6236",
|
|
"H'6244",
|
|
"H'6248",
|
|
"H'6264"
|
|
],
|
|
"outcome": "selector = 0x000 + low"
|
|
},
|
|
{
|
|
"condition": "page 1 and low <= 0xFF",
|
|
"evidence_addresses_hex": [
|
|
"H'6238",
|
|
"H'623A",
|
|
"H'624D",
|
|
"H'6251",
|
|
"H'6264"
|
|
],
|
|
"outcome": "selector = 0x080 + low"
|
|
},
|
|
{
|
|
"condition": "page 2 and low <= 0x7F",
|
|
"evidence_addresses_hex": [
|
|
"H'623C",
|
|
"H'623E",
|
|
"H'6256",
|
|
"H'625A",
|
|
"H'6264"
|
|
],
|
|
"outcome": "selector = 0x180 + low"
|
|
},
|
|
{
|
|
"condition": "page 3, page/range failure, or page 0/4-7 with low > 0x7F",
|
|
"evidence_addresses_hex": [
|
|
"H'6240",
|
|
"H'6242",
|
|
"H'625F",
|
|
"H'6261"
|
|
],
|
|
"outcome": "selector forced to 0x01FF"
|
|
}
|
|
],
|
|
"summary": "The RX handler builds a raw word from RX[1:2], uses RX[1] bit0-bit2 as a page, keeps RX[2] as the low selector byte, and maps the result into a 0x000-0x1FF logical selector.",
|
|
"title": "loc_622B logical selector decode"
|
|
},
|
|
"stages": [
|
|
{
|
|
"branches": [
|
|
{
|
|
"condition": "ERI taken",
|
|
"evidence_addresses_hex": [
|
|
"H'BB57",
|
|
"H'BB5B",
|
|
"H'BB5F",
|
|
"H'BB63"
|
|
],
|
|
"outcome": "set FAA4.7, clear ORER/FER/PER, then fall into RXI byte capture"
|
|
},
|
|
{
|
|
"condition": "F9C1 == 0 before byte",
|
|
"evidence_addresses_hex": [
|
|
"H'BB71",
|
|
"H'BB75",
|
|
"H'BB77"
|
|
],
|
|
"outcome": "clear F9C3 so the byte starts a fresh frame"
|
|
},
|
|
{
|
|
"condition": "F9C1 != 0 and F9C3 <= 5",
|
|
"evidence_addresses_hex": [
|
|
"H'BB7D",
|
|
"H'BB82",
|
|
"H'BB8A",
|
|
"H'BB90",
|
|
"H'BB96"
|
|
],
|
|
"outcome": "append byte at F868 + F9C3 and increment F9C3"
|
|
},
|
|
{
|
|
"condition": "F9C1 != 0 and F9C3 > 5",
|
|
"evidence_addresses_hex": [
|
|
"H'BB7D",
|
|
"H'BB82",
|
|
"H'BB84",
|
|
"H'BB88"
|
|
],
|
|
"outcome": "clear FAA4 and skip storing this byte"
|
|
},
|
|
{
|
|
"condition": "incremented F9C3 == 6",
|
|
"evidence_addresses_hex": [
|
|
"H'BB9A",
|
|
"H'BB9C",
|
|
"H'BB9E"
|
|
],
|
|
"outcome": "load F9C5 with 0x14 as the RX/session timeout window"
|
|
},
|
|
{
|
|
"condition": "any RXI exit",
|
|
"evidence_addresses_hex": [
|
|
"H'BBA3"
|
|
],
|
|
"outcome": "reload F9C1 with 0x05 as the inter-byte timeout"
|
|
}
|
|
],
|
|
"present": true,
|
|
"summary": "ERI latches FAA4.7 and clears physical error flags; RXI clears RDRF, reads SCI1_RDR, stores bytes into F868-F86D, reloads F9C1, and sets F9C5 when six bytes are captured.",
|
|
"title": "SCI1 RXI/ERI byte capture"
|
|
},
|
|
{
|
|
"branches": [
|
|
{
|
|
"condition": "F9C3 != 6",
|
|
"evidence_addresses_hex": [
|
|
"H'BBAB",
|
|
"H'BBB0"
|
|
],
|
|
"outcome": "return without processing"
|
|
},
|
|
{
|
|
"condition": "FAA4.7 set after capture",
|
|
"evidence_addresses_hex": [
|
|
"H'BBCF",
|
|
"H'BBD3"
|
|
],
|
|
"outcome": "enter retry/error path at BE29"
|
|
},
|
|
{
|
|
"condition": "checksum mismatch",
|
|
"evidence_addresses_hex": [
|
|
"H'BBD6",
|
|
"H'BBD8",
|
|
"H'BBDC",
|
|
"H'BBE0",
|
|
"H'BBE4",
|
|
"H'BBE8",
|
|
"H'BBEC",
|
|
"H'BBF0"
|
|
],
|
|
"outcome": "enter retry/error path at BE29"
|
|
},
|
|
{
|
|
"condition": "checksum valid",
|
|
"evidence_addresses_hex": [
|
|
"H'BBF3",
|
|
"H'BBF7",
|
|
"H'BBFD",
|
|
"H'BC01",
|
|
"H'BC08",
|
|
"H'BC0C"
|
|
],
|
|
"outcome": "clear FAA6, decode selector from RX[1:2] through loc_622B, and dispatch on RX[0] & 0x07"
|
|
}
|
|
],
|
|
"present": true,
|
|
"summary": "The main-loop processor only runs when F9C3 is six, copies F868-F86D to F860-F865, clears F9C3, rejects physical-error frames, checks the 0x5A XOR checksum, and decodes the index.",
|
|
"title": "six-byte validation and checksum"
|
|
},
|
|
{
|
|
"branches": [
|
|
{
|
|
"condition": "FAA2 == 0",
|
|
"evidence_addresses_hex": [
|
|
"H'BC0F",
|
|
"H'BC13",
|
|
"H'BC15",
|
|
"H'BC20",
|
|
"H'BC24",
|
|
"H'BC29",
|
|
"H'BC2E"
|
|
],
|
|
"outcome": "set FAA2.7 and test initial commands 0, 1, 2, 7"
|
|
},
|
|
{
|
|
"condition": "FAA2 != 0 and command bit2 set",
|
|
"evidence_addresses_hex": [
|
|
"H'BC0F",
|
|
"H'BC13",
|
|
"H'BC3A",
|
|
"H'BC45",
|
|
"H'BC4A",
|
|
"H'BC4F",
|
|
"H'BC54"
|
|
],
|
|
"outcome": "continuation commands 4, 5, 6, 7 are possible"
|
|
},
|
|
{
|
|
"condition": "FAA2 != 0 and command bit2 clear",
|
|
"evidence_addresses_hex": [
|
|
"H'BC3A",
|
|
"H'BC3C",
|
|
"H'BC5C",
|
|
"H'BC60",
|
|
"H'BC63",
|
|
"H'BC67"
|
|
],
|
|
"outcome": "BCLR FAA2.3; if that bit was set, clear FAA3 and re-enter initial dispatcher"
|
|
},
|
|
{
|
|
"condition": "byte1 bit7 set on initial path",
|
|
"evidence_addresses_hex": [
|
|
"H'BC19",
|
|
"H'BC1D",
|
|
"H'BD0B"
|
|
],
|
|
"outcome": "branch to BD0B and return without normal command handling"
|
|
},
|
|
{
|
|
"condition": "byte1 bit7 set on continuation path",
|
|
"evidence_addresses_hex": [
|
|
"H'BC3E",
|
|
"H'BC42",
|
|
"H'BE27"
|
|
],
|
|
"outcome": "branch to BE27 and return without normal command handling"
|
|
}
|
|
],
|
|
"present": true,
|
|
"summary": "FAA2 == 0 enters the initial dispatcher for commands 0, 1, 2, and 7. FAA2 != 0 enters the continuation dispatcher; commands 4, 5, and 6 only live there.",
|
|
"title": "FAA2 split dispatcher"
|
|
},
|
|
{
|
|
"branches": [
|
|
{
|
|
"condition": "FAA5.7 == 0",
|
|
"evidence_addresses_hex": [
|
|
"H'BE29",
|
|
"H'BE2D",
|
|
"H'BE31"
|
|
],
|
|
"outcome": "return after clearing FAA4.7; retry echo is disabled"
|
|
},
|
|
{
|
|
"condition": "FAA5.7 == 1 and FAA6 < 2",
|
|
"evidence_addresses_hex": [
|
|
"H'BE33",
|
|
"H'BE37",
|
|
"H'BE3C",
|
|
"H'BE4D",
|
|
"H'BE52",
|
|
"H'BE5A",
|
|
"H'BE62",
|
|
"H'BE6A"
|
|
],
|
|
"outcome": "stage F850=0x07 and F851-F854=RX[1:4], then call BA26"
|
|
},
|
|
{
|
|
"condition": "FAA5.7 == 1 and FAA6 >= 2",
|
|
"evidence_addresses_hex": [
|
|
"H'BE37",
|
|
"H'BE3C",
|
|
"H'BE3E",
|
|
"H'BE43",
|
|
"H'BE47"
|
|
],
|
|
"outcome": "load F9C0=0x1F and clear FAA3/FAA2"
|
|
}
|
|
],
|
|
"present": true,
|
|
"summary": "Physical RX errors or checksum failures can either be ignored, clear the session after two retries, or stage a command-7 retry/error echo of RX[1:4].",
|
|
"title": "checksum/error retry path"
|
|
},
|
|
{
|
|
"branches": [
|
|
{
|
|
"condition": "selector already present",
|
|
"evidence_addresses_hex": [
|
|
"H'BE84",
|
|
"H'BE88",
|
|
"H'BE9D"
|
|
],
|
|
"outcome": "exit without appending"
|
|
},
|
|
{
|
|
"condition": "ring scan reaches F9B4 cursor",
|
|
"evidence_addresses_hex": [
|
|
"H'BE80",
|
|
"H'BE82",
|
|
"H'BE91",
|
|
"H'BE95",
|
|
"H'BE99"
|
|
],
|
|
"outcome": "store R5 into the pending ring and advance F9B4"
|
|
}
|
|
],
|
|
"present": true,
|
|
"summary": "Several write/ACK paths call BE70 with R5 as the logical selector. BE70 deduplicates that selector against a small F970-like ring using cursors F9B9/F9B4, then appends it if absent.",
|
|
"title": "pending selector ring at loc_BE70"
|
|
},
|
|
{
|
|
"branches": [
|
|
{
|
|
"condition": "F9C5 == 0 at loc_3FEF",
|
|
"evidence_addresses_hex": [
|
|
"H'3FEF",
|
|
"H'3FF3",
|
|
"H'3FF5",
|
|
"H'3FF9",
|
|
"H'3FFD",
|
|
"H'4001",
|
|
"H'4003"
|
|
],
|
|
"outcome": "clear F9B5/F9B0 and clear FAA5.7; if FAA5.7 was set, call 400C reset/NOT-ACT state clear"
|
|
},
|
|
{
|
|
"condition": "F9C5 != 0 at loc_3FEF",
|
|
"evidence_addresses_hex": [
|
|
"H'3FEF",
|
|
"H'3FF3",
|
|
"H'4007"
|
|
],
|
|
"outcome": "set FAA5.7, allowing retry/resend/session-gated paths"
|
|
},
|
|
{
|
|
"condition": "BE9E sees no pending FAA5 & FAA3 & 0x80",
|
|
"evidence_addresses_hex": [
|
|
"H'BE9E",
|
|
"H'BEA5",
|
|
"H'BEA9",
|
|
"H'BEAD",
|
|
"H'BEAF"
|
|
],
|
|
"outcome": "clear FAA2 and return"
|
|
},
|
|
{
|
|
"condition": "BE9E pending and F9C6==0 and F9C8!=0",
|
|
"evidence_addresses_hex": [
|
|
"H'BEB5",
|
|
"H'BEBB",
|
|
"H'BEC1",
|
|
"H'BEC5",
|
|
"H'BECB",
|
|
"H'BED1",
|
|
"H'BED5"
|
|
],
|
|
"outcome": "decrement F9C8, reload F9C6, and possibly resend staged TX through BA26"
|
|
},
|
|
{
|
|
"condition": "BE9E pending but F9C8==0",
|
|
"evidence_addresses_hex": [
|
|
"H'BEBB",
|
|
"H'BEBF",
|
|
"H'BEE4"
|
|
],
|
|
"outcome": "clear F9C5, which lets 3FEF collapse the session gate later"
|
|
}
|
|
],
|
|
"present": true,
|
|
"summary": "After any complete RX frame, F9C5 keeps FAA5.7/session-gate state alive for a short window. When that window expires, 3FEF can clear queue cursors and call 400C, while BE9E handles resend countdowns.",
|
|
"title": "session timeout and resend side paths"
|
|
}
|
|
],
|
|
"state_bits": [
|
|
{
|
|
"address": 64162,
|
|
"address_hex": "H'FAA2",
|
|
"bit": 7,
|
|
"meaning": "set on initial-path parse; cleared by command 0/1/2 exits or by continuation cleanup",
|
|
"name": "rx_command_in_progress_candidate"
|
|
},
|
|
{
|
|
"address": 64162,
|
|
"address_hex": "H'FAA2",
|
|
"bit": 3,
|
|
"meaning": "set by the autonomous queue send path at BB00; continuation command 4/5/6 can advance F9B5 only when this bit was set",
|
|
"name": "queued_report_ack_needed_candidate"
|
|
},
|
|
{
|
|
"address": 64163,
|
|
"address_hex": "H'FAA3",
|
|
"bit": 7,
|
|
"meaning": "set after queued report send; BE9E masks it with FAA5.7 before resend/clear decisions",
|
|
"name": "pending_resend_mask_candidate"
|
|
},
|
|
{
|
|
"address": 64164,
|
|
"address_hex": "H'FAA4",
|
|
"bit": 7,
|
|
"meaning": "set by SCI1 ERI and tested before checksum dispatch",
|
|
"name": "rx_physical_error_latch_candidate"
|
|
},
|
|
{
|
|
"address": 64165,
|
|
"address_hex": "H'FAA5",
|
|
"bit": 7,
|
|
"meaning": "set while F9C5 is alive after a complete RX frame; gates retry/resend and heartbeat/report enqueue behavior",
|
|
"name": "rx_session_gate_candidate"
|
|
}
|
|
],
|
|
"summary": {
|
|
"confidence": "high",
|
|
"core_finding": "The ROM captures six SCI1 bytes, validates a 0x5A-seeded XOR checksum, decodes RX[0] & 0x07, then splits into initial commands while FAA2 == 0 and continuation commands while FAA2 != 0.",
|
|
"title": "SCI1 RX frame branch map"
|
|
},
|
|
"table_surfaces": [
|
|
{
|
|
"details": [
|
|
"indexed as E000 + 2*selector after loc_622B",
|
|
"selector zero writes force the low byte to 0x80 on commands 0 and 4",
|
|
"this is the table that must contain E000[0]=0x8080 for the emulator-correlated CONNECT OK branch"
|
|
],
|
|
"evidence_addresses_hex": [
|
|
"H'BC75",
|
|
"H'BC95",
|
|
"H'BCEC",
|
|
"H'BD1A",
|
|
"H'BD35"
|
|
],
|
|
"name": "primary_value_table",
|
|
"present": true,
|
|
"range_hex": "H'E000-H'E3FF",
|
|
"summary": "logical selector word table; command 0 and continuation command 4 write it, command 1 reads it"
|
|
},
|
|
{
|
|
"details": [
|
|
"command 0 writes both primary E000 and current E800 for zero and nonzero selectors",
|
|
"command 4 writes E800 only on the selector-zero special path; the nonzero command-4 path does not show a matching E800 write here",
|
|
"loc_BAF2 reads E800 + 2*queued_selector when building autonomous report frames"
|
|
],
|
|
"evidence_addresses_hex": [
|
|
"H'BC79",
|
|
"H'BC99",
|
|
"H'BD1E",
|
|
"H'BB35",
|
|
"H'BB39",
|
|
"H'BB3F"
|
|
],
|
|
"name": "current_report_value_table",
|
|
"present": true,
|
|
"range_hex": "H'E800-H'EBFF",
|
|
"summary": "current/report value table used when queued serial reports are converted into TX frames"
|
|
},
|
|
{
|
|
"details": [
|
|
"command 6 writes RX[3:4] to E400 + 2*selector",
|
|
"the matching EC00 flag bit is bit6 rather than bit7"
|
|
],
|
|
"evidence_addresses_hex": [
|
|
"H'BDE5",
|
|
"H'BDE9"
|
|
],
|
|
"name": "secondary_value_table",
|
|
"present": true,
|
|
"range_hex": "H'E400-H'E7FF",
|
|
"summary": "secondary logical selector word table written by continuation command 6"
|
|
},
|
|
{
|
|
"details": [
|
|
"the same logical selector indexes this byte table directly, not as a word offset",
|
|
"loc_48FA and other consumers test these table bits before raising follow-on reports"
|
|
],
|
|
"evidence_addresses_hex": [
|
|
"H'BC82",
|
|
"H'BC9D",
|
|
"H'BD22",
|
|
"H'BD39",
|
|
"H'BDE9"
|
|
],
|
|
"name": "dirty_flag_table",
|
|
"present": true,
|
|
"range_hex": "H'EC00-H'EDFF",
|
|
"summary": "per-selector flag bytes; command 0/4 set bit7 and command 6 sets bit6"
|
|
},
|
|
{
|
|
"details": [
|
|
"nonzero command-0 and command-4 writes consult mapping bytes/words before mirroring into F400",
|
|
"command 4 can call BFE0 to persist the mapped word when F76E.7 is set",
|
|
"selector zero bypasses this mapped mirror path"
|
|
],
|
|
"evidence_addresses_hex": [
|
|
"H'BCA1",
|
|
"H'BCA9",
|
|
"H'BD3D",
|
|
"H'BD45",
|
|
"H'BD49",
|
|
"H'BD5F"
|
|
],
|
|
"name": "mapped_shadow_or_eeprom_surface",
|
|
"present": true,
|
|
"range_hex": "H'F400-H'F4FF",
|
|
"summary": "optional mapped mirror/persistence surface selected through ROM tables around C564/C565"
|
|
}
|
|
]
|
|
}
|