1
0
Files
h8-536-decoder/docs/pt2-report-aftermath-trace.md
2026-05-27 11:50:10 +10:00

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: when R2.7 is set, deduplicates and appends R3 to F870, then advances F9B0.
  • H'4046-H'4070: when heartbeat/report cadence expires and the report queue is empty, appends selector 0x0000 to F870.

Consumer path:

  • H'BAF2 compares F9B5 against F9B0.
  • If equal, no report is pending.
  • If different, it reads selector F870[ F9B5 ], reads the report value from E800[selector], stages the outgoing frame, and calls BA26.
  • BAF2 leaves F9B5 unchanged.

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.7 is 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'BC5C clears FAA2.3.
  • If the bit was set, H'BC63 clears FAA3.
  • H'BC67 re-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 checks FAA2.3 && FAA5.7 && F9C3 != 0.
  • If true, it clears FAA2.3, clears FAA3, disables TXI, and loads F9C0=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 FAA3 with FAA5.7.
  • If the session gate is gone, FAA3 becomes zero and FAA2 is cleared.
  • If FAA3.7 is live and F9C6 != 0, it waits.
  • If F9C6 == 0 and F9C8 != 0, it decrements F9C8, reloads F9C6=0x01F4, clears F9C3, and calls BA26 to resend the same finalized frame.
  • If F9C8 == 0, it clears F9C5, 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=0x14 at H'BB9E.
  • FRT2 decrements F9C5 at H'BF31-H'BF37.
  • H'3FEF observes expiry, clears F9B5/F9B0, clears FAA5.7, and if the gate was previously live calls H'400C.
  • H'400C -> H'4075 -> H'4217 clears broad session/display state and redraws CONNECT: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 5 consumes the report cursor when FAA2.3 is live.
  • Selector 0x0040 is 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:

  1. Keep the serial format at 38400 8E1.
  2. Seed active state, especially selector zero.
  3. Listen for a complete RCP TX frame.
  4. Wait until the RCP frame is fully transmitted.
  5. Quickly send a command-5 generic ACK before F9C6/F9C8 resend handling starts.
  6. Continue sending enough valid six-byte frames to reload F9C5 before session expiry.
  7. 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 value 0x8080.
  • Waited for a report window where FAA2.3 and FAA3.7 were 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 cleared FAA3 and FAA2.
  • 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.