1
0

RX-tx understanding

This commit is contained in:
Aiden
2026-05-26 10:48:39 +10:00
parent d1d924c408
commit 421c9f4567
13 changed files with 3968 additions and 0 deletions

View File

@@ -0,0 +1,386 @@
{
"case_count": 25,
"description": "Queue selector zero in F970, start at loc_2806, then enter loc_2CB9 through the ROM dispatch.",
"hits": [
{
"case_index": 15,
"display": " CONNECT: OK | | | ",
"e000": "0x8080",
"f730": "0x81",
"f9b4": "0x01",
"f9b9": "0x01",
"final_pc": "H'FFFF",
"line0": " CONNECT: OK ",
"outcome": "ok",
"patches": [
"byte:H'F9B9=0x00",
"byte:H'F9B4=0x01",
"word:H'F970=0x0000",
"word:H'E000=0x8080",
"byte:H'F730=0x00"
],
"pc": "H'2806",
"steps": 37121,
"stopped_reason": "stop_pc",
"unsupported": null
}
],
"kind": "h8536_emulator_state_search",
"preset": "connect-queue",
"result_count": 16,
"results": [
{
"case_index": 0,
"display": " CONNECT:NOT ACT | | | ",
"e000": "0x0080",
"f730": "0x00",
"f9b4": "0x01",
"f9b9": "0x01",
"final_pc": "H'2D37",
"line0": " CONNECT:NOT ACT",
"outcome": "not-act",
"patches": [
"byte:H'F9B9=0x00",
"byte:H'F9B4=0x01",
"word:H'F970=0x0000",
"word:H'E000=0x0000",
"byte:H'F730=0x00"
],
"pc": "H'2806",
"steps": 5109,
"stopped_reason": "unsupported_instruction",
"unsupported": "unsupported instruction at H'2D37: 6E C6 MOV:L.W @H'00C6, R6"
},
{
"case_index": 1,
"display": " CONNECT:NOT ACT | | | ",
"e000": "0x0080",
"f730": "0x00",
"f9b4": "0x01",
"f9b9": "0x01",
"final_pc": "H'2D37",
"line0": " CONNECT:NOT ACT",
"outcome": "not-act",
"patches": [
"byte:H'F9B9=0x00",
"byte:H'F9B4=0x01",
"word:H'F970=0x0000",
"word:H'E000=0x0000",
"byte:H'F730=0x01"
],
"pc": "H'2806",
"steps": 5109,
"stopped_reason": "unsupported_instruction",
"unsupported": "unsupported instruction at H'2D37: 6E C6 MOV:L.W @H'00C6, R6"
},
{
"case_index": 2,
"display": " CONNECT:NOT ACT | | | ",
"e000": "0x0080",
"f730": "0x00",
"f9b4": "0x01",
"f9b9": "0x01",
"final_pc": "H'2D37",
"line0": " CONNECT:NOT ACT",
"outcome": "not-act",
"patches": [
"byte:H'F9B9=0x00",
"byte:H'F9B4=0x01",
"word:H'F970=0x0000",
"word:H'E000=0x0000",
"byte:H'F730=0x41"
],
"pc": "H'2806",
"steps": 5109,
"stopped_reason": "unsupported_instruction",
"unsupported": "unsupported instruction at H'2D37: 6E C6 MOV:L.W @H'00C6, R6"
},
{
"case_index": 3,
"display": " CONNECT:NOT ACT | | | ",
"e000": "0x0080",
"f730": "0x00",
"f9b4": "0x01",
"f9b9": "0x01",
"final_pc": "H'2D37",
"line0": " CONNECT:NOT ACT",
"outcome": "not-act",
"patches": [
"byte:H'F9B9=0x00",
"byte:H'F9B4=0x01",
"word:H'F970=0x0000",
"word:H'E000=0x0000",
"byte:H'F730=0x81"
],
"pc": "H'2806",
"steps": 5109,
"stopped_reason": "unsupported_instruction",
"unsupported": "unsupported instruction at H'2D37: 6E C6 MOV:L.W @H'00C6, R6"
},
{
"case_index": 4,
"display": " CONNECT:NOT ACT | | | ",
"e000": "0x0080",
"f730": "0x00",
"f9b4": "0x01",
"f9b9": "0x01",
"final_pc": "H'2D37",
"line0": " CONNECT:NOT ACT",
"outcome": "not-act",
"patches": [
"byte:H'F9B9=0x00",
"byte:H'F9B4=0x01",
"word:H'F970=0x0000",
"word:H'E000=0x0000",
"byte:H'F730=0xC1"
],
"pc": "H'2806",
"steps": 5109,
"stopped_reason": "unsupported_instruction",
"unsupported": "unsupported instruction at H'2D37: 6E C6 MOV:L.W @H'00C6, R6"
},
{
"case_index": 5,
"display": " CONNECT:NOT ACT | | | ",
"e000": "0x0080",
"f730": "0x00",
"f9b4": "0x01",
"f9b9": "0x01",
"final_pc": "H'2D37",
"line0": " CONNECT:NOT ACT",
"outcome": "not-act",
"patches": [
"byte:H'F9B9=0x00",
"byte:H'F9B4=0x01",
"word:H'F970=0x0000",
"word:H'E000=0x0080",
"byte:H'F730=0x00"
],
"pc": "H'2806",
"steps": 5109,
"stopped_reason": "unsupported_instruction",
"unsupported": "unsupported instruction at H'2D37: 6E C6 MOV:L.W @H'00C6, R6"
},
{
"case_index": 6,
"display": " CONNECT:NOT ACT | | | ",
"e000": "0x0080",
"f730": "0x00",
"f9b4": "0x01",
"f9b9": "0x01",
"final_pc": "H'2D37",
"line0": " CONNECT:NOT ACT",
"outcome": "not-act",
"patches": [
"byte:H'F9B9=0x00",
"byte:H'F9B4=0x01",
"word:H'F970=0x0000",
"word:H'E000=0x0080",
"byte:H'F730=0x01"
],
"pc": "H'2806",
"steps": 5109,
"stopped_reason": "unsupported_instruction",
"unsupported": "unsupported instruction at H'2D37: 6E C6 MOV:L.W @H'00C6, R6"
},
{
"case_index": 7,
"display": " CONNECT:NOT ACT | | | ",
"e000": "0x0080",
"f730": "0x00",
"f9b4": "0x01",
"f9b9": "0x01",
"final_pc": "H'2D37",
"line0": " CONNECT:NOT ACT",
"outcome": "not-act",
"patches": [
"byte:H'F9B9=0x00",
"byte:H'F9B4=0x01",
"word:H'F970=0x0000",
"word:H'E000=0x0080",
"byte:H'F730=0x41"
],
"pc": "H'2806",
"steps": 5109,
"stopped_reason": "unsupported_instruction",
"unsupported": "unsupported instruction at H'2D37: 6E C6 MOV:L.W @H'00C6, R6"
},
{
"case_index": 8,
"display": " CONNECT:NOT ACT | | | ",
"e000": "0x0080",
"f730": "0x00",
"f9b4": "0x01",
"f9b9": "0x01",
"final_pc": "H'2D37",
"line0": " CONNECT:NOT ACT",
"outcome": "not-act",
"patches": [
"byte:H'F9B9=0x00",
"byte:H'F9B4=0x01",
"word:H'F970=0x0000",
"word:H'E000=0x0080",
"byte:H'F730=0x81"
],
"pc": "H'2806",
"steps": 5109,
"stopped_reason": "unsupported_instruction",
"unsupported": "unsupported instruction at H'2D37: 6E C6 MOV:L.W @H'00C6, R6"
},
{
"case_index": 9,
"display": " CONNECT:NOT ACT | | | ",
"e000": "0x0080",
"f730": "0x00",
"f9b4": "0x01",
"f9b9": "0x01",
"final_pc": "H'2D37",
"line0": " CONNECT:NOT ACT",
"outcome": "not-act",
"patches": [
"byte:H'F9B9=0x00",
"byte:H'F9B4=0x01",
"word:H'F970=0x0000",
"word:H'E000=0x0080",
"byte:H'F730=0xC1"
],
"pc": "H'2806",
"steps": 5109,
"stopped_reason": "unsupported_instruction",
"unsupported": "unsupported instruction at H'2D37: 6E C6 MOV:L.W @H'00C6, R6"
},
{
"case_index": 10,
"display": " CONNECT:NOT ACT | | | ",
"e000": "0x4080",
"f730": "0x00",
"f9b4": "0x01",
"f9b9": "0x01",
"final_pc": "H'A9E8",
"line0": " CONNECT:NOT ACT",
"outcome": "not-act",
"patches": [
"byte:H'F9B9=0x00",
"byte:H'F9B4=0x01",
"word:H'F970=0x0000",
"word:H'E000=0x4080",
"byte:H'F730=0x00"
],
"pc": "H'2806",
"steps": 5366,
"stopped_reason": "unsupported_instruction",
"unsupported": "unsupported instruction at H'A9E8: 7E 58 MOV:S.W R6, @H'0058"
},
{
"case_index": 11,
"display": " CONNECT:NOT ACT | | | ",
"e000": "0x4080",
"f730": "0x01",
"f9b4": "0x01",
"f9b9": "0x01",
"final_pc": "H'A9E8",
"line0": " CONNECT:NOT ACT",
"outcome": "not-act",
"patches": [
"byte:H'F9B9=0x00",
"byte:H'F9B4=0x01",
"word:H'F970=0x0000",
"word:H'E000=0x4080",
"byte:H'F730=0x01"
],
"pc": "H'2806",
"steps": 5366,
"stopped_reason": "unsupported_instruction",
"unsupported": "unsupported instruction at H'A9E8: 7E 58 MOV:S.W R6, @H'0058"
},
{
"case_index": 12,
"display": " CONNECT:NOT ACT | | | ",
"e000": "0x4080",
"f730": "0x41",
"f9b4": "0x01",
"f9b9": "0x01",
"final_pc": "H'FFFF",
"line0": " CONNECT:NOT ACT",
"outcome": "not-act",
"patches": [
"byte:H'F9B9=0x00",
"byte:H'F9B4=0x01",
"word:H'F970=0x0000",
"word:H'E000=0x4080",
"byte:H'F730=0x41"
],
"pc": "H'2806",
"steps": 45,
"stopped_reason": "stop_pc",
"unsupported": null
},
{
"case_index": 13,
"display": " CONNECT:NOT ACT | | | ",
"e000": "0x4080",
"f730": "0x81",
"f9b4": "0x01",
"f9b9": "0x01",
"final_pc": "H'A9E8",
"line0": " CONNECT:NOT ACT",
"outcome": "not-act",
"patches": [
"byte:H'F9B9=0x00",
"byte:H'F9B4=0x01",
"word:H'F970=0x0000",
"word:H'E000=0x4080",
"byte:H'F730=0x81"
],
"pc": "H'2806",
"steps": 5366,
"stopped_reason": "unsupported_instruction",
"unsupported": "unsupported instruction at H'A9E8: 7E 58 MOV:S.W R6, @H'0058"
},
{
"case_index": 14,
"display": " CONNECT:NOT ACT | | | ",
"e000": "0x4080",
"f730": "0xC1",
"f9b4": "0x01",
"f9b9": "0x01",
"final_pc": "H'FFFF",
"line0": " CONNECT:NOT ACT",
"outcome": "not-act",
"patches": [
"byte:H'F9B9=0x00",
"byte:H'F9B4=0x01",
"word:H'F970=0x0000",
"word:H'E000=0x4080",
"byte:H'F730=0xC1"
],
"pc": "H'2806",
"steps": 45,
"stopped_reason": "stop_pc",
"unsupported": null
},
{
"case_index": 15,
"display": " CONNECT: OK | | | ",
"e000": "0x8080",
"f730": "0x81",
"f9b4": "0x01",
"f9b9": "0x01",
"final_pc": "H'FFFF",
"line0": " CONNECT: OK ",
"outcome": "ok",
"patches": [
"byte:H'F9B9=0x00",
"byte:H'F9B4=0x01",
"word:H'F970=0x0000",
"word:H'E000=0x8080",
"byte:H'F730=0x00"
],
"pc": "H'2806",
"steps": 37121,
"stopped_reason": "stop_pc",
"unsupported": null
}
],
"target": "ok"
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,218 @@
H8/536 SCI1 RX Branch Trace
Summary: 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.
Confidence: high
Frame Model:
- capture buffer: H'F868-H'F86D
- validation buffer: H'F860-H'F865
- command: RX[0] & 0x07
- logical index candidate: loc_622B(RX[1], RX[2])
- value candidate: RX[3:4]
- checksum: 0x5A XOR RX[0..4] == RX[5]
Selector Decode:
- loc_622B logical selector decode: present
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.
- page 0, or pages 4-7, and low <= 0x7F: selector = 0x000 + low [H'6234, H'6236, H'6244, H'6248, H'6264]
- page 1 and low <= 0xFF: selector = 0x080 + low [H'6238, H'623A, H'624D, H'6251, H'6264]
- page 2 and low <= 0x7F: selector = 0x180 + low [H'623C, H'623E, H'6256, H'625A, H'6264]
- page 3, page/range failure, or page 0/4-7 with low > 0x7F: selector forced to 0x01FF [H'6240, H'6242, H'625F, H'6261]
- implication: RX[1].7 is not part of the selector here because the dispatcher rejects byte1 bit7 before command handling.
- implication: Commands shaped as 01 80 xx ... are rejected before loc_622B-derived command handling even if the low byte looks useful.
- implication: Page 4-7 encodings appear to alias the page-0 decode path unless the low byte is out of range.
Stages:
- SCI1 RXI/ERI byte capture: present
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.
- ERI taken: set FAA4.7, clear ORER/FER/PER, then fall into RXI byte capture [H'BB57, H'BB5B, H'BB5F, H'BB63]
- F9C1 == 0 before byte: clear F9C3 so the byte starts a fresh frame [H'BB71, H'BB75, H'BB77]
- F9C1 != 0 and F9C3 <= 5: append byte at F868 + F9C3 and increment F9C3 [H'BB7D, H'BB82, H'BB8A, H'BB90, H'BB96]
- F9C1 != 0 and F9C3 > 5: clear FAA4 and skip storing this byte [H'BB7D, H'BB82, H'BB84, H'BB88]
- incremented F9C3 == 6: load F9C5 with 0x14 as the RX/session timeout window [H'BB9A, H'BB9C, H'BB9E]
- any RXI exit: reload F9C1 with 0x05 as the inter-byte timeout [H'BBA3]
- six-byte validation and checksum: present
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.
- F9C3 != 6: return without processing [H'BBAB, H'BBB0]
- FAA4.7 set after capture: enter retry/error path at BE29 [H'BBCF, H'BBD3]
- checksum mismatch: enter retry/error path at BE29 [H'BBD6, H'BBD8, H'BBDC, H'BBE0, H'BBE4, H'BBE8, H'BBEC, H'BBF0]
- checksum valid: clear FAA6, decode selector from RX[1:2] through loc_622B, and dispatch on RX[0] & 0x07 [H'BBF3, H'BBF7, H'BBFD, H'BC01, H'BC08, H'BC0C]
- FAA2 split dispatcher: present
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.
- FAA2 == 0: set FAA2.7 and test initial commands 0, 1, 2, 7 [H'BC0F, H'BC13, H'BC15, H'BC20, H'BC24, H'BC29, H'BC2E]
- FAA2 != 0 and command bit2 set: continuation commands 4, 5, 6, 7 are possible [H'BC0F, H'BC13, H'BC3A, H'BC45, H'BC4A, H'BC4F, H'BC54]
- FAA2 != 0 and command bit2 clear: BCLR FAA2.3; if that bit was set, clear FAA3 and re-enter initial dispatcher [H'BC3A, H'BC3C, H'BC5C, H'BC60, H'BC63, H'BC67]
- byte1 bit7 set on initial path: branch to BD0B and return without normal command handling [H'BC19, H'BC1D, H'BD0B]
- byte1 bit7 set on continuation path: branch to BE27 and return without normal command handling [H'BC3E, H'BC42, H'BE27]
- checksum/error retry path: present
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].
- FAA5.7 == 0: return after clearing FAA4.7; retry echo is disabled [H'BE29, H'BE2D, H'BE31]
- FAA5.7 == 1 and FAA6 < 2: stage F850=0x07 and F851-F854=RX[1:4], then call BA26 [H'BE33, H'BE37, H'BE3C, H'BE4D, H'BE52, H'BE5A, H'BE62, H'BE6A]
- FAA5.7 == 1 and FAA6 >= 2: load F9C0=0x1F and clear FAA3/FAA2 [H'BE37, H'BE3C, H'BE3E, H'BE43, H'BE47]
- pending selector ring at loc_BE70: present
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.
- selector already present: exit without appending [H'BE84, H'BE88, H'BE9D]
- ring scan reaches F9B4 cursor: store R5 into the pending ring and advance F9B4 [H'BE80, H'BE82, H'BE91, H'BE95, H'BE99]
- session timeout and resend side paths: present
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.
- F9C5 == 0 at loc_3FEF: clear F9B5/F9B0 and clear FAA5.7; if FAA5.7 was set, call 400C reset/NOT-ACT state clear [H'3FEF, H'3FF3, H'3FF5, H'3FF9, H'3FFD, H'4001, H'4003]
- F9C5 != 0 at loc_3FEF: set FAA5.7, allowing retry/resend/session-gated paths [H'3FEF, H'3FF3, H'4007]
- BE9E sees no pending FAA5 & FAA3 & 0x80: clear FAA2 and return [H'BE9E, H'BEA5, H'BEA9, H'BEAD, H'BEAF]
- BE9E pending and F9C6==0 and F9C8!=0: decrement F9C8, reload F9C6, and possibly resend staged TX through BA26 [H'BEB5, H'BEBB, H'BEC1, H'BEC5, H'BECB, H'BED1, H'BED5]
- BE9E pending but F9C8==0: clear F9C5, which lets 3FEF collapse the session gate later [H'BEBB, H'BEBF, H'BEE4]
Command Branches:
- cmd 0x00 set_value_acked_candidate: initial path only: checksum valid, FAA2 == 0, RX[1].7 == 0; handler H'BC69; writes RX[3:4] into primary/current tables, flags the selector, calls BE70, and sends an echo-style 0x04 response
response: F850=0x04; F851-F854 mostly echo RX[1:4]; BA26 sends it
- 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
- cmd 0x01 read_value_candidate: initial path only: checksum valid, FAA2 == 0, RX[1].7 == 0; handler H'BCD7; reads primary table E000 + 2*selector and stages a 0x04 response
response: F850=0x04; F851 is overwritten with RX[2]; F853/F854 receive table high/low; F852 is not freshly written here
- does not enter continuation command handling
- clears FAA2.7 before exit
- cmd 0x02 initial_clear_or_noop_candidate: initial path only: checksum valid, FAA2 == 0, RX[1].7 == 0; handler H'BD04; clears FAA2.7 and returns without staging a response
response: no immediate serial response
- likely a quiet/session-clear style command on the initial path
- cmd 0x04 continuation_set_value_candidate: continuation path only: checksum valid, FAA2 != 0, command bit2 set, RX[1].7 == 0; handler H'BD0E; writes a value into the primary table without an immediate serial response; selector zero also updates the current/report table
response: no immediate serial response
- 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
- cmd 0x05 continuation_ack_or_clear_pending_candidate: continuation path only: checksum valid, FAA2 != 0, command bit2 set, RX[1].7 == 0; handler H'BD80; ACK/session-clear path; usually no response, but selected logical indexes feed BE70 or clear connection latches
response: no immediate serial response
- 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
- cmd 0x06 continuation_set_secondary_candidate: continuation path only: checksum valid, FAA2 != 0, command bit2 set, RX[1].7 == 0; handler H'BDDB; writes RX[3:4] into the secondary table and sets flag-table bit 6
response: no immediate serial response
- if FAA2.3 was set from a queued report, advances F9B5
- clears FAA3 and FAA2 before exit
- cmd 0x07 retransmit_previous_tx_candidate: initial or continuation path; handler H'BE05; copies the previous finalized TX frame bytes back into staging and sends them again
response: previous TX frame retransmitted through BA26
- loads F9C0 with 0x1F before sending
Table Surfaces:
- primary_value_table H'E000-H'E3FF: present; logical selector word table; command 0 and continuation command 4 write it, command 1 reads it [H'BC75, H'BC95, H'BCEC, H'BD1A, H'BD35]
- 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
- current_report_value_table H'E800-H'EBFF: present; current/report value table used when queued serial reports are converted into TX frames [H'BC79, H'BC99, H'BD1E, H'BB35, H'BB39, H'BB3F]
- 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
- secondary_value_table H'E400-H'E7FF: present; secondary logical selector word table written by continuation command 6 [H'BDE5, H'BDE9]
- command 6 writes RX[3:4] to E400 + 2*selector
- the matching EC00 flag bit is bit6 rather than bit7
- dirty_flag_table H'EC00-H'EDFF: present; per-selector flag bytes; command 0/4 set bit7 and command 6 sets bit6 [H'BC82, H'BC9D, H'BD22, H'BD39, H'BDE9]
- 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
- mapped_shadow_or_eeprom_surface H'F400-H'F4FF: present; optional mapped mirror/persistence surface selected through ROM tables around C564/C565 [H'BCA1, H'BCA9, H'BD3D, H'BD45, H'BD49, H'BD5F]
- 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
Downstream Flow Traces:
- immediate response staging through loc_BA26: present
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.
- stage command-0 echo: F850=0x04 and F851-F854 mirror the accepted host fields before BA26 [H'BCB0, H'BCB5, H'BCC1, H'BCC9, H'BCCD]
- stage command-1 readback: F850=0x04, F853/F854 receive the E000 table word, and BA26 sends it [H'BCD7, H'BCEC, H'BCF0, H'BCF6, H'BCFA]
- finalize TX frame: BA26 copies F850-F854 to F858-F85C and computes F85D as 0x5A XOR bytes 0-4 [H'BA36, H'BA3A, H'BA42, H'BA4A, H'BA4E, H'BA64]
- start SCI1 transmission: BA26 waits for TDRE, writes F858 to SCI1_TDR, sets F9C2=1, clears TDRE, and enables TIE [H'BA68, H'BA72, H'BA76, H'BA7B, H'BA7F]
- finish SCI1 transmission: TXI indexes F858+F9C2 until six bytes are sent, then disables TIE [H'BAAB, H'BAB1, H'BAB5, H'BABF, H'BAC3, H'BACA]
- selector-processing queue BE70/F970 into loc_2806: present
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.
- append unique selector: BE70 scans from F9B9 to F9B4, skips duplicates, writes R5 to F970+2*cursor, and advances F9B4 [H'BE70, H'BE78, H'BE84, H'BE91, H'BE95, H'BE99]
- consume selector: loc_2806 reads F970+2*F9B9, advances F9B9, masks the selector to 0x01FF, and keeps it in R5 [H'2806, H'280C, H'2819, H'281D, H'2822, H'2826, H'282A]
- active-selector side path: selectors matching F736/F738/F73A/F73C/F73E/F740/F742/F754 call loc_48FA before the jump table [H'2837, H'285E, H'2878, H'2892, H'2CAB, H'2CAD]
- selector jump table: the consumer jumps through table 28A6; selector zero is emulator-correlated with the CONNECT handler window [H'289F, H'28A3]
- serial-report queue loc_3E54/F870 into loc_BAF2: present
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.
- enqueue serial report: when R2.7 is set, loc_3E54 deduplicates R3 in F870 and advances F9B0 [H'3E54, H'3E58, H'3E6C, H'3E76, H'3E7A, H'3E7E]
- queue backpressure drain: if the serial queue is nearly full, loc_3E54 calls loc_3FD3 until there is space [H'3E82, H'3E8B, H'3E91, H'3E93]
- enqueue selector processing: when R2.6 is set, loc_3E54 deduplicates R3 in F970 and advances F9B4 [H'3E9A, H'3E9E, H'3EB2, H'3EBF, H'3EC3, H'3EC7]
- dequeue serial report: loc_BAF2 compares F9B5/F9B0, reads F870+2*F9B5, builds a TX report from E800, and calls BA26 [H'BAF2, H'BAF8, H'BB00, H'BB08, H'BB1C, H'BB35, H'BB43]
- open continuation latch: 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 [H'BB00, H'BB46, H'BB4C, H'BB51]
- TXI/RXI race and continuation collapse: present
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.
- detect overlap: TXI tests FAA2.3, FAA5.7, and nonzero F9C3 before continuing the TX frame [H'BA84, H'BA8A, H'BA90]
- collapse continuation: on overlap it clears FAA2.3 and FAA3, disables TIE, and loads F9C0=0x1F [H'BA96, H'BA9A, H'BA9E, H'BAA2]
- normal completion path: without the overlap, TXI sends bytes until F9C2 reaches six and then starts the post-TX delay path [H'BAA9, H'BAB5, H'BAC3, H'BACA, H'BADA, H'BAED]
- session expiry into reset/not-active state: present
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.
- expire RX session: F9C5==0 clears F9B5/F9B0 and clears FAA5.7 [H'3FEF, H'3FF5, H'3FF9, H'3FFD]
- call reset side path: if clearing FAA5.7 changed the bit, loc_3FEF calls loc_400C [H'4001, H'4003]
- clear connection state: loc_400C clears F730/F756-F759/F732/F75C/FB03/F791/F795/F76E and calls follow-on display/session refresh routines [H'400C, H'4010, H'4020, H'4028, H'4034, H'403C, H'4040, H'4042]
RX-to-TX Feedback Loops:
- command-0 write echo and selector-processing loop: present
trigger: valid command 0 while FAA2 == 0
path: RX validation -> BC69 table write -> BE70 appends selector to F970 -> BCB0/BA26 sends immediate 0x04 echo -> later loc_2806 consumes F970
TX outcome: immediate command-4-style echo frame plus possible later selector-driven reports/display work
timing/gate: BA26 sets F9C0=0x64 and F9C4=0x07, temporarily delaying queued TX and heartbeat enqueue
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: H'BC69, H'BC75, H'BC86, H'BCB0, H'BCCD, H'BA2C, H'BA31, H'BE70, H'2819, H'28A3
- command-1 readback and previous-frame loop: present
trigger: valid command 1 while FAA2 == 0, followed by optional command 7
path: RX validation -> BCD7 reads E000[selector] -> BA26 finalizes TX in F858-F85D -> BE05 can copy F858-F85C back to F850-F854
TX outcome: direct 0x04 readback, then command 7 can retransmit the exact last finalized TX frame
timing/gate: command 1 clears FAA2.7 and never enters continuation handling; it is a readback path, not an ACK path
bench read: command 7 after command 1 proves what was last finalized, but does not prove a hidden continuation token by itself
evidence: H'BCD7, H'BCEC, H'BCFA, H'BA36, H'BA64, H'BE05, H'BE09, H'BE22
- retry/error 07 echo loop: present
trigger: physical RX error or checksum mismatch while FAA5.7 is set and retry count FAA6 is below two
path: RX validation error -> BE29 retry gate -> BE4D stages F850=0x07 and copies RX[1:4] into F851-F854 -> BA26 sends
TX outcome: a 0x07 frame that can echo the host payload bytes, independent of E000/E800 table contents
timing/gate: after two retries, the ROM loads F9C0=0x1F and clears FAA3/FAA2 instead of sending another echo
bench read: visible 07 frames in a noisy/tight timing run can be retry echoes, not necessarily device status or a continuation token
evidence: H'BE29, H'BE2D, H'BE33, H'BE37, H'BE3E, H'BE43, H'BE47, H'BE4D, H'BE6A
- autonomous report to host continuation loop: present
trigger: firmware enqueues a serial-visible report via loc_3E54 with R2.7 set
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
TX outcome: autonomous 6-byte report frame built from E800[selector], with FAA2.3/FAA3.7 left set to await host continuation or ACK
timing/gate: F9C0 must count down before BAF2 can send, and F9C6/F9C8/BE9E control repeated sends while FAA3.7 remains live
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: 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
- selector-processing to report loop: present
trigger: command 0/4/selected command 5 calls BE70, or loc_3E54 is called with R2.6 set
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
TX outcome: possible later serial report produced through the F870/BAF2 loop rather than an immediate response to the original RX frame
timing/gate: loc_48FA is gated by FB03.7, F732 values, E1EC.13, and F76E.6 before reaching its indirect table
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: H'BE70, H'BE91, H'2806, H'2819, H'2CAD, H'48FA, H'490F, H'4921, H'4923, H'4926
- TXI/RXI overlap cancellation loop: present
trigger: host RX bytes begin while a report TX is active, FAA2.3 is set, and FAA5.7 is set
path: TXI observes FAA2.3 + FAA5.7 + F9C3 != 0 -> clears FAA2.3/FAA3 -> disables TIE -> loads F9C0=0x1F
TX outcome: the pending report/continuation state can be canceled before the host command reaches the continuation dispatcher
timing/gate: this depends on byte timing relative to TXI and F9C3, so polite emulator injection can miss it
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: H'BA84, H'BA8A, H'BA90, H'BA96, H'BA9A, H'BA9E, H'BAA2
- session-expiry to heartbeat/not-active loop: present
trigger: any complete six-byte RX frame loads F9C5, then FRT2 decrements it to zero
path: RX complete -> F9C5=0x14 -> FRT2 decrements F9C5 -> loc_3FEF clears session/queues and calls 400C -> loc_4046 can later enqueue heartbeat selector 0
TX outcome: eventual return to idle heartbeat/report behavior and inactive-session display state
timing/gate: F9C4 gates heartbeat enqueue; BA26 reloads it to 0x07 after each send, matching the roughly 700 ms heartbeat cadence
bench read: the common CONNECT NOT ACT after arbitrary six-byte traffic is consistent with this expiry/reset loop
evidence: H'BB9E, H'BF31, H'BF37, H'3FEF, H'3FFD, H'4003, H'400C, H'4046, H'4067, H'BA31
State Bits:
- H'FAA2.7: rx_command_in_progress_candidate - set on initial-path parse; cleared by command 0/1/2 exits or by continuation cleanup
- H'FAA2.3: queued_report_ack_needed_candidate - set by the autonomous queue send path at BB00; continuation command 4/5/6 can advance F9B5 only when this bit was set
- H'FAA3.7: pending_resend_mask_candidate - set after queued report send; BE9E masks it with FAA5.7 before resend/clear decisions
- H'FAA4.7: rx_physical_error_latch_candidate - set by SCI1 ERI and tested before checksum dispatch
- H'FAA5.7: rx_session_gate_candidate - set while F9C5 is alive after a complete RX frame; gates retry/resend and heartbeat/report enqueue behavior
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.