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