# PT2 Session Rhythm ROM Trace

This note tracks ROM evidence for the CCU/RCP "session rhythm": which received commands update selector state, which internal queues process those selectors, and which timers expire visible states back toward `CONNECT: NOT ACT`.

## RX Command Front Door

The serial command dispatcher reads `F860 & 0x07` at `H'BC08-H'BC0C`.

Dispatch is split by `FAA2`:

| Command | Dispatcher state | Handler | Main effect |
| --- | --- | --- | --- |
| `0` | initial/idle, `FAA2 == 0` | `H'BC69` | writes primary `E000` and current/report `E800`, sets `EC00` dirty bit 7, appends selector to `F970`, replies with command-4 style echo |
| `1` | initial/idle, `FAA2 == 0`, `F861.7 == 0` | `H'BCD7` | reads primary `E000` and replies |
| `2` | initial/idle, `FAA2 == 0` | `H'BD04` | clears `FAA2.7`, likely abort/clear |
| `4` | continuation, `FAA2 != 0` | `H'BD0E` | writes primary `E000`, sets `EC00` dirty bit 7, appends selector to `F970`; selector zero also writes `E800`; no immediate reply |
| `5` | continuation, `FAA2 != 0` | `H'BD80` | ACK/selector side-effect path; special selectors can append to `F970` or clear latches |
| `6` | continuation, `FAA2 != 0` | `H'BDDB` | writes secondary `E400`, sets `EC00` dirty bit 6; no immediate reply |
| `7` | both states | `H'BE05` | retransmits previous frame or emits retry/error echo |

Practical meaning:

- The normal active link is stateful. Commands `4/5/6` only do their intended work in the continuation side where `FAA2 != 0`.
- Command `0` is both a value update and a continuation opener because it sets `FAA2.7`, writes tables, appends the selector to `F970`, and emits a reply.
- Command `4` is not identical to command `0`: for nonzero selectors it updates `E000` but does not directly update `E800` in this handler. That matters because autonomous reports read values from `E800`.
- Command `6` does not directly display anything. It changes the secondary feature/visibility table consumed later by local page code such as `5FD2`.

## Serial Session Timeout

The broad CCU-traffic watchdog is `F9C5`.

RXI frame capture path:

- `H'BB90-H'BB96` stores received bytes into `F868-F86D` and increments `F9C3`.
- When `F9C3 == 6`, `H'BB9E` loads `F9C5=0x14`.
- Main-loop handler `H'BBAB` only validates/dispatches a frame once `F9C3 == 6`.

FRT2 OCIA timer path:

- `H'BF31-H'BF37` decrements `F9C5` when nonzero.
- `H'3FEF` observes `F9C5`; once it is zero, the main loop can clear `F9B5/F9B0`, clear `FAA5.7`, then call `H'400C`.
- `H'400C` clears the broad session/display state and calls `H'4217`, which redraws `CONNECT:NOT ACT`.

Practical meaning:

- Any complete six-byte RX frame refreshes the short serial-session watchdog, independent of whether it ultimately produces the desired command-side effect.
- This is probably the main `CONNECT: OK -> CONNECT:NOT ACT` timer when CCU-like traffic stops.
- Separate display overlays still use `FB02`, so a page can expire even while serial traffic is otherwise alive.

## Selector Queue

`H'BE70` appends selectors to the processing queue at `F970`. `H'3E54` can also append to this queue when its mode byte has `R2.6` set.

Important queue RAM:

| RAM | Role |
| --- | --- |
| `F970` | selector-processing ring |
| `F9B4` | queue write cursor |
| `F9B9` | queue read cursor |

Queue processing happens at `H'2806` during the main loop:

1. If `F9B9 == F9B4`, no selector is pending.
2. Otherwise it reads the next selector from `F970`, increments `F9B9`, and masks the selector to `0x01FF`.
3. If the selector matches any active display slot (`F736/F738/F73A/F73C/F73E/F740/F742/F754`), it calls `H'48FA` before the selector-specific dispatch.
4. It then jumps through the selector handler table at `H'28A6`.

This explains why the same incoming selector can either look inert or redraw the LCD: the selector must match the current active display/page slots before `48FA` is called from the queue bridge.

## Autonomous Report Queue

The report queue is separate from the selector-processing queue.

| RAM | Role |
| --- | --- |
| `F870` | autonomous outbound report queue |
| `F9B0` | report producer cursor |
| `F9B5` | report consumer cursor |

Important report path:

- `H'3E54` appends report selectors to `F870` when its mode byte has `R2.7` set.
- `H'3FD3` sends reports only when `FAA2 == 0`, `F9C0 == 0`, and if `FAA5.7` is set then `F9C3 == 0`.
- `H'BAF2` drains `F870`, reads the report value from `E800 + 2*selector`, stages a six-byte TX frame, and sends it through `H'BA26`.
- `H'BB00` sets `FAA2.3` when a queued report is sent.
- After a report send, the ROM creates a continuation window with `F9C6=0x01F4`, `F9C8=0x14`, and `FAA3=0x80`.
- Continuation commands `4`, `5`, or `6` advance `F9B5` when `FAA2.3` was set, then clear `FAA3/FAA2`.

