# 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.