traces
This commit is contained in:
101
docs/pt2-button-report-bench-plan.md
Normal file
101
docs/pt2-button-report-bench-plan.md
Normal file
@@ -0,0 +1,101 @@
|
||||
# PT2 Button Report Bench Plan
|
||||
|
||||
Date: 2026-05-26
|
||||
|
||||
## Question
|
||||
|
||||
After the SHUTTER ON/OFF test exposed queued frames:
|
||||
|
||||
```text
|
||||
02 01 0F 80 00 D6
|
||||
01 01 0F 80 00 D5
|
||||
```
|
||||
|
||||
the next bench question is whether other buttons share the same common queue-service gate, or whether each button/selector needs its own feature gate.
|
||||
|
||||
## Current ROM Model
|
||||
|
||||
The known button ROM trace says many physical buttons share this front-door path:
|
||||
|
||||
```text
|
||||
panel byte snapshot -> shadow byte -> dirty bit -> loc_1C0E jump table -> handler -> loc_3E54 report builder
|
||||
```
|
||||
|
||||
CALL and CAM POWER use this path, and SHUTTER ON/OFF now appears to use it too once the CCU side services the queued report stream.
|
||||
|
||||
The handlers diverge after the front door. Some directly build reports. Others depend on session/menu/feature state, especially secondary-table `E400` bits.
|
||||
|
||||
## Test Method
|
||||
|
||||
Run a no-button baseline first:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\button-report-common-gate-baseline.json --parity E --quiet-console --log captures\button-common-baseline.txt --result-json captures\button-common-baseline-result.json
|
||||
```
|
||||
|
||||
Then run one physical button candidate through the same common gate:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\button-report-common-gate-press.json --parity E --quiet-console --log captures\button-common-SHORTNAME.txt --result-json captures\button-common-SHORTNAME-result.json
|
||||
```
|
||||
|
||||
Compare the result JSONs:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario_compare.py captures\button-common-baseline-result.json captures\button-common-SHORTNAME-result.json --show-labels
|
||||
```
|
||||
|
||||
If the candidate run has extra ACK-target frames, decode their selector/value. That suggests the button shares the common queue-service gate.
|
||||
|
||||
## Broad-Gate Fallback
|
||||
|
||||
If common-gate produces no extra selector for a button that should plausibly report, try the broader secondary-gate run:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\button-report-broad-gates-press.json --parity E --quiet-console --log captures\button-broad-SHORTNAME.txt --result-json captures\button-broad-SHORTNAME-result.json
|
||||
```
|
||||
|
||||
Compare it against the same baseline:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario_compare.py captures\button-common-baseline-result.json captures\button-broad-SHORTNAME-result.json --show-labels
|
||||
```
|
||||
|
||||
If a button only emits in the broad-gate run, it likely needs a selector-specific feature/report gate rather than only the common queue-service gate.
|
||||
|
||||
## Practical Candidate Order
|
||||
|
||||
Start with known or visually obvious controls:
|
||||
|
||||
- SHUTTER ON/OFF: positive control, should reproduce selector `0x008F` value `0x8000`.
|
||||
- CAM POWER: known direct selector `0x0007`, useful sanity check.
|
||||
- CALL: known direct selector `0x0015`, but it can emit outside active state so treat it as a control.
|
||||
- KNEE AUTO, DETAIL, BARS, WHITE BALANCE, BLACK/FLARE, and OTHER: useful unknowns because prior display/lamp tests suggest nearby ROM handlers and selector state.
|
||||
|
||||
Run one physical button per capture. The queue emits background reports, so button identity is much easier to recover by comparing against the no-button baseline than by reading one log in isolation.
|
||||
|
||||
## First Common-Gate Results
|
||||
|
||||
The first common-gate bench set compared each one-button run against `button-common-baseline`.
|
||||
|
||||
Positive results:
|
||||
|
||||
| Button | Extra queued report(s) | Current meaning |
|
||||
| --- | --- | --- |
|
||||
| BARS | `01/02 00 17 80 00`, `01/02 00 18 80 00` | BARS shares the common queue-service gate. This matches the ROM handler that emits selectors `0x0017` and `0x0018`. |
|
||||
| IRIS AUTO | `01/02 01 1A 08 00` | IRIS AUTO shares the common queue-service gate. This matches selector `0x009A` in the ROM button trace. |
|
||||
|
||||
No extra ACK-target frames were found in these common-gate runs:
|
||||
|
||||
- STANDARD
|
||||
- MASTER
|
||||
- SLAVE
|
||||
- KNEE AUTO
|
||||
- BLACK/FLARE FLARE
|
||||
- OTHERS
|
||||
|
||||
Interpretation: at least some local controls use the same queue-service gate as SHUTTER ON/OFF, but not every physical button emits through this simple state. The silent candidates may need a different secondary/menu/session gate, may be display-only in this mode, or may not have been captured as a single edge event.
|
||||
|
||||
OTHERS is now treated separately in `pt2-menu-state-machine.md` because the ROM evidence points to a local menu/display key rather than a simple report button.
|
||||
|
||||
Note: the result JSONs preserved the per-button summaries, but the test log path was reused as `button-common-SHORTNAME.txt` for the candidate runs. For future runs, replace `SHORTNAME` in both `--log` and `--result-json` so the full timeline is preserved per button.
|
||||
209
docs/pt2-continuation-command-trace.md
Normal file
209
docs/pt2-continuation-command-trace.md
Normal file
@@ -0,0 +1,209 @@
|
||||
# PT2 Continuation Command Trace
|
||||
|
||||
This note enumerates the command paths that are active after the ROM sees `FAA2 != 0`.
|
||||
|
||||
## Dispatcher Shape
|
||||
|
||||
RX command dispatch starts after six-byte frame validation at `H'BBD6-H'BC67`.
|
||||
|
||||
Important gates:
|
||||
|
||||
- `F9C3 == 6`.
|
||||
- SCI/RX physical error latch `FAA4.7 == 0`.
|
||||
- Checksum matches `0x5A ^ F860 ^ F861 ^ F862 ^ F863 ^ F864 == F865`.
|
||||
- Command number is `F860 & 0x07`.
|
||||
- `F861.7` rejects normal command handling.
|
||||
- `FAA2 == 0` enters the initial dispatcher.
|
||||
- `FAA2 != 0` enters the continuation dispatcher.
|
||||
|
||||
Continuation split:
|
||||
|
||||
| Incoming command bits | Path | Meaning |
|
||||
| --- | --- | --- |
|
||||
| `command & 0x04 != 0` | `H'BC3A-H'BC56` | explicit continuation commands `4/5/6/7` |
|
||||
| `command & 0x04 == 0`, `FAA2.3 == 0` | `H'BC5C -> H'BE6F` | ignored/returns |
|
||||
| `command & 0x04 == 0`, `FAA2.3 == 1` | `H'BC5C-H'BC67 -> H'BC15` | clears queued-report continuation bit and re-enters initial command handling |
|
||||
|
||||
That last row is easy to miss: command `0/1/2/3` can consume the report-continuation latch when `FAA2.3` was set by an autonomous report, then command `0/1/2` can run as an initial command. Command `3` still has no recognized initial handler and falls to the clear/return path.
|
||||
|
||||
Selector bytes are packed from `F861:F862`, mapped by `loc_622B`, then doubled into `R4 = selector * 2` before the command handlers use the selector as a word-table offset.
|
||||
|
||||
## Explicit Continuation Commands
|
||||
|
||||
| Command | Handler | Table writes | Queue/report behavior | Cleanup |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `4` | `H'BD0E` | writes `E000`; selector zero also writes `E800`; sets `EC00.7` | calls `BE70` to append selector to `F970`; if `FAA2.3` set, advances `F9B5` | clears `FAA3`, clears `FAA2` |
|
||||
| `5` | `H'BD80` | none | special selectors may append to `F970` or clear latches; if `FAA2.3` set, advances `F9B5` | clears `FAA3`, clears `FAA2` |
|
||||
| `6` | `H'BDDB` | writes `E400`; sets `EC00.6` | does not append to `F970`; if `FAA2.3` set, advances `F9B5` | clears `FAA3`, clears `FAA2` |
|
||||
| `7` | `H'BE05` | none | copies previous finalized TX frame from `F858-F85C` to `F850-F854` and retransmits | does not clear `FAA2/FAA3` in this handler |
|
||||
|
||||
## `BE70`: Selector Processing Queue Append
|
||||
|
||||
`BE70` is the shared helper used by command `0`, command `4`, and selected command-`5` cases.
|
||||
|
||||
Path `H'BE70-H'BE9D`:
|
||||
|
||||
- Scans the `F970` word ring from consumer cursor `F9B9` to producer cursor `F9B4`.
|
||||
- If the selector is already present, returns without appending a duplicate.
|
||||
- If absent, writes the selector to `F970 + 2*F9B4`.
|
||||
- Increments `F9B4` and clears bit 5, making the queue a 32-entry ring.
|
||||
|
||||
Practical meaning:
|
||||
|
||||
- `F970` means "process this selector internally".
|
||||
- It is separate from the serial-visible report queue at `F870`.
|
||||
- Re-sending the same selector may refresh table values without creating another queued selector entry if the old entry has not been consumed yet.
|
||||
|
||||
## Command 4: Continuation Primary Write
|
||||
|
||||
Selector zero branch:
|
||||
|
||||
- `H'BD12-H'BD18`: builds value from `F863` and forces low byte `0x80`.
|
||||
- `H'BD1A`: writes `E000[0]`.
|
||||
- `H'BD1E`: writes `E800[0]`.
|
||||
- `H'BD22`: sets `EC00[0].7`.
|
||||
- `H'BD26`: calls `BE70`, appending selector zero to `F970`.
|
||||
|
||||
Nonzero selector branch:
|
||||
|
||||
- `H'BD2B-H'BD35`: builds value from `F863/F864` and writes `E000[selector]`.
|
||||
- `H'BD39`: sets `EC00[selector].7`.
|
||||
- `H'BD3D-H'BD45`: if the selector has a mapped shadow slot, writes the value into the `F400` shadow area.
|
||||
- `H'BD49-H'BD5F`: if `F76E.7` is set, uses the mapped shadow offset plus the `F76E` page nibble and calls `BFE0`, the EEPROM/persistent-write path.
|
||||
- `H'BD64`: calls `BE70`, appending the selector to `F970`.
|
||||
|
||||
Persistent-write detail:
|
||||
|
||||
- If the selector-to-shadow map entry is zero, the mirror/persist path is skipped.
|
||||
- `BFE0` seeds retry timer `F840=0x0A`, writes via the P9/X24164 helper path, reads back for verification, and sets `F841.7` on timeout/failure.
|
||||
|
||||
Report consumption:
|
||||
|
||||
- `H'BD67-H'BD71`: if `FAA2.3` was set by a queued report, increments `F9B5` and clears `F9B5.7`.
|
||||
- `H'BD75-H'BD79`: clears `FAA3` and `FAA2`.
|
||||
|
||||
Practical meaning:
|
||||
|
||||
- Command `4` is a continuation write/update, not a generic always-live command.
|
||||
- Command `4` selector zero can refresh both the primary/current table and queue the CONNECT selector.
|
||||
- Nonzero command `4` does not directly refresh `E800`; autonomous report values still come from the older/current `E800` value unless another path updates it.
|
||||
|
||||
## Command 5: ACK-Like / Special Selector Command
|
||||
|
||||
Command `5` reaches `H'BD80` only from the continuation dispatcher:
|
||||
|
||||
- `FAA2 != 0`.
|
||||
- `command & 0x04 != 0`.
|
||||
- `F861.7 == 0`.
|
||||
- `F860 & 0x07 == 5`.
|
||||
|
||||
Special enqueue selectors:
|
||||
|
||||
| Selector | Branch | Later selector dispatch | Current meaning |
|
||||
| --- | --- | --- | --- |
|
||||
| `0x006C` | `H'BD80 -> H'BDBF` | `H'2FAF` | COPY completion/exit sibling when copy flags are live |
|
||||
| `0x006D` | `H'BD85 -> H'BDBF` | `H'3015` | COPY in-progress/start refresh |
|
||||
| `0x006E` | `H'BD8A/H'BD8F -> H'BDBF` | `H'2CA6` | special-accepted but selector dispatch is currently no-op |
|
||||
|
||||
The duplicate `0x006E` compare at `H'BD8A` and `H'BD8F` appears redundant in the current decode.
|
||||
|
||||
Selector-table math for the special group:
|
||||
|
||||
- Table base is `H'28A6`.
|
||||
- `0x006C` indexes `H'297E`, whose pointer is `H'2FAF`.
|
||||
- `0x006D` indexes `H'2980`, whose pointer is `H'3015`.
|
||||
- `0x006E` indexes `H'2982`, whose pointer is `H'2CA6`.
|
||||
- `H'2CA6` clears `F769.7` and returns.
|
||||
|
||||
Latch-clear selectors:
|
||||
|
||||
| Selector | Gate | Effect |
|
||||
| --- | --- | --- |
|
||||
| `0x006B` | only if `F731.7` set | clears `F731.7` and `F790.7` |
|
||||
| `0x0096` | only if `F731.7` set | clears `F731.7` and `F790.7` |
|
||||
| `0x0097` | only if `F731.7` set | clears `F731.7` and `F790.7` |
|
||||
| `0x00C6` | only if `F731.7` set | clears `F731.7` and `F790.7` |
|
||||
| `0x00F8` | only if `F731.7` set | clears `F731.7` and `F790.7` |
|
||||
|
||||
Report consumption and cleanup:
|
||||
|
||||
- `H'BDC2-H'BDCC`: if `FAA2.3` was set by a queued report, increments `F9B5` and clears `F9B5.7`.
|
||||
- `H'BDD0-H'BDD4`: clears `FAA3` and `FAA2`.
|
||||
|
||||
Practical meaning:
|
||||
|
||||
- Command `5` is the closest thing to an ACK, but only inside the continuation side.
|
||||
- Most command-5 selectors do not have selector-specific meaning; they just consume/clear the continuation state if one is live.
|
||||
- `0x006C/0x006D/0x006E` are command-5 special cases because they enter the `F970` selector-processing queue.
|
||||
- `0x006E` is accepted as special by the command handler, but its current selector-table target is `2CA6`, the no-op return path.
|
||||
|
||||
## Command 6: Continuation Secondary Write
|
||||
|
||||
Path `H'BDDB-H'BE03`:
|
||||
|
||||
- `H'BDDB-H'BDE5`: builds value from `F863/F864` and writes `E400[selector]`.
|
||||
- `H'BDE9`: sets `EC00[selector].6`.
|
||||
- `H'BDED-H'BDF7`: if `FAA2.3` was set by a queued report, increments `F9B5` and clears `F9B5.7`.
|
||||
- `H'BDFB-H'BDFF`: clears `FAA3` and `FAA2`.
|
||||
|
||||
Practical meaning:
|
||||
|
||||
- Command `6` is the secondary feature/status table write used by menu visibility and gate code.
|
||||
- It does not append the selector to `F970`, so it changes later decisions but does not itself force immediate selector dispatch.
|
||||
|
||||
## Command 7: Retransmit
|
||||
|
||||
Path `H'BE05-H'BE25`:
|
||||
|
||||
- Copies previous finalized TX bytes `F858-F85C` into staging bytes `F850-F854`.
|
||||
- Loads `F9C0=0x1F`.
|
||||
- Calls `BA26` to finalize/send again.
|
||||
- `BA26` then waits for `F9C0 == 0`, reloads `F9C0=0x64`, reloads `F9C4=0x07`, copies staging bytes back to `F858-F85C`, recomputes the checksum into `F85D`, and starts SCI1 TX.
|
||||
|
||||
Practical meaning:
|
||||
|
||||
- Command `7` repeats the previous finalized TX frame.
|
||||
- It is valid from both initial and continuation dispatch.
|
||||
- It does not acknowledge/consume `F870` report queue entries by itself and does not clear `FAA2/FAA3` in this handler.
|
||||
- The copied old checksum byte is not trusted; `BA26` recomputes the checksum.
|
||||
|
||||
## Distinct `07` Error Echo Path
|
||||
|
||||
The ROM also emits `07...` frames from an error/retry path that is separate from explicit command `7`.
|
||||
|
||||
Triggers:
|
||||
|
||||
- SCI/RX physical error latched in `FAA4.7`.
|
||||
- Checksum mismatch at `H'BBF0`.
|
||||
|
||||
Path `H'BE29-H'BE6A`:
|
||||
|
||||
- Clears `FAA4.7`.
|
||||
- Requires `FAA5.7`; if the session gate is absent, no echo is sent.
|
||||
- Increments retry counter `FAA6`.
|
||||
- For the first two retry attempts, stages:
|
||||
|
||||
```text
|
||||
byte0 = 0x07
|
||||
byte1 = RX[1]
|
||||
byte2 = RX[2]
|
||||
byte3 = RX[3]
|
||||
byte4 = RX[4]
|
||||
```
|
||||
|
||||
- Calls `BA26` to send the error echo.
|
||||
- After too many retries, loads `F9C0=0x1F` and clears `FAA3/FAA2` instead of sending another echo.
|
||||
|
||||
Practical meaning:
|
||||
|
||||
- A `07 ...` frame is not automatically a normal command-7 retransmit.
|
||||
- Old captures made with the wrong serial parity can easily be retry/error echoes.
|
||||
- Valid frames clear `FAA6` at `H'BBF3`.
|
||||
|
||||
## Bench Implications
|
||||
|
||||
- To update active selector state during a report window, use command `4` or `6` while `FAA2 != 0`.
|
||||
- To consume a queued report without changing tables, command `5` is the cleanest continuation ACK shape.
|
||||
- To trigger COPY side effects, command `5` with `0x006D` starts/refreshes `COPY IN PROGRESS`, and command `5` with `0x006C` completes/exits only while the copy flags are live.
|
||||
- Do not treat command `7` as an ACK. It is a repeat probe.
|
||||
- A low command `0/1/2` sent while `FAA2.3` is live may clear the report continuation and then run as an initial command, which can make timing-sensitive bench traces look like an ACK plus a new command in one frame.
|
||||
@@ -10,6 +10,7 @@ Frame:
|
||||
|
||||
```text
|
||||
05 00 6D 00 00 32
|
||||
00 00 6D 00 00 37 ; family-00 set/queue form to test
|
||||
```
|
||||
|
||||
ROM path:
|
||||
@@ -40,6 +41,7 @@ Frame:
|
||||
|
||||
```text
|
||||
05 00 6C 00 00 33
|
||||
00 00 6C 00 00 36 ; family-00 set/queue form observed during active report drain
|
||||
```
|
||||
|
||||
ROM path:
|
||||
@@ -110,10 +112,27 @@ Observed on the real panel:
|
||||
006D repeated without 006C -> COPY IN PROGRESS -> CONNECT NOT ACT
|
||||
```
|
||||
|
||||
Family-00 comparison run on 2026-05-27:
|
||||
|
||||
```text
|
||||
00 00 6D 00 00 37 -> 00 00 6C 00 00 36
|
||||
-> immediate 04 00 6D / 04 00 6C table readbacks
|
||||
-> no command-5-like 01 00 02 / 02 00 04 response rhythm
|
||||
|
||||
05 00 6D 00 00 32 -> 05 00 6C 00 00 33
|
||||
-> 01 00 02 responses after 006D
|
||||
-> 02 00 04 responses after 006C
|
||||
```
|
||||
|
||||
This suggests the family-00 forms update/read back selector values but should not
|
||||
be treated as equivalent to the command-5 COPY side-effect selectors unless an
|
||||
LCD observation proves otherwise.
|
||||
|
||||
Current interpretation:
|
||||
|
||||
- `0x006D` is a copy-start/progress-window refresh selector.
|
||||
- `0x006C` is a completion/exit selector that only behaves cleanly while the copy window is live.
|
||||
- The observed `00 00 6C 00 00 36` frame is copy-related, but should not be read as "COPY COMPLETED" by itself.
|
||||
- The copy window is transient and timer-controlled.
|
||||
- The panel does not treat `0x006C` as a stateless "show completed" command.
|
||||
|
||||
|
||||
157
docs/pt2-known-button-rom-trace.md
Normal file
157
docs/pt2-known-button-rom-trace.md
Normal file
@@ -0,0 +1,157 @@
|
||||
# PT2 Known Button ROM Trace
|
||||
|
||||
This trace starts from known serial-visible button reports and walks backward into the panel input scanner.
|
||||
|
||||
Known reports:
|
||||
|
||||
- `00 00 07 80 00 DD` = selector `0x0007`, value `0x8000`, observed CAM POWER report.
|
||||
- `00 00 15 80 00 CF` = selector `0x0015`, value `0x8000`, observed CALL active report.
|
||||
- `00 00 15 00 00 4F` = selector `0x0015`, value `0x0000`, observed CALL inactive report.
|
||||
|
||||
## Shared Button Path
|
||||
|
||||
CALL and CAM POWER both use the same general panel edge machinery:
|
||||
|
||||
```text
|
||||
external panel byte snapshot
|
||||
-> shadow byte F6D*
|
||||
-> dirty byte F6F2/F6F3
|
||||
-> main scanner loc_15E0
|
||||
-> bit dispatcher loc_1C0E
|
||||
-> table H'2706
|
||||
-> per-button handler
|
||||
-> loc_3E54 serial report queue
|
||||
```
|
||||
|
||||
That means the lamps and buttons are not just conceptually related. The ROM reads panel byte shadows and drives panel output masks through the same external panel-chip area, then uses per-button handlers to decide whether a press should become a serial report, a local menu action, or nothing.
|
||||
|
||||
## CAM POWER
|
||||
|
||||
Trace:
|
||||
|
||||
```text
|
||||
F105 external/panel byte changes
|
||||
-> F6D4 shadow changes
|
||||
-> F6F2.4 dirty
|
||||
-> loc_1BA0
|
||||
-> loc_1C0E table slot H'274C
|
||||
-> handler H'1F40
|
||||
-> writes E80E
|
||||
-> queues selector 0x0007 through loc_3E54
|
||||
```
|
||||
|
||||
Important handler behavior:
|
||||
|
||||
```text
|
||||
1F40: tests F6D4.3
|
||||
1F4C: tests E000[0x0007] / E00E bit 15
|
||||
1F52: writes E800[0x0007] / E80E = 0x8000
|
||||
1F61: can write E80E = 0x0000 when already set and page gate allows
|
||||
1F68: R3 = 0x0007
|
||||
1F6B: BSR loc_3E54
|
||||
```
|
||||
|
||||
So CAM POWER is a real local button path, not a host-only selector. The handler checks the current button level and local/session gates before emitting.
|
||||
|
||||
## CALL
|
||||
|
||||
Trace:
|
||||
|
||||
```text
|
||||
F006 external/panel byte changes
|
||||
-> F6DB shadow changes
|
||||
-> F6F3.3 dirty
|
||||
-> loc_1BF8
|
||||
-> loc_1C0E table slot H'27C0
|
||||
-> handler H'20A1
|
||||
-> writes E82A
|
||||
-> queues selector 0x0015 through loc_3E54
|
||||
```
|
||||
|
||||
Important handler behavior:
|
||||
|
||||
```text
|
||||
20A1: reads E000[0x0015] / E02A
|
||||
20A5: tests F6DB.5
|
||||
20AB: if pressed, sets bit 15
|
||||
20AF: if released, clears bit 15
|
||||
20B1: writes E800[0x0015] / E82A
|
||||
20B7: R3 = 0x0015
|
||||
20BA: BSR loc_3E54
|
||||
```
|
||||
|
||||
This cleanly matches the bench readings: CALL has both active and inactive reports because the handler explicitly sets or clears bit 15 from the current button level.
|
||||
|
||||
## Divergence
|
||||
|
||||
Other buttons do follow the same input edge path, but many diverge after `loc_1C0E`:
|
||||
|
||||
- Some handlers are `H'1C25`, an immediate `RTS`, so that matrix position is ignored.
|
||||
- Some handlers only change local menu/page state such as `F731`, `F732`, `FB03`, or `F798`.
|
||||
- Some handlers queue reports, but only if session/menu gates like `F731`, `F730`, `F791`, or selector bits in `E000/E400` allow it.
|
||||
- Several handlers queue different selectors such as `0x0083`, `0x008F`, `0x0093`, `0x009A`, `0x00B9`, `0x00F8`, etc.
|
||||
|
||||
The generated report `build/panel_button_trace.md` lists the current table-derived map.
|
||||
|
||||
## Bench Correlation: Common Queue Gate
|
||||
|
||||
The first common-gate button-report bench set used the queued-report ACK stream that exposed SHUTTER ON/OFF.
|
||||
|
||||
Confirmed positives:
|
||||
|
||||
| Physical button | Report selectors/value | ROM match |
|
||||
| --- | --- | --- |
|
||||
| BARS | `0x0017 = 0x8000`, `0x0018 = 0x8000` | `F105/F6D4.2 -> H'1EDE -> 0x0017/0x0018` |
|
||||
| IRIS AUTO | `0x009A = 0x0800` | `F006/F6DB.3 -> H'20BE -> 0x009A` |
|
||||
|
||||
Common-gate runs for STANDARD, MASTER, SLAVE, KNEE AUTO, and BLACK/FLARE FLARE did not differ from the no-button baseline. That is evidence against one universal "all buttons emit now" gate. Some controls likely need additional menu/session/secondary-table state, or are not represented as simple edge reports in this mode.
|
||||
|
||||
## F109 Shutter/Menu Cluster
|
||||
|
||||
A focused trace of the `F109 -> F6D0` input byte found local-key handlers that are close to the OTHERS/shutter/menu machinery:
|
||||
|
||||
| Source bit | Handler | Behavior |
|
||||
| --- | --- | --- |
|
||||
| `F6D0.1` | `H'2390` | Queues selector `0x0083`, unless `E000[0x0088].15` diverts to timed page `F732=0x1C01` |
|
||||
| `F6D0.2` | `H'2408` | Queues selector `0x0083`, unless `E000[0x0088].15` diverts to timed page `F732=0x1C01` |
|
||||
| `F6D0.3` | `H'24A9` | Queues selector `0x0083`, unless `E000[0x0088].15` diverts to timed page `F732=0x1C01` |
|
||||
| `F6D0.7` | `H'24E8` | Queues selector `0x008F` with local mask `0x8000` or `0x0000`; `E000[0x0088].14` diverts to timed page `F732=0x1C01` |
|
||||
| `F6D0.6` | `H'252E` | Queues selector `0x008F` with local mask `0x2000` or `0x0000`; `E000[0x0088].14` diverts to timed page `F732=0x1C01` |
|
||||
| `F6D0.4/F6D0.5` | `H'2574/H'25D4` | Uses selectors `0x0091/0x0092` and modal byte `F6F6`; `E000[0x0088].14` can divert to timed page `F732=0x1C01` |
|
||||
|
||||
This cluster explains why some adjacent controls may look like menu/display keys rather than ordinary reports. A CCU-side bit in selector `0x0088` can retarget them into a timed local page overlay, currently matching the DETAIL/KNEE neighborhood rather than the OTHERS page.
|
||||
|
||||
## OTHERS Difference
|
||||
|
||||
OTHERS page `0x01` is not driven by one of the simple confirmed report handlers above. The page-1 handlers consume low action bits in `F770`:
|
||||
|
||||
- `H'6EE4` consumes `F770.0/F770.1` for OTHERS/SHUTTER local actions.
|
||||
- `H'6FF0` consumes `F770.2` for COPY TO SLAVES.
|
||||
- No decoded direct writer for these low bits has been found yet.
|
||||
|
||||
That is the current best explanation for the bench result where the OTHERS physical press matched the no-button baseline: the shared scanner may see the key, but the useful OTHERS action is gated behind a separate local page/action latch.
|
||||
|
||||
## Emulator Probe
|
||||
|
||||
The emulator can inject these as ROM-level panel edges:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe h8536_emulator_rx_probe.py --wait-heartbeats 1 --panel-press cam-power
|
||||
.\.venv\Scripts\python.exe h8536_emulator_rx_probe.py --panel call=press --panel call=release --keep-listening
|
||||
.\.venv\Scripts\python.exe h8536_emulator_rx_probe.py --panel F6D4.6=press
|
||||
```
|
||||
|
||||
This is a post-scan injection model. It sets the external source byte, the `F6D*` shadow byte, the matching `F6E*` previous-shadow byte to the opposite bit level, and the `F6F2/F6F3` dirty bit. The ROM then runs its normal `loc_15E0 -> loc_1C0E -> H'2706` dispatch path, so gates and no-op handlers still behave like firmware rather than like forced serial output.
|
||||
|
||||
## Tooling
|
||||
|
||||
Regenerate the map with:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe h8536_panel_button_trace.py
|
||||
```
|
||||
|
||||
Outputs:
|
||||
|
||||
- `build/panel_button_trace.md`
|
||||
- `build/panel_button_trace.json`
|
||||
@@ -102,6 +102,52 @@ Relevant ROM behavior:
|
||||
- The FRT timer path decrements `F726`; when it expires, it clears `F713.6` and `F711.4-F711.7`.
|
||||
- The OTHERS/COPY branch sets `F711.7` and `F726=H'64` to keep the local key/display state alive briefly.
|
||||
|
||||
## OTHERS Action Latch Trace
|
||||
|
||||
The missing OTHERS mechanism appears to be `F770`, not another simple command-0 selector.
|
||||
|
||||
Root OTHERS/SHUTTER handler `H'6EE4`:
|
||||
|
||||
- Reads `F770`, clears it, and only keeps low bits `0x01/0x02`.
|
||||
- If the first action path is present and `E400[0x008F].11` is enabled, writes `E800[0x008F]=0x0800` and queues selector `0x008F`.
|
||||
- If the second action path is present and `E400[0x008F].12` is enabled, writes `E800[0x008F]=0x1000` and queues selector `0x008F`.
|
||||
|
||||
COPY TO SLAVES handler `H'6FF0`:
|
||||
|
||||
- Reads `F770`, clears it, and only keeps bit `0x04`.
|
||||
- If `F770.2` is clear, it only displays the OTHERS/COPY page.
|
||||
- If `F770.2` is set and `F791.7` is set, it enters the local copy-start branch.
|
||||
- If `F770.2` is set and `F791.7` is clear, it diverts to `SET RCP` / `MASTER` and stages restore selector `F734=0x0101`.
|
||||
|
||||
Static direct writers found so far only write high bits into `F770`:
|
||||
|
||||
| Writer family | Value | Meaning candidate |
|
||||
| --- | --- | --- |
|
||||
| `H'4394` | `0x80` | value/dial page redraw or change latch |
|
||||
| `H'4457` | `0x40` | value/dial page redraw or change latch |
|
||||
| `H'451A` | `0x20` | value/dial page redraw or change latch |
|
||||
|
||||
No decoded direct instruction has been found that writes `F770=0x01`, `0x02`, or `0x04`.
|
||||
|
||||
Updated interpretation:
|
||||
|
||||
- `E000[0x008F]` and `E400[0x0015]` can make OTHERS-adjacent UI state visible, but they do not synthesize the local OTHERS action.
|
||||
- The physical OTHERS/COPY/menu action likely arrives through a separate local key latch or indirect panel-chip path that produces the low `F770` bits only when the page machinery is in the right context.
|
||||
- Pressing OTHERS under the generic queued-report gate can therefore legitimately produce no new serial report.
|
||||
|
||||
## Adjacent F109 Menu/Shutter Key Trace
|
||||
|
||||
A focused trace of the `F109 -> F6D0` local-key handlers found a neighboring menu/shutter cluster. These are useful context because they share the same local-page style, but they do not directly prove the OTHERS low-bit latch.
|
||||
|
||||
| Source bit | Handler | Selector/page effect |
|
||||
| --- | --- | --- |
|
||||
| `F6D0.7` | `H'24E8` | Writes `E800[0x008F]=0x8000` or `0x0000`; if `E000[0x0088].14` is set, diverts to timed page `F732=0x1C01` |
|
||||
| `F6D0.6` | `H'252E` | Writes `E800[0x008F]=0x2000` or `0x0000`; if `E000[0x0088].14` is set, diverts to timed page `F732=0x1C01` |
|
||||
| `F6D0.4/F6D0.5` | `H'2574/H'25D4` | Uses selectors `0x0091/0x0092` and modal byte `F6F6`; if `E000[0x0088].14` is set, diverts to timed page `F732=0x1C01` |
|
||||
| `F6D0.1/F6D0.2/F6D0.3` | `H'2390/H'2408/H'24A9` | Uses selector `0x0083`; if `E000[0x0088].15` is set, diverts to timed page `F732=0x1C01` |
|
||||
|
||||
`F732=0x1C01` is in the DETAIL/KNEE neighborhood seen in earlier traces, not the OTHERS page `0x01`. This suggests selector `0x0088` can retarget adjacent local keys into a timed menu overlay, while OTHERS itself still depends on the page-1 wrapper and the `F770` low-bit action latch.
|
||||
|
||||
## Bench Implications
|
||||
|
||||
To make the local COPY path available from the panel, the fake CCU probably needs to:
|
||||
@@ -191,3 +237,40 @@ Manual correlation:
|
||||
- The same RCP-TX7 manual lists `EVS/ECS` under OTHERS for DXC-D30/D30P normal settings.
|
||||
- A later CCU/RCP manual states that when EVS is on, `EVS` is displayed; when the shutter switch is off, `OFF` is displayed.
|
||||
- Therefore `E000[0x008F].11` is best labeled `shutter_evs_display_or_mode`, and `E000[0x008F].12` is best labeled `shutter_off_display_or_mode` until ROM traces split display-only status from actual camera setting.
|
||||
|
||||
## Bench Observation: OTHERS Common-Gate Button Press
|
||||
|
||||
After the queued-report button tests found BARS and IRIS AUTO reports, the physical OTHERS button was tested with the same common queue-service gate.
|
||||
|
||||
Result:
|
||||
|
||||
- `button-common-OTHERS-result.json` matched `button-common-baseline-result.json`.
|
||||
- No extra ACK-target frames appeared.
|
||||
- The queued selector stream still included baseline selector `0x0015 = 0x0000`, but OTHERS did not turn that into a visible/new report.
|
||||
|
||||
Interpretation:
|
||||
|
||||
- OTHERS does not behave like BARS or IRIS AUTO under the simple common queue-service gate.
|
||||
- This supports the ROM model that OTHERS is a local menu/display key whose useful effect depends on additional page/menu state, not just the generic report queue being serviced.
|
||||
- The next fair comparison needs an OTHERS-specific no-button baseline because the OTHERS seeds themselves alter display/report state.
|
||||
|
||||
New focused scenarios:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\others-menu-gated-baseline.json --parity E --quiet-console --log captures\others-menu-gated-baseline.txt --result-json captures\others-menu-gated-baseline-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\others-menu-gated-press.json --parity E --quiet-console --log captures\others-menu-gated-press.txt --result-json captures\others-menu-gated-press-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario_compare.py captures\others-menu-gated-baseline-result.json captures\others-menu-gated-press-result.json --show-labels
|
||||
```
|
||||
|
||||
Result of the first OTHERS-gated comparison:
|
||||
|
||||
- The current baseline rerun overwrote the accidental first baseline capture; `serial_scenario.py` writes logs/results fresh when explicit paths are reused.
|
||||
- `others-menu-gated-baseline-result.json` and `others-menu-gated-press-result.json` were identical at the ACK-target level.
|
||||
- Both had `rx_frames=153`, `ack_sent=64`, and no label-count increase in the press run.
|
||||
- The seeded state was visible in the queued stream as `0x008F = 0x1800`, but pressing OTHERS still did not create an extra serial report.
|
||||
|
||||
Updated interpretation:
|
||||
|
||||
- The simple common queue gate is not enough for OTHERS.
|
||||
- The current OTHERS-adjacent seeds are also not enough for OTHERS to emit a report.
|
||||
- OTHERS is increasingly likely to be a local menu/page navigation key whose effect is visible only if the ROM has selected the right page/context (`F732/F733/F72C/F731/F770`), rather than a host-visible selector-report button like BARS or IRIS AUTO.
|
||||
|
||||
@@ -8,7 +8,11 @@ Focused companion notes:
|
||||
|
||||
- [PT2 Copy State Machine](pt2-copy-state-machine.md)
|
||||
- [PT2 Menu State Machine](pt2-menu-state-machine.md)
|
||||
- [PT2 Session Rhythm ROM Trace](pt2-session-rhythm-trace.md)
|
||||
- [PT2 Continuation Command Trace](pt2-continuation-command-trace.md)
|
||||
- [PT2 Report Aftermath ROM Trace](pt2-report-aftermath-trace.md)
|
||||
- [PT2 Shutter Display Trace](pt2-shutter-display-trace.md)
|
||||
- [PT2 Button Report Bench Plan](pt2-button-report-bench-plan.md)
|
||||
|
||||
## Current High-Confidence Facts
|
||||
|
||||
@@ -434,6 +438,9 @@ ROM report-source update:
|
||||
- The active `02/01 ...` frames seen during CONNECT OK attempts are best modeled as `F870 -> BAF2 -> BA26` report-queue transmissions.
|
||||
- `BAF2` dequeues a report word, encodes the first three TX bytes, reads the payload from `E800 + 2*selector`, and `BA26` appends the `0x5A` XOR checksum.
|
||||
- After sending a queued report, the ROM sets `FAA2.3` and `FAA3.7`; command `4`, `5`, or `6` can then consume/advance the report only while that continuation latch is live.
|
||||
- The emitted report does not appear to encode a required ACK selector. The ROM consume test is `FAA2.3`, so a generic command-5 continuation ACK such as `05 00 40 00 00 1F` is the cleanest report-cursor consume candidate.
|
||||
- Low commands `0/1/2` during the report wait can clear the continuation latch and re-enter initial dispatch, but they do not advance `F9B5`. Command `7` retransmits and also does not advance `F9B5`.
|
||||
- Emulator testing now supports the reactive ACK model: waiting for a finished RCP report frame, then sending `05 00 40 00 00 1F`, repeatedly advanced `F9B5`, cleared `FAA2/FAA3`, and kept the emulated LCD at `CONNECT: OK`.
|
||||
- This makes a reactive fake-CCU test more valuable than another blind fixed-delay matrix: recover to OK, wait for the first active report, then send one candidate continuation/ACK frame.
|
||||
|
||||
## Candidate CCU Seed Values
|
||||
@@ -578,6 +585,8 @@ RCP-side OTHERS/COPY menu trace:
|
||||
- The OTHERS menu is page `0x01`: `493E[0x01] -> H'631C`, local table `H'632E`.
|
||||
- Local table entry 1 points to `H'6FF0`, the page that renders `OTHERS` / `COPY TO SLAVES`.
|
||||
- The entry descriptor immediately before `H'6FF0` requires selector `0x0015` in the secondary table: `E400[0x0015] != 0`. Because command 6 writes `E400`, this is probably a CCU-provided feature/visibility bit, and command 6 must be sent in a live continuation/report window to have an effect.
|
||||
- The root OTHERS/SHUTTER page `H'6EE4` consumes `F770.0/F770.1`; the COPY page `H'6FF0` consumes `F770.2`. Both handlers read `F770`, clear it, and then act on those low bits.
|
||||
- The only decoded direct writers to `F770` found so far write high bits `0x80`, `0x40`, and `0x20` from value/dial redraw paths. No direct decoded write to `F770=0x01/0x02/0x04` has been found yet, so the physical OTHERS/COPY action probably arrives through an indirect panel-key latch or page-local mechanism.
|
||||
- When the page sees `F770.2` set, it only follows the local copy-start branch if `F791.7` is already set. That branch sets `F76E.6`, `F795.7`, `F731.7`, `F798=H'C8`, `F711.7`, `F726=H'64`, calls `loc_5500`, then displays `COPY TO SLAVES`. This is the RCP-side equivalent of the serial `0x006D` copy-start effect.
|
||||
- If `F770.2` is set while `F791.7` is clear, the ROM diverts through `H'704C` to a `SET RCP` / `MASTER` display path instead of starting copy. That makes `F791.7` a second, likely master/link/session gate for the physical COPY operation.
|
||||
- The OTHERS root handler at `H'6EE4` also tests primary selector `E000[0x008F]` (`H'E11E`) bits 11 and 12, and uses them to set `F711.6` and `F711.4`. Bench isolation shows this selector is broader than an OTHERS gate: bit 11 makes the SHUTTER seven-segment display show observed `EUS`, probably the manual's `EVS` display, and bit 12 makes it show the literal letters `OFF`; either bit also illuminates the iris AUTO lamp.
|
||||
|
||||
215
docs/pt2-report-aftermath-trace.md
Normal file
215
docs/pt2-report-aftermath-trace.md
Normal file
@@ -0,0 +1,215 @@
|
||||
# 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:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
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.
|
||||
186
docs/pt2-session-rhythm-trace.md
Normal file
186
docs/pt2-session-rhythm-trace.md
Normal file
@@ -0,0 +1,186 @@
|
||||
# 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.
|
||||
@@ -72,6 +72,19 @@ Practical meaning:
|
||||
- The CCU can force the display state by writing `E000[0x008F]`.
|
||||
- The RCP can also try to report local EVS/OFF changes through selector `0x008F`, but only when the secondary-table feature bits `E400[0x008F].11/.12` allow it.
|
||||
|
||||
Additional local-key trace:
|
||||
|
||||
- `F109 -> F6D0.7` handler `H'24E8` writes `E800[0x008F]=0x8000` or `0x0000`, then queues selector `0x008F`.
|
||||
- `F109 -> F6D0.6` handler `H'252E` writes `E800[0x008F]=0x2000` or `0x0000`, then queues selector `0x008F`.
|
||||
- Both handlers first check the current session/page gate (`F731 <= 2`) and both can divert to timed page `F732=0x1C01` when `E000[0x0088].14` is set.
|
||||
|
||||
This splits selector `0x008F` into at least two roles:
|
||||
|
||||
- CCU-visible display/status bits `0x0800` and `0x1000`, bench-mapped to `EVS` and `OFF`.
|
||||
- Local key/report bits `0x8000` and `0x2000`, emitted by the physical panel path when gates allow.
|
||||
|
||||
So the display bits that light `EVS/OFF` are not necessarily the same bits the local SHUTTER/OTHERS-adjacent buttons emit.
|
||||
|
||||
## Adjacent Shutter Value Family
|
||||
|
||||
The periodic/control-change scanner at `H'15E0` processes changed input words collected by IRQ3 from the external panel chips. Around the shutter path it calls `H'19A2`, which compares a local delta against the current primary table value and, if changed, writes the `E800` current table and calls `H'3E54`.
|
||||
|
||||
Reference in New Issue
Block a user