7.3 KiB
PT2 Report Aftermath ROM Trace
This note tracks what the ROM does after the RCP emits an autonomous serial report from the F870 report queue.
Core Model
The RCP report path is:
3E54 / 4046 enqueue selector into F870
3FD3 checks send gates
BAF2 dequeues/stages a report from F870 and E800
BA26 sends the six-byte SCI1 frame
BB46-BB51 arms the continuation/resend aftermath
The important consequence is that BAF2 does not advance the report consumer cursor. The emitted report remains outstanding until the host sends a valid continuation command.
Report Queue
| RAM | Role |
|---|---|
F870 |
autonomous serial-report word ring |
F9B0 |
producer cursor |
F9B5 |
consumer/outstanding cursor |
Producer paths:
H'3E54: whenR2.7is set, deduplicates and appendsR3toF870, then advancesF9B0.H'4046-H'4070: when heartbeat/report cadence expires and the report queue is empty, appends selector0x0000toF870.
Consumer path:
H'BAF2comparesF9B5againstF9B0.- If equal, no report is pending.
- If different, it reads selector
F870[ F9B5 ], reads the report value fromE800[selector], stages the outgoing frame, and callsBA26. BAF2leavesF9B5unchanged.
Only continuation command 4, 5, or 6 advances F9B5, and only when FAA2.3 is still set.
Report Send Gates
H'3FD3 allows BAF2 only when:
FAA2 == 0.F9C0 == 0.- If
FAA5.7is set,F9C3 == 0, meaning no partial RX frame is currently being assembled.
This means host RX traffic can block report sending while a session is active.
Aftermath Window
After BA26 sends the report frame, H'BB46-H'BB51 arms the report aftermath:
| Address | Write | Meaning |
|---|---|---|
H'BB00 |
set FAA2.3 |
queued report needs continuation |
H'BB46 |
F9C6 = 0x01F4 |
resend spacing countdown |
H'BB4C |
F9C8 = 0x14 |
resend/retry budget |
H'BB51 |
FAA3 = 0x80 |
live resend/window marker |
While this is live, valid RX frames enter the continuation dispatcher because FAA2 != 0.
Clean Continuation Consume
Commands 4, 5, and 6 all share the same report-consume pattern:
if FAA2.3 set:
F9B5 += 1
clear F9B5.7
clear FAA3
clear FAA2
Handler addresses:
| Command | Handler | Consume block |
|---|---|---|
4 |
H'BD0E |
H'BD67-H'BD79 |
5 |
H'BD80 |
H'BDC2-H'BDD4 |
6 |
H'BDDB |
H'BDED-H'BDFF |
The ROM does not appear to require the continuation ACK selector to match the emitted report selector. The consume test is FAA2.3, not selector equality.
Non-Clean Paths
Low commands 0/1/2/3 while FAA2.3 is live:
H'BC5CclearsFAA2.3.- If the bit was set,
H'BC63clearsFAA3. H'BC67re-enters initial dispatch.- This does not advance
F9B5.
Command 7:
- Retransmits the previous finalized TX frame through
H'BE05-H'BE25. - Does not clear
FAA2/FAA3. - Does not advance
F9B5.
TX/RX overlap interlock:
- At
H'BA84-H'BAA7, TXI checksFAA2.3 && FAA5.7 && F9C3 != 0. - If true, it clears
FAA2.3, clearsFAA3, disables TXI, and loadsF9C0=0x1F. - This collapses the report window without consuming
F9B5. - Bench implication: starting a host frame before the RCP has finished TX can destroy the very continuation window being targeted.
Resend And Expiry
H'BE9E-H'BEE8 manages the unconsumed report aftermath:
- Masks
FAA3withFAA5.7. - If the session gate is gone,
FAA3becomes zero andFAA2is cleared. - If
FAA3.7is live andF9C6 != 0, it waits. - If
F9C6 == 0andF9C8 != 0, it decrementsF9C8, reloadsF9C6=0x01F4, clearsF9C3, and callsBA26to resend the same finalized frame. - If
F9C8 == 0, it clearsF9C5, forcing the broader session timeout path.
So an unconsumed report can be resent repeatedly, then eventually force the session watchdog to expire.
Session Timeout
F9C5 is the broad active-session watchdog:
- A complete six-byte RX frame reloads
F9C5=0x14atH'BB9E. - FRT2 decrements
F9C5atH'BF31-H'BF37. H'3FEFobserves expiry, clearsF9B5/F9B0, clearsFAA5.7, and if the gate was previously live callsH'400C.H'400C -> H'4075 -> H'4217clears broad session/display state and redrawsCONNECT:NOT ACT.
Related timers:
| RAM | Role |
|---|---|
F9C0 |
post-TX/report-send gate; decremented by FRT1 |
F9C1 |
RX inter-byte timer; partial-frame timeout |
F9C4 |
heartbeat/report enqueue cadence |
F9C5 |
active serial-session watchdog |
F9C6/F9C8 |
unconsumed report resend spacing/budget |
Fake-CCU Implications
Best pure report ACK:
05 00 40 00 00 1F
Rationale:
- Command
5consumes the report cursor whenFAA2.3is live. - Selector
0x0040is not one of the known command-5 special side-effect selectors. - Value bytes are ignored by the generic command-5 consume path.
Same-selector command-5 ACKs are plausible for human readability, but not ROM-required:
05 00 00 00 00 5F ; ACK selector 0x0000
05 00 02 00 00 5D ; ACK selector 0x0002
05 00 07 00 00 58 ; ACK selector 0x0007
05 00 15 00 00 4A ; ACK selector 0x0015
05 01 0F 00 00 51 ; ACK selector 0x008F
Use command 4 only when the host intentionally wants to refresh primary/current state while consuming:
04 00 00 80 00 DE ; selector-zero active refresh
Use command 6 only when the host intentionally wants to refresh secondary feature gates while consuming:
06 00 15 00 01 48 ; E400[0x0015] = 1
06 01 0F 18 00 4A ; E400[0x008F] = 0x1800
Avoid command-5 special selectors as generic ACKs unless the side effect is desired:
05 00 6C 00 00 33 ; COPY completion/exit sibling
05 00 6D 00 00 32 ; COPY IN PROGRESS/start
05 00 6E 00 00 31 ; special accepted, later handler is cleanup/no-op-like
Proposed Normal Loop
A plausible fake-CCU report loop is:
- Keep the serial format at
38400 8E1. - Seed active state, especially selector zero.
- Listen for a complete RCP TX frame.
- Wait until the RCP frame is fully transmitted.
- Quickly send a command-5 generic ACK before
F9C6/F9C8resend handling starts. - Continue sending enough valid six-byte frames to reload
F9C5before session expiry. - Add command-4/command-6 state refreshes only when we intentionally want to update lamps, displays, or menu gates.
This is the current best ROM-supported path for maintaining CONNECT: OK without accidentally consuming the report incorrectly or triggering COPY/menu side effects.
Emulator Check
Reactive emulator testing supports this model:
- Seeded active state with command
0, selector zero value0x8080. - Waited for a report window where
FAA2.3andFAA3.7were set and SCI1 TXI was idle. - Sent
05 00 40 00 00 1F. - The ACK path reached the command-5 consume block and advanced
F9B5, then clearedFAA3andFAA2. - Repeating that reactive loop 12 times kept the emulated LCD at
CONNECT: OK.
Observed clean consume shape after each ACK:
before: FAA2=08 FAA3=80 F9B5=N
after: FAA2=00 FAA3=00 F9B5=N+1
A fixed-delay or extra-guard strategy was less reliable. In one run, waiting an additional 1 ms after TX idle before sending the ACK only consumed two reports before falling back to CONNECT:NOT ACT. That result should not be overfit as an exact real-device limit, but it reinforces the ROM timing lesson: ACK as a reaction to a finished frame, not as a loose periodic delay.