Practical meaning:

- A fake CCU probably needs to consume autonomous reports, not only stream status words.
- If a report is sent and the CCU does not answer during the continuation window, the RCP can repeat, retry, or let the broader session gates decay.
- Because report values come from `E800`, command `0` and local RCP report handlers are stronger report-value refreshes than nonzero command `4` writes.

## TX / Heartbeat Timing Gates

`H'BA26` is the common TX-finalize helper.

Observed reloads:

- `BA26` sets `F9C0=0x64` and `F9C4=0x07` after send finalization.
- TX completion later sets `F9C0=0x09`, or `F9C0=0xF0` when `F795.6` is set.
- The FRT2 path decrements `F9C4`; `H'4046` can enqueue heartbeat/report selector `0x0000` when the queue is empty and the gate is open.

Practical meaning:

- The roughly 700 ms heartbeat cadence is the `F9C4=0x07` post-send countdown with the current FRT2 tick model.
- COPY state can slow or alter TX pacing through `F795.6 -> F9C0=0xF0`.

## Display Restore Timer

`FB03.7` marks a temporary/timed display override. `FB02` is its countdown.

Writers that start timed display overrides:

| Address | State written | Visible candidate |
| --- | --- | --- |
| `H'1726` | `F732=0x1C07`, `FB02=0x14`, `FB03.7=1` | DETAIL/KNEE-style timed page |
| `H'176E` | `F732=0x1C06`, `FB02=0x14`, `FB03.7=1` | DETAIL/KNEE-style timed page |
| `H'2135` | `F732=0x1C03`, `FB02=0x14`, `FB03.7=1` | KNEE page seen in bench probes |
| `H'26F6` | `F732=0x1C01`, `FB02=0x14`, `FB03.7=1` | adjacent local menu overlay |
| `H'3004` | `F732=0x1904`, `FB02=0x14`, `FB03.7=1` | `COPY COMPLETED` |
| `H'3038` | `F732=0x1903`, `FB02=0x64`, `FB03.7=1` | `COPY IN PROGRESS` |
| `H'7092` | `FB03.7=1`, `FB02=0x14` | `SET RCP` / `MASTER` fallback from local COPY gate |

FRT2 OCIA timer path `H'BF50-H'BF6B`:

- If `FB03.7` is clear, nothing happens.
- If `FB02 != 0`, the timer decrements `FB02`.
- If `FB02 == 0`, it clears `FB03.7` and calls `H'48EF`.
- `H'48EF` restores `F732` from `F734`, then calls `H'48FA`.

Practical meaning:

- Many visible pages are deliberate timed overlays, not durable states.
- A scenario can appear to "drop to NOT ACT" simply because the overlay expires and restores the saved page.

## COPY / Activity Latch Timers

COPY-related selectors are handled through command 5 and the `F970` selector queue:

| Selector | Handler | Timer/latch effect |
| --- | --- | --- |
| `0x006C` | `H'2FAF` | completion/exit sibling; can clear `F731.7`, load `F797=0x1E` or `0x14`, and display `COPY COMPLETED` |
| `0x006D` | `H'3015` | start/progress; sets `F731.7`, `F795.6`, `F795.7`, `F798=0xC8`, displays `COPY IN PROGRESS` |
| `0x006E` | via command-5 special path | appended to `F970`; exact selector handler still needs labeling |

FRT2 OCIA timeout path:

- `H'BFA3-H'BFAF`: if `F797` is nonzero, decrement it; when it reaches zero, clear `F731.7`.
- `H'BFB3-H'BFBF`: if `F798` is nonzero, decrement it; when it reaches zero, clear `F731.7`.

Practical meaning:

- `F731.7` is an activity/copy/session latch with explicit timeout clear paths.
- `0x006D` refreshes the long progress window (`F798=0xC8` and `FB02=0x64`).
- `0x006C` only makes sense as a completion/exit frame when the copy/progress flags are live.

## Reset / NOT ACT Baseline

`H'400C` clears broad session/display state:

- clears `F732`, `FB03`, `F791`, `F795`, `F76E`
- calls `H'4217`

`H'4217`:

- clears `F798`
- sets `F731.7`
- clears output masks and writes the LCD text `CONNECT:NOT ACT`

This looks like the firmware's explicit inactive-session baseline.

## Current Rhythm Hypothesis

The session rhythm is probably not one magic keepalive frame. The ROM suggests a loop with three layers:

1. **Any complete six-byte RX frame** refreshes the broad `F9C5` session watchdog.
2. **Command-0 primary selector updates** keep both `E000` and `E800` current, append active selectors to `F970`, and reply.
3. **Command-4 continuation primary updates** keep `E000` current and append selectors to `F970`, but only selector zero directly refreshes `E800`.
4. **Autonomous reports from `F870`** must be consumed by continuation commands so the report cursor advances.
5. **Command-6 secondary selector updates** advertise which features/menu entries are valid through `E400`.
6. **Command-5 ACK/special selectors** advance report windows and drive side-effect selectors such as `0x006C/0x006D`.

The panel stays active when enough selector updates hit the right active slots and refresh the timed/latch counters before FRT2 expires them.
