Compare commits
37 Commits
6d4d9f0027
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4ebbb963bd | ||
|
|
4364d0ed48 | ||
|
|
21f0e455ee | ||
|
|
c0304c575c | ||
|
|
0d099235c5 | ||
|
|
57547fb6ed | ||
|
|
a187214e06 | ||
|
|
c007f2180c | ||
|
|
566b4ab108 | ||
|
|
8d98beb6aa | ||
|
|
fb282fea49 | ||
|
|
de992c6087 | ||
|
|
99946170cf | ||
|
|
fec48518c1 | ||
|
|
11b6a2dc3b | ||
|
|
3e1d30527f | ||
|
|
d9a9dade41 | ||
|
|
c0e3aaddee | ||
|
|
87fb14c71a | ||
|
|
ec30bb9dfd | ||
|
|
a48fa0ed18 | ||
|
|
74a2e2fd2c | ||
|
|
4e0ef92e25 | ||
|
|
85732f8754 | ||
|
|
6d68a87e4e | ||
|
|
edb8ed78f3 | ||
|
|
1ad03d5692 | ||
|
|
421c9f4567 | ||
|
|
d1d924c408 | ||
|
|
443789d6ae | ||
|
|
7c211f8112 | ||
|
|
1e4f87675d | ||
|
|
3f9f03388c | ||
|
|
0819701b22 | ||
|
|
0c241877eb | ||
|
|
c3eb09ddc8 | ||
|
|
4b50d0e98f |
151
README.md
151
README.md
@@ -30,8 +30,11 @@ To run the newer sidecar protocol and gate/queue analysis tools:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe h8536_serial_gate.py build\rom_decompiled.json --out build\rom_serial_gate.txt
|
||||
.\.venv\Scripts\python.exe h8536_rx_branch_trace.py build\rom_decompiled.json --out build\rom_rx_branch_trace.txt
|
||||
.\.venv\Scripts\python.exe h8536_report_source_trace.py build\rom_decompiled.json --out build\rom_report_sources.txt
|
||||
.\.venv\Scripts\python.exe h8536_table_xrefs.py --out build\rom_table_xrefs.txt
|
||||
.\.venv\Scripts\python.exe h8536_ccu_seed_hints.py build\rom_decompiled.json --out build\rom_ccu_seed_hints.txt
|
||||
.\.venv\Scripts\python.exe h8536_eeprom_layout.py build\rom_decompiled.json --out build\rom_eeprom_layout.txt
|
||||
.\.venv\Scripts\python.exe h8536_consistency.py build\rom_decompiled.json --out build\rom_consistency.txt
|
||||
.\.venv\Scripts\python.exe h8536_protocol_capture.py ROM\rcp-txd-idle-only.txt
|
||||
```
|
||||
@@ -43,11 +46,58 @@ To start the current emulator harness:
|
||||
.\.venv\Scripts\python.exe h8536_emulator_probe.py --max-steps 4000000 --stop-on-tx
|
||||
.\.venv\Scripts\python.exe h8536_emulator_probe.py --max-steps 1000000 --stop-on-tx --p9-fast-path
|
||||
.\.venv\Scripts\python.exe h8536_emulator_rx_probe.py --preset connect-lcd
|
||||
.\.venv\Scripts\python.exe h8536_emulator_rx_divergence.py --default-frames --uart-timing --wait-heartbeats 2 --summary-only
|
||||
.\.venv\Scripts\python.exe scripts\bench_connect_lcd_sequence.py --port COM5 --relay-port COM6 --prompt-screen
|
||||
.\.venv\Scripts\python.exe scripts\connect_ok_matrix.py --suite minimal --prompt-observation --result-json captures\connect-ok-minimal-result.json
|
||||
.\.venv\Scripts\python.exe scripts\connect_ok_advance_sweep.py --suite core --prompt-observation --result-json captures\connect-ok-advance-core-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_ack_probe.py --ack-frame "05 00 40 00 00 1F"
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\ack-race-000-001.json --log captures\ack-race-000-001.txt --result-json captures\ack-race-000-001-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\table-sweep-ack-000-07f.json --log captures\table-sweep-ack-000-07f.txt --result-json captures\table-sweep-ack-000-07f-result.json
|
||||
.\.venv\Scripts\python.exe scripts\state_map_runner.py --preset ok --prompt-screen
|
||||
.\.venv\Scripts\python.exe scripts\state_map_runner.py --analyze-log captures\ack-race-000-001.txt
|
||||
.\.venv\Scripts\python.exe scripts\ccu_emulator.py --dry-run
|
||||
.\.venv\Scripts\python.exe scripts\ccu_emulator.py --port COM5 --duration 30 --log captures\ccu-keepalive.txt
|
||||
.\.venv\Scripts\python.exe h8536_emulator_state_search.py --preset connect-queue --target ok --first-hit --json-out build\connect-state-search-ok.json
|
||||
.\.venv\Scripts\python.exe h8536_emulator_bench_replay.py captures\bench-connect-lcd-sequence-20260525-214411.txt --assert-bench-parity
|
||||
.\.venv\Scripts\python.exe h8536_emulator.py --max-steps 250000 --p9-fast-path --eeprom-seed blank --eeprom-save build\emulator-eeprom-boot.bin --eeprom-report build\emulator-eeprom-boot.txt --eeprom-report-json build\emulator-eeprom-boot.json
|
||||
```
|
||||
|
||||
The real-device bench helper uses `pyserial`; install repo dependencies with `.\.venv\Scripts\python.exe -m pip install -r requirements.txt` if needed.
|
||||
Optional webcam snapshots for `scripts\serial_scenario.py` use OpenCV; install it only on the bench machine that needs panel photos:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe -m pip install opencv-python
|
||||
```
|
||||
|
||||
Example snapshot run:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\copy-step-006d-006c-1000ms.json --parity E --quiet-console --log captures\copy-webcam.txt --result-json captures\copy-webcam-result.json --snapshot-dir captures\copy-webcam-shots --camera-index 4 --snapshot-delays 0.5
|
||||
```
|
||||
|
||||
Current bench calibration: webcam index `4` gives the useful panel view, and a `0.5` second post-command delay is enough for LCD changes to settle without producing too many images.
|
||||
|
||||
The current PT2/protocol reconstruction is documented in [docs/pt2-protocol.md](docs/pt2-protocol.md), with focused mini-notes for [COPY state](docs/pt2-copy-state-machine.md), [menu state](docs/pt2-menu-state-machine.md), the [session rhythm ROM trace](docs/pt2-session-rhythm-trace.md), [continuation commands](docs/pt2-continuation-command-trace.md), and [report aftermath handling](docs/pt2-report-aftermath-trace.md).
|
||||
|
||||
## Real Bench Serial Format
|
||||
|
||||
The real RCP serial link is `38400 8E1`, not `38400 8N1`. This is backed by the ROM SCI1 init:
|
||||
|
||||
- `build/rom_decompiled.asm:437`: `SCI1_SMR = H'24`, async 8-bit, even parity, 1 stop.
|
||||
- `build/rom_decompiled.asm:438`: `SCI1_SCR = H'3C`, RX/TX enabled.
|
||||
- `build/rom_decompiled.asm:439`: `SCI1_BRR = H'07`.
|
||||
|
||||
The traced board path is H8/536 SCI1 through the MAX202: H8 pin 66 `P95/TXD` to MAX202 pin 11, and MAX202 pin 12 to H8 pin 67 `P96/RXD`.
|
||||
|
||||
Bench scripts default to even parity now. Keep `--parity E` explicit in important captures, and use `--parity N` only to reproduce older 8N1 captures. With the wrong 8N1 format, commands fall into the RX error/retry path instead of the normal command handlers; apparent `07...` frames from those captures should be treated as error/retry echoes until repeated under 8E1.
|
||||
|
||||
Confirmed bench result under 8E1: the CONNECT path can reach `CONNECT: OK`, the CAM POWER lamp illuminates, and the numeric readouts illuminate as `----`.
|
||||
|
||||
Minimal smoke-test shape:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\bench_connect_lcd_sequence.py --port COM5 --relay-port COM6 --parity E --prompt-screen --log captures\8e1-connect-ok-smoke.txt
|
||||
```
|
||||
|
||||
## What It Does
|
||||
|
||||
@@ -71,8 +121,11 @@ The real-device bench helper uses `pyserial`; install repo dependencies with `.\
|
||||
- Decodes observed serial byte captures into six-byte frames, validates checksums, labels capture-observed heartbeat/call/camera-power candidates, and summarizes heartbeat cadence.
|
||||
- Accepts both analyzer-style lines such as `RX 006 bytes ...` and the idle reference `frame 006 ...` format in `ROM/rcp-txd-idle-only.txt`.
|
||||
- Reconstructs the autonomous serial gate/queue state-machine around `loc_3FD3`, `loc_BAF2`, `F9B0/F9B5`, `FAA2/FAA3/FAA5`, the `F9C4`/FRT2 idle heartbeat gate at `loc_4046`, and the resend path through `BE9E/BED5`.
|
||||
- Emits a focused SCI1 RX branch trace covering RXI/ERI byte capture, six-byte checksum validation, selector decode, the `FAA2 == 0` initial dispatcher, the `FAA2 != 0` continuation dispatcher, command `0x00/0x01/0x02/0x04/0x05/0x06/0x07` handlers, table surfaces, retry/error echoes, the separate `BE70/F970` selector-processing and `3E54/F870` serial-report queues, the TXI/RXI continuation-collapse interlock, RX-to-TX feedback loops, and session-timeout side effects.
|
||||
- Traces direct callers to `loc_3E54` to identify report queue sources and conservatively flags whether observed report indexes such as `0x0007` are ROM-proven constants or runtime/capture observations.
|
||||
- Generates table/index cross-reference reports for candidate value/current/secondary/flag tables and LCD text correlations.
|
||||
- Mines ROM-backed CCU seed hints from table xrefs, selector dispatch, LCD text terms, and observed report overlays, then proposes syntactically valid command-0 seed frames and command-1 readback frames for high-value selectors.
|
||||
- Mines the ROM-backed X24164 EEPROM layout, including the factory F400-F4FF shadow defaults, the page-0 EEPROM signature/options header, the fifteen blank-by-default 8-byte record slots loaded into F7B8-F82F, and the serial selector-to-persistent-offset map used by command 0/4 handlers.
|
||||
- Adds a Sony RCP-TX7 board profile that ties H8/536 pin 66 `P95/TXD` and pin 67 `P96/RXD` to the MAX202 RS232 transceiver.
|
||||
- Flags/manual-annotates TEMP-register access ordering for FRT and A/D 16-bit peripheral registers.
|
||||
- Scans unreached ROM ranges for ASCII strings and pointer-table candidates.
|
||||
@@ -86,11 +139,20 @@ The real-device bench helper uses `pyserial`; install repo dependencies with `.\
|
||||
- Handles the E-clock transfer instructions `MOVFPE` and `MOVTPE`.
|
||||
- Recognizes likely LCD E-clock access routines at `H'F200`/`H'F201`, including busy-flag polling and data/control writes.
|
||||
- Generates a separate C-like pseudocode view from the JSON, preserving labels, calls, branches, register names, inferred symbols, metadata comments, optional cycle notes, and simple structured `if`/`do while` patterns.
|
||||
- Provides an early H8/536 emulator harness with ROM/RAM/register memory mapping, reset-vector boot, SCI1 transmit capture, MOV condition-code updates, `SCB/F`, stack/call/return support, indirect `JMP/JSR @Rn` dispatch, scaffolded SCI1 RXI/ERI/TXI and interval/FRT1-OCIA/FRT2-OCIA interrupt scheduling, a P9 bit-banged bus model, a 16x4 LCD bus/DDRAM model for `H'F200`/`H'F201`, and an opt-in P9 transfer fast path.
|
||||
- Provides an early H8/536 emulator harness with ROM/RAM/register memory mapping, reset-vector boot, SCI1 transmit capture, MOV condition-code updates, `SCB/F`, stack/call/return support, indirect `JMP/JSR @Rn` dispatch, scaffolded SCI1 RXI/ERI/TXI and interval timer scheduling, manual-derived FRT1/FRT2 OCIA cycle scheduling, a P9 bit-banged bus model, an X24164 two-wire EEPROM model on traced `P91/SCL` and `P97/SDA`, logical EEPROM image load/save/reporting, a 16x4 LCD bus/DDRAM model for `H'F200`/`H'F201`, and an opt-in P9 transfer fast path.
|
||||
- Includes an emulator probe that reports hot PCs, recent P9/SCI accesses, serial report queue/gate traces, RAM lifecycle watches, final SCI1/TXI state, and captured P9 byte candidates while running the real ROM.
|
||||
- Includes an RX command probe that boots until SCI1 RXI is serviceable, injects host six-byte frames through RDR/RDRF, listens for device TX frames, and reports serial latch/table/LCD-buffer and emulated-LCD effects.
|
||||
- Includes an RX command probe that boots until SCI1 RXI is serviceable, injects host six-byte frames through RDR/RDRF, can optionally schedule bench-style UART byte arrivals at real spacing, listens for device TX frames, and reports serial latch/table/LCD-buffer and emulated-LCD effects.
|
||||
- Includes a bench helper for replaying the emulator-derived CONNECT LCD frame sequence against the real device through COM5, with optional COM6 relay power cycling and timestamped capture logs.
|
||||
- Includes a bench-log replay harness that feeds recorded host TX frames back into the ROM emulator and asserts parity against the real device's observed response/LCD state.
|
||||
- Includes a CONNECT: OK bench matrix runner that power-cycles between cases and tests the known sequence, single frames, primer pairs, order permutations, inter-frame gaps, repeats, and hold time to separate magic-frame, primer, cadence, and latch behavior.
|
||||
- Includes a CONNECT: OK advance sweep runner that recovers to the known OK cadence, waits for an active RCP report frame, then sends one candidate continuation/ACK frame so ACK-only, selector-zero-refresh, and command-5 special selectors can be compared from the same baseline.
|
||||
- Includes a bench ACK probe that reproduces the `01 00 00...` -> `01 00 01...` visible retry burst, waits for `07 80 40 20 90 2D`, then sends a candidate command-5 ACK and reports whether the target keeps repeating.
|
||||
- Includes a checksum-resynchronizing bench receiver that scans RX byte streams for valid six-byte frames, avoids common shifted-heartbeat false locks, and can fall back to the old fixed six-byte slicer with `--sync fixed`.
|
||||
- Includes a JSON scenario bench runner for repeatable multi-step serial tests, including low-latency ACK-aware command-1 probes that can send the current command-5 ACK candidate immediately after the retry frame appears, with explicit max-ACK/max-target guardrails.
|
||||
- The scenario runner can optionally schedule webcam snapshots on each command send, writing image paths into logs/result JSON without delaying timing-sensitive serial steps.
|
||||
- Includes a modular fake-CCU runner in `ccu_emulator/` that seeds active state, listens for complete RCP report frames, and immediately sends the neutral command-5 ACK `05 00 40 00 00 1F`; optional periodic refresh frames let lamp/value streaming be tested separately from report ACKs.
|
||||
- Includes a PT2 state-map-aware bench runner/analyzer for the current CONNECT gate proof: it hunts a fresh device `07...` visible-drain token candidate, sends exactly one selector-zero command-4 force, probes `E000[0]` with command 1, optionally uses command 7 to recover a hidden finalized response, and labels likely token-destroying turns.
|
||||
- Includes a bounded emulator CONNECT state-search tool that patches small ROM-derived RAM/table surfaces, runs either the direct CONNECT branch or the selector-zero queue dispatch path, and classifies LCD outcomes as OK, DXC, NOT ACT, or other.
|
||||
- Includes a bench-log replay harness that feeds recorded host TX frames back into the ROM emulator with bench-style UART byte timing by default and asserts parity against the real device's observed response/LCD state.
|
||||
|
||||
Current serial observations:
|
||||
|
||||
@@ -99,10 +161,24 @@ Current serial observations:
|
||||
- Capture-side label: `heartbeat_alive_candidate`.
|
||||
- Idle cadence from the reference file: 54 frames, average about 699.9 ms, min 601 ms, max 803 ms.
|
||||
- Static/runtime finding: `F9C4` is a candidate idle heartbeat/report countdown. Init loads `H'14`, `loc_BA26` reloads `H'07` after a send, FRT2 OCIA decrements it, and `loc_4046` can enqueue report `H'0000` when it reaches zero and the queue is empty.
|
||||
- Emulator timing finding: the ROM initializes FRT2 with `TCR=H'02` and `OCRA=H'7A12`; using the manual's `phi/32` prescaler gives a 1,000,000-cycle OCIA period, so the default `--clock-hz 10000000` models that tick as 100 ms and the post-send `F9C4=H'07` heartbeat delay as about 700 ms.
|
||||
- Runtime-confirmed heartbeat path: `loc_4067` writes `H'0000` into the queue via a zero-extended word move, `loc_BAF2/loc_BB08` dequeue it, `loc_BB1C/loc_BB20/loc_BB2B` stage the TX bytes, and `loc_BA26` emits `00 00 00 00 80 DA`.
|
||||
- Emulator LCD finding: the ROM writes the boot/no-active-session message to the LCD bus as ` CONNECT:NOT ACT` on line 0 by the time SCI1 RX is serviceable. Valid and invalid six-byte host frames leave that display active while normal serial replies/heartbeats continue.
|
||||
- RX probe finding: the `--preset connect-lcd` sequence reaches the command-`0x04` handler; `04 00 00 80 00 DE` writes table index zero, fills the LCD line buffer with `CONNECT: OK`, and emits `02 00 02 00 00 5A` in the current emulator model.
|
||||
- Bench follow-up: replaying the emulator CONNECT sequence on the real device did not switch the LCD to OK. The real device answered the `04 00 00 80 00 DE` step with `07 80 C0 60 20 5D` in the captured run and remained at `CONNECT NOT ACT`, which points to a missing gate/session precondition in the emulator.
|
||||
- Bench serial-format finding: real hardware talks `38400 8E1`. Earlier `8N1` captures primarily exercised SCI1 parity/error handling and retry echoes, not the normal command path. After switching bench scripts to even parity, the selector-zero CONNECT path can reach `CONNECT: OK`.
|
||||
- Bench CONNECT recovery finding: `CONNECT:NOT ACT` is recoverable without a power cycle. This makes it a normal no-active-session/cleared-state display rather than a terminal latch; tests can now probe from the idle NOT ACT state directly, then separately check whether OK is held or needs periodic CCU-like refresh traffic.
|
||||
- Bench CONNECT cadence finding: the `40 -> 80 -> C0` sequence stayed at `CONNECT:NOT ACT` with 10 ms, 50 ms, and 150 ms gaps, but produced `CONNECT: OK` then returned to `CONNECT:NOT ACT` with 700 ms and 1.5 s gaps. At 700 ms, single `40`/`80`/`C0` frames did not work, but all tested two-frame pairs did. Repeated `80 -> 80` at about 700 ms also worked, so the values do not need to differ. The no-power-cycle NOT ACT recovery capture produced repeated `02 00 02 00 00 5A` OK-path responses before heartbeat traffic resumed.
|
||||
- Bench special-selector finding: in the CONNECT OK advance sweep, command-5 selector `0x006C` (`05 00 6C 00 00 33`) produced `CONNECT OK` then a blank LCD with the CAM POWER lamp still on, while selector `0x006D` (`05 00 6D 00 00 32`) produced `CONNECT OK` then `COPY IN PROGRESS` then `CONNECT NOT ACT`. A later fresh isolated `ack-006d` run in `captures/connect-ok-advance-special-20260526-153339.txt` reproduced the copy path after a relay power-cycle. Forced ROM decoding confirms `0x006C -> H'2FAF` and `0x006D -> H'3015`; the `0x006D` path sets display selector `F732=H'1903`, a long `F798` countdown, and the ROM contains the `COPY IN PROGRESS` LCD string. LCD dispatch now traces through `493E[0x19] -> H'930A`, with local table entry `H'9F6A` building `COPY IN PROGRESS` and entry `H'9FDA` building `COPY COMPLETED`; `0x006C` appears to be the completion/exit sibling only after `0x006D` has set the `F795.6/F795.7` copy flags. The RCP-side menu trace now also identifies page `0x01` table entry `H'6FF0` as `OTHERS / COPY TO SLAVES`; it is gated by `E400[0x0015]`, and its local copy-start branch also requires `F791.7` before setting `F76E.6`, `F795.7`, `F731.7`, `F798=H'C8`, `F711.7`, and `F726=H'64`. The RCP-TX7 manual identifies `COPY IN PROGRESS` as the multi-camera `COPY TO SLAVES` transfer state over the RS232C command-link system, with controls locked until `COPY COMPLETED`.
|
||||
- ROM report-source finding: the active `02/01 ...` frames exposed during CONNECT OK attempts are autonomous `F870 -> BAF2 -> BA26` report-queue transmissions, not ordinary command-1 readbacks. The ROM sets `FAA2.3/FAA3.7` after sending them, so the CCU probably needs to answer in that continuation window with command `4`, `5`, or `6` to consume the report queue and keep the session alive.
|
||||
- Board/P9 finding: traced MCU pin 62 `P91` reaches X24164 pin 6 `SCL`, and MCU pin 68 `P97` reaches the shared X24164 pin 5 `SDA` node. The emulator now treats the ROM's `C121/C08B/C0DB/C10C/C142` P9 routines as an X24164-style two-wire EEPROM bus, with ROM logical addresses `0x000-0x7FF` on the `H'A0/H'A1` control-byte family and `0x800-0xFFF` on `H'E0/H'E1`.
|
||||
- EEPROM role finding: `loc_40BB` checks `P7DR.7` and the `F402 == H'6B6F` signature before defaulting EEPROM/shadow tables; `loc_4103` writes ROM default words through `BFE0`, `loc_41D2` reads sixteen 8-byte records into `F7B0-F82F`, and the command-4 path at `BD2B-BD5F` can persist serial table writes when `F76E.7` is set.
|
||||
- EEPROM layout finding: `build\rom_eeprom_layout.txt` currently identifies the ROM factory table at `H'C964-H'CA63`, the F400 shadow defaults, page 0 offset `0x000-0x007` as the signature/options header (`00 00 6B 6F FE 00 00 00`), pages 1-F offset `0x00-0x07` as blank-by-default record slots, and 89 selector mappings from the `H'C564` table into F400/EEPROM offsets. `F404` defaults to `H'FE00` and is tested as option/feature bits, while `F76E` combines persistence enable, dispatch suppression, and low-nibble EEPROM page selection.
|
||||
- Emulator EEPROM-image finding: `build\emulator-eeprom-boot.txt` captures a blank-EEPROM boot defaulting pass. The ROM writes 2108 words, leaves page 0's signature/options header intact, blanks page 1-F record headers, and the final image matches the ROM factory/default baseline. Use `--eeprom-load`/`--eeprom-save` to persist an emulated EEPROM image across runs and compare command-induced changes.
|
||||
- Emulator board-state finding: P7 now reads external pin state for input bits, so the DIP-off default is modeled as `--p7-input 0xFF`; `--eeprom-seed factory` can pre-seed the X24164 devices and `F400-F4FF` shadow from the ROM default table for already-initialized-state experiments.
|
||||
- RX probe finding: the `--preset connect-lcd` sequence is sensitive to injection timing and modeled external state. With timed UART injection, the emulator can still reach `CONNECT: OK`/`02 00 02 00 00 5A`, while the real bench remains at `CONNECT NOT ACT`; this points to missing session/P9/external-panel context rather than a simple checksum or UART-spacing issue.
|
||||
- Emulator state-search finding: the minimum ROM-visible OK display condition is now reproducible without serial. Direct entry at `loc_2CB9` with `E000[0]=0x8080` and unsuppressed `F730=0` reaches `CONNECT: OK`; the queued selector-zero path also reaches OK when `F970[0]=0`, `F9B9=0`, `F9B4=1`, `E000[0]=0x8080`, and `F730=0`. This makes the bench problem sharper: prove whether serial can retain `E000[0]=0x8080` and enqueue selector zero without the reset/clobber path clearing it first.
|
||||
- Emulator panel-input finding: `h8536_emulator_rx_probe.py` can now inject ROM-level panel edges using traced shadow/dirty bytes. `--panel-press cam-power` models `F105 -> F6D4.3/F6F2.4`, `--panel-press call` models `F006 -> F6DB.5/F6F3.3`, and raw specs such as `--panel F6D4.6=press` let adjacent report-capable table entries be probed while the ROM still decides whether a serial report, menu action, or no-op happens.
|
||||
- Bench follow-up: replaying the emulator CONNECT sequence on the real device did not switch the LCD to OK. The real device answered the `04 00 00 80 00 DE` step with `07 80 C0 60 20 5D` in the captured run and remained at `CONNECT NOT ACT`, so the next mismatch to chase is the missing visible `07 80 C0 60 20 5D` response/session context rather than the LCD OK branch.
|
||||
- CCU seed-hint finding: `build\rom_ccu_seed_hints.txt` currently ranks selector `0x000`, `0x0F6`, `0x003`, and `0x040` as the highest-value fake-CCU stream candidates. The generated seed frames are `00 00 00 80 80 5A`, `00 01 76 20 00 0D`, `00 00 03 80 00 D9`, and `00 00 40 FF FF 1A`, with command-1 readbacks listed beside them.
|
||||
- Observed capture labels such as `cam_power_button_candidate` and `call_button_candidate` are deliberately treated as capture overlays, not protocol facts hard-coded in ROM.
|
||||
|
||||
The generated listing is written to:
|
||||
@@ -125,7 +201,10 @@ build/rom_serial_pseudocode.c
|
||||
build/rom_serial_gate.txt
|
||||
build/rom_report_sources.txt
|
||||
build/rom_table_xrefs.txt
|
||||
build/rom_ccu_seed_hints.txt
|
||||
build/rom_eeprom_layout.txt
|
||||
build/rom_consistency.txt
|
||||
build/emulator-eeprom-boot.txt
|
||||
build/callgraph.dot
|
||||
```
|
||||
|
||||
@@ -186,14 +265,22 @@ For gate/queue and table reports:
|
||||
|
||||
```powershell
|
||||
python h8536_serial_gate.py --help
|
||||
python h8536_rx_branch_trace.py --help
|
||||
python h8536_report_source_trace.py --help
|
||||
python h8536_panel_button_trace.py --help
|
||||
python h8536_table_xrefs.py --help
|
||||
python h8536_ccu_seed_hints.py --help
|
||||
python h8536_eeprom_layout.py --help
|
||||
python h8536_consistency.py --help
|
||||
```
|
||||
|
||||
- `h8536_serial_gate.py`: reports the autonomous TX gate and report queue evidence.
|
||||
- `h8536_rx_branch_trace.py`: reports the SCI1 RX branch tree. Current finding: command `0x04/0x05/0x06` are continuation-path commands behind `FAA2 != 0`, so a standalone command-4 force from idle should not reach `BD0E`.
|
||||
- `h8536_report_source_trace.py`: traces direct `loc_3E54` report enqueue sources. Current finding: no direct static `R3 = 0x0007` enqueue in the JSON, so CAM power `0x0007` remains runtime/capture-observed unless a later indirect/table path proves it.
|
||||
- `h8536_panel_button_trace.py`: decodes the `H'2706` panel-button jump table and traces known CALL/CAM POWER reports back through the input shadow bytes.
|
||||
- `h8536_table_xrefs.py`: emits candidate table/index xrefs and LCD text correlation hints.
|
||||
- `h8536_ccu_seed_hints.py`: mines table, dispatch, LCD, and observed-report hints for the CCU-side state stream the RCP may expect before active displays/reports.
|
||||
- `h8536_eeprom_layout.py`: mines the X24164 EEPROM layout, ROM factory defaults, persistent record slots, and serial selector-to-EEPROM offset mapping.
|
||||
- `h8536_consistency.py`: flags JSON-to-pseudocode semantic hazards such as byte immediates written to word destinations.
|
||||
|
||||
For the emulator harness:
|
||||
@@ -202,6 +289,7 @@ For the emulator harness:
|
||||
python h8536_emulator.py --help
|
||||
python h8536_emulator_probe.py --help
|
||||
python h8536_emulator_rx_probe.py --help
|
||||
python h8536_emulator_rx_divergence.py --help
|
||||
```
|
||||
|
||||
- `--rom PATH`: use an explicit ROM path instead of auto-discovering `ROM\M27C512@DIP28_1.BIN`.
|
||||
@@ -209,15 +297,40 @@ python h8536_emulator_rx_probe.py --help
|
||||
- `--trace`: print executed instructions.
|
||||
- `--stop-on-heartbeat`: stop only if `00 00 00 00 80 DA` is emitted through SCI1 TDR.
|
||||
- `--interval-steps N`: tune the scaffolded interval timer cadence.
|
||||
- `--frt1-ocia-steps N` / `--frt2-ocia-steps N`: tune rough FRT compare-interrupt cadence.
|
||||
- `--p9-fast-path`: shortcut known P9 transfer routines for exploration.
|
||||
- `--clock-hz N`: set the CPU/phi clock used for calibrated FRT1/FRT2 compare timing; the default is 10 MHz.
|
||||
- `--frt1-ocia-steps N` / `--frt2-ocia-steps N`: optional legacy overrides for forcing rough FRT compare cadence in targeted tests.
|
||||
- `--p9-fast-path`: shortcut known P9 transfer routines for exploration. Fast-path byte/marker calls now feed the X24164 EEPROM model, and `BFE0/BFFE` wrapper shortcuts perform EEPROM word write-verify/read operations against the modeled banks.
|
||||
- `--p9-fast-optimistic-wrapper`: legacy fallback for older wrapper experiments; the known `BFE0/BFFE` EEPROM wrappers now use the X24164 model instead.
|
||||
- `--p7-input 0xFF`: set external P7 input pin state; this matters for the EEPROM defaulting gate at `P7DR.7` and the DIP-switch style inputs.
|
||||
- `--eeprom-seed blank|factory`: choose blank X24164 power-on state or pre-seed the X24164/shadow tables from the ROM defaults before reset.
|
||||
- `--eeprom-load PATH`: load a 0x1000-byte logical X24164 EEPROM image before boot/probe; page 0 is also mirrored into the F400 shadow so the ROM's early `F402` signature check sees the loaded state.
|
||||
- `--eeprom-save PATH`: save the final 0x1000-byte logical EEPROM image after boot/probe.
|
||||
- `--eeprom-report PATH` / `--eeprom-report-json PATH`: write a ROM-layout-aware EEPROM snapshot with page records, write logs, factory diffs, and F400 shadow diffs.
|
||||
- `--trace-report-gates`, `--trace-report-queue`, and `--trace-ram-lifecycle`: inspect the serial report queue, `loc_4046`/`F9C4` gate, and watched RAM byte history.
|
||||
- `--target-frame "00 00 00 00 80 DA"`: compare staged/emitted TX bytes against an expected six-byte frame.
|
||||
- `h8536_emulator_rx_probe.py "04 00 00 80 00"`: append the checksum, inject the host frame through SCI1 RX, and summarize responses.
|
||||
- `h8536_emulator_rx_probe.py --wait-heartbeats 1 --panel-press cam-power`: inject the traced CAM POWER edge into the ROM panel shadow/dirty path and listen for the resulting selector `0x0007` behavior.
|
||||
- `h8536_emulator_rx_probe.py --panel call=press --panel call=release --keep-listening`: preserve ordered synthetic panel actions and test the CALL active/inactive path through the normal ROM dispatcher.
|
||||
- `h8536_emulator_rx_probe.py --panel F6D4.6=press`: probe an adjacent raw matrix bit from the table at `H'2706`; raw specs may be shadow bytes like `F6D4.6` or source bytes like `F105.6`.
|
||||
- `h8536_emulator_rx_probe.py --uart-timing --uart-baud 38400 "04 00 00 80 00"`: inject all six host bytes with bench-style wire spacing of about 260 us per byte, letting RXI/TXI/timers interleave; if the ROM has not cleared `RDRF` before the next byte, the SCI model raises `ORER`. The real bench link is `8E1`.
|
||||
- `h8536_emulator_rx_probe.py --uart-timing --uart-format 8E1 --tx-wire-timing --wait-heartbeats 2 --post-frame-ms 700 "04 00 00 80 00 DE" "04 00 00 80 00 DE"`: replay the CONNECT refresh shape after heartbeat readiness and keep the emulator running for a bench-scale gap after each frame. The RAM trace now tags interesting accesses with the executing ROM PC, models SCI1 TDRE/TXI at 8E1 character time, and reports whether X24164 EEPROM bytes were written.
|
||||
- `h8536_emulator_rx_probe.py --preset connect-lcd`: replay the current CONNECT LCD activation candidates.
|
||||
- `h8536_emulator_rx_divergence.py --default-frames --uart-timing --wait-heartbeats 2 --summary-only`: run the focused RX divergence trace for the bench mismatch. It flags whether a frame reached cmd0 `BC69`, cmd1 `BCD7`, retry echo, command-7 replay, autonomous `BAF2` report output, or the TX/RX overlap-collapse path.
|
||||
- `scripts\serial_table_dump.py --port COM5 --relay-port COM6 --start 0x000 --count 0x200 --log captures\table-read.txt`: read-only command-1 sweep of the firmware-exposed serial table state for EEPROM/shadow inference. Bench serial scripts default to `8E1` because the ROM initializes SCI1 as async 8-bit even parity, 1 stop; pass `--parity N` only when reproducing older 8N1 captures.
|
||||
- `scripts\serial_scenario.py scenarios\ack-race-000-001.json --log captures\ack-race-000-001.txt --result-json captures\ack-race-000-001-result.json`: run the focused `0x000 -> 0x001` retry probe with immediate reactive ACK and a 2 ms poll interval, to test whether command 5 can arrive before the second `07 80 40 20 90 2D` retry.
|
||||
- `scripts\serial_scenario.py scenarios\early-ack-000-001.json --log captures\early-ack-000-001.txt --result-json captures\early-ack-000-001-result.json`: send the same command-1 pair, then send command-5 ACK immediately without waiting for the retry frame.
|
||||
- `scripts\serial_scenario.py scenarios\table-sweep-ack-000-07f.json --log captures\table-sweep-ack-000-07f.txt --result-json captures\table-sweep-ack-000-07f-result.json`: run a repeatable bench scenario that sweeps selectors `0x000-0x07F` and sends `05 00 40 00 00 1F` only after `07 80 40 20 90 2D` appears. The checked-in scenario stops if it reaches 8 ACKs or 32 target hits. Use `--sync fixed` only when comparing against the old non-resyncing receiver.
|
||||
- `scripts\state_map_runner.py --preset ok --prime-frame "01 80 40 40 30 EB" --prime-repeat 1 --prompt-screen`: run the state-map proof sequence against the bench device. The runner waits for a device `07...` visible-drain candidate, guards briefly so TXI can finish, sends the selector-zero force, then probes direct readback and command-7 recovery without inserting a command-0/command-1 destroyer before the force.
|
||||
- `scripts\state_map_runner.py --analyze-log captures\ack-race-000-001.txt --json-out captures\ack-race-000-001-state-map.json`: classify an existing capture using the same state-map rules and report whether the selector-zero `BD0E -> E000[0]` edge was proven.
|
||||
- `h8536_emulator_state_search.py --preset connect-queue --target ok --first-hit --json-out build\connect-state-search-ok.json`: run the bounded emulator state search for the minimum selector-zero queue condition that reaches `CONNECT: OK`. The default matrix varies `E000[0]` and `F730`, seeds `F970[0]=0`, starts at `loc_2806`, and executes real ROM code into the LCD handler.
|
||||
- `h8536_emulator_state_search.py --preset custom --pc 0x2CB9 --word E000=0x8080 --byte F730=0 --target ok`: directly test the CONNECT handler branch with explicit internal state patches.
|
||||
- `scripts\bench_connect_lcd_sequence.py --port COM5 --relay-port COM6 --prompt-screen`: power-cycle the bench device, wait for heartbeat readiness, send `04 00 00 40 00 1E`, `04 00 00 80 00 DE`, `04 00 00 C0 00 9E`, log RX/TX, and prompt for observed LCD text.
|
||||
- `h8536_emulator_bench_replay.py captures\bench-connect-lcd-sequence-20260525-214411.txt --assert-bench-parity`: replay a real bench log into the emulator and intentionally fail while the emulator still emits `02 00 02 00 00 5A` instead of the bench-observed `07 80 C0 60 20 5D`.
|
||||
- Current status: boots from `H'1000`, initializes SCI1, models the first P9 bit-banged handshakes, captures P9 byte candidates, can optionally fast-path known P9 routines, schedules FRT1/FRT2 OCIA, captures the ROM-driven LCD line ` CONNECT:NOT ACT`, and emits the observed heartbeat frame `00 00 00 00 80 DA`.
|
||||
- `scripts\bench_connect_lcd_sequence.py --port COM5 --relay-port COM6 --no-power-cycle --prompt-before-send --prompt-screen --post-sequence-read 10 --log captures\connect-notact-to-ok.txt`: prove the recoverable path by waiting for `CONNECT:NOT ACT`, then sending the CONNECT sequence without cycling power.
|
||||
- `scripts\connect_ok_matrix.py --suite minimal --prompt-observation --result-json captures\connect-ok-minimal-result.json`: run the first reproducibility pass for the 8E1 CONNECT: OK discovery. It power-cycles between cases and tests the known sequence, each single frame, and the likely primer pairs.
|
||||
- `scripts\connect_ok_matrix.py --suite gap --prompt-observation --result-json captures\connect-ok-gap-result.json`: rerun the known `40 -> 80 -> C0` order with varied inter-frame gaps to test whether cadence matters.
|
||||
- `scripts\connect_ok_matrix.py --suite hold --prompt-observation --result-json captures\connect-ok-hold-result.json`: rerun the known order with longer post-send observation windows to test whether CONNECT: OK is latched or needs continued traffic.
|
||||
- `h8536_emulator_bench_replay.py captures\bench-connect-lcd-sequence-20260525-214411.txt --assert-bench-parity`: replay a real bench log into the emulator using timed UART RX by default and intentionally fail while any response/LCD state still diverges from the bench-observed `CONNECT NOT ACT` plus `07 80 C0 60 20 5D` path. Pass `--polite-rx` for the old wait-until-consumed injection mode.
|
||||
- Current status: boots from `H'1000`, initializes SCI1, models the traced X24164 EEPROM bus on P9, captures P9 byte candidates, can optionally fast-path known P9 EEPROM routines, schedules FRT1/FRT2 OCIA from timer registers and `--clock-hz`, captures the ROM-driven LCD line ` CONNECT:NOT ACT`, and emits the observed heartbeat frame `00 00 00 00 80 DA`.
|
||||
|
||||
## Code Layout
|
||||
|
||||
@@ -244,12 +357,21 @@ python h8536_emulator_rx_probe.py --help
|
||||
- `h8536/serial_pseudocode.py`: focused RX/TX protocol pseudocode generation from reconstruction metadata.
|
||||
- `h8536/protocol_trace.py`: raw six-byte protocol frame decoder/checksum validator.
|
||||
- `h8536/protocol_capture.py`: timestamped serial capture parser, frame recombiner, and cadence/gate-session analyzer.
|
||||
- `h8536/serial_scenario.py`: JSON-driven bench scenario engine shared by real-device serial scripts.
|
||||
- `h8536/state_map_runner.py`: PT2 state-map proof runner and bench-log analyzer for visible-drain token, selector-zero force, `E000[0]` readback, and command-7 recovery experiments.
|
||||
- `ccu_emulator/`: modular fake-CCU package for reactive report ACKs and optional periodic state refreshes.
|
||||
- `h8536/serial_gate.py`: autonomous TX gate/queue state-machine reconstruction.
|
||||
- `h8536/report_source_trace.py`: direct `loc_3E54` report enqueue source tracer.
|
||||
- `h8536/panel_button_trace.py`: panel button matrix/jump-table tracer for CALL, CAM POWER, and adjacent report-capable button paths.
|
||||
- `h8536/table_xrefs.py`: table/index xrefs and LCD correlation report generation.
|
||||
- `h8536/ccu_seed_hints.py`: ROM miner for likely fake-CCU state seed selectors and candidate command/readback frames.
|
||||
- `h8536/eeprom_layout.py`: ROM miner for X24164 EEPROM defaults, 8-byte record slots, and serial persistence mapping.
|
||||
- `h8536/consistency.py`: decompiler/pseudocode semantic consistency checks.
|
||||
- `h8536/emulator/`: early H8/536 emulator package split into CPU state, memory map, SCI1 TX capture, P9 bus model, LCD model, runner, probe, CLI, and peripheral scaffolding.
|
||||
- `h8536/emulator/`: early H8/536 emulator package split into CPU state, memory map, SCI1 TX capture, bench-style UART injection timing, P9/X24164 EEPROM bus model, LCD model, manual-derived FRT timer scheduling, runner, probe, CLI, and peripheral scaffolding.
|
||||
- `h8536/emulator/eeprom_image.py`: logical EEPROM image dump/report helpers for emulator runs, including factory diffs and record-slot summaries.
|
||||
- `h8536/emulator/panel.py`: synthetic panel input descriptors for known CALL/CAM POWER edges and raw ROM shadow/source-bit injection.
|
||||
- `h8536/emulator/rx_probe.py`: host-frame injection and response/listener probe for SCI1 RX experiments.
|
||||
- `h8536/emulator/state_search.py`: bounded internal-state search for CONNECT LCD outcomes using ROM execution plus explicit RAM/table patches.
|
||||
- `h8536/board_profile.py`: Sony RCP-TX7 board-trace annotations, including the MAX202 RS232 path.
|
||||
- `h8536/peripheral_access.py`: FRT/A-D TEMP-register access analysis.
|
||||
- `h8536/pseudocode.py`: JSON-to-C-like pseudocode generation.
|
||||
@@ -258,6 +380,11 @@ python h8536_emulator_rx_probe.py --help
|
||||
- `h8536_pseudocode.py`: pseudocode CLI wrapper.
|
||||
- `h8536_serial_pseudocode.py`: focused serial pseudocode CLI wrapper.
|
||||
- `h8536_protocol_trace.py`, `h8536_protocol_capture.py`: protocol analysis CLI wrappers.
|
||||
- `h8536_serial_gate.py`, `h8536_report_source_trace.py`, `h8536_table_xrefs.py`, `h8536_consistency.py`: sidecar analysis CLI wrappers.
|
||||
- `h8536_emulator.py`, `h8536_emulator_probe.py`, `h8536_emulator_rx_probe.py`, `h8536_emulator_bench_replay.py`: emulator CLI wrappers.
|
||||
- `h8536_serial_gate.py`, `h8536_report_source_trace.py`, `h8536_panel_button_trace.py`, `h8536_table_xrefs.py`, `h8536_ccu_seed_hints.py`, `h8536_eeprom_layout.py`, `h8536_consistency.py`: sidecar analysis CLI wrappers.
|
||||
- `h8536_emulator.py`, `h8536_emulator_probe.py`, `h8536_emulator_rx_probe.py`, `h8536_emulator_rx_divergence.py`, `h8536_emulator_bench_replay.py`: emulator CLI wrappers.
|
||||
- `h8536_emulator_state_search.py`: emulator CONNECT state-search CLI wrapper.
|
||||
- `scripts/bench_connect_lcd_sequence.py`: real-device COM5/COM6 bench runner for the CONNECT LCD sequence.
|
||||
- `scripts/connect_ok_matrix.py`: real-device COM5/COM6 CONNECT: OK reproducibility matrix runner for single-frame, pair, order, gap, repeat, and hold tests.
|
||||
- `scripts/serial_table_dump.py`: read-only COM5/COM6 command-1 table sweep for inferring live EEPROM-backed parameter state. Bench scripts default to `38400 8E1`.
|
||||
- `scripts/serial_scenario.py`: JSON-driven COM5/COM6 bench scenario runner for chained probes, waits, read sweeps, and ACK-on-target experiments.
|
||||
- `scripts/state_map_runner.py`: COM5/COM6 PT2 state-map proof runner and offline bench-log analyzer.
|
||||
|
||||
BIN
build/bench-sync-after-dip-reset.bin
Normal file
BIN
build/bench-sync-after-dip-reset.bin
Normal file
Binary file not shown.
158603
build/bench-sync-after-dip-reset.json
Normal file
158603
build/bench-sync-after-dip-reset.json
Normal file
File diff suppressed because it is too large
Load Diff
111
build/bench-sync-after-dip-reset.txt
Normal file
111
build/bench-sync-after-dip-reset.txt
Normal file
@@ -0,0 +1,111 @@
|
||||
Emulator EEPROM Snapshot
|
||||
|
||||
size=0x1000 sha256=4bed7704e1ea085487ca325c43bd60da75d37b6ae6f8292544e069a8825c64c6
|
||||
writes: bytes=4216 words=2108 factory_diff_words=0
|
||||
|
||||
Persistent Records:
|
||||
- page 0x0 EEPROM 0x000-0x007 bytes=00 00 6B 6F FE 00 00 00 text='..ko....'
|
||||
- page 0x1 EEPROM 0x100-0x107 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x2 EEPROM 0x200-0x207 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x3 EEPROM 0x300-0x307 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x4 EEPROM 0x400-0x407 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x5 EEPROM 0x500-0x507 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x6 EEPROM 0x600-0x607 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x7 EEPROM 0x700-0x707 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x8 EEPROM 0x800-0x807 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x9 EEPROM 0x900-0x907 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xA EEPROM 0xA00-0xA07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xB EEPROM 0xB00-0xB07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xC EEPROM 0xC00-0xC07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xD EEPROM 0xD00-0xD07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xE EEPROM 0xE00-0xE07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xF EEPROM 0xF00-0xF07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
|
||||
EEPROM Word Writes:
|
||||
- 0x0FE page=0x0 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1FE page=0x1 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2FE page=0x2 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3FE page=0x3 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4FE page=0x4 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5FE page=0x5 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6FE page=0x6 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7FE page=0x7 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8FE page=0x8 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9FE page=0x9 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAFE page=0xA offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBFE page=0xB offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCFE page=0xC offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDFE page=0xD offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEFE page=0xE offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFFE page=0xF offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x0FC page=0x0 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1FC page=0x1 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2FC page=0x2 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3FC page=0x3 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4FC page=0x4 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5FC page=0x5 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6FC page=0x6 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7FC page=0x7 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8FC page=0x8 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9FC page=0x9 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAFC page=0xA offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBFC page=0xB offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCFC page=0xC offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDFC page=0xD offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEFC page=0xE offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFFC page=0xF offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x0FA page=0x0 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1FA page=0x1 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2FA page=0x2 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3FA page=0x3 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4FA page=0x4 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5FA page=0x5 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6FA page=0x6 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7FA page=0x7 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8FA page=0x8 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9FA page=0x9 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAFA page=0xA offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBFA page=0xB offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCFA page=0xC offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDFA page=0xD offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEFA page=0xE offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFFA page=0xF offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x0F8 page=0x0 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1F8 page=0x1 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2F8 page=0x2 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3F8 page=0x3 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4F8 page=0x4 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5F8 page=0x5 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6F8 page=0x6 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7F8 page=0x7 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8F8 page=0x8 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9F8 page=0x9 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAF8 page=0xA offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBF8 page=0xB offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCF8 page=0xC offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDF8 page=0xD offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEF8 page=0xE offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFF8 page=0xF offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x0F6 page=0x0 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1F6 page=0x1 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2F6 page=0x2 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3F6 page=0x3 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4F6 page=0x4 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5F6 page=0x5 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6F6 page=0x6 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7F6 page=0x7 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8F6 page=0x8 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9F6 page=0x9 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAF6 page=0xA offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBF6 page=0xB offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCF6 page=0xC offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDF6 page=0xD offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEF6 page=0xE offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFF6 page=0xF offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- ... 2028 more word writes omitted
|
||||
|
||||
Factory Diffs:
|
||||
- current EEPROM image matches ROM factory/default image
|
||||
|
||||
F400 Shadow Diffs:
|
||||
- F400-F4FF shadow matches ROM factory words or no ROM factory baseline was supplied
|
||||
31
build/bench-sync-cmd0-readback-zero-eeprom.txt
Normal file
31
build/bench-sync-cmd0-readback-zero-eeprom.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
Emulator EEPROM Snapshot
|
||||
|
||||
size=0x1000 sha256=4bed7704e1ea085487ca325c43bd60da75d37b6ae6f8292544e069a8825c64c6
|
||||
writes: bytes=0 words=0 factory_diff_words=0
|
||||
|
||||
Persistent Records:
|
||||
- page 0x0 EEPROM 0x000-0x007 bytes=00 00 6B 6F FE 00 00 00 text='..ko....'
|
||||
- page 0x1 EEPROM 0x100-0x107 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x2 EEPROM 0x200-0x207 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x3 EEPROM 0x300-0x307 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x4 EEPROM 0x400-0x407 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x5 EEPROM 0x500-0x507 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x6 EEPROM 0x600-0x607 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x7 EEPROM 0x700-0x707 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x8 EEPROM 0x800-0x807 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x9 EEPROM 0x900-0x907 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xA EEPROM 0xA00-0xA07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xB EEPROM 0xB00-0xB07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xC EEPROM 0xC00-0xC07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xD EEPROM 0xD00-0xD07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xE EEPROM 0xE00-0xE07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xF EEPROM 0xF00-0xF07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
|
||||
EEPROM Word Writes:
|
||||
- none since EEPROM setup/load
|
||||
|
||||
Factory Diffs:
|
||||
- current EEPROM image matches ROM factory/default image
|
||||
|
||||
F400 Shadow Diffs:
|
||||
- H'F4AA offset=0xAA expected=0x8000 actual=0x5500 (factory_shadow_offset; selectors=0x112)
|
||||
BIN
build/bench-sync-cmd0-readback-zero.bin
Normal file
BIN
build/bench-sync-cmd0-readback-zero.bin
Normal file
Binary file not shown.
31
build/bench-sync-cmd0-seed-zero-eeprom.txt
Normal file
31
build/bench-sync-cmd0-seed-zero-eeprom.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
Emulator EEPROM Snapshot
|
||||
|
||||
size=0x1000 sha256=4bed7704e1ea085487ca325c43bd60da75d37b6ae6f8292544e069a8825c64c6
|
||||
writes: bytes=0 words=0 factory_diff_words=0
|
||||
|
||||
Persistent Records:
|
||||
- page 0x0 EEPROM 0x000-0x007 bytes=00 00 6B 6F FE 00 00 00 text='..ko....'
|
||||
- page 0x1 EEPROM 0x100-0x107 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x2 EEPROM 0x200-0x207 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x3 EEPROM 0x300-0x307 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x4 EEPROM 0x400-0x407 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x5 EEPROM 0x500-0x507 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x6 EEPROM 0x600-0x607 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x7 EEPROM 0x700-0x707 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x8 EEPROM 0x800-0x807 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x9 EEPROM 0x900-0x907 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xA EEPROM 0xA00-0xA07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xB EEPROM 0xB00-0xB07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xC EEPROM 0xC00-0xC07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xD EEPROM 0xD00-0xD07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xE EEPROM 0xE00-0xE07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xF EEPROM 0xF00-0xF07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
|
||||
EEPROM Word Writes:
|
||||
- none since EEPROM setup/load
|
||||
|
||||
Factory Diffs:
|
||||
- current EEPROM image matches ROM factory/default image
|
||||
|
||||
F400 Shadow Diffs:
|
||||
- H'F4AA offset=0xAA expected=0x8000 actual=0x5500 (factory_shadow_offset; selectors=0x112)
|
||||
BIN
build/bench-sync-cmd0-seed-zero.bin
Normal file
BIN
build/bench-sync-cmd0-seed-zero.bin
Normal file
Binary file not shown.
BIN
build/bench-sync-factory-trial1.bin
Normal file
BIN
build/bench-sync-factory-trial1.bin
Normal file
Binary file not shown.
31
build/bench-sync-factory-trial1.txt
Normal file
31
build/bench-sync-factory-trial1.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
Emulator EEPROM Snapshot
|
||||
|
||||
size=0x1000 sha256=4bed7704e1ea085487ca325c43bd60da75d37b6ae6f8292544e069a8825c64c6
|
||||
writes: bytes=0 words=0 factory_diff_words=0
|
||||
|
||||
Persistent Records:
|
||||
- page 0x0 EEPROM 0x000-0x007 bytes=00 00 6B 6F FE 00 00 00 text='..ko....'
|
||||
- page 0x1 EEPROM 0x100-0x107 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x2 EEPROM 0x200-0x207 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x3 EEPROM 0x300-0x307 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x4 EEPROM 0x400-0x407 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x5 EEPROM 0x500-0x507 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x6 EEPROM 0x600-0x607 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x7 EEPROM 0x700-0x707 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x8 EEPROM 0x800-0x807 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x9 EEPROM 0x900-0x907 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xA EEPROM 0xA00-0xA07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xB EEPROM 0xB00-0xB07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xC EEPROM 0xC00-0xC07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xD EEPROM 0xD00-0xD07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xE EEPROM 0xE00-0xE07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xF EEPROM 0xF00-0xF07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
|
||||
EEPROM Word Writes:
|
||||
- none since EEPROM setup/load
|
||||
|
||||
Factory Diffs:
|
||||
- current EEPROM image matches ROM factory/default image
|
||||
|
||||
F400 Shadow Diffs:
|
||||
- H'F4AA offset=0xAA expected=0x8000 actual=0x5500 (factory_shadow_offset; selectors=0x112)
|
||||
31
build/bench-sync-polite-trial1-eeprom.txt
Normal file
31
build/bench-sync-polite-trial1-eeprom.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
Emulator EEPROM Snapshot
|
||||
|
||||
size=0x1000 sha256=4bed7704e1ea085487ca325c43bd60da75d37b6ae6f8292544e069a8825c64c6
|
||||
writes: bytes=0 words=0 factory_diff_words=0
|
||||
|
||||
Persistent Records:
|
||||
- page 0x0 EEPROM 0x000-0x007 bytes=00 00 6B 6F FE 00 00 00 text='..ko....'
|
||||
- page 0x1 EEPROM 0x100-0x107 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x2 EEPROM 0x200-0x207 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x3 EEPROM 0x300-0x307 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x4 EEPROM 0x400-0x407 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x5 EEPROM 0x500-0x507 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x6 EEPROM 0x600-0x607 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x7 EEPROM 0x700-0x707 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x8 EEPROM 0x800-0x807 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x9 EEPROM 0x900-0x907 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xA EEPROM 0xA00-0xA07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xB EEPROM 0xB00-0xB07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xC EEPROM 0xC00-0xC07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xD EEPROM 0xD00-0xD07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xE EEPROM 0xE00-0xE07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xF EEPROM 0xF00-0xF07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
|
||||
EEPROM Word Writes:
|
||||
- none since EEPROM setup/load
|
||||
|
||||
Factory Diffs:
|
||||
- current EEPROM image matches ROM factory/default image
|
||||
|
||||
F400 Shadow Diffs:
|
||||
- H'F4AA offset=0xAA expected=0x8000 actual=0x5500 (factory_shadow_offset; selectors=0x112)
|
||||
31
build/bench-sync-polite-trial2-eeprom.txt
Normal file
31
build/bench-sync-polite-trial2-eeprom.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
Emulator EEPROM Snapshot
|
||||
|
||||
size=0x1000 sha256=4bed7704e1ea085487ca325c43bd60da75d37b6ae6f8292544e069a8825c64c6
|
||||
writes: bytes=0 words=0 factory_diff_words=0
|
||||
|
||||
Persistent Records:
|
||||
- page 0x0 EEPROM 0x000-0x007 bytes=00 00 6B 6F FE 00 00 00 text='..ko....'
|
||||
- page 0x1 EEPROM 0x100-0x107 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x2 EEPROM 0x200-0x207 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x3 EEPROM 0x300-0x307 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x4 EEPROM 0x400-0x407 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x5 EEPROM 0x500-0x507 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x6 EEPROM 0x600-0x607 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x7 EEPROM 0x700-0x707 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x8 EEPROM 0x800-0x807 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x9 EEPROM 0x900-0x907 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xA EEPROM 0xA00-0xA07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xB EEPROM 0xB00-0xB07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xC EEPROM 0xC00-0xC07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xD EEPROM 0xD00-0xD07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xE EEPROM 0xE00-0xE07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xF EEPROM 0xF00-0xF07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
|
||||
EEPROM Word Writes:
|
||||
- none since EEPROM setup/load
|
||||
|
||||
Factory Diffs:
|
||||
- current EEPROM image matches ROM factory/default image
|
||||
|
||||
F400 Shadow Diffs:
|
||||
- H'F4AA offset=0xAA expected=0x8000 actual=0x5500 (factory_shadow_offset; selectors=0x112)
|
||||
BIN
build/bench-sync-polite-trial2.bin
Normal file
BIN
build/bench-sync-polite-trial2.bin
Normal file
Binary file not shown.
BIN
build/bench-sync-pololite-trial1.bin
Normal file
BIN
build/bench-sync-pololite-trial1.bin
Normal file
Binary file not shown.
50
build/bench-sync-state-search-direct-ok.json
Normal file
50
build/bench-sync-state-search-direct-ok.json
Normal file
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"case_count": 1,
|
||||
"description": "Use only --byte/--word/--matrix-* patches and --pc.",
|
||||
"hits": [
|
||||
{
|
||||
"case_index": 0,
|
||||
"display": " CONNECT: OK | | | ",
|
||||
"e000": "0x8080",
|
||||
"f730": "0x81",
|
||||
"f9b4": "0x00",
|
||||
"f9b9": "0x00",
|
||||
"final_pc": "H'FFFF",
|
||||
"line0": " CONNECT: OK ",
|
||||
"outcome": "ok",
|
||||
"patches": [
|
||||
"byte:H'F730=0x00",
|
||||
"word:H'E000=0x8080"
|
||||
],
|
||||
"pc": "H'2CB9",
|
||||
"steps": 37097,
|
||||
"stopped_reason": "stop_pc",
|
||||
"unsupported": null
|
||||
}
|
||||
],
|
||||
"kind": "h8536_emulator_state_search",
|
||||
"preset": "custom",
|
||||
"result_count": 1,
|
||||
"results": [
|
||||
{
|
||||
"case_index": 0,
|
||||
"display": " CONNECT: OK | | | ",
|
||||
"e000": "0x8080",
|
||||
"f730": "0x81",
|
||||
"f9b4": "0x00",
|
||||
"f9b9": "0x00",
|
||||
"final_pc": "H'FFFF",
|
||||
"line0": " CONNECT: OK ",
|
||||
"outcome": "ok",
|
||||
"patches": [
|
||||
"byte:H'F730=0x00",
|
||||
"word:H'E000=0x8080"
|
||||
],
|
||||
"pc": "H'2CB9",
|
||||
"steps": 37097,
|
||||
"stopped_reason": "stop_pc",
|
||||
"unsupported": null
|
||||
}
|
||||
],
|
||||
"target": "ok"
|
||||
}
|
||||
56
build/bench-sync-state-search-queue-ok-exact.json
Normal file
56
build/bench-sync-state-search-queue-ok-exact.json
Normal file
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"case_count": 1,
|
||||
"description": "Use only --byte/--word/--matrix-* patches and --pc.",
|
||||
"hits": [
|
||||
{
|
||||
"case_index": 0,
|
||||
"display": " CONNECT: OK | | | ",
|
||||
"e000": "0x8080",
|
||||
"f730": "0x81",
|
||||
"f9b4": "0x01",
|
||||
"f9b9": "0x01",
|
||||
"final_pc": "H'FFFF",
|
||||
"line0": " CONNECT: OK ",
|
||||
"outcome": "ok",
|
||||
"patches": [
|
||||
"byte:H'F9B9=0x00",
|
||||
"byte:H'F9B4=0x01",
|
||||
"byte:H'F730=0x00",
|
||||
"word:H'F970=0x0000",
|
||||
"word:H'E000=0x8080"
|
||||
],
|
||||
"pc": "H'2806",
|
||||
"steps": 37121,
|
||||
"stopped_reason": "stop_pc",
|
||||
"unsupported": null
|
||||
}
|
||||
],
|
||||
"kind": "h8536_emulator_state_search",
|
||||
"preset": "custom",
|
||||
"result_count": 1,
|
||||
"results": [
|
||||
{
|
||||
"case_index": 0,
|
||||
"display": " CONNECT: OK | | | ",
|
||||
"e000": "0x8080",
|
||||
"f730": "0x81",
|
||||
"f9b4": "0x01",
|
||||
"f9b9": "0x01",
|
||||
"final_pc": "H'FFFF",
|
||||
"line0": " CONNECT: OK ",
|
||||
"outcome": "ok",
|
||||
"patches": [
|
||||
"byte:H'F9B9=0x00",
|
||||
"byte:H'F9B4=0x01",
|
||||
"byte:H'F730=0x00",
|
||||
"word:H'F970=0x0000",
|
||||
"word:H'E000=0x8080"
|
||||
],
|
||||
"pc": "H'2806",
|
||||
"steps": 37121,
|
||||
"stopped_reason": "stop_pc",
|
||||
"unsupported": null
|
||||
}
|
||||
],
|
||||
"target": "ok"
|
||||
}
|
||||
31
build/bench-sync-timed-trial1-eeprom.txt
Normal file
31
build/bench-sync-timed-trial1-eeprom.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
Emulator EEPROM Snapshot
|
||||
|
||||
size=0x1000 sha256=4bed7704e1ea085487ca325c43bd60da75d37b6ae6f8292544e069a8825c64c6
|
||||
writes: bytes=0 words=0 factory_diff_words=0
|
||||
|
||||
Persistent Records:
|
||||
- page 0x0 EEPROM 0x000-0x007 bytes=00 00 6B 6F FE 00 00 00 text='..ko....'
|
||||
- page 0x1 EEPROM 0x100-0x107 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x2 EEPROM 0x200-0x207 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x3 EEPROM 0x300-0x307 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x4 EEPROM 0x400-0x407 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x5 EEPROM 0x500-0x507 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x6 EEPROM 0x600-0x607 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x7 EEPROM 0x700-0x707 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x8 EEPROM 0x800-0x807 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x9 EEPROM 0x900-0x907 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xA EEPROM 0xA00-0xA07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xB EEPROM 0xB00-0xB07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xC EEPROM 0xC00-0xC07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xD EEPROM 0xD00-0xD07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xE EEPROM 0xE00-0xE07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xF EEPROM 0xF00-0xF07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
|
||||
EEPROM Word Writes:
|
||||
- none since EEPROM setup/load
|
||||
|
||||
Factory Diffs:
|
||||
- current EEPROM image matches ROM factory/default image
|
||||
|
||||
F400 Shadow Diffs:
|
||||
- H'F4AA offset=0xAA expected=0x8000 actual=0x5500 (factory_shadow_offset; selectors=0x112)
|
||||
BIN
build/bench-sync-timed-trial1.bin
Normal file
BIN
build/bench-sync-timed-trial1.bin
Normal file
Binary file not shown.
31
build/bench-sync-timed-trial2-eeprom.txt
Normal file
31
build/bench-sync-timed-trial2-eeprom.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
Emulator EEPROM Snapshot
|
||||
|
||||
size=0x1000 sha256=4bed7704e1ea085487ca325c43bd60da75d37b6ae6f8292544e069a8825c64c6
|
||||
writes: bytes=0 words=0 factory_diff_words=0
|
||||
|
||||
Persistent Records:
|
||||
- page 0x0 EEPROM 0x000-0x007 bytes=00 00 6B 6F FE 00 00 00 text='..ko....'
|
||||
- page 0x1 EEPROM 0x100-0x107 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x2 EEPROM 0x200-0x207 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x3 EEPROM 0x300-0x307 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x4 EEPROM 0x400-0x407 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x5 EEPROM 0x500-0x507 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x6 EEPROM 0x600-0x607 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x7 EEPROM 0x700-0x707 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x8 EEPROM 0x800-0x807 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x9 EEPROM 0x900-0x907 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xA EEPROM 0xA00-0xA07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xB EEPROM 0xB00-0xB07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xC EEPROM 0xC00-0xC07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xD EEPROM 0xD00-0xD07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xE EEPROM 0xE00-0xE07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xF EEPROM 0xF00-0xF07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
|
||||
EEPROM Word Writes:
|
||||
- none since EEPROM setup/load
|
||||
|
||||
Factory Diffs:
|
||||
- current EEPROM image matches ROM factory/default image
|
||||
|
||||
F400 Shadow Diffs:
|
||||
- H'F4AA offset=0xAA expected=0x8000 actual=0x5500 (factory_shadow_offset; selectors=0x112)
|
||||
BIN
build/bench-sync-timed-trial2.bin
Normal file
BIN
build/bench-sync-timed-trial2.bin
Normal file
Binary file not shown.
386
build/connect-state-search-ok.json
Normal file
386
build/connect-state-search-ok.json
Normal file
@@ -0,0 +1,386 @@
|
||||
{
|
||||
"case_count": 25,
|
||||
"description": "Queue selector zero in F970, start at loc_2806, then enter loc_2CB9 through the ROM dispatch.",
|
||||
"hits": [
|
||||
{
|
||||
"case_index": 15,
|
||||
"display": " CONNECT: OK | | | ",
|
||||
"e000": "0x8080",
|
||||
"f730": "0x81",
|
||||
"f9b4": "0x01",
|
||||
"f9b9": "0x01",
|
||||
"final_pc": "H'FFFF",
|
||||
"line0": " CONNECT: OK ",
|
||||
"outcome": "ok",
|
||||
"patches": [
|
||||
"byte:H'F9B9=0x00",
|
||||
"byte:H'F9B4=0x01",
|
||||
"word:H'F970=0x0000",
|
||||
"word:H'E000=0x8080",
|
||||
"byte:H'F730=0x00"
|
||||
],
|
||||
"pc": "H'2806",
|
||||
"steps": 37121,
|
||||
"stopped_reason": "stop_pc",
|
||||
"unsupported": null
|
||||
}
|
||||
],
|
||||
"kind": "h8536_emulator_state_search",
|
||||
"preset": "connect-queue",
|
||||
"result_count": 16,
|
||||
"results": [
|
||||
{
|
||||
"case_index": 0,
|
||||
"display": " CONNECT:NOT ACT | | | ",
|
||||
"e000": "0x0080",
|
||||
"f730": "0x00",
|
||||
"f9b4": "0x01",
|
||||
"f9b9": "0x01",
|
||||
"final_pc": "H'2D37",
|
||||
"line0": " CONNECT:NOT ACT",
|
||||
"outcome": "not-act",
|
||||
"patches": [
|
||||
"byte:H'F9B9=0x00",
|
||||
"byte:H'F9B4=0x01",
|
||||
"word:H'F970=0x0000",
|
||||
"word:H'E000=0x0000",
|
||||
"byte:H'F730=0x00"
|
||||
],
|
||||
"pc": "H'2806",
|
||||
"steps": 5109,
|
||||
"stopped_reason": "unsupported_instruction",
|
||||
"unsupported": "unsupported instruction at H'2D37: 6E C6 MOV:L.W @H'00C6, R6"
|
||||
},
|
||||
{
|
||||
"case_index": 1,
|
||||
"display": " CONNECT:NOT ACT | | | ",
|
||||
"e000": "0x0080",
|
||||
"f730": "0x00",
|
||||
"f9b4": "0x01",
|
||||
"f9b9": "0x01",
|
||||
"final_pc": "H'2D37",
|
||||
"line0": " CONNECT:NOT ACT",
|
||||
"outcome": "not-act",
|
||||
"patches": [
|
||||
"byte:H'F9B9=0x00",
|
||||
"byte:H'F9B4=0x01",
|
||||
"word:H'F970=0x0000",
|
||||
"word:H'E000=0x0000",
|
||||
"byte:H'F730=0x01"
|
||||
],
|
||||
"pc": "H'2806",
|
||||
"steps": 5109,
|
||||
"stopped_reason": "unsupported_instruction",
|
||||
"unsupported": "unsupported instruction at H'2D37: 6E C6 MOV:L.W @H'00C6, R6"
|
||||
},
|
||||
{
|
||||
"case_index": 2,
|
||||
"display": " CONNECT:NOT ACT | | | ",
|
||||
"e000": "0x0080",
|
||||
"f730": "0x00",
|
||||
"f9b4": "0x01",
|
||||
"f9b9": "0x01",
|
||||
"final_pc": "H'2D37",
|
||||
"line0": " CONNECT:NOT ACT",
|
||||
"outcome": "not-act",
|
||||
"patches": [
|
||||
"byte:H'F9B9=0x00",
|
||||
"byte:H'F9B4=0x01",
|
||||
"word:H'F970=0x0000",
|
||||
"word:H'E000=0x0000",
|
||||
"byte:H'F730=0x41"
|
||||
],
|
||||
"pc": "H'2806",
|
||||
"steps": 5109,
|
||||
"stopped_reason": "unsupported_instruction",
|
||||
"unsupported": "unsupported instruction at H'2D37: 6E C6 MOV:L.W @H'00C6, R6"
|
||||
},
|
||||
{
|
||||
"case_index": 3,
|
||||
"display": " CONNECT:NOT ACT | | | ",
|
||||
"e000": "0x0080",
|
||||
"f730": "0x00",
|
||||
"f9b4": "0x01",
|
||||
"f9b9": "0x01",
|
||||
"final_pc": "H'2D37",
|
||||
"line0": " CONNECT:NOT ACT",
|
||||
"outcome": "not-act",
|
||||
"patches": [
|
||||
"byte:H'F9B9=0x00",
|
||||
"byte:H'F9B4=0x01",
|
||||
"word:H'F970=0x0000",
|
||||
"word:H'E000=0x0000",
|
||||
"byte:H'F730=0x81"
|
||||
],
|
||||
"pc": "H'2806",
|
||||
"steps": 5109,
|
||||
"stopped_reason": "unsupported_instruction",
|
||||
"unsupported": "unsupported instruction at H'2D37: 6E C6 MOV:L.W @H'00C6, R6"
|
||||
},
|
||||
{
|
||||
"case_index": 4,
|
||||
"display": " CONNECT:NOT ACT | | | ",
|
||||
"e000": "0x0080",
|
||||
"f730": "0x00",
|
||||
"f9b4": "0x01",
|
||||
"f9b9": "0x01",
|
||||
"final_pc": "H'2D37",
|
||||
"line0": " CONNECT:NOT ACT",
|
||||
"outcome": "not-act",
|
||||
"patches": [
|
||||
"byte:H'F9B9=0x00",
|
||||
"byte:H'F9B4=0x01",
|
||||
"word:H'F970=0x0000",
|
||||
"word:H'E000=0x0000",
|
||||
"byte:H'F730=0xC1"
|
||||
],
|
||||
"pc": "H'2806",
|
||||
"steps": 5109,
|
||||
"stopped_reason": "unsupported_instruction",
|
||||
"unsupported": "unsupported instruction at H'2D37: 6E C6 MOV:L.W @H'00C6, R6"
|
||||
},
|
||||
{
|
||||
"case_index": 5,
|
||||
"display": " CONNECT:NOT ACT | | | ",
|
||||
"e000": "0x0080",
|
||||
"f730": "0x00",
|
||||
"f9b4": "0x01",
|
||||
"f9b9": "0x01",
|
||||
"final_pc": "H'2D37",
|
||||
"line0": " CONNECT:NOT ACT",
|
||||
"outcome": "not-act",
|
||||
"patches": [
|
||||
"byte:H'F9B9=0x00",
|
||||
"byte:H'F9B4=0x01",
|
||||
"word:H'F970=0x0000",
|
||||
"word:H'E000=0x0080",
|
||||
"byte:H'F730=0x00"
|
||||
],
|
||||
"pc": "H'2806",
|
||||
"steps": 5109,
|
||||
"stopped_reason": "unsupported_instruction",
|
||||
"unsupported": "unsupported instruction at H'2D37: 6E C6 MOV:L.W @H'00C6, R6"
|
||||
},
|
||||
{
|
||||
"case_index": 6,
|
||||
"display": " CONNECT:NOT ACT | | | ",
|
||||
"e000": "0x0080",
|
||||
"f730": "0x00",
|
||||
"f9b4": "0x01",
|
||||
"f9b9": "0x01",
|
||||
"final_pc": "H'2D37",
|
||||
"line0": " CONNECT:NOT ACT",
|
||||
"outcome": "not-act",
|
||||
"patches": [
|
||||
"byte:H'F9B9=0x00",
|
||||
"byte:H'F9B4=0x01",
|
||||
"word:H'F970=0x0000",
|
||||
"word:H'E000=0x0080",
|
||||
"byte:H'F730=0x01"
|
||||
],
|
||||
"pc": "H'2806",
|
||||
"steps": 5109,
|
||||
"stopped_reason": "unsupported_instruction",
|
||||
"unsupported": "unsupported instruction at H'2D37: 6E C6 MOV:L.W @H'00C6, R6"
|
||||
},
|
||||
{
|
||||
"case_index": 7,
|
||||
"display": " CONNECT:NOT ACT | | | ",
|
||||
"e000": "0x0080",
|
||||
"f730": "0x00",
|
||||
"f9b4": "0x01",
|
||||
"f9b9": "0x01",
|
||||
"final_pc": "H'2D37",
|
||||
"line0": " CONNECT:NOT ACT",
|
||||
"outcome": "not-act",
|
||||
"patches": [
|
||||
"byte:H'F9B9=0x00",
|
||||
"byte:H'F9B4=0x01",
|
||||
"word:H'F970=0x0000",
|
||||
"word:H'E000=0x0080",
|
||||
"byte:H'F730=0x41"
|
||||
],
|
||||
"pc": "H'2806",
|
||||
"steps": 5109,
|
||||
"stopped_reason": "unsupported_instruction",
|
||||
"unsupported": "unsupported instruction at H'2D37: 6E C6 MOV:L.W @H'00C6, R6"
|
||||
},
|
||||
{
|
||||
"case_index": 8,
|
||||
"display": " CONNECT:NOT ACT | | | ",
|
||||
"e000": "0x0080",
|
||||
"f730": "0x00",
|
||||
"f9b4": "0x01",
|
||||
"f9b9": "0x01",
|
||||
"final_pc": "H'2D37",
|
||||
"line0": " CONNECT:NOT ACT",
|
||||
"outcome": "not-act",
|
||||
"patches": [
|
||||
"byte:H'F9B9=0x00",
|
||||
"byte:H'F9B4=0x01",
|
||||
"word:H'F970=0x0000",
|
||||
"word:H'E000=0x0080",
|
||||
"byte:H'F730=0x81"
|
||||
],
|
||||
"pc": "H'2806",
|
||||
"steps": 5109,
|
||||
"stopped_reason": "unsupported_instruction",
|
||||
"unsupported": "unsupported instruction at H'2D37: 6E C6 MOV:L.W @H'00C6, R6"
|
||||
},
|
||||
{
|
||||
"case_index": 9,
|
||||
"display": " CONNECT:NOT ACT | | | ",
|
||||
"e000": "0x0080",
|
||||
"f730": "0x00",
|
||||
"f9b4": "0x01",
|
||||
"f9b9": "0x01",
|
||||
"final_pc": "H'2D37",
|
||||
"line0": " CONNECT:NOT ACT",
|
||||
"outcome": "not-act",
|
||||
"patches": [
|
||||
"byte:H'F9B9=0x00",
|
||||
"byte:H'F9B4=0x01",
|
||||
"word:H'F970=0x0000",
|
||||
"word:H'E000=0x0080",
|
||||
"byte:H'F730=0xC1"
|
||||
],
|
||||
"pc": "H'2806",
|
||||
"steps": 5109,
|
||||
"stopped_reason": "unsupported_instruction",
|
||||
"unsupported": "unsupported instruction at H'2D37: 6E C6 MOV:L.W @H'00C6, R6"
|
||||
},
|
||||
{
|
||||
"case_index": 10,
|
||||
"display": " CONNECT:NOT ACT | | | ",
|
||||
"e000": "0x4080",
|
||||
"f730": "0x00",
|
||||
"f9b4": "0x01",
|
||||
"f9b9": "0x01",
|
||||
"final_pc": "H'A9E8",
|
||||
"line0": " CONNECT:NOT ACT",
|
||||
"outcome": "not-act",
|
||||
"patches": [
|
||||
"byte:H'F9B9=0x00",
|
||||
"byte:H'F9B4=0x01",
|
||||
"word:H'F970=0x0000",
|
||||
"word:H'E000=0x4080",
|
||||
"byte:H'F730=0x00"
|
||||
],
|
||||
"pc": "H'2806",
|
||||
"steps": 5366,
|
||||
"stopped_reason": "unsupported_instruction",
|
||||
"unsupported": "unsupported instruction at H'A9E8: 7E 58 MOV:S.W R6, @H'0058"
|
||||
},
|
||||
{
|
||||
"case_index": 11,
|
||||
"display": " CONNECT:NOT ACT | | | ",
|
||||
"e000": "0x4080",
|
||||
"f730": "0x01",
|
||||
"f9b4": "0x01",
|
||||
"f9b9": "0x01",
|
||||
"final_pc": "H'A9E8",
|
||||
"line0": " CONNECT:NOT ACT",
|
||||
"outcome": "not-act",
|
||||
"patches": [
|
||||
"byte:H'F9B9=0x00",
|
||||
"byte:H'F9B4=0x01",
|
||||
"word:H'F970=0x0000",
|
||||
"word:H'E000=0x4080",
|
||||
"byte:H'F730=0x01"
|
||||
],
|
||||
"pc": "H'2806",
|
||||
"steps": 5366,
|
||||
"stopped_reason": "unsupported_instruction",
|
||||
"unsupported": "unsupported instruction at H'A9E8: 7E 58 MOV:S.W R6, @H'0058"
|
||||
},
|
||||
{
|
||||
"case_index": 12,
|
||||
"display": " CONNECT:NOT ACT | | | ",
|
||||
"e000": "0x4080",
|
||||
"f730": "0x41",
|
||||
"f9b4": "0x01",
|
||||
"f9b9": "0x01",
|
||||
"final_pc": "H'FFFF",
|
||||
"line0": " CONNECT:NOT ACT",
|
||||
"outcome": "not-act",
|
||||
"patches": [
|
||||
"byte:H'F9B9=0x00",
|
||||
"byte:H'F9B4=0x01",
|
||||
"word:H'F970=0x0000",
|
||||
"word:H'E000=0x4080",
|
||||
"byte:H'F730=0x41"
|
||||
],
|
||||
"pc": "H'2806",
|
||||
"steps": 45,
|
||||
"stopped_reason": "stop_pc",
|
||||
"unsupported": null
|
||||
},
|
||||
{
|
||||
"case_index": 13,
|
||||
"display": " CONNECT:NOT ACT | | | ",
|
||||
"e000": "0x4080",
|
||||
"f730": "0x81",
|
||||
"f9b4": "0x01",
|
||||
"f9b9": "0x01",
|
||||
"final_pc": "H'A9E8",
|
||||
"line0": " CONNECT:NOT ACT",
|
||||
"outcome": "not-act",
|
||||
"patches": [
|
||||
"byte:H'F9B9=0x00",
|
||||
"byte:H'F9B4=0x01",
|
||||
"word:H'F970=0x0000",
|
||||
"word:H'E000=0x4080",
|
||||
"byte:H'F730=0x81"
|
||||
],
|
||||
"pc": "H'2806",
|
||||
"steps": 5366,
|
||||
"stopped_reason": "unsupported_instruction",
|
||||
"unsupported": "unsupported instruction at H'A9E8: 7E 58 MOV:S.W R6, @H'0058"
|
||||
},
|
||||
{
|
||||
"case_index": 14,
|
||||
"display": " CONNECT:NOT ACT | | | ",
|
||||
"e000": "0x4080",
|
||||
"f730": "0xC1",
|
||||
"f9b4": "0x01",
|
||||
"f9b9": "0x01",
|
||||
"final_pc": "H'FFFF",
|
||||
"line0": " CONNECT:NOT ACT",
|
||||
"outcome": "not-act",
|
||||
"patches": [
|
||||
"byte:H'F9B9=0x00",
|
||||
"byte:H'F9B4=0x01",
|
||||
"word:H'F970=0x0000",
|
||||
"word:H'E000=0x4080",
|
||||
"byte:H'F730=0xC1"
|
||||
],
|
||||
"pc": "H'2806",
|
||||
"steps": 45,
|
||||
"stopped_reason": "stop_pc",
|
||||
"unsupported": null
|
||||
},
|
||||
{
|
||||
"case_index": 15,
|
||||
"display": " CONNECT: OK | | | ",
|
||||
"e000": "0x8080",
|
||||
"f730": "0x81",
|
||||
"f9b4": "0x01",
|
||||
"f9b9": "0x01",
|
||||
"final_pc": "H'FFFF",
|
||||
"line0": " CONNECT: OK ",
|
||||
"outcome": "ok",
|
||||
"patches": [
|
||||
"byte:H'F9B9=0x00",
|
||||
"byte:H'F9B4=0x01",
|
||||
"word:H'F970=0x0000",
|
||||
"word:H'E000=0x8080",
|
||||
"byte:H'F730=0x00"
|
||||
],
|
||||
"pc": "H'2806",
|
||||
"steps": 37121,
|
||||
"stopped_reason": "stop_pc",
|
||||
"unsupported": null
|
||||
}
|
||||
],
|
||||
"target": "ok"
|
||||
}
|
||||
BIN
build/emulator-eeprom-boot.bin
Normal file
BIN
build/emulator-eeprom-boot.bin
Normal file
Binary file not shown.
158603
build/emulator-eeprom-boot.json
Normal file
158603
build/emulator-eeprom-boot.json
Normal file
File diff suppressed because it is too large
Load Diff
111
build/emulator-eeprom-boot.txt
Normal file
111
build/emulator-eeprom-boot.txt
Normal file
@@ -0,0 +1,111 @@
|
||||
Emulator EEPROM Snapshot
|
||||
|
||||
size=0x1000 sha256=4bed7704e1ea085487ca325c43bd60da75d37b6ae6f8292544e069a8825c64c6
|
||||
writes: bytes=4216 words=2108 factory_diff_words=0
|
||||
|
||||
Persistent Records:
|
||||
- page 0x0 EEPROM 0x000-0x007 bytes=00 00 6B 6F FE 00 00 00 text='..ko....'
|
||||
- page 0x1 EEPROM 0x100-0x107 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x2 EEPROM 0x200-0x207 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x3 EEPROM 0x300-0x307 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x4 EEPROM 0x400-0x407 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x5 EEPROM 0x500-0x507 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x6 EEPROM 0x600-0x607 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x7 EEPROM 0x700-0x707 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x8 EEPROM 0x800-0x807 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x9 EEPROM 0x900-0x907 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xA EEPROM 0xA00-0xA07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xB EEPROM 0xB00-0xB07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xC EEPROM 0xC00-0xC07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xD EEPROM 0xD00-0xD07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xE EEPROM 0xE00-0xE07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xF EEPROM 0xF00-0xF07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
|
||||
EEPROM Word Writes:
|
||||
- 0x0FE page=0x0 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1FE page=0x1 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2FE page=0x2 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3FE page=0x3 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4FE page=0x4 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5FE page=0x5 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6FE page=0x6 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7FE page=0x7 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8FE page=0x8 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9FE page=0x9 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAFE page=0xA offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBFE page=0xB offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCFE page=0xC offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDFE page=0xD offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEFE page=0xE offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFFE page=0xF offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x0FC page=0x0 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1FC page=0x1 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2FC page=0x2 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3FC page=0x3 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4FC page=0x4 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5FC page=0x5 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6FC page=0x6 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7FC page=0x7 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8FC page=0x8 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9FC page=0x9 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAFC page=0xA offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBFC page=0xB offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCFC page=0xC offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDFC page=0xD offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEFC page=0xE offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFFC page=0xF offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x0FA page=0x0 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1FA page=0x1 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2FA page=0x2 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3FA page=0x3 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4FA page=0x4 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5FA page=0x5 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6FA page=0x6 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7FA page=0x7 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8FA page=0x8 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9FA page=0x9 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAFA page=0xA offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBFA page=0xB offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCFA page=0xC offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDFA page=0xD offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEFA page=0xE offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFFA page=0xF offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x0F8 page=0x0 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1F8 page=0x1 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2F8 page=0x2 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3F8 page=0x3 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4F8 page=0x4 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5F8 page=0x5 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6F8 page=0x6 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7F8 page=0x7 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8F8 page=0x8 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9F8 page=0x9 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAF8 page=0xA offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBF8 page=0xB offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCF8 page=0xC offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDF8 page=0xD offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEF8 page=0xE offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFF8 page=0xF offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x0F6 page=0x0 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1F6 page=0x1 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2F6 page=0x2 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3F6 page=0x3 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4F6 page=0x4 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5F6 page=0x5 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6F6 page=0x6 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7F6 page=0x7 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8F6 page=0x8 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9F6 page=0x9 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAF6 page=0xA offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBF6 page=0xB offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCF6 page=0xC offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDF6 page=0xD offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEF6 page=0xE offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFF6 page=0xF offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- ... 2028 more word writes omitted
|
||||
|
||||
Factory Diffs:
|
||||
- current EEPROM image matches ROM factory/default image
|
||||
|
||||
F400 Shadow Diffs:
|
||||
- F400-F4FF shadow matches ROM factory words or no ROM factory baseline was supplied
|
||||
300
build/emulator-eeprom-loaded-boot.json
Normal file
300
build/emulator-eeprom-loaded-boot.json
Normal file
@@ -0,0 +1,300 @@
|
||||
{
|
||||
"factory_diffs": [],
|
||||
"kind": "emulator_eeprom_snapshot",
|
||||
"records": [
|
||||
{
|
||||
"address": 0,
|
||||
"address_hex": "0x000",
|
||||
"ascii": "..ko....",
|
||||
"bytes_hex": "00 00 6B 6F FE 00 00 00",
|
||||
"is_blank_spaces": false,
|
||||
"page": 0,
|
||||
"page_hex": "0x0",
|
||||
"range_hex": "0x000-0x007",
|
||||
"words_hex": [
|
||||
"0x0000",
|
||||
"0x6B6F",
|
||||
"0xFE00",
|
||||
"0x0000"
|
||||
]
|
||||
},
|
||||
{
|
||||
"address": 256,
|
||||
"address_hex": "0x100",
|
||||
"ascii": " ",
|
||||
"bytes_hex": "20 20 20 20 20 20 20 20",
|
||||
"is_blank_spaces": true,
|
||||
"page": 1,
|
||||
"page_hex": "0x1",
|
||||
"range_hex": "0x100-0x107",
|
||||
"words_hex": [
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020"
|
||||
]
|
||||
},
|
||||
{
|
||||
"address": 512,
|
||||
"address_hex": "0x200",
|
||||
"ascii": " ",
|
||||
"bytes_hex": "20 20 20 20 20 20 20 20",
|
||||
"is_blank_spaces": true,
|
||||
"page": 2,
|
||||
"page_hex": "0x2",
|
||||
"range_hex": "0x200-0x207",
|
||||
"words_hex": [
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020"
|
||||
]
|
||||
},
|
||||
{
|
||||
"address": 768,
|
||||
"address_hex": "0x300",
|
||||
"ascii": " ",
|
||||
"bytes_hex": "20 20 20 20 20 20 20 20",
|
||||
"is_blank_spaces": true,
|
||||
"page": 3,
|
||||
"page_hex": "0x3",
|
||||
"range_hex": "0x300-0x307",
|
||||
"words_hex": [
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020"
|
||||
]
|
||||
},
|
||||
{
|
||||
"address": 1024,
|
||||
"address_hex": "0x400",
|
||||
"ascii": " ",
|
||||
"bytes_hex": "20 20 20 20 20 20 20 20",
|
||||
"is_blank_spaces": true,
|
||||
"page": 4,
|
||||
"page_hex": "0x4",
|
||||
"range_hex": "0x400-0x407",
|
||||
"words_hex": [
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020"
|
||||
]
|
||||
},
|
||||
{
|
||||
"address": 1280,
|
||||
"address_hex": "0x500",
|
||||
"ascii": " ",
|
||||
"bytes_hex": "20 20 20 20 20 20 20 20",
|
||||
"is_blank_spaces": true,
|
||||
"page": 5,
|
||||
"page_hex": "0x5",
|
||||
"range_hex": "0x500-0x507",
|
||||
"words_hex": [
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020"
|
||||
]
|
||||
},
|
||||
{
|
||||
"address": 1536,
|
||||
"address_hex": "0x600",
|
||||
"ascii": " ",
|
||||
"bytes_hex": "20 20 20 20 20 20 20 20",
|
||||
"is_blank_spaces": true,
|
||||
"page": 6,
|
||||
"page_hex": "0x6",
|
||||
"range_hex": "0x600-0x607",
|
||||
"words_hex": [
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020"
|
||||
]
|
||||
},
|
||||
{
|
||||
"address": 1792,
|
||||
"address_hex": "0x700",
|
||||
"ascii": " ",
|
||||
"bytes_hex": "20 20 20 20 20 20 20 20",
|
||||
"is_blank_spaces": true,
|
||||
"page": 7,
|
||||
"page_hex": "0x7",
|
||||
"range_hex": "0x700-0x707",
|
||||
"words_hex": [
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020"
|
||||
]
|
||||
},
|
||||
{
|
||||
"address": 2048,
|
||||
"address_hex": "0x800",
|
||||
"ascii": " ",
|
||||
"bytes_hex": "20 20 20 20 20 20 20 20",
|
||||
"is_blank_spaces": true,
|
||||
"page": 8,
|
||||
"page_hex": "0x8",
|
||||
"range_hex": "0x800-0x807",
|
||||
"words_hex": [
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020"
|
||||
]
|
||||
},
|
||||
{
|
||||
"address": 2304,
|
||||
"address_hex": "0x900",
|
||||
"ascii": " ",
|
||||
"bytes_hex": "20 20 20 20 20 20 20 20",
|
||||
"is_blank_spaces": true,
|
||||
"page": 9,
|
||||
"page_hex": "0x9",
|
||||
"range_hex": "0x900-0x907",
|
||||
"words_hex": [
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020"
|
||||
]
|
||||
},
|
||||
{
|
||||
"address": 2560,
|
||||
"address_hex": "0xA00",
|
||||
"ascii": " ",
|
||||
"bytes_hex": "20 20 20 20 20 20 20 20",
|
||||
"is_blank_spaces": true,
|
||||
"page": 10,
|
||||
"page_hex": "0xA",
|
||||
"range_hex": "0xA00-0xA07",
|
||||
"words_hex": [
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020"
|
||||
]
|
||||
},
|
||||
{
|
||||
"address": 2816,
|
||||
"address_hex": "0xB00",
|
||||
"ascii": " ",
|
||||
"bytes_hex": "20 20 20 20 20 20 20 20",
|
||||
"is_blank_spaces": true,
|
||||
"page": 11,
|
||||
"page_hex": "0xB",
|
||||
"range_hex": "0xB00-0xB07",
|
||||
"words_hex": [
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020"
|
||||
]
|
||||
},
|
||||
{
|
||||
"address": 3072,
|
||||
"address_hex": "0xC00",
|
||||
"ascii": " ",
|
||||
"bytes_hex": "20 20 20 20 20 20 20 20",
|
||||
"is_blank_spaces": true,
|
||||
"page": 12,
|
||||
"page_hex": "0xC",
|
||||
"range_hex": "0xC00-0xC07",
|
||||
"words_hex": [
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020"
|
||||
]
|
||||
},
|
||||
{
|
||||
"address": 3328,
|
||||
"address_hex": "0xD00",
|
||||
"ascii": " ",
|
||||
"bytes_hex": "20 20 20 20 20 20 20 20",
|
||||
"is_blank_spaces": true,
|
||||
"page": 13,
|
||||
"page_hex": "0xD",
|
||||
"range_hex": "0xD00-0xD07",
|
||||
"words_hex": [
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020"
|
||||
]
|
||||
},
|
||||
{
|
||||
"address": 3584,
|
||||
"address_hex": "0xE00",
|
||||
"ascii": " ",
|
||||
"bytes_hex": "20 20 20 20 20 20 20 20",
|
||||
"is_blank_spaces": true,
|
||||
"page": 14,
|
||||
"page_hex": "0xE",
|
||||
"range_hex": "0xE00-0xE07",
|
||||
"words_hex": [
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020"
|
||||
]
|
||||
},
|
||||
{
|
||||
"address": 3840,
|
||||
"address_hex": "0xF00",
|
||||
"ascii": " ",
|
||||
"bytes_hex": "20 20 20 20 20 20 20 20",
|
||||
"is_blank_spaces": true,
|
||||
"page": 15,
|
||||
"page_hex": "0xF",
|
||||
"range_hex": "0xF00-0xF07",
|
||||
"words_hex": [
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020",
|
||||
"0x2020"
|
||||
]
|
||||
}
|
||||
],
|
||||
"shadow_f400": {
|
||||
"diff_count": 1,
|
||||
"diffs": [
|
||||
{
|
||||
"actual_word": 21760,
|
||||
"actual_word_hex": "0x5500",
|
||||
"address": 62634,
|
||||
"address_hex": "H'F4AA",
|
||||
"aligned_offset": 170,
|
||||
"aligned_offset_hex": "0xAA",
|
||||
"expected_word": 32768,
|
||||
"expected_word_hex": "0x8000",
|
||||
"mapped_selectors": [
|
||||
274
|
||||
],
|
||||
"mapped_selectors_hex": [
|
||||
"0x112"
|
||||
],
|
||||
"offset": 170,
|
||||
"offset_hex": "0xAA",
|
||||
"page": 0,
|
||||
"page_hex": "0x0",
|
||||
"record_byte": null,
|
||||
"role": "factory_shadow_offset"
|
||||
}
|
||||
]
|
||||
},
|
||||
"summary": {
|
||||
"factory_diff_word_count": 0,
|
||||
"logical_size": 4096,
|
||||
"logical_size_hex": "0x1000",
|
||||
"record_count": 16,
|
||||
"sha256": "4bed7704e1ea085487ca325c43bd60da75d37b6ae6f8292544e069a8825c64c6",
|
||||
"write_byte_count": 0,
|
||||
"write_word_count": 0
|
||||
},
|
||||
"write_events": [],
|
||||
"write_word_events": []
|
||||
}
|
||||
31
build/emulator-eeprom-loaded-boot.txt
Normal file
31
build/emulator-eeprom-loaded-boot.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
Emulator EEPROM Snapshot
|
||||
|
||||
size=0x1000 sha256=4bed7704e1ea085487ca325c43bd60da75d37b6ae6f8292544e069a8825c64c6
|
||||
writes: bytes=0 words=0 factory_diff_words=0
|
||||
|
||||
Persistent Records:
|
||||
- page 0x0 EEPROM 0x000-0x007 bytes=00 00 6B 6F FE 00 00 00 text='..ko....'
|
||||
- page 0x1 EEPROM 0x100-0x107 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x2 EEPROM 0x200-0x207 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x3 EEPROM 0x300-0x307 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x4 EEPROM 0x400-0x407 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x5 EEPROM 0x500-0x507 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x6 EEPROM 0x600-0x607 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x7 EEPROM 0x700-0x707 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x8 EEPROM 0x800-0x807 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x9 EEPROM 0x900-0x907 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xA EEPROM 0xA00-0xA07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xB EEPROM 0xB00-0xB07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xC EEPROM 0xC00-0xC07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xD EEPROM 0xD00-0xD07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xE EEPROM 0xE00-0xE07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xF EEPROM 0xF00-0xF07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
|
||||
EEPROM Word Writes:
|
||||
- none since EEPROM setup/load
|
||||
|
||||
Factory Diffs:
|
||||
- current EEPROM image matches ROM factory/default image
|
||||
|
||||
F400 Shadow Diffs:
|
||||
- H'F4AA offset=0xAA expected=0x8000 actual=0x5500 (factory_shadow_offset; selectors=0x112)
|
||||
2951
build/panel_button_trace.json
Normal file
2951
build/panel_button_trace.json
Normal file
File diff suppressed because it is too large
Load Diff
74
build/panel_button_trace.md
Normal file
74
build/panel_button_trace.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# PT2 Known Button ROM Trace
|
||||
|
||||
This report follows the panel button edge path from the serial-visible reports back into the ROM input scanner.
|
||||
The key table is the indirect handler table at `H'2706`, used by `loc_1C0E` after byte-level panel input changes are detected.
|
||||
|
||||
## Known Anchors
|
||||
|
||||
### CAM POWER
|
||||
|
||||
- Emitted selector: `0x0007`
|
||||
- Handler: `H'1F40`
|
||||
- Edge source: `F105 -> F6D4` via `F6F2.4`
|
||||
- Trigger bit: `F6D4.3`
|
||||
- Table slot: `H'274C` -> `H'1F40`
|
||||
- Current-level tests: F6D4.3
|
||||
- State writes: E80E
|
||||
|
||||
### IRIS/M.BLACK LINK
|
||||
|
||||
- Emitted selector: `0x0013`
|
||||
- Handler: `H'200E`
|
||||
- Edge source: `F006 -> F6DB` via `F6F3.3`
|
||||
- Trigger bit: `F6DB.7`
|
||||
- Table slot: `H'27C4` -> `H'200E`
|
||||
- Current-level tests: F6DB.7
|
||||
- State writes: E826
|
||||
|
||||
### CALL
|
||||
|
||||
- Emitted selector: `0x0015`
|
||||
- Handler: `H'20A1`
|
||||
- Edge source: `F006 -> F6DB` via `F6F3.3`
|
||||
- Trigger bit: `F6DB.5`
|
||||
- Table slot: `H'27C0` -> `H'20A1`
|
||||
- Current-level tests: F6DB.5
|
||||
- State writes: E82A
|
||||
|
||||
## Button Matrix Entries With Serial Reports
|
||||
|
||||
| Source | Shadow bit | Dirty | Handler | Selector(s) | State writes |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `F105` | `F6D4.6` | `F6F2.4` | `H'2048` | `0x006B` | `E8D6` |
|
||||
| `F105` | `F6D4.3` | `F6F2.4` | `H'1F40` | `0x0007` | `E80E` |
|
||||
| `F105` | `F6D4.2` | `F6F2.4` | `H'1EDE` | `0x0017`, `0x0018` | `E82E`, `E830` |
|
||||
| `F105` | `F6D4.1` | `F6F2.4` | `H'1EA9` | `0x00F8` | `E9F0` |
|
||||
| `F105` | `F6D4.0` | `F6F2.4` | `H'1E20` | `0x00B7`, `0x00C4`, `0x00C6`, `0x0097` | `E96E`, `E988`, `E98C`, `E92E` |
|
||||
| `F106` | `F6D3.7` | `F6F2.3` | `H'1DCE` | `0x0096` | `E92C` |
|
||||
| `F106` | `F6D3.6` | `F6F2.3` | `H'1D87` | `0x0097` | `E92E` |
|
||||
| `F106` | `F6D3.5` | `F6F2.3` | `H'1D56` | `0x001A` | `E834` |
|
||||
| `F106` | `F6D3.4` | `F6F2.3` | `H'1D25` | `0x001A` | `E834` |
|
||||
| `F106` | `F6D3.3` | `F6F2.3` | `H'1CF4` | `0x001A` | `E834` |
|
||||
| `F106` | `F6D3.2` | `F6F2.3` | `H'1CCE` | `0x001A` | `E834` |
|
||||
| `F106` | `F6D3.1` | `F6F2.3` | `H'1CB2` | `0x001A` | `E834` |
|
||||
| `F109` | `F6D0.7` | `F6F2.0` | `H'24E8` | `0x008F` | `E91E` |
|
||||
| `F109` | `F6D0.6` | `F6F2.0` | `H'252E` | `0x008F` | `E91E` |
|
||||
| `F109` | `F6D0.3` | `F6F2.0` | `H'24A9` | `0x0083` | `E906` |
|
||||
| `F109` | `F6D0.2` | `F6F2.0` | `H'2408` | `0x0083` | `E906` |
|
||||
| `F109` | `F6D0.1` | `F6F2.0` | `H'2390` | `0x0083` | `E906` |
|
||||
| `F005` | `F6DC.7` | `F6F3.4` | `H'20F1` | `0x00B9` | `E972` |
|
||||
| `F005` | `F6DC.5` | `F6F3.4` | `H'2204` | `0x0093` | `E926` |
|
||||
| `F005` | `F6DC.4` | `F6F3.4` | `H'226D` | `0x0093` | `E926` |
|
||||
| `F005` | `F6DC.3` | `F6F3.4` | `H'22A6` | `0x0093` | `E926` |
|
||||
| `F005` | `F6DC.1` | `F6F3.4` | `H'22FC` | `0x0093` | `E926` |
|
||||
| `F005` | `F6DC.0` | `F6F3.4` | `H'2326` | `0x0093` | `E926` |
|
||||
| `F006` | `F6DB.7` | `F6F3.3` | `H'200E` | `0x0013` | `E826` |
|
||||
| `F006` | `F6DB.5` | `F6F3.3` | `H'20A1` | `0x0015` | `E82A` |
|
||||
| `F006` | `F6DB.3` | `F6F3.3` | `H'20BE` | `0x009A` | `E934` |
|
||||
|
||||
## Practical Read
|
||||
|
||||
- CALL and CAM POWER do share the general panel edge path with many other buttons.
|
||||
- The shared path is: panel byte snapshot -> shadow byte -> dirty bit -> `loc_1C0E` jump table -> handler -> `loc_3E54` report.
|
||||
- Other buttons diverge in their handlers: many require `F731/F730/F791` session/menu gates, mutate page state, or emit different selectors.
|
||||
- Some table entries are `H'1C25`, an immediate `RTS`, so those physical matrix positions are intentionally ignored in this firmware context.
|
||||
191
build/pin50-p77-high-blank-eeprom.txt
Normal file
191
build/pin50-p77-high-blank-eeprom.txt
Normal file
@@ -0,0 +1,191 @@
|
||||
Emulator EEPROM Snapshot
|
||||
|
||||
size=0x1000 sha256=f47a8ec3e9aff2318d896942282ad4fe37d6391c82914f54a5da8a37de1300c6
|
||||
writes: bytes=0 words=0 factory_diff_words=2048
|
||||
|
||||
Persistent Records:
|
||||
- page 0x0 EEPROM 0x000-0x007 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0x1 EEPROM 0x100-0x107 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0x2 EEPROM 0x200-0x207 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0x3 EEPROM 0x300-0x307 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0x4 EEPROM 0x400-0x407 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0x5 EEPROM 0x500-0x507 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0x6 EEPROM 0x600-0x607 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0x7 EEPROM 0x700-0x707 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0x8 EEPROM 0x800-0x807 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0x9 EEPROM 0x900-0x907 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0xA EEPROM 0xA00-0xA07 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0xB EEPROM 0xB00-0xB07 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0xC EEPROM 0xC00-0xC07 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0xD EEPROM 0xD00-0xD07 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0xE EEPROM 0xE00-0xE07 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0xF EEPROM 0xF00-0xF07 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
|
||||
EEPROM Word Writes:
|
||||
- none since EEPROM setup/load
|
||||
|
||||
Factory Diffs:
|
||||
- 0x000 page=0x0 offset=0x00 expected=0x0000 actual=0xFFFF (record_header_or_label)
|
||||
- 0x002 page=0x0 offset=0x02 expected=0x6B6F actual=0xFFFF (record_header_or_label)
|
||||
- 0x004 page=0x0 offset=0x04 expected=0xFE00 actual=0xFFFF (record_header_or_label)
|
||||
- 0x006 page=0x0 offset=0x06 expected=0x0000 actual=0xFFFF (record_header_or_label)
|
||||
- 0x008 page=0x0 offset=0x08 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x004)
|
||||
- 0x00A page=0x0 offset=0x0A expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x012)
|
||||
- 0x00C page=0x0 offset=0x0C expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x013)
|
||||
- 0x00E page=0x0 offset=0x0E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x017)
|
||||
- 0x010 page=0x0 offset=0x10 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x018)
|
||||
- 0x012 page=0x0 offset=0x12 expected=0x0808 actual=0xFFFF (factory_shadow_offset; selectors=0x01A)
|
||||
- 0x014 page=0x0 offset=0x14 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x01F)
|
||||
- 0x016 page=0x0 offset=0x16 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x020)
|
||||
- 0x018 page=0x0 offset=0x18 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x023)
|
||||
- 0x01A page=0x0 offset=0x1A expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x037)
|
||||
- 0x01C page=0x0 offset=0x1C expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x038)
|
||||
- 0x01E page=0x0 offset=0x1E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x080)
|
||||
- 0x020 page=0x0 offset=0x20 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x081)
|
||||
- 0x022 page=0x0 offset=0x22 expected=0x0020 actual=0xFFFF (factory_shadow_offset; selectors=0x083)
|
||||
- 0x024 page=0x0 offset=0x24 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x088)
|
||||
- 0x026 page=0x0 offset=0x26 expected=0x0400 actual=0xFFFF (factory_shadow_offset; selectors=0x089)
|
||||
- 0x028 page=0x0 offset=0x28 expected=0x0800 actual=0xFFFF (factory_shadow_offset; selectors=0x08B)
|
||||
- 0x02A page=0x0 offset=0x2A expected=0x0040 actual=0xFFFF (factory_shadow_offset; selectors=0x08D)
|
||||
- 0x02C page=0x0 offset=0x2C expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x08F)
|
||||
- 0x02E page=0x0 offset=0x2E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x091)
|
||||
- 0x030 page=0x0 offset=0x30 expected=0xFF80 actual=0xFFFF (factory_shadow_offset; selectors=0x092)
|
||||
- 0x032 page=0x0 offset=0x32 expected=0x4040 actual=0xFFFF (factory_shadow_offset; selectors=0x093)
|
||||
- 0x034 page=0x0 offset=0x34 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x095)
|
||||
- 0x036 page=0x0 offset=0x36 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x098)
|
||||
- 0x038 page=0x0 offset=0x38 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x09A)
|
||||
- 0x03A page=0x0 offset=0x3A expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x09D)
|
||||
- 0x03C page=0x0 offset=0x3C expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x09E)
|
||||
- 0x03E page=0x0 offset=0x3E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x09F)
|
||||
- 0x040 page=0x0 offset=0x40 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A3)
|
||||
- 0x042 page=0x0 offset=0x42 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A4)
|
||||
- 0x044 page=0x0 offset=0x44 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A5)
|
||||
- 0x046 page=0x0 offset=0x46 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A6)
|
||||
- 0x048 page=0x0 offset=0x48 expected=0xF000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A7)
|
||||
- 0x04A page=0x0 offset=0x4A expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A9)
|
||||
- 0x04C page=0x0 offset=0x4C expected=0x2000 actual=0xFFFF (factory_shadow_offset; selectors=0x0AA)
|
||||
- 0x04E page=0x0 offset=0x4E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0AC)
|
||||
- 0x050 page=0x0 offset=0x50 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0AD)
|
||||
- 0x052 page=0x0 offset=0x52 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0AE)
|
||||
- 0x054 page=0x0 offset=0x54 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0AF)
|
||||
- 0x056 page=0x0 offset=0x56 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B0)
|
||||
- 0x058 page=0x0 offset=0x58 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B2)
|
||||
- 0x05A page=0x0 offset=0x5A expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B3)
|
||||
- 0x05C page=0x0 offset=0x5C expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B4)
|
||||
- 0x05E page=0x0 offset=0x5E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B6)
|
||||
- 0x060 page=0x0 offset=0x60 expected=0xF800 actual=0xFFFF (factory_shadow_offset; selectors=0x0B7)
|
||||
- 0x062 page=0x0 offset=0x62 expected=0x4000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B9)
|
||||
- 0x064 page=0x0 offset=0x64 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0BC)
|
||||
- 0x066 page=0x0 offset=0x66 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0BD)
|
||||
- 0x068 page=0x0 offset=0x68 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C0)
|
||||
- 0x06A page=0x0 offset=0x6A expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C1)
|
||||
- 0x06C page=0x0 offset=0x6C expected=0x4000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C3)
|
||||
- 0x06E page=0x0 offset=0x6E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C4)
|
||||
- 0x070 page=0x0 offset=0x70 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C5)
|
||||
- 0x072 page=0x0 offset=0x72 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C6)
|
||||
- 0x074 page=0x0 offset=0x74 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C7)
|
||||
- 0x076 page=0x0 offset=0x76 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C8)
|
||||
- 0x078 page=0x0 offset=0x78 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C9)
|
||||
- 0x07A page=0x0 offset=0x7A expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0CA)
|
||||
- 0x07C page=0x0 offset=0x7C expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0CB)
|
||||
- 0x07E page=0x0 offset=0x7E expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0CC)
|
||||
- 0x080 page=0x0 offset=0x80 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0CD)
|
||||
- 0x082 page=0x0 offset=0x82 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D4)
|
||||
- 0x084 page=0x0 offset=0x84 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D5)
|
||||
- 0x086 page=0x0 offset=0x86 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D6)
|
||||
- 0x088 page=0x0 offset=0x88 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D7)
|
||||
- 0x08A page=0x0 offset=0x8A expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D8)
|
||||
- 0x08C page=0x0 offset=0x8C expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D9)
|
||||
- 0x08E page=0x0 offset=0x8E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0DA)
|
||||
- 0x090 page=0x0 offset=0x90 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0F6)
|
||||
- 0x092 page=0x0 offset=0x92 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0F9)
|
||||
- 0x094 page=0x0 offset=0x94 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FA)
|
||||
- 0x096 page=0x0 offset=0x96 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FB)
|
||||
- 0x098 page=0x0 offset=0x98 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FC)
|
||||
- 0x09A page=0x0 offset=0x9A expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FD)
|
||||
- 0x09C page=0x0 offset=0x9C expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FE)
|
||||
- 0x09E page=0x0 offset=0x9E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FF)
|
||||
- ... 1968 more factory diffs omitted
|
||||
|
||||
F400 Shadow Diffs:
|
||||
- H'F400 offset=0x00 expected=0x0000 actual=0xFFFF (record_header_or_label)
|
||||
- H'F402 offset=0x02 expected=0x6B6F actual=0xFFFF (record_header_or_label)
|
||||
- H'F404 offset=0x04 expected=0xFE00 actual=0xFFFF (record_header_or_label)
|
||||
- H'F406 offset=0x06 expected=0x0000 actual=0xFFFF (record_header_or_label)
|
||||
- H'F408 offset=0x08 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x004)
|
||||
- H'F40A offset=0x0A expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x012)
|
||||
- H'F40C offset=0x0C expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x013)
|
||||
- H'F40E offset=0x0E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x017)
|
||||
- H'F410 offset=0x10 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x018)
|
||||
- H'F412 offset=0x12 expected=0x0808 actual=0xFFFF (factory_shadow_offset; selectors=0x01A)
|
||||
- H'F414 offset=0x14 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x01F)
|
||||
- H'F416 offset=0x16 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x020)
|
||||
- H'F418 offset=0x18 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x023)
|
||||
- H'F41A offset=0x1A expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x037)
|
||||
- H'F41C offset=0x1C expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x038)
|
||||
- H'F41E offset=0x1E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x080)
|
||||
- H'F420 offset=0x20 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x081)
|
||||
- H'F422 offset=0x22 expected=0x0020 actual=0xFFFF (factory_shadow_offset; selectors=0x083)
|
||||
- H'F424 offset=0x24 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x088)
|
||||
- H'F426 offset=0x26 expected=0x0400 actual=0xFFFF (factory_shadow_offset; selectors=0x089)
|
||||
- H'F428 offset=0x28 expected=0x0800 actual=0xFFFF (factory_shadow_offset; selectors=0x08B)
|
||||
- H'F42A offset=0x2A expected=0x0040 actual=0xFFFF (factory_shadow_offset; selectors=0x08D)
|
||||
- H'F42C offset=0x2C expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x08F)
|
||||
- H'F42E offset=0x2E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x091)
|
||||
- H'F430 offset=0x30 expected=0xFF80 actual=0xFFFF (factory_shadow_offset; selectors=0x092)
|
||||
- H'F432 offset=0x32 expected=0x4040 actual=0xFFFF (factory_shadow_offset; selectors=0x093)
|
||||
- H'F434 offset=0x34 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x095)
|
||||
- H'F436 offset=0x36 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x098)
|
||||
- H'F438 offset=0x38 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x09A)
|
||||
- H'F43A offset=0x3A expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x09D)
|
||||
- H'F43C offset=0x3C expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x09E)
|
||||
- H'F43E offset=0x3E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x09F)
|
||||
- H'F440 offset=0x40 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A3)
|
||||
- H'F442 offset=0x42 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A4)
|
||||
- H'F444 offset=0x44 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A5)
|
||||
- H'F446 offset=0x46 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A6)
|
||||
- H'F448 offset=0x48 expected=0xF000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A7)
|
||||
- H'F44A offset=0x4A expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A9)
|
||||
- H'F44C offset=0x4C expected=0x2000 actual=0xFFFF (factory_shadow_offset; selectors=0x0AA)
|
||||
- H'F44E offset=0x4E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0AC)
|
||||
- H'F450 offset=0x50 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0AD)
|
||||
- H'F452 offset=0x52 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0AE)
|
||||
- H'F454 offset=0x54 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0AF)
|
||||
- H'F456 offset=0x56 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B0)
|
||||
- H'F458 offset=0x58 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B2)
|
||||
- H'F45A offset=0x5A expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B3)
|
||||
- H'F45C offset=0x5C expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B4)
|
||||
- H'F45E offset=0x5E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B6)
|
||||
- H'F460 offset=0x60 expected=0xF800 actual=0xFFFF (factory_shadow_offset; selectors=0x0B7)
|
||||
- H'F462 offset=0x62 expected=0x4000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B9)
|
||||
- H'F464 offset=0x64 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0BC)
|
||||
- H'F466 offset=0x66 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0BD)
|
||||
- H'F468 offset=0x68 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C0)
|
||||
- H'F46A offset=0x6A expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C1)
|
||||
- H'F46C offset=0x6C expected=0x4000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C3)
|
||||
- H'F46E offset=0x6E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C4)
|
||||
- H'F470 offset=0x70 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C5)
|
||||
- H'F472 offset=0x72 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C6)
|
||||
- H'F474 offset=0x74 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C7)
|
||||
- H'F476 offset=0x76 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C8)
|
||||
- H'F478 offset=0x78 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C9)
|
||||
- H'F47A offset=0x7A expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0CA)
|
||||
- H'F47C offset=0x7C expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0CB)
|
||||
- H'F47E offset=0x7E expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0CC)
|
||||
- H'F480 offset=0x80 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0CD)
|
||||
- H'F482 offset=0x82 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D4)
|
||||
- H'F484 offset=0x84 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D5)
|
||||
- H'F486 offset=0x86 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D6)
|
||||
- H'F488 offset=0x88 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D7)
|
||||
- H'F48A offset=0x8A expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D8)
|
||||
- H'F48C offset=0x8C expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D9)
|
||||
- H'F48E offset=0x8E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0DA)
|
||||
- H'F490 offset=0x90 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0F6)
|
||||
- H'F492 offset=0x92 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0F9)
|
||||
- H'F494 offset=0x94 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FA)
|
||||
- H'F496 offset=0x96 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FB)
|
||||
- H'F498 offset=0x98 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FC)
|
||||
- H'F49A offset=0x9A expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FD)
|
||||
- H'F49C offset=0x9C expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FE)
|
||||
- H'F49E offset=0x9E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FF)
|
||||
- ... 47 more shadow diffs omitted
|
||||
111
build/pin50-p77-high-fast-blank-eeprom.txt
Normal file
111
build/pin50-p77-high-fast-blank-eeprom.txt
Normal file
@@ -0,0 +1,111 @@
|
||||
Emulator EEPROM Snapshot
|
||||
|
||||
size=0x1000 sha256=4bed7704e1ea085487ca325c43bd60da75d37b6ae6f8292544e069a8825c64c6
|
||||
writes: bytes=4216 words=2108 factory_diff_words=0
|
||||
|
||||
Persistent Records:
|
||||
- page 0x0 EEPROM 0x000-0x007 bytes=00 00 6B 6F FE 00 00 00 text='..ko....'
|
||||
- page 0x1 EEPROM 0x100-0x107 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x2 EEPROM 0x200-0x207 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x3 EEPROM 0x300-0x307 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x4 EEPROM 0x400-0x407 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x5 EEPROM 0x500-0x507 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x6 EEPROM 0x600-0x607 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x7 EEPROM 0x700-0x707 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x8 EEPROM 0x800-0x807 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x9 EEPROM 0x900-0x907 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xA EEPROM 0xA00-0xA07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xB EEPROM 0xB00-0xB07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xC EEPROM 0xC00-0xC07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xD EEPROM 0xD00-0xD07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xE EEPROM 0xE00-0xE07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xF EEPROM 0xF00-0xF07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
|
||||
EEPROM Word Writes:
|
||||
- 0x0FE page=0x0 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1FE page=0x1 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2FE page=0x2 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3FE page=0x3 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4FE page=0x4 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5FE page=0x5 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6FE page=0x6 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7FE page=0x7 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8FE page=0x8 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9FE page=0x9 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAFE page=0xA offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBFE page=0xB offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCFE page=0xC offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDFE page=0xD offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEFE page=0xE offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFFE page=0xF offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x0FC page=0x0 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1FC page=0x1 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2FC page=0x2 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3FC page=0x3 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4FC page=0x4 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5FC page=0x5 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6FC page=0x6 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7FC page=0x7 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8FC page=0x8 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9FC page=0x9 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAFC page=0xA offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBFC page=0xB offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCFC page=0xC offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDFC page=0xD offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEFC page=0xE offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFFC page=0xF offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x0FA page=0x0 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1FA page=0x1 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2FA page=0x2 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3FA page=0x3 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4FA page=0x4 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5FA page=0x5 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6FA page=0x6 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7FA page=0x7 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8FA page=0x8 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9FA page=0x9 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAFA page=0xA offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBFA page=0xB offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCFA page=0xC offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDFA page=0xD offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEFA page=0xE offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFFA page=0xF offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x0F8 page=0x0 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1F8 page=0x1 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2F8 page=0x2 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3F8 page=0x3 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4F8 page=0x4 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5F8 page=0x5 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6F8 page=0x6 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7F8 page=0x7 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8F8 page=0x8 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9F8 page=0x9 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAF8 page=0xA offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBF8 page=0xB offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCF8 page=0xC offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDF8 page=0xD offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEF8 page=0xE offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFF8 page=0xF offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x0F6 page=0x0 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1F6 page=0x1 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2F6 page=0x2 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3F6 page=0x3 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4F6 page=0x4 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5F6 page=0x5 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6F6 page=0x6 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7F6 page=0x7 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8F6 page=0x8 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9F6 page=0x9 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAF6 page=0xA offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBF6 page=0xB offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCF6 page=0xC offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDF6 page=0xD offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEF6 page=0xE offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFF6 page=0xF offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- ... 2028 more word writes omitted
|
||||
|
||||
Factory Diffs:
|
||||
- current EEPROM image matches ROM factory/default image
|
||||
|
||||
F400 Shadow Diffs:
|
||||
- F400-F4FF shadow matches ROM factory words or no ROM factory baseline was supplied
|
||||
31
build/pin50-p77-high-fast-factory-eeprom.txt
Normal file
31
build/pin50-p77-high-fast-factory-eeprom.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
Emulator EEPROM Snapshot
|
||||
|
||||
size=0x1000 sha256=4bed7704e1ea085487ca325c43bd60da75d37b6ae6f8292544e069a8825c64c6
|
||||
writes: bytes=0 words=0 factory_diff_words=0
|
||||
|
||||
Persistent Records:
|
||||
- page 0x0 EEPROM 0x000-0x007 bytes=00 00 6B 6F FE 00 00 00 text='..ko....'
|
||||
- page 0x1 EEPROM 0x100-0x107 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x2 EEPROM 0x200-0x207 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x3 EEPROM 0x300-0x307 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x4 EEPROM 0x400-0x407 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x5 EEPROM 0x500-0x507 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x6 EEPROM 0x600-0x607 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x7 EEPROM 0x700-0x707 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x8 EEPROM 0x800-0x807 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x9 EEPROM 0x900-0x907 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xA EEPROM 0xA00-0xA07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xB EEPROM 0xB00-0xB07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xC EEPROM 0xC00-0xC07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xD EEPROM 0xD00-0xD07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xE EEPROM 0xE00-0xE07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xF EEPROM 0xF00-0xF07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
|
||||
EEPROM Word Writes:
|
||||
- none since EEPROM setup/load
|
||||
|
||||
Factory Diffs:
|
||||
- current EEPROM image matches ROM factory/default image
|
||||
|
||||
F400 Shadow Diffs:
|
||||
- H'F4AA offset=0xAA expected=0x8000 actual=0x5500 (factory_shadow_offset; selectors=0x112)
|
||||
191
build/pin50-p77-low-blank-eeprom.txt
Normal file
191
build/pin50-p77-low-blank-eeprom.txt
Normal file
@@ -0,0 +1,191 @@
|
||||
Emulator EEPROM Snapshot
|
||||
|
||||
size=0x1000 sha256=f47a8ec3e9aff2318d896942282ad4fe37d6391c82914f54a5da8a37de1300c6
|
||||
writes: bytes=0 words=0 factory_diff_words=2048
|
||||
|
||||
Persistent Records:
|
||||
- page 0x0 EEPROM 0x000-0x007 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0x1 EEPROM 0x100-0x107 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0x2 EEPROM 0x200-0x207 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0x3 EEPROM 0x300-0x307 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0x4 EEPROM 0x400-0x407 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0x5 EEPROM 0x500-0x507 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0x6 EEPROM 0x600-0x607 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0x7 EEPROM 0x700-0x707 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0x8 EEPROM 0x800-0x807 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0x9 EEPROM 0x900-0x907 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0xA EEPROM 0xA00-0xA07 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0xB EEPROM 0xB00-0xB07 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0xC EEPROM 0xC00-0xC07 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0xD EEPROM 0xD00-0xD07 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0xE EEPROM 0xE00-0xE07 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
- page 0xF EEPROM 0xF00-0xF07 bytes=FF FF FF FF FF FF FF FF text='........'
|
||||
|
||||
EEPROM Word Writes:
|
||||
- none since EEPROM setup/load
|
||||
|
||||
Factory Diffs:
|
||||
- 0x000 page=0x0 offset=0x00 expected=0x0000 actual=0xFFFF (record_header_or_label)
|
||||
- 0x002 page=0x0 offset=0x02 expected=0x6B6F actual=0xFFFF (record_header_or_label)
|
||||
- 0x004 page=0x0 offset=0x04 expected=0xFE00 actual=0xFFFF (record_header_or_label)
|
||||
- 0x006 page=0x0 offset=0x06 expected=0x0000 actual=0xFFFF (record_header_or_label)
|
||||
- 0x008 page=0x0 offset=0x08 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x004)
|
||||
- 0x00A page=0x0 offset=0x0A expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x012)
|
||||
- 0x00C page=0x0 offset=0x0C expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x013)
|
||||
- 0x00E page=0x0 offset=0x0E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x017)
|
||||
- 0x010 page=0x0 offset=0x10 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x018)
|
||||
- 0x012 page=0x0 offset=0x12 expected=0x0808 actual=0xFFFF (factory_shadow_offset; selectors=0x01A)
|
||||
- 0x014 page=0x0 offset=0x14 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x01F)
|
||||
- 0x016 page=0x0 offset=0x16 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x020)
|
||||
- 0x018 page=0x0 offset=0x18 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x023)
|
||||
- 0x01A page=0x0 offset=0x1A expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x037)
|
||||
- 0x01C page=0x0 offset=0x1C expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x038)
|
||||
- 0x01E page=0x0 offset=0x1E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x080)
|
||||
- 0x020 page=0x0 offset=0x20 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x081)
|
||||
- 0x022 page=0x0 offset=0x22 expected=0x0020 actual=0xFFFF (factory_shadow_offset; selectors=0x083)
|
||||
- 0x024 page=0x0 offset=0x24 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x088)
|
||||
- 0x026 page=0x0 offset=0x26 expected=0x0400 actual=0xFFFF (factory_shadow_offset; selectors=0x089)
|
||||
- 0x028 page=0x0 offset=0x28 expected=0x0800 actual=0xFFFF (factory_shadow_offset; selectors=0x08B)
|
||||
- 0x02A page=0x0 offset=0x2A expected=0x0040 actual=0xFFFF (factory_shadow_offset; selectors=0x08D)
|
||||
- 0x02C page=0x0 offset=0x2C expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x08F)
|
||||
- 0x02E page=0x0 offset=0x2E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x091)
|
||||
- 0x030 page=0x0 offset=0x30 expected=0xFF80 actual=0xFFFF (factory_shadow_offset; selectors=0x092)
|
||||
- 0x032 page=0x0 offset=0x32 expected=0x4040 actual=0xFFFF (factory_shadow_offset; selectors=0x093)
|
||||
- 0x034 page=0x0 offset=0x34 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x095)
|
||||
- 0x036 page=0x0 offset=0x36 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x098)
|
||||
- 0x038 page=0x0 offset=0x38 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x09A)
|
||||
- 0x03A page=0x0 offset=0x3A expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x09D)
|
||||
- 0x03C page=0x0 offset=0x3C expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x09E)
|
||||
- 0x03E page=0x0 offset=0x3E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x09F)
|
||||
- 0x040 page=0x0 offset=0x40 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A3)
|
||||
- 0x042 page=0x0 offset=0x42 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A4)
|
||||
- 0x044 page=0x0 offset=0x44 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A5)
|
||||
- 0x046 page=0x0 offset=0x46 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A6)
|
||||
- 0x048 page=0x0 offset=0x48 expected=0xF000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A7)
|
||||
- 0x04A page=0x0 offset=0x4A expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A9)
|
||||
- 0x04C page=0x0 offset=0x4C expected=0x2000 actual=0xFFFF (factory_shadow_offset; selectors=0x0AA)
|
||||
- 0x04E page=0x0 offset=0x4E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0AC)
|
||||
- 0x050 page=0x0 offset=0x50 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0AD)
|
||||
- 0x052 page=0x0 offset=0x52 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0AE)
|
||||
- 0x054 page=0x0 offset=0x54 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0AF)
|
||||
- 0x056 page=0x0 offset=0x56 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B0)
|
||||
- 0x058 page=0x0 offset=0x58 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B2)
|
||||
- 0x05A page=0x0 offset=0x5A expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B3)
|
||||
- 0x05C page=0x0 offset=0x5C expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B4)
|
||||
- 0x05E page=0x0 offset=0x5E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B6)
|
||||
- 0x060 page=0x0 offset=0x60 expected=0xF800 actual=0xFFFF (factory_shadow_offset; selectors=0x0B7)
|
||||
- 0x062 page=0x0 offset=0x62 expected=0x4000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B9)
|
||||
- 0x064 page=0x0 offset=0x64 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0BC)
|
||||
- 0x066 page=0x0 offset=0x66 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0BD)
|
||||
- 0x068 page=0x0 offset=0x68 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C0)
|
||||
- 0x06A page=0x0 offset=0x6A expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C1)
|
||||
- 0x06C page=0x0 offset=0x6C expected=0x4000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C3)
|
||||
- 0x06E page=0x0 offset=0x6E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C4)
|
||||
- 0x070 page=0x0 offset=0x70 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C5)
|
||||
- 0x072 page=0x0 offset=0x72 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C6)
|
||||
- 0x074 page=0x0 offset=0x74 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C7)
|
||||
- 0x076 page=0x0 offset=0x76 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C8)
|
||||
- 0x078 page=0x0 offset=0x78 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C9)
|
||||
- 0x07A page=0x0 offset=0x7A expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0CA)
|
||||
- 0x07C page=0x0 offset=0x7C expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0CB)
|
||||
- 0x07E page=0x0 offset=0x7E expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0CC)
|
||||
- 0x080 page=0x0 offset=0x80 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0CD)
|
||||
- 0x082 page=0x0 offset=0x82 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D4)
|
||||
- 0x084 page=0x0 offset=0x84 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D5)
|
||||
- 0x086 page=0x0 offset=0x86 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D6)
|
||||
- 0x088 page=0x0 offset=0x88 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D7)
|
||||
- 0x08A page=0x0 offset=0x8A expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D8)
|
||||
- 0x08C page=0x0 offset=0x8C expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D9)
|
||||
- 0x08E page=0x0 offset=0x8E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0DA)
|
||||
- 0x090 page=0x0 offset=0x90 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0F6)
|
||||
- 0x092 page=0x0 offset=0x92 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0F9)
|
||||
- 0x094 page=0x0 offset=0x94 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FA)
|
||||
- 0x096 page=0x0 offset=0x96 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FB)
|
||||
- 0x098 page=0x0 offset=0x98 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FC)
|
||||
- 0x09A page=0x0 offset=0x9A expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FD)
|
||||
- 0x09C page=0x0 offset=0x9C expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FE)
|
||||
- 0x09E page=0x0 offset=0x9E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FF)
|
||||
- ... 1968 more factory diffs omitted
|
||||
|
||||
F400 Shadow Diffs:
|
||||
- H'F400 offset=0x00 expected=0x0000 actual=0xFFFF (record_header_or_label)
|
||||
- H'F402 offset=0x02 expected=0x6B6F actual=0xFFFF (record_header_or_label)
|
||||
- H'F404 offset=0x04 expected=0xFE00 actual=0xFFFF (record_header_or_label)
|
||||
- H'F406 offset=0x06 expected=0x0000 actual=0xFFFF (record_header_or_label)
|
||||
- H'F408 offset=0x08 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x004)
|
||||
- H'F40A offset=0x0A expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x012)
|
||||
- H'F40C offset=0x0C expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x013)
|
||||
- H'F40E offset=0x0E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x017)
|
||||
- H'F410 offset=0x10 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x018)
|
||||
- H'F412 offset=0x12 expected=0x0808 actual=0xFFFF (factory_shadow_offset; selectors=0x01A)
|
||||
- H'F414 offset=0x14 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x01F)
|
||||
- H'F416 offset=0x16 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x020)
|
||||
- H'F418 offset=0x18 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x023)
|
||||
- H'F41A offset=0x1A expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x037)
|
||||
- H'F41C offset=0x1C expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x038)
|
||||
- H'F41E offset=0x1E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x080)
|
||||
- H'F420 offset=0x20 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x081)
|
||||
- H'F422 offset=0x22 expected=0x0020 actual=0xFFFF (factory_shadow_offset; selectors=0x083)
|
||||
- H'F424 offset=0x24 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x088)
|
||||
- H'F426 offset=0x26 expected=0x0400 actual=0xFFFF (factory_shadow_offset; selectors=0x089)
|
||||
- H'F428 offset=0x28 expected=0x0800 actual=0xFFFF (factory_shadow_offset; selectors=0x08B)
|
||||
- H'F42A offset=0x2A expected=0x0040 actual=0xFFFF (factory_shadow_offset; selectors=0x08D)
|
||||
- H'F42C offset=0x2C expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x08F)
|
||||
- H'F42E offset=0x2E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x091)
|
||||
- H'F430 offset=0x30 expected=0xFF80 actual=0xFFFF (factory_shadow_offset; selectors=0x092)
|
||||
- H'F432 offset=0x32 expected=0x4040 actual=0xFFFF (factory_shadow_offset; selectors=0x093)
|
||||
- H'F434 offset=0x34 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x095)
|
||||
- H'F436 offset=0x36 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x098)
|
||||
- H'F438 offset=0x38 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x09A)
|
||||
- H'F43A offset=0x3A expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x09D)
|
||||
- H'F43C offset=0x3C expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x09E)
|
||||
- H'F43E offset=0x3E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x09F)
|
||||
- H'F440 offset=0x40 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A3)
|
||||
- H'F442 offset=0x42 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A4)
|
||||
- H'F444 offset=0x44 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A5)
|
||||
- H'F446 offset=0x46 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A6)
|
||||
- H'F448 offset=0x48 expected=0xF000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A7)
|
||||
- H'F44A offset=0x4A expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0A9)
|
||||
- H'F44C offset=0x4C expected=0x2000 actual=0xFFFF (factory_shadow_offset; selectors=0x0AA)
|
||||
- H'F44E offset=0x4E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0AC)
|
||||
- H'F450 offset=0x50 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0AD)
|
||||
- H'F452 offset=0x52 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0AE)
|
||||
- H'F454 offset=0x54 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0AF)
|
||||
- H'F456 offset=0x56 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B0)
|
||||
- H'F458 offset=0x58 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B2)
|
||||
- H'F45A offset=0x5A expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B3)
|
||||
- H'F45C offset=0x5C expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B4)
|
||||
- H'F45E offset=0x5E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B6)
|
||||
- H'F460 offset=0x60 expected=0xF800 actual=0xFFFF (factory_shadow_offset; selectors=0x0B7)
|
||||
- H'F462 offset=0x62 expected=0x4000 actual=0xFFFF (factory_shadow_offset; selectors=0x0B9)
|
||||
- H'F464 offset=0x64 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0BC)
|
||||
- H'F466 offset=0x66 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0BD)
|
||||
- H'F468 offset=0x68 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C0)
|
||||
- H'F46A offset=0x6A expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C1)
|
||||
- H'F46C offset=0x6C expected=0x4000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C3)
|
||||
- H'F46E offset=0x6E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C4)
|
||||
- H'F470 offset=0x70 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C5)
|
||||
- H'F472 offset=0x72 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C6)
|
||||
- H'F474 offset=0x74 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C7)
|
||||
- H'F476 offset=0x76 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C8)
|
||||
- H'F478 offset=0x78 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0C9)
|
||||
- H'F47A offset=0x7A expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0CA)
|
||||
- H'F47C offset=0x7C expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0CB)
|
||||
- H'F47E offset=0x7E expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0CC)
|
||||
- H'F480 offset=0x80 expected=0x0000 actual=0xFFFF (factory_shadow_offset; selectors=0x0CD)
|
||||
- H'F482 offset=0x82 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D4)
|
||||
- H'F484 offset=0x84 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D5)
|
||||
- H'F486 offset=0x86 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D6)
|
||||
- H'F488 offset=0x88 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D7)
|
||||
- H'F48A offset=0x8A expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D8)
|
||||
- H'F48C offset=0x8C expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0D9)
|
||||
- H'F48E offset=0x8E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0DA)
|
||||
- H'F490 offset=0x90 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0F6)
|
||||
- H'F492 offset=0x92 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0F9)
|
||||
- H'F494 offset=0x94 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FA)
|
||||
- H'F496 offset=0x96 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FB)
|
||||
- H'F498 offset=0x98 expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FC)
|
||||
- H'F49A offset=0x9A expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FD)
|
||||
- H'F49C offset=0x9C expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FE)
|
||||
- H'F49E offset=0x9E expected=0x8000 actual=0xFFFF (factory_shadow_offset; selectors=0x0FF)
|
||||
- ... 47 more shadow diffs omitted
|
||||
31
build/pin50-p77-low-eeprom.txt
Normal file
31
build/pin50-p77-low-eeprom.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
Emulator EEPROM Snapshot
|
||||
|
||||
size=0x1000 sha256=4bed7704e1ea085487ca325c43bd60da75d37b6ae6f8292544e069a8825c64c6
|
||||
writes: bytes=0 words=0 factory_diff_words=0
|
||||
|
||||
Persistent Records:
|
||||
- page 0x0 EEPROM 0x000-0x007 bytes=00 00 6B 6F FE 00 00 00 text='..ko....'
|
||||
- page 0x1 EEPROM 0x100-0x107 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x2 EEPROM 0x200-0x207 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x3 EEPROM 0x300-0x307 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x4 EEPROM 0x400-0x407 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x5 EEPROM 0x500-0x507 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x6 EEPROM 0x600-0x607 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x7 EEPROM 0x700-0x707 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x8 EEPROM 0x800-0x807 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x9 EEPROM 0x900-0x907 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xA EEPROM 0xA00-0xA07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xB EEPROM 0xB00-0xB07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xC EEPROM 0xC00-0xC07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xD EEPROM 0xD00-0xD07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xE EEPROM 0xE00-0xE07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xF EEPROM 0xF00-0xF07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
|
||||
EEPROM Word Writes:
|
||||
- none since EEPROM setup/load
|
||||
|
||||
Factory Diffs:
|
||||
- current EEPROM image matches ROM factory/default image
|
||||
|
||||
F400 Shadow Diffs:
|
||||
- H'F4AA offset=0xAA expected=0x8000 actual=0x5500 (factory_shadow_offset; selectors=0x112)
|
||||
111
build/pin50-p77-low-fast-blank-eeprom.txt
Normal file
111
build/pin50-p77-low-fast-blank-eeprom.txt
Normal file
@@ -0,0 +1,111 @@
|
||||
Emulator EEPROM Snapshot
|
||||
|
||||
size=0x1000 sha256=4bed7704e1ea085487ca325c43bd60da75d37b6ae6f8292544e069a8825c64c6
|
||||
writes: bytes=4216 words=2108 factory_diff_words=0
|
||||
|
||||
Persistent Records:
|
||||
- page 0x0 EEPROM 0x000-0x007 bytes=00 00 6B 6F FE 00 00 00 text='..ko....'
|
||||
- page 0x1 EEPROM 0x100-0x107 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x2 EEPROM 0x200-0x207 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x3 EEPROM 0x300-0x307 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x4 EEPROM 0x400-0x407 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x5 EEPROM 0x500-0x507 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x6 EEPROM 0x600-0x607 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x7 EEPROM 0x700-0x707 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x8 EEPROM 0x800-0x807 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x9 EEPROM 0x900-0x907 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xA EEPROM 0xA00-0xA07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xB EEPROM 0xB00-0xB07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xC EEPROM 0xC00-0xC07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xD EEPROM 0xD00-0xD07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xE EEPROM 0xE00-0xE07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xF EEPROM 0xF00-0xF07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
|
||||
EEPROM Word Writes:
|
||||
- 0x0FE page=0x0 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1FE page=0x1 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2FE page=0x2 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3FE page=0x3 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4FE page=0x4 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5FE page=0x5 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6FE page=0x6 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7FE page=0x7 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8FE page=0x8 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9FE page=0x9 offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAFE page=0xA offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBFE page=0xB offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCFE page=0xC offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDFE page=0xD offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEFE page=0xE offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFFE page=0xF offset=0xFE 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x0FC page=0x0 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1FC page=0x1 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2FC page=0x2 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3FC page=0x3 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4FC page=0x4 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5FC page=0x5 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6FC page=0x6 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7FC page=0x7 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8FC page=0x8 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9FC page=0x9 offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAFC page=0xA offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBFC page=0xB offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCFC page=0xC offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDFC page=0xD offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEFC page=0xE offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFFC page=0xF offset=0xFC 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x0FA page=0x0 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1FA page=0x1 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2FA page=0x2 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3FA page=0x3 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4FA page=0x4 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5FA page=0x5 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6FA page=0x6 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7FA page=0x7 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8FA page=0x8 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9FA page=0x9 offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAFA page=0xA offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBFA page=0xB offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCFA page=0xC offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDFA page=0xD offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEFA page=0xE offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFFA page=0xF offset=0xFA 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x0F8 page=0x0 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1F8 page=0x1 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2F8 page=0x2 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3F8 page=0x3 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4F8 page=0x4 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5F8 page=0x5 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6F8 page=0x6 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7F8 page=0x7 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8F8 page=0x8 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9F8 page=0x9 offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAF8 page=0xA offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBF8 page=0xB offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCF8 page=0xC offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDF8 page=0xD offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEF8 page=0xE offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFF8 page=0xF offset=0xF8 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x0F6 page=0x0 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1F6 page=0x1 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2F6 page=0x2 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3F6 page=0x3 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4F6 page=0x4 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5F6 page=0x5 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6F6 page=0x6 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7F6 page=0x7 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8F6 page=0x8 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9F6 page=0x9 offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAF6 page=0xA offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBF6 page=0xB offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCF6 page=0xC offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDF6 page=0xD offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEF6 page=0xE offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFF6 page=0xF offset=0xF6 0xFFFF->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- ... 2028 more word writes omitted
|
||||
|
||||
Factory Diffs:
|
||||
- current EEPROM image matches ROM factory/default image
|
||||
|
||||
F400 Shadow Diffs:
|
||||
- F400-F4FF shadow matches ROM factory words or no ROM factory baseline was supplied
|
||||
111
build/pin50-p77-low-fast-factory-eeprom.txt
Normal file
111
build/pin50-p77-low-fast-factory-eeprom.txt
Normal file
@@ -0,0 +1,111 @@
|
||||
Emulator EEPROM Snapshot
|
||||
|
||||
size=0x1000 sha256=4bed7704e1ea085487ca325c43bd60da75d37b6ae6f8292544e069a8825c64c6
|
||||
writes: bytes=4216 words=2108 factory_diff_words=0
|
||||
|
||||
Persistent Records:
|
||||
- page 0x0 EEPROM 0x000-0x007 bytes=00 00 6B 6F FE 00 00 00 text='..ko....'
|
||||
- page 0x1 EEPROM 0x100-0x107 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x2 EEPROM 0x200-0x207 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x3 EEPROM 0x300-0x307 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x4 EEPROM 0x400-0x407 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x5 EEPROM 0x500-0x507 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x6 EEPROM 0x600-0x607 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x7 EEPROM 0x700-0x707 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x8 EEPROM 0x800-0x807 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0x9 EEPROM 0x900-0x907 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xA EEPROM 0xA00-0xA07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xB EEPROM 0xB00-0xB07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xC EEPROM 0xC00-0xC07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xD EEPROM 0xD00-0xD07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xE EEPROM 0xE00-0xE07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
- page 0xF EEPROM 0xF00-0xF07 bytes=20 20 20 20 20 20 20 20 text=' '
|
||||
|
||||
EEPROM Word Writes:
|
||||
- 0x0FE page=0x0 offset=0xFE 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1FE page=0x1 offset=0xFE 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2FE page=0x2 offset=0xFE 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3FE page=0x3 offset=0xFE 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4FE page=0x4 offset=0xFE 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5FE page=0x5 offset=0xFE 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6FE page=0x6 offset=0xFE 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7FE page=0x7 offset=0xFE 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8FE page=0x8 offset=0xFE 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9FE page=0x9 offset=0xFE 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAFE page=0xA offset=0xFE 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBFE page=0xB offset=0xFE 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCFE page=0xC offset=0xFE 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDFE page=0xD offset=0xFE 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEFE page=0xE offset=0xFE 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFFE page=0xF offset=0xFE 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x0FC page=0x0 offset=0xFC 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1FC page=0x1 offset=0xFC 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2FC page=0x2 offset=0xFC 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3FC page=0x3 offset=0xFC 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4FC page=0x4 offset=0xFC 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5FC page=0x5 offset=0xFC 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6FC page=0x6 offset=0xFC 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7FC page=0x7 offset=0xFC 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8FC page=0x8 offset=0xFC 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9FC page=0x9 offset=0xFC 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAFC page=0xA offset=0xFC 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBFC page=0xB offset=0xFC 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCFC page=0xC offset=0xFC 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDFC page=0xD offset=0xFC 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEFC page=0xE offset=0xFC 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFFC page=0xF offset=0xFC 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x0FA page=0x0 offset=0xFA 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1FA page=0x1 offset=0xFA 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2FA page=0x2 offset=0xFA 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3FA page=0x3 offset=0xFA 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4FA page=0x4 offset=0xFA 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5FA page=0x5 offset=0xFA 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6FA page=0x6 offset=0xFA 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7FA page=0x7 offset=0xFA 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8FA page=0x8 offset=0xFA 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9FA page=0x9 offset=0xFA 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAFA page=0xA offset=0xFA 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBFA page=0xB offset=0xFA 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCFA page=0xC offset=0xFA 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDFA page=0xD offset=0xFA 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEFA page=0xE offset=0xFA 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFFA page=0xF offset=0xFA 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x0F8 page=0x0 offset=0xF8 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1F8 page=0x1 offset=0xF8 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2F8 page=0x2 offset=0xF8 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3F8 page=0x3 offset=0xF8 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4F8 page=0x4 offset=0xF8 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5F8 page=0x5 offset=0xF8 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6F8 page=0x6 offset=0xF8 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7F8 page=0x7 offset=0xF8 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8F8 page=0x8 offset=0xF8 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9F8 page=0x9 offset=0xF8 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAF8 page=0xA offset=0xF8 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBF8 page=0xB offset=0xF8 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCF8 page=0xC offset=0xF8 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDF8 page=0xD offset=0xF8 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEF8 page=0xE offset=0xF8 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFF8 page=0xF offset=0xF8 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x0F6 page=0x0 offset=0xF6 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x1F6 page=0x1 offset=0xF6 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x2F6 page=0x2 offset=0xF6 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x3F6 page=0x3 offset=0xF6 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x4F6 page=0x4 offset=0xF6 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x5F6 page=0x5 offset=0xF6 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x6F6 page=0x6 offset=0xF6 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x7F6 page=0x7 offset=0xF6 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x8F6 page=0x8 offset=0xF6 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0x9F6 page=0x9 offset=0xF6 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xAF6 page=0xA offset=0xF6 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xBF6 page=0xB offset=0xF6 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xCF6 page=0xC offset=0xF6 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xDF6 page=0xD offset=0xF6 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xEF6 page=0xE offset=0xF6 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- 0xFF6 page=0xF offset=0xF6 0x0000->0x0000 source=linear_word (factory_shadow_offset)
|
||||
- ... 2028 more word writes omitted
|
||||
|
||||
Factory Diffs:
|
||||
- current EEPROM image matches ROM factory/default image
|
||||
|
||||
F400 Shadow Diffs:
|
||||
- F400-F4FF shadow matches ROM factory words or no ROM factory baseline was supplied
|
||||
200
build/rom_0013_button_handler_linear.asm
Normal file
200
build/rom_0013_button_handler_linear.asm
Normal file
@@ -0,0 +1,200 @@
|
||||
; H8/536 ROM disassembly
|
||||
; input: ROM\M27C512@DIP28_1.BIN
|
||||
; bytes: 65536
|
||||
; vector mode: min
|
||||
; analysis: linear sweep
|
||||
;
|
||||
; Notes from the manual:
|
||||
; - H8/536 uses the H8/500 CPU instruction set.
|
||||
; - In minimum mode the reset vector at H'0000-H'0001 is a 16-bit PC.
|
||||
; - The register field is H'FE80-H'FFFF; names below come from appendix B.
|
||||
; - @aa:8 short absolute operands use BR as the upper address byte.
|
||||
; - SCI baud inference uses section 14.2.8 BRR formulas when SMR/BRR are known.
|
||||
; - LCD inference treats E-clock H'F200/H'F201 accesses as status/control and data candidates.
|
||||
|
||||
; Memory Map
|
||||
; H'0000-H'009F exception_vectors vectors
|
||||
; H'00A0-H'00FF dtc_vectors dtc_vectors
|
||||
; H'0100-H'F67F program_or_external program
|
||||
; H'F680-H'FE7F on_chip_ram ram
|
||||
; H'FE80-H'FFFF register_field registers
|
||||
|
||||
; Vectors
|
||||
; H'0000 reset -> vec_reset_1000 (H'1000)
|
||||
; H'0004 invalid_instruction -> vec_reset_1000 (H'1000)
|
||||
; H'0006 zero_divide -> vec_reset_1000 (H'1000)
|
||||
; H'0008 trap_vs -> vec_reset_1000 (H'1000)
|
||||
; H'0010 address_error -> vec_reset_1000 (H'1000)
|
||||
; H'0012 trace -> vec_reset_1000 (H'1000)
|
||||
; H'0016 nmi -> vec_nmi_4393 (H'4393)
|
||||
; H'0020 trapa_0 -> vec_reset_1000 (H'1000)
|
||||
; H'0022 trapa_1 -> vec_reset_1000 (H'1000)
|
||||
; H'0024 trapa_2 -> vec_reset_1000 (H'1000)
|
||||
; H'0026 trapa_3 -> vec_reset_1000 (H'1000)
|
||||
; H'0028 trapa_4 -> vec_reset_1000 (H'1000)
|
||||
; H'002A trapa_5 -> vec_reset_1000 (H'1000)
|
||||
; H'002C trapa_6 -> vec_reset_1000 (H'1000)
|
||||
; H'002E trapa_7 -> vec_reset_1000 (H'1000)
|
||||
; H'0030 trapa_8 -> vec_reset_1000 (H'1000)
|
||||
; H'0032 trapa_9 -> vec_reset_1000 (H'1000)
|
||||
; H'0034 trapa_a -> vec_reset_1000 (H'1000)
|
||||
; H'0036 trapa_b -> vec_reset_1000 (H'1000)
|
||||
; H'0038 trapa_c -> vec_reset_1000 (H'1000)
|
||||
; H'003A trapa_d -> vec_reset_1000 (H'1000)
|
||||
; H'003C trapa_e -> vec_reset_1000 (H'1000)
|
||||
; H'003E trapa_f -> vec_reset_1000 (H'1000)
|
||||
; H'0040 irq0 -> vec_reset_1000 (H'1000)
|
||||
; H'0042 interval_timer -> vec_interval_timer_BFC4 (H'BFC4)
|
||||
; H'0048 irq1 -> vec_reset_1000 (H'1000)
|
||||
; H'0050 irq2 -> vec_reset_1000 (H'1000)
|
||||
; H'0052 irq3 -> vec_irq3_3C30 (H'3C30)
|
||||
; H'0058 irq4 -> vec_irq4_3AC7 (H'3AC7)
|
||||
; H'005A irq5 -> vec_reset_1000 (H'1000)
|
||||
; H'0062 frt1_ocia -> vec_frt1_ocia_BEEA (H'BEEA)
|
||||
; H'006A frt2_ocia -> vec_frt2_ocia_BF23 (H'BF23)
|
||||
; H'0080 sci1_eri -> vec_sci1_eri_BB57 (H'BB57)
|
||||
; H'0082 sci1_rxi -> vec_sci1_rxi_BB67 (H'BB67)
|
||||
; H'0084 sci1_txi -> vec_sci1_txi_BA84 (H'BA84)
|
||||
; H'0090 ad_adi -> vec_ad_adi_3D99 (H'3D99)
|
||||
|
||||
; Symbols
|
||||
; mem_E026 H'E026 program_or_external memory r=4 w=0 width=word
|
||||
; mem_E02A H'E02A program_or_external memory r=1 w=0 width=word
|
||||
; mem_E046 H'E046 program_or_external memory r=0 w=1 width=word
|
||||
; mem_E110 H'E110 program_or_external memory r=1 w=0 width=word
|
||||
; mem_E134 H'E134 program_or_external memory r=1 w=0 width=word
|
||||
; mem_E824 H'E824 program_or_external memory r=0 w=1 width=word
|
||||
; mem_E826 H'E826 program_or_external memory r=0 w=4 width=word
|
||||
; mem_E82A H'E82A program_or_external memory r=0 w=1 width=word
|
||||
; mem_E8D6 H'E8D6 program_or_external memory r=0 w=1 width=word
|
||||
; ram_F6D4 H'F6D4 on_chip_ram ram r=1 w=0 width=byte
|
||||
; ram_F6DB H'F6DB on_chip_ram ram r=3 w=0 width=byte
|
||||
; ram_F713 H'F713 on_chip_ram ram r=2 w=2 width=byte
|
||||
; ram_F726 H'F726 on_chip_ram ram r=0 w=1 width=byte
|
||||
; ram_F730 H'F730 on_chip_ram ram r=1 w=0 width=byte
|
||||
; ram_F731 H'F731 on_chip_ram ram r=5 w=2 width=byte
|
||||
; ram_F732 H'F732 on_chip_ram ram r=0 w=1 width=word
|
||||
; ram_F76A H'F76A on_chip_ram ram r=0 w=1 width=word
|
||||
; ram_F76E H'F76E on_chip_ram ram r=1 w=1 width=byte
|
||||
; ram_F791 H'F791 on_chip_ram ram r=2 w=1 width=byte
|
||||
; ram_F798 H'F798 on_chip_ram ram r=0 w=2 width=byte
|
||||
; ram_FB03 H'FB03 on_chip_ram ram r=1 w=1 width=byte
|
||||
|
||||
; Board Profile
|
||||
; Board trace ties the H8/536 SCI1 pins to a MAX202 RS232 transceiver.
|
||||
; H8 pin 66 P95/TXD (TXD) -> MAX202 pin 11
|
||||
; H8 pin 67 P96/RXD (RXD) -> MAX202 pin 12
|
||||
; SCI2 pin routing is disabled by SYSCR2.P9SCI2E=0 in the observed setup.
|
||||
|
||||
; LCD/Text Scan
|
||||
; search 'CONNECT': not literal, hits=0
|
||||
|
||||
1FC0: F7 13 C5 1D ROTR.B @(H'13C5,R7)
|
||||
1FC4: E8 24 07 80 00 MOV:G.W #H'8000, @(H'24,R0)
|
||||
1FC9: 52 80 MOV:E.B #H'80, R2 ; dataflow R2=H'80
|
||||
1FCB: 5B 40 12 MOV:I.W #H'4012, R3 ; dataflow R3=H'4012
|
||||
1FCE: 1E 1E 83 BSR loc_3E54
|
||||
1FD1: 19 RTS
|
||||
1FD2: 15 F7 91 D7 BCLR.B #7, @H'F791 ; refs ram_F791 in on_chip_ram
|
||||
1FD6: 15 F7 13 D5 BCLR.B #5, @H'F713 ; refs ram_F713 in on_chip_ram
|
||||
1FDA: 1D E8 24 06 00 MOV:G.W #H'00, @H'E824 ; refs mem_E824 in program_or_external
|
||||
1FDF: 52 80 MOV:E.B #H'80, R2 ; dataflow R2=H'80
|
||||
1FE1: 5B 40 12 MOV:I.W #H'4012, R3 ; dataflow R3=H'4012
|
||||
1FE4: 1E 1E 6D BSR loc_3E54
|
||||
1FE7: 19 RTS
|
||||
1FE8: 1D E0 26 80 MOV:G.W @H'E026, R0 ; refs mem_E026 in program_or_external
|
||||
1FEC: A8 CF BSET.W #15, R0
|
||||
1FEE: 1D E8 26 90 MOV:G.W R0, @H'E826 ; refs mem_E826 in program_or_external
|
||||
1FF2: 52 80 MOV:E.B #H'80, R2 ; dataflow R2=H'80
|
||||
1FF4: 5B 00 13 MOV:I.W #H'0013, R3 ; dataflow R3=H'0013
|
||||
1FF7: 1E 1E 5A BSR loc_3E54
|
||||
1FFA: 19 RTS
|
||||
1FFB: 1D E0 26 80 MOV:G.W @H'E026, R0 ; refs mem_E026 in program_or_external
|
||||
1FFF: A8 DF BCLR.W #15, R0
|
||||
2001: 1D E8 26 90 MOV:G.W R0, @H'E826 ; refs mem_E826 in program_or_external
|
||||
2005: 52 80 MOV:E.B #H'80, R2 ; dataflow R2=H'80
|
||||
2007: 5B 00 13 MOV:I.W #H'0013, R3 ; dataflow R3=H'0013
|
||||
200A: 1E 1E 47 BSR loc_3E54
|
||||
200D: 19 RTS
|
||||
200E: 15 F6 DB F7 BTST.B #7, @H'F6DB ; refs ram_F6DB in on_chip_ram
|
||||
2012: 27 33 BEQ loc_2047
|
||||
2014: 15 F7 31 04 03 CMP:G.B #H'03, @H'F731 ; refs ram_F731 in on_chip_ram
|
||||
2019: 22 2C BHI loc_2047
|
||||
201B: 15 F7 91 F5 BTST.B #5, @H'F791 ; refs ram_F791 in on_chip_ram
|
||||
201F: 26 14 BNE loc_2035
|
||||
2021: 1D E0 26 80 MOV:G.W @H'E026, R0 ; refs mem_E026 in program_or_external
|
||||
2025: A8 CE BSET.W #14, R0
|
||||
2027: 1D E8 26 90 MOV:G.W R0, @H'E826 ; refs mem_E826 in program_or_external
|
||||
202B: 52 80 MOV:E.B #H'80, R2 ; dataflow R2=H'80
|
||||
202D: 5B 00 13 MOV:I.W #H'0013, R3 ; dataflow R3=H'0013
|
||||
2030: 1E 1E 21 BSR loc_3E54
|
||||
2033: 20 12 BRA loc_2047
|
||||
|
||||
loc_2035:
|
||||
2035: 1D E0 26 80 MOV:G.W @H'E026, R0 ; refs mem_E026 in program_or_external
|
||||
2039: A8 DE BCLR.W #14, R0
|
||||
203B: 1D E8 26 90 MOV:G.W R0, @H'E826 ; refs mem_E826 in program_or_external
|
||||
203F: 52 80 MOV:E.B #H'80, R2 ; dataflow R2=H'80
|
||||
2041: 5B 00 13 MOV:I.W #H'0013, R3 ; dataflow R3=H'0013
|
||||
2044: 1E 1E 0D BSR loc_3E54
|
||||
|
||||
loc_2047:
|
||||
2047: 19 RTS
|
||||
2048: 15 F6 D4 F6 BTST.B #6, @H'F6D4 ; refs ram_F6D4 in on_chip_ram
|
||||
204C: 27 52 BEQ loc_20A0
|
||||
204E: 15 F7 31 04 02 CMP:G.B #H'02, @H'F731 ; refs ram_F731 in on_chip_ram
|
||||
2053: 22 4B BHI loc_20A0
|
||||
2055: 15 F7 30 F7 BTST.B #7, @H'F730 ; refs ram_F730 in on_chip_ram
|
||||
2059: 27 19 BEQ loc_2074
|
||||
205B: 1D E8 D6 07 80 00 MOV:G.W #H'8000, @H'E8D6 ; refs mem_E8D6 in program_or_external
|
||||
2061: 52 80 MOV:E.B #H'80, R2 ; dataflow R2=H'80
|
||||
2063: 5B 00 6B MOV:I.W #H'006B, R3 ; dataflow R3=H'006B
|
||||
2066: 1E 1D EB BSR loc_3E54
|
||||
2069: 15 F7 31 C7 BSET.B #7, @H'F731 ; refs ram_F731 in on_chip_ram
|
||||
206D: 15 F7 98 06 C8 MOV:G.B #H'C8, @H'F798 ; refs ram_F798 in on_chip_ram
|
||||
2072: 20 2C BRA loc_20A0
|
||||
|
||||
loc_2074:
|
||||
2074: 1D F7 32 13 CLR.W @H'F732 ; refs ram_F732 in on_chip_ram
|
||||
2078: 15 FB 03 D7 BCLR.B #7, @H'FB03 ; refs ram_FB03 in on_chip_ram
|
||||
207C: 1D E0 46 13 CLR.W @H'E046 ; refs mem_E046 in program_or_external
|
||||
2080: 1D F7 6A 13 CLR.W @H'F76A ; refs ram_F76A in on_chip_ram
|
||||
2084: 1E 28 73 BSR loc_48FA
|
||||
2087: 15 F7 13 C6 BSET.B #6, @H'F713 ; refs ram_F713 in on_chip_ram
|
||||
208B: 15 F7 26 06 1E MOV:G.B #H'1E, @H'F726 ; refs ram_F726 in on_chip_ram
|
||||
2090: 15 F7 6E C6 BSET.B #6, @H'F76E ; refs ram_F76E in on_chip_ram
|
||||
2094: 15 F7 31 C7 BSET.B #7, @H'F731 ; refs ram_F731 in on_chip_ram
|
||||
2098: 15 F7 98 06 C8 MOV:G.B #H'C8, @H'F798 ; refs ram_F798 in on_chip_ram
|
||||
209D: 1E 36 38 BSR loc_56D8
|
||||
|
||||
loc_20A0:
|
||||
20A0: 19 RTS
|
||||
20A1: 1D E0 2A 80 MOV:G.W @H'E02A, R0 ; refs mem_E02A in program_or_external
|
||||
20A5: 15 F6 DB F5 BTST.B #5, @H'F6DB ; refs ram_F6DB in on_chip_ram
|
||||
20A9: 27 04 BEQ loc_20AF
|
||||
20AB: A8 CF BSET.W #15, R0
|
||||
20AD: 20 02 BRA loc_20B1
|
||||
|
||||
loc_20AF:
|
||||
20AF: A8 DF BCLR.W #15, R0
|
||||
|
||||
loc_20B1:
|
||||
20B1: 1D E8 2A 90 MOV:G.W R0, @H'E82A ; refs mem_E82A in program_or_external
|
||||
20B5: 52 80 MOV:E.B #H'80, R2 ; dataflow R2=H'80
|
||||
20B7: 5B 00 15 MOV:I.W #H'0015, R3 ; dataflow R3=H'0015
|
||||
20BA: 1E 1D 97 BSR loc_3E54
|
||||
20BD: 19 RTS
|
||||
20BE: 15 F6 DB F3 BTST.B #3, @H'F6DB ; refs ram_F6DB in on_chip_ram
|
||||
20C2: 27 2C BEQ loc_20F0
|
||||
20C4: 15 F7 31 04 03 CMP:G.B #H'03, @H'F731 ; refs ram_F731 in on_chip_ram
|
||||
20C9: 22 25 BHI loc_20F0
|
||||
20CB: 1D E1 10 16 TST.W @H'E110 ; refs mem_E110 in program_or_external
|
||||
20CF: 27 05 BEQ loc_20D6
|
||||
20D1: 1E 06 14 BSR loc_26E8
|
||||
20D4: 20 1A BRA loc_20F0
|
||||
|
||||
loc_20D6:
|
||||
20D6: 1D E1 34 80 MOV:G.W @H'E134, R0 ; refs mem_E134 in program_or_external
|
||||
20DA: A8 FB BTST.W #11, R0
|
||||
20DC: 27 04 BEQ loc_20E2
|
||||
20DE: A8 DB BCLR.W #11, R0
|
||||
7108
build/rom_0013_button_handler_linear.json
Normal file
7108
build/rom_0013_button_handler_linear.json
Normal file
File diff suppressed because it is too large
Load Diff
135
build/rom_0013_handler_linear.asm
Normal file
135
build/rom_0013_handler_linear.asm
Normal file
@@ -0,0 +1,135 @@
|
||||
; H8/536 ROM disassembly
|
||||
; input: ROM\M27C512@DIP28_1.BIN
|
||||
; bytes: 65536
|
||||
; vector mode: min
|
||||
; analysis: linear sweep
|
||||
;
|
||||
; Notes from the manual:
|
||||
; - H8/536 uses the H8/500 CPU instruction set.
|
||||
; - In minimum mode the reset vector at H'0000-H'0001 is a 16-bit PC.
|
||||
; - The register field is H'FE80-H'FFFF; names below come from appendix B.
|
||||
; - @aa:8 short absolute operands use BR as the upper address byte.
|
||||
; - SCI baud inference uses section 14.2.8 BRR formulas when SMR/BRR are known.
|
||||
; - LCD inference treats E-clock H'F200/H'F201 accesses as status/control and data candidates.
|
||||
|
||||
; Memory Map
|
||||
; H'0000-H'009F exception_vectors vectors
|
||||
; H'00A0-H'00FF dtc_vectors dtc_vectors
|
||||
; H'0100-H'F67F program_or_external program
|
||||
; H'F680-H'FE7F on_chip_ram ram
|
||||
; H'FE80-H'FFFF register_field registers
|
||||
|
||||
; Vectors
|
||||
; H'0000 reset -> vec_reset_1000 (H'1000)
|
||||
; H'0004 invalid_instruction -> vec_reset_1000 (H'1000)
|
||||
; H'0006 zero_divide -> vec_reset_1000 (H'1000)
|
||||
; H'0008 trap_vs -> vec_reset_1000 (H'1000)
|
||||
; H'0010 address_error -> vec_reset_1000 (H'1000)
|
||||
; H'0012 trace -> vec_reset_1000 (H'1000)
|
||||
; H'0016 nmi -> vec_nmi_4393 (H'4393)
|
||||
; H'0020 trapa_0 -> vec_reset_1000 (H'1000)
|
||||
; H'0022 trapa_1 -> vec_reset_1000 (H'1000)
|
||||
; H'0024 trapa_2 -> vec_reset_1000 (H'1000)
|
||||
; H'0026 trapa_3 -> vec_reset_1000 (H'1000)
|
||||
; H'0028 trapa_4 -> vec_reset_1000 (H'1000)
|
||||
; H'002A trapa_5 -> vec_reset_1000 (H'1000)
|
||||
; H'002C trapa_6 -> vec_reset_1000 (H'1000)
|
||||
; H'002E trapa_7 -> vec_reset_1000 (H'1000)
|
||||
; H'0030 trapa_8 -> vec_reset_1000 (H'1000)
|
||||
; H'0032 trapa_9 -> vec_reset_1000 (H'1000)
|
||||
; H'0034 trapa_a -> vec_reset_1000 (H'1000)
|
||||
; H'0036 trapa_b -> vec_reset_1000 (H'1000)
|
||||
; H'0038 trapa_c -> vec_reset_1000 (H'1000)
|
||||
; H'003A trapa_d -> vec_reset_1000 (H'1000)
|
||||
; H'003C trapa_e -> vec_reset_1000 (H'1000)
|
||||
; H'003E trapa_f -> vec_reset_1000 (H'1000)
|
||||
; H'0040 irq0 -> vec_reset_1000 (H'1000)
|
||||
; H'0042 interval_timer -> vec_interval_timer_BFC4 (H'BFC4)
|
||||
; H'0048 irq1 -> vec_reset_1000 (H'1000)
|
||||
; H'0050 irq2 -> vec_reset_1000 (H'1000)
|
||||
; H'0052 irq3 -> vec_irq3_3C30 (H'3C30)
|
||||
; H'0058 irq4 -> vec_irq4_3AC7 (H'3AC7)
|
||||
; H'005A irq5 -> vec_reset_1000 (H'1000)
|
||||
; H'0062 frt1_ocia -> vec_frt1_ocia_BEEA (H'BEEA)
|
||||
; H'006A frt2_ocia -> vec_frt2_ocia_BF23 (H'BF23)
|
||||
; H'0080 sci1_eri -> vec_sci1_eri_BB57 (H'BB57)
|
||||
; H'0082 sci1_rxi -> vec_sci1_rxi_BB67 (H'BB67)
|
||||
; H'0084 sci1_txi -> vec_sci1_txi_BA84 (H'BA84)
|
||||
; H'0090 ad_adi -> vec_ad_adi_3D99 (H'3D99)
|
||||
|
||||
; Symbols
|
||||
; mem_E02E H'E02E program_or_external memory r=1 w=0 width=word
|
||||
; mem_E030 H'E030 program_or_external memory r=1 w=0 width=word
|
||||
; mem_E826 H'E826 program_or_external memory r=2 w=0 width=word
|
||||
; mem_E82E H'E82E program_or_external memory r=0 w=1 width=word
|
||||
; ram_F711 H'F711 on_chip_ram ram r=4 w=4 width=byte
|
||||
; ram_F713 H'F713 on_chip_ram ram r=2 w=2 width=byte
|
||||
; ram_F716 H'F716 on_chip_ram ram r=4 w=4 width=byte
|
||||
; ram_F791 H'F791 on_chip_ram ram r=4 w=4 width=byte
|
||||
|
||||
; Board Profile
|
||||
; Board trace ties the H8/536 SCI1 pins to a MAX202 RS232 transceiver.
|
||||
; H8 pin 66 P95/TXD (TXD) -> MAX202 pin 11
|
||||
; H8 pin 67 P96/RXD (RXD) -> MAX202 pin 12
|
||||
; SCI2 pin routing is disabled by SYSCR2.P9SCI2E=0 in the observed setup.
|
||||
|
||||
; LCD/Text Scan
|
||||
; search 'CONNECT': not literal, hits=0
|
||||
|
||||
2E00: 30 FE A3 BRA loc_2CA6
|
||||
2E03: 30 FE A0 BRA loc_2CA6
|
||||
2E06: 1D E8 26 FF BTST.W #15, @H'E826 ; refs mem_E826 in program_or_external
|
||||
2E0A: 27 0A BEQ loc_2E16
|
||||
2E0C: 15 F7 91 C6 BSET.B #6, @H'F791 ; refs ram_F791 in on_chip_ram
|
||||
2E10: 15 F7 13 C4 BSET.B #4, @H'F713 ; refs ram_F713 in on_chip_ram
|
||||
2E14: 20 08 BRA loc_2E1E
|
||||
|
||||
loc_2E16:
|
||||
2E16: 15 F7 91 D6 BCLR.B #6, @H'F791 ; refs ram_F791 in on_chip_ram
|
||||
2E1A: 15 F7 13 D4 BCLR.B #4, @H'F713 ; refs ram_F713 in on_chip_ram
|
||||
|
||||
loc_2E1E:
|
||||
2E1E: 1D E8 26 FE BTST.W #14, @H'E826 ; refs mem_E826 in program_or_external
|
||||
2E22: 27 0A BEQ loc_2E2E
|
||||
2E24: 15 F7 91 C5 BSET.B #5, @H'F791 ; refs ram_F791 in on_chip_ram
|
||||
2E28: 15 F7 16 C7 BSET.B #7, @H'F716 ; refs ram_F716 in on_chip_ram
|
||||
2E2C: 20 08 BRA loc_2E36
|
||||
|
||||
loc_2E2E:
|
||||
2E2E: 15 F7 91 D5 BCLR.B #5, @H'F791 ; refs ram_F791 in on_chip_ram
|
||||
2E32: 15 F7 16 D7 BCLR.B #7, @H'F716 ; refs ram_F716 in on_chip_ram
|
||||
|
||||
loc_2E36:
|
||||
2E36: 30 FE 6D BRA loc_2CA6
|
||||
2E39: FC E0 00 81 MOV:G.W @(-H'2000,R4), R1
|
||||
2E3D: A9 FF BTST.W #15, R1
|
||||
2E3F: 26 0E BNE loc_2E4F
|
||||
2E41: A9 FE BTST.W #14, R1
|
||||
2E43: 26 0A BNE loc_2E4F
|
||||
2E45: 15 F7 11 D0 BCLR.B #0, @H'F711 ; refs ram_F711 in on_chip_ram
|
||||
2E49: 15 F7 16 D5 BCLR.B #5, @H'F716 ; refs ram_F716 in on_chip_ram
|
||||
2E4D: 20 08 BRA loc_2E57
|
||||
|
||||
loc_2E4F:
|
||||
2E4F: 15 F7 11 C0 BSET.B #0, @H'F711 ; refs ram_F711 in on_chip_ram
|
||||
2E53: 15 F7 16 C5 BSET.B #5, @H'F716 ; refs ram_F716 in on_chip_ram
|
||||
|
||||
loc_2E57:
|
||||
2E57: 30 FE 4C BRA loc_2CA6
|
||||
2E5A: FC E0 00 81 MOV:G.W @(-H'2000,R4), R1
|
||||
2E5E: A9 FF BTST.W #15, R1
|
||||
2E60: 26 06 BNE loc_2E68
|
||||
2E62: 15 F7 11 D1 BCLR.B #1, @H'F711 ; refs ram_F711 in on_chip_ram
|
||||
2E66: 20 04 BRA loc_2E6C
|
||||
|
||||
loc_2E68:
|
||||
2E68: 15 F7 11 C1 BSET.B #1, @H'F711 ; refs ram_F711 in on_chip_ram
|
||||
|
||||
loc_2E6C:
|
||||
2E6C: 30 FE 37 BRA loc_2CA6
|
||||
2E6F: 1D E0 30 81 MOV:G.W @H'E030, R1 ; refs mem_E030 in program_or_external
|
||||
2E73: 1D E0 2E 71 CMP:G.W @H'E02E, R1 ; refs mem_E02E in program_or_external
|
||||
2E77: 27 0C BEQ loc_2E85
|
||||
2E79: 1D E8 2E 91 MOV:G.W R1, @H'E82E ; refs mem_E82E in program_or_external
|
||||
2E7D: 52 80 MOV:E.B #H'80, R2 ; dataflow R2=H'80
|
||||
2E7F: 5B 00 17 MOV:I.W #H'0017, R3 ; dataflow R3=H'0017
|
||||
2590
build/rom_0013_handler_linear.json
Normal file
2590
build/rom_0013_handler_linear.json
Normal file
File diff suppressed because it is too large
Load Diff
38
build/rom_0013_table_xrefs.txt
Normal file
38
build/rom_0013_table_xrefs.txt
Normal file
@@ -0,0 +1,38 @@
|
||||
Table/Index Cross-Reference Report for build\rom_0013_handler_linear.json
|
||||
=========================================================================
|
||||
|
||||
Static offsets are emitted only when an index register value can be derived from nearby immediate loads in the current JSON. Other indexed accesses are dynamic.
|
||||
|
||||
LCD correlation hints
|
||||
term 'CONNECT': no LCD/text candidate hits in current decompile
|
||||
term 'CONNECT: OK': no LCD/text candidate hits in current decompile
|
||||
term 'CONNECT: NOT ACT': no LCD/text candidate hits in current decompile
|
||||
term 'NOT ACT': no LCD/text candidate hits in current decompile
|
||||
term 'COMM LINK': no LCD/text candidate hits in current decompile
|
||||
term 'COMPLETED': no LCD/text candidate hits in current decompile
|
||||
caveat: LCD strings can be builder/script output; absence of a literal term does not disprove runtime composition.
|
||||
|
||||
primary_value_table_candidate H'E000-H'E3FF (negative H'2000; direct H'F900-H'F91F)
|
||||
accesses=4 reads=4 writes=0 dynamic=2
|
||||
static offsets: H'002E, H'0030
|
||||
functions: <no function>:4
|
||||
- H'2E39 read index dynamic via R4 operand @(-H'2000,R4); <no function>; MOV:G.W @(-H'2000,R4), R1
|
||||
- H'2E5A read index dynamic via R4 operand @(-H'2000,R4); <no function>; MOV:G.W @(-H'2000,R4), R1
|
||||
- H'2E6F read offset H'0030 selector 0x018 -> H'E030; <no function>; MOV:G.W @H'E030, R1
|
||||
- H'2E73 read offset H'002E selector 0x017 -> H'E02E; <no function>; CMP:G.W @H'E02E, R1
|
||||
|
||||
secondary_value_table_candidate H'E400-H'E7FF (negative H'1C00; direct H'F940-H'F95F)
|
||||
accesses=0 reads=0 writes=0 dynamic=0
|
||||
no references found in current JSON
|
||||
|
||||
current_value_table_candidate H'E800-H'EBFF (negative H'1800; direct H'F920-H'F93F)
|
||||
accesses=3 reads=2 writes=1 dynamic=0
|
||||
static offsets: H'0026, H'002E
|
||||
functions: <no function>:3
|
||||
- H'2E06 read offset H'0026 selector 0x013 -> H'E826; <no function>; BTST.W #15, @H'E826
|
||||
- H'2E1E read offset H'0026 selector 0x013 -> H'E826; <no function>; BTST.W #14, @H'E826
|
||||
- H'2E79 write offset H'002E selector 0x017 -> H'E82E; <no function>; MOV:G.W R1, @H'E82E
|
||||
|
||||
flag_table_candidate H'EC00-H'EFFF (negative H'1400; direct H'F980-H'F99F)
|
||||
accesses=0 reads=0 writes=0 dynamic=0
|
||||
no references found in current JSON
|
||||
2226
build/rom_ccu_seed_hints.json
Normal file
2226
build/rom_ccu_seed_hints.json
Normal file
File diff suppressed because it is too large
Load Diff
186
build/rom_ccu_seed_hints.txt
Normal file
186
build/rom_ccu_seed_hints.txt
Normal file
@@ -0,0 +1,186 @@
|
||||
H8/536 CCU Seed Hint Report
|
||||
|
||||
Summary: The RCP likely waits for the CCU to seed mirrored state tables, then uses those selector values to update LCD text, panel lamps, and report state changes.
|
||||
Confidence: medium
|
||||
|
||||
Table Model:
|
||||
- primary_value_table_candidate: H'E000-H'E3FF; accesses=31 static selectors=0x000, 0x002, 0x003, 0x023, 0x040, 0x081, 0x092, 0x093, 0x0A7, 0x0B7, 0x0B9, 0x0F6
|
||||
- secondary_value_table_candidate: H'E400-H'E7FF; accesses=8 static selectors=none
|
||||
- current_value_table_candidate: H'E800-H'EBFF; accesses=14 static selectors=0x000, 0x003, 0x040, 0x081, 0x092, 0x0F6
|
||||
- flag_table_candidate: H'EC00-H'EFFF; accesses=6 static selectors=0x000
|
||||
|
||||
Highest-Value Selector Candidates:
|
||||
- 0x093 white_balance_black_flare_mode_lane: score=19 tables=primary_value_table_candidate
|
||||
- primary_value_table_candidate read in loc_17C9: BTST.W #12, @H'E126
|
||||
- primary_value_table_candidate read in loc_17FB: BTST.W #12, @H'E126
|
||||
- primary_value_table_candidate read in loc_182D: BTST.W #5, @H'E126
|
||||
- primary_value_table_candidate read in loc_1891: BTST.W #5, @H'E126
|
||||
seed frames: 0x8000 -> 00 01 13 80 00 C8; 0x4000 -> 00 01 13 40 00 08; 0x2000 -> 00 01 13 20 00 68
|
||||
readback frame: 01 01 13 00 00 49
|
||||
- 0x000 heartbeat_or_idle_report_candidate: score=18 tables=primary_value_table_candidate, current_value_table_candidate, flag_table_candidate
|
||||
- primary_value_table_candidate write in loc_4096: MOV:G.W #H'0080, @H'E000
|
||||
- current_value_table_candidate write in loc_4096: MOV:G.W #H'0080, @H'E800
|
||||
- flag_table_candidate write in loc_4075: CLR.W @(-H'1400,R0)
|
||||
- idle report selector and CONNECT OK emulator condition both center on selector zero
|
||||
seed frames: 0x0080 -> 00 00 00 00 80 DA; 0x8080 -> 00 00 00 80 80 5A
|
||||
readback frame: 01 00 00 00 00 5B
|
||||
- 0x0F6 active_status_bridge_candidate: score=14 tables=primary_value_table_candidate, current_value_table_candidate
|
||||
- primary_value_table_candidate read in loc_48FA: BTST.W #13, @H'E1EC
|
||||
- primary_value_table_candidate read in loc_48FA: MOV:G.W @H'E1EC, R0
|
||||
- current_value_table_candidate write in loc_48FA: MOV:G.W R0, @H'E9EC
|
||||
- loc_48FA tests E1EC bit13 and can enqueue report selector 0x00F6
|
||||
seed frames: 0x2000 -> 00 01 76 20 00 0D
|
||||
readback frame: 01 01 76 00 00 2C
|
||||
- 0x003 default_enabled_bit_candidate: score=11 tables=primary_value_table_candidate, current_value_table_candidate
|
||||
- primary_value_table_candidate write in loc_4096: MOV:G.W #H'8000, @H'E006
|
||||
- current_value_table_candidate write in loc_4096: MOV:G.W #H'8000, @H'E806
|
||||
- ROM default table writes E000/E800 selector 0x003 to 0x8000
|
||||
seed frames: 0x8000 -> 00 00 03 80 00 D9
|
||||
readback frame: 01 00 03 00 00 58
|
||||
- 0x040 default_all_ones_or_status_block_candidate: score=11 tables=primary_value_table_candidate, current_value_table_candidate
|
||||
- primary_value_table_candidate write in loc_4096: MOV:G.W #H'FFFF, @H'E080
|
||||
- current_value_table_candidate write in loc_4096: MOV:G.W #H'FFFF, @H'E880
|
||||
- ROM default table writes E000/E800 selector 0x040 to 0xFFFF and bench tests repeatedly touched the 0x40 family
|
||||
seed frames: 0xFFFF -> 00 00 40 FF FF 1A; 0x4030 -> 00 00 40 40 30 6A
|
||||
readback frame: 01 00 40 00 00 1B
|
||||
- 0x06B standard_lamp_lane: score=11 tables=none
|
||||
- when F731.7 is set, command 5 on this selector clears F731.7/F790.7
|
||||
- Bench-visible STANDARD lamp lane found from ROM-derived F6D4.6 handler candidate.
|
||||
- selector dispatches to H'2F72
|
||||
seed frames: 0x8000 -> 00 00 6B 80 00 B1
|
||||
readback frame: 01 00 6B 00 00 30
|
||||
- 0x015 call_and_red_tally_lamp_lane: score=9 tables=none
|
||||
- observed RCP autonomous report frame(s): 00 00 15 80 00 CF, 00 00 15 00 00 4F
|
||||
- Bench-visible CALL lamp and red tally lane; local CALL handler mirrors F6DB.5 into E800[0x0015].15.
|
||||
- selector dispatches to H'2E39
|
||||
seed frames: 0x8000 -> 00 00 15 80 00 CF; 0x0000 -> 00 00 15 00 00 4F
|
||||
readback frame: 01 00 15 00 00 4E
|
||||
- 0x081 state_selector_candidate: score=9 tables=primary_value_table_candidate, current_value_table_candidate
|
||||
- primary_value_table_candidate read in vec_ad_adi_3D99: MOV:G.W @H'E102, R0
|
||||
- primary_value_table_candidate read in vec_ad_adi_3D99: CMP:G.W @H'E102, R1
|
||||
- current_value_table_candidate write in loc_15E0: MOV:G.W R1, @H'E902
|
||||
readback frame: 01 01 01 00 00 5B
|
||||
- 0x092 state_selector_candidate: score=9 tables=primary_value_table_candidate, current_value_table_candidate
|
||||
- primary_value_table_candidate read in loc_2650: MOV:G.W @H'E124, R0
|
||||
- primary_value_table_candidate read in loc_2650: CMP:G.W @H'E124, R0
|
||||
- current_value_table_candidate write in loc_2650: MOV:G.W R0, @H'E924
|
||||
readback frame: 01 01 12 00 00 48
|
||||
- 0x06C command5_be70_candidate: score=7 tables=none
|
||||
- continuation command 5 calls BE70 for selector 0x006C
|
||||
- selector dispatches to H'2FAF
|
||||
readback frame: 01 00 6C 00 00 37
|
||||
- 0x06D command5_be70_candidate: score=7 tables=none
|
||||
- continuation command 5 calls BE70 for selector 0x006D
|
||||
- selector dispatches to H'3015
|
||||
readback frame: 01 00 6D 00 00 36
|
||||
- 0x110 knee_auto_lamp_or_page_status_lane: score=7 tables=primary_value_table_candidate
|
||||
- primary_value_table_candidate read in loc_1795: BTST.W #15, @H'E220
|
||||
- Bench-visible KNEE AUTO source; ROM notes indicate timed KNEE/detail page interaction.
|
||||
seed frames: 0x8000 -> 00 01 90 80 00 4B
|
||||
readback frame: 01 01 90 00 00 CA
|
||||
- 0x013 slave_and_iris_mblack_link_lamps: score=6 tables=none
|
||||
- Selector 0x0013 is a two-bit lamp/status word. ROM dispatch H'2E06 reads current table word H'E826 and fans bit 15 and bit 14 into panel latch RAM.
|
||||
- 0x8000 SLAVE lamp: sets F791.6 and F713.4
|
||||
- 0x4000 IRIS/M.BLACK LINK lamp: sets F791.5 and F716.7
|
||||
- selector dispatches to H'2E06
|
||||
seed frames: 0x8000 -> 00 00 13 80 00 C9; 0x4000 -> 00 00 13 40 00 09; 0x0000 -> 00 00 13 00 00 49
|
||||
readback frame: 01 00 13 00 00 48
|
||||
- 0x017 bars_lamp_lane: score=6 tables=none
|
||||
- Bench-visible BARS lamp/latch lane; low writes do not reliably clear the visible latch.
|
||||
- selector dispatches to H'2E85
|
||||
seed frames: 0x8000 -> 00 00 17 80 00 CD; 0x4000 -> 00 00 17 40 00 0D; 0x0000 -> 00 00 17 00 00 4D
|
||||
readback frame: 01 00 17 00 00 4C
|
||||
- 0x01A monitor_selector_lamps: score=6 tables=none
|
||||
- Bench-visible MONITOR selector cluster found from ROM-derived button-output sweep.
|
||||
- selector dispatches to H'2EC4
|
||||
seed frames: 0x0808 -> 00 00 1A 08 08 40; 0x2020 -> 00 00 1A 20 20 40; 0x4040 -> 00 00 1A 40 40 40
|
||||
readback frame: 01 00 1A 00 00 41
|
||||
- 0x024 lcd_selector_button_lamp: score=6 tables=none
|
||||
- Bench-visible LCD selector-button lamp lane.
|
||||
- selector dispatches to H'2F0C
|
||||
seed frames: 0x8000 -> 00 00 24 80 00 FE; 0x0000 -> 00 00 24 00 00 7E
|
||||
readback frame: 01 00 24 00 00 7F
|
||||
- 0x007 camera_power_report_candidate: score=5 tables=none
|
||||
- observed RCP autonomous report frame(s): 00 00 07 80 00 DD
|
||||
- selector dispatches to H'2DC3
|
||||
readback frame: 01 00 07 00 00 5C
|
||||
- 0x023 state_selector_candidate: score=5 tables=primary_value_table_candidate
|
||||
- primary_value_table_candidate write in loc_400C: CLR.W @H'E046
|
||||
- selector dispatches to H'2EE6
|
||||
readback frame: 01 00 23 00 00 78
|
||||
- 0x06E command5_be70_candidate: score=5 tables=none
|
||||
- continuation command 5 calls BE70 for selector 0x006E
|
||||
readback frame: 01 00 6E 00 00 35
|
||||
- 0x096 connection_latch_clear_candidate: score=5 tables=none
|
||||
- when F731.7 is set, command 5 on this selector clears F731.7/F790.7
|
||||
readback frame: 01 01 16 00 00 4C
|
||||
- 0x097 connection_latch_clear_candidate: score=5 tables=none
|
||||
- when F731.7 is set, command 5 on this selector clears F731.7/F790.7
|
||||
readback frame: 01 01 17 00 00 4D
|
||||
- 0x0C6 connection_latch_clear_candidate: score=5 tables=none
|
||||
- when F731.7 is set, command 5 on this selector clears F731.7/F790.7
|
||||
readback frame: 01 01 46 00 00 1C
|
||||
- 0x0F8 connection_latch_clear_candidate: score=5 tables=none
|
||||
- when F731.7 is set, command 5 on this selector clears F731.7/F790.7
|
||||
readback frame: 01 01 78 00 00 22
|
||||
- 0x082 iris_readout_lane: score=4 tables=none
|
||||
- Bench-visible IRIS seven-segment/display lane.
|
||||
seed frames: 0x8000 -> 00 01 02 80 00 D9; 0x4000 -> 00 01 02 40 00 19; 0x0000 -> 00 01 02 00 00 59
|
||||
readback frame: 01 01 02 00 00 58
|
||||
|
||||
Display Text Hints:
|
||||
- CONNECT: 0 hit(s)
|
||||
- COMM LINK: 4 hit(s) - H'77F4 'literal COMM LINK', H'78F4 'literal COMM LINK', H'77F4 'COMM LINK ITEM-1Xw'
|
||||
- COMPLETED: 2 hit(s) - H'A027 'literal COMPLETED', H'A025 'COMPLETED'
|
||||
- CAM: 6 hit(s) - H'7149 'literal CAM', H'71FC 'literal CAM', H'72C7 'literal CAM'
|
||||
- BARS: 12 hit(s) - H'72D1 'literal BARS', H'757D 'literal BARS', H'9C61 'literal BARS'
|
||||
- BLACK: 22 hit(s) - H'65CC 'literal BLACK', H'6647 'literal BLACK', H'6709 'literal BLACK'
|
||||
- IRIS: 6 hit(s) - H'6461 'literal IRIS', H'6A92 'literal IRIS', H'A5CA 'literal IRIS'
|
||||
- GAIN: 10 hit(s) - H'6825 'literal GAIN', H'7813 'literal GAIN', H'98A1 'literal GAIN'
|
||||
- SHUTTER: 4 hit(s) - H'6FB2 'literal SHUTTER', H'781A 'literal SHUTTER', H'6FAE 'SHUTTER Xo'
|
||||
- CALL: 8 hit(s) - H'B53E 'literal CALL', H'B563 'literal CALL', H'B62F 'literal CALL'
|
||||
- POWER: 0 hit(s)
|
||||
- AUTO: 34 hit(s) - H'693E 'literal AUTO', H'6A52 'literal AUTO', H'6B40 'literal AUTO'
|
||||
- DIAG: 6 hit(s) - H'6BF5 'literal DIAG', H'6C19 'literal DIAG', H'6E46 'literal DIAG'
|
||||
- DXC: 0 hit(s)
|
||||
|
||||
Selector Dispatch Hints:
|
||||
- table H'28A6: 25 non-default/interesting entries
|
||||
- selector 0x000 -> H'2CB9 (dispatch index 0x000)
|
||||
- selector 0x007 -> H'2DC3 (dispatch index 0x007)
|
||||
- selector 0x012 -> H'2E03 (dispatch index 0x012)
|
||||
- selector 0x013 -> H'2E06 (dispatch index 0x013)
|
||||
- selector 0x015 -> H'2E39 (dispatch index 0x015)
|
||||
- selector 0x016 -> H'2E5A (dispatch index 0x016)
|
||||
- selector 0x017 -> H'2E85 (dispatch index 0x017)
|
||||
- selector 0x018 -> H'2E6F (dispatch index 0x018)
|
||||
- selector 0x01A -> H'2EC4 (dispatch index 0x01A)
|
||||
- selector 0x023 -> H'2EE6 (dispatch index 0x023)
|
||||
- selector 0x024 -> H'2F0C (dispatch index 0x024)
|
||||
- selector 0x025 -> H'2F1C (dispatch index 0x025)
|
||||
- selector 0x043 -> H'2F4A (dispatch index 0x043)
|
||||
- selector 0x04A -> H'2F5C (dispatch index 0x04A)
|
||||
- selector 0x04E -> H'2F5C (dispatch index 0x04E)
|
||||
- selector 0x052 -> H'2F5C (dispatch index 0x052)
|
||||
|
||||
Candidate Fake-CCU Seed Plan:
|
||||
- cmd0 seed selector 0x000 = 0x8080: 00 00 00 80 80 5A
|
||||
selector zero active/connect candidate from emulator state search
|
||||
- cmd0 seed selector 0x003 = 0x8000: 00 00 03 80 00 D9
|
||||
ROM default state also sets selector 0x003 high bit
|
||||
- cmd0 seed selector 0x040 = 0xFFFF: 00 00 40 FF FF 1A
|
||||
ROM default all-ones/status candidate touched by bench 0x40 family
|
||||
- cmd0 seed selector 0x0F6 = 0x2000: 00 01 76 20 00 0D
|
||||
sets E1EC bit13 candidate used by loc_48FA report bridge
|
||||
|
||||
Bench Implications:
|
||||
- Do not wait for non-heartbeat reports as the only activation source; the CCU may be expected to push initial table state first.
|
||||
- Use command 0 writes for initial seeding, then command 1 readbacks for verification. Treat command 4/5/6 as continuation-only until a live report proves otherwise.
|
||||
- Selector zero remains the highest-value activation candidate because the emulator reaches CONNECT OK when E000[0]=0x8080 and the selector-zero processing queue runs.
|
||||
- E1EC/selector 0x00F6 is a strong follow-up candidate because loc_48FA tests bit13 there and can enqueue report 0x00F6.
|
||||
- LCD text terms such as CAM/BARS/BLACK/COMM LINK appear in ROM records, but they are not direct serial payload strings; they point to selector-driven display builders.
|
||||
|
||||
Caveats:
|
||||
- Selector names are candidates, not confirmed protocol labels.
|
||||
- Static table xrefs prove that firmware reads/writes a selector; they do not prove the external CCU must seed it on boot.
|
||||
- Generated frames are syntactically valid six-byte host frames; bench safety still depends on timing and current RCP state.
|
||||
4771
build/rom_copy_lcd.asm
Normal file
4771
build/rom_copy_lcd.asm
Normal file
File diff suppressed because it is too large
Load Diff
248176
build/rom_copy_lcd.json
Normal file
248176
build/rom_copy_lcd.json
Normal file
File diff suppressed because it is too large
Load Diff
4259
build/rom_copy_lcd_path.asm
Normal file
4259
build/rom_copy_lcd_path.asm
Normal file
File diff suppressed because it is too large
Load Diff
221997
build/rom_copy_lcd_path.json
Normal file
221997
build/rom_copy_lcd_path.json
Normal file
File diff suppressed because it is too large
Load Diff
203
build/rom_copy_text_linear.asm
Normal file
203
build/rom_copy_text_linear.asm
Normal file
@@ -0,0 +1,203 @@
|
||||
; H8/536 ROM disassembly
|
||||
; input: ROM\M27C512@DIP28_1.BIN
|
||||
; bytes: 65536
|
||||
; vector mode: min
|
||||
; analysis: linear sweep
|
||||
;
|
||||
; Notes from the manual:
|
||||
; - H8/536 uses the H8/500 CPU instruction set.
|
||||
; - In minimum mode the reset vector at H'0000-H'0001 is a 16-bit PC.
|
||||
; - The register field is H'FE80-H'FFFF; names below come from appendix B.
|
||||
; - @aa:8 short absolute operands use BR as the upper address byte.
|
||||
; - SCI baud inference uses section 14.2.8 BRR formulas when SMR/BRR are known.
|
||||
; - LCD inference treats E-clock H'F200/H'F201 accesses as status/control and data candidates.
|
||||
; - Pass --clock-hz to convert SCI BRR settings into numeric baud rates.
|
||||
; - Cycle counts use Appendix A tables A-7/A-8 for on-chip access with no external wait states.
|
||||
|
||||
; Memory Map
|
||||
; H'0000-H'009F exception_vectors vectors
|
||||
; H'00A0-H'00FF dtc_vectors dtc_vectors
|
||||
; H'0100-H'F67F program_or_external program
|
||||
; H'F680-H'FE7F on_chip_ram ram
|
||||
; H'FE80-H'FFFF register_field registers
|
||||
|
||||
; Vectors
|
||||
; H'0000 reset -> vec_reset_1000 (H'1000)
|
||||
; H'0004 invalid_instruction -> vec_reset_1000 (H'1000)
|
||||
; H'0006 zero_divide -> vec_reset_1000 (H'1000)
|
||||
; H'0008 trap_vs -> vec_reset_1000 (H'1000)
|
||||
; H'0010 address_error -> vec_reset_1000 (H'1000)
|
||||
; H'0012 trace -> vec_reset_1000 (H'1000)
|
||||
; H'0016 nmi -> vec_nmi_4393 (H'4393)
|
||||
; H'0020 trapa_0 -> vec_reset_1000 (H'1000)
|
||||
; H'0022 trapa_1 -> vec_reset_1000 (H'1000)
|
||||
; H'0024 trapa_2 -> vec_reset_1000 (H'1000)
|
||||
; H'0026 trapa_3 -> vec_reset_1000 (H'1000)
|
||||
; H'0028 trapa_4 -> vec_reset_1000 (H'1000)
|
||||
; H'002A trapa_5 -> vec_reset_1000 (H'1000)
|
||||
; H'002C trapa_6 -> vec_reset_1000 (H'1000)
|
||||
; H'002E trapa_7 -> vec_reset_1000 (H'1000)
|
||||
; H'0030 trapa_8 -> vec_reset_1000 (H'1000)
|
||||
; H'0032 trapa_9 -> vec_reset_1000 (H'1000)
|
||||
; H'0034 trapa_a -> vec_reset_1000 (H'1000)
|
||||
; H'0036 trapa_b -> vec_reset_1000 (H'1000)
|
||||
; H'0038 trapa_c -> vec_reset_1000 (H'1000)
|
||||
; H'003A trapa_d -> vec_reset_1000 (H'1000)
|
||||
; H'003C trapa_e -> vec_reset_1000 (H'1000)
|
||||
; H'003E trapa_f -> vec_reset_1000 (H'1000)
|
||||
; H'0040 irq0 -> vec_reset_1000 (H'1000)
|
||||
; H'0042 interval_timer -> vec_interval_timer_BFC4 (H'BFC4)
|
||||
; H'0048 irq1 -> vec_reset_1000 (H'1000)
|
||||
; H'0050 irq2 -> vec_reset_1000 (H'1000)
|
||||
; H'0052 irq3 -> vec_irq3_3C30 (H'3C30)
|
||||
; H'0058 irq4 -> vec_irq4_3AC7 (H'3AC7)
|
||||
; H'005A irq5 -> vec_reset_1000 (H'1000)
|
||||
; H'0062 frt1_ocia -> vec_frt1_ocia_BEEA (H'BEEA)
|
||||
; H'006A frt2_ocia -> vec_frt2_ocia_BF23 (H'BF23)
|
||||
; H'0080 sci1_eri -> vec_sci1_eri_BB57 (H'BB57)
|
||||
; H'0082 sci1_rxi -> vec_sci1_rxi_BB67 (H'BB67)
|
||||
; H'0084 sci1_txi -> vec_sci1_txi_BA84 (H'BA84)
|
||||
; H'0090 ad_adi -> vec_ad_adi_3D99 (H'3D99)
|
||||
|
||||
; Symbols
|
||||
; ram_F738 H'F738 on_chip_ram ram r=0 w=2 width=word
|
||||
; ram_F73A H'F73A on_chip_ram ram r=0 w=2 width=word
|
||||
; ram_F73C H'F73C on_chip_ram ram r=0 w=2 width=word
|
||||
; ram_F73E H'F73E on_chip_ram ram r=0 w=3 width=word
|
||||
; ram_F740 H'F740 on_chip_ram ram r=0 w=2 width=word
|
||||
; ram_F742 H'F742 on_chip_ram ram r=0 w=3 width=word
|
||||
; ram_F754 H'F754 on_chip_ram ram r=0 w=3 width=word
|
||||
|
||||
; Board Profile
|
||||
; Board trace ties the H8/536 SCI1 pins to a MAX202 RS232 transceiver.
|
||||
; H8 pin 66 P95/TXD (TXD) -> MAX202 pin 11
|
||||
; H8 pin 67 P96/RXD (RXD) -> MAX202 pin 12
|
||||
; SCI2 pin routing is disabled by SYSCR2.P9SCI2E=0 in the observed setup.
|
||||
|
||||
; LCD/Text Scan
|
||||
; search 'CONNECT': not literal, hits=0
|
||||
; near: H'A025 'COMPLETED', H'9F98 'COPY', H'A008 'COPY'
|
||||
; LCD text regions
|
||||
; region H'9F98-H'A033 count=4 'COPY', 'IN PROGRESS', 'COPY', 'COMPLETED'
|
||||
; LCD text candidates
|
||||
; text H'9F98 len=14 medium 'COPY' xrefs=2
|
||||
; text H'9FB5 len=14 medium 'IN PROGRESS' xrefs=2
|
||||
; text H'A008 len=14 medium 'COPY' xrefs=2
|
||||
; text H'A025 len=14 medium 'COMPLETED' xrefs=2
|
||||
|
||||
9F80: 40 06 CMP:E #H'06, R0 ; cycles=2
|
||||
9F82: 00 NOP ; cycles=2
|
||||
9F83: 1D F7 3E 06 00 MOV:G.W #H'00, @H'F73E ; refs ram_F73E in on_chip_ram; cycles=9
|
||||
9F88: 1D F7 42 06 00 MOV:G.W #H'00, @H'F742 ; refs ram_F742 in on_chip_ram; cycles=11
|
||||
9F8D: 1D F7 54 06 00 MOV:G.W #H'00, @H'F754 ; refs ram_F754 in on_chip_ram; cycles=9
|
||||
9F92: 1E C1 71 BSR loc_6106 ; cycles=13
|
||||
9F95: 20 10 BRA loc_9FA7 ; cycles=8
|
||||
9F97: 06 .db H'06
|
||||
9F98: 20 20 BRA loc_9FBA ; cycles=7
|
||||
9F9A: 20 20 BRA loc_9FBC ; cycles=7
|
||||
9F9C: 20 43 BRA loc_9FE1 ; cycles=7
|
||||
9F9E: 4F 50 59 CMP:I #H'5059, R7 ; cycles=3
|
||||
9FA1: 20 20 BRA loc_9FC3 ; cycles=8
|
||||
9FA3: 20 20 BRA loc_9FC5 ; cycles=8
|
||||
9FA5: 20 07 BRA loc_9FAE ; cycles=8
|
||||
|
||||
loc_9FA7:
|
||||
9FA7: 58 9F 97 MOV:I.W #H'9F97, R0 ; LCD text xref H'9F98 'COPY'; dataflow R0=H'9F97; cycles=3
|
||||
9FAA: 1E BA E4 BSR loc_5A91 ; cycles=13
|
||||
9FAD: 55 01 MOV:E.B #H'01, R5 ; dataflow R5=H'01; cycles=2
|
||||
9FAF: 1E 9F 1A BSR loc_3ECC ; cycles=14
|
||||
9FB2: 20 10 BRA loc_9FC4 ; cycles=7
|
||||
9FB4: 06 .db H'06
|
||||
9FB5: 20 49 BRA loc_A000 ; cycles=8
|
||||
9FB7: 4E 20 50 CMP:I #H'2050, R6 ; cycles=3
|
||||
|
||||
loc_9FBA:
|
||||
9FBA: 52 4F MOV:E.B #H'4F, R2 ; dataflow R2=H'4F; cycles=2
|
||||
|
||||
loc_9FBC:
|
||||
9FBC: 47 52 CMP:E #H'52, R7 ; cycles=2
|
||||
9FBE: 45 53 CMP:E #H'53, R5 ; cycles=2
|
||||
9FC0: 53 20 MOV:E.B #H'20, R3 ; dataflow R3=H'20; cycles=2
|
||||
9FC2: 20 07 BRA loc_9FCB ; cycles=7
|
||||
|
||||
loc_9FC4:
|
||||
9FC4: 58 9F B4 MOV:I.W #H'9FB4, R0 ; LCD text xref H'9FB5 'IN PROGRESS'; dataflow R0=H'9FB4; cycles=3
|
||||
9FC7: 1E BA C7 BSR loc_5A91 ; cycles=14
|
||||
9FCA: 55 02 MOV:E.B #H'02, R5 ; dataflow R5=H'02; cycles=2
|
||||
9FCC: 1E 9E FD BSR loc_3ECC ; cycles=13
|
||||
9FCF: 1E C1 6A BSR loc_613C ; cycles=14
|
||||
9FD2: 1E BA 2F BSR loc_5A04 ; cycles=13
|
||||
9FD5: 19 RTS ; cycles=13
|
||||
9FD6: 00 NOP ; cycles=2
|
||||
9FD7: 00 NOP ; cycles=2
|
||||
9FD8: 00 NOP ; cycles=2
|
||||
9FD9: FF 1D F7 36 SUB.W @(H'1DF7,R7), R6 ; cycles=6
|
||||
9FDD: 06 .db H'06
|
||||
9FDE: 00 NOP ; cycles=2
|
||||
9FDF: 1D F7 38 06 00 MOV:G.W #H'00, @H'F738 ; refs ram_F738 in on_chip_ram; cycles=9
|
||||
9FE4: 1D F7 3A 06 00 MOV:G.W #H'00, @H'F73A ; refs ram_F73A in on_chip_ram; cycles=11
|
||||
9FE9: 1D F7 3C 06 00 MOV:G.W #H'00, @H'F73C ; refs ram_F73C in on_chip_ram; cycles=9
|
||||
9FEE: 1D F7 40 06 00 MOV:G.W #H'00, @H'F740 ; refs ram_F740 in on_chip_ram; cycles=11
|
||||
9FF3: 1D F7 3E 06 00 MOV:G.W #H'00, @H'F73E ; refs ram_F73E in on_chip_ram; cycles=9
|
||||
9FF8: 1D F7 42 06 00 MOV:G.W #H'00, @H'F742 ; refs ram_F742 in on_chip_ram; cycles=11
|
||||
9FFD: 1D F7 54 06 00 MOV:G.W #H'00, @H'F754 ; refs ram_F754 in on_chip_ram; cycles=9
|
||||
A002: 1E C1 01 BSR loc_6106 ; cycles=13
|
||||
A005: 20 10 BRA loc_A017 ; cycles=8
|
||||
A007: 06 .db H'06
|
||||
A008: 20 20 BRA loc_A02A ; cycles=7
|
||||
A00A: 20 20 BRA loc_A02C ; cycles=7
|
||||
A00C: 20 43 BRA loc_A051 ; cycles=7
|
||||
A00E: 4F 50 59 CMP:I #H'5059, R7 ; cycles=3
|
||||
A011: 20 20 BRA loc_A033 ; cycles=8
|
||||
A013: 20 20 BRA loc_A035 ; cycles=8
|
||||
A015: 20 07 BRA loc_A01E ; cycles=8
|
||||
|
||||
loc_A017:
|
||||
A017: 58 A0 07 MOV:I.W #H'A007, R0 ; LCD text xref H'A008 'COPY'; dataflow R0=H'A007; cycles=3
|
||||
A01A: 1E BA 74 BSR loc_5A91 ; cycles=13
|
||||
A01D: 55 01 MOV:E.B #H'01, R5 ; dataflow R5=H'01; cycles=2
|
||||
A01F: 1E 9E AA BSR loc_3ECC ; cycles=14
|
||||
A022: 20 10 BRA loc_A034 ; cycles=7
|
||||
A024: 06 .db H'06
|
||||
A025: 20 20 BRA loc_A047 ; cycles=8
|
||||
A027: 43 4F CMP:E #H'4F, R3 ; cycles=2
|
||||
A029: 4D 50 4C CMP:I #H'504C, R5 ; cycles=3
|
||||
|
||||
loc_A02C:
|
||||
A02C: 45 54 CMP:E #H'54, R5 ; cycles=2
|
||||
A02E: 45 44 CMP:E #H'44, R5 ; cycles=2
|
||||
A030: 20 20 BRA loc_A052 ; cycles=7
|
||||
A032: 20 07 BRA loc_A03B ; cycles=7
|
||||
|
||||
loc_A034:
|
||||
A034: 58 A0 24 MOV:I.W #H'A024, R0 ; LCD text xref H'A025 'COMPLETED'; dataflow R0=H'A024; cycles=3
|
||||
A037: 1E BA 57 BSR loc_5A91 ; cycles=14
|
||||
A03A: 55 02 MOV:E.B #H'02, R5 ; dataflow R5=H'02; cycles=2
|
||||
A03C: 1E 9E 8D BSR loc_3ECC ; cycles=13
|
||||
A03F: 1E C0 FA BSR loc_613C ; cycles=14
|
||||
A042: 1E B9 BF BSR loc_5A04 ; cycles=13
|
||||
A045: 19 RTS ; cycles=13
|
||||
A046: 00 NOP ; cycles=2
|
||||
|
||||
loc_A047:
|
||||
A047: 00 NOP ; cycles=2
|
||||
A048: 00 NOP ; cycles=2
|
||||
A049: FF 1E C2 FB BTST.W #11, @(H'1EC2,R7) ; cycles=6
|
||||
A04D: 19 RTS ; cycles=13
|
||||
A04E: 00 NOP ; cycles=2
|
||||
A04F: 00 NOP ; cycles=2
|
||||
A050: 00 NOP ; cycles=2
|
||||
|
||||
loc_A051:
|
||||
A051: FF 1D F7 36 SUB.W @(H'1DF7,R7), R6 ; cycles=6
|
||||
A055: 06 .db H'06
|
||||
A056: 00 NOP ; cycles=2
|
||||
A057: 1D F7 38 06 00 MOV:G.W #H'00, @H'F738 ; refs ram_F738 in on_chip_ram; cycles=9
|
||||
A05C: 1D F7 3A 06 00 MOV:G.W #H'00, @H'F73A ; refs ram_F73A in on_chip_ram; cycles=11
|
||||
A061: 1D F7 3C 06 00 MOV:G.W #H'00, @H'F73C ; refs ram_F73C in on_chip_ram; cycles=9
|
||||
A066: 1D F7 40 06 00 MOV:G.W #H'00, @H'F740 ; refs ram_F740 in on_chip_ram; cycles=11
|
||||
A06B: 1D F7 3E 06 00 MOV:G.W #H'00, @H'F73E ; refs ram_F73E in on_chip_ram; cycles=9
|
||||
A070: 1D F7 42 06 00 MOV:G.W #H'00, @H'F742 ; refs ram_F742 in on_chip_ram; cycles=11
|
||||
A075: 1D F7 54 07 00 B9 MOV:G.W #H'00B9, @H'F754 ; refs ram_F754 in on_chip_ram; cycles=9
|
||||
A07B: 59 00 A9 MOV:I.W #H'00A9, R1 ; dataflow R1=H'00A9; cycles=3
|
||||
A07E: 58 00 00 MOV:I.W #H'0000, R0 ; dataflow R0=H'0000; cycles=3
|
||||
6016
build/rom_copy_text_linear.json
Normal file
6016
build/rom_copy_text_linear.json
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
8903
build/rom_eeprom_layout.json
Normal file
8903
build/rom_eeprom_layout.json
Normal file
File diff suppressed because it is too large
Load Diff
179
build/rom_eeprom_layout.txt
Normal file
179
build/rom_eeprom_layout.txt
Normal file
@@ -0,0 +1,179 @@
|
||||
H8/536 EEPROM Layout Report
|
||||
|
||||
Summary: The ROM treats the traced P9 bus as two X24164-style EEPROM banks, mirrors a 0x100-byte factory/default block into F400-F4FF, and loads sixteen 8-byte persistent records into F7B0-F82F at boot.
|
||||
Confidence: medium-high
|
||||
|
||||
Physical / Logical Model:
|
||||
- lower_x24164_candidate: logical 0x000-0x7FF control A0/A1
|
||||
- upper_x24164_candidate: logical 0x800-0xFFF control E0/E1
|
||||
- bus: P91/SCL and P97/SDA bit-banged two-wire bus through ROM routines C121/C08B/C0DB/C10C/C142
|
||||
- page model: 16 logical pages of 0x100 bytes; low 8 address bits are sent as the EEPROM word address
|
||||
|
||||
Boot Flow:
|
||||
- H'40BB eeprom_boot_gate: initializes queue/table scratch, checks P7DR.7, then checks F402 == H'6B6F before trusting persisted state
|
||||
- H'4103 factory_default_fill: copies ROM C964-CA63 into F400-F4FF and writes the same 0x100-byte defaults to each EEPROM page
|
||||
- H'4187 record_header_blank: overwrites page offsets 0x00-0x07 on pages 0x1-0xF with four H'2020 words after factory replication; page 0 keeps the signature/options header
|
||||
- H'41D2 persistent_record_load: reads page offsets 0x00-0x07 from pages 0x0-0xF into F7B0-F82F; record 0 is a signature/options header, records 1-F are label/identity-like slots
|
||||
- H'BD2B serial_persist_path: command-4 continuation writes the live value into F400+map[selector] and persists it through BFE0 when F76E.7 is set
|
||||
|
||||
Factory Shadow Block:
|
||||
- ROM H'C964 length 0x100 mirrors to H'F400-H'F4FF
|
||||
- H'F402 offset 0x02 default 0x6B6F (ascii='ko'; xrefs=1)
|
||||
- H'F404 offset 0x04 default 0xFE00 (xrefs=8)
|
||||
- H'F408 offset 0x08 default 0x8000 (selectors=0x004)
|
||||
- H'F40A offset 0x0A default 0x0000 (selectors=0x012)
|
||||
- H'F40C offset 0x0C default 0x0000 (selectors=0x013)
|
||||
- H'F40E offset 0x0E default 0x8000 (selectors=0x017)
|
||||
- H'F410 offset 0x10 default 0x8000 (selectors=0x018)
|
||||
- H'F412 offset 0x12 default 0x0808 (selectors=0x01A)
|
||||
- H'F414 offset 0x14 default 0x0000 (selectors=0x01F)
|
||||
- H'F416 offset 0x16 default 0x0000 (selectors=0x020)
|
||||
- H'F418 offset 0x18 default 0x0000 (selectors=0x023)
|
||||
- H'F41A offset 0x1A default 0x0000 (selectors=0x037)
|
||||
- H'F41C offset 0x1C default 0x0000 (selectors=0x038)
|
||||
- H'F41E offset 0x1E default 0x8000 (selectors=0x080)
|
||||
- H'F420 offset 0x20 default 0x8000 (selectors=0x081)
|
||||
- H'F422 offset 0x22 default 0x0020 (ascii='. '; selectors=0x083)
|
||||
- H'F424 offset 0x24 default 0x0000 (selectors=0x088)
|
||||
- H'F426 offset 0x26 default 0x0400 (selectors=0x089)
|
||||
- H'F428 offset 0x28 default 0x0800 (selectors=0x08B)
|
||||
- H'F42A offset 0x2A default 0x0040 (ascii='.@'; selectors=0x08D)
|
||||
- H'F42C offset 0x2C default 0x0000 (selectors=0x08F)
|
||||
- H'F42E offset 0x2E default 0x8000 (selectors=0x091)
|
||||
- H'F430 offset 0x30 default 0xFF80 (selectors=0x092)
|
||||
- H'F432 offset 0x32 default 0x4040 (ascii='@@'; selectors=0x093)
|
||||
- H'F434 offset 0x34 default 0x0000 (selectors=0x095)
|
||||
- H'F436 offset 0x36 default 0x0000 (selectors=0x098)
|
||||
- H'F438 offset 0x38 default 0x8000 (selectors=0x09A)
|
||||
- H'F43A offset 0x3A default 0x0000 (selectors=0x09D)
|
||||
- H'F43C offset 0x3C default 0x8000 (selectors=0x09E)
|
||||
- H'F43E offset 0x3E default 0x8000 (selectors=0x09F)
|
||||
- H'F440 offset 0x40 default 0x8000 (selectors=0x0A3)
|
||||
- H'F442 offset 0x42 default 0x8000 (selectors=0x0A4)
|
||||
|
||||
Persistent 8-Byte Records:
|
||||
- 16 records: EEPROM 0x000-0x007 .. 0xF00-0xF07 load into RAM H'F7B0-H'F7B7 .. H'F828-H'F82F
|
||||
- record 0x0: EEPROM 0x000-0x007 -> RAM H'F7B0-H'F7B7 default '..ko....'
|
||||
- record 0x1: EEPROM 0x100-0x107 -> RAM H'F7B8-H'F7BF default ' '
|
||||
- record 0x2: EEPROM 0x200-0x207 -> RAM H'F7C0-H'F7C7 default ' '
|
||||
- record 0x3: EEPROM 0x300-0x307 -> RAM H'F7C8-H'F7CF default ' '
|
||||
- record 0x4: EEPROM 0x400-0x407 -> RAM H'F7D0-H'F7D7 default ' '
|
||||
- record 0x5: EEPROM 0x500-0x507 -> RAM H'F7D8-H'F7DF default ' '
|
||||
- record 0x6: EEPROM 0x600-0x607 -> RAM H'F7E0-H'F7E7 default ' '
|
||||
- record 0x7: EEPROM 0x700-0x707 -> RAM H'F7E8-H'F7EF default ' '
|
||||
- record 0x8: EEPROM 0x800-0x807 -> RAM H'F7F0-H'F7F7 default ' '
|
||||
- record 0x9: EEPROM 0x900-0x907 -> RAM H'F7F8-H'F7FF default ' '
|
||||
- record 0xA: EEPROM 0xA00-0xA07 -> RAM H'F800-H'F807 default ' '
|
||||
- record 0xB: EEPROM 0xB00-0xB07 -> RAM H'F808-H'F80F default ' '
|
||||
- record 0xC: EEPROM 0xC00-0xC07 -> RAM H'F810-H'F817 default ' '
|
||||
- record 0xD: EEPROM 0xD00-0xD07 -> RAM H'F818-H'F81F default ' '
|
||||
- record 0xE: EEPROM 0xE00-0xE07 -> RAM H'F820-H'F827 default ' '
|
||||
- record 0xF: EEPROM 0xF00-0xF07 -> RAM H'F828-H'F82F default ' '
|
||||
|
||||
Serial Selector -> Shadow/EEPROM Mapping:
|
||||
- table H'C564 has 89 nonzero low-byte mappings
|
||||
- formula: command 4 persists to EEPROM address (((F76E & 0x0F) << 8) | (mapping_low_byte & 0xFE)) when F76E.7 is set
|
||||
- selector 0x004 map_word=0x4808 -> H'F408 page+0x08 default=0x8000
|
||||
- selector 0x012 map_word=0x080A -> H'F40A page+0x0A default=0x0000
|
||||
- selector 0x013 map_word=0x080C -> H'F40C page+0x0C default=0x0000
|
||||
- selector 0x017 map_word=0x600E -> H'F40E page+0x0E default=0x8000
|
||||
- selector 0x018 map_word=0x6010 -> H'F410 page+0x10 default=0x8000
|
||||
- selector 0x01A map_word=0x1012 -> H'F412 page+0x12 default=0x0808
|
||||
- selector 0x01F map_word=0x4414 -> H'F414 page+0x14 default=0x0000
|
||||
- selector 0x020 map_word=0x4416 -> H'F416 page+0x16 default=0x0000
|
||||
- selector 0x023 map_word=0x0418 -> H'F418 page+0x18 default=0x0000
|
||||
- selector 0x037 map_word=0x641A -> H'F41A page+0x1A default=0x0000
|
||||
- selector 0x038 map_word=0x641C -> H'F41C page+0x1C default=0x0000
|
||||
- selector 0x080 map_word=0xE01E -> H'F41E page+0x1E default=0x8000
|
||||
- selector 0x081 map_word=0x6020 -> H'F420 page+0x20 default=0x8000
|
||||
- selector 0x083 map_word=0x6022 -> H'F422 page+0x22 default=0x0020
|
||||
- selector 0x088 map_word=0x4024 -> H'F424 page+0x24 default=0x0000
|
||||
- selector 0x089 map_word=0x4426 -> H'F426 page+0x26 default=0x0400
|
||||
- selector 0x08B map_word=0x4428 -> H'F428 page+0x28 default=0x0800
|
||||
- selector 0x08D map_word=0x442A -> H'F42A page+0x2A default=0x0040
|
||||
- selector 0x08F map_word=0x602C -> H'F42C page+0x2C default=0x0000
|
||||
- selector 0x091 map_word=0x602E -> H'F42E page+0x2E default=0x8000
|
||||
- selector 0x092 map_word=0x6030 -> H'F430 page+0x30 default=0xFF80
|
||||
- selector 0x093 map_word=0x6032 -> H'F432 page+0x32 default=0x4040
|
||||
- selector 0x095 map_word=0x6034 -> H'F434 page+0x34 default=0x0000
|
||||
- selector 0x098 map_word=0x4036 -> H'F436 page+0x36 default=0x0000
|
||||
- selector 0x09A map_word=0x6038 -> H'F438 page+0x38 default=0x8000
|
||||
- selector 0x09D map_word=0x443A -> H'F43A page+0x3A default=0x0000
|
||||
- selector 0x09E map_word=0x603C -> H'F43C page+0x3C default=0x8000
|
||||
- selector 0x09F map_word=0x603E -> H'F43E page+0x3E default=0x8000
|
||||
- selector 0x0A3 map_word=0x6040 -> H'F440 page+0x40 default=0x8000
|
||||
- selector 0x0A4 map_word=0x6042 -> H'F442 page+0x42 default=0x8000
|
||||
- selector 0x0A5 map_word=0x6044 -> H'F444 page+0x44 default=0x8000
|
||||
- selector 0x0A6 map_word=0x6046 -> H'F446 page+0x46 default=0x8000
|
||||
- selector 0x0A7 map_word=0x4048 -> H'F448 page+0x48 default=0xF000
|
||||
- selector 0x0A9 map_word=0xE04A -> H'F44A page+0x4A default=0x8000
|
||||
- selector 0x0AA map_word=0xC44C -> H'F44C page+0x4C default=0x2000
|
||||
- selector 0x0AC map_word=0xC44E -> H'F44E page+0x4E default=0x8000
|
||||
- selector 0x0AD map_word=0xC450 -> H'F450 page+0x50 default=0x8000
|
||||
- selector 0x0AE map_word=0xC452 -> H'F452 page+0x52 default=0x8000
|
||||
- selector 0x0AF map_word=0xC454 -> H'F454 page+0x54 default=0x8000
|
||||
- selector 0x0B0 map_word=0xC456 -> H'F456 page+0x56 default=0x8000
|
||||
- selector 0x0B2 map_word=0xC458 -> H'F458 page+0x58 default=0x8000
|
||||
- selector 0x0B3 map_word=0xC45A -> H'F45A page+0x5A default=0x8000
|
||||
- selector 0x0B4 map_word=0xC45C -> H'F45C page+0x5C default=0x8000
|
||||
- selector 0x0B6 map_word=0xC45E -> H'F45E page+0x5E default=0x8000
|
||||
- selector 0x0B7 map_word=0x4060 -> H'F460 page+0x60 default=0xF800
|
||||
- selector 0x0B9 map_word=0x6862 -> H'F462 page+0x62 default=0x4000
|
||||
- selector 0x0BC map_word=0xE064 -> H'F464 page+0x64 default=0x8000
|
||||
- selector 0x0BD map_word=0xC066 -> H'F466 page+0x66 default=0x8000
|
||||
- selector 0x0C0 map_word=0x4468 -> H'F468 page+0x68 default=0x8000
|
||||
- selector 0x0C1 map_word=0xC46A -> H'F46A page+0x6A default=0x8000
|
||||
- selector 0x0C3 map_word=0xE46C -> H'F46C page+0x6C default=0x4000
|
||||
- selector 0x0C4 map_word=0x446E -> H'F46E page+0x6E default=0x8000
|
||||
- selector 0x0C5 map_word=0xC070 -> H'F470 page+0x70 default=0x8000
|
||||
- selector 0x0C6 map_word=0x4472 -> H'F472 page+0x72 default=0x8000
|
||||
- selector 0x0C7 map_word=0xC474 -> H'F474 page+0x74 default=0x8000
|
||||
- selector 0x0C8 map_word=0xC476 -> H'F476 page+0x76 default=0x0000
|
||||
- selector 0x0C9 map_word=0xC478 -> H'F478 page+0x78 default=0x0000
|
||||
- selector 0x0CA map_word=0xC47A -> H'F47A page+0x7A default=0x0000
|
||||
- selector 0x0CB map_word=0xC47C -> H'F47C page+0x7C default=0x0000
|
||||
- selector 0x0CC map_word=0xC47E -> H'F47E page+0x7E default=0x0000
|
||||
- selector 0x0CD map_word=0xC480 -> H'F480 page+0x80 default=0x0000
|
||||
- selector 0x0D4 map_word=0xC482 -> H'F482 page+0x82 default=0x8000
|
||||
- selector 0x0D5 map_word=0xC484 -> H'F484 page+0x84 default=0x8000
|
||||
- selector 0x0D6 map_word=0xC086 -> H'F486 page+0x86 default=0x8000
|
||||
- selector 0x0D7 map_word=0xC088 -> H'F488 page+0x88 default=0x8000
|
||||
- selector 0x0D8 map_word=0x408A -> H'F48A page+0x8A default=0x8000
|
||||
- selector 0x0D9 map_word=0x408C -> H'F48C page+0x8C default=0x8000
|
||||
- selector 0x0DA map_word=0x408E -> H'F48E page+0x8E default=0x8000
|
||||
- selector 0x0F6 map_word=0x4090 -> H'F490 page+0x90 default=0x8000
|
||||
- selector 0x0F9 map_word=0x4492 -> H'F492 page+0x92 default=0x8000
|
||||
- selector 0x0FA map_word=0x4494 -> H'F494 page+0x94 default=0x8000
|
||||
- selector 0x0FB map_word=0x4496 -> H'F496 page+0x96 default=0x8000
|
||||
- selector 0x0FC map_word=0x4498 -> H'F498 page+0x98 default=0x8000
|
||||
- selector 0x0FD map_word=0x409A -> H'F49A page+0x9A default=0x8000
|
||||
- selector 0x0FE map_word=0x449C -> H'F49C page+0x9C default=0x8000
|
||||
- selector 0x0FF map_word=0x449E -> H'F49E page+0x9E default=0x8000
|
||||
- selector 0x100 map_word=0x44A0 -> H'F4A0 page+0xA0 default=0x8000
|
||||
- selector 0x101 map_word=0x44A2 -> H'F4A2 page+0xA2 default=0x8000
|
||||
- selector 0x10F map_word=0xC4A4 -> H'F4A4 page+0xA4 default=0x8000
|
||||
- selector 0x110 map_word=0x48A6 -> H'F4A6 page+0xA6 default=0x0000
|
||||
- ... 9 more mapped selectors omitted
|
||||
|
||||
State Byte Hints:
|
||||
- H'F402 factory_signature_word: factory 0x6B6F; boot accepts persisted state only when this word is H'6B6F (xrefs=1)
|
||||
- H'F404 feature_or_option_flags_candidate: factory 0xFE00; bits 1-4 are tested with F791 gates in display/status routines (xrefs=8)
|
||||
- H'F730 connect_display_state_candidate: volatile/no factory word (xrefs=3)
|
||||
- H'F731 session_latch_candidate: volatile/no factory word (xrefs=22)
|
||||
- H'F732 display_dispatch_selector_candidate: volatile display dispatch selector feeding the 493E pointer table and 48FA report bridge (xrefs=11)
|
||||
- H'F76E eeprom_page_and_persist_flags: bit7 enables command-4 EEPROM persistence, bit6 suppresses 48FA dispatch, low nibble selects EEPROM page (xrefs=4)
|
||||
- H'F790 connection_latch_shadow_candidate: volatile/no factory word (xrefs=1)
|
||||
- H'F791 feature_flag_gate_candidate: volatile gate tested alongside F404 option bits before setting report/display flags (xrefs=12)
|
||||
- H'FB03 report_bridge_suppress_candidate: volatile/no factory word (xrefs=10)
|
||||
|
||||
Bench Implications:
|
||||
- A live EEPROM dump should first compare F400-F4FF shadow-equivalent offsets against the ROM factory table, especially F402/F404 and mapped offsets.
|
||||
- Pages 0x0-0xF offset 0x00-0x07 are loaded into F7B0-F82F; page 0 carries the signature/options header and pages 1-F default to spaces, so non-space bytes there are high-value identity/config data.
|
||||
- Serial command 0/4 can mirror values into F400 offsets selected by the ROM mapping table, but command 4 only persists when the continuation path reaches BD2B and F76E.7 is set.
|
||||
- F76E is not just a page byte: bit7 gates EEPROM persistence, bit6 suppresses the 48FA dispatch path, and only its low nibble survives into the EEPROM page address.
|
||||
- CONNECT OK is still likely gated by volatile table/session state as well as EEPROM-backed defaults; EEPROM differences may explain why bench and emulator diverge, but are unlikely to be the whole protocol by themselves.
|
||||
|
||||
Caveats:
|
||||
- The selector map proves where firmware mirrors/persists serial values, not what every field means to the panel UI.
|
||||
- High bytes in the C564 selector map look structured, but the observed command-0/command-4 paths only use the low byte for F400/EEPROM offsets.
|
||||
- Indexed F7B0-F82F record consumers can be missed by a static xref pass; dynamic emulator traces should be used once interesting record bytes are found.
|
||||
433
build/rom_f109_handlers.asm
Normal file
433
build/rom_f109_handlers.asm
Normal file
@@ -0,0 +1,433 @@
|
||||
; H8/536 ROM disassembly
|
||||
; input: ROM\M27C512@DIP28_1.BIN
|
||||
; bytes: 65536
|
||||
; vector mode: min
|
||||
; analysis: recursive trace from vectors
|
||||
;
|
||||
; Notes from the manual:
|
||||
; - H8/536 uses the H8/500 CPU instruction set.
|
||||
; - In minimum mode the reset vector at H'0000-H'0001 is a 16-bit PC.
|
||||
; - The register field is H'FE80-H'FFFF; names below come from appendix B.
|
||||
; - @aa:8 short absolute operands use BR as the upper address byte.
|
||||
; - SCI baud inference uses section 14.2.8 BRR formulas when SMR/BRR are known.
|
||||
; - LCD inference treats E-clock H'F200/H'F201 accesses as status/control and data candidates.
|
||||
; - Pass --clock-hz to convert SCI BRR settings into numeric baud rates.
|
||||
; - Cycle counts use Appendix A tables A-7/A-8 for on-chip access with no external wait states.
|
||||
|
||||
; Memory Map
|
||||
; H'0000-H'009F exception_vectors vectors
|
||||
; H'00A0-H'00FF dtc_vectors dtc_vectors
|
||||
; H'0100-H'F67F program_or_external program
|
||||
; H'F680-H'FE7F on_chip_ram ram
|
||||
; H'FE80-H'FFFF register_field registers
|
||||
|
||||
; Vectors
|
||||
; H'0000 reset -> vec_reset_1000 (H'1000)
|
||||
; H'0004 invalid_instruction -> vec_reset_1000 (H'1000)
|
||||
; H'0006 zero_divide -> vec_reset_1000 (H'1000)
|
||||
; H'0008 trap_vs -> vec_reset_1000 (H'1000)
|
||||
; H'0010 address_error -> vec_reset_1000 (H'1000)
|
||||
; H'0012 trace -> vec_reset_1000 (H'1000)
|
||||
; H'0016 nmi -> vec_nmi_4393 (H'4393)
|
||||
; H'0020 trapa_0 -> vec_reset_1000 (H'1000)
|
||||
; H'0022 trapa_1 -> vec_reset_1000 (H'1000)
|
||||
; H'0024 trapa_2 -> vec_reset_1000 (H'1000)
|
||||
; H'0026 trapa_3 -> vec_reset_1000 (H'1000)
|
||||
; H'0028 trapa_4 -> vec_reset_1000 (H'1000)
|
||||
; H'002A trapa_5 -> vec_reset_1000 (H'1000)
|
||||
; H'002C trapa_6 -> vec_reset_1000 (H'1000)
|
||||
; H'002E trapa_7 -> vec_reset_1000 (H'1000)
|
||||
; H'0030 trapa_8 -> vec_reset_1000 (H'1000)
|
||||
; H'0032 trapa_9 -> vec_reset_1000 (H'1000)
|
||||
; H'0034 trapa_a -> vec_reset_1000 (H'1000)
|
||||
; H'0036 trapa_b -> vec_reset_1000 (H'1000)
|
||||
; H'0038 trapa_c -> vec_reset_1000 (H'1000)
|
||||
; H'003A trapa_d -> vec_reset_1000 (H'1000)
|
||||
; H'003C trapa_e -> vec_reset_1000 (H'1000)
|
||||
; H'003E trapa_f -> vec_reset_1000 (H'1000)
|
||||
; H'0040 irq0 -> vec_reset_1000 (H'1000)
|
||||
; H'0042 interval_timer -> vec_interval_timer_BFC4 (H'BFC4)
|
||||
; H'0048 irq1 -> vec_reset_1000 (H'1000)
|
||||
; H'0050 irq2 -> vec_reset_1000 (H'1000)
|
||||
; H'0052 irq3 -> vec_irq3_3C30 (H'3C30)
|
||||
; H'0058 irq4 -> vec_irq4_3AC7 (H'3AC7)
|
||||
; H'005A irq5 -> vec_reset_1000 (H'1000)
|
||||
; H'0062 frt1_ocia -> vec_frt1_ocia_BEEA (H'BEEA)
|
||||
; H'006A frt2_ocia -> vec_frt2_ocia_BF23 (H'BF23)
|
||||
; H'0080 sci1_eri -> vec_sci1_eri_BB57 (H'BB57)
|
||||
; H'0082 sci1_rxi -> vec_sci1_rxi_BB67 (H'BB67)
|
||||
; H'0084 sci1_txi -> vec_sci1_txi_BA84 (H'BA84)
|
||||
; H'0090 ad_adi -> vec_ad_adi_3D99 (H'3D99)
|
||||
|
||||
; Symbols
|
||||
; mem_E106 H'E106 program_or_external memory r=5 w=2 width=word
|
||||
; mem_E110 H'E110 program_or_external memory r=7 w=0 width=word
|
||||
; mem_E11E H'E11E program_or_external memory r=4 w=0 width=word
|
||||
; mem_E506 H'E506 program_or_external memory r=2 w=0 width=word
|
||||
; mem_E906 H'E906 program_or_external memory r=0 w=4 width=word
|
||||
; mem_E91E H'E91E program_or_external memory r=0 w=2 width=word
|
||||
; mem_E922 H'E922 program_or_external memory r=0 w=1 width=word
|
||||
; mem_F404 H'F404 program_or_external memory r=11 w=0 width=byte
|
||||
; ram_F6D0 H'F6D0 on_chip_ram ram r=13 w=0 width=byte
|
||||
; ram_F6F4 H'F6F4 on_chip_ram ram r=0 w=2 width=word
|
||||
; ram_F6F6 H'F6F6 on_chip_ram ram r=0 w=4 width=byte
|
||||
; ram_F730 H'F730 on_chip_ram ram r=4 w=0 width=byte
|
||||
; ram_F731 H'F731 on_chip_ram ram r=7 w=0 width=byte
|
||||
; ram_F791 H'F791 on_chip_ram ram r=11 w=0 width=byte
|
||||
|
||||
; Board Profile
|
||||
; Board trace ties the H8/536 SCI1 pins to a MAX202 RS232 transceiver.
|
||||
; H8 pin 66 P95/TXD (TXD) -> MAX202 pin 11
|
||||
; H8 pin 67 P96/RXD (RXD) -> MAX202 pin 12
|
||||
; SCI2 pin routing is disabled by SYSCR2.P9SCI2E=0 in the observed setup.
|
||||
|
||||
; LCD/Text Scan
|
||||
; search 'CONNECT': not literal, hits=0
|
||||
; LCD text candidates
|
||||
; ... 1 more LCD text candidates
|
||||
|
||||
2390: 15 F6 D0 F1 BTST.B #1, @H'F6D0 ; refs ram_F6D0 in on_chip_ram; cycles=7
|
||||
2394: 37 00 70 BEQ loc_2407 ; cycles=3/7 nt/t
|
||||
2397: 15 F7 31 04 02 CMP:G.B #H'02, @H'F731 ; refs ram_F731 in on_chip_ram; cycles=6
|
||||
239C: 32 00 68 BHI loc_2407 ; cycles=3/7 nt/t
|
||||
239F: 1D E1 10 FF BTST.W #15, @H'E110 ; refs mem_E110 in program_or_external; cycles=6
|
||||
23A3: 27 05 BEQ loc_23AA ; cycles=3/8 nt/t
|
||||
23A5: 1E 03 40 BSR loc_26E8 ; cycles=14
|
||||
23A8: 20 5D BRA loc_2407 ; cycles=7
|
||||
|
||||
loc_23AA:
|
||||
23AA: 15 F6 D0 F2 BTST.B #2, @H'F6D0 ; refs ram_F6D0 in on_chip_ram; cycles=7
|
||||
23AE: 36 00 CF BNE loc_2480 ; cycles=3/7 nt/t
|
||||
23B1: 15 F7 30 F7 BTST.B #7, @H'F730 ; refs ram_F730 in on_chip_ram; cycles=6
|
||||
23B5: 27 35 BEQ loc_23EC ; cycles=3/8 nt/t
|
||||
23B7: 1D E1 06 80 MOV:G.W @H'E106, R0 ; refs mem_E106 in program_or_external; cycles=6
|
||||
|
||||
loc_23BB:
|
||||
23BB: A8 1B SHLR.W R0 ; cycles=3
|
||||
|
||||
loc_23BD:
|
||||
23BD: A8 81 MOV:G.W R0, R1 ; cycles=3
|
||||
23BF: 27 26 BEQ loc_23E7 ; cycles=3/8 nt/t
|
||||
23C1: 1D E5 06 51 AND.W @H'E506, R1 ; refs mem_E506 in program_or_external; cycles=6
|
||||
23C5: 0C FF C4 51 AND.W #H'FFC4, R1 ; cycles=4
|
||||
23C9: 27 F0 BEQ loc_23BB ; cycles=3/8 nt/t
|
||||
23CB: 1D E9 06 91 MOV:G.W R1, @H'E906 ; refs mem_E906 in program_or_external; cycles=6
|
||||
23CF: 52 80 MOV:E.B #H'80, R2 ; dataflow R2=H'80; cycles=2
|
||||
23D1: 5B 00 83 MOV:I.W #H'0083, R3 ; dataflow R3=H'0083; cycles=3
|
||||
23D4: 15 F7 91 F7 BTST.B #7, @H'F791 ; refs ram_F791 in on_chip_ram; cycles=7
|
||||
23D8: 27 08 BEQ loc_23E2 ; cycles=3/7 nt/t
|
||||
23DA: 15 F4 04 F5 BTST.B #5, @H'F404 ; refs mem_F404 in program_or_external; cycles=7
|
||||
23DE: 27 02 BEQ loc_23E2 ; cycles=3/7 nt/t
|
||||
23E0: AB CE BSET.W #14, R3 ; cycles=3
|
||||
|
||||
loc_23E2:
|
||||
23E2: 1E 1A 6F BSR loc_3E54 ; cycles=13
|
||||
23E5: 20 20 BRA loc_2407 ; cycles=8
|
||||
|
||||
loc_23E7:
|
||||
23E7: 58 00 04 MOV:I.W #H'0004, R0 ; dataflow R0=H'0004; cycles=3
|
||||
23EA: 20 48 BRA loc_2434 ; cycles=7
|
||||
|
||||
loc_23EC:
|
||||
23EC: 1D E1 06 D0 BCLR.W #0, @H'E106 ; refs mem_E106 in program_or_external; cycles=9
|
||||
23F0: 5C 00 00 MOV:I.W #H'0000, R4 ; dataflow R4=H'0000; cycles=3
|
||||
23F3: 5B 00 83 MOV:I.W #H'0083, R3 ; dataflow R3=H'0083; cycles=3
|
||||
23F6: 15 F7 91 F7 BTST.B #7, @H'F791 ; refs ram_F791 in on_chip_ram; cycles=7
|
||||
23FA: 27 08 BEQ loc_2404 ; cycles=3/7 nt/t
|
||||
23FC: 15 F4 04 F5 BTST.B #5, @H'F404 ; refs mem_F404 in program_or_external; cycles=7
|
||||
2400: 27 02 BEQ loc_2404 ; cycles=3/7 nt/t
|
||||
2402: AB CE BSET.W #14, R3 ; cycles=3
|
||||
|
||||
loc_2404:
|
||||
2404: 1E F6 2E BSR loc_1A35 ; cycles=13
|
||||
|
||||
loc_2407:
|
||||
2407: 19 RTS ; cycles=13
|
||||
2408: 15 F6 D0 F2 BTST.B #2, @H'F6D0 ; refs ram_F6D0 in on_chip_ram; cycles=7
|
||||
240C: 37 00 70 BEQ loc_247F ; cycles=3/7 nt/t
|
||||
240F: 15 F7 31 04 02 CMP:G.B #H'02, @H'F731 ; refs ram_F731 in on_chip_ram; cycles=6
|
||||
2414: 32 00 68 BHI loc_247F ; cycles=3/7 nt/t
|
||||
2417: 1D E1 10 FF BTST.W #15, @H'E110 ; refs mem_E110 in program_or_external; cycles=6
|
||||
241B: 27 05 BEQ loc_2422 ; cycles=3/8 nt/t
|
||||
241D: 1E 02 C8 BSR loc_26E8 ; cycles=14
|
||||
2420: 20 5D BRA loc_247F ; cycles=7
|
||||
|
||||
loc_2422:
|
||||
2422: 15 F6 D0 F1 BTST.B #1, @H'F6D0 ; refs ram_F6D0 in on_chip_ram; cycles=7
|
||||
2426: 26 58 BNE loc_2480 ; cycles=3/7 nt/t
|
||||
2428: 15 F7 30 F7 BTST.B #7, @H'F730 ; refs ram_F730 in on_chip_ram; cycles=7
|
||||
242C: 27 36 BEQ loc_2464 ; cycles=3/7 nt/t
|
||||
242E: 1D E1 06 80 MOV:G.W @H'E106, R0 ; refs mem_E106 in program_or_external; cycles=7
|
||||
|
||||
loc_2432:
|
||||
2432: A8 1A SHLL.W R0 ; cycles=3
|
||||
|
||||
loc_2434:
|
||||
2434: A8 81 MOV:G.W R0, R1 ; cycles=3
|
||||
2436: 27 26 BEQ loc_245E ; cycles=3/7 nt/t
|
||||
2438: 1D E5 06 51 AND.W @H'E506, R1 ; refs mem_E506 in program_or_external; cycles=7
|
||||
243C: 0C FF C4 51 AND.W #H'FFC4, R1 ; cycles=4
|
||||
2440: 27 F0 BEQ loc_2432 ; cycles=3/7 nt/t
|
||||
2442: 1D E9 06 91 MOV:G.W R1, @H'E906 ; refs mem_E906 in program_or_external; cycles=7
|
||||
2446: 52 80 MOV:E.B #H'80, R2 ; dataflow R2=H'80; cycles=2
|
||||
2448: 5B 00 83 MOV:I.W #H'0083, R3 ; dataflow R3=H'0083; cycles=3
|
||||
244B: 15 F7 91 F7 BTST.B #7, @H'F791 ; refs ram_F791 in on_chip_ram; cycles=6
|
||||
244F: 27 08 BEQ loc_2459 ; cycles=3/8 nt/t
|
||||
2451: 15 F4 04 F5 BTST.B #5, @H'F404 ; refs mem_F404 in program_or_external; cycles=6
|
||||
2455: 27 02 BEQ loc_2459 ; cycles=3/8 nt/t
|
||||
2457: AB CE BSET.W #14, R3 ; cycles=3
|
||||
|
||||
loc_2459:
|
||||
2459: 1E 19 F8 BSR loc_3E54 ; cycles=14
|
||||
245C: 20 21 BRA loc_247F ; cycles=7
|
||||
|
||||
loc_245E:
|
||||
245E: 58 80 00 MOV:I.W #H'8000, R0 ; dataflow R0=H'8000; cycles=3
|
||||
2461: 30 FF 59 BRA loc_23BD ; cycles=8
|
||||
|
||||
loc_2464:
|
||||
2464: 1D E1 06 D0 BCLR.W #0, @H'E106 ; refs mem_E106 in program_or_external; cycles=9
|
||||
2468: 5C 00 01 MOV:I.W #H'0001, R4 ; dataflow R4=H'0001; cycles=3
|
||||
246B: 5B 00 83 MOV:I.W #H'0083, R3 ; dataflow R3=H'0083; cycles=3
|
||||
246E: 15 F7 91 F7 BTST.B #7, @H'F791 ; refs ram_F791 in on_chip_ram; cycles=7
|
||||
2472: 27 08 BEQ loc_247C ; cycles=3/7 nt/t
|
||||
2474: 15 F4 04 F5 BTST.B #5, @H'F404 ; refs mem_F404 in program_or_external; cycles=7
|
||||
2478: 27 02 BEQ loc_247C ; cycles=3/7 nt/t
|
||||
247A: AB CE BSET.W #14, R3 ; cycles=3
|
||||
|
||||
loc_247C:
|
||||
247C: 1E F5 B6 BSR loc_1A35 ; cycles=13
|
||||
|
||||
loc_247F:
|
||||
247F: 19 RTS ; cycles=13
|
||||
|
||||
loc_2480:
|
||||
2480: 15 F7 30 F7 BTST.B #7, @H'F730 ; refs ram_F730 in on_chip_ram; cycles=7
|
||||
2484: 27 05 BEQ loc_248B ; cycles=3/7 nt/t
|
||||
2486: 58 40 00 MOV:I.W #H'4000, R0 ; dataflow R0=H'4000; cycles=3
|
||||
2489: 20 03 BRA loc_248E ; cycles=8
|
||||
|
||||
loc_248B:
|
||||
248B: 58 00 20 MOV:I.W #H'0020, R0 ; dataflow R0=H'0020; cycles=3
|
||||
|
||||
loc_248E:
|
||||
248E: 1D E9 06 90 MOV:G.W R0, @H'E906 ; refs mem_E906 in program_or_external; cycles=7
|
||||
2492: 52 80 MOV:E.B #H'80, R2 ; dataflow R2=H'80; cycles=2
|
||||
2494: 5B 00 83 MOV:I.W #H'0083, R3 ; dataflow R3=H'0083; cycles=3
|
||||
2497: 15 F7 91 F7 BTST.B #7, @H'F791 ; refs ram_F791 in on_chip_ram; cycles=6
|
||||
249B: 27 08 BEQ loc_24A5 ; cycles=3/8 nt/t
|
||||
249D: 15 F4 04 F5 BTST.B #5, @H'F404 ; refs mem_F404 in program_or_external; cycles=6
|
||||
24A1: 27 02 BEQ loc_24A5 ; cycles=3/8 nt/t
|
||||
24A3: AB CE BSET.W #14, R3 ; cycles=3
|
||||
|
||||
loc_24A5:
|
||||
24A5: 1E 19 AC BSR loc_3E54 ; cycles=14
|
||||
24A8: 19 RTS ; cycles=12
|
||||
24A9: 15 F6 D0 F3 BTST.B #3, @H'F6D0 ; refs ram_F6D0 in on_chip_ram; cycles=6
|
||||
24AD: 27 38 BEQ loc_24E7 ; cycles=3/8 nt/t
|
||||
24AF: 15 F7 31 04 02 CMP:G.B #H'02, @H'F731 ; refs ram_F731 in on_chip_ram; cycles=6
|
||||
24B4: 22 31 BHI loc_24E7 ; cycles=3/7 nt/t
|
||||
24B6: 1D E1 10 FF BTST.W #15, @H'E110 ; refs mem_E110 in program_or_external; cycles=7
|
||||
24BA: 27 05 BEQ loc_24C1 ; cycles=3/7 nt/t
|
||||
24BC: 1E 02 29 BSR loc_26E8 ; cycles=13
|
||||
24BF: 20 26 BRA loc_24E7 ; cycles=8
|
||||
|
||||
loc_24C1:
|
||||
24C1: 15 F7 30 F7 BTST.B #7, @H'F730 ; refs ram_F730 in on_chip_ram; cycles=6
|
||||
24C5: 27 20 BEQ loc_24E7 ; cycles=3/8 nt/t
|
||||
24C7: 1D E1 06 80 MOV:G.W @H'E106, R0 ; refs mem_E106 in program_or_external; cycles=6
|
||||
24CB: A8 E0 BNOT.W #0, R0 ; cycles=3
|
||||
24CD: 1D E9 06 90 MOV:G.W R0, @H'E906 ; refs mem_E906 in program_or_external; cycles=6
|
||||
24D1: 52 80 MOV:E.B #H'80, R2 ; dataflow R2=H'80; cycles=2
|
||||
24D3: 5B 00 83 MOV:I.W #H'0083, R3 ; dataflow R3=H'0083; cycles=3
|
||||
24D6: 15 F7 91 F7 BTST.B #7, @H'F791 ; refs ram_F791 in on_chip_ram; cycles=7
|
||||
24DA: 27 08 BEQ loc_24E4 ; cycles=3/7 nt/t
|
||||
24DC: 15 F4 04 F5 BTST.B #5, @H'F404 ; refs mem_F404 in program_or_external; cycles=7
|
||||
24E0: 27 02 BEQ loc_24E4 ; cycles=3/7 nt/t
|
||||
24E2: AB CE BSET.W #14, R3 ; cycles=3
|
||||
|
||||
loc_24E4:
|
||||
24E4: 1E 19 6D BSR loc_3E54 ; cycles=13
|
||||
|
||||
loc_24E7:
|
||||
24E7: 19 RTS ; cycles=13
|
||||
24E8: 15 F6 D0 F7 BTST.B #7, @H'F6D0 ; refs ram_F6D0 in on_chip_ram; cycles=7
|
||||
24EC: 27 3F BEQ loc_252D ; cycles=3/7 nt/t
|
||||
24EE: 15 F7 31 04 02 CMP:G.B #H'02, @H'F731 ; refs ram_F731 in on_chip_ram; cycles=7
|
||||
24F3: 22 38 BHI loc_252D ; cycles=3/8 nt/t
|
||||
24F5: 1D E1 10 FE BTST.W #14, @H'E110 ; refs mem_E110 in program_or_external; cycles=6
|
||||
24F9: 27 05 BEQ loc_2500 ; cycles=3/8 nt/t
|
||||
24FB: 1E 01 EA BSR loc_26E8 ; cycles=14
|
||||
24FE: 20 2D BRA loc_252D ; cycles=7
|
||||
|
||||
loc_2500:
|
||||
2500: 15 F6 F6 13 CLR.B @H'F6F6 ; refs ram_F6F6 in on_chip_ram; cycles=9
|
||||
2504: 1D E1 1E 80 MOV:G.W @H'E11E, R0 ; refs mem_E11E in program_or_external; cycles=7
|
||||
2508: A8 FF BTST.W #15, R0 ; cycles=3
|
||||
250A: 26 05 BNE loc_2511 ; cycles=3/7 nt/t
|
||||
250C: 58 80 00 MOV:I.W #H'8000, R0 ; dataflow R0=H'8000; cycles=3
|
||||
250F: 20 02 BRA loc_2513 ; cycles=8
|
||||
|
||||
loc_2511:
|
||||
2511: A8 13 CLR.W R0 ; dataflow R0=H'0000; cycles=3
|
||||
|
||||
loc_2513:
|
||||
2513: 1D E9 1E 90 MOV:G.W R0, @H'E91E ; refs mem_E91E in program_or_external; cycles=6
|
||||
2517: 52 80 MOV:E.B #H'80, R2 ; dataflow R2=H'80; cycles=2
|
||||
2519: 5B 00 8F MOV:I.W #H'008F, R3 ; dataflow R3=H'008F; cycles=3
|
||||
251C: 15 F7 91 F7 BTST.B #7, @H'F791 ; refs ram_F791 in on_chip_ram; cycles=7
|
||||
2520: 27 08 BEQ loc_252A ; cycles=3/7 nt/t
|
||||
2522: 15 F4 04 F4 BTST.B #4, @H'F404 ; refs mem_F404 in program_or_external; cycles=7
|
||||
2526: 27 02 BEQ loc_252A ; cycles=3/7 nt/t
|
||||
2528: AB CE BSET.W #14, R3 ; cycles=3
|
||||
|
||||
loc_252A:
|
||||
252A: 1E 19 27 BSR loc_3E54 ; cycles=13
|
||||
|
||||
loc_252D:
|
||||
252D: 19 RTS ; cycles=13
|
||||
252E: 15 F6 D0 F6 BTST.B #6, @H'F6D0 ; refs ram_F6D0 in on_chip_ram; cycles=7
|
||||
2532: 27 3F BEQ loc_2573 ; cycles=3/7 nt/t
|
||||
2534: 15 F7 31 04 02 CMP:G.B #H'02, @H'F731 ; refs ram_F731 in on_chip_ram; cycles=7
|
||||
2539: 22 38 BHI loc_2573 ; cycles=3/8 nt/t
|
||||
253B: 1D E1 10 FE BTST.W #14, @H'E110 ; refs mem_E110 in program_or_external; cycles=6
|
||||
253F: 27 05 BEQ loc_2546 ; cycles=3/8 nt/t
|
||||
2541: 1E 01 A4 BSR loc_26E8 ; cycles=14
|
||||
2544: 20 2D BRA loc_2573 ; cycles=7
|
||||
|
||||
loc_2546:
|
||||
2546: 15 F6 F6 13 CLR.B @H'F6F6 ; refs ram_F6F6 in on_chip_ram; cycles=9
|
||||
254A: 1D E1 1E 80 MOV:G.W @H'E11E, R0 ; refs mem_E11E in program_or_external; cycles=7
|
||||
254E: A8 FD BTST.W #13, R0 ; cycles=3
|
||||
2550: 26 05 BNE loc_2557 ; cycles=3/7 nt/t
|
||||
2552: 58 20 00 MOV:I.W #H'2000, R0 ; dataflow R0=H'2000; cycles=3
|
||||
2555: 20 02 BRA loc_2559 ; cycles=8
|
||||
|
||||
loc_2557:
|
||||
2557: A8 13 CLR.W R0 ; dataflow R0=H'0000; cycles=3
|
||||
|
||||
loc_2559:
|
||||
2559: 1D E9 1E 90 MOV:G.W R0, @H'E91E ; refs mem_E91E in program_or_external; cycles=6
|
||||
255D: 52 80 MOV:E.B #H'80, R2 ; dataflow R2=H'80; cycles=2
|
||||
255F: 5B 00 8F MOV:I.W #H'008F, R3 ; dataflow R3=H'008F; cycles=3
|
||||
2562: 15 F7 91 F7 BTST.B #7, @H'F791 ; refs ram_F791 in on_chip_ram; cycles=7
|
||||
2566: 27 08 BEQ loc_2570 ; cycles=3/7 nt/t
|
||||
2568: 15 F4 04 F4 BTST.B #4, @H'F404 ; refs mem_F404 in program_or_external; cycles=7
|
||||
256C: 27 02 BEQ loc_2570 ; cycles=3/7 nt/t
|
||||
256E: AB CE BSET.W #14, R3 ; cycles=3
|
||||
|
||||
loc_2570:
|
||||
2570: 1E 18 E1 BSR loc_3E54 ; cycles=13
|
||||
|
||||
loc_2573:
|
||||
2573: 19 RTS ; cycles=13
|
||||
2574: 15 F6 D0 F4 BTST.B #4, @H'F6D0 ; refs ram_F6D0 in on_chip_ram; cycles=7
|
||||
2578: 37 01 45 BEQ loc_26C0 ; cycles=3/7 nt/t
|
||||
257B: 15 F7 31 04 02 CMP:G.B #H'02, @H'F731 ; refs ram_F731 in on_chip_ram; cycles=6
|
||||
2580: 22 51 BHI loc_25D3 ; cycles=3/7 nt/t
|
||||
2582: 1D E1 10 FE BTST.W #14, @H'E110 ; refs mem_E110 in program_or_external; cycles=7
|
||||
2586: 27 05 BEQ loc_258D ; cycles=3/7 nt/t
|
||||
2588: 1E 01 5D BSR loc_26E8 ; cycles=13
|
||||
258B: 20 46 BRA loc_25D3 ; cycles=8
|
||||
|
||||
loc_258D:
|
||||
258D: 1D E1 1E 80 MOV:G.W @H'E11E, R0 ; refs mem_E11E in program_or_external; cycles=6
|
||||
2591: A8 FF BTST.W #15, R0 ; cycles=3
|
||||
2593: 26 06 BNE loc_259B ; cycles=3/8 nt/t
|
||||
2595: A8 FD BTST.W #13, R0 ; cycles=3
|
||||
2597: 26 26 BNE loc_25BF ; cycles=3/8 nt/t
|
||||
2599: 20 38 BRA loc_25D3 ; cycles=8
|
||||
|
||||
loc_259B:
|
||||
259B: 15 F6 D0 F5 BTST.B #5, @H'F6D0 ; refs ram_F6D0 in on_chip_ram; cycles=6
|
||||
259F: 27 05 BEQ loc_25A6 ; cycles=3/8 nt/t
|
||||
25A1: 1E 00 8F BSR loc_2633 ; cycles=14
|
||||
25A4: 20 2D BRA loc_25D3 ; cycles=7
|
||||
|
||||
loc_25A6:
|
||||
25A6: 5C 00 00 MOV:I.W #H'0000, R4 ; dataflow R4=H'0000; cycles=3
|
||||
25A9: 5B 00 91 MOV:I.W #H'0091, R3 ; dataflow R3=H'0091; cycles=3
|
||||
25AC: 15 F7 91 F7 BTST.B #7, @H'F791 ; refs ram_F791 in on_chip_ram; cycles=7
|
||||
25B0: 27 08 BEQ loc_25BA ; cycles=3/7 nt/t
|
||||
25B2: 15 F4 04 F4 BTST.B #4, @H'F404 ; refs mem_F404 in program_or_external; cycles=7
|
||||
25B6: 27 02 BEQ loc_25BA ; cycles=3/7 nt/t
|
||||
25B8: AB CE BSET.W #14, R3 ; cycles=3
|
||||
|
||||
loc_25BA:
|
||||
25BA: 1E F4 78 BSR loc_1A35 ; cycles=13
|
||||
25BD: 20 14 BRA loc_25D3 ; cycles=8
|
||||
|
||||
loc_25BF:
|
||||
25BF: 15 F6 D0 F5 BTST.B #5, @H'F6D0 ; refs ram_F6D0 in on_chip_ram; cycles=6
|
||||
25C3: 27 05 BEQ loc_25CA ; cycles=3/8 nt/t
|
||||
25C5: 1E 00 FF BSR loc_26C7 ; cycles=14
|
||||
25C8: 20 09 BRA loc_25D3 ; cycles=7
|
||||
|
||||
loc_25CA:
|
||||
25CA: 15 F6 F6 06 C0 MOV:G.B #H'C0, @H'F6F6 ; refs ram_F6F6 in on_chip_ram; cycles=9
|
||||
25CF: 1D F6 F4 13 CLR.W @H'F6F4 ; refs ram_F6F4 in on_chip_ram; cycles=8
|
||||
|
||||
loc_25D3:
|
||||
25D3: 19 RTS ; cycles=13
|
||||
25D4: 15 F6 D0 F5 BTST.B #5, @H'F6D0 ; refs ram_F6D0 in on_chip_ram; cycles=7
|
||||
25D8: 37 00 E5 BEQ loc_26C0 ; cycles=3/7 nt/t
|
||||
25DB: 15 F7 31 04 02 CMP:G.B #H'02, @H'F731 ; refs ram_F731 in on_chip_ram; cycles=6
|
||||
25E0: 22 50 BHI loc_2632 ; cycles=3/7 nt/t
|
||||
25E2: 1D E1 10 FE BTST.W #14, @H'E110 ; refs mem_E110 in program_or_external; cycles=7
|
||||
25E6: 27 05 BEQ loc_25ED ; cycles=3/7 nt/t
|
||||
25E8: 1E 00 FD BSR loc_26E8 ; cycles=13
|
||||
25EB: 20 45 BRA loc_2632 ; cycles=8
|
||||
|
||||
loc_25ED:
|
||||
25ED: 1D E1 1E 80 MOV:G.W @H'E11E, R0 ; refs mem_E11E in program_or_external; cycles=6
|
||||
25F1: A8 FF BTST.W #15, R0 ; cycles=3
|
||||
25F3: 26 06 BNE loc_25FB ; cycles=3/8 nt/t
|
||||
25F5: A8 FD BTST.W #13, R0 ; cycles=3
|
||||
25F7: 26 25 BNE loc_261E ; cycles=3/8 nt/t
|
||||
25F9: 20 37 BRA loc_2632 ; cycles=8
|
||||
|
||||
loc_25FB:
|
||||
25FB: 15 F6 D0 F4 BTST.B #4, @H'F6D0 ; refs ram_F6D0 in on_chip_ram; cycles=6
|
||||
25FF: 27 04 BEQ loc_2605 ; cycles=3/8 nt/t
|
||||
2601: 0E 30 BSR loc_2633 ; cycles=14
|
||||
2603: 20 2D BRA loc_2632 ; cycles=8
|
||||
|
||||
loc_2605:
|
||||
2605: 5C 00 01 MOV:I.W #H'0001, R4 ; dataflow R4=H'0001; cycles=3
|
||||
2608: 5B 00 91 MOV:I.W #H'0091, R3 ; dataflow R3=H'0091; cycles=3
|
||||
260B: 15 F7 91 F7 BTST.B #7, @H'F791 ; refs ram_F791 in on_chip_ram; cycles=6
|
||||
260F: 27 08 BEQ loc_2619 ; cycles=3/8 nt/t
|
||||
2611: 15 F4 04 F4 BTST.B #4, @H'F404 ; refs mem_F404 in program_or_external; cycles=6
|
||||
2615: 27 02 BEQ loc_2619 ; cycles=3/8 nt/t
|
||||
2617: AB CE BSET.W #14, R3 ; cycles=3
|
||||
|
||||
loc_2619:
|
||||
2619: 1E F4 19 BSR loc_1A35 ; cycles=14
|
||||
261C: 20 14 BRA loc_2632 ; cycles=7
|
||||
|
||||
loc_261E:
|
||||
261E: 15 F6 D0 F4 BTST.B #4, @H'F6D0 ; refs ram_F6D0 in on_chip_ram; cycles=7
|
||||
2622: 27 05 BEQ loc_2629 ; cycles=3/7 nt/t
|
||||
2624: 1E 00 A0 BSR loc_26C7 ; cycles=13
|
||||
2627: 20 09 BRA loc_2632 ; cycles=8
|
||||
|
||||
loc_2629:
|
||||
2629: 15 F6 F6 06 80 MOV:G.B #H'80, @H'F6F6 ; refs ram_F6F6 in on_chip_ram; cycles=9
|
||||
262E: 1D F6 F4 13 CLR.W @H'F6F4 ; refs ram_F6F4 in on_chip_ram; cycles=9
|
||||
|
||||
loc_2632:
|
||||
2632: 19 RTS ; cycles=12
|
||||
|
||||
loc_2633:
|
||||
2633: 1D E9 22 07 80 00 MOV:G.W #H'8000, @H'E922 ; refs mem_E922 in program_or_external; cycles=9
|
||||
2639: 52 80 MOV:E.B #H'80, R2 ; dataflow R2=H'80; cycles=2
|
||||
263B: 5B 00 91 MOV:I.W #H'0091, R3 ; dataflow R3=H'0091; cycles=3
|
||||
263E: 15 F7 91 F7 BTST.B #7, @H'F791 ; refs ram_F791 in on_chip_ram; cycles=7
|
||||
2642: 27 08 BEQ loc_264C ; cycles=3/7 nt/t
|
||||
2644: 15 F4 04 F4 BTST.B #4, @H'F404 ; refs mem_F404 in program_or_external; cycles=7
|
||||
2648: 27 02 BEQ loc_264C ; cycles=3/7 nt/t
|
||||
264A: AB CE BSET.W #14, R3 ; cycles=3
|
||||
|
||||
loc_264C:
|
||||
264C: 1E 18 05 BSR loc_3E54 ; cycles=13
|
||||
264F: 19 RTS ; cycles=13
|
||||
16353
build/rom_f109_handlers.json
Normal file
16353
build/rom_f109_handlers.json
Normal file
File diff suppressed because it is too large
Load Diff
107
build/rom_f109_tail.asm
Normal file
107
build/rom_f109_tail.asm
Normal file
@@ -0,0 +1,107 @@
|
||||
; H8/536 ROM disassembly
|
||||
; input: ROM\M27C512@DIP28_1.BIN
|
||||
; bytes: 65536
|
||||
; vector mode: min
|
||||
; analysis: recursive trace from vectors
|
||||
;
|
||||
; Notes from the manual:
|
||||
; - H8/536 uses the H8/500 CPU instruction set.
|
||||
; - In minimum mode the reset vector at H'0000-H'0001 is a 16-bit PC.
|
||||
; - The register field is H'FE80-H'FFFF; names below come from appendix B.
|
||||
; - @aa:8 short absolute operands use BR as the upper address byte.
|
||||
; - SCI baud inference uses section 14.2.8 BRR formulas when SMR/BRR are known.
|
||||
; - LCD inference treats E-clock H'F200/H'F201 accesses as status/control and data candidates.
|
||||
; - Pass --clock-hz to convert SCI BRR settings into numeric baud rates.
|
||||
; - Cycle counts use Appendix A tables A-7/A-8 for on-chip access with no external wait states.
|
||||
|
||||
; Memory Map
|
||||
; H'0000-H'009F exception_vectors vectors
|
||||
; H'00A0-H'00FF dtc_vectors dtc_vectors
|
||||
; H'0100-H'F67F program_or_external program
|
||||
; H'F680-H'FE7F on_chip_ram ram
|
||||
; H'FE80-H'FFFF register_field registers
|
||||
|
||||
; Vectors
|
||||
; H'0000 reset -> vec_reset_1000 (H'1000)
|
||||
; H'0004 invalid_instruction -> vec_reset_1000 (H'1000)
|
||||
; H'0006 zero_divide -> vec_reset_1000 (H'1000)
|
||||
; H'0008 trap_vs -> vec_reset_1000 (H'1000)
|
||||
; H'0010 address_error -> vec_reset_1000 (H'1000)
|
||||
; H'0012 trace -> vec_reset_1000 (H'1000)
|
||||
; H'0016 nmi -> vec_nmi_4393 (H'4393)
|
||||
; H'0020 trapa_0 -> vec_reset_1000 (H'1000)
|
||||
; H'0022 trapa_1 -> vec_reset_1000 (H'1000)
|
||||
; H'0024 trapa_2 -> vec_reset_1000 (H'1000)
|
||||
; H'0026 trapa_3 -> vec_reset_1000 (H'1000)
|
||||
; H'0028 trapa_4 -> vec_reset_1000 (H'1000)
|
||||
; H'002A trapa_5 -> vec_reset_1000 (H'1000)
|
||||
; H'002C trapa_6 -> vec_reset_1000 (H'1000)
|
||||
; H'002E trapa_7 -> vec_reset_1000 (H'1000)
|
||||
; H'0030 trapa_8 -> vec_reset_1000 (H'1000)
|
||||
; H'0032 trapa_9 -> vec_reset_1000 (H'1000)
|
||||
; H'0034 trapa_a -> vec_reset_1000 (H'1000)
|
||||
; H'0036 trapa_b -> vec_reset_1000 (H'1000)
|
||||
; H'0038 trapa_c -> vec_reset_1000 (H'1000)
|
||||
; H'003A trapa_d -> vec_reset_1000 (H'1000)
|
||||
; H'003C trapa_e -> vec_reset_1000 (H'1000)
|
||||
; H'003E trapa_f -> vec_reset_1000 (H'1000)
|
||||
; H'0040 irq0 -> vec_reset_1000 (H'1000)
|
||||
; H'0042 interval_timer -> vec_interval_timer_BFC4 (H'BFC4)
|
||||
; H'0048 irq1 -> vec_reset_1000 (H'1000)
|
||||
; H'0050 irq2 -> vec_reset_1000 (H'1000)
|
||||
; H'0052 irq3 -> vec_irq3_3C30 (H'3C30)
|
||||
; H'0058 irq4 -> vec_irq4_3AC7 (H'3AC7)
|
||||
; H'005A irq5 -> vec_reset_1000 (H'1000)
|
||||
; H'0062 frt1_ocia -> vec_frt1_ocia_BEEA (H'BEEA)
|
||||
; H'006A frt2_ocia -> vec_frt2_ocia_BF23 (H'BF23)
|
||||
; H'0080 sci1_eri -> vec_sci1_eri_BB57 (H'BB57)
|
||||
; H'0082 sci1_rxi -> vec_sci1_rxi_BB67 (H'BB67)
|
||||
; H'0084 sci1_txi -> vec_sci1_txi_BA84 (H'BA84)
|
||||
; H'0090 ad_adi -> vec_ad_adi_3D99 (H'3D99)
|
||||
|
||||
; Symbols
|
||||
; mem_E924 H'E924 program_or_external memory r=0 w=1 width=word
|
||||
; mem_F404 H'F404 program_or_external memory r=1 w=0 width=byte
|
||||
; ram_F6F6 H'F6F6 on_chip_ram ram r=0 w=2 width=byte
|
||||
; ram_F732 H'F732 on_chip_ram ram r=1 w=1 width=word
|
||||
; ram_F734 H'F734 on_chip_ram ram r=0 w=1 width=word
|
||||
; ram_F791 H'F791 on_chip_ram ram r=1 w=0 width=byte
|
||||
; ram_FB02 H'FB02 on_chip_ram ram r=0 w=1 width=byte
|
||||
; ram_FB03 H'FB03 on_chip_ram ram r=1 w=1 width=byte
|
||||
|
||||
; Board Profile
|
||||
; Board trace ties the H8/536 SCI1 pins to a MAX202 RS232 transceiver.
|
||||
; H8 pin 66 P95/TXD (TXD) -> MAX202 pin 11
|
||||
; H8 pin 67 P96/RXD (RXD) -> MAX202 pin 12
|
||||
; SCI2 pin routing is disabled by SYSCR2.P9SCI2E=0 in the observed setup.
|
||||
|
||||
; LCD/Text Scan
|
||||
; search 'CONNECT': not literal, hits=0
|
||||
; LCD text candidates
|
||||
; ... 1 more LCD text candidates
|
||||
|
||||
26C0: 15 F6 F6 13 CLR.B @H'F6F6 ; refs ram_F6F6 in on_chip_ram; cycles=9
|
||||
26C4: 30 FF 0C BRA loc_25D3 ; cycles=7
|
||||
26C7: 15 F6 F6 13 CLR.B @H'F6F6 ; refs ram_F6F6 in on_chip_ram; cycles=8
|
||||
26CB: 1D E9 24 07 FF 80 MOV:G.W #H'FF80, @H'E924 ; refs mem_E924 in program_or_external; cycles=9
|
||||
26D1: 52 80 MOV:E.B #H'80, R2 ; dataflow R2=H'80; cycles=2
|
||||
26D3: 5B 00 92 MOV:I.W #H'0092, R3 ; dataflow R3=H'0092; cycles=3
|
||||
26D6: 15 F7 91 F7 BTST.B #7, @H'F791 ; refs ram_F791 in on_chip_ram; cycles=7
|
||||
26DA: 27 08 BEQ loc_26E4 ; cycles=3/7 nt/t
|
||||
26DC: 15 F4 04 F4 BTST.B #4, @H'F404 ; refs mem_F404 in program_or_external; cycles=7
|
||||
26E0: 27 02 BEQ loc_26E4 ; cycles=3/7 nt/t
|
||||
26E2: AB CE BSET.W #14, R3 ; cycles=3
|
||||
|
||||
loc_26E4:
|
||||
26E4: 1E 17 6D BSR loc_3E54 ; cycles=13
|
||||
26E7: 19 RTS ; cycles=13
|
||||
26E8: 15 FB 03 C7 BSET.B #7, @H'FB03 ; refs ram_FB03 in on_chip_ram; cycles=9
|
||||
26EC: 26 08 BNE loc_26F6 ; cycles=3/7 nt/t
|
||||
26EE: 1D F7 32 81 MOV:G.W @H'F732, R1 ; refs ram_F732 in on_chip_ram; cycles=7
|
||||
26F2: 1D F7 34 91 MOV:G.W R1, @H'F734 ; refs ram_F734 in on_chip_ram; cycles=7
|
||||
|
||||
loc_26F6:
|
||||
26F6: 1D F7 32 07 1C 01 MOV:G.W #H'1C01, @H'F732 ; refs ram_F732 in on_chip_ram; cycles=11
|
||||
26FC: 15 FB 02 06 14 MOV:G.B #H'14, @H'FB02 ; refs ram_FB02 in on_chip_ram; cycles=9
|
||||
2701: 1E 21 F6 BSR loc_48FA ; cycles=14
|
||||
2704: 19 RTS ; cycles=12
|
||||
2076
build/rom_f109_tail.json
Normal file
2076
build/rom_f109_tail.json
Normal file
File diff suppressed because it is too large
Load Diff
4037
build/rom_lcd_selector_handlers.asm
Normal file
4037
build/rom_lcd_selector_handlers.asm
Normal file
File diff suppressed because it is too large
Load Diff
212465
build/rom_lcd_selector_handlers.json
Normal file
212465
build/rom_lcd_selector_handlers.json
Normal file
File diff suppressed because it is too large
Load Diff
4263
build/rom_others_menu.asm
Normal file
4263
build/rom_others_menu.asm
Normal file
File diff suppressed because it is too large
Load Diff
219643
build/rom_others_menu.json
Normal file
219643
build/rom_others_menu.json
Normal file
File diff suppressed because it is too large
Load Diff
4219
build/rom_others_menu_deep.asm
Normal file
4219
build/rom_others_menu_deep.asm
Normal file
File diff suppressed because it is too large
Load Diff
220100
build/rom_others_menu_deep.json
Normal file
220100
build/rom_others_menu_deep.json
Normal file
File diff suppressed because it is too large
Load Diff
4295
build/rom_others_menu_gate.asm
Normal file
4295
build/rom_others_menu_gate.asm
Normal file
File diff suppressed because it is too large
Load Diff
221410
build/rom_others_menu_gate.json
Normal file
221410
build/rom_others_menu_gate.json
Normal file
File diff suppressed because it is too large
Load Diff
4642
build/rom_others_page1.asm
Normal file
4642
build/rom_others_page1.asm
Normal file
File diff suppressed because it is too large
Load Diff
239015
build/rom_others_page1.json
Normal file
239015
build/rom_others_page1.json
Normal file
File diff suppressed because it is too large
Load Diff
1111
build/rom_rx_branch_trace.json
Normal file
1111
build/rom_rx_branch_trace.json
Normal file
File diff suppressed because it is too large
Load Diff
218
build/rom_rx_branch_trace.txt
Normal file
218
build/rom_rx_branch_trace.txt
Normal file
@@ -0,0 +1,218 @@
|
||||
H8/536 SCI1 RX Branch Trace
|
||||
|
||||
Summary: The ROM captures six SCI1 bytes, validates a 0x5A-seeded XOR checksum, decodes RX[0] & 0x07, then splits into initial commands while FAA2 == 0 and continuation commands while FAA2 != 0.
|
||||
Confidence: high
|
||||
|
||||
Frame Model:
|
||||
- capture buffer: H'F868-H'F86D
|
||||
- validation buffer: H'F860-H'F865
|
||||
- command: RX[0] & 0x07
|
||||
- logical index candidate: loc_622B(RX[1], RX[2])
|
||||
- value candidate: RX[3:4]
|
||||
- checksum: 0x5A XOR RX[0..4] == RX[5]
|
||||
|
||||
Selector Decode:
|
||||
- loc_622B logical selector decode: present
|
||||
The RX handler builds a raw word from RX[1:2], uses RX[1] bit0-bit2 as a page, keeps RX[2] as the low selector byte, and maps the result into a 0x000-0x1FF logical selector.
|
||||
- page 0, or pages 4-7, and low <= 0x7F: selector = 0x000 + low [H'6234, H'6236, H'6244, H'6248, H'6264]
|
||||
- page 1 and low <= 0xFF: selector = 0x080 + low [H'6238, H'623A, H'624D, H'6251, H'6264]
|
||||
- page 2 and low <= 0x7F: selector = 0x180 + low [H'623C, H'623E, H'6256, H'625A, H'6264]
|
||||
- page 3, page/range failure, or page 0/4-7 with low > 0x7F: selector forced to 0x01FF [H'6240, H'6242, H'625F, H'6261]
|
||||
- implication: RX[1].7 is not part of the selector here because the dispatcher rejects byte1 bit7 before command handling.
|
||||
- implication: Commands shaped as 01 80 xx ... are rejected before loc_622B-derived command handling even if the low byte looks useful.
|
||||
- implication: Page 4-7 encodings appear to alias the page-0 decode path unless the low byte is out of range.
|
||||
|
||||
Stages:
|
||||
- SCI1 RXI/ERI byte capture: present
|
||||
ERI latches FAA4.7 and clears physical error flags; RXI clears RDRF, reads SCI1_RDR, stores bytes into F868-F86D, reloads F9C1, and sets F9C5 when six bytes are captured.
|
||||
- ERI taken: set FAA4.7, clear ORER/FER/PER, then fall into RXI byte capture [H'BB57, H'BB5B, H'BB5F, H'BB63]
|
||||
- F9C1 == 0 before byte: clear F9C3 so the byte starts a fresh frame [H'BB71, H'BB75, H'BB77]
|
||||
- F9C1 != 0 and F9C3 <= 5: append byte at F868 + F9C3 and increment F9C3 [H'BB7D, H'BB82, H'BB8A, H'BB90, H'BB96]
|
||||
- F9C1 != 0 and F9C3 > 5: clear FAA4 and skip storing this byte [H'BB7D, H'BB82, H'BB84, H'BB88]
|
||||
- incremented F9C3 == 6: load F9C5 with 0x14 as the RX/session timeout window [H'BB9A, H'BB9C, H'BB9E]
|
||||
- any RXI exit: reload F9C1 with 0x05 as the inter-byte timeout [H'BBA3]
|
||||
- six-byte validation and checksum: present
|
||||
The main-loop processor only runs when F9C3 is six, copies F868-F86D to F860-F865, clears F9C3, rejects physical-error frames, checks the 0x5A XOR checksum, and decodes the index.
|
||||
- F9C3 != 6: return without processing [H'BBAB, H'BBB0]
|
||||
- FAA4.7 set after capture: enter retry/error path at BE29 [H'BBCF, H'BBD3]
|
||||
- checksum mismatch: enter retry/error path at BE29 [H'BBD6, H'BBD8, H'BBDC, H'BBE0, H'BBE4, H'BBE8, H'BBEC, H'BBF0]
|
||||
- checksum valid: clear FAA6, decode selector from RX[1:2] through loc_622B, and dispatch on RX[0] & 0x07 [H'BBF3, H'BBF7, H'BBFD, H'BC01, H'BC08, H'BC0C]
|
||||
- FAA2 split dispatcher: present
|
||||
FAA2 == 0 enters the initial dispatcher for commands 0, 1, 2, and 7. FAA2 != 0 enters the continuation dispatcher; commands 4, 5, and 6 only live there.
|
||||
- FAA2 == 0: set FAA2.7 and test initial commands 0, 1, 2, 7 [H'BC0F, H'BC13, H'BC15, H'BC20, H'BC24, H'BC29, H'BC2E]
|
||||
- FAA2 != 0 and command bit2 set: continuation commands 4, 5, 6, 7 are possible [H'BC0F, H'BC13, H'BC3A, H'BC45, H'BC4A, H'BC4F, H'BC54]
|
||||
- FAA2 != 0 and command bit2 clear: BCLR FAA2.3; if that bit was set, clear FAA3 and re-enter initial dispatcher [H'BC3A, H'BC3C, H'BC5C, H'BC60, H'BC63, H'BC67]
|
||||
- byte1 bit7 set on initial path: branch to BD0B and return without normal command handling [H'BC19, H'BC1D, H'BD0B]
|
||||
- byte1 bit7 set on continuation path: branch to BE27 and return without normal command handling [H'BC3E, H'BC42, H'BE27]
|
||||
- checksum/error retry path: present
|
||||
Physical RX errors or checksum failures can either be ignored, clear the session after two retries, or stage a command-7 retry/error echo of RX[1:4].
|
||||
- FAA5.7 == 0: return after clearing FAA4.7; retry echo is disabled [H'BE29, H'BE2D, H'BE31]
|
||||
- FAA5.7 == 1 and FAA6 < 2: stage F850=0x07 and F851-F854=RX[1:4], then call BA26 [H'BE33, H'BE37, H'BE3C, H'BE4D, H'BE52, H'BE5A, H'BE62, H'BE6A]
|
||||
- FAA5.7 == 1 and FAA6 >= 2: load F9C0=0x1F and clear FAA3/FAA2 [H'BE37, H'BE3C, H'BE3E, H'BE43, H'BE47]
|
||||
- pending selector ring at loc_BE70: present
|
||||
Several write/ACK paths call BE70 with R5 as the logical selector. BE70 deduplicates that selector against a small F970-like ring using cursors F9B9/F9B4, then appends it if absent.
|
||||
- selector already present: exit without appending [H'BE84, H'BE88, H'BE9D]
|
||||
- ring scan reaches F9B4 cursor: store R5 into the pending ring and advance F9B4 [H'BE80, H'BE82, H'BE91, H'BE95, H'BE99]
|
||||
- session timeout and resend side paths: present
|
||||
After any complete RX frame, F9C5 keeps FAA5.7/session-gate state alive for a short window. When that window expires, 3FEF can clear queue cursors and call 400C, while BE9E handles resend countdowns.
|
||||
- F9C5 == 0 at loc_3FEF: clear F9B5/F9B0 and clear FAA5.7; if FAA5.7 was set, call 400C reset/NOT-ACT state clear [H'3FEF, H'3FF3, H'3FF5, H'3FF9, H'3FFD, H'4001, H'4003]
|
||||
- F9C5 != 0 at loc_3FEF: set FAA5.7, allowing retry/resend/session-gated paths [H'3FEF, H'3FF3, H'4007]
|
||||
- BE9E sees no pending FAA5 & FAA3 & 0x80: clear FAA2 and return [H'BE9E, H'BEA5, H'BEA9, H'BEAD, H'BEAF]
|
||||
- BE9E pending and F9C6==0 and F9C8!=0: decrement F9C8, reload F9C6, and possibly resend staged TX through BA26 [H'BEB5, H'BEBB, H'BEC1, H'BEC5, H'BECB, H'BED1, H'BED5]
|
||||
- BE9E pending but F9C8==0: clear F9C5, which lets 3FEF collapse the session gate later [H'BEBB, H'BEBF, H'BEE4]
|
||||
|
||||
Command Branches:
|
||||
- cmd 0x00 set_value_acked_candidate: initial path only: checksum valid, FAA2 == 0, RX[1].7 == 0; handler H'BC69; writes RX[3:4] into primary/current tables, flags the selector, calls BE70, and sends an echo-style 0x04 response
|
||||
response: F850=0x04; F851-F854 mostly echo RX[1:4]; BA26 sends it
|
||||
- selector zero is special: the low byte is forced to 0x80 after the high byte is taken from RX[3]
|
||||
- nonzero selectors can mirror into an auxiliary table via a mapping table
|
||||
- clears FAA2.7 before exit
|
||||
- cmd 0x01 read_value_candidate: initial path only: checksum valid, FAA2 == 0, RX[1].7 == 0; handler H'BCD7; reads primary table E000 + 2*selector and stages a 0x04 response
|
||||
response: F850=0x04; F851 is overwritten with RX[2]; F853/F854 receive table high/low; F852 is not freshly written here
|
||||
- does not enter continuation command handling
|
||||
- clears FAA2.7 before exit
|
||||
- cmd 0x02 initial_clear_or_noop_candidate: initial path only: checksum valid, FAA2 == 0, RX[1].7 == 0; handler H'BD04; clears FAA2.7 and returns without staging a response
|
||||
response: no immediate serial response
|
||||
- likely a quiet/session-clear style command on the initial path
|
||||
- cmd 0x04 continuation_set_value_candidate: continuation path only: checksum valid, FAA2 != 0, command bit2 set, RX[1].7 == 0; handler H'BD0E; writes a value into the primary table without an immediate serial response; selector zero also updates the current/report table
|
||||
response: no immediate serial response
|
||||
- selector zero is special: RX[3] becomes the high byte and low byte is forced to 0x80
|
||||
- nonzero selectors write E000 and flag EC00.7; the matching E800 current/report write is not present in this handler
|
||||
- nonzero selectors can mirror/persist through F400/BFE0 when mapping and F76E.7 allow it
|
||||
- if FAA2.3 was set from a queued report, advances F9B5 to consume that report
|
||||
- clears FAA3 and FAA2 before exit
|
||||
- cmd 0x05 continuation_ack_or_clear_pending_candidate: continuation path only: checksum valid, FAA2 != 0, command bit2 set, RX[1].7 == 0; handler H'BD80; ACK/session-clear path; usually no response, but selected logical indexes feed BE70 or clear connection latches
|
||||
response: no immediate serial response
|
||||
- selectors 0x006C, 0x006D, and 0x006E call BE70
|
||||
- with F731.7 set, selectors 0x006B, 0x0096, 0x0097, 0x00C6, and 0x00F8 clear F731.7/F790.7
|
||||
- if FAA2.3 was set from a queued report, advances F9B5
|
||||
- clears FAA3 and FAA2 before exit
|
||||
- cmd 0x06 continuation_set_secondary_candidate: continuation path only: checksum valid, FAA2 != 0, command bit2 set, RX[1].7 == 0; handler H'BDDB; writes RX[3:4] into the secondary table and sets flag-table bit 6
|
||||
response: no immediate serial response
|
||||
- if FAA2.3 was set from a queued report, advances F9B5
|
||||
- clears FAA3 and FAA2 before exit
|
||||
- cmd 0x07 retransmit_previous_tx_candidate: initial or continuation path; handler H'BE05; copies the previous finalized TX frame bytes back into staging and sends them again
|
||||
response: previous TX frame retransmitted through BA26
|
||||
- loads F9C0 with 0x1F before sending
|
||||
|
||||
Table Surfaces:
|
||||
- primary_value_table H'E000-H'E3FF: present; logical selector word table; command 0 and continuation command 4 write it, command 1 reads it [H'BC75, H'BC95, H'BCEC, H'BD1A, H'BD35]
|
||||
- indexed as E000 + 2*selector after loc_622B
|
||||
- selector zero writes force the low byte to 0x80 on commands 0 and 4
|
||||
- this is the table that must contain E000[0]=0x8080 for the emulator-correlated CONNECT OK branch
|
||||
- current_report_value_table H'E800-H'EBFF: present; current/report value table used when queued serial reports are converted into TX frames [H'BC79, H'BC99, H'BD1E, H'BB35, H'BB39, H'BB3F]
|
||||
- command 0 writes both primary E000 and current E800 for zero and nonzero selectors
|
||||
- command 4 writes E800 only on the selector-zero special path; the nonzero command-4 path does not show a matching E800 write here
|
||||
- loc_BAF2 reads E800 + 2*queued_selector when building autonomous report frames
|
||||
- secondary_value_table H'E400-H'E7FF: present; secondary logical selector word table written by continuation command 6 [H'BDE5, H'BDE9]
|
||||
- command 6 writes RX[3:4] to E400 + 2*selector
|
||||
- the matching EC00 flag bit is bit6 rather than bit7
|
||||
- dirty_flag_table H'EC00-H'EDFF: present; per-selector flag bytes; command 0/4 set bit7 and command 6 sets bit6 [H'BC82, H'BC9D, H'BD22, H'BD39, H'BDE9]
|
||||
- the same logical selector indexes this byte table directly, not as a word offset
|
||||
- loc_48FA and other consumers test these table bits before raising follow-on reports
|
||||
- mapped_shadow_or_eeprom_surface H'F400-H'F4FF: present; optional mapped mirror/persistence surface selected through ROM tables around C564/C565 [H'BCA1, H'BCA9, H'BD3D, H'BD45, H'BD49, H'BD5F]
|
||||
- nonzero command-0 and command-4 writes consult mapping bytes/words before mirroring into F400
|
||||
- command 4 can call BFE0 to persist the mapped word when F76E.7 is set
|
||||
- selector zero bypasses this mapped mirror path
|
||||
|
||||
Downstream Flow Traces:
|
||||
- immediate response staging through loc_BA26: present
|
||||
Command 0, command 1, command 7, and the retry/error path stage F850-F854, call BA26, copy that staging area to F858-F85C, compute F85D, send the first byte, then let TXI send bytes 1-5.
|
||||
- stage command-0 echo: F850=0x04 and F851-F854 mirror the accepted host fields before BA26 [H'BCB0, H'BCB5, H'BCC1, H'BCC9, H'BCCD]
|
||||
- stage command-1 readback: F850=0x04, F853/F854 receive the E000 table word, and BA26 sends it [H'BCD7, H'BCEC, H'BCF0, H'BCF6, H'BCFA]
|
||||
- finalize TX frame: BA26 copies F850-F854 to F858-F85C and computes F85D as 0x5A XOR bytes 0-4 [H'BA36, H'BA3A, H'BA42, H'BA4A, H'BA4E, H'BA64]
|
||||
- start SCI1 transmission: BA26 waits for TDRE, writes F858 to SCI1_TDR, sets F9C2=1, clears TDRE, and enables TIE [H'BA68, H'BA72, H'BA76, H'BA7B, H'BA7F]
|
||||
- finish SCI1 transmission: TXI indexes F858+F9C2 until six bytes are sent, then disables TIE [H'BAAB, H'BAB1, H'BAB5, H'BABF, H'BAC3, H'BACA]
|
||||
- selector-processing queue BE70/F970 into loc_2806: present
|
||||
BE70 appends unique logical selectors into the F970 ring. The main loop later consumes that ring at loc_2806 and dispatches selector-specific behavior through the 28A6 jump table.
|
||||
- append unique selector: BE70 scans from F9B9 to F9B4, skips duplicates, writes R5 to F970+2*cursor, and advances F9B4 [H'BE70, H'BE78, H'BE84, H'BE91, H'BE95, H'BE99]
|
||||
- consume selector: loc_2806 reads F970+2*F9B9, advances F9B9, masks the selector to 0x01FF, and keeps it in R5 [H'2806, H'280C, H'2819, H'281D, H'2822, H'2826, H'282A]
|
||||
- active-selector side path: selectors matching F736/F738/F73A/F73C/F73E/F740/F742/F754 call loc_48FA before the jump table [H'2837, H'285E, H'2878, H'2892, H'2CAB, H'2CAD]
|
||||
- selector jump table: the consumer jumps through table 28A6; selector zero is emulator-correlated with the CONNECT handler window [H'289F, H'28A3]
|
||||
- serial-report queue loc_3E54/F870 into loc_BAF2: present
|
||||
loc_3E54 is a shared enqueue helper. R2.bit7 queues serial-visible report indexes in F870, while R2.bit6 queues selector-processing work in F970. loc_BAF2 is the path that turns F870 entries into outbound 6-byte frames.
|
||||
- enqueue serial report: when R2.7 is set, loc_3E54 deduplicates R3 in F870 and advances F9B0 [H'3E54, H'3E58, H'3E6C, H'3E76, H'3E7A, H'3E7E]
|
||||
- queue backpressure drain: if the serial queue is nearly full, loc_3E54 calls loc_3FD3 until there is space [H'3E82, H'3E8B, H'3E91, H'3E93]
|
||||
- enqueue selector processing: when R2.6 is set, loc_3E54 deduplicates R3 in F970 and advances F9B4 [H'3E9A, H'3E9E, H'3EB2, H'3EBF, H'3EC3, H'3EC7]
|
||||
- dequeue serial report: loc_BAF2 compares F9B5/F9B0, reads F870+2*F9B5, builds a TX report from E800, and calls BA26 [H'BAF2, H'BAF8, H'BB00, H'BB08, H'BB1C, H'BB35, H'BB43]
|
||||
- open continuation latch: after a report send, loc_BAF2 sets FAA2.3, FAA3.7, F9C6, and F9C8; command 4/5/6 can then consume or ACK that report [H'BB00, H'BB46, H'BB4C, H'BB51]
|
||||
- TXI/RXI race and continuation collapse: present
|
||||
The TX interrupt handler has an interlock: if a queued report is awaiting continuation and RX bytes are already arriving, it clears the report/continuation state and stops TXI before the normal frame-finish path.
|
||||
- detect overlap: TXI tests FAA2.3, FAA5.7, and nonzero F9C3 before continuing the TX frame [H'BA84, H'BA8A, H'BA90]
|
||||
- collapse continuation: on overlap it clears FAA2.3 and FAA3, disables TIE, and loads F9C0=0x1F [H'BA96, H'BA9A, H'BA9E, H'BAA2]
|
||||
- normal completion path: without the overlap, TXI sends bytes until F9C2 reaches six and then starts the post-TX delay path [H'BAA9, H'BAB5, H'BAC3, H'BACA, H'BADA, H'BAED]
|
||||
- session expiry into reset/not-active state: present
|
||||
When F9C5 reaches zero, loc_3FEF clears queue cursors and FAA5.7; if FAA5.7 had been set, loc_400C clears connection/session RAM and refreshes the inactive display state.
|
||||
- expire RX session: F9C5==0 clears F9B5/F9B0 and clears FAA5.7 [H'3FEF, H'3FF5, H'3FF9, H'3FFD]
|
||||
- call reset side path: if clearing FAA5.7 changed the bit, loc_3FEF calls loc_400C [H'4001, H'4003]
|
||||
- clear connection state: loc_400C clears F730/F756-F759/F732/F75C/FB03/F791/F795/F76E and calls follow-on display/session refresh routines [H'400C, H'4010, H'4020, H'4028, H'4034, H'403C, H'4040, H'4042]
|
||||
|
||||
RX-to-TX Feedback Loops:
|
||||
- command-0 write echo and selector-processing loop: present
|
||||
trigger: valid command 0 while FAA2 == 0
|
||||
path: RX validation -> BC69 table write -> BE70 appends selector to F970 -> BCB0/BA26 sends immediate 0x04 echo -> later loc_2806 consumes F970
|
||||
TX outcome: immediate command-4-style echo frame plus possible later selector-driven reports/display work
|
||||
timing/gate: BA26 sets F9C0=0x64 and F9C4=0x07, temporarily delaying queued TX and heartbeat enqueue
|
||||
bench read: a command-0 probe is stateful: it both writes table state and spends time in the post-TX delay, so it can disturb the continuation window being tested
|
||||
evidence: H'BC69, H'BC75, H'BC86, H'BCB0, H'BCCD, H'BA2C, H'BA31, H'BE70, H'2819, H'28A3
|
||||
- command-1 readback and previous-frame loop: present
|
||||
trigger: valid command 1 while FAA2 == 0, followed by optional command 7
|
||||
path: RX validation -> BCD7 reads E000[selector] -> BA26 finalizes TX in F858-F85D -> BE05 can copy F858-F85C back to F850-F854
|
||||
TX outcome: direct 0x04 readback, then command 7 can retransmit the exact last finalized TX frame
|
||||
timing/gate: command 1 clears FAA2.7 and never enters continuation handling; it is a readback path, not an ACK path
|
||||
bench read: command 7 after command 1 proves what was last finalized, but does not prove a hidden continuation token by itself
|
||||
evidence: H'BCD7, H'BCEC, H'BCFA, H'BA36, H'BA64, H'BE05, H'BE09, H'BE22
|
||||
- retry/error 07 echo loop: present
|
||||
trigger: physical RX error or checksum mismatch while FAA5.7 is set and retry count FAA6 is below two
|
||||
path: RX validation error -> BE29 retry gate -> BE4D stages F850=0x07 and copies RX[1:4] into F851-F854 -> BA26 sends
|
||||
TX outcome: a 0x07 frame that can echo the host payload bytes, independent of E000/E800 table contents
|
||||
timing/gate: after two retries, the ROM loads F9C0=0x1F and clears FAA3/FAA2 instead of sending another echo
|
||||
bench read: visible 07 frames in a noisy/tight timing run can be retry echoes, not necessarily device status or a continuation token
|
||||
evidence: H'BE29, H'BE2D, H'BE33, H'BE37, H'BE3E, H'BE43, H'BE47, H'BE4D, H'BE6A
|
||||
- autonomous report to host continuation loop: present
|
||||
trigger: firmware enqueues a serial-visible report via loc_3E54 with R2.7 set
|
||||
path: loc_3E54 appends report selector to F870 -> loc_3FD3 allows BAF2 when FAA2/F9C0 gates are clear -> BAF2 sends report -> command 4/5/6 continuation can advance F9B5
|
||||
TX outcome: autonomous 6-byte report frame built from E800[selector], with FAA2.3/FAA3.7 left set to await host continuation or ACK
|
||||
timing/gate: F9C0 must count down before BAF2 can send, and F9C6/F9C8/BE9E control repeated sends while FAA3.7 remains live
|
||||
bench read: the actual ACK/write target is not just the selector; it is the report that is live under FAA2.3 before TXI/RXI or BE9E clears it
|
||||
evidence: H'3E54, H'3E76, H'3E7A, H'3FD3, H'3FE5, H'3FEB, H'BAF2, H'BB00, H'BB35, H'BB43, H'BB46, H'BB51, H'BD67, H'BDC2, H'BDED
|
||||
- selector-processing to report loop: present
|
||||
trigger: command 0/4/selected command 5 calls BE70, or loc_3E54 is called with R2.6 set
|
||||
path: BE70/F970 selector queue -> loc_2806 selector dispatch -> active-selector side path loc_48FA -> loc_3E54 can enqueue report 0x00F6 when E1EC.13 is set
|
||||
TX outcome: possible later serial report produced through the F870/BAF2 loop rather than an immediate response to the original RX frame
|
||||
timing/gate: loc_48FA is gated by FB03.7, F732 values, E1EC.13, and F76E.6 before reaching its indirect table
|
||||
bench read: selector-zero CONNECT work and visible serial reports can be separated in time; lack of immediate TX does not mean the selector queue did nothing
|
||||
evidence: H'BE70, H'BE91, H'2806, H'2819, H'2CAD, H'48FA, H'490F, H'4921, H'4923, H'4926
|
||||
- TXI/RXI overlap cancellation loop: present
|
||||
trigger: host RX bytes begin while a report TX is active, FAA2.3 is set, and FAA5.7 is set
|
||||
path: TXI observes FAA2.3 + FAA5.7 + F9C3 != 0 -> clears FAA2.3/FAA3 -> disables TIE -> loads F9C0=0x1F
|
||||
TX outcome: the pending report/continuation state can be canceled before the host command reaches the continuation dispatcher
|
||||
timing/gate: this depends on byte timing relative to TXI and F9C3, so polite emulator injection can miss it
|
||||
bench read: this is a concrete ROM reason why bench timing might see latches/retries while a too-polite emulator reaches cleaner continuation paths
|
||||
evidence: H'BA84, H'BA8A, H'BA90, H'BA96, H'BA9A, H'BA9E, H'BAA2
|
||||
- session-expiry to heartbeat/not-active loop: present
|
||||
trigger: any complete six-byte RX frame loads F9C5, then FRT2 decrements it to zero
|
||||
path: RX complete -> F9C5=0x14 -> FRT2 decrements F9C5 -> loc_3FEF clears session/queues and calls 400C -> loc_4046 can later enqueue heartbeat selector 0
|
||||
TX outcome: eventual return to idle heartbeat/report behavior and inactive-session display state
|
||||
timing/gate: F9C4 gates heartbeat enqueue; BA26 reloads it to 0x07 after each send, matching the roughly 700 ms heartbeat cadence
|
||||
bench read: the common CONNECT NOT ACT after arbitrary six-byte traffic is consistent with this expiry/reset loop
|
||||
evidence: H'BB9E, H'BF31, H'BF37, H'3FEF, H'3FFD, H'4003, H'400C, H'4046, H'4067, H'BA31
|
||||
|
||||
State Bits:
|
||||
- H'FAA2.7: rx_command_in_progress_candidate - set on initial-path parse; cleared by command 0/1/2 exits or by continuation cleanup
|
||||
- H'FAA2.3: queued_report_ack_needed_candidate - set by the autonomous queue send path at BB00; continuation command 4/5/6 can advance F9B5 only when this bit was set
|
||||
- H'FAA3.7: pending_resend_mask_candidate - set after queued report send; BE9E masks it with FAA5.7 before resend/clear decisions
|
||||
- H'FAA4.7: rx_physical_error_latch_candidate - set by SCI1 ERI and tested before checksum dispatch
|
||||
- H'FAA5.7: rx_session_gate_candidate - set while F9C5 is alive after a complete RX frame; gates retry/resend and heartbeat/report enqueue behavior
|
||||
|
||||
Bench Implications:
|
||||
- A standalone command 4 frame from idle should not hit BD0E; command 4 is continuation-only and initial dispatch does not accept it.
|
||||
- Command 5 is not a generic always-live ACK. It only performs ACK/session-clear work on the continuation path while FAA2 != 0.
|
||||
- A valid six-byte RX frame loads F9C5 with 0x14, which temporarily sets FAA5.7; when that window expires, loc_3FEF can clear queue/session state and call loc_400C.
|
||||
- The observed 07 retry/error family can be produced by BE4D from RX[1:4] after error/checksum retry conditions; it is not automatically proof of a table value or a command-4 continuation token.
|
||||
- To prove CONNECT OK through serial, the bench has to create or preserve FAA2 != 0 at the moment command 4 arrives, and ideally FAA2.3 if it expects queued-report advancement.
|
||||
|
||||
Caveats:
|
||||
- This is an address-driven static branch map, not proof of every runtime predicate value.
|
||||
- Semantic names are candidates; the branch destinations and RAM side effects are ROM evidence.
|
||||
- loc_BE70/F970 and loc_3E54/F870 are separate queues; this report names them separately because mixing them up changes the command-4/5 interpretation.
|
||||
3827
build/rom_selector_006c_006d.asm
Normal file
3827
build/rom_selector_006c_006d.asm
Normal file
File diff suppressed because it is too large
Load Diff
202350
build/rom_selector_006c_006d.json
Normal file
202350
build/rom_selector_006c_006d.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -67,6 +67,7 @@
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
|
||||
#define BIT(n) (1u << (n))
|
||||
extern volatile u8 MEM8[0x10000];
|
||||
|
||||
#define SCI1_SCR MEM8[0xFEDAu]
|
||||
@@ -113,26 +114,45 @@ extern volatile u8 MEM8[0x10000];
|
||||
* - byte4: value_lo (medium) - candidate low byte of a word value
|
||||
* - byte5: checksum (high) - 0x5A-seeded XOR of bytes 0..4
|
||||
* dispatch: command_low3 = RX_FRAME(0) & 0x07; observed H'00, H'01, H'02, H'04, H'05, H'06, H'07
|
||||
* dispatcher split: FAA2 == 0 accepts initial/idle commands H'00, H'01, H'02, H'07; FAA2 != 0 accepts continuation commands H'04, H'05, H'06, H'07
|
||||
* dispatcher caveat: Initial dispatch follows checksum validation and RX error handling. Command 1 is only on the initial/idle path and is also gated by F861.bit7 == 0.
|
||||
* dispatch evidence: H'BC08, H'BC0C, H'BC20, H'BC22, H'BC24, H'BC26, H'BC29, H'BC2B, H'BC2E, H'BC30, H'BC45, H'BC47, H'BC4A, H'BC4C, H'BC4F, H'BC51, H'BC54, H'BC56
|
||||
* index decoder: RX[1:2] -> logical index via loc_622B (medium)
|
||||
* command candidates:
|
||||
* - H'00 set_value_acked: candidate write of RX[3:4] into primary/current tables, followed by a response; handler H'BC69; responses response_at_BCCD
|
||||
* - H'01 read_value: candidate read from the primary table, followed by a response carrying the value; handler H'BCD7; responses response_at_BCFA
|
||||
* availability: valid checksum/no RX physical error && FAA2 == 0
|
||||
* - H'01 read_value: initial/idle-path primary table read only, followed by an odd response staging sequence; handler H'BCD7; responses response_at_BCFA
|
||||
* availability: valid checksum/no RX physical error && FAA2 == 0 && F861.bit7 == 0
|
||||
* note: Only accepted on the initial/idle dispatcher path: valid checksum/no RX error, FAA2 == 0, and F861.bit7 == 0.
|
||||
* note: BCD7 stages F850=0x04, writes F851 from F861 and then overwrites F851 from F862.
|
||||
* note: BCD7 reads the primary table word at E000 + 2*selector; F854 receives the low byte and F853 receives the high byte.
|
||||
* note: F852 is not freshly written in the BCD7 handler, so do not describe the response as a fixed 04 00 QQ hi lo frame.
|
||||
* - H'02 clear_or_abort: candidate clear/abort path with no immediate response builder; handler H'BD04; responses none
|
||||
* availability: valid checksum/no RX physical error && FAA2 == 0
|
||||
* - H'04 set_value_no_immediate_reply: candidate write/update path that stores a value without an immediate serial response; handler H'BD0E; responses none
|
||||
* - H'05 ack_or_clear_pending: candidate pending/event acknowledgement path; handler H'BD80; responses none
|
||||
* availability: valid checksum/no RX physical error && FAA2 != 0
|
||||
* - H'05 ack_or_clear_pending: continuation-only conditional acknowledgement/session clear path; handler H'BD80; responses none
|
||||
* availability: valid checksum/no RX physical error && FAA2 != 0
|
||||
* note: Only accepted on the continuation dispatcher path when FAA2 != 0.
|
||||
* note: For selector 0x0040, frame 05 00 40 00 00 1F performs no response staging.
|
||||
* note: The handler clears FAA3/FAA2; F9B5 advances only when FAA2.bit3 was set from a queued report.
|
||||
* note: If FAA2 == 0, command 5 falls through the initial dispatcher instead of doing acknowledgement work.
|
||||
* - H'06 set_secondary_value: candidate secondary-table value write path; handler H'BDDB; responses none
|
||||
* - H'07 retransmit_or_error_reply: candidate retransmit/NAK-style path; error handling also builds command 0x07 responses; handler H'BE05; responses response_at_BE22
|
||||
* availability: valid checksum/no RX physical error && FAA2 != 0
|
||||
* - H'07 retransmit_or_error_reply: candidate retransmit path; retry/error handling also builds a command 0x07 RX-payload echo; handler H'BE05; responses response_at_BE22
|
||||
* availability: valid checksum/no RX physical error && FAA2 == 0 OR valid checksum/no RX physical error && FAA2 != 0
|
||||
* note: loc_BE4D is a retry/error echo path: F850=0x07 and F861-F864 are copied into F851-F854 before loc_BA26.
|
||||
* note: Observed frame 07 80 40 20 90 2D means RX bytes F861-F864 were 80 40 20 90; it is not a table value.
|
||||
* command effects:
|
||||
* - H'00 set_value_acked: Candidate acknowledged set: writes value bytes to primary/current tables, flags the index, and stages an echo-style response.
|
||||
* effect: table_write_candidate; target primary_value_table_candidate; source RX[3:4] value bytes, with an observed 0x80 fallback when decoded index is zero; table H'E000
|
||||
* effect: table_write_candidate; target current_value_table_candidate; source same candidate value written to the primary table; table H'E800
|
||||
* effect: flag_update_candidate; target per_index_flag_table_candidate; set bit 7; table H'EC00
|
||||
* evidence: H'BC08, H'BC0C, H'BC20, H'BC22, H'BCB0, H'BCB9, H'BCC1, H'BCC9, H'BCB5, H'BCBD, H'BCC5, H'BCCD
|
||||
* - H'01 read_value: Candidate read: reads the primary table and stages a value response.
|
||||
* - H'01 read_value: Initial/idle candidate read: reads the primary table and stages an odd value response with F852 possibly stale.
|
||||
* effect: table_read_candidate; target primary_value_table_candidate; table H'E000
|
||||
* effect: response_staging_candidate; stage F850-F854 and call loc_BA26
|
||||
* evidence: H'BC08, H'BC0C, H'BC24, H'BC26, H'BCB0, H'BCB9, H'BCC1, H'BCC9, H'BCD7, H'BCE0, H'BCE8, H'BCF0, H'BCF6, H'BCB5, H'BCBD, H'BCC5, H'BCDC, H'BCE4, H'BCFA
|
||||
* evidence: H'BC08, H'BC0C, H'BC24, H'BC26, H'BCD7, H'BCE0, H'BCE8, H'BCF0, H'BCF6, H'BCDC, H'BCE4, H'BCFA
|
||||
* - H'02 clear_or_abort: Candidate clear/abort: clears serial session state without an observed immediate response.
|
||||
* effect: state_clear_candidate; target serial_session_flags_candidate; clear bit 7; state H'FAA2
|
||||
* evidence: H'BC08, H'BC0C, H'BC29, H'BC2B
|
||||
@@ -140,15 +160,16 @@ extern volatile u8 MEM8[0x10000];
|
||||
* effect: table_write_candidate; target primary_value_table_candidate; source RX[3:4] value bytes, with an observed 0x80 fallback when decoded index is zero; table H'E000
|
||||
* effect: flag_update_candidate; target per_index_flag_table_candidate; set bit 7; table H'EC00
|
||||
* evidence: H'BC08, H'BC0C, H'BC45, H'BC47
|
||||
* - H'05 ack_or_clear_pending: Candidate acknowledgement/clear: updates pending/event state without an observed immediate response.
|
||||
* effect: pending_acknowledgement_candidate; target selected event/pending state; clear selected pending flags and then clear serial session state
|
||||
* - H'05 ack_or_clear_pending: Continuation-only ACK/session clear: clears FAA3/FAA2 and only advances F9B5 when queued-report FAA2.bit3 was set; selector 0x0040 has no response.
|
||||
* effect: conditional_ack_session_clear_candidate; target selected event/pending state; when FAA2 != 0, clear FAA3/FAA2; advance F9B5 only if FAA2.bit3 was set from queued-report state; selector 0x0040 stages no response; selector H'0040 has no response
|
||||
* evidence: H'BC08, H'BC0C, H'BC4A, H'BC4C
|
||||
* - H'06 set_secondary_value: Candidate secondary set: writes value bytes to the secondary table and flags the index.
|
||||
* effect: table_write_candidate; target secondary_value_table_candidate; source RX[3:4] value bytes; table H'E400
|
||||
* effect: flag_update_candidate; target per_index_flag_table_candidate; set bit 6; table H'EC00
|
||||
* evidence: H'BC08, H'BC0C, H'BC4F, H'BC51
|
||||
* - H'07 retransmit_or_error_reply: Candidate retransmit/error reply: reuses prior TX bytes or builds an explicit 0x07 retry/error response.
|
||||
* - H'07 retransmit_or_error_reply: Candidate retransmit/error reply: reuses prior TX bytes or copies RX payload bytes behind an explicit 0x07 retry/error echo.
|
||||
* effect: retransmit_candidate; target TX staging bytes H'F850-H'F854 before loc_BA26; source previous TX frame bytes H'F858-H'F85C
|
||||
* effect: retry_error_echo_candidate; target F850=0x07, F851-F854=F861-F864 before loc_BA26; source RX payload bytes F861-F864; 07 80 40 20 90 2D echoes RX payload 80 40 20 90; it is not a table value
|
||||
* effect: response_staging_candidate; stage F850-F854 and call loc_BA26
|
||||
* evidence: H'BC08, H'BC0C, H'BC2E, H'BC30, H'BC54, H'BC56, H'BE09, H'BE11, H'BE19, H'BE22
|
||||
* response schemas:
|
||||
@@ -156,8 +177,11 @@ extern volatile u8 MEM8[0x10000];
|
||||
* evidence: H'BB1C, H'BB2B, H'BB20, H'BB3F, H'BB39
|
||||
* - response_at_BCCD: byte0=0x04; byte1=rx[1]; byte2=rx[2]; byte3=rx[3]; byte4=rx[4]
|
||||
* evidence: H'BCB0, H'BCB9, H'BCC1, H'BCC9
|
||||
* - response_at_BCFA: byte0=0x04; byte1=rx[2]; byte2=rx[2]; byte3=primary_value_table_candidate; byte4=primary_value_table_candidate
|
||||
* evidence: H'BCD7, H'BCE8, H'BCC1, H'BCF6, H'BCF0
|
||||
* - response_at_BCFA: byte0=0x04; byte1=rx[2]; byte2=stale/unchanged; byte3=primary_value_table_candidate; byte4=primary_value_table_candidate
|
||||
* note: Command 1 BCD7 staging is odd: F850=0x04; F851 is written from F861 then overwritten by F862.
|
||||
* note: The primary table word is read from E000 + 2*selector; F854/F853 receive low/high value bytes.
|
||||
* note: F852 may be stale or unchanged in this handler; avoid a fixed 04 00 QQ hi lo response shape.
|
||||
* evidence: H'BCD7, H'BCE8, H'BCF6, H'BCF0
|
||||
* - response_at_BE22: byte0=tx[0]; byte1=tx[1]; byte2=tx[2]; byte3=tx[3]; byte4=tx[4]
|
||||
* evidence: H'BE09, H'BE11, H'BE19
|
||||
* - ... 1 more candidate response schemas
|
||||
@@ -170,6 +194,36 @@ extern volatile u8 MEM8[0x10000];
|
||||
* evidence: H'1A09, H'1A71, H'3F90, H'407F, H'BB35, H'BC79, H'BC99, H'BD1E
|
||||
* - flag_table_candidate at H'EC00 (bit_flags); observed write
|
||||
* evidence: H'4088, H'BC82, H'BC9D, H'BD22, H'BD39, H'BDE9
|
||||
* panel selector semantics:
|
||||
* - 0x0013 slave_and_iris_mblack_link_lamps: Selector 0x0013 is a two-bit lamp/status word. ROM dispatch H'2E06 reads current table word H'E826 and fans bit 15 and bit 14 into panel latch RAM.
|
||||
* current word: H'E826; dispatch: H'2E06
|
||||
* 0x8000 -> SLAVE lamp: sets F791.6 and F713.4; RAM F791.6, F713.4
|
||||
* 0x4000 -> IRIS/M.BLACK LINK lamp: sets F791.5 and F716.7; RAM F791.5, F716.7
|
||||
* observed values: 0x8000 SLAVE lamp on; 0x4000 IRIS/M.BLACK LINK lamp on; 0x0000 SLAVE and IRIS/M.BLACK LINK latch bits clear through H'2E06
|
||||
* state machine: iris_mblack_link_closed_loop_state_candidate: Bench-proven closed loop: the RCP reports local IRIS/M.BLACK LINK intent, the CCU ACKs selector 0x0013, then the CCU mirrors the accepted selector state back with command 0. The mirrored state controls the next toggle direction.
|
||||
* frames: active report 00 00 13 40 00 09; clear report 00 00 13 00 00 49; ACK 05 00 13 00 00 4C; mirror active 00 00 13 40 00 09; mirror clear 00 00 13 00 00 49
|
||||
* local trigger candidates: provisional_iris_mblack_link_button_toggle_report F006.7 / F6DB.7: When F6DB.7 is asserted and F731 <= 3, the ROM toggles current-table bit 14 at H'E826 based on F791.5, then queues selector 0x0013 through loc_3E54.; H'1FE8/H'1FFB: Adjacent local helpers set or clear current-table bit 15 at H'E826 and queue selector 0x0013.
|
||||
* evidence: bench: 00 00 13 80 00 C9 lights far-right SLAVE lamp, bench: 00 00 13 40 00 09 lights IRIS/M.BLACK LINK lamp, ROM: H'2E06-H'2E32 tests H'E826 bits 15/14 and sets/clears F791/F713/F716 latch bits
|
||||
* - 0x0015 call_and_red_tally_lamp_lane: Bench-visible CALL lamp and red tally lane; local CALL handler mirrors F6DB.5 into E800[0x0015].15.
|
||||
* current word: H'E82A; dispatch: handler unknown
|
||||
* observed values: 0x8000 CALL lamp and red tally on; 0x0000 CALL inactive/clear report
|
||||
* evidence: bench: 00 00 15 80 00 CF lights CALL and red tally, ROM: H'20A1-H'20BA reads F6DB.5, writes H'E82A, and queues selector 0x0015
|
||||
* - 0x0017 bars_lamp_lane: Bench-visible BARS lamp/latch lane; low writes do not reliably clear the visible latch.
|
||||
* current word: H'E82E; dispatch: handler unknown
|
||||
* observed values: 0x8000 BARS lamp on; 0x4000 BARS lamp/latch on; 0x0000 BARS low write; visible latch may remain
|
||||
* evidence: bench: 00 00 17 80 00 CD lights BARS, bench: 00 00 17 40 00 0D also lights the BARS latch in neighbor sweep, ROM: H'1EDE can queue selector 0x0017 from F6D4.2
|
||||
* - 0x001A monitor_selector_lamps: Bench-visible MONITOR selector cluster found from ROM-derived button-output sweep.
|
||||
* current word: H'E834; dispatch: handler unknown
|
||||
* observed values: 0x0808 MONITOR ENC lamp; 0x2020 MONITOR B lamp; 0x4040 MONITOR G lamp; 0x8080 MONITOR R lamp
|
||||
* evidence: bench: 00 00 1A 08 08 40 lights MONITOR ENC, bench: 00 00 1A 20 20 40 lights MONITOR B, bench: 00 00 1A 40 40 40 lights MONITOR G, bench: 00 00 1A 80 80 40 lights MONITOR R, ROM: H'1CB2-H'1D56 writes packed values to H'E834 and queues selector 0x001A
|
||||
* - 0x0024 lcd_selector_button_lamp: Bench-visible LCD selector-button lamp lane.
|
||||
* current word: H'E848; dispatch: dispatch unknown
|
||||
* observed values: 0x8000 LCD selector-button lamp visible; 0x0000 lamp remained visible at 0.5 s in isolation run
|
||||
* - 0x006B standard_lamp_lane: Bench-visible STANDARD lamp lane found from ROM-derived F6D4.6 handler candidate.
|
||||
* current word: H'E8D6; dispatch: handler unknown
|
||||
* observed values: 0x8000 STANDARD lamp on
|
||||
* evidence: bench: 00 00 6B 80 00 B1 lights STANDARD, ROM: H'2048 can write H'E8D6=0x8000 and queue selector 0x006B from F6D4.6
|
||||
* - ... 5 more panel selector annotations
|
||||
* state variable candidates:
|
||||
* - event_queue_read_cursor_candidate H'F9B4: reads 1, writes 2; bits 5
|
||||
* evidence: H'BE78, H'BE95, H'BE99
|
||||
@@ -186,7 +240,9 @@ extern volatile u8 MEM8[0x10000];
|
||||
* - ... 7 more state-variable candidates
|
||||
* retry/error model candidate:
|
||||
* - checksum path: 0x5A-seeded XOR over RX[0..4] differs from RX[5] -> loc_BE29
|
||||
* - retry path: counter H'FAA6, threshold 2; Candidate retry path clears/consults serial flags, increments FAA6, compares it with 2, and when still below the apparent limit stages a command 0x07 response.
|
||||
* - retry path: counter H'FAA6, threshold 2; Candidate retry path clears/consults serial flags, increments FAA6, compares it with 2, and when still below the apparent limit enters loc_BE4D to stage a command 0x07 retry/error echo of RX payload bytes F861-F864.
|
||||
* echo path: loc_BE4D: F850=0x07; F851-F854=F861-F864
|
||||
* echo caveat: 07 80 40 20 90 2D echoes RX payload 80 40 20 90 and is not a table value.
|
||||
* - command 0x07 path: Candidate retransmit/explicit command 0x07 path either copies previous TX frame bytes back to F850-F854 or stages an observed 0x07 response before loc_BA26.
|
||||
* - evidence: H'BBD8, H'BBDC, H'BBE0, H'BBE4, H'BBE8, H'BBEC, H'BBF0, H'BE4D, H'BE56, H'BE5E, H'BE66, H'BE52, H'BE5A, H'BE62, H'BE6A, H'BE29, H'BE2D, H'BE33, H'BE37, H'BE43, H'BE47, H'BE05, H'BE0D, H'BE15, H'BE09, H'BE11, H'BE19, H'BE22
|
||||
* gate/queue state machine candidate:
|
||||
@@ -201,7 +257,7 @@ extern volatile u8 MEM8[0x10000];
|
||||
* - session_timeout_clears_gate_and_queue: When F9C5 is clear, loc_3FEF clears F9B5/F9B0 and clears FAA5.bit7; when nonzero, it sets FAA5.bit7.
|
||||
* - idle_heartbeat_gate_initial_delay_loaded: Startup/init loads F9C4 with H'14 before the first idle/default report can be queued.
|
||||
* - idle_heartbeat_gate_post_send_delay_loaded: loc_BA26 reloads F9C4 with H'07 after each send, matching the observed heartbeat spacing.
|
||||
* - host_ack_can_advance_queue: Commands 0x05/0x06 are modeled as acknowledgement paths that can clear pending state or advance F9B5.; commands H'05, H'06
|
||||
* - host_ack_can_advance_queue: Command 0x05 is a continuation-only ACK/session clear path: it clears FAA3/FAA2 and advances F9B5 only when queued-report FAA2.bit3 was set. Selector 0x0040 has no response; if FAA2 == 0 the command falls through instead of doing ACK work.; commands H'05
|
||||
* - caveat: Many panel controls may require host/session traffic before reporting. Observed autonomous call/camera-power indexes are runtime/capture overlays, not ROM constants.
|
||||
* - evidence: H'3FD3, H'3FD7, H'3FD9, H'3FDD, H'3FDF, H'3FE3, H'3FE5, H'3FE9, H'3FEB, H'3FEF, H'3FF3, H'3FF5, H'3FF9, H'3FFD, H'4001, H'4003, H'4005, H'4007, H'4046, H'404A, H'404C, H'4050, H'4052, H'4056, H'4058, H'4059, H'405D, H'405F, H'4063, H'4065, H'4067, H'406C, H'4070, H'BAF2, H'BAF6, H'BAF8, H'BAFC, H'BAFE, H'BB00, H'BB04, H'BB06, H'BB08, H'BB0C, H'BB0E, H'BB11, H'BB13, H'BB15, H'BB17, H'BB19, H'BB1C, H'BB20, H'BB24, H'BB26, H'BB29, H'BB2B, H'BB2F, H'BB33, H'BB35, H'BB39, H'BB3D, H'BB3F, H'BB43, H'BE9E, H'BEA2, H'BEA5, H'BEA9, H'BEAD, H'BEAF, H'BEB3, H'BEB5, H'BEB9, H'BEBB, H'BEBF, H'BEC1, H'BEC5, H'BECB, H'BECF, H'BED1, H'BED5
|
||||
* TX/autonomous report model candidate:
|
||||
@@ -332,39 +388,261 @@ void frt2_ocia_candidate_tick_isr(void)
|
||||
|
||||
}
|
||||
|
||||
static void sci1_candidate_panel_selector_annotation(u16 logical_index, u16 value)
|
||||
{
|
||||
/* Known bench/ROM selector labels. This helper is commentary for the decompile. */
|
||||
switch (logical_index) {
|
||||
case 0x0013u:
|
||||
/* 0x0013 slave_and_iris_mblack_link_lamps; current word H'E826; H'2E06. */
|
||||
if ((value & 0x8000u) != 0u) {
|
||||
/* SLAVE lamp: sets F791.6 and F713.4. */
|
||||
} else {
|
||||
/* SLAVE lamp: clears F791.6 and F713.4. */
|
||||
}
|
||||
if ((value & 0x4000u) != 0u) {
|
||||
/* IRIS/M.BLACK LINK lamp: sets F791.5 and F716.7. */
|
||||
} else {
|
||||
/* IRIS/M.BLACK LINK lamp: clears F791.5 and F716.7. */
|
||||
}
|
||||
if (value == 0x8000u) {
|
||||
/* SLAVE lamp on. */
|
||||
}
|
||||
if (value == 0x4000u) {
|
||||
/* IRIS/M.BLACK LINK lamp on. */
|
||||
}
|
||||
if (value == 0x0000u) {
|
||||
/* SLAVE and IRIS/M.BLACK LINK latch bits clear through H'2E06. */
|
||||
}
|
||||
break;
|
||||
case 0x0015u:
|
||||
/* 0x0015 call_and_red_tally_lamp_lane; current word H'E82A; handler unknown. */
|
||||
if (value == 0x8000u) {
|
||||
/* CALL lamp and red tally on. */
|
||||
}
|
||||
if (value == 0x0000u) {
|
||||
/* CALL inactive/clear report. */
|
||||
}
|
||||
break;
|
||||
case 0x0017u:
|
||||
/* 0x0017 bars_lamp_lane; current word H'E82E; handler unknown. */
|
||||
if (value == 0x8000u) {
|
||||
/* BARS lamp on. */
|
||||
}
|
||||
if (value == 0x4000u) {
|
||||
/* BARS lamp/latch on. */
|
||||
}
|
||||
if (value == 0x0000u) {
|
||||
/* BARS low write; visible latch may remain. */
|
||||
}
|
||||
break;
|
||||
case 0x001Au:
|
||||
/* 0x001A monitor_selector_lamps; current word H'E834; handler unknown. */
|
||||
if (value == 0x0808u) {
|
||||
/* MONITOR ENC lamp. */
|
||||
}
|
||||
if (value == 0x2020u) {
|
||||
/* MONITOR B lamp. */
|
||||
}
|
||||
if (value == 0x4040u) {
|
||||
/* MONITOR G lamp. */
|
||||
}
|
||||
if (value == 0x8080u) {
|
||||
/* MONITOR R lamp. */
|
||||
}
|
||||
break;
|
||||
case 0x0024u:
|
||||
/* 0x0024 lcd_selector_button_lamp; current word H'E848; dispatch unknown. */
|
||||
if (value == 0x8000u) {
|
||||
/* LCD selector-button lamp visible. */
|
||||
}
|
||||
if (value == 0x0000u) {
|
||||
/* lamp remained visible at 0.5 s in isolation run. */
|
||||
}
|
||||
break;
|
||||
case 0x006Bu:
|
||||
/* 0x006B standard_lamp_lane; current word H'E8D6; handler unknown. */
|
||||
if (value == 0x8000u) {
|
||||
/* STANDARD lamp on. */
|
||||
}
|
||||
break;
|
||||
case 0x0082u:
|
||||
/* 0x0082 iris_readout_lane; current word H'E904; dispatch unknown. */
|
||||
if (value == 0x8000u) {
|
||||
/* IRIS display OP. */
|
||||
}
|
||||
if (value == 0x4000u) {
|
||||
/* IRIS display 1.4. */
|
||||
}
|
||||
if (value == 0x0000u) {
|
||||
/* IRIS display blank. */
|
||||
}
|
||||
break;
|
||||
case 0x0083u:
|
||||
/* 0x0083 combined_iris_shutter_master_gain_status_lane; current word H'E906; dispatch unknown. */
|
||||
if (value == 0x8000u) {
|
||||
/* IRIS AUTO, SHUTTER OFF, MASTER GAIN -3. */
|
||||
}
|
||||
if (value == 0x4000u) {
|
||||
/* IRIS AUTO, SHUTTER OFF, MASTER GAIN 0. */
|
||||
}
|
||||
if (value == 0x2000u) {
|
||||
/* IRIS AUTO, SHUTTER OFF, MASTER GAIN 3. */
|
||||
}
|
||||
if (value == 0x0004u) {
|
||||
/* IRIS AUTO, SHUTTER OFF, MASTER GAIN HP. */
|
||||
}
|
||||
if (value == 0x0000u) {
|
||||
/* same visible state remained at 0.5 s. */
|
||||
}
|
||||
break;
|
||||
case 0x008Fu:
|
||||
/* 0x008F shutter_display_status_lane; current word H'E91E; dispatch unknown. */
|
||||
if (value == 0x8000u) {
|
||||
/* IRIS AUTO plus shutter value beginning with 1. */
|
||||
}
|
||||
if (value == 0x2000u) {
|
||||
/* IRIS AUTO plus shutter 00.0. */
|
||||
}
|
||||
if (value == 0x0800u) {
|
||||
/* IRIS AUTO plus shutter EVS. */
|
||||
}
|
||||
if (value == 0x1000u) {
|
||||
/* IRIS AUTO plus shutter OFF. */
|
||||
}
|
||||
break;
|
||||
case 0x0093u:
|
||||
/* 0x0093 white_balance_black_flare_mode_lane; current word H'E926; dispatch unknown. */
|
||||
if (value == 0x8000u) {
|
||||
/* BLACK/FLARE MANUAL plus white-balance PRESET. */
|
||||
}
|
||||
if (value == 0x4000u) {
|
||||
/* BLACK/FLARE MANUAL plus white-balance AUTO. */
|
||||
}
|
||||
if (value == 0x2000u) {
|
||||
/* BLACK/FLARE MANUAL plus white-balance MANUAL. */
|
||||
}
|
||||
if (value == 0x1020u) {
|
||||
/* BLACK/FLARE MANUAL plus white-balance MANUAL. */
|
||||
}
|
||||
if (value == 0x4040u) {
|
||||
/* BLACK/FLARE AUTO plus white-balance AUTO. */
|
||||
}
|
||||
if (value == 0x8040u) {
|
||||
/* BLACK/FLARE AUTO plus white-balance PRESET. */
|
||||
}
|
||||
if (value == 0x0020u) {
|
||||
/* BLACK/FLARE MANUAL plus white-balance MANUAL. */
|
||||
}
|
||||
if (value == 0x0040u) {
|
||||
/* BLACK/FLARE AUTO plus white-balance MANUAL. */
|
||||
}
|
||||
if (value == 0x0000u) {
|
||||
/* BLACK/FLARE MANUAL plus white-balance MANUAL. */
|
||||
}
|
||||
break;
|
||||
case 0x0110u:
|
||||
/* 0x0110 knee_auto_lamp_or_page_status_lane; current word H'EA20; dispatch unknown. */
|
||||
if (value == 0x8000u) {
|
||||
/* KNEE AUTO lamp/status on. */
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void provisional_iris_mblack_link_button_toggle_report(void)
|
||||
{
|
||||
/* Provisional name for ROM H'200E: When F6DB.7 is asserted and F731 <= 3, the ROM toggles current-table bit 14 at H'E826 based on F791.5, then queues selector 0x0013 through loc_3E54. */
|
||||
/* Source F006.7 / F6DB.7; gate F731 <= 3; current state F791.5. */
|
||||
if ((MEM8[0xF6DBu] & BIT(7)) == 0u) {
|
||||
return;
|
||||
}
|
||||
if (MEM8[0xF731u] > 3u) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((MEM8[0xF791u] & BIT(5)) == 0u) {
|
||||
/* Requests selector 0x0013=0x4000: 00 00 13 40 00 09. */
|
||||
/* CCU should ACK 05 00 13 00 00 4C, then mirror 00 00 13 40 00 09. */
|
||||
} else {
|
||||
/* Requests selector 0x0013=0x0000: 00 00 13 00 00 49. */
|
||||
/* CCU should ACK 05 00 13 00 00 4C, then mirror 00 00 13 00 00 49. */
|
||||
}
|
||||
}
|
||||
|
||||
void sci1_process_candidate_protocol_command(void)
|
||||
{
|
||||
u8 command = sci1_rx_candidate_command();
|
||||
u16 logical_index = sci1_rx_candidate_logical_index();
|
||||
u16 value = sci1_rx_candidate_value();
|
||||
|
||||
sci1_candidate_panel_selector_annotation(logical_index, value);
|
||||
|
||||
bool session_active = MEM8[0xFAA2u] != 0u;
|
||||
|
||||
if (!session_active) {
|
||||
/* Initial/idle dispatcher: valid checksum/no RX error, FAA2 == 0. */
|
||||
switch (command) {
|
||||
case 0x00u:
|
||||
/* set_value_acked: candidate write of RX[3:4] into primary/current tables, followed by a response
|
||||
* availability: valid checksum/no RX physical error && FAA2 == 0
|
||||
* candidate effect: table_write_candidate; target primary_value_table_candidate; source RX[3:4] value bytes, with an observed 0x80 fallback when decoded index is zero; table H'E000
|
||||
* candidate effect: table_write_candidate; target current_value_table_candidate; source same candidate value written to the primary table; table H'E800
|
||||
* candidate effect: flag_update_candidate; target per_index_flag_table_candidate; set bit 7; table H'EC00
|
||||
* evidence: H'BC08, H'BC0C, H'BC20, H'BC22, H'BCB0, H'BCB9, H'BCC1, H'BCC9, H'BCB5, H'BCBD, H'BCC5, H'BCCD
|
||||
*/
|
||||
candidate_set_value_acked(logical_index, value);
|
||||
break;
|
||||
case 0x01u:
|
||||
/* read_value: initial/idle-path primary table read only, followed by an odd response staging sequence
|
||||
* availability: valid checksum/no RX physical error && FAA2 == 0 && F861.bit7 == 0
|
||||
* note: Only accepted on the initial/idle dispatcher path: valid checksum/no RX error, FAA2 == 0, and F861.bit7 == 0.
|
||||
* note: BCD7 stages F850=0x04, writes F851 from F861 and then overwrites F851 from F862.
|
||||
* note: BCD7 reads the primary table word at E000 + 2*selector; F854 receives the low byte and F853 receives the high byte.
|
||||
* note: F852 is not freshly written in the BCD7 handler, so do not describe the response as a fixed 04 00 QQ hi lo frame.
|
||||
* candidate effect: table_read_candidate; target primary_value_table_candidate; table H'E000
|
||||
* candidate effect: response_staging_candidate; stage F850-F854 and call loc_BA26
|
||||
* evidence: H'BC08, H'BC0C, H'BC24, H'BC26, H'BCD7, H'BCE0, H'BCE8, H'BCF0, H'BCF6, H'BCDC, H'BCE4, H'BCFA
|
||||
*/
|
||||
if ((RX_FRAME(1) & 0x80u) != 0u) {
|
||||
candidate_unknown_command(command, logical_index, value);
|
||||
break;
|
||||
}
|
||||
candidate_read_value(logical_index, value);
|
||||
break;
|
||||
case 0x02u:
|
||||
/* clear_or_abort: candidate clear/abort path with no immediate response builder
|
||||
* availability: valid checksum/no RX physical error && FAA2 == 0
|
||||
* candidate effect: state_clear_candidate; target serial_session_flags_candidate; clear bit 7; state H'FAA2
|
||||
* evidence: H'BC08, H'BC0C, H'BC29, H'BC2B
|
||||
*/
|
||||
candidate_clear_or_abort(logical_index, value);
|
||||
break;
|
||||
case 0x07u:
|
||||
/* retransmit_or_error_reply: candidate retransmit path; retry/error handling also builds a command 0x07 RX-payload echo
|
||||
* availability: valid checksum/no RX physical error && FAA2 == 0 OR valid checksum/no RX physical error && FAA2 != 0
|
||||
* note: loc_BE4D is a retry/error echo path: F850=0x07 and F861-F864 are copied into F851-F854 before loc_BA26.
|
||||
* note: Observed frame 07 80 40 20 90 2D means RX bytes F861-F864 were 80 40 20 90; it is not a table value.
|
||||
* candidate effect: retransmit_candidate; target TX staging bytes H'F850-H'F854 before loc_BA26; source previous TX frame bytes H'F858-H'F85C
|
||||
* candidate effect: retry_error_echo_candidate; target F850=0x07, F851-F854=F861-F864 before loc_BA26; source RX payload bytes F861-F864; 07 80 40 20 90 2D echoes RX payload 80 40 20 90; it is not a table value
|
||||
* candidate effect: response_staging_candidate; stage F850-F854 and call loc_BA26
|
||||
* evidence: H'BC08, H'BC0C, H'BC2E, H'BC30, H'BC54, H'BC56, H'BE09, H'BE11, H'BE19, H'BE22
|
||||
*/
|
||||
candidate_retransmit_or_error_reply(logical_index, value);
|
||||
break;
|
||||
default:
|
||||
candidate_unknown_command(command, logical_index, value);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Continuation dispatcher: FAA2 != 0. */
|
||||
switch (command) {
|
||||
case 0x00u:
|
||||
/* set_value_acked: candidate write of RX[3:4] into primary/current tables, followed by a response
|
||||
* candidate effect: table_write_candidate; target primary_value_table_candidate; source RX[3:4] value bytes, with an observed 0x80 fallback when decoded index is zero; table H'E000
|
||||
* candidate effect: table_write_candidate; target current_value_table_candidate; source same candidate value written to the primary table; table H'E800
|
||||
* candidate effect: flag_update_candidate; target per_index_flag_table_candidate; set bit 7; table H'EC00
|
||||
* evidence: H'BC08, H'BC0C, H'BC20, H'BC22, H'BCB0, H'BCB9, H'BCC1, H'BCC9, H'BCB5, H'BCBD, H'BCC5, H'BCCD
|
||||
*/
|
||||
candidate_set_value_acked(logical_index, value);
|
||||
break;
|
||||
case 0x01u:
|
||||
/* read_value: candidate read from the primary table, followed by a response carrying the value
|
||||
* candidate effect: table_read_candidate; target primary_value_table_candidate; table H'E000
|
||||
* candidate effect: response_staging_candidate; stage F850-F854 and call loc_BA26
|
||||
* evidence: H'BC08, H'BC0C, H'BC24, H'BC26, H'BCB0, H'BCB9, H'BCC1, H'BCC9, H'BCD7, H'BCE0, H'BCE8, H'BCF0, H'BCF6, H'BCB5, H'BCBD, H'BCC5, H'BCDC, H'BCE4, H'BCFA
|
||||
*/
|
||||
candidate_read_value(logical_index, value);
|
||||
break;
|
||||
case 0x02u:
|
||||
/* clear_or_abort: candidate clear/abort path with no immediate response builder
|
||||
* candidate effect: state_clear_candidate; target serial_session_flags_candidate; clear bit 7; state H'FAA2
|
||||
* evidence: H'BC08, H'BC0C, H'BC29, H'BC2B
|
||||
*/
|
||||
candidate_clear_or_abort(logical_index, value);
|
||||
break;
|
||||
case 0x04u:
|
||||
/* set_value_no_immediate_reply: candidate write/update path that stores a value without an immediate serial response
|
||||
* availability: valid checksum/no RX physical error && FAA2 != 0
|
||||
* candidate effect: table_write_candidate; target primary_value_table_candidate; source RX[3:4] value bytes, with an observed 0x80 fallback when decoded index is zero; table H'E000
|
||||
* candidate effect: flag_update_candidate; target per_index_flag_table_candidate; set bit 7; table H'EC00
|
||||
* evidence: H'BC08, H'BC0C, H'BC45, H'BC47
|
||||
@@ -372,14 +650,20 @@ void sci1_process_candidate_protocol_command(void)
|
||||
candidate_set_value_no_immediate_reply(logical_index, value);
|
||||
break;
|
||||
case 0x05u:
|
||||
/* ack_or_clear_pending: candidate pending/event acknowledgement path
|
||||
* candidate effect: pending_acknowledgement_candidate; target selected event/pending state; clear selected pending flags and then clear serial session state
|
||||
/* ack_or_clear_pending: continuation-only conditional acknowledgement/session clear path
|
||||
* availability: valid checksum/no RX physical error && FAA2 != 0
|
||||
* note: Only accepted on the continuation dispatcher path when FAA2 != 0.
|
||||
* note: For selector 0x0040, frame 05 00 40 00 00 1F performs no response staging.
|
||||
* note: The handler clears FAA3/FAA2; F9B5 advances only when FAA2.bit3 was set from a queued report.
|
||||
* note: If FAA2 == 0, command 5 falls through the initial dispatcher instead of doing acknowledgement work.
|
||||
* candidate effect: conditional_ack_session_clear_candidate; target selected event/pending state; when FAA2 != 0, clear FAA3/FAA2; advance F9B5 only if FAA2.bit3 was set from queued-report state; selector 0x0040 stages no response; selector H'0040 has no response
|
||||
* evidence: H'BC08, H'BC0C, H'BC4A, H'BC4C
|
||||
*/
|
||||
candidate_ack_or_clear_pending(logical_index, value);
|
||||
break;
|
||||
case 0x06u:
|
||||
/* set_secondary_value: candidate secondary-table value write path
|
||||
* availability: valid checksum/no RX physical error && FAA2 != 0
|
||||
* candidate effect: table_write_candidate; target secondary_value_table_candidate; source RX[3:4] value bytes; table H'E400
|
||||
* candidate effect: flag_update_candidate; target per_index_flag_table_candidate; set bit 6; table H'EC00
|
||||
* evidence: H'BC08, H'BC0C, H'BC4F, H'BC51
|
||||
@@ -387,8 +671,12 @@ void sci1_process_candidate_protocol_command(void)
|
||||
candidate_set_secondary_value(logical_index, value);
|
||||
break;
|
||||
case 0x07u:
|
||||
/* retransmit_or_error_reply: candidate retransmit/NAK-style path; error handling also builds command 0x07 responses
|
||||
/* retransmit_or_error_reply: candidate retransmit path; retry/error handling also builds a command 0x07 RX-payload echo
|
||||
* availability: valid checksum/no RX physical error && FAA2 == 0 OR valid checksum/no RX physical error && FAA2 != 0
|
||||
* note: loc_BE4D is a retry/error echo path: F850=0x07 and F861-F864 are copied into F851-F854 before loc_BA26.
|
||||
* note: Observed frame 07 80 40 20 90 2D means RX bytes F861-F864 were 80 40 20 90; it is not a table value.
|
||||
* candidate effect: retransmit_candidate; target TX staging bytes H'F850-H'F854 before loc_BA26; source previous TX frame bytes H'F858-H'F85C
|
||||
* candidate effect: retry_error_echo_candidate; target F850=0x07, F851-F854=F861-F864 before loc_BA26; source RX payload bytes F861-F864; 07 80 40 20 90 2D echoes RX payload 80 40 20 90; it is not a table value
|
||||
* candidate effect: response_staging_candidate; stage F850-F854 and call loc_BA26
|
||||
* evidence: H'BC08, H'BC0C, H'BC2E, H'BC30, H'BC54, H'BC56, H'BE09, H'BE11, H'BE19, H'BE22
|
||||
*/
|
||||
|
||||
@@ -18,32 +18,32 @@ primary_value_table_candidate H'E000-H'E3FF (negative H'2000; direct H'F900-H'F9
|
||||
accesses=31 reads=21 writes=10 dynamic=11
|
||||
static offsets: H'0000, H'0004, H'0006, H'0046, H'0080, H'0102, H'0124, H'0126, H'014E, H'016E, H'0172, H'01EC, H'0220
|
||||
functions: loc_BBAB:5, loc_2650:3, loc_4096:3, loc_1795:2, loc_19DB:2, loc_1A35:2, loc_48FA:2, vec_ad_adi_3D99:2, <no function>:1, loc_1705:1, loc_174D:1, loc_17C9:1
|
||||
- H'170C read offset H'014E -> H'E14E; loc_1705; BTST.W #15, @H'E14E
|
||||
- H'175A read offset H'016E -> H'E16E; loc_174D; BTST.W #13, @H'E16E
|
||||
- H'179C read offset H'0172 -> H'E172; loc_1795; BTST.W #13, @H'E172
|
||||
- H'17A7 read offset H'0220 -> H'E220; loc_1795; BTST.W #15, @H'E220
|
||||
- H'17D0 read offset H'0126 -> H'E126; loc_17C9; BTST.W #12, @H'E126
|
||||
- H'1802 read offset H'0126 -> H'E126; loc_17FB; BTST.W #12, @H'E126
|
||||
- H'183A read offset H'0126 -> H'E126; loc_182D; BTST.W #5, @H'E126
|
||||
- H'189E read offset H'0126 -> H'E126; loc_1891; BTST.W #5, @H'E126
|
||||
- H'18F4 read offset H'0126 -> H'E126; loc_18E7; BTST.W #5, @H'E126
|
||||
- H'170C read offset H'014E selector 0x0A7 -> H'E14E; loc_1705; BTST.W #15, @H'E14E
|
||||
- H'175A read offset H'016E selector 0x0B7 -> H'E16E; loc_174D; BTST.W #13, @H'E16E
|
||||
- H'179C read offset H'0172 selector 0x0B9 -> H'E172; loc_1795; BTST.W #13, @H'E172
|
||||
- H'17A7 read offset H'0220 selector 0x110 -> H'E220; loc_1795; BTST.W #15, @H'E220
|
||||
- H'17D0 read offset H'0126 selector 0x093 -> H'E126; loc_17C9; BTST.W #12, @H'E126
|
||||
- H'1802 read offset H'0126 selector 0x093 -> H'E126; loc_17FB; BTST.W #12, @H'E126
|
||||
- H'183A read offset H'0126 selector 0x093 -> H'E126; loc_182D; BTST.W #5, @H'E126
|
||||
- H'189E read offset H'0126 selector 0x093 -> H'E126; loc_1891; BTST.W #5, @H'E126
|
||||
- H'18F4 read offset H'0126 selector 0x093 -> H'E126; loc_18E7; BTST.W #5, @H'E126
|
||||
- H'19E3 read index dynamic via R3 operand @(-H'2000,R3); loc_19DB; MOV:G.W @(-H'2000,R3), R0
|
||||
- H'1A03 read index dynamic via R3 operand @(-H'2000,R3); loc_19DB; CMP:G.W @(-H'2000,R3), R1
|
||||
- H'1A3D read index dynamic via R3 operand @(-H'2000,R3); loc_1A35; MOV:G.W @(-H'2000,R3), R0
|
||||
- H'1A6B read index dynamic via R3 operand @(-H'2000,R3); loc_1A35; CMP:G.W @(-H'2000,R3), R0
|
||||
- H'2657 read offset H'0124 -> H'E124; loc_2650; MOV:G.W @H'E124, R0
|
||||
- H'266F read offset H'0004 -> H'E004; loc_2650; BTST.W #13, @H'E004
|
||||
- H'268B read offset H'0124 -> H'E124; loc_2650; CMP:G.W @H'E124, R0
|
||||
- H'3DDA read offset H'0102 -> H'E102; vec_ad_adi_3D99; MOV:G.W @H'E102, R0
|
||||
- H'3DFA read offset H'0102 -> H'E102; vec_ad_adi_3D99; CMP:G.W @H'E102, R1
|
||||
- H'2657 read offset H'0124 selector 0x092 -> H'E124; loc_2650; MOV:G.W @H'E124, R0
|
||||
- H'266F read offset H'0004 selector 0x002 -> H'E004; loc_2650; BTST.W #13, @H'E004
|
||||
- H'268B read offset H'0124 selector 0x092 -> H'E124; loc_2650; CMP:G.W @H'E124, R0
|
||||
- H'3DDA read offset H'0102 selector 0x081 -> H'E102; vec_ad_adi_3D99; MOV:G.W @H'E102, R0
|
||||
- H'3DFA read offset H'0102 selector 0x081 -> H'E102; vec_ad_adi_3D99; CMP:G.W @H'E102, R1
|
||||
- H'3F8C write index dynamic via R0 operand @(-H'2000,R0); <no function>; CLR.W @(-H'2000,R0)
|
||||
- H'402C write offset H'0046 -> H'E046; loc_400C; CLR.W @H'E046
|
||||
- H'402C write offset H'0046 selector 0x023 -> H'E046; loc_400C; CLR.W @H'E046
|
||||
- H'4077 write index dynamic via R0 operand @(-H'2000,R0); loc_4075; CLR.W @(-H'2000,R0)
|
||||
- H'4096 write offset H'0000 -> H'E000; loc_4096; MOV:G.W #H'0080, @H'E000
|
||||
- H'409C write offset H'0006 -> H'E006; loc_4096; MOV:G.W #H'8000, @H'E006
|
||||
- H'40A2 write offset H'0080 -> H'E080; loc_4096; MOV:G.W #H'FFFF, @H'E080
|
||||
- H'490F read offset H'01EC -> H'E1EC; loc_48FA; BTST.W #13, @H'E1EC
|
||||
- H'4915 read offset H'01EC -> H'E1EC; loc_48FA; MOV:G.W @H'E1EC, R0
|
||||
- H'4096 write offset H'0000 selector 0x000 -> H'E000; loc_4096; MOV:G.W #H'0080, @H'E000
|
||||
- H'409C write offset H'0006 selector 0x003 -> H'E006; loc_4096; MOV:G.W #H'8000, @H'E006
|
||||
- H'40A2 write offset H'0080 selector 0x040 -> H'E080; loc_4096; MOV:G.W #H'FFFF, @H'E080
|
||||
- H'490F read offset H'01EC selector 0x0F6 -> H'E1EC; loc_48FA; BTST.W #13, @H'E1EC
|
||||
- H'4915 read offset H'01EC selector 0x0F6 -> H'E1EC; loc_48FA; MOV:G.W @H'E1EC, R0
|
||||
- H'BC75 write index dynamic via R4 operand @(-H'2000,R4); loc_BBAB; MOV:G.W R0, @(-H'2000,R4)
|
||||
- H'BC95 write index dynamic via R4 operand @(-H'2000,R4); loc_BBAB; MOV:G.W R0, @(-H'2000,R4)
|
||||
- H'BCEC read index dynamic via R4 operand @(-H'2000,R4); loc_BBAB; MOV:G.W @(-H'2000,R4), R0
|
||||
@@ -66,16 +66,16 @@ current_value_table_candidate H'E800-H'EBFF (negative H'1800; direct H'F920-H'F9
|
||||
accesses=14 reads=1 writes=13 dynamic=8
|
||||
static offsets: H'0000, H'0006, H'0080, H'0102, H'0124, H'01EC
|
||||
functions: loc_4096:3, loc_BBAB:3, <no function>:1, loc_15E0:1, loc_19DB:1, loc_1A35:1, loc_2650:1, loc_4075:1, loc_48FA:1, loc_BAF2:1
|
||||
- H'15ED write offset H'0102 -> H'E902; loc_15E0; MOV:G.W R1, @H'E902
|
||||
- H'15ED write offset H'0102 selector 0x081 -> H'E902; loc_15E0; MOV:G.W R1, @H'E902
|
||||
- H'1A09 write index dynamic via R3 operand @(-H'1800,R3); loc_19DB; MOV:G.W R1, @(-H'1800,R3)
|
||||
- H'1A71 write index dynamic via R3 operand @(-H'1800,R3); loc_1A35; MOV:G.W R0, @(-H'1800,R3)
|
||||
- H'2691 write offset H'0124 -> H'E924; loc_2650; MOV:G.W R0, @H'E924
|
||||
- H'2691 write offset H'0124 selector 0x092 -> H'E924; loc_2650; MOV:G.W R0, @H'E924
|
||||
- H'3F90 write index dynamic via R0 operand @(-H'1800,R0); <no function>; CLR.W @(-H'1800,R0)
|
||||
- H'407F write index dynamic via R0 operand @(-H'1800,R0); loc_4075; CLR.W @(-H'1800,R0)
|
||||
- H'40A8 write offset H'0000 -> H'E800; loc_4096; MOV:G.W #H'0080, @H'E800
|
||||
- H'40AE write offset H'0006 -> H'E806; loc_4096; MOV:G.W #H'8000, @H'E806
|
||||
- H'40B4 write offset H'0080 -> H'E880; loc_4096; MOV:G.W #H'FFFF, @H'E880
|
||||
- H'491D write offset H'01EC -> H'E9EC; loc_48FA; MOV:G.W R0, @H'E9EC
|
||||
- H'40A8 write offset H'0000 selector 0x000 -> H'E800; loc_4096; MOV:G.W #H'0080, @H'E800
|
||||
- H'40AE write offset H'0006 selector 0x003 -> H'E806; loc_4096; MOV:G.W #H'8000, @H'E806
|
||||
- H'40B4 write offset H'0080 selector 0x040 -> H'E880; loc_4096; MOV:G.W #H'FFFF, @H'E880
|
||||
- H'491D write offset H'01EC selector 0x0F6 -> H'E9EC; loc_48FA; MOV:G.W R0, @H'E9EC
|
||||
- H'BB35 read index dynamic via R0 operand @(-H'1800,R0); loc_BAF2; MOV:G.W @(-H'1800,R0), R4
|
||||
- H'BC79 write index dynamic via R4 operand @(-H'1800,R4); loc_BBAB; MOV:G.W R0, @(-H'1800,R4)
|
||||
- H'BC99 write index dynamic via R4 operand @(-H'1800,R4); loc_BBAB; MOV:G.W R0, @(-H'1800,R4)
|
||||
@@ -85,7 +85,7 @@ flag_table_candidate H'EC00-H'EFFF (negative H'1400; direct H'F980-H'F99F)
|
||||
accesses=6 reads=0 writes=6 dynamic=5
|
||||
static offsets: H'0200
|
||||
functions: loc_BBAB:5, loc_4075:1
|
||||
- H'4088 write offset H'0200 -> H'EE00; loc_4075; CLR.W @(-H'1400,R0)
|
||||
- H'4088 write offset H'0200 selector 0x000 -> H'EE00; loc_4075; CLR.W @(-H'1400,R0)
|
||||
- H'BC82 write index dynamic via R5 operand @(-H'1400,R5); loc_BBAB; BSET.B #7, @(-H'1400,R5)
|
||||
- H'BC9D write index dynamic via R5 operand @(-H'1400,R5); loc_BBAB; BSET.B #7, @(-H'1400,R5)
|
||||
- H'BD22 write index dynamic via R5 operand @(-H'1400,R5); loc_BBAB; BSET.B #7, @(-H'1400,R5)
|
||||
|
||||
86
ccu_emulator/README.md
Normal file
86
ccu_emulator/README.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# PT2 Fake CCU
|
||||
|
||||
This folder contains a small modular fake-CCU runner for the Sony RCP PT2-style serial link.
|
||||
|
||||
The first goal is simple:
|
||||
|
||||
1. Open the RCP serial link at `38400 8E1`.
|
||||
2. Optionally wait for heartbeat.
|
||||
3. Seed active selector-zero state.
|
||||
4. Listen for complete RCP report frames.
|
||||
5. Immediately answer report-looking frames with the neutral command-5 ACK:
|
||||
|
||||
```text
|
||||
05 00 40 00 00 1F
|
||||
```
|
||||
|
||||
ROM and emulator evidence says this consumes the outstanding report cursor without triggering COPY or lamp/display side effects.
|
||||
|
||||
## Run
|
||||
|
||||
Dry-run configuration:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\ccu_emulator.py --dry-run
|
||||
```
|
||||
|
||||
Run against the bench RCP on COM5:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\ccu_emulator.py --port COM5 --duration 30 --log captures\ccu-keepalive.txt
|
||||
```
|
||||
|
||||
Power-cycle first through the COM6 relay:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\ccu_emulator.py --port COM5 --power-cycle --relay-port COM6 --duration 30 --log captures\ccu-keepalive-powercycle.txt
|
||||
```
|
||||
|
||||
Try the older three-frame CONNECT cadence seed instead of the command-0 active seed:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\ccu_emulator.py --seed connect-sequence --seed-gap 0.700 --duration 30
|
||||
```
|
||||
|
||||
Optionally add periodic state refresh traffic:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\ccu_emulator.py --refresh-active --refresh-interval 0.600 --duration 30
|
||||
```
|
||||
|
||||
Enable the bench-proven IRIS/M.BLACK LINK closed-loop module:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\ccu_emulator.py --iris-mblack-link --duration 60 --log captures\ccu-iris-mblack-link.txt
|
||||
```
|
||||
|
||||
When the RCP reports selector `0x0013` as `0x4000` or `0x0000`, this module sends:
|
||||
|
||||
```text
|
||||
05 00 13 00 00 4C ; ACK selector 0x0013
|
||||
00 00 13 40 00 09 ; mirror active, or 00 00 13 00 00 49 for clear
|
||||
```
|
||||
|
||||
That matches the bench-proven IRIS/M.BLACK LINK state machine: the RCP reports local intent, the CCU acknowledges the selector, then the CCU mirrors the accepted state back so the next physical press toggles the other way.
|
||||
|
||||
## Layout
|
||||
|
||||
- `frames.py`: checksums, built-in frames, and simple host-frame builders.
|
||||
- `iris_mblack_link.py`: selector `0x0013` ACK-and-mirror state-machine module.
|
||||
- `modules.py`: small protocol-module interface for feature-specific CCU behavior.
|
||||
- `policy.py`: decides whether an RCP frame should be ACKed.
|
||||
- `refresh.py`: optional periodic state-refresh scheduling.
|
||||
- `serial_link.py`: serial read/write plus checksum-resync frame detection.
|
||||
- `controller.py`: event loop and stats.
|
||||
- `cli.py`: command-line entry point.
|
||||
|
||||
## Why Periodic Lamp/Value Writes Help
|
||||
|
||||
Repeated button/lamp/status writes probably do play into the normal CCU flow. The ROM reloads the broad `F9C5` session watchdog on every complete six-byte RX frame, and command-0/command-4/command-6 table writes refresh the selector tables that drive lamps, readouts, and menus.
|
||||
|
||||
So a real CCU likely does both:
|
||||
|
||||
- reactively ACK RCP reports so the report queue advances, and
|
||||
- stream or refresh panel state so the visible UI remains current.
|
||||
|
||||
The first version keeps those concerns separate: reactive ACKs are always available, while periodic refresh frames are opt-in with `--refresh-frame` or `--refresh-active`.
|
||||
30
ccu_emulator/__init__.py
Normal file
30
ccu_emulator/__init__.py
Normal file
@@ -0,0 +1,30 @@
|
||||
"""Small fake-CCU helpers for the Sony RCP PT2-style serial link."""
|
||||
|
||||
from .controller import CcuEmulator, CcuStats
|
||||
from .frames import (
|
||||
ACTIVE_SEED_COMMAND0,
|
||||
CONNECT_CADENCE_SEQUENCE,
|
||||
HEARTBEAT_FRAME,
|
||||
NEUTRAL_ACK_FRAME,
|
||||
format_frame,
|
||||
frame_checksum,
|
||||
frame_checksum_ok,
|
||||
parse_frame,
|
||||
)
|
||||
from .iris_mblack_link import IrisMblackLinkModule
|
||||
from .policy import AckPolicy
|
||||
|
||||
__all__ = [
|
||||
"ACTIVE_SEED_COMMAND0",
|
||||
"CONNECT_CADENCE_SEQUENCE",
|
||||
"CcuEmulator",
|
||||
"CcuStats",
|
||||
"HEARTBEAT_FRAME",
|
||||
"IrisMblackLinkModule",
|
||||
"NEUTRAL_ACK_FRAME",
|
||||
"AckPolicy",
|
||||
"format_frame",
|
||||
"frame_checksum",
|
||||
"frame_checksum_ok",
|
||||
"parse_frame",
|
||||
]
|
||||
5
ccu_emulator/__main__.py
Normal file
5
ccu_emulator/__main__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from .cli import main
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
208
ccu_emulator/cli.py
Normal file
208
ccu_emulator/cli.py
Normal file
@@ -0,0 +1,208 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
import time
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import TextIO
|
||||
|
||||
from h8536.bench_connect_lcd import (
|
||||
BenchLogger,
|
||||
_import_serial,
|
||||
_read_relay_lines,
|
||||
_relay_command,
|
||||
_relay_settle,
|
||||
add_serial_format_args,
|
||||
open_device_serial,
|
||||
serial_format_label,
|
||||
)
|
||||
|
||||
from .controller import CcuConfig, CcuEmulator
|
||||
from .frames import ACTIVE_SEED_COMMAND0, CONNECT_CADENCE_SEQUENCE, NEUTRAL_ACK_FRAME, format_frame, parse_frame
|
||||
from .iris_mblack_link import IrisMblackLinkModule
|
||||
from .modules import CcuModule
|
||||
from .policy import AckPolicy
|
||||
from .refresh import PeriodicRefresh
|
||||
from .serial_link import SerialLink
|
||||
|
||||
|
||||
def build_arg_parser() -> argparse.ArgumentParser:
|
||||
parser = argparse.ArgumentParser(description="Run a small fake CCU for the Sony RCP PT2-style serial link.")
|
||||
parser.add_argument("--port", default="COM5", help="RS232 serial port connected to the RCP")
|
||||
parser.add_argument("--baud", type=int, default=38400, help="RCP serial baud rate")
|
||||
add_serial_format_args(parser)
|
||||
parser.add_argument("--duration", type=float, default=30.0, help="seconds to run the CCU loop")
|
||||
parser.add_argument("--sync", choices=("checksum", "fixed"), default="checksum", help="RX frame sync strategy")
|
||||
parser.add_argument("--log", type=Path, help="capture log path")
|
||||
|
||||
parser.add_argument(
|
||||
"--seed",
|
||||
choices=("command0", "connect-sequence", "none"),
|
||||
default="command0",
|
||||
help="built-in wake-up seed before reactive ACK loop",
|
||||
)
|
||||
parser.add_argument("--seed-frame", action="append", type=parse_frame, help="custom seed frame; repeatable")
|
||||
parser.add_argument("--seed-gap", type=float, default=0.050, help="seconds to listen after each seed frame")
|
||||
parser.add_argument("--ready-heartbeats", type=int, default=1, help="heartbeats to observe before seeding")
|
||||
parser.add_argument("--ready-timeout", type=float, default=10.0, help="seconds to wait for ready heartbeat")
|
||||
|
||||
parser.add_argument("--ack-frame", type=parse_frame, default=NEUTRAL_ACK_FRAME, help="ACK frame to send after RCP reports")
|
||||
parser.add_argument("--ack-delay", type=float, default=0.0, help="seconds to wait after detecting an RCP frame before ACK")
|
||||
parser.add_argument("--no-ack-heartbeats", action="store_true", help="do not ACK heartbeat frames")
|
||||
parser.add_argument("--no-ack-reports", action="store_true", help="do not ACK report-looking frames")
|
||||
parser.add_argument(
|
||||
"--no-ack-unlabeled",
|
||||
action="store_true",
|
||||
help="do not ACK checksum-valid unlabeled frames outside known report command bytes",
|
||||
)
|
||||
|
||||
parser.add_argument("--refresh-frame", action="append", type=parse_frame, help="optional periodic refresh frame")
|
||||
parser.add_argument(
|
||||
"--refresh-active",
|
||||
action="store_true",
|
||||
help="periodically refresh selector zero with command0 0x8080",
|
||||
)
|
||||
parser.add_argument("--refresh-interval", type=float, default=0.0, help="seconds between optional refresh frames")
|
||||
parser.add_argument("--loop-poll", type=float, default=0.001, help="sleep between service loop iterations")
|
||||
|
||||
parser.add_argument(
|
||||
"--iris-mblack-link",
|
||||
action="store_true",
|
||||
help="enable the selector 0x0013 IRIS/M.BLACK LINK ACK-and-mirror module",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--iris-mblack-link-mirror-delay",
|
||||
type=float,
|
||||
default=0.050,
|
||||
help="seconds between the selector 0x0013 ACK and command-0 mirror",
|
||||
)
|
||||
|
||||
parser.add_argument("--power-cycle", action="store_true", help="power-cycle DUT through relay before starting")
|
||||
parser.add_argument("--relay-port", default="COM6", help="Pico relay serial port")
|
||||
parser.add_argument("--relay-baud", type=int, default=115200, help="Pico relay serial baud rate")
|
||||
parser.add_argument("--power-off-command", default="off", help="relay command used to remove DUT power")
|
||||
parser.add_argument("--power-on-command", default="on", help="relay command used to apply DUT power")
|
||||
parser.add_argument("--off-seconds", type=float, default=1.5, help="seconds to hold DUT powered off")
|
||||
parser.add_argument("--relay-settle", type=float, default=2.0, help="seconds to wait after opening relay port")
|
||||
|
||||
parser.add_argument("--dry-run", action="store_true", help="print configuration without opening serial ports")
|
||||
return parser
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None, *, stdout: TextIO = sys.stdout) -> int:
|
||||
args = build_arg_parser().parse_args(argv)
|
||||
seed_frames = _seed_frames(args)
|
||||
refresh_frames = _refresh_frames(args)
|
||||
modules = _modules(args)
|
||||
log_path = args.log or _default_log_path()
|
||||
|
||||
if args.dry_run:
|
||||
_print_dry_run(args, seed_frames, refresh_frames, modules, log_path, stdout)
|
||||
return 0
|
||||
|
||||
serial = _import_serial()
|
||||
logger = BenchLogger(log_path, stdout=stdout)
|
||||
relay = None
|
||||
try:
|
||||
logger.emit("PT2 fake CCU")
|
||||
logger.emit(f"device={args.port} {args.baud} {serial_format_label(args)} sync={args.sync}")
|
||||
logger.emit(f"log={log_path}")
|
||||
logger.emit(f"ack_frame={format_frame(args.ack_frame)}")
|
||||
logger.emit("seed_frames=" + (" | ".join(format_frame(frame) for frame in seed_frames) or "none"))
|
||||
if refresh_frames:
|
||||
logger.emit(
|
||||
f"refresh_interval={args.refresh_interval:.3f}s frames="
|
||||
+ " | ".join(format_frame(frame) for frame in refresh_frames)
|
||||
)
|
||||
if modules:
|
||||
logger.emit("modules=" + " | ".join(module.name for module in modules))
|
||||
|
||||
with open_device_serial(serial, args) as device:
|
||||
if args.power_cycle:
|
||||
relay = serial.Serial(args.relay_port, args.relay_baud, timeout=0.25)
|
||||
_relay_settle(relay, args.relay_settle, logger)
|
||||
_relay_command(relay, args.power_off_command, logger)
|
||||
time.sleep(max(0.0, args.off_seconds))
|
||||
device.reset_input_buffer()
|
||||
_relay_command(relay, args.power_on_command, logger)
|
||||
else:
|
||||
device.reset_input_buffer()
|
||||
|
||||
link = SerialLink(device, logger, sync_mode=args.sync)
|
||||
config = CcuConfig(
|
||||
seed_frames=tuple(seed_frames),
|
||||
seed_gap=args.seed_gap,
|
||||
ack_delay=args.ack_delay,
|
||||
ready_heartbeats=args.ready_heartbeats,
|
||||
ready_timeout=args.ready_timeout,
|
||||
loop_poll=args.loop_poll,
|
||||
)
|
||||
policy = AckPolicy(
|
||||
ack_frame=args.ack_frame,
|
||||
ack_reports=not args.no_ack_reports,
|
||||
ack_heartbeats=not args.no_ack_heartbeats,
|
||||
ack_unlabeled_checksum_frames=not args.no_ack_unlabeled,
|
||||
)
|
||||
refresh = PeriodicRefresh(frames=refresh_frames, interval=args.refresh_interval)
|
||||
CcuEmulator(link, logger, config=config, ack_policy=policy, refresh=refresh, modules=modules).run(
|
||||
args.duration
|
||||
)
|
||||
return 0
|
||||
finally:
|
||||
if relay is not None:
|
||||
relay.close()
|
||||
logger.close()
|
||||
|
||||
|
||||
def _seed_frames(args: argparse.Namespace) -> list[bytes]:
|
||||
if args.seed_frame:
|
||||
return list(args.seed_frame)
|
||||
if args.seed == "none":
|
||||
return []
|
||||
if args.seed == "connect-sequence":
|
||||
return list(CONNECT_CADENCE_SEQUENCE)
|
||||
return [ACTIVE_SEED_COMMAND0]
|
||||
|
||||
|
||||
def _refresh_frames(args: argparse.Namespace) -> list[bytes]:
|
||||
frames = list(args.refresh_frame or [])
|
||||
if args.refresh_active:
|
||||
frames.append(ACTIVE_SEED_COMMAND0)
|
||||
return frames
|
||||
|
||||
|
||||
def _modules(args: argparse.Namespace) -> tuple[CcuModule, ...]:
|
||||
modules: list[CcuModule] = []
|
||||
if args.iris_mblack_link:
|
||||
modules.append(IrisMblackLinkModule(mirror_delay=max(0.0, args.iris_mblack_link_mirror_delay)))
|
||||
return tuple(modules)
|
||||
|
||||
|
||||
def _print_dry_run(
|
||||
args: argparse.Namespace,
|
||||
seed_frames: list[bytes],
|
||||
refresh_frames: list[bytes],
|
||||
modules: tuple[CcuModule, ...],
|
||||
log_path: Path,
|
||||
stdout: TextIO,
|
||||
) -> None:
|
||||
print(f"device={args.port} {args.baud} {serial_format_label(args)} sync={args.sync}", file=stdout)
|
||||
print(f"duration={args.duration:.3f}s log={log_path}", file=stdout)
|
||||
print(f"power_cycle={int(args.power_cycle)} relay={args.relay_port} {args.relay_baud}", file=stdout)
|
||||
print(f"ack_frame={format_frame(args.ack_frame)}", file=stdout)
|
||||
print("seed_frames=" + (" | ".join(format_frame(frame) for frame in seed_frames) or "none"), file=stdout)
|
||||
print(
|
||||
f"refresh_interval={args.refresh_interval:.3f}s frames="
|
||||
+ (" | ".join(format_frame(frame) for frame in refresh_frames) or "none"),
|
||||
file=stdout,
|
||||
)
|
||||
print("modules=" + (" | ".join(module.name for module in modules) or "none"), file=stdout)
|
||||
|
||||
|
||||
def _default_log_path() -> Path:
|
||||
return Path("captures") / f"ccu-emulator-{datetime.now().strftime('%Y%m%d-%H%M%S')}.txt"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
179
ccu_emulator/controller.py
Normal file
179
ccu_emulator/controller.py
Normal file
@@ -0,0 +1,179 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
|
||||
from h8536.bench_connect_lcd import BenchLogger, format_frame
|
||||
|
||||
from .frames import ACTIVE_SEED_COMMAND0
|
||||
from .modules import CcuModule, ModuleDecision
|
||||
from .policy import AckPolicy
|
||||
from .refresh import PeriodicRefresh
|
||||
from .serial_link import RxFrame, SerialLink
|
||||
|
||||
|
||||
@dataclass
|
||||
class CcuStats:
|
||||
rx_frames: int = 0
|
||||
tx_frames: int = 0
|
||||
ack_frames: int = 0
|
||||
module_frames: int = 0
|
||||
seed_frames: int = 0
|
||||
refresh_frames: int = 0
|
||||
started_at: float = 0.0
|
||||
ended_at: float = 0.0
|
||||
|
||||
@property
|
||||
def elapsed(self) -> float:
|
||||
end = self.ended_at or time.monotonic()
|
||||
return max(0.0, end - self.started_at)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class CcuConfig:
|
||||
seed_frames: tuple[bytes, ...] = (ACTIVE_SEED_COMMAND0,)
|
||||
seed_gap: float = 0.050
|
||||
ack_delay: float = 0.0
|
||||
ready_heartbeats: int = 1
|
||||
ready_timeout: float = 10.0
|
||||
loop_poll: float = 0.001
|
||||
|
||||
|
||||
class CcuEmulator:
|
||||
"""Event-driven fake CCU for the PT2-style RCP serial protocol."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
link: SerialLink,
|
||||
logger: BenchLogger,
|
||||
*,
|
||||
config: CcuConfig | None = None,
|
||||
ack_policy: AckPolicy | None = None,
|
||||
refresh: PeriodicRefresh | None = None,
|
||||
modules: tuple[CcuModule, ...] = (),
|
||||
) -> None:
|
||||
self.link = link
|
||||
self.logger = logger
|
||||
self.config = config or CcuConfig()
|
||||
self.ack_policy = ack_policy or AckPolicy()
|
||||
self.refresh = refresh or PeriodicRefresh()
|
||||
self.modules = modules
|
||||
self.stats = CcuStats()
|
||||
|
||||
def run(self, duration: float) -> CcuStats:
|
||||
self.stats = CcuStats(started_at=time.monotonic())
|
||||
self.logger.event(
|
||||
"CCU_START "
|
||||
f"duration={duration:.3f}s seed_frames={len(self.config.seed_frames)} "
|
||||
f"ack={format_frame(self.ack_policy.ack_frame)} modules={len(self.modules)}"
|
||||
)
|
||||
self._wait_ready()
|
||||
self._send_seed_frames()
|
||||
self.refresh.start()
|
||||
|
||||
deadline = time.monotonic() + max(0.0, duration)
|
||||
try:
|
||||
while time.monotonic() < deadline:
|
||||
self._service_rx()
|
||||
self._service_refresh()
|
||||
time.sleep(max(0.0, self.config.loop_poll))
|
||||
except KeyboardInterrupt:
|
||||
self.logger.event("CCU_STOP keyboard_interrupt")
|
||||
finally:
|
||||
self.stats.ended_at = time.monotonic()
|
||||
self._emit_summary()
|
||||
return self.stats
|
||||
|
||||
def _wait_ready(self) -> None:
|
||||
if self.config.ready_heartbeats <= 0:
|
||||
self.logger.event("READY skipped")
|
||||
return
|
||||
self.logger.event(
|
||||
f"READY_WAIT heartbeats={self.config.ready_heartbeats} timeout={self.config.ready_timeout:.3f}s"
|
||||
)
|
||||
start_count = self.link.detector.labels["heartbeat"]
|
||||
deadline = time.monotonic() + max(0.0, self.config.ready_timeout)
|
||||
while time.monotonic() < deadline:
|
||||
for frame in self.link.read_available():
|
||||
self._record_rx(frame)
|
||||
if self.link.detector.labels["heartbeat"] - start_count >= self.config.ready_heartbeats:
|
||||
self.logger.event(f"READY heartbeat_count={self.link.detector.labels['heartbeat']}")
|
||||
return
|
||||
time.sleep(max(0.0, self.config.loop_poll))
|
||||
self.logger.event(f"READY_TIMEOUT heartbeat_count={self.link.detector.labels['heartbeat']}")
|
||||
|
||||
def _send_seed_frames(self) -> None:
|
||||
for index, frame in enumerate(self.config.seed_frames, start=1):
|
||||
self.link.send(frame, f"seed[{index}]")
|
||||
self.stats.seed_frames += 1
|
||||
self.stats.tx_frames += 1
|
||||
self._listen_for(self.config.seed_gap)
|
||||
|
||||
def _listen_for(self, seconds: float) -> None:
|
||||
deadline = time.monotonic() + max(0.0, seconds)
|
||||
while time.monotonic() < deadline:
|
||||
self._service_rx()
|
||||
self._service_refresh()
|
||||
time.sleep(max(0.0, self.config.loop_poll))
|
||||
|
||||
def _service_rx(self) -> None:
|
||||
for item in self.link.read_available():
|
||||
self._record_rx(item)
|
||||
suppress_default_ack = self._service_modules(item)
|
||||
if suppress_default_ack:
|
||||
continue
|
||||
decision = self.ack_policy.decide(item.frame, item.label)
|
||||
if not decision.should_ack:
|
||||
self.logger.event(f"ACK_SKIP reason={decision.reason} frame={format_frame(item.frame)}")
|
||||
continue
|
||||
if self.config.ack_delay > 0:
|
||||
time.sleep(self.config.ack_delay)
|
||||
self.link.send(decision.frame, f"ack reason={decision.reason}")
|
||||
self.stats.ack_frames += 1
|
||||
self.stats.tx_frames += 1
|
||||
|
||||
def _service_modules(self, item: RxFrame) -> bool:
|
||||
suppress_default_ack = False
|
||||
for module in self.modules:
|
||||
decision = module.on_rx(item.frame, item.label)
|
||||
if decision is None:
|
||||
continue
|
||||
if decision.reason:
|
||||
self.logger.event(
|
||||
f"MODULE {module.name} reason={decision.reason} frame={format_frame(item.frame)}"
|
||||
)
|
||||
self._send_module_decision(decision)
|
||||
suppress_default_ack = suppress_default_ack or decision.suppress_default_ack
|
||||
return suppress_default_ack
|
||||
|
||||
def _send_module_decision(self, decision: ModuleDecision) -> None:
|
||||
for tx in decision.tx:
|
||||
if tx.delay > 0:
|
||||
time.sleep(tx.delay)
|
||||
self.link.send(tx.frame, tx.label)
|
||||
self.stats.module_frames += 1
|
||||
self.stats.tx_frames += 1
|
||||
|
||||
def _service_refresh(self) -> None:
|
||||
for frame in self.refresh.due_frames():
|
||||
self.link.send(frame, "refresh")
|
||||
self.stats.refresh_frames += 1
|
||||
self.stats.tx_frames += 1
|
||||
|
||||
def _record_rx(self, item: RxFrame) -> None:
|
||||
self.stats.rx_frames += 1
|
||||
|
||||
def _emit_summary(self) -> None:
|
||||
self.logger.emit()
|
||||
self.logger.emit("CCU Summary")
|
||||
self.logger.emit(f"elapsed={self.stats.elapsed:.3f}s")
|
||||
self.logger.emit(f"rx_frames={self.stats.rx_frames}")
|
||||
self.logger.emit(f"tx_frames={self.stats.tx_frames}")
|
||||
self.logger.emit(f"ack_frames={self.stats.ack_frames}")
|
||||
self.logger.emit(f"module_frames={self.stats.module_frames}")
|
||||
self.logger.emit(f"seed_frames={self.stats.seed_frames}")
|
||||
self.logger.emit(f"refresh_frames={self.stats.refresh_frames}")
|
||||
self.logger.emit(f"resync_events={self.link.detector.resync_events}")
|
||||
self.logger.emit(f"dropped_bytes={self.link.detector.dropped_bytes}")
|
||||
for label, count in sorted(self.link.detector.labels.items()):
|
||||
self.logger.emit(f"{label}={count}")
|
||||
59
ccu_emulator/frames.py
Normal file
59
ccu_emulator/frames.py
Normal file
@@ -0,0 +1,59 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from h8536.bench_connect_lcd import format_frame, frame_checksum, frame_checksum_ok, parse_frame
|
||||
|
||||
|
||||
FRAME_LENGTH = 6
|
||||
|
||||
HEARTBEAT_FRAME = bytes.fromhex("0000000080DA")
|
||||
|
||||
# Command 0, selector 0, value 0x8080. This seeds E000/E800 selector zero.
|
||||
ACTIVE_SEED_COMMAND0 = bytes.fromhex("00000080805A")
|
||||
|
||||
# The older bench cadence sequence. It is still useful as an optional wake-up
|
||||
# strategy because the real panel proved timing-sensitive around these frames.
|
||||
CONNECT_CADENCE_SEQUENCE = (
|
||||
bytes.fromhex("04000040001E"),
|
||||
bytes.fromhex("0400008000DE"),
|
||||
bytes.fromhex("040000C0009E"),
|
||||
)
|
||||
|
||||
# Command 5, selector 0x0040, value ignored. ROM trace shows this is the safest
|
||||
# neutral report-consume candidate.
|
||||
NEUTRAL_ACK_FRAME = bytes.fromhex("05004000001F")
|
||||
|
||||
|
||||
def build_frame(command: int, selector: int, value: int) -> bytes:
|
||||
"""Build a six-byte host frame for simple page-0/page-1 selectors.
|
||||
|
||||
This helper covers the selector encodings we currently use in fake-CCU
|
||||
probes. Keep more exotic mapping in one place when we learn it.
|
||||
"""
|
||||
|
||||
if not 0 <= command <= 0xFF:
|
||||
raise ValueError("command byte out of range")
|
||||
if not 0 <= selector <= 0x01FF:
|
||||
raise ValueError("selector out of supported range 0x000-0x1FF")
|
||||
if not 0 <= value <= 0xFFFF:
|
||||
raise ValueError("value out of range")
|
||||
|
||||
if selector <= 0x007F:
|
||||
byte1 = 0x00
|
||||
byte2 = selector
|
||||
elif selector <= 0x017F:
|
||||
byte1 = 0x01
|
||||
byte2 = selector - 0x0080
|
||||
else:
|
||||
byte1 = 0x02
|
||||
byte2 = selector - 0x0180
|
||||
|
||||
frame = bytes(
|
||||
[
|
||||
command & 0xFF,
|
||||
byte1 & 0xFF,
|
||||
byte2 & 0xFF,
|
||||
(value >> 8) & 0xFF,
|
||||
value & 0xFF,
|
||||
]
|
||||
)
|
||||
return frame + bytes([frame_checksum(frame)])
|
||||
65
ccu_emulator/iris_mblack_link.py
Normal file
65
ccu_emulator/iris_mblack_link.py
Normal file
@@ -0,0 +1,65 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
from .frames import build_frame, frame_checksum_ok
|
||||
from .modules import ModuleDecision, ModuleTx
|
||||
|
||||
|
||||
SELECTOR_IRIS_MBLACK_LINK = 0x0013
|
||||
IRIS_MBLACK_LINK_CLEAR = 0x0000
|
||||
IRIS_MBLACK_LINK_ACTIVE = 0x4000
|
||||
|
||||
|
||||
def selector_from_frame(frame: bytes) -> int | None:
|
||||
if len(frame) != 6:
|
||||
return None
|
||||
if frame[1] == 0x00:
|
||||
return frame[2]
|
||||
if frame[1] == 0x01:
|
||||
return 0x0080 + frame[2]
|
||||
if frame[1] == 0x02:
|
||||
return 0x0180 + frame[2]
|
||||
return None
|
||||
|
||||
|
||||
def value_from_frame(frame: bytes) -> int | None:
|
||||
if len(frame) != 6:
|
||||
return None
|
||||
return ((frame[3] << 8) | frame[4]) & 0xFFFF
|
||||
|
||||
|
||||
@dataclass
|
||||
class IrisMblackLinkModule:
|
||||
"""Closed-loop CCU side for the IRIS/M.BLACK LINK button/report path."""
|
||||
|
||||
mirror_delay: float = 0.050
|
||||
report_commands: frozenset[int] = frozenset({0x00, 0x01, 0x02})
|
||||
handled_values: frozenset[int] = frozenset({IRIS_MBLACK_LINK_CLEAR, IRIS_MBLACK_LINK_ACTIVE})
|
||||
name: str = "iris_mblack_link"
|
||||
|
||||
def on_rx(self, frame: bytes, label: str = "") -> ModuleDecision | None:
|
||||
if not frame_checksum_ok(frame) or frame[0] not in self.report_commands:
|
||||
return None
|
||||
selector = selector_from_frame(frame)
|
||||
if selector != SELECTOR_IRIS_MBLACK_LINK:
|
||||
return None
|
||||
value = value_from_frame(frame)
|
||||
if value not in self.handled_values:
|
||||
return None
|
||||
|
||||
state = "active" if value == IRIS_MBLACK_LINK_ACTIVE else "clear"
|
||||
ack = build_frame(0x05, SELECTOR_IRIS_MBLACK_LINK, 0x0000)
|
||||
mirror = build_frame(0x00, SELECTOR_IRIS_MBLACK_LINK, value)
|
||||
return ModuleDecision(
|
||||
tx=(
|
||||
ModuleTx(ack, f"{self.name} ack selector=0x0013 value=0x{value:04X}"),
|
||||
ModuleTx(
|
||||
mirror,
|
||||
f"{self.name} mirror {state} selector=0x0013 value=0x{value:04X}",
|
||||
delay=self.mirror_delay,
|
||||
),
|
||||
),
|
||||
suppress_default_ack=True,
|
||||
reason=f"{self.name}_{state}_report",
|
||||
)
|
||||
25
ccu_emulator/modules.py
Normal file
25
ccu_emulator/modules.py
Normal file
@@ -0,0 +1,25 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Protocol
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ModuleTx:
|
||||
frame: bytes
|
||||
label: str
|
||||
delay: float = 0.0
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ModuleDecision:
|
||||
tx: tuple[ModuleTx, ...] = ()
|
||||
suppress_default_ack: bool = False
|
||||
reason: str = ""
|
||||
|
||||
|
||||
class CcuModule(Protocol):
|
||||
name: str
|
||||
|
||||
def on_rx(self, frame: bytes, label: str = "") -> ModuleDecision | None:
|
||||
"""Inspect an RCP frame and optionally provide CCU response frames."""
|
||||
44
ccu_emulator/policy.py
Normal file
44
ccu_emulator/policy.py
Normal file
@@ -0,0 +1,44 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
from .frames import HEARTBEAT_FRAME, NEUTRAL_ACK_FRAME, frame_checksum_ok
|
||||
|
||||
|
||||
REPORT_COMMAND_BYTES = frozenset({0x00, 0x01, 0x02})
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class AckDecision:
|
||||
should_ack: bool
|
||||
frame: bytes = NEUTRAL_ACK_FRAME
|
||||
reason: str = ""
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class AckPolicy:
|
||||
"""Decides whether an RCP-origin frame should get a continuation ACK."""
|
||||
|
||||
ack_frame: bytes = NEUTRAL_ACK_FRAME
|
||||
ack_reports: bool = True
|
||||
ack_heartbeats: bool = True
|
||||
ack_unlabeled_checksum_frames: bool = True
|
||||
|
||||
def decide(self, frame: bytes, label: str = "") -> AckDecision:
|
||||
if not frame_checksum_ok(frame):
|
||||
return AckDecision(False, self.ack_frame, "checksum_bad")
|
||||
|
||||
if frame == HEARTBEAT_FRAME:
|
||||
if self.ack_heartbeats:
|
||||
return AckDecision(True, self.ack_frame, "heartbeat_report")
|
||||
return AckDecision(False, self.ack_frame, "heartbeat_ignored")
|
||||
|
||||
if frame[0] in REPORT_COMMAND_BYTES:
|
||||
if self.ack_reports:
|
||||
return AckDecision(True, self.ack_frame, f"report_cmd_{frame[0]:02X}")
|
||||
return AckDecision(False, self.ack_frame, "reports_disabled")
|
||||
|
||||
if label == "checksum_ok_unlabeled" and self.ack_unlabeled_checksum_frames:
|
||||
return AckDecision(True, self.ack_frame, "unlabeled_checksum_ok")
|
||||
|
||||
return AckDecision(False, self.ack_frame, f"non_report_cmd_{frame[0]:02X}")
|
||||
41
ccu_emulator/refresh.py
Normal file
41
ccu_emulator/refresh.py
Normal file
@@ -0,0 +1,41 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
|
||||
@dataclass
|
||||
class PeriodicRefresh:
|
||||
"""Small scheduler for optional CCU state-refresh frames."""
|
||||
|
||||
frames: list[bytes] = field(default_factory=list)
|
||||
interval: float = 0.0
|
||||
_next_due: float | None = None
|
||||
_index: int = 0
|
||||
|
||||
@property
|
||||
def enabled(self) -> bool:
|
||||
return bool(self.frames) and self.interval > 0
|
||||
|
||||
def start(self, now: float | None = None) -> None:
|
||||
if not self.enabled:
|
||||
self._next_due = None
|
||||
return
|
||||
self._next_due = (time.monotonic() if now is None else now) + self.interval
|
||||
|
||||
def due_frames(self, now: float | None = None) -> list[bytes]:
|
||||
if not self.enabled:
|
||||
return []
|
||||
current = time.monotonic() if now is None else now
|
||||
if self._next_due is None:
|
||||
self._next_due = current + self.interval
|
||||
return []
|
||||
if current < self._next_due:
|
||||
return []
|
||||
|
||||
frame = self.frames[self._index % len(self.frames)]
|
||||
self._index += 1
|
||||
|
||||
while self._next_due <= current:
|
||||
self._next_due += self.interval
|
||||
return [frame]
|
||||
67
ccu_emulator/serial_link.py
Normal file
67
ccu_emulator/serial_link.py
Normal file
@@ -0,0 +1,67 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Iterable
|
||||
|
||||
from h8536.bench_connect_lcd import BenchLogger, FrameDetector, format_frame, label_frame
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class RxFrame:
|
||||
frame: bytes
|
||||
label: str
|
||||
|
||||
|
||||
class SerialLink:
|
||||
"""Thin serial-port wrapper with checksum-resync frame detection."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
device: Any,
|
||||
logger: BenchLogger,
|
||||
*,
|
||||
sync_mode: str = "checksum",
|
||||
) -> None:
|
||||
self.device = device
|
||||
self.logger = logger
|
||||
self.detector = FrameDetector(sync_mode=sync_mode)
|
||||
|
||||
def reset_input(self) -> None:
|
||||
self.device.reset_input_buffer()
|
||||
self.detector = FrameDetector(sync_mode=self.detector.sync_mode)
|
||||
|
||||
def read_available(self) -> list[RxFrame]:
|
||||
waiting = getattr(self.device, "in_waiting", 0)
|
||||
data = self.device.read(waiting or 1)
|
||||
if not data:
|
||||
return []
|
||||
|
||||
dropped_before = self.detector.dropped_bytes
|
||||
self.logger.chunk("RX", data)
|
||||
frames = [RxFrame(frame, label) for frame, label in self.detector.feed(data)]
|
||||
for item in frames:
|
||||
self.logger.event(f"DETECT {item.label} {format_frame(item.frame)}")
|
||||
dropped_now = self.detector.dropped_bytes - dropped_before
|
||||
if dropped_now:
|
||||
self.logger.event(
|
||||
f"RESYNC dropped_bytes={dropped_now} total_dropped={self.detector.dropped_bytes} "
|
||||
f"buffered={len(self.detector.buffer)}"
|
||||
)
|
||||
return frames
|
||||
|
||||
def send(self, frame: bytes, label: str) -> None:
|
||||
self.device.write(frame)
|
||||
self.device.flush()
|
||||
self.logger.chunk("TX", frame)
|
||||
self.logger.event(f"SENT {label} {format_frame(frame)}")
|
||||
|
||||
def labels(self) -> dict[str, int]:
|
||||
return dict(self.detector.labels)
|
||||
|
||||
|
||||
def label_for_frame(frame: bytes) -> str:
|
||||
return label_frame(frame)
|
||||
|
||||
|
||||
def format_frames(frames: Iterable[bytes]) -> str:
|
||||
return " | ".join(format_frame(frame) for frame in frames)
|
||||
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.
|
||||
154
docs/pt2-copy-state-machine.md
Normal file
154
docs/pt2-copy-state-machine.md
Normal file
@@ -0,0 +1,154 @@
|
||||
# PT2 Copy State Machine
|
||||
|
||||
This is a focused reference for the COPY behavior seen on the RCP LCD and traced in the ROM.
|
||||
|
||||
## Known Entry Points
|
||||
|
||||
### Serial Start / Progress
|
||||
|
||||
Frame:
|
||||
|
||||
```text
|
||||
05 00 6D 00 00 32
|
||||
00 00 6D 00 00 37 ; family-00 set/queue form to test
|
||||
```
|
||||
|
||||
ROM path:
|
||||
|
||||
- Command 5 accepts selector `0x006D` at `BD80-BDBF`.
|
||||
- The selector is queued through `BE70`.
|
||||
- Selector `0x006D` dispatches to `H'3015`.
|
||||
|
||||
Observed effects from forced decode:
|
||||
|
||||
- Sets `F731.7`.
|
||||
- Sets `F795.6/F795.7`.
|
||||
- Loads `F798=H'C8`.
|
||||
- Sets display selector `F732=H'1903`.
|
||||
- Sets `FB02=H'64`.
|
||||
- Calls the display/report bridge at `48FA`.
|
||||
- Sets `F76E.6`.
|
||||
|
||||
LCD dispatch:
|
||||
|
||||
- `F732` high byte `0x19` selects `493E[0x19] -> H'930A`.
|
||||
- The local table at `H'931C` maps substate `0x03` to `H'9F6A`.
|
||||
- `H'9F6A` builds `COPY` / `IN PROGRESS`.
|
||||
|
||||
### Serial Complete / Exit
|
||||
|
||||
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:
|
||||
|
||||
- Command 5 accepts selector `0x006C` at `BD80-BDBF`.
|
||||
- The selector is queued through `BE70`.
|
||||
- Selector `0x006C` dispatches to `H'2FAF`.
|
||||
|
||||
Observed effects from forced decode:
|
||||
|
||||
- Manipulates `F76E`, `F795`, `F797`, and `F799`.
|
||||
- Can set display selector `F732=H'1904`.
|
||||
- Sets `FB02=H'14`.
|
||||
- Calls the display/report bridge at `48FA`.
|
||||
|
||||
LCD dispatch:
|
||||
|
||||
- `F732` high byte `0x19` selects `493E[0x19] -> H'930A`.
|
||||
- The local table at `H'931C` maps substate `0x04` to `H'9FDA`.
|
||||
- `H'9FDA` builds `COPY` / `COMPLETED`.
|
||||
|
||||
### RCP-Side Menu Start
|
||||
|
||||
ROM path:
|
||||
|
||||
- OTHERS menu page: `493E[0x01] -> H'631C`.
|
||||
- Local page table: `H'632E`.
|
||||
- `COPY TO SLAVES` entry handler: `H'6FF0`.
|
||||
|
||||
Required gates:
|
||||
|
||||
- The entry descriptor before `H'6FF0` requires `E400[0x0015] != 0`.
|
||||
- The local COPY action branch requires `F770.2` and `F791.7`.
|
||||
|
||||
Local branch effects:
|
||||
|
||||
- Sets `F76E.6`.
|
||||
- Sets `F795.7`.
|
||||
- Sets `F731.7`.
|
||||
- Loads `F798=H'C8`.
|
||||
- Sets `F711.7`.
|
||||
- Loads `F726=H'64`.
|
||||
- Calls `loc_5500`.
|
||||
- Displays `COPY TO SLAVES`.
|
||||
|
||||
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.
|
||||
|
||||
## Working State Model
|
||||
|
||||
| State | Likely indicators | Entry | Exit |
|
||||
| --- | --- | --- | --- |
|
||||
| Idle / no copy | `F731.7` clear | Boot, timeout, or completion cleanup | `0x006D` or local COPY branch |
|
||||
| Copy in progress | `F731.7`, `F795.6/F795.7`, `F798` live, `F732=H'1903` | `05 00 6D 00 00 32` or local COPY branch | `0x006C` in the live window, or timer expiry |
|
||||
| Copy completed | `F732=H'1904` | `05 00 6C 00 00 33` while copy flags are live | Display/session timeout or next state update |
|
||||
| Timeout / not active | `F731.7` cleared by timer path | `F797` or `F798` reaches zero | Normal CONNECT recovery traffic |
|
||||
|
||||
## Bench Results
|
||||
|
||||
Observed on the real panel:
|
||||
|
||||
```text
|
||||
006C alone -> CONNECT OK -> blank
|
||||
006D alone -> CONNECT OK -> COPY IN PROGRESS -> CONNECT NOT ACT
|
||||
006D -> 006C after 250 ms -> COPY IN PROGRESS -> COPY COMPLETED
|
||||
006D -> 006C after 1.0-1.5 s -> COPY IN PROGRESS -> COPY COMPLETED
|
||||
006D -> 006C after 2.0-2.5 s -> COPY IN PROGRESS -> CONNECT NOT ACT
|
||||
006D repeated, then 006C -> COPY IN PROGRESS held longer -> COPY COMPLETED
|
||||
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
|
||||
```
|
||||
|
||||
Webcam-confirmed LCD results from the same 2026-05-27 run:
|
||||
|
||||
```text
|
||||
00 00 6D 00 00 37 -> COPY IN PROGRESS
|
||||
00 00 6C 00 00 36 -> COPY COMPLETED
|
||||
05 00 6D 00 00 32 -> COPY IN PROGRESS
|
||||
05 00 6C 00 00 33 -> COPY COMPLETED
|
||||
```
|
||||
|
||||
The 250 ms and 1000 ms gap variants both produced the same LCD sequence. This
|
||||
means the family-00 selector/write form can reach the COPY LCD side effects, even
|
||||
though its serial response rhythm is the table-readback rhythm rather than the
|
||||
command-5 `01 00 02` / `02 00 04` rhythm.
|
||||
|
||||
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 can display `COPY COMPLETED` when it is sent inside a live copy window, but should not be read as a stateless "show completed" command.
|
||||
- The copy window is transient and timer-controlled.
|
||||
- The panel does not treat `0x006C` as a stateless "show completed" command.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- What sets `F791.7` during normal CCU/RCP operation?
|
||||
- What exact official PT2 name belongs to selectors `0x006C`, `0x006D`, and `0x006E`?
|
||||
- Whether `0x006E` is a copy cancel/error sibling or an unrelated special selector.
|
||||
- Whether the CCU sends repeated progress refreshes during a real COPY TO SLAVES operation.
|
||||
78
docs/pt2-iris-mblack-link-rom-trace.md
Normal file
78
docs/pt2-iris-mblack-link-rom-trace.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# PT2 IRIS/M.BLACK LINK ROM Trace
|
||||
|
||||
This note records the ROM evidence for the bench-visible
|
||||
`IRIS/M.BLACK LINK` lamp.
|
||||
|
||||
## Confirmed Host Trigger
|
||||
|
||||
The isolated bench trigger is:
|
||||
|
||||
```text
|
||||
00 00 13 40 00 09 ; command 0, selector 0x0013, value 0x4000
|
||||
```
|
||||
|
||||
Command 0 mirrors nonzero selector writes into both `E000[selector]` and
|
||||
`E800[selector]`, then queues the selector for internal processing. For this
|
||||
frame that means:
|
||||
|
||||
```text
|
||||
E000[0x0013] = 0x4000
|
||||
E800[0x0013] = 0x4000
|
||||
```
|
||||
|
||||
The current-table word is `E800 + 2 * 0x0013 = H'E826`.
|
||||
|
||||
## Selector Handler
|
||||
|
||||
The selector dispatch table maps selector `0x0013` to `H'2E06`.
|
||||
|
||||
Focused linear decode:
|
||||
|
||||
```text
|
||||
H'2E06 BTST.W #15, @H'E826
|
||||
set/clear F791.6 and F713.4
|
||||
|
||||
H'2E1E BTST.W #14, @H'E826
|
||||
set/clear F791.5 and F716.7
|
||||
```
|
||||
|
||||
Bench labels:
|
||||
|
||||
| Selector value | ROM latch bits | Visible result |
|
||||
| --- | --- | --- |
|
||||
| `0x8000` | `F791.6`, `F713.4` | far-right `SLAVE` lamp |
|
||||
| `0x4000` | `F791.5`, `F716.7` | `IRIS/M.BLACK LINK` lamp |
|
||||
| `0x0000` | clears both bit groups through `H'2E06` | both latch groups clear |
|
||||
|
||||
## Other Trigger Path
|
||||
|
||||
There is also a local panel-input path:
|
||||
|
||||
```text
|
||||
F006.7 / F6DB.7 -> H'200E -> H'E826 bit14 -> loc_3E54 queues selector 0x0013
|
||||
```
|
||||
|
||||
At `H'200E`, the ROM checks `F6DB.7` and requires `F731 <= 3`. It then uses
|
||||
`F791.5` as a current-state toggle:
|
||||
|
||||
- if `F791.5` is clear, it sets `H'E826.14`,
|
||||
- if `F791.5` is set, it clears `H'E826.14`,
|
||||
- in both cases it calls `loc_3E54` with selector `0x0013`.
|
||||
|
||||
This is not a separate lamp driver. It feeds the same `E800[0x0013].14`
|
||||
state consumed by the selector handler.
|
||||
|
||||
## Practical Meaning
|
||||
|
||||
The strongest current model is:
|
||||
|
||||
- CCU/host can drive the lamp directly by sending selector `0x0013` value
|
||||
`0x4000` through command 0.
|
||||
- The panel can also toggle/report the same state through a local input lane,
|
||||
but only when the relevant session/page gate is open.
|
||||
- No other decoded selector currently appears to directly set the same
|
||||
`F791.5` plus `F716.7` latch pair.
|
||||
|
||||
Generated semantics now label selector `0x0013`, `E800[0x0013]`, and the
|
||||
`IRIS/M.BLACK LINK` / `SLAVE` bit meanings so pseudo-code output does not leave
|
||||
this as a generic table write.
|
||||
193
docs/pt2-iris-mblack-link-state-machine.md
Normal file
193
docs/pt2-iris-mblack-link-state-machine.md
Normal file
@@ -0,0 +1,193 @@
|
||||
# PT2 IRIS/M.BLACK LINK State Machine
|
||||
|
||||
Date: 2026-05-27
|
||||
|
||||
This note records the bench-proven closed loop for the `IRIS/M.BLACK LINK`
|
||||
button/lamp path.
|
||||
|
||||
## Short Answer
|
||||
|
||||
There is no current evidence that the CCU first sends a separate
|
||||
"this function exists" capability command for `IRIS/M.BLACK LINK`.
|
||||
|
||||
The stronger model is:
|
||||
|
||||
1. The CCU/RCP session must be awake/active.
|
||||
2. The CCU must service the RCP report queue.
|
||||
3. The CCU is the authoritative owner of selector state.
|
||||
4. When the RCP reports a local button intent, the CCU ACKs the report and
|
||||
mirrors the resulting selector value back to the RCP.
|
||||
|
||||
For this control, selector `0x0013` bit `0x4000` is the
|
||||
`IRIS/M.BLACK LINK` state.
|
||||
|
||||
## Proven Frames
|
||||
|
||||
Selector value frames:
|
||||
|
||||
```text
|
||||
00 00 13 40 00 09 ; command 0, selector 0x0013, value 0x4000, active
|
||||
00 00 13 00 00 49 ; command 0, selector 0x0013, value 0x0000, clear
|
||||
```
|
||||
|
||||
Report ACK:
|
||||
|
||||
```text
|
||||
05 00 13 00 00 4C ; command 5 ACK/continuation for selector 0x0013
|
||||
```
|
||||
|
||||
Readback request:
|
||||
|
||||
```text
|
||||
01 00 13 00 00 48 ; command 1 read selector 0x0013
|
||||
```
|
||||
|
||||
Observed readback shapes:
|
||||
|
||||
```text
|
||||
04 00 13 40 00 0D ; command-0 write response, selector 0x0013 active
|
||||
04 00 13 00 00 4D ; command-0 write response, selector 0x0013 clear
|
||||
04 13 00 40 00 0D ; command-1 readback response, selector 0x0013 active
|
||||
04 13 00 00 00 4D ; command-1 readback response, selector 0x0013 clear
|
||||
```
|
||||
|
||||
## Successful Closed Loop
|
||||
|
||||
Capture:
|
||||
|
||||
```text
|
||||
captures/iris-mblack-link-mirror-state-machine.txt
|
||||
captures/iris-mblack-link-mirror-state-machine-result.json
|
||||
```
|
||||
|
||||
Scenario:
|
||||
|
||||
```text
|
||||
scenarios/iris-mblack-link-mirror-state-machine.json
|
||||
```
|
||||
|
||||
The visible panel behavior was:
|
||||
|
||||
```text
|
||||
press 1: lamp on
|
||||
press 2: lamp off
|
||||
press 3: lamp on
|
||||
```
|
||||
|
||||
The serial behavior matched that cycle.
|
||||
|
||||
### Baseline Clear
|
||||
|
||||
```text
|
||||
TX 00 00 13 00 00 49
|
||||
RX 04 00 13 00 00 4D
|
||||
```
|
||||
|
||||
### Press 1: Active
|
||||
|
||||
```text
|
||||
RX 00 00 13 40 00 09
|
||||
TX 05 00 13 00 00 4C ; ACK report
|
||||
TX 00 00 13 40 00 09 ; mirror active back
|
||||
RX 04 00 13 40 00 0D
|
||||
TX 01 00 13 00 00 48 ; readback
|
||||
RX 04 13 00 40 00 0D
|
||||
```
|
||||
|
||||
### Press 2: Clear
|
||||
|
||||
```text
|
||||
RX 00 00 13 00 00 49
|
||||
TX 05 00 13 00 00 4C ; ACK report
|
||||
TX 00 00 13 00 00 49 ; mirror clear back
|
||||
RX 04 00 13 00 00 4D
|
||||
TX 01 00 13 00 00 48 ; readback
|
||||
RX 04 13 00 00 00 4D
|
||||
```
|
||||
|
||||
### Press 3: Active Again
|
||||
|
||||
```text
|
||||
RX 00 00 13 40 00 09
|
||||
TX 05 00 13 00 00 4C
|
||||
TX 00 00 13 40 00 09
|
||||
RX 04 00 13 40 00 0D
|
||||
TX 01 00 13 00 00 48
|
||||
RX 04 13 00 40 00 0D
|
||||
```
|
||||
|
||||
## Interpretation
|
||||
|
||||
The RCP does not appear to treat the local button press as final local state.
|
||||
It reports local intent to the CCU.
|
||||
|
||||
The CCU then:
|
||||
|
||||
1. ACKs the selector report with command `5`.
|
||||
2. Applies the chosen state back to the RCP with command `0`.
|
||||
|
||||
The RCP uses the mirrored/current selector state to decide the next toggle
|
||||
direction. This explains the earlier failed/incomplete behavior:
|
||||
|
||||
- Without mirroring `0x0013=0x4000` back, repeated presses could keep reporting
|
||||
active because the RCP still believed the selector was clear.
|
||||
- Once the CCU mirrored active back, the next press reported clear.
|
||||
- Once the CCU mirrored clear back, the next press reported active again.
|
||||
|
||||
## Wakeup Versus Capability
|
||||
|
||||
The successful test also had active session traffic:
|
||||
|
||||
```text
|
||||
00 00 00 80 80 5A ; active selector-zero keepalive/report
|
||||
05 00 00 00 00 5F ; ACK for selector zero
|
||||
```
|
||||
|
||||
That traffic looks like general session/connected behavior, not a
|
||||
per-function enable for `IRIS/M.BLACK LINK`.
|
||||
|
||||
So the current working model is:
|
||||
|
||||
- `CONNECT: OK` / active rhythm opens the report path and keeps the panel from
|
||||
falling back to `CONNECT: NOT ACT`.
|
||||
- Selector `0x0013` state tells the RCP the current value of this specific
|
||||
control/lamp.
|
||||
- There may still be feature-specific gates for other controls, but this test
|
||||
did not require a distinct `IRIS/M.BLACK LINK exists` command.
|
||||
|
||||
## ROM Correlation
|
||||
|
||||
The ROM trace in `docs/pt2-iris-mblack-link-rom-trace.md` matches the bench
|
||||
behavior:
|
||||
|
||||
```text
|
||||
F006.7 / F6DB.7 -> H'200E -> H'E826 bit14 -> loc_3E54 queues selector 0x0013
|
||||
```
|
||||
|
||||
At `H'200E`, the ROM reads `F791.5` as the current `IRIS/M.BLACK LINK` state:
|
||||
|
||||
- if `F791.5` is clear, the local press queues/set reports `0x0013=0x4000`;
|
||||
- if `F791.5` is set, the local press queues/clear reports `0x0013=0x0000`.
|
||||
|
||||
The selector handler for `0x0013` updates `F791.5` from `E800[0x0013].14`.
|
||||
That is why mirroring command-0 selector state back to the RCP completes the
|
||||
toggle loop.
|
||||
|
||||
## Implications
|
||||
|
||||
For a CCU emulator:
|
||||
|
||||
- Maintain an authoritative selector table.
|
||||
- Treat RCP button reports as requested state changes, not just notifications.
|
||||
- ACK each report with command `5`.
|
||||
- Write the accepted selector value back with command `0`.
|
||||
- Keep the selector-zero/session rhythm alive separately.
|
||||
|
||||
For other latched buttons:
|
||||
|
||||
- The same pattern is likely: RCP emits a selector report, then expects the CCU
|
||||
to mirror the accepted state back.
|
||||
- A button that only reports "active" repeatedly may not be broken; it may be
|
||||
waiting for the CCU to update the selector state that controls its next
|
||||
toggle direction.
|
||||
|
||||
175
docs/pt2-knee-rom-trace.md
Normal file
175
docs/pt2-knee-rom-trace.md
Normal file
@@ -0,0 +1,175 @@
|
||||
# PT2 KNEE ROM Trace
|
||||
|
||||
Date: 2026-05-26
|
||||
|
||||
## Short Version
|
||||
|
||||
KNEE is not a simple held selector bit. The ROM has a dedicated local panel-input handler at `loc_1795`, reached when the panel input word at `F104` changes. That handler uses CCU-side selector state as gates, then either shows a short timed KNEE page or reports a KNEE value change on selector `0x00BC`.
|
||||
|
||||
This explains the bench pattern where KNEE AUTO can light or flash and then clear even while serial traffic remains healthy: one ROM path is a timed display/page override, not a maintained lamp value.
|
||||
|
||||
## Input Path
|
||||
|
||||
The local panel path is:
|
||||
|
||||
```text
|
||||
F104 changes -> F692 updated -> F6F0.1 set -> main dispatcher calls loc_1795
|
||||
```
|
||||
|
||||
The important code anchors are:
|
||||
|
||||
```text
|
||||
3B33 MOV:G.W @H'F104, R0
|
||||
3B37 CMP:G.W @H'F692, R0
|
||||
3B3D BSET.B #1, @H'F6F0
|
||||
3B41 MOV:G.W R0, @H'F692
|
||||
|
||||
1630 BCLR.B #1, @H'F6F0
|
||||
1636 JSR @loc_1795
|
||||
```
|
||||
|
||||
So serial writes can prepare the state table, but the main KNEE control branch appears to require the panel-side input lane to change.
|
||||
|
||||
## Handler Decision Table
|
||||
|
||||
`loc_1795` reads two words from the primary selector table:
|
||||
|
||||
| ROM read | Selector meaning |
|
||||
| --- | --- |
|
||||
| `@H'E172` | `E000[0x00B9]` |
|
||||
| `@H'E220` | `E000[0x0110]` |
|
||||
|
||||
The branch is:
|
||||
|
||||
```text
|
||||
1795 if F731 > 2: skip
|
||||
179C if E000[0x00B9].13 == 0: loc_2127()
|
||||
17A7 else if E000[0x0110].15 == 1: loc_2127()
|
||||
17B2 else:
|
||||
delta = F692 - F6B2
|
||||
report/update selector 0x00BC via loc_19A2
|
||||
17C0 F6B2 = F692
|
||||
```
|
||||
|
||||
Practical interpretation:
|
||||
|
||||
| Condition | ROM effect | Current meaning |
|
||||
| --- | --- | --- |
|
||||
| `0x00B9.13 = 0` | timed KNEE page via `loc_2127` | KNEE value reporting not enabled |
|
||||
| `0x00B9.13 = 1`, `0x0110.15 = 1` | timed KNEE page via `loc_2127` | override/inhibit mode |
|
||||
| `0x00B9.13 = 1`, `0x0110.15 = 0` | value delta reported as selector `0x00BC` | likely live KNEE control/report lane |
|
||||
|
||||
This downgrades the earlier bench label that treated `0x00B9.15` as the main KNEE gate. The ROM gate for the panel-input handler is `0x00B9.13`.
|
||||
|
||||
## Timed KNEE Page
|
||||
|
||||
`loc_2127` is the timed page path:
|
||||
|
||||
```text
|
||||
2127 set FB03.7
|
||||
212D save old F732 into F734, if this is a fresh override
|
||||
2135 F732 = 0x1C03
|
||||
213B FB02 = 0x14
|
||||
2140 call loc_48FA
|
||||
```
|
||||
|
||||
The timer path later decrements `FB02`; when it expires, `loc_48EF` restores `F732` from `F734` and redraws. That is the likely cause of "lights, then falls away" observations.
|
||||
|
||||
The LCD dispatcher confirms `F732=0x1C03` is a KNEE page:
|
||||
|
||||
```text
|
||||
493E[0x1C] -> 0x92CC
|
||||
0x92DE[3] -> 0x95CE
|
||||
0x960B prints "KNEE"
|
||||
```
|
||||
|
||||
On that KNEE page, the second line is selected like this:
|
||||
|
||||
```text
|
||||
if E000[0x0110].15: "DL"
|
||||
else if E000[0x00B9].15: "PRESET"
|
||||
else: "AUTO"
|
||||
```
|
||||
|
||||
So `0x00B9.15` still matters, but it appears to choose the KNEE page label (`PRESET` versus `AUTO`) rather than enabling the report path. `0x0110.15` selects the `DL` label and also forces the timed page path from `loc_1795`.
|
||||
|
||||
## Bench Implications
|
||||
|
||||
Useful frames to test this model:
|
||||
|
||||
| Purpose | Frame |
|
||||
| --- | --- |
|
||||
| clear `0x00B9` | `00 01 39 00 00 62` |
|
||||
| set `0x00B9.13` gate | `00 01 39 20 00 42` |
|
||||
| set `0x00B9.15` label bit | `00 01 39 80 00 E2` |
|
||||
| set `0x00B9.15` and `.13` | `00 01 39 A0 00 C2` |
|
||||
| clear `0x0110` | `00 01 90 00 00 CB` |
|
||||
| set `0x0110.15` override | `00 01 90 80 00 4B` |
|
||||
| read `0x00BC` | `01 01 3C 00 00 66` |
|
||||
|
||||
The most direct live-control test is:
|
||||
|
||||
1. Reach `CONNECT: OK`.
|
||||
2. Send `00 01 39 20 00 42` to set `0x00B9.13`.
|
||||
3. Send `00 01 90 00 00 CB` to clear `0x0110.15`.
|
||||
4. Move or exercise the physical KNEE-related control, if available.
|
||||
5. Watch for TX/report traffic around selector `0x00BC`.
|
||||
|
||||
If no physical KNEE input is moved, the ROM may not enter `loc_1795`, because the trigger is the `F104` panel input change path rather than the serial write itself.
|
||||
|
||||
## Bench Observation: DTL / KNEE
|
||||
|
||||
The first `knee-rom-gate-and-value-probe` bench run produced a new LCD state with `DTL` on the left and `KNEE` on the right. That is an important confirmation: page `0x1C` contains both a KNEE entry and a DETAIL entry.
|
||||
|
||||
Relevant ROM text and page entries:
|
||||
|
||||
```text
|
||||
0x92DE[3] -> 0x95CE KNEE page entry
|
||||
0x92DE[7] -> 0x97C8 DETAIL page entry
|
||||
0x960B prints "KNEE"
|
||||
0x9805 prints "DETAIL"
|
||||
```
|
||||
|
||||
The bench display probably shows the page-0x1C menu neighborhood, with DETAIL abbreviated as `DTL` and KNEE as the selected/right-side item. The log does not encode LCD pixels, but the serial timing around the observation is consistent with the KNEE probe:
|
||||
|
||||
```text
|
||||
00 01 39 20 00 42 ; set 0x00B9.13 gate
|
||||
00 01 39 A0 00 C2 ; set 0x00B9.15 + 0x00B9.13
|
||||
00 01 90 80 00 4B ; set 0x0110.15 timed KNEE/DL override
|
||||
```
|
||||
|
||||
Next isolation target: determine whether `DTL/KNEE` appears from `0x00B9.13`, `0x00B9.A0`, `0x0110.15`, or only the combined sequence.
|
||||
|
||||
## Panel Correlation
|
||||
|
||||
The physical panel has both DETAIL and KNEE buttons near the LCD. That matches the ROM page-`0x1C` neighborhood and makes the observed `DTL/KNEE` state likely to be a local menu/button context rather than a generic lamp status.
|
||||
|
||||
Practical implication: once the CCU-side selector gates are prepared, pressing the physical DETAIL/KNEE buttons may be the missing `F104` panel-input transition that calls `loc_1795`. If so, the useful evidence should be:
|
||||
|
||||
- visible LCD movement between DETAIL and KNEE entries,
|
||||
- possible KNEE timed page redraws,
|
||||
- TX/report traffic for selector `0x00BC` when KNEE input movement is accepted,
|
||||
- or other page-`0x1C` selector reports from neighboring DETAIL/KNEE controls.
|
||||
|
||||
## Follow-Up: Lamp Without LCD Movement
|
||||
|
||||
The follow-up run after discovering the DETAIL/KNEE buttons did not reproduce an LCD page change. The observed result was:
|
||||
|
||||
- only the later KNEE cases/windows illuminated the KNEE AUTO lamp,
|
||||
- none of those cases changed the LCD.
|
||||
|
||||
Current interpretation:
|
||||
|
||||
- `0x0110.15` is still the strongest KNEE AUTO lamp/status source.
|
||||
- Serial table writes can light KNEE AUTO without necessarily entering the LCD DETAIL/KNEE page.
|
||||
- The LCD path probably needs an additional local-display/menu condition, not just the CCU-side selector bits.
|
||||
- The physical DETAIL/KNEE buttons may be scanned by the local panel path, but in this test they did not create a visible LCD transition or new serial report evidence.
|
||||
|
||||
This separates two related but distinct paths:
|
||||
|
||||
```text
|
||||
KNEE AUTO lamp/status: mostly selector/table driven, strongest source 0x0110.15
|
||||
DETAIL/KNEE LCD page: local page/menu context, likely page 0x1C plus panel/menu state
|
||||
```
|
||||
|
||||
Next ROM target: trace the DETAIL and KNEE button scan bits through the page-`0x1C` menu dispatcher, not just the `loc_1795` KNEE value handler.
|
||||
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`
|
||||
241
docs/pt2-lamp-selector-map.md
Normal file
241
docs/pt2-lamp-selector-map.md
Normal file
@@ -0,0 +1,241 @@
|
||||
# PT2 Lamp And Panel Output Selector Map
|
||||
|
||||
This note tracks bench-visible lamp/readout effects from CCU-to-RCP selector writes.
|
||||
|
||||
## Current Model
|
||||
|
||||
The panel lamps and seven-segment displays are driven by selector-table state, not by one monolithic "connected" flag. Command 0 writes into the primary/current tables, and several selectors immediately affect visible panel outputs while `CONNECT: OK` is alive.
|
||||
|
||||
Known active-state foundation:
|
||||
|
||||
- `E000[0x0000] = 0x8080` wakes/holds `CONNECT: OK`.
|
||||
- `E000[0x008F]` drives shutter `EVS`/`OFF` style display state and iris AUTO side effects.
|
||||
- `E000[0x0093]` drives at least white-balance and black/flare lamp state.
|
||||
|
||||
## Bench Observations 2026-05-26
|
||||
|
||||
### `lamp-0093-lowbyte-sweep`
|
||||
|
||||
Result: no new visible behavior beyond the already-known `0x0093` family.
|
||||
|
||||
Interpretation:
|
||||
|
||||
- The earlier `0x0093` mapping still stands.
|
||||
- Individual low-byte probes inside a streamed `0x90xx` context did not reveal a new lamp in this run.
|
||||
- Keep `0x9020` as a useful manual/baseline context and `0x90FF` / `0xFFFF` as black/flare AUTO positive controls.
|
||||
|
||||
### `lamp-known-button-selector-probe`
|
||||
|
||||
Visible result:
|
||||
|
||||
- CAM button/lamp flashed on/off.
|
||||
- CALL lamp flashed on/off.
|
||||
- BARS and MASTER lamps flashed on/off.
|
||||
- Camera tally changed red, then later green.
|
||||
- Each visible output illuminated by itself, not as a broad all-lamps blast.
|
||||
|
||||
Serial result:
|
||||
|
||||
- The run stayed in normal `CONNECT: OK` response cadence.
|
||||
- Each command-0 write produced an immediate `04 ...` readback-style frame and repeated `02 00 02 00 00 5A` active responses.
|
||||
|
||||
Candidate mapping:
|
||||
|
||||
| Selector/value pair | Current meaning |
|
||||
| --- | --- |
|
||||
| `0x0007 = 0x8000/0x0000` | CAM POWER lamp blink confirmed by isolated run |
|
||||
| `0x0015 = 0x8000/0x0000` | CALL lamp blink confirmed; red tally also blinked in the same phase |
|
||||
| `0x0012`, `0x0013`, `0x0016`, `0x0017`, `0x0018`, `0x001A` | ordered candidates for SLAVE, green tally, BARS, MASTER, and neighboring lamp states |
|
||||
|
||||
Follow-up `lamp-isolate-cam-call` result:
|
||||
|
||||
- First phase blinked CAM POWER.
|
||||
- Second phase blinked CALL and red tally.
|
||||
|
||||
Follow-up `lamp-isolate-known-neighbors` result:
|
||||
|
||||
- Visible order was SLAVE, then green tally, then BARS.
|
||||
- The pattern repeated, and at one point SLAVE and BARS were visible together.
|
||||
- Treat the ordered mapping as likely but not final until a fresh-boot single-selector run separates latch/persistence effects from the selector under test.
|
||||
|
||||
Follow-up `lamp-isolate-neighbor-single-boot` result:
|
||||
|
||||
| Fresh-boot candidate | Visible result |
|
||||
| --- | --- |
|
||||
| `0x0012 = 0x8000/0x0000` | no visible change reported |
|
||||
| `0x0013 = 0x8000/0x0000` | SLAVE lamp |
|
||||
| `0x0016 = 0x8000/0x0000` | camera tally green |
|
||||
| `0x0017 = 0x8000/0x0000` | BARS lamp |
|
||||
| `0x0018 = 0x8000/0x0000` | no visible result reported yet |
|
||||
| `0x001A = 0x8000/0x0000` | no visible result reported yet |
|
||||
|
||||
This confirms that the host/CCU can directly drive panel lamps through selector-table writes. It also validates using the ROM dispatch-neighbor list around `0x0007` and `0x0015` as a high-value lamp map.
|
||||
|
||||
Follow-up `panel-atlas-standard-master-*` webcam runs:
|
||||
|
||||
- `0x0012`, `0x0013`, and `0x0014` high-nibble/selected-bit sweeps did not
|
||||
produce a clean STANDARD or MASTER lamp trigger. The `0x0013=0x8000` SLAVE
|
||||
positive control still worked.
|
||||
- `0x0010`, `0x0011`, `0x0015`, `0x0016`, `0x0017`, `0x0018`, `0x0019`, and
|
||||
`0x001A` high-nibble sweeps did not produce a clean STANDARD or MASTER lamp
|
||||
trigger.
|
||||
- `0x0008` through `0x000F` high-nibble sweeps did not produce a clean
|
||||
STANDARD or MASTER lamp trigger.
|
||||
- `0x0017=0x4000` lit the same far-right bottom BARS lamp/latch as the known
|
||||
`0x0017=0x8000` family. Later `0x0018` rows in that run were latch-contaminated
|
||||
and need fresh-boot isolation before assigning a separate meaning.
|
||||
|
||||
Current implication: STANDARD and MASTER are probably not simple direct
|
||||
command-0 high-nibble writes in the `0x0008`-`0x001A` pocket, despite the older
|
||||
broad run that made MASTER flash. Treat that older observation as a real
|
||||
bench-visible event but not yet an isolated selector mapping.
|
||||
|
||||
Later refinement: the ROM-derived fresh-boot output sweep found a clean
|
||||
STANDARD trigger at `0x006B = 0x8000` (`00 00 6B 80 00 B1`). It also reclassed
|
||||
the formerly vague `0x001A` pocket as the MONITOR selector cluster:
|
||||
|
||||
| Selector/value | Visible effect |
|
||||
| --- | --- |
|
||||
| `0x001A = 0x0808` | MONITOR ENC |
|
||||
| `0x001A = 0x2020` | MONITOR B |
|
||||
| `0x001A = 0x4040` | MONITOR G |
|
||||
| `0x001A = 0x8080` | MONITOR R |
|
||||
| `0x006B = 0x8000` | STANDARD |
|
||||
|
||||
### `panel-atlas-big-visual-sweep-0001-017f-highbits`
|
||||
|
||||
The broad webcam sweep and fresh-boot isolation pass produced these confirmed
|
||||
or near-confirmed panel-output mappings:
|
||||
|
||||
| Selector/value | Current meaning |
|
||||
| --- | --- |
|
||||
| `0x0013 = 0x4000` | `IRIS/M.BLACK LINK` lamp |
|
||||
| `0x0024 = 0x8000` | LCD selector-button lamp |
|
||||
| `0x0024 = 0x0000` | LCD selector-button lamp remained visible at 0.5 s; not a simple clear in this timing window |
|
||||
| `0x0082 = 0x8000` | IRIS readout `OP` |
|
||||
| `0x0082 = 0x4000` | IRIS readout `1.4` |
|
||||
| `0x0082 = 0x0000` | IRIS readout blank |
|
||||
| `0x0083 = 0x8000` | MASTER GAIN `-3`, SHUTTER `OFF`, and IRIS AUTO |
|
||||
| `0x0083 = 0x0000` | same visible state remained at 0.5 s; likely latched/copied elsewhere |
|
||||
| `0x0093 = 0x8000` | BLACK/FLARE MANUAL plus white-balance PRESET |
|
||||
| `0x0093 = 0x4000` | BLACK/FLARE MANUAL plus white-balance AUTO |
|
||||
| `0x0093 = 0x2000` | BLACK/FLARE MANUAL plus white-balance MANUAL |
|
||||
| `0x0093 = 0x0000` | BLACK/FLARE MANUAL plus white-balance MANUAL |
|
||||
|
||||
Run health was good: no resync events, no dropped bytes, and command-4
|
||||
readbacks appeared for the listed writes.
|
||||
|
||||
ROM trace now confirms the `0x0013` bit split:
|
||||
|
||||
- `E800[0x0013]` is `H'E826`.
|
||||
- Selector `0x0013` dispatches to `H'2E06`.
|
||||
- `H'E826.15` sets/clears `F791.6` and `F713.4`, matching SLAVE.
|
||||
- `H'E826.14` sets/clears `F791.5` and `F716.7`, matching
|
||||
`IRIS/M.BLACK LINK`.
|
||||
- Local handler `H'200E` can also toggle `H'E826.14` from panel input
|
||||
`F006.7/F6DB.7` when its session gate allows it.
|
||||
|
||||
Interpretation:
|
||||
|
||||
- `0x0082` is the cleanest direct readout lane found so far: set values update
|
||||
the IRIS display and `0x0000` blanks it.
|
||||
- `0x0083` appears to be a combined status/display lane rather than only the
|
||||
MASTER GAIN display. Its `0x8000` state also brings up SHUTTER `OFF` and IRIS
|
||||
AUTO, and the clear write did not visually clear it at 0.5 s.
|
||||
- `0x0093` selects white-balance mode. In this run, `0x2000` and `0x0000` both
|
||||
presented white-balance MANUAL, so bit 13 may be redundant in this context or
|
||||
may need another gate to show a distinct state.
|
||||
|
||||
### `lamp-broad-status-selector-sweep`
|
||||
|
||||
Visible result:
|
||||
|
||||
- KNEE AUTO lamp flashed a few times.
|
||||
- No other new visible result was reported.
|
||||
- Follow-up isolation saw KNEE AUTO toward the end of the run, then blinking.
|
||||
|
||||
Candidate selectors in that run:
|
||||
|
||||
`0x0003`, `0x0040`, `0x0081`, `0x0092`, `0x00A7`, `0x00B7`, `0x00B9`, `0x0110`
|
||||
|
||||
Interpretation:
|
||||
|
||||
- KNEE AUTO is likely in this broader status cluster.
|
||||
- Because the visible change happened toward the end, strongest next candidates are `0x00A7`, `0x00B7`, `0x00B9`, and `0x0110`, with `0x0092` kept as a guard candidate.
|
||||
- Exact selector/value still needs isolation because the broad sweep changed several selectors in sequence.
|
||||
|
||||
Follow-up `lamp-isolate-knee-tail-single-boot` result:
|
||||
|
||||
| Fresh-boot candidate | Visible result |
|
||||
| --- | --- |
|
||||
| `0x0092` | iris AUTO/OFF behavior |
|
||||
| `0x00A7` | no visible result reported |
|
||||
| `0x00B7` | no visible result reported |
|
||||
| `0x00B9` | KNEE AUTO |
|
||||
| `0x0110` | KNEE AUTO |
|
||||
|
||||
Interpretation:
|
||||
|
||||
- `0x00B9` and `0x0110` are real KNEE-related selectors, but a ROM trace now shows they are not a simple OR-held lamp pair.
|
||||
- `loc_1795` is the local KNEE/panel-input handler. It is reached from `F104 -> F692 -> F6F0.1`, then reads `E000[0x00B9]` and `E000[0x0110]`.
|
||||
- The ROM gate for the live KNEE value/report branch is `0x00B9.13`, not `0x00B9.15`.
|
||||
- `0x0110.15` forces a timed KNEE page/display override. That fits the observed "lights, then clears" behavior.
|
||||
- `0x00B9.15` still matters on the timed KNEE LCD page: it selects the `PRESET` label when `0x0110.15` is clear. With both clear, the same page labels KNEE as `AUTO`.
|
||||
- When `0x00B9.13` is set and `0x0110.15` is clear, the ROM computes `F692 - F6B2` and reports/updates selector `0x00BC`. That is now the strongest candidate for the KNEE control value lane.
|
||||
|
||||
Follow-up `lamp-knee-or-precedence` result:
|
||||
|
||||
- Case 1 (`0x00B9.15` set, then `0x0110.15` set, then `0x00B9` cleared) kept KNEE AUTO on until near the end, when `0x0110` was cleared.
|
||||
- Case 2 (`0x0110.15` set, then `0x00B9.15` set, then `0x0110` cleared) turned KNEE AUTO off well before the end, even though `0x00B9` had been set.
|
||||
- This argues against a simple OR model. Current best interpretation: `0x0110.15` is the stronger live display/control source for KNEE AUTO; `0x00B9.15` is related, but may be a transient, secondary status source, or only meaningful with another gate active.
|
||||
|
||||
Follow-up `lamp-knee-sustain-compare` result:
|
||||
|
||||
- Repeated `0x00B9.15` refresh never lit KNEE AUTO.
|
||||
- Repeated `0x0110.15` refresh lit KNEE AUTO, but it turned off again around the middle of the repeated-refresh window.
|
||||
- This makes `0x00B9.15` look like a context-sensitive or stale interpretation rather than a maintained lamp source.
|
||||
- `0x0110.15` remains the best KNEE AUTO source, but it is not sufficient by itself to hold the lamp. It likely needs a surrounding CCU status refresh, or another selector periodically clears/rebuilds the visible lamp bank.
|
||||
|
||||
Follow-up `lamp-knee-context-hold` result:
|
||||
|
||||
- Pairing `0x00B9.15` with the known `0x0093=0x9020` active refresh did not light KNEE AUTO.
|
||||
- Pairing `0x0110.15` with `0x0093=0x9020` did light KNEE AUTO, but it still turned off around the middle of the run.
|
||||
- The serial log stayed clean: repeated table readbacks and `02 00 02 00 00 5A` active responses continued, with no resync or NOT ACT-style serial collapse.
|
||||
- Current best hypothesis: `0x0110.15` behaves more like an edge/pulse or consumed display request than a pure level-held lamp bit. Repeating the same high value may not retrigger it after the display task has consumed the state.
|
||||
|
||||
ROM follow-up:
|
||||
|
||||
- Detailed notes: `docs/pt2-knee-rom-trace.md`.
|
||||
- The timed path sets `F732=0x1C03`, `FB02=0x14`, calls `loc_48FA`, and later restores the previous page through `loc_48EF`.
|
||||
- `F732=0x1C03` dispatches to a KNEE LCD page. Its second line is `DL` when `0x0110.15` is set, `PRESET` when `0x0110.15` is clear and `0x00B9.15` is set, otherwise `AUTO`.
|
||||
- `knee-rom-gate-and-value-probe` produced a new bench LCD state with `DTL` on the left and `KNEE` on the right. This matches the ROM page-0x1C neighborhood: KNEE entry at `0x95CE`, DETAIL entry at `0x97C8`.
|
||||
- The panel physically has DETAIL and KNEE buttons near the LCD, so this is likely a local menu/button context. Pressing those buttons during the prepared gate window may supply the `F104` transition that the ROM needs before it calls `loc_1795`.
|
||||
- Follow-up isolation lit KNEE AUTO in the later KNEE cases/windows but did not change the LCD. Treat the KNEE AUTO lamp and the DETAIL/KNEE LCD page as related but separate paths: `0x0110.15` remains the strongest lamp/status source, while LCD movement likely needs an additional local menu/display gate.
|
||||
- Next bench retest should include `0x00B9.13` (`00 01 39 20 00 42`) and the `0x00BC` report/read lane, not only the older `0x00B9.15` / `0x0110.15` pair.
|
||||
|
||||
## Follow-Up Isolation Scenarios
|
||||
|
||||
Run these with the console visible and record the exact label shown when each lamp changes:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\lamp-isolate-cam-call.json --parity E --log captures\lamp-isolate-cam-call.txt --result-json captures\lamp-isolate-cam-call-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\lamp-isolate-known-neighbors.json --parity E --log captures\lamp-isolate-known-neighbors.txt --result-json captures\lamp-isolate-known-neighbors-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\lamp-isolate-knee-status-selectors.json --parity E --log captures\lamp-isolate-knee-status-selectors.txt --result-json captures\lamp-isolate-knee-status-selectors-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\lamp-isolate-neighbor-single-boot.json --parity E --log captures\lamp-isolate-neighbor-single-boot.txt --result-json captures\lamp-isolate-neighbor-single-boot-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\lamp-isolate-knee-tail-single-boot.json --parity E --log captures\lamp-isolate-knee-tail-single-boot.txt --result-json captures\lamp-isolate-knee-tail-single-boot-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\lamp-isolate-knee-bit-scan.json --parity E --log captures\lamp-isolate-knee-bit-scan.txt --result-json captures\lamp-isolate-knee-bit-scan-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\lamp-knee-or-precedence.json --parity E --log captures\lamp-knee-or-precedence.txt --result-json captures\lamp-knee-or-precedence-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\lamp-knee-sustain-compare.json --parity E --log captures\lamp-knee-sustain-compare.txt --result-json captures\lamp-knee-sustain-compare-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\lamp-knee-context-hold.json --parity E --log captures\lamp-knee-context-hold.txt --result-json captures\lamp-knee-context-hold-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\lamp-knee-edge-refresh.json --parity E --log captures\lamp-knee-edge-refresh.txt --result-json captures\lamp-knee-edge-refresh-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\knee-rom-gate-and-value-probe.json --parity E --log captures\knee-rom-gate-and-value-probe.txt --result-json captures\knee-rom-gate-and-value-probe-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\knee-rom-dtl-knee-isolation.json --parity E --log captures\knee-rom-dtl-knee-isolation.txt --result-json captures\knee-rom-dtl-knee-isolation-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\knee-detail-physical-button-watch.json --parity E --log captures\knee-detail-physical-button-watch.txt --result-json captures\knee-detail-physical-button-watch-result.json
|
||||
```
|
||||
|
||||
Method notes:
|
||||
|
||||
- Record visible changes immediately during each labeled hold. Later `CONNECT: NOT ACT` cleanup is not selector evidence.
|
||||
- If a selector causes a latch or unexpected mode, stop and keep the log instead of continuing the whole sweep.
|
||||
- Prefer exact notes like `selector_0018_high -> tally red`, because the logs already preserve send timestamps and readback frames.
|
||||
- For the single-boot follow-ups, each candidate gets a fresh power cycle. That is deliberate: it tests whether a lamp is truly driven by that selector rather than retained from a previous write.
|
||||
276
docs/pt2-menu-state-machine.md
Normal file
276
docs/pt2-menu-state-machine.md
Normal file
@@ -0,0 +1,276 @@
|
||||
# PT2 Menu State Machine
|
||||
|
||||
This is a focused reference for the ROM menu/display selection machinery that drives LCD pages and panel soft-key activity.
|
||||
|
||||
## Page Dispatch
|
||||
|
||||
Primary display selector:
|
||||
|
||||
- `F732` holds the current display/page selector.
|
||||
- The high byte of `F732` selects a page wrapper through `493E`.
|
||||
- The low byte is used as a page-local substate/selection, commonly through `F733`.
|
||||
|
||||
Important dispatcher:
|
||||
|
||||
- `48FA` bridges table/report state into LCD page dispatch.
|
||||
- `493E[page]` points at a wrapper.
|
||||
- Wrappers pass a local table pointer to `5FD2`.
|
||||
|
||||
For COPY status:
|
||||
|
||||
- `F732=H'1903` selects page `0x19`, substate `0x03`, `COPY IN PROGRESS`.
|
||||
- `F732=H'1904` selects page `0x19`, substate `0x04`, `COPY COMPLETED`.
|
||||
|
||||
For OTHERS:
|
||||
|
||||
- `493E[0x01] -> H'631C`.
|
||||
- Local table `H'632E` includes the OTHERS pages.
|
||||
|
||||
## Local Entry Selection
|
||||
|
||||
`loc_5FD2` is the local menu chooser.
|
||||
|
||||
Important RAM:
|
||||
|
||||
| RAM | Role |
|
||||
| --- | --- |
|
||||
| `F72C` | visible/selectable entry bitmask |
|
||||
| `F72E` | count of visible/selectable entries |
|
||||
| `F72F` | cached page high byte |
|
||||
| `F733` | selected local entry index |
|
||||
| `FB03.7` | no-entry/error/display suppression flag |
|
||||
| `FB02` | display/session timer or message timer |
|
||||
|
||||
Observed algorithm shape:
|
||||
|
||||
1. If the page changed, clear `F72C/F72E` and cache the new page in `F72F`.
|
||||
2. Walk the page-local handler table from the last entry down.
|
||||
3. For each handler, read descriptor words immediately before the handler.
|
||||
4. Compare the entry state descriptor against `F731`.
|
||||
5. If the entry has required selector descriptors, test `E400 + selector*2`.
|
||||
6. If requirements pass, set the entry bit in `F72C` and increment `F72E`.
|
||||
7. Clamp or reset `F733` so it points at a visible entry.
|
||||
8. If no entries are visible, set `FB03.7`, set `FB02=H'14`, clear `F72F`, and return `R4=H'FFFE`.
|
||||
|
||||
Practical meaning:
|
||||
|
||||
- A page can exist in ROM but be invisible/inactive until the CCU seeds the right `E400` feature/status selector.
|
||||
- Command 6 writes the `E400-E7FF` secondary table, but only on the continuation side of the protocol.
|
||||
|
||||
## OTHERS / COPY TO SLAVES Gates
|
||||
|
||||
OTHERS page map:
|
||||
|
||||
| Local entry | Handler | Visible text | Required secondary selector |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | `H'6FF0` | `OTHERS` / `COPY TO SLAVES` | `E400[0x0015] != 0` |
|
||||
| 2 | `H'70F6` | `OTHERS` / `CAM ID SET` | `E400[0x0043] != 0` |
|
||||
| 3 | `H'7188` | `OTHERS` / `CAM ID IND` | `E400[0x0037] != 0` |
|
||||
| 4 | `H'7258` | `OTHERS` / `CAM BARS` | `E400[0x0038] != 0` |
|
||||
| 5-6 | `H'7328/H'73D8` | marker/percentage pages | `E400[0x0027] != 0` |
|
||||
|
||||
COPY TO SLAVES local action gate:
|
||||
|
||||
- Handler `H'6FF0` watches `F770.2`.
|
||||
- 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`.
|
||||
|
||||
Root OTHERS soft-key bits:
|
||||
|
||||
- Root handler `H'6EE4` tests `E000[0x008F]` at `H'E11E`.
|
||||
- Bit 11 sets `F711.6`.
|
||||
- Bit 12 sets `F711.4`.
|
||||
|
||||
These bits are not only OTHERS soft-key enables. Bench tests show `E000[0x008F]` directly changes the shutter seven-segment display and iris AUTO lamp, so treat it as a packed camera/display status selector that also feeds the OTHERS root handler.
|
||||
|
||||
## Button / Lamp Masks
|
||||
|
||||
Important RAM:
|
||||
|
||||
| RAM | Role |
|
||||
| --- | --- |
|
||||
| `F711-F718` | panel output masks used by external panel chips |
|
||||
| `F711.4-F711.7` | soft-key/menu-related bits seen around OTHERS/COPY |
|
||||
| `F726` | countdown that temporarily preserves some soft-key bits |
|
||||
| `F770` | local panel action/change code |
|
||||
|
||||
Relevant ROM behavior:
|
||||
|
||||
- Init clears `F711-F717` and sets `F718=H'FF`.
|
||||
- `5A7A` clears `F711.4-F711.7` if `F726 == 0`.
|
||||
- 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:
|
||||
|
||||
1. Recover to a live `CONNECT: OK` style session.
|
||||
2. Seed root OTHERS soft-key bits:
|
||||
|
||||
```text
|
||||
00 01 0F 18 00 4C ; E000[0x008F] bits 11+12
|
||||
```
|
||||
|
||||
3. During a live continuation/report window, seed the COPY page visibility bit:
|
||||
|
||||
```text
|
||||
06 00 15 00 01 48 ; E400[0x0015] nonzero
|
||||
```
|
||||
|
||||
4. Still satisfy the `F791.7` local copy-start gate.
|
||||
|
||||
The current hardest unknown is step 4: the ROM uses `F791.7` in several places, but the source that sets it has not yet been identified.
|
||||
|
||||
## Bench Observation: OTHERS Gate Probe
|
||||
|
||||
Run:
|
||||
|
||||
```text
|
||||
00 00 00 80 00 DA ; recover/seed CONNECT OK
|
||||
00 01 0F 18 00 4C ; E000[0x008F] = 0x1800
|
||||
06 00 15 00 01 48 ; E400[0x0015] = 0x0001, sent in active window
|
||||
```
|
||||
|
||||
Observed on the real panel without touching the controls:
|
||||
|
||||
- LCD stayed at `CONNECT: OK`.
|
||||
- SHUTTER seven-segment display changed to something like `EUS`; manuals make this likely `EVS` rendered on a seven-segment display.
|
||||
- Iris AUTO lamp illuminated.
|
||||
- OTHERS menu did not appear by itself.
|
||||
|
||||
Interpretation:
|
||||
|
||||
- The sequence reached real UI state, not only serial parser state.
|
||||
- `E000[0x008F]=0x1800` is now a candidate shutter/mode-status value as well as an OTHERS soft-key source. Treat the earlier "soft-key bits" interpretation as incomplete.
|
||||
- `E400[0x0015]=0x0001` may be the OTHERS/COPY visibility bit, but it may also affect an iris/auto feature path. Isolate before assigning a final meaning.
|
||||
|
||||
Recommended isolation probes:
|
||||
|
||||
```text
|
||||
00 01 0F 08 00 5C ; E000[0x008F] bit 11 only
|
||||
00 01 0F 10 00 44 ; E000[0x008F] bit 12 only
|
||||
00 01 0F 18 00 4C ; E000[0x008F] bits 11+12
|
||||
06 00 15 00 00 49 ; E400[0x0015] clear/zero
|
||||
06 00 15 00 01 48 ; E400[0x0015] low nonzero
|
||||
06 00 15 80 00 C9 ; E400[0x0015] high nonzero
|
||||
```
|
||||
|
||||
Scenario files:
|
||||
|
||||
- `scenarios/others-isolate-008f-bit11.json`
|
||||
- `scenarios/others-isolate-008f-bit12.json`
|
||||
- `scenarios/others-isolate-008f-bits11-12.json`
|
||||
- `scenarios/others-isolate-e400-0015-low.json`
|
||||
- `scenarios/others-isolate-e400-0015-high.json`
|
||||
- `scenarios/others-isolate-008f-then-e400-clear.json`
|
||||
|
||||
Isolation results:
|
||||
|
||||
| Scenario | Visible panel result | Serial result |
|
||||
| --- | --- | --- |
|
||||
| `others-isolate-008f-bit11` | Iris AUTO lamp on, SHUTTER seven-segment shows observed `EUS`, likely manual `EVS` | `04 01 0F 08 00 58`, then repeated `02 00 02 00 00 5A` |
|
||||
| `others-isolate-008f-bit12` | Iris AUTO lamp on, SHUTTER seven-segment shows literal letters `OFF` | `04 01 0F 10 00 40`, then repeated `02 00 02 00 00 5A` |
|
||||
| `others-isolate-008f-bits11-12` | Iris AUTO lamp on, SHUTTER seven-segment shows observed `EUS`, likely manual `EVS` | `04 01 0F 18 00 48`, then repeated `02 00 02 00 00 5A` |
|
||||
| `others-isolate-e400-0015-low` | LCD stays `CONNECT: OK` only | repeated `01 00 02 00 00 59` after command 6 |
|
||||
| `others-isolate-e400-0015-high` | LCD stays `CONNECT: OK` only | repeated `01 00 02 00 00 59` after command 6 |
|
||||
| `others-isolate-008f-then-e400-clear` | Iris AUTO lamp on, SHUTTER seven-segment shows observed `EUS`, likely manual `EVS` | repeated `01 00 02 00 00 59` after command 6 |
|
||||
|
||||
Updated interpretation:
|
||||
|
||||
- `E000[0x008F]` directly affects visible shutter/iris UI state.
|
||||
- Bit 11 selects the observed `EUS` shutter display, probably manual `EVS`; bit 12 selects literal shutter-display text `OFF`; when both are present, the likely `EVS` display appears to win.
|
||||
- The iris AUTO lamp turns on for either bit 11 or bit 12, so it may be tied to the same status selector or to the resulting display mode.
|
||||
- `E400[0x0015]` does not visibly change the panel by itself, even though command 6 does alter the report stream from `02 00 02 00 00 5A` to `01 00 02 00 00 59`.
|
||||
- Keep `E400[0x0015]` as a probable OTHERS/COPY visibility/report-gate candidate, but do not assign the shutter/iris effect to it.
|
||||
|
||||
Manual correlation:
|
||||
|
||||
- The RCP-TX7 operating instructions list `OTHERS (1/6: SHUTTER)` with an `EVS` button, and say to use the shutter block `C.SCAN` or `SHUTTER ON/OFF` buttons when not using EVS.
|
||||
- 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.
|
||||
338
docs/pt2-panel-atlas.md
Normal file
338
docs/pt2-panel-atlas.md
Normal file
@@ -0,0 +1,338 @@
|
||||
# PT2 Panel Atlas
|
||||
|
||||
This note tracks bench tests that intentionally drive visible panel outputs from
|
||||
PT2/command-0 table writes.
|
||||
|
||||
## Scenario Files
|
||||
|
||||
Current compact atlas scenarios:
|
||||
|
||||
```text
|
||||
scenarios/panel-atlas-operator-lamps-v1.json
|
||||
scenarios/panel-atlas-readout-status-v1.json
|
||||
scenarios/panel-atlas-right-stack-isolation-v1.json
|
||||
scenarios/panel-atlas-right-stack-fresh-latch-v1.json
|
||||
scenarios/panel-atlas-standard-master-bit-sweep-v1.json
|
||||
scenarios/panel-atlas-standard-master-neighbor-sweep-v2.json
|
||||
scenarios/panel-atlas-standard-master-lower-neighbor-sweep-v3.json
|
||||
```
|
||||
|
||||
Both are designed for webcam capture with the calibrated bench settings:
|
||||
|
||||
```text
|
||||
--parity E --camera-index 4 --snapshot-delays 0.5
|
||||
```
|
||||
|
||||
## Run: 2026-05-27
|
||||
|
||||
Logs:
|
||||
|
||||
```text
|
||||
captures/panel-atlas-operator-lamps-v1-webcam.txt
|
||||
captures/panel-atlas-readout-status-v1-webcam.txt
|
||||
captures/panel-atlas-right-stack-isolation-v1-webcam.txt
|
||||
captures/panel-atlas-right-stack-fresh-latch-v1-webcam.txt
|
||||
captures/panel-atlas-standard-master-bit-sweep-v1-webcam.txt
|
||||
captures/panel-atlas-standard-master-neighbor-sweep-v2-webcam.txt
|
||||
captures/panel-atlas-standard-master-lower-neighbor-sweep-v3-webcam.txt
|
||||
```
|
||||
|
||||
Snapshots:
|
||||
|
||||
```text
|
||||
captures/panel-atlas-operator-lamps-v1-webcam-shots/
|
||||
captures/panel-atlas-readout-status-v1-webcam-shots/
|
||||
captures/panel-atlas-right-stack-isolation-v1-webcam-shots/
|
||||
captures/panel-atlas-right-stack-fresh-latch-v1-webcam-shots/
|
||||
captures/panel-atlas-standard-master-bit-sweep-v1-webcam-shots/
|
||||
captures/panel-atlas-standard-master-neighbor-sweep-v2-webcam-shots/
|
||||
captures/panel-atlas-standard-master-lower-neighbor-sweep-v3-webcam-shots/
|
||||
```
|
||||
|
||||
Serial health:
|
||||
|
||||
| Run | RX frames | TX frames | Resync | Dropped bytes |
|
||||
| --- | ---: | ---: | ---: | ---: |
|
||||
| operator lamps | 82 | 19 | 0 | 0 |
|
||||
| readout/status | 76 | 16 | 0 | 0 |
|
||||
| right-stack isolation | 115 | 26 | 0 | 0 |
|
||||
| right-stack fresh latch | 20 | 12 | 0 | 0 |
|
||||
| standard/master bit sweep v1 | 144 | 34 | 0 | 0 |
|
||||
| standard/master neighbor sweep v2 | 188 | 47 | 0 | 0 |
|
||||
| standard/master lower-neighbor sweep v3 | 188 | 47 | 0 | 0 |
|
||||
|
||||
The compact and isolation runs stayed in the expected table-readback plus
|
||||
`02 00 02 00 00 5A` CONNECT-OK response rhythm.
|
||||
|
||||
The fresh-latch run ended with one trailing unframed byte after the final send.
|
||||
There were no resync events or dropped bytes; this is consistent with the run
|
||||
ending while the next response frame was just beginning.
|
||||
|
||||
## Confirmed Visible Effects
|
||||
|
||||
## Far-Right Stack Reference
|
||||
|
||||
The physical far-right stack, top to bottom, is:
|
||||
|
||||
```text
|
||||
TALLY light, with camera number
|
||||
STANDARD
|
||||
MASTER
|
||||
SLAVE
|
||||
CAM POWER
|
||||
BARS
|
||||
```
|
||||
|
||||
Use these names instead of generic "right-side status" labels when reviewing
|
||||
webcam crops.
|
||||
|
||||
Readout/status run:
|
||||
|
||||
| Frame | Selector/value | Visible effect |
|
||||
| --- | --- | --- |
|
||||
| `00 01 0F 08 00 5C` | `E000[0x008F]=0x0800` | SHUTTER display shows `EUS`/likely `EVS`; iris AUTO lamp is lit |
|
||||
| `00 01 0F 10 00 44` | `E000[0x008F]=0x1000` | SHUTTER display shows `OFF`; iris AUTO lamp remains lit |
|
||||
| `00 01 13 80 00 C8` | `E000[0x0093]=0x8000` | white-balance / black-flare lamp cluster changes, consistent with prior preset/manual observation |
|
||||
| `00 01 13 90 20 F8` | `E000[0x0093]=0x9020` | black-flare manual-context candidate remains visible |
|
||||
| `00 01 13 90 FF 27` | `E000[0x0093]=0x90FF` | black-flare auto-context candidate remains visible |
|
||||
| `00 01 90 80 00 4B` | `E000[0x0110]=0x8000` | KNEE AUTO lamp lights |
|
||||
|
||||
The `0x00B9` gate writes in this compact run did not light KNEE AUTO by
|
||||
themselves at the 0.5 s snapshot point. That matches the ROM model where
|
||||
`0x00B9.13` is more of a report-path gate, while `0x0110.15` is the stronger
|
||||
visible KNEE AUTO source.
|
||||
|
||||
Operator-lamp run:
|
||||
|
||||
| Frame | Selector/value | Visible effect |
|
||||
| --- | --- | --- |
|
||||
| `00 00 13 80 00 C9` | `E000[0x0013]=0x8000` | far-right SLAVE lamp lights, based on stack order and crop position |
|
||||
| `00 00 17 80 00 CD` | `E000[0x0017]=0x8000` | far-right bottom white BARS lamp lights |
|
||||
| `00 00 1A 80 00 C0` | `E000[0x001A]=0x8000` | lower right white lamp appeared lit in the compact run, later refined as likely `0x0017` carryover |
|
||||
|
||||
Right-stack isolation/fresh-latch refinement:
|
||||
|
||||
| Frame | Selector/value | Visible effect |
|
||||
| --- | --- | --- |
|
||||
| `00 00 15 80 00 CF` | `E000[0x0015]=0x8000` | CALL lamp lights |
|
||||
| `00 00 15 00 00 4F` | `E000[0x0015]=0x0000` | CALL lamp clears |
|
||||
| `00 00 13 80 00 C9` | `E000[0x0013]=0x8000` | far-right SLAVE lamp lights |
|
||||
| `00 00 13 00 00 49` | `E000[0x0013]=0x0000` | SLAVE lamp clears |
|
||||
| `00 00 17 80 00 CD` | `E000[0x0017]=0x8000` | far-right bottom white BARS lamp lights |
|
||||
| `00 00 17 00 00 4D` | `E000[0x0017]=0x0000` | lamp remains lit; low write does not clear it |
|
||||
| `00 00 1A 80 00 C0` | `E000[0x001A]=0x8000` | no independent BARS-lamp effect from fresh boot |
|
||||
| `00 00 07 80 00 DD` / `00 00 07 00 00 5D` | `E000[0x0007]` high/low | no clear visible delta from CONNECT-OK baseline |
|
||||
|
||||
So `0x0017` is currently the strongest BARS lamp-on/latch selector.
|
||||
`0x001A` should not be labeled as the same lamp source from the prior compact
|
||||
run; that was likely carryover after `0x0017` had latched the white lamp on.
|
||||
`0x0007` is still protocol-relevant because the real panel emits the matching
|
||||
CAM POWER event frame, but the host-write visible lamp mapping is not separated
|
||||
from the CONNECT-OK baseline yet.
|
||||
|
||||
ROM trace refinement: selector `0x0013` dispatches to `H'2E06`, reads current
|
||||
table word `E800[0x0013]` at `H'E826`, and maps bit 15 to SLAVE while bit 14
|
||||
maps to `IRIS/M.BLACK LINK`. See `docs/pt2-iris-mblack-link-rom-trace.md`.
|
||||
|
||||
STANDARD/MASTER hunt:
|
||||
|
||||
| Run | Tested selector/value pocket | Result |
|
||||
| --- | --- | --- |
|
||||
| `panel-atlas-standard-master-bit-sweep-v1` | `0x0012`, `0x0013`, `0x0014` with high-bit/high-nibble candidates | no clean STANDARD or MASTER lamp trigger; positive SLAVE control worked |
|
||||
| `panel-atlas-standard-master-neighbor-sweep-v2` | `0x0010`, `0x0011`, `0x0015`, `0x0016`, `0x0017`, `0x0018`, `0x0019`, `0x001A` high-nibble candidates | no clean STANDARD or MASTER trigger |
|
||||
| `panel-atlas-standard-master-lower-neighbor-sweep-v3` | `0x0008` through `0x000F` high-nibble candidates | no clean STANDARD or MASTER trigger |
|
||||
|
||||
The `v2` sweep did show the far-right bottom BARS lamp/latch from the
|
||||
`0x0017` family when using non-`0x8000` high-nibble values. The clearest
|
||||
transition is `00 00 17 40 00 0D` (`E000[0x0017]=0x4000`) lighting the same
|
||||
bottom white BARS lamp that `0x0017=0x8000` can light. The lamp persisted after
|
||||
`0x0017=0x0000`, matching the existing BARS latch behavior. Later `0x0018`
|
||||
rows are contaminated by that latch and need a fresh-boot isolation run before
|
||||
labeling `0x0018` as a separate BARS source.
|
||||
|
||||
## Next Atlas Step
|
||||
|
||||
The next useful run is still a clear/ack/state-transition probe for the
|
||||
`0x0017` BARS latch, now including `0x0017=0x4000`:
|
||||
|
||||
- test likely sibling selectors around `0x0016`, `0x0018`, `0x0019`, and `0x001A`
|
||||
from a fresh boot after `0x0017` has latched on,
|
||||
- try command-7 repeat/ack and selector-zero refreshes to see whether the lamp
|
||||
clears through a state-machine transition rather than a simple low write,
|
||||
- test `0x0007` with an alternate baseline, because CONNECT OK already lights
|
||||
CAM POWER and masks any host-write lamp delta.
|
||||
- do not re-run `0x0008` through `0x0014` high-nibble values for
|
||||
STANDARD/MASTER unless the ROM trace points back there; the webcam sweeps did
|
||||
not show those lamps in that pocket.
|
||||
|
||||
## ROM-Derived Button Output Sweep
|
||||
|
||||
To skip the physical RCP button-press side and directly test likely "on" states
|
||||
from ROM handlers, use:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\build_rom_button_output_sweep.py
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\panel-atlas-rom-button-output-candidates-v1.json --parity E --quiet-console --log captures\panel-atlas-rom-button-output-candidates-v1-webcam.txt --result-json captures\panel-atlas-rom-button-output-candidates-v1-webcam-result.json --snapshot-dir captures\panel-atlas-rom-button-output-candidates-v1-webcam-shots --camera-index 4 --snapshot-delays 0.5
|
||||
```
|
||||
|
||||
This scenario power-cycles before every candidate, seeds `CONNECT: OK`, sends
|
||||
one command-0 selector/value from the ROM-derived candidate list, and captures a
|
||||
single webcam image 0.5 s later. It is intentionally slower than a continuous
|
||||
sweep but should avoid most latch/carryover ambiguity.
|
||||
|
||||
Run result notes from `captures/panel-atlas-rom-button-output-candidates-v1-webcam-shots/`:
|
||||
|
||||
| Case | Frame | Selector/value | Visible result |
|
||||
| --- | --- | --- | --- |
|
||||
| 001 | `00 00 13 40 00 09` | `0x0013 = 0x4000` | IRIS/M.BLACK LINK |
|
||||
| 002 | `00 00 13 80 00 C9` | `0x0013 = 0x8000` | SLAVE |
|
||||
| 003 | `00 00 15 80 00 CF` | `0x0015 = 0x8000` | CALL and red tally |
|
||||
| 004 | `00 00 17 80 00 CD` | `0x0017 = 0x8000` | BARS |
|
||||
| 005 | `00 01 90 80 00 4B` | `0x0110 = 0x8000` | KNEE AUTO |
|
||||
| 006 | `00 00 1A 08 08 40` | `0x001A = 0x0808` | MONITOR ENC |
|
||||
| 007 | `00 00 1A 20 20 40` | `0x001A = 0x2020` | MONITOR B |
|
||||
| 008 | `00 00 1A 40 40 40` | `0x001A = 0x4040` | MONITOR G |
|
||||
| 009 | `00 00 1A 80 80 40` | `0x001A = 0x8080` | MONITOR R |
|
||||
| 010 | `00 00 6B 80 00 B1` | `0x006B = 0x8000` | STANDARD |
|
||||
| 011 | `00 01 03 00 04 5C` | `0x0083 = 0x0004` | IRIS AUTO, SHUTTER OFF, MASTER GAIN HP |
|
||||
| 012 | `00 01 03 40 00 18` | `0x0083 = 0x4000` | IRIS AUTO, SHUTTER OFF, MASTER GAIN 0 |
|
||||
| 013 | `00 01 03 20 00 78` | `0x0083 = 0x2000` | IRIS AUTO, SHUTTER OFF, MASTER GAIN 3 |
|
||||
| 014 | `00 01 0F 80 00 D4` | `0x008F = 0x8000` | IRIS AUTO, SHUTTER begins with `1...` |
|
||||
| 015 | `00 01 0F 20 00 74` | `0x008F = 0x2000` | IRIS AUTO, SHUTTER `00.0` |
|
||||
| 016 | `00 01 0F 08 00 5C` | `0x008F = 0x0800` | IRIS AUTO, SHUTTER EVS |
|
||||
| 017 | `00 01 0F 10 00 44` | `0x008F = 0x1000` | IRIS AUTO, SHUTTER OFF |
|
||||
| 018 | `00 01 13 10 20 78` | `0x0093 = 0x1020` | BLACK/FLARE MANUAL, white balance MANUAL |
|
||||
| 019 | `00 01 13 40 40 48` | `0x0093 = 0x4040` | BLACK/FLARE AUTO, white balance AUTO |
|
||||
| 020 | `00 01 13 80 40 88` | `0x0093 = 0x8040` | BLACK/FLARE AUTO, white balance PRESET |
|
||||
| 021 | `00 01 13 00 20 68` | `0x0093 = 0x0020` | BLACK/FLARE MANUAL, white balance MANUAL |
|
||||
| 022 | `00 01 13 00 40 08` | `0x0093 = 0x0040` | BLACK/FLARE AUTO, white balance MANUAL |
|
||||
| 023 | `00 01 1A 08 00 49` | `0x009A = 0x0800` | no panel change observed |
|
||||
| 024 | `00 01 37 20 00 4C` | `0x00B7 = 0x2000` | no panel change observed |
|
||||
|
||||
The run directory contains 28 candidate photos. The user-supplied ordered notes
|
||||
covered the first 24, so cases 025-028 still need visual review before assigning
|
||||
meanings:
|
||||
|
||||
| Case | Frame | Selector/value | Candidate |
|
||||
| --- | --- | --- | --- |
|
||||
| 025 | `00 01 39 40 00 22` | `0x00B9 = 0x4000` | F6DC.7 handler value candidate |
|
||||
| 026 | `00 01 44 80 00 9F` | `0x00C4 = 0x8000` | F6D4.0 bundle selector candidate |
|
||||
| 027 | `00 01 46 80 00 9D` | `0x00C6 = 0x8000` | F6D4.0 bundle selector candidate |
|
||||
| 028 | `00 01 78 80 00 A3` | `0x00F8 = 0x8000` | F6D4.1 handler candidate |
|
||||
|
||||
Key refinements from this run:
|
||||
|
||||
- `0x001A` is now best labeled as the MONITOR selector cluster: `ENC`, `B`, `G`,
|
||||
and `R` appeared cleanly from the four packed values.
|
||||
- `0x006B = 0x8000` is the first clean STANDARD lamp trigger.
|
||||
- `0x0083` is a MASTER GAIN/status display word, with values observed for `HP`,
|
||||
`0`, and `3`, while also lighting IRIS AUTO and showing SHUTTER OFF.
|
||||
- `0x008F` carries local shutter display/value states beyond the earlier
|
||||
EVS/OFF bits.
|
||||
- `0x0093` now has stronger white-balance plus BLACK/FLARE field mapping:
|
||||
high/mid bit combinations select WB AUTO/PRESET/MANUAL and BLACK/FLARE
|
||||
AUTO/MANUAL together.
|
||||
|
||||
## Broad Visual Sweep Workflow
|
||||
|
||||
For exploratory lamp/readout mining, use the generated big sweep rather than
|
||||
hand-writing thousands of frames:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\build_panel_visual_sweep.py scenarios\panel-atlas-big-visual-sweep-0001-017f-highbits.json --start 0x0001 --end 0x017F --values 0x8000,0x4000,0x2000,0x1000,0x0800 --power-cycle-every 32 --ok-every 8 --listen 0.65 --clear-listen 0.15 --ok-listen 0.30
|
||||
```
|
||||
|
||||
Run the generated scenario with webcam snapshots:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\panel-atlas-big-visual-sweep-0001-017f-highbits.json --parity E --quiet-console --log captures\panel-atlas-big-visual-sweep-0001-017f-highbits-webcam.txt --result-json captures\panel-atlas-big-visual-sweep-0001-017f-highbits-webcam-result.json --snapshot-dir captures\panel-atlas-big-visual-sweep-0001-017f-highbits-webcam-shots --camera-index 4 --snapshot-delays 0.5
|
||||
```
|
||||
|
||||
The generated high-bit sweep covers selectors `0x0001` through `0x017F` with
|
||||
five candidate values per selector, for 1,915 candidate snapshots. It power
|
||||
cycles every 32 selectors to reduce latch contamination. Selector zero is
|
||||
omitted because it controls the CONNECT OK baseline.
|
||||
|
||||
After the run, create labeled review sheets:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\make_panel_sweep_contact_sheets.py captures\panel-atlas-big-visual-sweep-0001-017f-highbits-webcam-shots --output-dir captures\panel-atlas-big-visual-sweep-0001-017f-highbits-sheets --only-candidates --crop panel --cols 4 --rows 5 --thumb-width 360
|
||||
```
|
||||
|
||||
If a sheet shows a visible change, the image label has the exact trigger form:
|
||||
`candidate_XXXX_YYYY` means command-0 wrote `E000[0xXXXX]=0xYYYY`. Use that
|
||||
selector/value in a smaller fresh-boot isolation scenario.
|
||||
|
||||
## Broad Sweep Findings
|
||||
|
||||
Run:
|
||||
|
||||
```text
|
||||
captures/panel-atlas-big-visual-sweep-0001-017f-highbits-webcam.txt
|
||||
captures/panel-atlas-big-visual-sweep-0001-017f-highbits-webcam-result.json
|
||||
captures/panel-atlas-big-visual-sweep-0001-017f-highbits-webcam-shots/
|
||||
```
|
||||
|
||||
Serial health:
|
||||
|
||||
| RX frames | TX frames | Resync | Dropped bytes | Snapshots |
|
||||
| ---: | ---: | ---: | ---: | ---: |
|
||||
| 706 | 2372 | 0 | 0 | 1916 |
|
||||
|
||||
User-reviewed new visible hits from the broad sweep:
|
||||
|
||||
| Candidate label | Frame | Selector/value | Reported visible effect |
|
||||
| --- | --- | --- | --- |
|
||||
| `candidate_0013_4000` | `00 00 13 40 00 09` | `E000[0x0013]=0x4000` | `IRIS/M.BLACK LINK` area/lamp |
|
||||
| `candidate_0024_8000` | `00 00 24 80 00 FE` | `E000[0x0024]=0x8000` | LCD selector button/lamp |
|
||||
| `candidate_0082_8000` | `00 01 02 80 00 D9` | `E000[0x0082]=0x8000` | IRIS readout shows `OP` |
|
||||
| `candidate_0082_4000` | `00 01 02 40 00 19` | `E000[0x0082]=0x4000` | IRIS readout shows `1.4` |
|
||||
| `candidate_0083_8000` | `00 01 03 80 00 D8` | `E000[0x0083]=0x8000` | MASTER GAIN readout shows `-3` |
|
||||
| `candidate_0093_8000` | `00 01 13 80 00 C8` | `E000[0x0093]=0x8000` | white-balance PRESET lamp |
|
||||
| `candidate_0093_4000` | `00 01 13 40 00 08` | `E000[0x0093]=0x4000` | white-balance AUTO lamp |
|
||||
| `candidate_0093_2000` | `00 01 13 20 00 68` | `E000[0x0093]=0x2000` | white-balance MANUAL lamp |
|
||||
|
||||
The serial log shows immediate command-4 table readback frames for these writes,
|
||||
so the RCP accepted the selector updates.
|
||||
|
||||
Fresh-boot isolation scenario:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\panel-atlas-big-hits-isolation-v1.json --parity E --quiet-console --log captures\panel-atlas-big-hits-isolation-v1-webcam.txt --result-json captures\panel-atlas-big-hits-isolation-v1-webcam-result.json --snapshot-dir captures\panel-atlas-big-hits-isolation-v1-webcam-shots --camera-index 4 --snapshot-delays 0.5
|
||||
```
|
||||
|
||||
Create review sheets for that isolation run:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\make_panel_sweep_contact_sheets.py captures\panel-atlas-big-hits-isolation-v1-webcam-shots --output-dir captures\panel-atlas-big-hits-isolation-v1-sheets --crop panel --cols 3 --rows 4 --thumb-width 420
|
||||
```
|
||||
|
||||
Fresh-boot isolation results:
|
||||
|
||||
| Frame | Selector/value | Confirmed visible effect |
|
||||
| --- | --- | --- |
|
||||
| `00 00 13 40 00 09` | `E000[0x0013]=0x4000` | `IRIS/M.BLACK LINK` lamp |
|
||||
| `00 00 24 80 00 FE` | `E000[0x0024]=0x8000` | LCD selector-button lamp |
|
||||
| `00 00 24 00 00 7E` | `E000[0x0024]=0x0000` | same LCD selector-button lamp remained visible at 0.5 s |
|
||||
| `00 01 02 80 00 D9` | `E000[0x0082]=0x8000` | IRIS readout `OP` |
|
||||
| `00 01 02 40 00 19` | `E000[0x0082]=0x4000` | IRIS readout `1.4` |
|
||||
| `00 01 02 00 00 59` | `E000[0x0082]=0x0000` | IRIS readout blank |
|
||||
| `00 01 03 80 00 D8` | `E000[0x0083]=0x8000` | IRIS AUTO lamp, SHUTTER `OFF`, MASTER GAIN `-3` |
|
||||
| `00 01 03 00 00 58` | `E000[0x0083]=0x0000` | same IRIS AUTO / SHUTTER `OFF` / MASTER GAIN `-3` state remained visible at 0.5 s |
|
||||
| `00 01 13 80 00 C8` | `E000[0x0093]=0x8000` | BLACK/FLARE MANUAL plus white-balance PRESET |
|
||||
| `00 01 13 40 00 08` | `E000[0x0093]=0x4000` | BLACK/FLARE MANUAL plus white-balance AUTO |
|
||||
| `00 01 13 20 00 68` | `E000[0x0093]=0x2000` | BLACK/FLARE MANUAL plus white-balance MANUAL |
|
||||
| `00 01 13 00 00 48` | `E000[0x0093]=0x0000` | BLACK/FLARE MANUAL plus white-balance MANUAL |
|
||||
|
||||
Interpretation:
|
||||
|
||||
- `0x0082` is a direct IRIS display/status selector. Clearing it blanks the IRIS
|
||||
readout, so this one behaves like a simple display source.
|
||||
- `0x0083=0x8000` drives a combined state: MASTER GAIN `-3`, SHUTTER `OFF`, and
|
||||
IRIS AUTO. Clearing the selector did not visibly clear that state in the
|
||||
isolation run, so it may be latched or copied into another display bank.
|
||||
- `0x0093` is now a confirmed white-balance mode selector with
|
||||
`0x8000=PRESET`, `0x4000=AUTO`, and `0x0000/0x2000=MANUAL` under this test
|
||||
context. BLACK/FLARE MANUAL was also present for all tested `0x0093` states.
|
||||
- `0x0024=0x8000` lights an LCD selector-button lamp, but `0x0024=0x0000` did
|
||||
not clear it in this timing window.
|
||||
772
docs/pt2-protocol.md
Normal file
772
docs/pt2-protocol.md
Normal file
@@ -0,0 +1,772 @@
|
||||
# PT2 Protocol Working Notes
|
||||
|
||||
This document is the current working model for the serial protocol spoken by the Sony RCP-TX7 panel ROM.
|
||||
|
||||
A later RCP manual mentions a "PT2 compatibility mode" for controlling the same CCU family this panel was made for. We are using "PT2" here as a practical label for this six-byte SCI1 protocol model. It is not yet a claim that every field name matches Sony's official PT2 terminology.
|
||||
|
||||
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
|
||||
|
||||
- The real bench link is `38400 8E1`, not `38400 8N1`.
|
||||
- The ROM uses H8/536 SCI1 through the MAX202 RS232 transceiver.
|
||||
- Frames are six bytes long.
|
||||
- The checksum is `0x5A XOR byte0 XOR byte1 XOR byte2 XOR byte3 XOR byte4`.
|
||||
- The ROM validates the checksum before normal command dispatch.
|
||||
- The first byte is decoded as `command = byte0 & 0x07`.
|
||||
- Bytes 1 and 2 encode a logical selector.
|
||||
- Bytes 3 and 4 are a 16-bit value for write-style commands.
|
||||
- The protocol is stateful. Some commands only work while a continuation/session latch is live.
|
||||
- `CONNECT:NOT ACT` is recoverable without a power cycle.
|
||||
- `CONNECT: OK` can be reached on real hardware after using the correct `8E1` serial format.
|
||||
|
||||
## Hardware Path
|
||||
|
||||
SCI1 is the external serial path:
|
||||
|
||||
- H8/536 pin 66, `P95/TXD`, goes to MAX202 pin 11.
|
||||
- MAX202 pin 12 goes to H8/536 pin 67, `P96/RXD`.
|
||||
- The ROM initializes SCI1 as async 8-bit, even parity, 1 stop.
|
||||
|
||||
ROM evidence:
|
||||
|
||||
- `build/rom_decompiled.asm:437`: `SCI1_SMR = H'24`.
|
||||
- `build/rom_decompiled.asm:438`: `SCI1_SCR = H'3C`.
|
||||
- `build/rom_decompiled.asm:439`: `SCI1_BRR = H'07`.
|
||||
|
||||
Bench implication:
|
||||
|
||||
- Use `38400 8E1` for all real-device captures and probes.
|
||||
- Old `38400 8N1` captures mostly exercised parity/error handling and retry echoes. Do not assign normal protocol meaning to old `8N1` `07...` frames until they are reproduced under `8E1`.
|
||||
|
||||
## Frame Format
|
||||
|
||||
Working host/RCP frame layout:
|
||||
|
||||
```text
|
||||
byte0 command byte; ROM uses byte0 & 0x07
|
||||
byte1 selector page/high bits; byte1.7 is rejected by normal handlers
|
||||
byte2 selector low byte
|
||||
byte3 value high byte
|
||||
byte4 value low byte
|
||||
byte5 checksum = 0x5A XOR byte0..byte4
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
```text
|
||||
00 00 00 80 80 5A ; command 0, selector 0x000, value 0x8080
|
||||
01 00 00 00 00 5B ; command 1, read selector 0x000
|
||||
04 00 00 80 00 DE ; command 4 shape, selector 0x000, value high 0x80
|
||||
07 00 00 00 00 5D ; command 7, repeat previous finalized TX frame
|
||||
```
|
||||
|
||||
## Selector Decode
|
||||
|
||||
The ROM builds a raw selector from bytes 1 and 2, then maps it through `loc_622B`.
|
||||
|
||||
Known decode:
|
||||
|
||||
| byte1 page | byte2 range | selector |
|
||||
| --- | --- | --- |
|
||||
| page 0, or pages 4-7 | `00-7F` | `0x000 + byte2` |
|
||||
| page 1 | `00-FF` | `0x080 + byte2` |
|
||||
| page 2 | `00-7F` | `0x180 + byte2` |
|
||||
| page 3 | any | `0x1FF` fallback |
|
||||
| invalid range | any | `0x1FF` fallback |
|
||||
|
||||
Important caveats:
|
||||
|
||||
- `byte1.7` is rejected before normal command handling.
|
||||
- Frames like `01 80 40 ...` may look like a selector encoding, but the normal command path rejects `byte1.7`.
|
||||
- Pages 4-7 appear to alias the page-0 path when the low byte is in range.
|
||||
|
||||
## Checksum
|
||||
|
||||
Checksum formula:
|
||||
|
||||
```python
|
||||
checksum = 0x5A
|
||||
for b in frame[:5]:
|
||||
checksum ^= b
|
||||
```
|
||||
|
||||
The ROM path:
|
||||
|
||||
- RXI captures bytes into `F868-F86D`.
|
||||
- Main-loop processing copies them to `F860-F865`.
|
||||
- Physical error latch `FAA4.7` is checked before checksum dispatch.
|
||||
- Checksum mismatch enters the retry/error path.
|
||||
- Valid checksum clears retry counter `FAA6`, decodes selector, and dispatches on `byte0 & 0x07`.
|
||||
|
||||
Key ROM areas:
|
||||
|
||||
- RXI/ERI capture: `BB57`, `BB67`.
|
||||
- Validation and checksum: `BBAB-BBF0`.
|
||||
- Selector decode call: `BC01 -> 622B`.
|
||||
- Command dispatch: `BC08-BC67`.
|
||||
|
||||
## Command Model
|
||||
|
||||
The biggest protocol lesson is that the command set has two modes:
|
||||
|
||||
- Initial dispatcher: active while `FAA2 == 0`.
|
||||
- Continuation dispatcher: active while `FAA2 != 0`.
|
||||
|
||||
That means command numbers are not globally meaningful. Command `4`, `5`, and `6` are continuation-path commands, not normal idle commands.
|
||||
|
||||
| Command | Path | Current meaning | Response |
|
||||
| --- | --- | --- | --- |
|
||||
| `0x00` | initial | Set primary/current value, queue selector processing | Immediate `0x04` echo-style response |
|
||||
| `0x01` | initial | Read primary value table | Immediate `0x04` readback response |
|
||||
| `0x02` | initial | Quiet clear/no-op style command | No immediate response seen in ROM |
|
||||
| `0x04` | continuation | Set/update value without immediate response | Usually no immediate response |
|
||||
| `0x05` | continuation | ACK/session-clear/pending handling | Usually no immediate response |
|
||||
| `0x06` | continuation | Set secondary value table | Usually no immediate response |
|
||||
| `0x07` | both | Retransmit previous finalized TX frame | Repeats last TX frame |
|
||||
|
||||
## Command Details
|
||||
|
||||
### Command 0: Initial Set Value
|
||||
|
||||
Path: `BC69`.
|
||||
|
||||
Conditions:
|
||||
|
||||
- Valid checksum.
|
||||
- `FAA2 == 0`.
|
||||
- `byte1.7 == 0`.
|
||||
|
||||
Effects:
|
||||
|
||||
- Writes value into `E000 + 2*selector`.
|
||||
- Writes value into `E800 + 2*selector`.
|
||||
- Sets dirty flag bit 7 in `EC00 + selector`.
|
||||
- Calls `BE70`, which appends the selector into the `F970` selector-processing queue.
|
||||
- Sends an immediate `0x04` response through `BA26`.
|
||||
|
||||
Selector-zero special case:
|
||||
|
||||
- For selector `0x000`, the low byte is forced to `0x80`.
|
||||
- This makes selector-zero writes look like `xx80`, not arbitrary `xxLL`.
|
||||
|
||||
Important candidate:
|
||||
|
||||
```text
|
||||
00 00 00 80 80 5A ; selector 0 = 0x8080, strongest CONNECT OK seed
|
||||
```
|
||||
|
||||
### Command 1: Read Value
|
||||
|
||||
Path: `BCD7`.
|
||||
|
||||
Effects:
|
||||
|
||||
- Reads `E000 + 2*selector`.
|
||||
- Stages a `0x04` response.
|
||||
- Clears `FAA2.7`.
|
||||
|
||||
Useful readback examples:
|
||||
|
||||
```text
|
||||
01 00 00 00 00 5B ; read selector 0x000
|
||||
01 00 40 00 00 1B ; read selector 0x040
|
||||
01 01 76 00 00 2C ; read selector 0x0F6
|
||||
```
|
||||
|
||||
Bench implication:
|
||||
|
||||
- Command 1 verifies table state.
|
||||
- It is not an ACK and does not enter continuation handling.
|
||||
- Command 7 after command 1 can repeat the last finalized readback.
|
||||
|
||||
### Command 2: Initial Clear/No-Op Candidate
|
||||
|
||||
Path: `BD04`.
|
||||
|
||||
Effects:
|
||||
|
||||
- Clears `FAA2.7`.
|
||||
- Returns without staging an obvious response.
|
||||
|
||||
Meaning is still unclear. Treat it as a quiet/session-control candidate, not as a data write.
|
||||
|
||||
### Command 4: Continuation Set Value
|
||||
|
||||
Path: `BD0E`.
|
||||
|
||||
Conditions:
|
||||
|
||||
- Valid checksum.
|
||||
- `FAA2 != 0`.
|
||||
- Command bit 2 set.
|
||||
- `byte1.7 == 0`.
|
||||
|
||||
Effects:
|
||||
|
||||
- Writes value into `E000 + 2*selector`.
|
||||
- Selector zero also updates `E800`.
|
||||
- Nonzero selectors set dirty flag bit 7 in `EC00 + selector`.
|
||||
- Can mirror/persist mapped nonzero selectors through the `F400`/EEPROM path when `F76E.7` allows it.
|
||||
- If `FAA2.3` was set by a queued report, command 4 can advance `F9B5` to consume that report.
|
||||
- Clears `FAA3` and `FAA2` before exit.
|
||||
|
||||
Known CONNECT test frames:
|
||||
|
||||
```text
|
||||
04 00 00 40 00 1E
|
||||
04 00 00 80 00 DE
|
||||
04 00 00 C0 00 9E
|
||||
```
|
||||
|
||||
ROM caveat:
|
||||
|
||||
- A standalone command 4 from a truly idle `FAA2 == 0` state should not reach `BD0E`.
|
||||
- Bench evidence now proves the panel can still recover from `CONNECT:NOT ACT` without power cycling, so visible `NOT ACT` is not equivalent to "all serial continuation state is impossible".
|
||||
|
||||
### Command 5: Continuation ACK/Clear Candidate
|
||||
|
||||
Path: `BD80`.
|
||||
|
||||
Conditions:
|
||||
|
||||
- Continuation path only.
|
||||
|
||||
Effects:
|
||||
|
||||
- Usually no immediate response.
|
||||
- Selectors `0x006C`, `0x006D`, and `0x006E` call `BE70`.
|
||||
- If `F731.7` is set, selectors `0x006B`, `0x0096`, `0x0097`, `0x00C6`, and `0x00F8` clear `F731.7/F790.7`.
|
||||
- If `FAA2.3` was set by a queued report, command 5 can advance `F9B5`.
|
||||
- Clears `FAA3` and `FAA2` before exit.
|
||||
|
||||
Bench implication:
|
||||
|
||||
- Command 5 is not a generic always-live ACK.
|
||||
- It only has ACK-like meaning when the continuation latch is live.
|
||||
|
||||
### Command 6: Continuation Secondary Set
|
||||
|
||||
Path: `BDDB`.
|
||||
|
||||
Effects:
|
||||
|
||||
- Writes value into `E400 + 2*selector`.
|
||||
- Sets dirty flag bit 6 in `EC00 + selector`.
|
||||
- Can advance queued-report state when `FAA2.3` is live.
|
||||
- Clears `FAA3` and `FAA2`.
|
||||
|
||||
### Command 7: Repeat Previous TX
|
||||
|
||||
Path: `BE05`.
|
||||
|
||||
Effects:
|
||||
|
||||
- Copies the previous finalized TX frame back into staging.
|
||||
- Sends it again through `BA26`.
|
||||
- Works from initial and continuation paths.
|
||||
|
||||
Bench implication:
|
||||
|
||||
- Command 7 is useful as a "what did you last finalize?" probe.
|
||||
- It does not prove a hidden continuation token by itself.
|
||||
|
||||
## RCP Transmit Frames
|
||||
|
||||
The TX side uses the same six-byte checksum model.
|
||||
|
||||
TX staging:
|
||||
|
||||
- `F850-F854`: staging bytes.
|
||||
- `F858-F85C`: finalized bytes.
|
||||
- `F85D`: computed checksum.
|
||||
- `BA26`: finalizes and starts SCI1 TX.
|
||||
- TXI sends bytes 1-5 after the first TDR write.
|
||||
|
||||
Known RCP-origin frames:
|
||||
|
||||
| Frame | Confidence | Current meaning |
|
||||
| --- | --- | --- |
|
||||
| `00 00 00 00 80 DA` | high | idle heartbeat / selector-zero report |
|
||||
| `00 00 07 80 00 DD` | medium-high | observed CAM POWER button/report candidate |
|
||||
| `00 00 15 80 00 CF` | medium-high | observed CALL on/report candidate |
|
||||
| `00 00 15 00 00 4F` | medium-high | observed CALL off/report candidate |
|
||||
| `02 00 02 00 00 5A` | medium | emulator CONNECT OK path response candidate |
|
||||
|
||||
Heartbeat:
|
||||
|
||||
- Idle frame: `00 00 00 00 80 DA`.
|
||||
- Observed cadence: about 700 ms.
|
||||
- ROM path: `loc_4067` enqueues selector 0, `loc_BAF2/BB08` dequeues it, `BB1C/BB20/BB2B` stages TX bytes, `BA26` emits the frame.
|
||||
- FRT2 timing model: `TCR=H'02`, `OCRA=H'7A12`, modeled as a 100 ms tick at 10 MHz; `F9C4=0x07` gives about 700 ms post-send heartbeat delay.
|
||||
|
||||
## Retry/Error 07 Frames
|
||||
|
||||
`07...` frames are easy to misread.
|
||||
|
||||
The ROM can generate a `0x07` retry/error echo when:
|
||||
|
||||
- A physical RX error occurs, or
|
||||
- A checksum mismatch occurs, and
|
||||
- `FAA5.7` is set, and
|
||||
- Retry count `FAA6` is below two.
|
||||
|
||||
Path:
|
||||
|
||||
- `BE29` retry gate.
|
||||
- `BE4D` stages `F850=0x07`.
|
||||
- `F851-F854` copy host `RX[1:4]`.
|
||||
- `BA26` sends it.
|
||||
|
||||
Bench implication:
|
||||
|
||||
- A visible `07...` frame is not automatically a normal status report or ACK.
|
||||
- Old `8N1` captures produced many misleading `07...` frames because parity errors exercised this path.
|
||||
|
||||
## Table Model
|
||||
|
||||
The ROM behaves like a selector-indexed state machine. The CCU likely seeds values, and the RCP updates LCD/lamp/control behavior from those values.
|
||||
|
||||
| Table | Range | Role |
|
||||
| --- | --- | --- |
|
||||
| Primary value table | `E000-E3FF` | Command 0/4 writes, command 1 reads |
|
||||
| Secondary value table | `E400-E7FF` | Command 6 writes |
|
||||
| Current/report table | `E800-EBFF` | Used when RCP builds outbound report frames |
|
||||
| Dirty/flag table | `EC00-EFFF` | Per-selector flags, bit7 for primary writes, bit6 for secondary writes |
|
||||
| EEPROM/shadow | `F400-F4FF` | Optional mapped persistence/config surface |
|
||||
|
||||
Important details:
|
||||
|
||||
- Selector zero is special in command 0 and command 4.
|
||||
- Command 0 writes both `E000` and `E800`.
|
||||
- Command 4 writes `E800` only for selector zero in the current ROM evidence.
|
||||
- `BAF2` reads `E800 + 2*selector` when building autonomous RCP reports.
|
||||
- `BE70/F970` is a selector-processing queue.
|
||||
- `3E54/F870` is a separate serial-visible report queue.
|
||||
|
||||
Do not mix up:
|
||||
|
||||
- `F970`: "process this selector internally".
|
||||
- `F870`: "send this selector/report over serial".
|
||||
|
||||
## State And Queues
|
||||
|
||||
Important RAM/state bytes:
|
||||
|
||||
| Address | Working name | Meaning |
|
||||
| --- | --- | --- |
|
||||
| `FAA2.7` | RX command in progress | Set on initial parse, cleared on exits |
|
||||
| `FAA2.3` | queued report continuation needed | Set after autonomous report send |
|
||||
| `FAA3.7` | pending resend mask | Set after queued report send |
|
||||
| `FAA4.7` | RX physical error latch | Set by SCI1 ERI |
|
||||
| `FAA5.7` | RX session gate | Set while `F9C5` is alive after complete RX |
|
||||
| `FAA6` | retry counter | Limits retry/error echoes |
|
||||
| `F9C1` | inter-byte timeout | Reloaded on RXI |
|
||||
| `F9C3` | RX byte count | Counts up to six |
|
||||
| `F9C4` | heartbeat/report cadence gate | Controls idle heartbeat enqueue |
|
||||
| `F9C5` | RX/session timeout | Loaded with `0x14` after full RX frame |
|
||||
| `F9B0/F9B5` | serial report queue cursors | Drive `F870`/`BAF2` |
|
||||
| `F9B4/F9B9` | selector-processing queue cursors | Drive `F970`/`2806` |
|
||||
|
||||
Session expiry:
|
||||
|
||||
- A complete six-byte RX frame loads `F9C5=0x14`.
|
||||
- FRT2 decrements `F9C5`.
|
||||
- When `F9C5` reaches zero, `loc_3FEF` can clear queues/session state.
|
||||
- If `FAA5.7` was set, expiry calls `loc_400C`.
|
||||
- `loc_400C` clears connection/session RAM and refreshes inactive display state.
|
||||
|
||||
This explains why random traffic tends to settle back to `CONNECT:NOT ACT`.
|
||||
|
||||
## CONNECT State
|
||||
|
||||
`CONNECT` strings are built through the LCD driver, not received as literal serial text.
|
||||
|
||||
Known LCD path:
|
||||
|
||||
```text
|
||||
FAF0-FAFF line buffer -> 3ECC -> 3F28 -> 3F40 -> F200/F201 LCD ports
|
||||
```
|
||||
|
||||
ROM/emulator findings:
|
||||
|
||||
- Boot/no-active-session display can show `CONNECT:NOT ACT`.
|
||||
- Direct emulator entry at `loc_2CB9` with `E000[0]=0x8080` and `F730=0` reaches `CONNECT: OK`.
|
||||
- Queued selector-zero path reaches OK when:
|
||||
- `F970[0]=0`
|
||||
- `F9B9=0`
|
||||
- `F9B4=1`
|
||||
- `E000[0]=0x8080`
|
||||
- `F730=0`
|
||||
- Selector zero dispatches through the `28A6` jump table into the CONNECT handler window.
|
||||
|
||||
Bench findings:
|
||||
|
||||
- Correct `8E1` serial format made the CONNECT path work on real hardware.
|
||||
- Real hardware can recover from `CONNECT:NOT ACT` to `CONNECT: OK` without a power cycle.
|
||||
- Successful active-looking state included:
|
||||
- `CONNECT: OK`
|
||||
- CAM POWER lamp illuminated
|
||||
- numeric readouts illuminated as `----`
|
||||
- Matrix tests show that cadence matters:
|
||||
- `40 -> 80 -> C0` with 10 ms, 50 ms, or 150 ms inter-frame gaps stayed at `CONNECT:NOT ACT` after a fresh power-cycle test.
|
||||
- The same order with 700 ms and 1.5 s inter-frame gaps produced `CONNECT: OK` before falling back to `CONNECT:NOT ACT`.
|
||||
- At 700 ms gaps, no single frame worked by itself.
|
||||
- At 700 ms gaps, every tested two-frame pair worked: `40 -> 80`, `80 -> C0`, and `40 -> C0`.
|
||||
- A repeated identical pair also worked: `80 -> 80` at about 700 ms produced eight `02 00 02 00 00 5A` OK-path responses, then heartbeat traffic resumed.
|
||||
- The no-power-cycle recovery test from an already visible `CONNECT:NOT ACT` state produced repeated `02 00 02 00 00 5A` OK-path responses, then returned to heartbeat traffic.
|
||||
|
||||
Current interpretation:
|
||||
|
||||
- `CONNECT:NOT ACT` is a normal no-active-session/cleared-state display, not a terminal latch.
|
||||
- `CONNECT: OK` is table/state driven, probably selector-zero active/connect state.
|
||||
- `0x8080` at selector zero is the strongest known active/connect value.
|
||||
- The panel likely expects the CCU to consume/ACK report-queue frames and keep seeding or refreshing state after entering OK.
|
||||
- The working fake-CCU sequence is probably not "three frames as fast as possible"; it appears to need CCU-like cadence or a live session window, roughly on the heartbeat/report timescale.
|
||||
- A single selector-zero continuation-shaped frame is insufficient in the current tests; two selector-zero writes at the working cadence are enough. They do not need to carry different values, because `80 -> 80` also worked.
|
||||
|
||||
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
|
||||
|
||||
These are syntactically valid host frames produced from ROM table mining. Use them as candidate fake-CCU state seeds, not as final protocol truth.
|
||||
|
||||
| Selector | Candidate value | Frame | Why it matters |
|
||||
| --- | --- | --- | --- |
|
||||
| `0x000` | `0x8080` | `00 00 00 80 80 5A` | strongest CONNECT OK seed |
|
||||
| `0x003` | `0x8000` | `00 00 03 80 00 D9` | ROM default enabled bit candidate |
|
||||
| `0x040` | `0xFFFF` | `00 00 40 FF FF 1A` | ROM default all-ones/status block candidate |
|
||||
| `0x040` | `0x4030` | `00 00 40 40 30 6A` | bench-touched 0x40 family value |
|
||||
| `0x0F6` | `0x2000` | `00 01 76 20 00 0D` | `loc_48FA` tests `E1EC.13` and can enqueue report `0x00F6` |
|
||||
|
||||
Readbacks:
|
||||
|
||||
```text
|
||||
01 00 00 00 00 5B ; selector 0x000
|
||||
01 00 03 00 00 58 ; selector 0x003
|
||||
01 00 40 00 00 1B ; selector 0x040
|
||||
01 01 76 00 00 2C ; selector 0x0F6
|
||||
```
|
||||
|
||||
## Observed Button/Panel Reports
|
||||
|
||||
Before the protocol format was corrected, the RCP appeared to emit only a few report families by itself:
|
||||
|
||||
```text
|
||||
00 00 00 00 80 DA ; heartbeat
|
||||
00 00 07 80 00 DD ; CAM POWER candidate
|
||||
00 00 15 80 00 CF ; CALL on candidate
|
||||
00 00 15 00 00 4F ; CALL off candidate
|
||||
```
|
||||
|
||||
Current interpretation:
|
||||
|
||||
- The RCP can report some panel events.
|
||||
- Many other controls probably need CCU-provided state before they become reportable or meaningful.
|
||||
- The CCU likely streams display/lamp/readout state to the RCP, while the RCP reports operator changes back.
|
||||
|
||||
## EEPROM And Board Config
|
||||
|
||||
The P9 bus is not the external PT2 serial link. It is a bit-banged EEPROM/config path:
|
||||
|
||||
- H8 pin 62, `P91`, reaches X24164 pin 6 `SCL`.
|
||||
- H8 pin 68, `P97`, reaches shared X24164 pin 5 `SDA`.
|
||||
|
||||
ROM findings:
|
||||
|
||||
- `loc_40BB` checks `P7DR.7` and `F402 == H'6B6F` before deciding whether to default EEPROM/shadow tables.
|
||||
- `loc_4103` writes ROM default words through `BFE0`.
|
||||
- `loc_41D2` reads sixteen 8-byte records into `F7B0-F82F`.
|
||||
- Command 4 can persist mapped serial table writes when `F76E.7` is set.
|
||||
|
||||
Current interpretation:
|
||||
|
||||
- EEPROM stores panel/config/default state.
|
||||
- It can affect startup and option behavior.
|
||||
- After the `8E1` discovery, EEPROM is less likely to be the fundamental reason CONNECT failed, but it can still influence which selectors/features are active.
|
||||
|
||||
## Known Useful Bench Commands
|
||||
|
||||
Minimal CONNECT sequence runner:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\bench_connect_lcd_sequence.py --port COM5 --relay-port COM6 --parity E --prompt-screen
|
||||
```
|
||||
|
||||
Recover from `CONNECT:NOT ACT` without power cycling:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\bench_connect_lcd_sequence.py --port COM5 --relay-port COM6 --no-power-cycle --parity E --prompt-before-send --prompt-screen --post-sequence-read 10 --log captures\connect-notact-to-ok.txt
|
||||
```
|
||||
|
||||
Run the reproducibility/minimization matrix:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\connect_ok_matrix.py --suite minimal --parity E --prompt-observation --result-json captures\connect-ok-minimal-result.json
|
||||
```
|
||||
|
||||
Test timing/cadence:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\connect_ok_matrix.py --suite gap --parity E --prompt-observation --result-json captures\connect-ok-gap-result.json
|
||||
```
|
||||
|
||||
Test whether OK is held:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\connect_ok_matrix.py --suite hold --parity E --prompt-observation --result-json captures\connect-ok-hold-result.json
|
||||
```
|
||||
|
||||
Sweep strong continuation/ACK candidates after recovering to `CONNECT: OK`:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\connect_ok_advance_sweep.py --suite core --parity E --prompt-observation --result-json captures\connect-ok-advance-core-result.json
|
||||
```
|
||||
|
||||
Candidate suites:
|
||||
|
||||
- `core`: `05 00 40 00 00 1F` pure command-5 report-consume candidate, then `04 00 00 80 00 DE` selector-zero refresh/consume candidate.
|
||||
- `special`: command-5 `0x006C/0x006D/0x006E`, which call the ROM's `BE70` queue helper.
|
||||
- `latch`: command-5 `0x006B/0x0096/0x0097/0x00C6/0x00F8`, which can clear the `F731/F790` latch bits when that path is live.
|
||||
- `all`: all of the above.
|
||||
|
||||
Current matrix result summary:
|
||||
|
||||
```text
|
||||
minimal suite at 150 ms gaps: all cases stayed CONNECT NOT ACT
|
||||
gap suite at 10/50/150 ms: stayed CONNECT NOT ACT
|
||||
gap suite at 700 ms and 1.5 s: CONNECT OK, then CONNECT NOT ACT
|
||||
minimal suite at 700 ms gaps: singles stayed CONNECT NOT ACT; all pairs reached CONNECT OK then CONNECT NOT ACT
|
||||
repeated 80 -> 80 at about 700 ms: CONNECT OK responses, then CONNECT NOT ACT
|
||||
hold suite at 150 ms gaps: stayed CONNECT NOT ACT
|
||||
no-power-cycle NOT ACT recovery: CONNECT OK responses observed, then heartbeat resumes
|
||||
```
|
||||
|
||||
Advance sweep result summary:
|
||||
|
||||
```text
|
||||
core suite: no new LCD behavior
|
||||
all suite, ack-006C (05 00 6C 00 00 33): CONNECT OK, then LCD blank while CAM POWER lamp stayed on
|
||||
all suite, ack-006D (05 00 6D 00 00 32): CONNECT OK, then COPY IN PROGRESS, then CONNECT NOT ACT
|
||||
all suite, ack-006E/latch candidates: mostly OK then NOT ACT
|
||||
fresh isolated ack-006D run: COPY path reproduced after a relay power-cycle
|
||||
```
|
||||
|
||||
The `0x006D` copy path is now confirmed outside the earlier all-suite ordering caveat: `captures/connect-ok-advance-special-20260526-153339.txt` power-cycled the panel, waited for heartbeats, sent the two-frame `0x8080` CONNECT baseline, then sent only `05 00 6D 00 00 32`; the LCD again entered the copy path. The ROM strongly supports that these are real selector side effects:
|
||||
|
||||
- Command 5 compares `R5` against `0x006C`, `0x006D`, and `0x006E`; those selectors call `BE70` to append the selector to the `F970` processing queue.
|
||||
- Selector `0x006C` dispatches to `H'2FAF`. Forced decoding shows it manipulates `F76E`, `F795`, `F797`, `F799`, can set display selector `F732=H'1904`, sets `FB02=H'14`, and calls the `48FA` display/report bridge.
|
||||
- Selector `0x006D` dispatches to `H'3015`. Forced decoding shows it sets `F731.7`, loads `F798=H'C8`, sets `F795.6/F795.7`, sets display selector `F732=H'1903`, sets `FB02=H'64`, calls `48FA`, then sets `F76E.6`.
|
||||
- The LCD dispatch for these states is now traced: `loc_48FA` reads the high byte at `F732`, so `F732=H'1903/H'1904` selects display page `0x19`, not direct page `0x03/0x04`. `493E[0x19] -> H'930A`; that page's local table at `H'931C` includes `H'9F6A` for `COPY` / `IN PROGRESS` and `H'9FDA` for `COPY` / `COMPLETED`. The low byte at `F733` is the substate selector: `0x03` is in-progress and `0x04` is completed.
|
||||
- This makes the likely copy handshake: `0x006D` starts copy and sets the `F795.6/F795.7` in-progress flags; `0x006C` is the completion/exit sibling only when those flags are live. Sending `0x006C` alone can therefore blank or clear state instead of displaying `COPY COMPLETED`.
|
||||
- Bench step-through confirmed the sequence model: `006C` alone produced `CONNECT OK -> blank`; `006D` alone produced `CONNECT OK -> COPY IN PROGRESS`; `006D` followed by `006C` after 250 ms produced a brief `COPY IN PROGRESS` then `COPY COMPLETED`; the same after 1.0 s and 1.5 s produced a longer `COPY IN PROGRESS` then `COPY COMPLETED`; after 2.0 s or 2.5 s it fell to `CONNECT:NOT ACT` instead of completing. Repeating `006D` before `006C` also completed successfully in the 2x and 3x repeat tests. A longer `006D` hold test kept `COPY IN PROGRESS` active for several seconds and then completed when `006C` arrived, while the same hold without `006C` timed out from `COPY IN PROGRESS` to `CONNECT:NOT ACT`. This points to `006D` as an in-progress/progress-window refresh selector and `006C` as the explicit completion/exit selector, not a stateless command pair.
|
||||
- The FRT1 timer path decrements `F797` and `F798`; when either reaches zero, it clears `F731.7`. This matches the observed transient display modes falling back to `CONNECT:NOT ACT`.
|
||||
- The string `COPY IN PROGRESS` is present in the ROM LCD resources, so the `006D` result is not a generic serial artifact.
|
||||
- Manual interpretation: the RCP-TX7 operating manual describes `COPY IN PROGRESS` as the LCD state shown during the multi-camera `COPY TO SLAVES` data-transfer operation over the RS232C command-link system. During that state, all linked RCP units display the message and their buttons/knobs are locked until `COPY COMPLETED`. Therefore selector `0x006D` is best treated as entering a command-link copy/data-transfer state, not as a normal CCU connection ACK.
|
||||
|
||||
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.
|
||||
- Candidate gate probes, not final protocol truth:
|
||||
|
||||
```text
|
||||
00 01 0F 18 00 4C ; command 0, set E000[0x008F] bits 11+12
|
||||
06 00 15 00 01 48 ; command 6, set E400[0x0015] nonzero; requires live continuation
|
||||
06 00 15 80 00 C9 ; command 6, alternate nonzero visibility value; requires live continuation
|
||||
```
|
||||
|
||||
Read table state:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\serial_table_dump.py --port COM5 --relay-port COM6 --start 0x000 --count 0x200 --parity E --log captures\table-read-8e1.txt
|
||||
```
|
||||
|
||||
## Current Best Model Of Normal CCU/RCP Communication
|
||||
|
||||
The protocol looks like a shared selector table with stateful reporting:
|
||||
|
||||
1. CCU sends initial state seeds into selector tables, especially selector zero and status/display selectors.
|
||||
2. RCP updates LCD, lamps, and numeric readouts from selector dispatch handlers.
|
||||
3. RCP emits heartbeat/report frames from `E800` via the `F870 -> BAF2` report queue.
|
||||
4. Host/CCU uses continuation commands to consume/ACK/update live reports while `FAA2/FAA3` gates are active.
|
||||
5. If the CCU stops talking or session state expires, RCP clears volatile session state and returns to `CONNECT:NOT ACT`.
|
||||
|
||||
This fits the real panel behavior:
|
||||
|
||||
- Idle panel emits heartbeat.
|
||||
- Correct fake-CCU traffic can wake it to `CONNECT: OK`.
|
||||
- Without richer CCU state, readouts illuminate but show placeholders like `----`.
|
||||
|
||||
## Active-State Local-Control Watch
|
||||
|
||||
Bench evidence now suggests `CONNECT: OK` is maintained by an ongoing CCU refresh stream, not by one magic wake frame. This creates a useful local-control test: keep the RCP in the active state and press/turn physical controls while logging device TX.
|
||||
|
||||
Two JSON scenarios are set up for that:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\active-control-report-watch-quiet.json --parity E --log captures\active-control-report-watch-quiet.txt --result-json captures\active-control-report-watch-quiet-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\active-control-report-watch-broad.json --parity E --log captures\active-control-report-watch-broad.txt --result-json captures\active-control-report-watch-broad-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\active-control-report-watch-gated.json --parity E --log captures\active-control-report-watch-gated.txt --result-json captures\active-control-report-watch-gated-result.json
|
||||
```
|
||||
|
||||
The quiet scenario sends the selector-zero OK seed, then refreshes `E000[0x0093]=0x9020` every 0.60 s. This is the lowest-noise active hold that has already kept `CONNECT: OK` alive.
|
||||
|
||||
The broad scenario streams `E000[0x008F]=0x1800` and `E000[0x0093]=0xFFFF` every cycle. This is noisier, but may open more local-control/status gates.
|
||||
|
||||
The gated scenario first seeds candidate secondary-table feature bits with command 6:
|
||||
|
||||
```text
|
||||
06 00 15 80 00 C9 ; E400[0x0015] OTHERS/COPY visibility candidate
|
||||
06 01 0F 18 00 4A ; E400[0x008F] shutter/OTHERS bits 11+12
|
||||
06 01 13 FF FF 4E ; E400[0x0093] broad local-report/status gate candidate
|
||||
```
|
||||
|
||||
Then it streams `E000[0x008F]=0x1800` and `E000[0x0093]=0x90FF`. This is the better next watch if quiet/broad E000-only refreshes do not produce local-control TX.
|
||||
|
||||
## Bench Webcam Capture
|
||||
|
||||
For tests where LCD timing/state matters, `serial_scenario.py` can take webcam
|
||||
snapshots tied to exact TX commands. Current bench calibration:
|
||||
|
||||
```powershell
|
||||
--camera-index 4 --snapshot-delays 0.5
|
||||
```
|
||||
|
||||
Camera index `4` is the working panel-facing webcam on the current PC. A single
|
||||
`0.5` second post-TX delay captures readable LCD changes without creating the
|
||||
large image sets produced by `0,0.25,1.0`.
|
||||
|
||||
Example:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\copy-step-006d-006c-1000ms.json --parity E --quiet-console --log captures\copy-webcam.txt --result-json captures\copy-webcam-result.json --snapshot-dir captures\copy-webcam-shots --camera-index 4 --snapshot-delays 0.5
|
||||
```
|
||||
|
||||
After a run, summarize unexpected device frames with:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario_unexpected.py captures\active-control-report-watch-quiet.txt --show-all
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario_unexpected.py captures\active-control-report-watch-broad.txt --show-all
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario_unexpected.py captures\active-control-report-watch-gated.txt --show-all
|
||||
```
|
||||
|
||||
Expected refresh responses are ignored by default: heartbeat, table readbacks, and `02 00 02 00 00 5A`. Any remaining checksum-valid frame is a candidate local-control report. This is where physical button/dial reports should appear if the RCP only talks while the CCU keeps the selector tables active.
|
||||
|
||||
The unexpected-frame summarizer also labels known autonomous button frames so they are not mistaken for newly unlocked controls:
|
||||
|
||||
```text
|
||||
00 00 15 80 00 CF ; known CALL active report
|
||||
00 00 15 00 00 4F ; known CALL inactive report
|
||||
00 00 07 80 00 DD ; known CAM POWER report
|
||||
```
|
||||
|
||||
First quiet/broad watch captures on 2026-05-26 showed no unexpected checksum-valid frames in the observed window:
|
||||
|
||||
```text
|
||||
active-control-report-watch-quiet: 114 detected frames, all expected refresh/heartbeat/readback
|
||||
active-control-report-watch-broad: 133 detected frames, all expected refresh/heartbeat/readback
|
||||
```
|
||||
|
||||
Those runs stopped mid-scenario, so this is not a full negative proof. The practical interpretation is narrower: E000 active-state refresh alone did not make the pressed controls emit visible TX in the watched window. The gated command-6 version is the next ROM-supported test.
|
||||
|
||||
The first gated watch capture produced a new periodic active-state response:
|
||||
|
||||
```text
|
||||
02 00 04 00 00 5C ; gated 0x0004 transition candidate, seen twice
|
||||
01 00 04 00 00 5F ; gated 0x0004 active response candidate, seen 328 times
|
||||
```
|
||||
|
||||
After treating those as expected gated refresh traffic, the capture had zero novel frames. A direct search found no known CALL/CAM POWER frames in that log. So the gated setup changed the session/status response shape, but it did not yet prove that physical controls beyond the already-known autonomous buttons are reporting.
|
||||
|
||||
## Lamp Selector Mapping
|
||||
|
||||
Bench lamp sweeps now prove that several panel outputs are directly driven by command-0 selector writes while `CONNECT: OK` is alive. The current detailed map lives in `docs/pt2-lamp-selector-map.md`.
|
||||
|
||||
Newest confirmed behavior:
|
||||
|
||||
- `lamp-known-button-selector-probe` made CAM, CALL, BARS, MASTER, and camera tally outputs flash individually.
|
||||
- `0x0007 = 0x8000/0x0000` blinked CAM POWER in isolation.
|
||||
- `0x0015 = 0x8000/0x0000` blinked CALL and red tally in isolation.
|
||||
- Fresh-boot isolation maps `0x0013` to SLAVE, `0x0016` to green tally, and `0x0017` to BARS for the `0x8000/0x0000` value pair.
|
||||
- Fresh-boot isolation maps `0x0092` to iris AUTO/OFF behavior, and maps both `0x00B9` and `0x0110` to KNEE-related behavior.
|
||||
- A ROM trace now explains why the KNEE tests looked non-level-held. `loc_1795` is reached from the panel input lane (`F104 -> F692 -> F6F0.1`) and reads `E000[0x00B9]` plus `E000[0x0110]`.
|
||||
- The live KNEE value/report gate is `0x00B9.13`, not the earlier bench-only `0x00B9.15` guess.
|
||||
- `0x0110.15` forces a timed KNEE page/display override (`F732=0x1C03`, `FB02=0x14`), which matches the observed "lights, then clears" behavior.
|
||||
- On that KNEE LCD page, `0x0110.15` selects `DL`, `0x00B9.15` selects `PRESET`, and both clear selects `AUTO`.
|
||||
- When `0x00B9.13` is set and `0x0110.15` is clear, the ROM reports/updates selector `0x00BC` from the `F692 - F6B2` panel-input delta. See `docs/pt2-knee-rom-trace.md`.
|
||||
- The first KNEE ROM probe produced a new bench LCD state with `DTL` on the left and `KNEE` on the right, matching the ROM page-0x1C DETAIL/KNEE neighborhood.
|
||||
- A follow-up isolation lit the KNEE AUTO lamp in later KNEE windows but did not change the LCD. Current model: KNEE AUTO lamp/status is mostly selector driven, while the DETAIL/KNEE LCD page needs an additional local menu/display condition.
|
||||
|
||||
## What Is Still Unknown
|
||||
|
||||
- The official PT2 names for commands and selectors.
|
||||
- Which selectors drive every lamp and numeric display.
|
||||
- Whether the CCU sends a periodic refresh stream after CONNECT OK.
|
||||
- Exact hold time before OK falls back to NOT ACT, if no refresh traffic follows.
|
||||
- Whether command 4 CONNECT success depends on an existing continuation latch, timing, or a side effect created by earlier frames.
|
||||
- Whether the remaining emulator/bench mismatch is an SCI timing bug or a missing ROM/peripheral behavior. The emulator now has an optional 8E1 TX wire-timing mode; with it enabled, repeated `80` no longer immediately reaches `CONNECT: OK`, which is closer to bench behavior but still needs calibration.
|
||||
- How EEPROM option bits change selector behavior.
|
||||
- Whether all old visible `07...` families can be reproduced under `8E1`.
|
||||
|
||||
## Next Best Refinements
|
||||
|
||||
1. Finish the CONNECT matrix runs:
|
||||
- rerun `hold` with 700 ms gaps to measure how long OK remains without refresh traffic.
|
||||
2. Run the reactive advance sweep from OK and compare:
|
||||
- ACK-only `05 00 40 00 00 1F`
|
||||
- refresh/consume `04 00 00 80 00 DE`
|
||||
- command-5 special selectors `0x006C/0x006D/0x006E`
|
||||
3. Test whether periodic report ACKs plus periodic `80` refreshes hold CONNECT OK.
|
||||
4. Sweep emulator RX phase/gap with `--tx-wire-timing` and compare where `BD0E` is reached or missed.
|
||||
5. Dump selector table state before and after CONNECT OK.
|
||||
6. Seed selectors `0x003`, `0x040`, and `0x0F6` after selector-zero OK and watch lamps/readouts.
|
||||
7. Mine selector dispatch handlers for known UI text terms: `IRIS`, `GAIN`, `SHUTTER`, `BARS`, `BLACK`, `CALL`, `AUTO`, `DIAG`.
|
||||
8. Run the active-control watch scenarios and map any unexpected frames back to physical controls.
|
||||
|
||||
## Source Files And Reports
|
||||
|
||||
Generated evidence:
|
||||
|
||||
- `build/rom_decompiled.asm`
|
||||
- `build/rom_rx_branch_trace.txt`
|
||||
- `build/rom_ccu_seed_hints.txt`
|
||||
- `build/rom_eeprom_layout.txt`
|
||||
- `build/rom_table_xrefs.txt`
|
||||
- `build/connect-state-search-ok.json`
|
||||
|
||||
Useful tools:
|
||||
|
||||
- `h8536_protocol_trace.py`
|
||||
- `h8536_protocol_capture.py`
|
||||
- `h8536_rx_branch_trace.py`
|
||||
- `h8536_ccu_seed_hints.py`
|
||||
- `h8536_emulator_rx_probe.py`
|
||||
- `h8536_emulator_state_search.py`
|
||||
- `scripts/bench_connect_lcd_sequence.py`
|
||||
- `scripts/connect_ok_matrix.py`
|
||||
- `scripts/connect_ok_advance_sweep.py`
|
||||
- `scripts/serial_table_dump.py`
|
||||
- `scripts/serial_scenario.py`
|
||||
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.
|
||||
214
docs/pt2-shutter-display-trace.md
Normal file
214
docs/pt2-shutter-display-trace.md
Normal file
@@ -0,0 +1,214 @@
|
||||
# PT2 Shutter Display Trace
|
||||
|
||||
This note collects the current ROM evidence for the shutter seven-segment display and related selector traffic.
|
||||
|
||||
## Confirmed Bench Mapping
|
||||
|
||||
The real panel responds to primary selector `0x008F`:
|
||||
|
||||
| Command 0 write | Meaning candidate | Observed panel result |
|
||||
| --- | --- | --- |
|
||||
| `00 01 0F 08 00 5C` | `E000[0x008F].11` | SHUTTER shows observed `EUS`, likely manual `EVS`; iris AUTO lamp on |
|
||||
| `00 01 0F 10 00 44` | `E000[0x008F].12` | SHUTTER shows literal `OFF`; iris AUTO lamp on |
|
||||
| `00 01 0F 18 00 4C` | bits 11 and 12 | likely `EVS` wins over `OFF`; iris AUTO lamp on |
|
||||
| `00 01 0F 00 00 54` | live default/clear | in the short clear-control run, SHUTTER swapped to `OFF`, then back to `EVS` when bit 11 was restored |
|
||||
|
||||
Manual correlation:
|
||||
|
||||
- The RCP-TX7 manual has `OTHERS (1/6: SHUTTER)` with an `EVS` button.
|
||||
- The RCP-TX7 menu table lists `EVS/ECS` under OTHERS for DXC-D30/D30P.
|
||||
- A later CCU/RCP manual says the shutter display shows `EVS` when EVS is on and `OFF` when the shutter switch is off.
|
||||
|
||||
So `0x008F.11` is currently best labeled `shutter_evs_display_or_mode`. `0x008F.12` and `0x008F=0` both have `OFF` display evidence, so treat `OFF` as the live default/fallback shutter display unless a later bit-isolation run splits forced OFF from default OFF.
|
||||
|
||||
## Selector 0x008F ROM Path
|
||||
|
||||
Primary table address:
|
||||
|
||||
```text
|
||||
selector 0x008F -> E000 + 2 * 0x008F = H'E11E
|
||||
```
|
||||
|
||||
The OTHERS/SHUTTER menu handler is `H'6EE4`.
|
||||
|
||||
Important instructions:
|
||||
|
||||
```text
|
||||
6F6E: BTST.W #11, @H'E11E
|
||||
6F74: BSET.B #6, R0
|
||||
6F76: BTST.W #12, @H'E11E
|
||||
6F7C: BSET.B #4, R0
|
||||
6F7E: MOV:G.B R0, @H'F711
|
||||
```
|
||||
|
||||
This is the direct consumer seen so far. The current decompile does not show another static read of `H'E11E` outside this handler.
|
||||
|
||||
`H'6EE4` also programs local descriptor RAM before this:
|
||||
|
||||
```text
|
||||
6EFD: F73E = H'088F
|
||||
6F09: F74E = H'0800
|
||||
6F0F: F742 = H'088F
|
||||
6F1B: F752 = H'1000
|
||||
```
|
||||
|
||||
Those descriptors match selector `0x008F` plus the two observed masks `0x0800` and `0x1000`, so the generic panel-output updater also appears to know about the same selector.
|
||||
|
||||
## Local Panel Trigger Path
|
||||
|
||||
`H'6EE4` can also generate a selector `0x008F` report/update from local OTHERS/SHUTTER controls:
|
||||
|
||||
```text
|
||||
6F26: read F770 local action byte
|
||||
6F2E: keep low two action bits
|
||||
6F37: if action bit path and E400[0x008F].11 is enabled, set E800[0x008F] = 0x0800
|
||||
6F45: if alternate action path and E400[0x008F].12 is enabled, set E800[0x008F] = 0x1000
|
||||
6F53: R3 = 0x008F
|
||||
6F64: call 3E54 report/target-frame builder
|
||||
```
|
||||
|
||||
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`.
|
||||
|
||||
Candidate selectors:
|
||||
|
||||
| Handler | Source RAM | Gate | Selector sent | Meaning candidate |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `H'17C9` | `F6AE/F6CE` | `E000[0x0093].12` | `0x00A3` | clear-scan/shutter value lane |
|
||||
| `H'17FB` | `F6AC/F6CC` | `E000[0x0093].12` | `0x00A4` | clear-scan/shutter value lane |
|
||||
| `H'182D` | `F6AA/F6CA` | `E000[0x0093].5`, `F717.2` clear | `0x00A5` | shutter value lane |
|
||||
| `H'182D` | `F6AA/F6CA` | `F717.2` set | `0x00D8` | alternate/DXC-637 shutter lane |
|
||||
| `H'1891` | `F6A8/F6C8` | `E000[0x0093].5`, `F717.2` clear | `0x0080` | shutter value lane |
|
||||
| `H'1891` | `F6A8/F6C8` | `F717.2` set | `0x00D9` | alternate/DXC-637 shutter lane |
|
||||
| `H'18E7` | `F6A6/F6C6` | `E000[0x0093].5`, `F717.2` clear | `0x00A6` | shutter value lane |
|
||||
| `H'18E7` | `F6A6/F6C6` | `F717.2` set | `0x00DA` | alternate/DXC-637 shutter lane |
|
||||
| `H'194A` | `F6A4/F6C4` | `F731 <= 3` | `0x0080` | shared value lane |
|
||||
| `H'1979` | `F6A2/F6C2` plus `F68C` scale | `F731 <= 3` | `0x0081` | scaled analog value lane |
|
||||
|
||||
This cluster is a strong candidate for the numeric shutter speed / clear-scan frequency side of the display. It is not yet bench-confirmed.
|
||||
|
||||
ROM refinement:
|
||||
|
||||
- `F6AE/F6AC` are sampled from the external panel bus in the IRQ3 `A8` branch (`H'3CCB`), from `F00C/F00A`.
|
||||
- `F6AA/F6A8/F6A6/F6A4/F6A2` are sampled from the IRQ3 `A9` branch (`H'3C49`), from `F00C/F00A/F008/F006/F004`.
|
||||
- Those IRQ3 branches set dirty bits in `F6F1`, then the `H'15E0` scanner fans changes into the selector reports above.
|
||||
- Several lanes can OR bit 14 into the report selector when `F791` and `F404` feature bits are live. So emitted report traffic may carry a tagged variant of the base selector even though the table readback probes below use the base selector.
|
||||
- This makes the adjacent selector family more likely to be live local-panel state than a simple CCU-write display latch.
|
||||
|
||||
## Candidate Probe Frames
|
||||
|
||||
Readback:
|
||||
|
||||
```text
|
||||
01 01 0F 00 00 55 ; read 0x008F
|
||||
01 01 13 00 00 49 ; read 0x0093 gate/status
|
||||
01 01 23 00 00 79 ; read 0x00A3
|
||||
01 01 24 00 00 7E ; read 0x00A4
|
||||
01 01 25 00 00 7F ; read 0x00A5
|
||||
01 01 58 00 00 02 ; read 0x00D8
|
||||
01 01 00 00 00 5A ; read 0x0080
|
||||
01 01 59 00 00 03 ; read 0x00D9
|
||||
01 01 26 00 00 7C ; read 0x00A6
|
||||
01 01 5A 00 00 00 ; read 0x00DA
|
||||
01 01 01 00 00 5B ; read 0x0081
|
||||
```
|
||||
|
||||
Potential display probes after `CONNECT: OK`:
|
||||
|
||||
```text
|
||||
00 01 0F 00 00 54 ; clear selector 0x008F
|
||||
00 01 13 80 00 C8 ; set 0x0093 high bit candidate
|
||||
00 01 13 FF FF 48 ; enable all 0x0093 gates candidate
|
||||
```
|
||||
|
||||
Use the value-lane selectors cautiously. They may represent shutter/clear-scan numeric values, but they are also part of the local control-report path, so bench probing should change one selector at a time and record LCD, shutter display, iris AUTO, and emitted report frames.
|
||||
|
||||
Important methodology caveat:
|
||||
|
||||
- `CONNECT:NOT ACT` globally clears volatile panel presentation. A blank LCD/segment result after a long wait is not evidence that a tested selector cleared the panel.
|
||||
- For selector-display tests, record the visible state inside the short post-write window, before the session can fall back to `NOT ACT`.
|
||||
- Use the timeout-control scenario below to measure the current bench's natural EVS-to-NOT-ACT cleanup time. Treat results after that point as timeout-contaminated.
|
||||
- Re-seed `CONNECT: OK` immediately before gate writes when a prior readback sweep may have consumed enough time for the visible state to expire.
|
||||
|
||||
## Adjacent Selector Bench Scenarios
|
||||
|
||||
These JSON scenarios are set up for the current bench runner and default to `38400 8E1`:
|
||||
|
||||
```text
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\shutter-adjacent-readback.json --parity E --log captures\shutter-adjacent-readback.txt --result-json captures\shutter-adjacent-readback-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\shutter-008f-evs-timeout-control.json --parity E --log captures\shutter-008f-evs-timeout-control.txt --result-json captures\shutter-008f-evs-timeout-control-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\shutter-008f-evs-clear-control.json --parity E --log captures\shutter-008f-evs-clear-control.txt --result-json captures\shutter-008f-evs-clear-control-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\shutter-0093-gate-8000.json --parity E --log captures\shutter-0093-gate-8000.txt --result-json captures\shutter-0093-gate-8000-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\shutter-0093-gate-ffff.json --parity E --log captures\shutter-0093-gate-ffff.txt --result-json captures\shutter-0093-gate-ffff-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\shutter-0093-bit-isolation.json --parity E --log captures\shutter-0093-bit-isolation.txt --result-json captures\shutter-0093-bit-isolation-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\shutter-0093-blackflare-auto-candidates.json --parity E --log captures\shutter-0093-blackflare-auto-candidates.txt --result-json captures\shutter-0093-blackflare-auto-candidates-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\shutter-0093-blackflare-slow-marked.json --parity E --log captures\shutter-0093-blackflare-slow-marked.txt --result-json captures\shutter-0093-blackflare-slow-marked-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\shutter-0093-blackflare-field-groups.json --parity E --log captures\shutter-0093-blackflare-field-groups.txt --result-json captures\shutter-0093-blackflare-field-groups-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\shutter-0093-blackflare-field-confirm.json --parity E --log captures\shutter-0093-blackflare-field-confirm.txt --result-json captures\shutter-0093-blackflare-field-confirm-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\shutter-0093-blackflare-field-stream-confirm.json --parity E --log captures\shutter-0093-blackflare-field-stream-confirm.txt --result-json captures\shutter-0093-blackflare-field-stream-confirm-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\shutter-0093-blackflare-confirm-f020.json --parity E --log captures\shutter-0093-blackflare-confirm-f020.txt --result-json captures\shutter-0093-blackflare-confirm-f020-result.json
|
||||
-Manual-auto-manual
|
||||
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\shutter-0093-blackflare-confirm-ff20.json --parity E --log captures\shutter-0093-blackflare-confirm-ff20.txt --result-json captures\shutter-0093-blackflare-confirm-ff20-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\shutter-0093-blackflare-confirm-9f20.json --parity E --log captures\shutter-0093-blackflare-confirm-9f20.txt --result-json captures\shutter-0093-blackflare-confirm-9f20-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\shutter-0093-blackflare-confirm-90ff.json --parity E --log captures\shutter-0093-blackflare-confirm-90ff.txt --result-json captures\shutter-0093-blackflare-confirm-90ff-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\shutter-0093-blackflare-confirm-9fff.json --parity E --log captures\shutter-0093-blackflare-confirm-9fff.txt --result-json captures\shutter-0093-blackflare-confirm-9fff-result.json
|
||||
.\.venv\Scripts\python.exe scripts\serial_scenario.py scenarios\shutter-0093-blackflare-lowbyte-groups.json --parity E --log captures\shutter-0093-blackflare-lowbyte-groups.txt --result-json captures\shutter-0093-blackflare-lowbyte-groups-result.json
|
||||
```
|
||||
|
||||
Run order:
|
||||
|
||||
1. `shutter-adjacent-readback.json`: read-only baseline for the adjacent shutter cluster after the selector-zero `CONNECT: OK` seed.
|
||||
2. `shutter-008f-evs-timeout-control.json`: measures how long EVS survives before `CONNECT:NOT ACT` clears it with no explicit clear command.
|
||||
3. `shutter-008f-evs-clear-control.json`: checks whether the EVS/OFF display selector can be cleared live inside the safe pre-timeout window.
|
||||
4. `shutter-0093-gate-8000.json`: tests the ROM-observed `0x0093` high-bit gate without enabling every unknown bit.
|
||||
5. `shutter-0093-gate-ffff.json`: broader gate test if the targeted high-bit run is uneventful.
|
||||
6. `shutter-0093-bit-isolation.json`: isolates the `0x0093` bits after bench evidence showed this selector also controls white-balance and black/flare lamps.
|
||||
7. `shutter-0093-blackflare-auto-candidates.json`: uses the known `0x9020` black/flare-manual context and adds each remaining bit to hunt for the `0xFFFF` black/flare-AUTO effect.
|
||||
8. `shutter-0093-blackflare-slow-marked.json`: repeats the hunt without clear/OK resets between candidates, so white-balance should flicker less and black/flare AUTO transitions can be matched to candidate holds.
|
||||
9. `shutter-0093-blackflare-field-groups.json`: tests multi-bit field groups after the slow-marked run suggested black/flare AUTO is not one single extra bit over `0x9020`.
|
||||
10. `shutter-0093-blackflare-field-confirm.json`: shorter, longer-hold confirmation of the broad field groups after the first field-groups run produced three MANUAL->AUTO->MANUAL swaps.
|
||||
11. `shutter-0093-blackflare-field-stream-confirm.json`: repeats each candidate every 0.60 s after the longer-hold confirmation fell into `CONNECT:NOT ACT`, testing the CCU-refresh model directly.
|
||||
12. `shutter-0093-blackflare-confirm-*.json`: one-candidate streamed confirmations. Each run includes a known `0xFFFF` AUTO positive control, then brackets one candidate with `0x9020` manual context. After the positive-control section, the expected candidate pattern is MANUAL -> AUTO -> MANUAL -> AUTO -> MANUAL only if that candidate drives black/flare AUTO.
|
||||
13. `shutter-0093-blackflare-lowbyte-groups.json`: keeps the high byte fixed at `0x90` and varies only the low byte, after `0x90FF` and `0x9FFF` both toggled black/flare AUTO.
|
||||
|
||||
## Bench Observations 2026-05-26
|
||||
|
||||
Observed visible effects from the first adjacent-selector run set:
|
||||
|
||||
| Scenario | Serial evidence | Observed panel result | Current interpretation |
|
||||
| --- | --- | --- | --- |
|
||||
| `shutter-adjacent-readback` | all read selectors returned value `0x0000` | no specific visible note | baseline cluster was clear |
|
||||
| `shutter-0093-gate-8000` | `E000[0x0093]` read back as `0x8000` | white-balance PRESET lamp on, black/flare MANUAL lamp on | `0x0093.15` is a live panel-status/lamp bit, not just a shutter gate |
|
||||
| `shutter-0093-gate-ffff` | `E000[0x0093]` read back as `0xFFFF` | white-balance PRESET lamp on, black/flare AUTO lamp on | another `0x0093` bit overrides/selects black/flare AUTO when all bits are set |
|
||||
| `shutter-0093-bit-isolation` | stepped through `0x1000`, `0x0020`, `0x1020`, `0x8000`, `0x8020`, `0x9000`, `0x9020` | white-balance lamps swapped between MANUAL and PRESET; black/flare stayed MANUAL | bit 15 remains the prime white-balance PRESET candidate; black/flare AUTO is likely outside bits 15/12/5 |
|
||||
| `shutter-0093-blackflare-auto-candidates` | stepped through `0x9020`, `0xFFFF`, then `0x9020` plus each remaining bit | black/flare swapped AUTO/MANUAL more slowly than white-balance MANUAL/PRESET | the clear/OK reset before each candidate likely caused extra white-balance flicker; use the slow-marked follow-up to map black/flare transitions to exact bits |
|
||||
| `shutter-0093-blackflare-slow-marked` | held `0x9020`, `0xFFFF`, then alternated `0x9020` with each candidate | white-balance stayed stable, black/flare swapped twice with large pauses; panel stayed `CONNECT: OK` throughout | likely only the manual-reference to `0xFFFF` and `0xFFFF` back to `0x9020` changed black/flare, so AUTO is probably a multi-bit field rather than one added bit |
|
||||
| `shutter-0093-blackflare-field-groups` | held broad grouped values such as `0xF020`, `0xFF20`, `0x9F20`, `0x90FF`, `0x9FFF` | black/flare made three MANUAL->AUTO->MANUAL swaps | broad field combinations can produce black/flare AUTO; use the shorter confirmation run to identify which grouped windows caused the swaps |
|
||||
| `shutter-0093-blackflare-field-confirm` | held `0xFFFF` for 2.8 s, then candidate groups | one MANUAL->AUTO transition at the start, then `CONNECT:NOT ACT`; PRESET white-balance lamp briefly flashed a few times while inactive | a silent 2.8 s hold is too long; traffic must be refreshed, and some lamp latch/update paths can still flash during inactive display cleanup |
|
||||
| `shutter-0093-blackflare-field-stream-confirm` | streamed every candidate at 0.60 s and saw 148 `02 00 02 00 00 5A` OK-path responses with no resync errors | manual/auto/manual groups were visible, then `CONNECT:NOT ACT` after the stream ended | the stream itself kept OK alive; the final inactive state is likely just the refresh stopping. Candidate isolation needs streamed, one-candidate tests |
|
||||
| `shutter-0093-blackflare-confirm-f020`, `ff20`, `9f20` | each completed cleanly with 137 OK-path responses and no resync errors | MANUAL->AUTO->MANUAL only | only the built-in `0xFFFF` positive control produced AUTO; these candidates did not drive black/flare AUTO by themselves |
|
||||
| `shutter-0093-blackflare-confirm-90ff`, `9fff` | each completed cleanly with 137 OK-path responses and no resync errors | black/flare went back and forth a couple of times | `0x90FF` is sufficient to drive the AUTO effect, so the black/flare field is likely in the low byte of `0x0093`; `0x9FFF` is a superset rather than a separate high-byte requirement |
|
||||
| `shutter-008f-evs-clear-control` | `0x008F` writes acknowledged as `0x0800`, `0x0000`, `0x0800` | SHUTTER swapped between EVS and OFF while iris AUTO lamp stayed on | `0x008F` is a packed shutter/display status word; clearing it does not simply mean "blank" |
|
||||
| `shutter-008f-evs-timeout-control` | only `0x008F=0x0800` was sent after OK seed | EVS/iris AUTO, then `CONNECT:NOT ACT` | later blanking is timeout cleanup, not selector-clear evidence |
|
||||
|
||||
This changes the local naming: the "adjacent shutter" group should be treated as a broader camera-status and panel-output word cluster. `0x008F` currently covers shutter EVS/OFF plus iris AUTO side effects; `0x0093` covers at least white-balance manual/preset and black/flare manual/auto side effects, and still gates some ROM-observed shutter/clear-scan report lanes. Current black/flare evidence points to `0x0093` high byte `0x90` as enough context, with the low byte selecting the black/flare MANUAL/AUTO state.
|
||||
@@ -12,6 +12,7 @@ from typing import Iterable, TextIO
|
||||
|
||||
CHECKSUM_SEED = 0x5A
|
||||
FRAME_LENGTH = 6
|
||||
SERIAL_PARITY_CHOICES = ("N", "E", "O")
|
||||
|
||||
CONNECT_LCD_SEQUENCE = (
|
||||
bytes.fromhex("04000040001E"),
|
||||
@@ -23,12 +24,22 @@ COMMAND7_REPEAT_FRAME = bytes.fromhex("07000000005D")
|
||||
|
||||
@dataclass
|
||||
class FrameDetector:
|
||||
sync_mode: str = "checksum"
|
||||
buffer: bytearray = field(default_factory=bytearray)
|
||||
frames: list[bytes] = field(default_factory=list)
|
||||
labels: Counter[str] = field(default_factory=Counter)
|
||||
dropped_bytes: int = 0
|
||||
resync_events: int = 0
|
||||
|
||||
def feed(self, data: bytes) -> list[tuple[bytes, str]]:
|
||||
self.buffer.extend(data)
|
||||
if self.sync_mode == "fixed":
|
||||
return self._feed_fixed()
|
||||
if self.sync_mode != "checksum":
|
||||
raise ValueError(f"unknown frame sync mode {self.sync_mode!r}")
|
||||
return self._feed_checksum_resync()
|
||||
|
||||
def _feed_fixed(self) -> list[tuple[bytes, str]]:
|
||||
detected = []
|
||||
while len(self.buffer) >= FRAME_LENGTH:
|
||||
frame = bytes(self.buffer[:FRAME_LENGTH])
|
||||
@@ -40,6 +51,35 @@ class FrameDetector:
|
||||
detected.append((frame, label))
|
||||
return detected
|
||||
|
||||
def _feed_checksum_resync(self) -> list[tuple[bytes, str]]:
|
||||
detected = []
|
||||
while len(self.buffer) >= FRAME_LENGTH:
|
||||
offset = _next_sync_offset(self.buffer)
|
||||
if offset is None:
|
||||
self._drop_unsynced_prefix(len(self.buffer) - (FRAME_LENGTH - 1))
|
||||
break
|
||||
if offset:
|
||||
self._drop_unsynced_prefix(offset)
|
||||
frame = bytes(self.buffer[:FRAME_LENGTH])
|
||||
if not frame_checksum_ok(frame):
|
||||
self._drop_unsynced_prefix(1)
|
||||
continue
|
||||
del self.buffer[:FRAME_LENGTH]
|
||||
label = label_frame(frame)
|
||||
self.frames.append(frame)
|
||||
if label:
|
||||
self.labels[label] += 1
|
||||
detected.append((frame, label))
|
||||
return detected
|
||||
|
||||
def _drop_unsynced_prefix(self, count: int) -> None:
|
||||
count = max(0, min(count, len(self.buffer)))
|
||||
if not count:
|
||||
return
|
||||
del self.buffer[:count]
|
||||
self.dropped_bytes += count
|
||||
self.resync_events += 1
|
||||
|
||||
|
||||
class BenchLogger:
|
||||
def __init__(self, path: Path, stdout: TextIO = sys.stdout) -> None:
|
||||
@@ -101,21 +141,93 @@ def format_frame(data: bytes) -> str:
|
||||
def label_frame(frame: bytes) -> str:
|
||||
labels = {
|
||||
bytes.fromhex("0000000080DA"): "heartbeat",
|
||||
bytes.fromhex("00000080805A"): "active_selector0_keepalive_report",
|
||||
bytes.fromhex("00006C000036"): "copy_completion_exit_selector_006c_candidate",
|
||||
bytes.fromhex("00006D000037"): "copy_in_progress_selector_006d_candidate",
|
||||
bytes.fromhex("02000200005A"): "connect_ok_path_response_candidate",
|
||||
bytes.fromhex("010002000059"): "connect_c0_path_response_candidate",
|
||||
bytes.fromhex("07804040A07D"): "visible_40A0_family_40",
|
||||
bytes.fromhex("07808040A0BD"): "visible_40A0_family_80",
|
||||
bytes.fromhex("0780C040A0FD"): "visible_40A0_family_C0",
|
||||
bytes.fromhex("07804020902D"): "visible_retry_0040_2090_candidate",
|
||||
bytes.fromhex("0780C060205D"): "visible_C0_6020_family_candidate",
|
||||
bytes.fromhex("0000158000CF"): "known_call_button_active_report",
|
||||
bytes.fromhex("00001500004F"): "known_call_button_inactive_report",
|
||||
bytes.fromhex("0000078000DD"): "known_cam_power_button_report",
|
||||
bytes.fromhex("000013000049"): "known_iris_mblack_link_clear_report_candidate",
|
||||
bytes.fromhex("000013400009"): "known_iris_mblack_link_active_report_candidate",
|
||||
bytes.fromhex("0000138000C9"): "known_selector_0013_bit15_report_candidate",
|
||||
bytes.fromhex("000013C00089"): "known_selector_0013_bit15_plus_iris_mblack_link_report_candidate",
|
||||
bytes.fromhex("00010F8000D4"): "known_shutter_onoff_bit7_report_candidate",
|
||||
bytes.fromhex("00010F200074"): "known_shutter_onoff_bit6_report_candidate",
|
||||
bytes.fromhex("00010F000054"): "known_shutter_onoff_clear_report_candidate",
|
||||
bytes.fromhex("010013000048"): "queued_iris_mblack_link_clear_report_candidate",
|
||||
bytes.fromhex("02001300004B"): "queued_iris_mblack_link_clear_report_candidate",
|
||||
bytes.fromhex("010013400008"): "queued_iris_mblack_link_active_report_candidate",
|
||||
bytes.fromhex("02001340000B"): "queued_iris_mblack_link_active_report_candidate",
|
||||
bytes.fromhex("0100138000C8"): "queued_selector_0013_bit15_report_candidate",
|
||||
bytes.fromhex("0200138000CB"): "queued_selector_0013_bit15_report_candidate",
|
||||
bytes.fromhex("010013C00088"): "queued_selector_0013_bit15_plus_iris_mblack_link_report_candidate",
|
||||
bytes.fromhex("020013C0008B"): "queued_selector_0013_bit15_plus_iris_mblack_link_report_candidate",
|
||||
bytes.fromhex("01010F8000D5"): "queued_shutter_onoff_bit7_report_candidate",
|
||||
bytes.fromhex("02010F8000D6"): "queued_shutter_onoff_bit7_report_candidate",
|
||||
bytes.fromhex("01010F200075"): "queued_shutter_onoff_bit6_report_candidate",
|
||||
bytes.fromhex("02010F200076"): "queued_shutter_onoff_bit6_report_candidate",
|
||||
bytes.fromhex("01010F000055"): "queued_shutter_onoff_clear_report_candidate",
|
||||
bytes.fromhex("02010F000056"): "queued_shutter_onoff_clear_report_candidate",
|
||||
bytes.fromhex("0100178000CC"): "queued_bars_button_selector_0017_active_candidate",
|
||||
bytes.fromhex("0200178000CF"): "queued_bars_button_selector_0017_active_candidate",
|
||||
bytes.fromhex("0100188000C3"): "queued_bars_button_selector_0018_active_candidate",
|
||||
bytes.fromhex("0200188000C0"): "queued_bars_button_selector_0018_active_candidate",
|
||||
bytes.fromhex("01011A080048"): "queued_iris_auto_button_selector_009a_active_candidate",
|
||||
bytes.fromhex("02011A08004B"): "queued_iris_auto_button_selector_009a_active_candidate",
|
||||
bytes.fromhex("01000400005F"): "gated_active_0004_response_candidate",
|
||||
bytes.fromhex("02000400005C"): "gated_active_0004_transition_candidate",
|
||||
}
|
||||
label = labels.get(frame, "")
|
||||
if label:
|
||||
return label
|
||||
if frame_checksum_ok(frame):
|
||||
if frame[0] == 0x04:
|
||||
return "table_readback_candidate"
|
||||
if frame[0] == 0x07:
|
||||
return "visible_report_candidate"
|
||||
return "checksum_ok_unlabeled"
|
||||
return "checksum_bad_or_unaligned"
|
||||
|
||||
|
||||
def _next_sync_offset(buffer: bytearray) -> int | None:
|
||||
scored_offsets: list[tuple[int, int]] = []
|
||||
for offset in range(0, len(buffer) - FRAME_LENGTH + 1):
|
||||
frame = bytes(buffer[offset : offset + FRAME_LENGTH])
|
||||
if not frame_checksum_ok(frame):
|
||||
continue
|
||||
if offset == 0 and not _looks_like_shifted_heartbeat(frame):
|
||||
return 0
|
||||
label = label_frame(frame)
|
||||
scored_offsets.append((_sync_score(frame, label), offset))
|
||||
if not scored_offsets:
|
||||
return None
|
||||
return min(scored_offsets)[1]
|
||||
|
||||
|
||||
def _sync_score(frame: bytes, label: str) -> int:
|
||||
if label and label not in {"checksum_ok_unlabeled", "checksum_bad_or_unaligned"}:
|
||||
return 0
|
||||
if frame[0] in {0x00, 0x02, 0x04, 0x07}:
|
||||
return 100
|
||||
return 200
|
||||
|
||||
|
||||
def _looks_like_shifted_heartbeat(frame: bytes) -> bool:
|
||||
return frame in {
|
||||
bytes.fromhex("00000080DA00"),
|
||||
bytes.fromhex("000080DA0000"),
|
||||
bytes.fromhex("0080DA000000"),
|
||||
bytes.fromhex("80DA00000000"),
|
||||
}
|
||||
|
||||
|
||||
def default_log_path() -> Path:
|
||||
return Path("captures") / f"bench-connect-lcd-sequence-{datetime.now().strftime('%Y%m%d-%H%M%S')}.txt"
|
||||
|
||||
@@ -126,6 +238,7 @@ def build_arg_parser() -> argparse.ArgumentParser:
|
||||
)
|
||||
parser.add_argument("--port", default="COM5", help="RS232 serial port connected to the RCP")
|
||||
parser.add_argument("--baud", type=int, default=38400, help="RCP serial baud rate")
|
||||
add_serial_format_args(parser)
|
||||
parser.add_argument("--relay-port", default="COM6", help="Pico relay serial port")
|
||||
parser.add_argument("--relay-baud", type=int, default=115200, help="Pico relay serial baud rate")
|
||||
parser.add_argument("--no-power-cycle", action="store_true", help="do not send relay off/on before the test")
|
||||
@@ -140,6 +253,7 @@ def build_arg_parser() -> argparse.ArgumentParser:
|
||||
parser.add_argument("--post-sequence-read", type=float, default=3.0, help="seconds to listen after the sequence")
|
||||
parser.add_argument("--repeat", type=int, default=1, help="times to send the frame sequence in the same power session")
|
||||
parser.add_argument("--frame", action="append", type=parse_frame, help="override preset with a custom frame; repeatable")
|
||||
parser.add_argument("--sync", choices=("checksum", "fixed"), default="checksum", help="RX frame sync strategy")
|
||||
parser.add_argument("--two-frame", action="store_true", help="send only the first two CONNECT candidate frames")
|
||||
parser.add_argument("--command7-after", action="store_true", help="send command-7 repeat probe after the sequence")
|
||||
parser.add_argument("--pre-sequence-drain", type=float, default=0.250, help="seconds to drain/log RX immediately before sending")
|
||||
@@ -156,7 +270,7 @@ def main(argv: list[str] | None = None, *, stdout: TextIO = sys.stdout) -> int:
|
||||
log_path = args.log or default_log_path()
|
||||
|
||||
if args.dry_run:
|
||||
print(f"device={args.port} {args.baud} 8N1", file=stdout)
|
||||
print(f"device={args.port} {args.baud} {serial_format_label(args)}", file=stdout)
|
||||
print(f"relay={args.relay_port} {args.relay_baud}", file=stdout)
|
||||
print(f"power_cycle={int(not args.no_power_cycle)} off={args.power_off_command!r} on={args.power_on_command!r}", file=stdout)
|
||||
for index, frame in enumerate(frames, start=1):
|
||||
@@ -168,15 +282,18 @@ def main(argv: list[str] | None = None, *, stdout: TextIO = sys.stdout) -> int:
|
||||
|
||||
serial = _import_serial()
|
||||
logger = BenchLogger(log_path, stdout=stdout)
|
||||
detector = FrameDetector()
|
||||
detector = FrameDetector(sync_mode=args.sync)
|
||||
try:
|
||||
logger.emit("CONNECT LCD bench sequence")
|
||||
logger.emit(f"device={args.port} {args.baud} 8N1 relay={args.relay_port} {args.relay_baud}")
|
||||
logger.emit(
|
||||
f"device={args.port} {args.baud} {serial_format_label(args)} "
|
||||
f"relay={args.relay_port} {args.relay_baud}"
|
||||
)
|
||||
logger.emit(f"log={log_path}")
|
||||
for index, frame in enumerate(frames, start=1):
|
||||
logger.emit(f"plan frame[{index}]={format_frame(frame)} checksum_ok={int(frame_checksum_ok(frame))}")
|
||||
|
||||
with serial.Serial(args.port, args.baud, bytesize=8, parity="N", stopbits=1, timeout=0.05) as device:
|
||||
with open_device_serial(serial, args) as device:
|
||||
relay = None
|
||||
try:
|
||||
if not args.no_power_cycle:
|
||||
@@ -185,7 +302,7 @@ def main(argv: list[str] | None = None, *, stdout: TextIO = sys.stdout) -> int:
|
||||
_relay_command(relay, args.power_off_command, logger)
|
||||
time.sleep(args.off_seconds)
|
||||
device.reset_input_buffer()
|
||||
detector = FrameDetector()
|
||||
detector = FrameDetector(sync_mode=args.sync)
|
||||
_relay_command(relay, args.power_on_command, logger)
|
||||
else:
|
||||
device.reset_input_buffer()
|
||||
@@ -242,6 +359,23 @@ def _import_serial():
|
||||
return serial
|
||||
|
||||
|
||||
def add_serial_format_args(parser: argparse.ArgumentParser) -> None:
|
||||
parser.add_argument(
|
||||
"--parity",
|
||||
choices=SERIAL_PARITY_CHOICES,
|
||||
default="E",
|
||||
help="serial parity for the RCP link; ROM SCI1 setup uses even parity",
|
||||
)
|
||||
|
||||
|
||||
def serial_format_label(args: argparse.Namespace) -> str:
|
||||
return f"8{args.parity}1"
|
||||
|
||||
|
||||
def open_device_serial(serial, args: argparse.Namespace):
|
||||
return serial.Serial(args.port, args.baud, bytesize=8, parity=args.parity, stopbits=1, timeout=0.05)
|
||||
|
||||
|
||||
def _send_frame(device, frame: bytes, logger: BenchLogger, label: str) -> None:
|
||||
device.write(frame)
|
||||
device.flush()
|
||||
@@ -255,9 +389,16 @@ def _read_for(device, detector: FrameDetector, logger: BenchLogger, seconds: flo
|
||||
waiting = getattr(device, "in_waiting", 0)
|
||||
data = device.read(waiting or 1)
|
||||
if data:
|
||||
dropped_before = detector.dropped_bytes
|
||||
logger.chunk("RX", data)
|
||||
for frame, label in detector.feed(data):
|
||||
logger.event(f"DETECT {label} {format_frame(frame)}")
|
||||
dropped_now = detector.dropped_bytes - dropped_before
|
||||
if dropped_now:
|
||||
logger.event(
|
||||
f"RESYNC dropped_bytes={dropped_now} total_dropped={detector.dropped_bytes} "
|
||||
f"buffered={len(detector.buffer)}"
|
||||
)
|
||||
|
||||
|
||||
def _wait_for_ready(
|
||||
@@ -309,6 +450,7 @@ def _summary(detector: FrameDetector, logger: BenchLogger) -> None:
|
||||
logger.emit()
|
||||
logger.emit("Summary")
|
||||
logger.emit(f"rx_frames={len(detector.frames)} trailing_unframed_bytes={len(detector.buffer)}")
|
||||
logger.emit(f"resync_events={detector.resync_events} dropped_bytes={detector.dropped_bytes}")
|
||||
for label, count in sorted(detector.labels.items()):
|
||||
logger.emit(f"{label}={count}")
|
||||
|
||||
|
||||
168
h8536/camera_snapshots.py
Normal file
168
h8536/camera_snapshots.py
Normal file
@@ -0,0 +1,168 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import heapq
|
||||
import threading
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
_SAFE_NAME_RE = re.compile(r"[^A-Za-z0-9_.-]+")
|
||||
|
||||
|
||||
class CameraSnapshots:
|
||||
"""Small optional OpenCV webcam wrapper for bench-test snapshots."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
camera_index: int,
|
||||
output_dir: Path,
|
||||
warmup_seconds: float = 0.5,
|
||||
width: int | None = None,
|
||||
height: int | None = None,
|
||||
) -> None:
|
||||
self.camera_index = camera_index
|
||||
self.output_dir = output_dir
|
||||
self.warmup_seconds = max(0.0, warmup_seconds)
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.cv2: Any | None = None
|
||||
self.device: Any | None = None
|
||||
self._condition = threading.Condition()
|
||||
self._tasks: list[tuple[float, int, dict[str, Any]]] = []
|
||||
self._records: list[dict[str, Any]] = []
|
||||
self._thread: threading.Thread | None = None
|
||||
self._seq = 0
|
||||
self._closing = False
|
||||
|
||||
def open(self) -> None:
|
||||
try:
|
||||
import cv2
|
||||
except ImportError as exc: # pragma: no cover - depends on local bench environment.
|
||||
raise SystemExit(
|
||||
"OpenCV is required for webcam snapshots. Install it with: "
|
||||
".\\.venv\\Scripts\\python.exe -m pip install opencv-python"
|
||||
) from exc
|
||||
|
||||
self.output_dir.mkdir(parents=True, exist_ok=True)
|
||||
self.cv2 = cv2
|
||||
self.device = cv2.VideoCapture(self.camera_index)
|
||||
if not self.device.isOpened():
|
||||
raise SystemExit(f"could not open webcam index {self.camera_index}")
|
||||
if self.width:
|
||||
self.device.set(cv2.CAP_PROP_FRAME_WIDTH, self.width)
|
||||
if self.height:
|
||||
self.device.set(cv2.CAP_PROP_FRAME_HEIGHT, self.height)
|
||||
self._warm_up()
|
||||
self._thread = threading.Thread(target=self._run, name="camera-snapshots", daemon=True)
|
||||
self._thread.start()
|
||||
|
||||
def close(self) -> None:
|
||||
with self._condition:
|
||||
self._closing = True
|
||||
self._condition.notify_all()
|
||||
if self._thread is not None:
|
||||
self._thread.join()
|
||||
self._thread = None
|
||||
if self.device is not None:
|
||||
self.device.release()
|
||||
self.device = None
|
||||
|
||||
def schedule(
|
||||
self,
|
||||
*,
|
||||
label: str,
|
||||
frame_text: str,
|
||||
phase: str,
|
||||
delay_seconds: float = 0.0,
|
||||
step_index: int | None = None,
|
||||
) -> dict[str, Any]:
|
||||
if self.cv2 is None or self.device is None:
|
||||
raise RuntimeError("camera snapshotter is not open")
|
||||
|
||||
due_monotonic = time.monotonic() + max(0.0, delay_seconds)
|
||||
due_timestamp = datetime.now() + timedelta(seconds=max(0.0, delay_seconds))
|
||||
timestamp = due_timestamp.strftime("%Y%m%d-%H%M%S-%f")[:-3]
|
||||
step_part = f"step{step_index:03d}_" if step_index is not None else ""
|
||||
frame_part = frame_text.replace(" ", "")
|
||||
filename = _safe_name(f"{timestamp}_{step_part}{phase}_{label}_{frame_part}.jpg")
|
||||
path = self.output_dir / filename
|
||||
record: dict[str, Any] = {
|
||||
"path": str(path),
|
||||
"scheduled_timestamp": timestamp,
|
||||
"camera_index": self.camera_index,
|
||||
"step_index": step_index,
|
||||
"phase": phase,
|
||||
"delay_seconds": delay_seconds,
|
||||
"label": label,
|
||||
"frame": frame_text,
|
||||
"status": "scheduled",
|
||||
}
|
||||
with self._condition:
|
||||
self._seq += 1
|
||||
heapq.heappush(self._tasks, (due_monotonic, self._seq, record))
|
||||
self._records.append(record)
|
||||
self._condition.notify_all()
|
||||
return record
|
||||
|
||||
def records(self) -> list[dict[str, Any]]:
|
||||
with self._condition:
|
||||
return [dict(record) for record in self._records]
|
||||
|
||||
def _run(self) -> None:
|
||||
while True:
|
||||
with self._condition:
|
||||
while not self._tasks and not self._closing:
|
||||
self._condition.wait()
|
||||
if not self._tasks and self._closing:
|
||||
return
|
||||
due_monotonic, _seq, record = self._tasks[0]
|
||||
wait_seconds = due_monotonic - time.monotonic()
|
||||
if wait_seconds > 0:
|
||||
self._condition.wait(wait_seconds)
|
||||
continue
|
||||
heapq.heappop(self._tasks)
|
||||
self._write_snapshot(record)
|
||||
|
||||
def _write_snapshot(self, record: dict[str, Any]) -> None:
|
||||
if self.cv2 is None or self.device is None:
|
||||
record["status"] = "error"
|
||||
record["error"] = "camera closed before capture"
|
||||
return
|
||||
|
||||
image = None
|
||||
ok = False
|
||||
for _attempt in range(3):
|
||||
ok, image = self.device.read()
|
||||
if ok:
|
||||
break
|
||||
time.sleep(0.020)
|
||||
if not ok or image is None:
|
||||
record["status"] = "error"
|
||||
record["error"] = f"webcam index {self.camera_index} did not return an image"
|
||||
return
|
||||
|
||||
path = Path(str(record["path"]))
|
||||
if not self.cv2.imwrite(str(path), image):
|
||||
record["status"] = "error"
|
||||
record["error"] = f"failed to write webcam snapshot {path}"
|
||||
return
|
||||
record["status"] = "written"
|
||||
record["captured_timestamp"] = datetime.now().strftime("%Y%m%d-%H%M%S-%f")[:-3]
|
||||
|
||||
def _warm_up(self) -> None:
|
||||
if self.device is None:
|
||||
return
|
||||
deadline = time.monotonic() + self.warmup_seconds
|
||||
while time.monotonic() < deadline:
|
||||
self.device.read()
|
||||
time.sleep(0.020)
|
||||
self.device.read()
|
||||
|
||||
|
||||
def _safe_name(text: str) -> str:
|
||||
cleaned = _SAFE_NAME_RE.sub("_", text.strip()).strip("._")
|
||||
return cleaned or "snapshot.jpg"
|
||||
627
h8536/ccu_seed_hints.py
Normal file
627
h8536/ccu_seed_hints.py
Normal file
@@ -0,0 +1,627 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from collections import Counter, defaultdict
|
||||
from collections.abc import Mapping
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from .formatting import h16
|
||||
from .lcd_text import analyze_lcd_text
|
||||
from .panel_selectors import panel_selector_semantics_payload
|
||||
from .rom import Rom
|
||||
from .serial_semantics import OBSERVED_TX_REPORT_OVERLAY
|
||||
from .table_xrefs import analyze_table_xrefs
|
||||
|
||||
|
||||
JsonObject = dict[str, Any]
|
||||
|
||||
DEFAULT_INPUT = Path("build/rom_decompiled.json")
|
||||
DEFAULT_ROM = Path("ROM/M27C512@DIP28_1.BIN")
|
||||
CHECKSUM_SEED = 0x5A
|
||||
DISPLAY_TERMS = (
|
||||
"CONNECT",
|
||||
"COMM LINK",
|
||||
"COMPLETED",
|
||||
"CAM",
|
||||
"BARS",
|
||||
"BLACK",
|
||||
"IRIS",
|
||||
"GAIN",
|
||||
"SHUTTER",
|
||||
"CALL",
|
||||
"POWER",
|
||||
"AUTO",
|
||||
"DIAG",
|
||||
"DXC",
|
||||
)
|
||||
|
||||
SPECIAL_SELECTORS: tuple[JsonObject, ...] = (
|
||||
{
|
||||
"selector": 0x000,
|
||||
"name": "connection_or_heartbeat_root_candidate",
|
||||
"reason": "idle report selector and CONNECT OK emulator condition both center on selector zero",
|
||||
"seed_values": [0x0080, 0x8080],
|
||||
},
|
||||
{
|
||||
"selector": 0x003,
|
||||
"name": "default_enabled_bit_candidate",
|
||||
"reason": "ROM default table writes E000/E800 selector 0x003 to 0x8000",
|
||||
"seed_values": [0x8000],
|
||||
},
|
||||
{
|
||||
"selector": 0x040,
|
||||
"name": "default_all_ones_or_status_block_candidate",
|
||||
"reason": "ROM default table writes E000/E800 selector 0x040 to 0xFFFF and bench tests repeatedly touched the 0x40 family",
|
||||
"seed_values": [0xFFFF, 0x4030],
|
||||
},
|
||||
{
|
||||
"selector": 0x0F6,
|
||||
"name": "active_status_bridge_candidate",
|
||||
"reason": "loc_48FA tests E1EC bit13 and can enqueue report selector 0x00F6",
|
||||
"seed_values": [0x2000],
|
||||
},
|
||||
{
|
||||
"selector": 0x006C,
|
||||
"name": "command5_be70_candidate",
|
||||
"reason": "continuation command 5 calls BE70 for selector 0x006C",
|
||||
"seed_values": [],
|
||||
},
|
||||
{
|
||||
"selector": 0x006D,
|
||||
"name": "command5_be70_candidate",
|
||||
"reason": "continuation command 5 calls BE70 for selector 0x006D",
|
||||
"seed_values": [],
|
||||
},
|
||||
{
|
||||
"selector": 0x006E,
|
||||
"name": "command5_be70_candidate",
|
||||
"reason": "continuation command 5 calls BE70 for selector 0x006E",
|
||||
"seed_values": [],
|
||||
},
|
||||
{
|
||||
"selector": 0x006B,
|
||||
"name": "connection_latch_clear_candidate",
|
||||
"reason": "when F731.7 is set, command 5 on this selector clears F731.7/F790.7",
|
||||
"seed_values": [],
|
||||
},
|
||||
{
|
||||
"selector": 0x0096,
|
||||
"name": "connection_latch_clear_candidate",
|
||||
"reason": "when F731.7 is set, command 5 on this selector clears F731.7/F790.7",
|
||||
"seed_values": [],
|
||||
},
|
||||
{
|
||||
"selector": 0x0097,
|
||||
"name": "connection_latch_clear_candidate",
|
||||
"reason": "when F731.7 is set, command 5 on this selector clears F731.7/F790.7",
|
||||
"seed_values": [],
|
||||
},
|
||||
{
|
||||
"selector": 0x00C6,
|
||||
"name": "connection_latch_clear_candidate",
|
||||
"reason": "when F731.7 is set, command 5 on this selector clears F731.7/F790.7",
|
||||
"seed_values": [],
|
||||
},
|
||||
{
|
||||
"selector": 0x00F8,
|
||||
"name": "connection_latch_clear_candidate",
|
||||
"reason": "when F731.7 is set, command 5 on this selector clears F731.7/F790.7",
|
||||
"seed_values": [],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def load_seed_hints_input(path: Path) -> JsonObject:
|
||||
with path.open("r", encoding="utf-8") as handle:
|
||||
payload = json.load(handle)
|
||||
if not isinstance(payload, dict) or "instructions" not in payload:
|
||||
raise ValueError(f"{path} does not look like h8536_decompiler JSON output")
|
||||
return payload
|
||||
|
||||
|
||||
def analyze_ccu_seed_hints(payload: Mapping[str, Any], *, rom_path: Path | None = DEFAULT_ROM) -> JsonObject:
|
||||
table_analysis = analyze_table_xrefs(payload)
|
||||
selector_hints = _selector_hints_from_tables(table_analysis)
|
||||
_merge_special_selectors(selector_hints)
|
||||
_merge_observed_reports(selector_hints)
|
||||
_merge_panel_selector_semantics(selector_hints)
|
||||
|
||||
dispatch = _dispatch_table_summary(payload, rom_path)
|
||||
for entry in dispatch.get("interesting_entries", []):
|
||||
selector = int(entry["selector"])
|
||||
hint = selector_hints.setdefault(selector, _new_selector_hint(selector))
|
||||
hint["score"] += 2
|
||||
hint["reasons"].append(f"selector dispatches to {entry['target_label_or_hex']}")
|
||||
hint["dispatch_target"] = entry
|
||||
|
||||
display = _display_hint_summary(payload, rom_path)
|
||||
seed_plan = _seed_plan(selector_hints)
|
||||
|
||||
candidates = sorted(
|
||||
selector_hints.values(),
|
||||
key=lambda item: (-int(item["score"]), int(item["selector"])),
|
||||
)
|
||||
return {
|
||||
"kind": "ccu_seed_hints",
|
||||
"summary": {
|
||||
"candidate_count": len(candidates),
|
||||
"core_model": (
|
||||
"The RCP likely waits for the CCU to seed mirrored state tables, then uses those "
|
||||
"selector values to update LCD text, panel lamps, and report state changes."
|
||||
),
|
||||
"confidence": "medium",
|
||||
},
|
||||
"table_model": _table_model_summary(table_analysis),
|
||||
"selector_candidates": candidates[:80],
|
||||
"display_text_hints": display,
|
||||
"dispatch_table": dispatch,
|
||||
"seed_plan": seed_plan,
|
||||
"bench_implications": [
|
||||
"Do not wait for non-heartbeat reports as the only activation source; the CCU may be expected to push initial table state first.",
|
||||
"Use command 0 writes for initial seeding, then command 1 readbacks for verification. Treat command 4/5/6 as continuation-only until a live report proves otherwise.",
|
||||
"Selector zero remains the highest-value activation candidate because the emulator reaches CONNECT OK when E000[0]=0x8080 and the selector-zero processing queue runs.",
|
||||
"E1EC/selector 0x00F6 is a strong follow-up candidate because loc_48FA tests bit13 there and can enqueue report 0x00F6.",
|
||||
"LCD text terms such as CAM/BARS/BLACK/COMM LINK appear in ROM records, but they are not direct serial payload strings; they point to selector-driven display builders.",
|
||||
],
|
||||
"caveats": [
|
||||
"Selector names are candidates, not confirmed protocol labels.",
|
||||
"Static table xrefs prove that firmware reads/writes a selector; they do not prove the external CCU must seed it on boot.",
|
||||
"Generated frames are syntactically valid six-byte host frames; bench safety still depends on timing and current RCP state.",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def format_text_report(analysis: Mapping[str, Any]) -> str:
|
||||
summary = analysis["summary"]
|
||||
lines = [
|
||||
"H8/536 CCU Seed Hint Report",
|
||||
"",
|
||||
f"Summary: {summary['core_model']}",
|
||||
f"Confidence: {summary['confidence']}",
|
||||
"",
|
||||
"Table Model:",
|
||||
]
|
||||
for table in analysis.get("table_model", []):
|
||||
lines.append(
|
||||
f"- {table['name']}: {table['logical_range_hex']}; accesses={table['access_count']} "
|
||||
f"static selectors={', '.join(table.get('static_selectors_hex', [])[:12]) or 'none'}"
|
||||
)
|
||||
|
||||
lines.extend(["", "Highest-Value Selector Candidates:"])
|
||||
for hint in analysis.get("selector_candidates", [])[:24]:
|
||||
lines.append(
|
||||
f"- {hint['selector_hex']} {hint['name']}: score={hint['score']} "
|
||||
f"tables={', '.join(hint.get('tables', [])) or 'none'}"
|
||||
)
|
||||
for reason in hint.get("reasons", [])[:4]:
|
||||
lines.append(f" - {reason}")
|
||||
frames = hint.get("seed_frames", [])
|
||||
if frames:
|
||||
frame_text = "; ".join(f"{frame['value_hex']} -> {frame['cmd0_frame']}" for frame in frames[:3])
|
||||
lines.append(f" seed frames: {frame_text}")
|
||||
read_frame = hint.get("cmd1_read_frame")
|
||||
if read_frame:
|
||||
lines.append(f" readback frame: {read_frame}")
|
||||
|
||||
display = analysis.get("display_text_hints", {})
|
||||
lines.extend(["", "Display Text Hints:"])
|
||||
for hit in display.get("term_hits", [])[:16]:
|
||||
samples = ", ".join(
|
||||
f"{sample['address_hex']} {sample['text']!r}"
|
||||
for sample in hit.get("samples", [])[:3]
|
||||
)
|
||||
lines.append(f"- {hit['term']}: {hit['hit_count']} hit(s){f' - {samples}' if samples else ''}")
|
||||
|
||||
dispatch = analysis.get("dispatch_table", {})
|
||||
lines.extend(["", "Selector Dispatch Hints:"])
|
||||
lines.append(
|
||||
f"- table {dispatch.get('table_base_hex', 'unknown')}: "
|
||||
f"{dispatch.get('interesting_count', 0)} non-default/interesting entries"
|
||||
)
|
||||
for entry in dispatch.get("interesting_entries", [])[:16]:
|
||||
lines.append(
|
||||
f" - selector {entry['selector_hex']} -> {entry['target_label_or_hex']} "
|
||||
f"(dispatch index {entry['dispatch_index_hex']})"
|
||||
)
|
||||
|
||||
seed_plan = analysis.get("seed_plan", {})
|
||||
lines.extend(["", "Candidate Fake-CCU Seed Plan:"])
|
||||
for step in seed_plan.get("steps", []):
|
||||
lines.append(f"- {step['name']}: {step['frame']}")
|
||||
lines.append(f" {step['why']}")
|
||||
|
||||
lines.extend(["", "Bench Implications:"])
|
||||
for item in analysis.get("bench_implications", []):
|
||||
lines.append(f"- {item}")
|
||||
|
||||
lines.extend(["", "Caveats:"])
|
||||
for item in analysis.get("caveats", []):
|
||||
lines.append(f"- {item}")
|
||||
return "\n".join(lines).rstrip() + "\n"
|
||||
|
||||
|
||||
def write_ccu_seed_hints(
|
||||
input_path: Path,
|
||||
output_path: Path,
|
||||
*,
|
||||
rom_path: Path | None = DEFAULT_ROM,
|
||||
as_json: bool = False,
|
||||
) -> JsonObject:
|
||||
analysis = analyze_ccu_seed_hints(load_seed_hints_input(input_path), rom_path=rom_path)
|
||||
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
if as_json:
|
||||
output_path.write_text(json.dumps(analysis, indent=2, sort_keys=True) + "\n", encoding="utf-8")
|
||||
else:
|
||||
output_path.write_text(format_text_report(analysis), encoding="utf-8")
|
||||
return analysis
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None, stdout: Any | None = None) -> int:
|
||||
parser = argparse.ArgumentParser(description="Mine ROM hints for CCU-to-RCP state seeding candidates.")
|
||||
parser.add_argument("input", nargs="?", type=Path, default=DEFAULT_INPUT)
|
||||
parser.add_argument("--rom", type=Path, default=DEFAULT_ROM, help="ROM binary used for LCD text and dispatch-table mining")
|
||||
parser.add_argument("--json", action="store_true", help="emit structured JSON instead of readable text")
|
||||
parser.add_argument("--out", type=Path, default=None, help="write report to this path")
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
stream = stdout
|
||||
if stream is None:
|
||||
import sys
|
||||
|
||||
stream = sys.stdout
|
||||
|
||||
rom_path = args.rom if args.rom and args.rom.exists() else None
|
||||
analysis = analyze_ccu_seed_hints(load_seed_hints_input(args.input), rom_path=rom_path)
|
||||
rendered = json.dumps(analysis, indent=2, sort_keys=True) + "\n" if args.json else format_text_report(analysis)
|
||||
if args.out:
|
||||
args.out.parent.mkdir(parents=True, exist_ok=True)
|
||||
args.out.write_text(rendered, encoding="utf-8")
|
||||
print(f"wrote {args.out}", file=stream)
|
||||
else:
|
||||
print(rendered, end="", file=stream)
|
||||
return 0
|
||||
|
||||
|
||||
def encode_host_frame(command: int, selector: int, value: int = 0) -> list[int]:
|
||||
byte1, byte2 = selector_bytes(selector)
|
||||
frame = [command & 0x07, byte1, byte2, (value >> 8) & 0xFF, value & 0xFF]
|
||||
frame.append(checksum(frame))
|
||||
return frame
|
||||
|
||||
|
||||
def frame_hex(frame: list[int]) -> str:
|
||||
return " ".join(f"{byte & 0xFF:02X}" for byte in frame)
|
||||
|
||||
|
||||
def selector_bytes(selector: int) -> tuple[int, int]:
|
||||
selector &= 0x01FF
|
||||
if selector <= 0x007F:
|
||||
return 0x00, selector
|
||||
if selector <= 0x017F:
|
||||
return 0x01, selector - 0x0080
|
||||
return 0x02, selector - 0x0180
|
||||
|
||||
|
||||
def checksum(frame_without_checksum: list[int]) -> int:
|
||||
value = CHECKSUM_SEED
|
||||
for byte in frame_without_checksum[:5]:
|
||||
value ^= byte & 0xFF
|
||||
return value & 0xFF
|
||||
|
||||
|
||||
def _selector_hints_from_tables(table_analysis: Mapping[str, Any]) -> dict[int, JsonObject]:
|
||||
hints: dict[int, JsonObject] = {}
|
||||
for table in table_analysis.get("tables", []):
|
||||
if not isinstance(table, Mapping):
|
||||
continue
|
||||
table_name = str(table.get("name", "unknown_table"))
|
||||
element = str(table.get("element_candidate", ""))
|
||||
for access in table.get("accesses", []):
|
||||
if not isinstance(access, Mapping) or not isinstance(access.get("offset"), int):
|
||||
continue
|
||||
selector = _selector_from_offset(int(access["offset"]), element)
|
||||
if selector is None:
|
||||
continue
|
||||
hint = hints.setdefault(selector, _new_selector_hint(selector))
|
||||
hint["score"] += _access_score(access, table_name)
|
||||
if table_name not in hint["tables"]:
|
||||
hint["tables"].append(table_name)
|
||||
hint["accesses"].append(
|
||||
{
|
||||
"address_hex": access.get("instruction_address_hex"),
|
||||
"function": access.get("function_label"),
|
||||
"table": table_name,
|
||||
"access": access.get("access"),
|
||||
"instruction": access.get("instruction"),
|
||||
}
|
||||
)
|
||||
reason = _access_reason(access, table_name)
|
||||
if reason not in hint["reasons"]:
|
||||
hint["reasons"].append(reason)
|
||||
return hints
|
||||
|
||||
|
||||
def _merge_special_selectors(hints: dict[int, JsonObject]) -> None:
|
||||
for item in SPECIAL_SELECTORS:
|
||||
selector = int(item["selector"])
|
||||
hint = hints.setdefault(selector, _new_selector_hint(selector))
|
||||
hint["score"] += 5
|
||||
hint["name"] = str(item["name"])
|
||||
hint["reasons"].append(str(item["reason"]))
|
||||
for value in item.get("seed_values", []):
|
||||
_add_seed_value(hint, int(value))
|
||||
|
||||
|
||||
def _merge_observed_reports(hints: dict[int, JsonObject]) -> None:
|
||||
for report in OBSERVED_TX_REPORT_OVERLAY:
|
||||
selector = int(report["logical_index"])
|
||||
hint = hints.setdefault(selector, _new_selector_hint(selector))
|
||||
hint["score"] += 3
|
||||
hint["name"] = str(report["name_candidate"])
|
||||
frames = ", ".join(str(frame) for frame in report.get("observed_frames_hex", []))
|
||||
hint["reasons"].append(f"observed RCP autonomous report frame(s): {frames}")
|
||||
|
||||
|
||||
def _merge_panel_selector_semantics(hints: dict[int, JsonObject]) -> None:
|
||||
for item in panel_selector_semantics_payload():
|
||||
selector = int(item["selector"])
|
||||
hint = hints.setdefault(selector, _new_selector_hint(selector))
|
||||
hint["score"] += 4
|
||||
hint["name"] = str(item.get("name") or hint["name"])
|
||||
summary = str(item.get("summary") or "").strip()
|
||||
if summary:
|
||||
hint["reasons"].append(summary)
|
||||
for effect in item.get("effects", []):
|
||||
if not isinstance(effect, Mapping):
|
||||
continue
|
||||
name = effect.get("name") or "panel effect"
|
||||
mask = effect.get("mask_hex") or "mask?"
|
||||
when_set = effect.get("when_set") or "set"
|
||||
hint["reasons"].append(f"{mask} {name}: {when_set}")
|
||||
for meaning in item.get("value_meanings", []):
|
||||
if not isinstance(meaning, Mapping):
|
||||
continue
|
||||
value = meaning.get("value")
|
||||
if isinstance(value, int):
|
||||
_add_seed_value(hint, value)
|
||||
|
||||
|
||||
def _seed_plan(hints: Mapping[int, JsonObject]) -> JsonObject:
|
||||
planned = [
|
||||
(0x000, 0x8080, "selector zero active/connect candidate from emulator state search"),
|
||||
(0x003, 0x8000, "ROM default state also sets selector 0x003 high bit"),
|
||||
(0x040, 0xFFFF, "ROM default all-ones/status candidate touched by bench 0x40 family"),
|
||||
(0x0F6, 0x2000, "sets E1EC bit13 candidate used by loc_48FA report bridge"),
|
||||
]
|
||||
steps: list[JsonObject] = []
|
||||
for selector, value, why in planned:
|
||||
frame = frame_hex(encode_host_frame(0x00, selector, value))
|
||||
readback = frame_hex(encode_host_frame(0x01, selector, 0))
|
||||
hint = hints.get(selector)
|
||||
if hint is not None:
|
||||
_add_seed_value(hint, value)
|
||||
steps.append(
|
||||
{
|
||||
"selector": selector,
|
||||
"selector_hex": f"0x{selector:03X}",
|
||||
"value": value,
|
||||
"value_hex": f"0x{value:04X}",
|
||||
"name": f"cmd0 seed selector 0x{selector:03X} = 0x{value:04X}",
|
||||
"frame": frame,
|
||||
"readback_frame": readback,
|
||||
"why": why,
|
||||
}
|
||||
)
|
||||
return {
|
||||
"model": "candidate initial CCU state push using command 0 writes, verified with command 1 reads",
|
||||
"steps": steps,
|
||||
}
|
||||
|
||||
|
||||
def _table_model_summary(table_analysis: Mapping[str, Any]) -> list[JsonObject]:
|
||||
rows: list[JsonObject] = []
|
||||
for table in table_analysis.get("tables", []):
|
||||
if not isinstance(table, Mapping):
|
||||
continue
|
||||
element = str(table.get("element_candidate", ""))
|
||||
selectors = []
|
||||
for offset in table.get("static_offsets", []):
|
||||
if isinstance(offset, int):
|
||||
selector = _selector_from_offset(offset, element)
|
||||
if selector is not None:
|
||||
selectors.append(selector)
|
||||
rows.append(
|
||||
{
|
||||
"name": table.get("name"),
|
||||
"logical_range_hex": f"{table.get('logical_base_address_hex')}-{table.get('logical_range_end_hex')}",
|
||||
"access_count": table.get("access_count", 0),
|
||||
"static_selectors": sorted(set(selectors)),
|
||||
"static_selectors_hex": [f"0x{selector:03X}" for selector in sorted(set(selectors))],
|
||||
}
|
||||
)
|
||||
return rows
|
||||
|
||||
|
||||
def _display_hint_summary(payload: Mapping[str, Any], rom_path: Path | None) -> JsonObject:
|
||||
del payload
|
||||
if rom_path is None or not rom_path.exists():
|
||||
return {"term_hits": [], "note": "ROM binary was not available for LCD text mining."}
|
||||
rom = Rom(rom_path.read_bytes())
|
||||
text = analyze_lcd_text(rom, None, search_terms=DISPLAY_TERMS, max_candidates=360)
|
||||
term_hits = []
|
||||
for search in text.get("searches", []):
|
||||
if not isinstance(search, Mapping):
|
||||
continue
|
||||
samples = []
|
||||
for address in search.get("literal_hits", [])[:4]:
|
||||
if isinstance(address, int):
|
||||
samples.append({"address_hex": h16(address), "text": f"literal {search.get('term')}"})
|
||||
for hit in search.get("candidate_hits", [])[:6]:
|
||||
if not isinstance(hit, Mapping):
|
||||
continue
|
||||
samples.append(
|
||||
{
|
||||
"address_hex": h16(int(hit.get("address", 0))),
|
||||
"text": str(hit.get("trimmed") or hit.get("text") or ""),
|
||||
}
|
||||
)
|
||||
hit_count = len(search.get("literal_hits", []) or []) + len(search.get("candidate_hits", []) or [])
|
||||
term_hits.append({"term": search.get("term"), "hit_count": hit_count, "samples": samples[:8]})
|
||||
return {
|
||||
"term_hits": term_hits,
|
||||
"regions": text.get("regions", [])[:8],
|
||||
"note": "Text hits are ROM display resources, not literal serial payloads.",
|
||||
}
|
||||
|
||||
|
||||
def _dispatch_table_summary(payload: Mapping[str, Any], rom_path: Path | None) -> JsonObject:
|
||||
table_base = 0x28A6
|
||||
entries = _indirect_entries(payload, table_base)
|
||||
if not entries and rom_path is not None and rom_path.exists():
|
||||
entries = _raw_dispatch_entries(rom_path, table_base, 128)
|
||||
if not entries:
|
||||
return {"table_base": table_base, "table_base_hex": h16(table_base), "interesting_count": 0, "interesting_entries": []}
|
||||
|
||||
target_counts = Counter(int(entry["target"]) for entry in entries if isinstance(entry.get("target"), int))
|
||||
default_target, _ = target_counts.most_common(1)[0]
|
||||
interesting: list[JsonObject] = []
|
||||
for entry in entries:
|
||||
index = int(entry["index"])
|
||||
selector = _selector_from_dispatch_index(index)
|
||||
if selector is None:
|
||||
continue
|
||||
target = int(entry["target"])
|
||||
label = entry.get("target_label") or h16(target)
|
||||
decoded = bool(entry.get("decoded_code", True))
|
||||
if target == default_target and decoded:
|
||||
continue
|
||||
interesting.append(
|
||||
{
|
||||
"selector": selector,
|
||||
"selector_hex": f"0x{selector:03X}",
|
||||
"dispatch_index": index,
|
||||
"dispatch_index_hex": f"0x{index:03X}",
|
||||
"entry_address_hex": h16(int(entry.get("entry_address", table_base + index * 2))),
|
||||
"target": target,
|
||||
"target_hex": h16(target),
|
||||
"target_label_or_hex": str(label),
|
||||
"decoded_code": decoded,
|
||||
}
|
||||
)
|
||||
return {
|
||||
"table_base": table_base,
|
||||
"table_base_hex": h16(table_base),
|
||||
"entry_count": len(entries),
|
||||
"default_target_hex": h16(default_target),
|
||||
"interesting_count": len(interesting),
|
||||
"interesting_entries": interesting[:80],
|
||||
}
|
||||
|
||||
|
||||
def _indirect_entries(payload: Mapping[str, Any], table_base: int) -> list[JsonObject]:
|
||||
indirect = payload.get("indirect_flow")
|
||||
if not isinstance(indirect, Mapping):
|
||||
return []
|
||||
for site in indirect.get("sites", []):
|
||||
if not isinstance(site, Mapping):
|
||||
continue
|
||||
table = site.get("table")
|
||||
if isinstance(table, Mapping) and int(table.get("base", -1)) == table_base:
|
||||
entries = table.get("entries", [])
|
||||
if isinstance(entries, list):
|
||||
return [dict(entry) for entry in entries if isinstance(entry, Mapping)]
|
||||
return []
|
||||
|
||||
|
||||
def _raw_dispatch_entries(rom_path: Path, table_base: int, count: int) -> list[JsonObject]:
|
||||
rom = Rom(rom_path.read_bytes())
|
||||
entries = []
|
||||
for index in range(count):
|
||||
address = table_base + index * 2
|
||||
if not rom.contains(address, 2):
|
||||
break
|
||||
target = rom.u16(address)
|
||||
entries.append({"index": index, "entry_address": address, "target": target, "target_label": None, "decoded_code": True})
|
||||
return entries
|
||||
|
||||
|
||||
def _selector_from_dispatch_index(index: int) -> int | None:
|
||||
if 0 <= index <= 0x007F:
|
||||
return index
|
||||
if 0x0100 <= index <= 0x01FF:
|
||||
return index - 0x0080
|
||||
if 0x0200 <= index <= 0x027F:
|
||||
return index - 0x0080
|
||||
return None
|
||||
|
||||
|
||||
def _selector_from_offset(offset: int, element: str) -> int | None:
|
||||
if element == "word_value":
|
||||
if offset % 2:
|
||||
return None
|
||||
return (offset // 2) & 0x01FF
|
||||
return offset & 0x01FF
|
||||
|
||||
|
||||
def _new_selector_hint(selector: int) -> JsonObject:
|
||||
return {
|
||||
"selector": selector,
|
||||
"selector_hex": f"0x{selector:03X}",
|
||||
"name": "state_selector_candidate",
|
||||
"score": 0,
|
||||
"tables": [],
|
||||
"reasons": [],
|
||||
"accesses": [],
|
||||
"seed_frames": [],
|
||||
"cmd1_read_frame": frame_hex(encode_host_frame(0x01, selector, 0)),
|
||||
}
|
||||
|
||||
|
||||
def _add_seed_value(hint: JsonObject, value: int) -> None:
|
||||
frames = hint.setdefault("seed_frames", [])
|
||||
value_hex = f"0x{value & 0xFFFF:04X}"
|
||||
if any(frame.get("value_hex") == value_hex for frame in frames):
|
||||
return
|
||||
frames.append(
|
||||
{
|
||||
"value": value & 0xFFFF,
|
||||
"value_hex": value_hex,
|
||||
"cmd0_frame": frame_hex(encode_host_frame(0x00, int(hint["selector"]), value)),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def _access_score(access: Mapping[str, Any], table_name: str) -> int:
|
||||
score = 1
|
||||
if access.get("access") == "read":
|
||||
score += 1
|
||||
if access.get("access") == "write":
|
||||
score += 1
|
||||
if "primary" in table_name or "current" in table_name:
|
||||
score += 1
|
||||
return score
|
||||
|
||||
|
||||
def _access_reason(access: Mapping[str, Any], table_name: str) -> str:
|
||||
function = access.get("function_label") or "<no function>"
|
||||
instruction = access.get("instruction") or ""
|
||||
return f"{table_name} {access.get('access')} in {function}: {instruction}"
|
||||
|
||||
|
||||
__all__ = [
|
||||
"analyze_ccu_seed_hints",
|
||||
"checksum",
|
||||
"encode_host_frame",
|
||||
"format_text_report",
|
||||
"frame_hex",
|
||||
"load_seed_hints_input",
|
||||
"main",
|
||||
"selector_bytes",
|
||||
"write_ccu_seed_hints",
|
||||
]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
442
h8536/connect_ok_advance_sweep.py
Normal file
442
h8536/connect_ok_advance_sweep.py
Normal file
@@ -0,0 +1,442 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Any, TextIO
|
||||
|
||||
from .bench_connect_lcd import (
|
||||
BenchLogger,
|
||||
FrameDetector,
|
||||
add_serial_format_args,
|
||||
_import_serial,
|
||||
open_device_serial,
|
||||
_read_for,
|
||||
_relay_command,
|
||||
_relay_settle,
|
||||
_send_frame,
|
||||
_wait_for_ready,
|
||||
format_frame,
|
||||
frame_checksum_ok,
|
||||
label_frame,
|
||||
parse_frame,
|
||||
serial_format_label,
|
||||
)
|
||||
from .connect_ok_matrix import FRAME_80_OK
|
||||
|
||||
|
||||
ACK_0040 = bytes.fromhex("05004000001F")
|
||||
REFRESH_OK = bytes.fromhex("0400008000DE")
|
||||
ACK_006B = bytes.fromhex("05006B000034")
|
||||
ACK_006C = bytes.fromhex("05006C000033")
|
||||
ACK_006D = bytes.fromhex("05006D000032")
|
||||
ACK_006E = bytes.fromhex("05006E000031")
|
||||
ACK_0096 = bytes.fromhex("050116000048")
|
||||
ACK_0097 = bytes.fromhex("050117000049")
|
||||
ACK_00C6 = bytes.fromhex("050146000018")
|
||||
ACK_00F8 = bytes.fromhex("050178000026")
|
||||
|
||||
DEFAULT_BASELINE = (FRAME_80_OK, FRAME_80_OK)
|
||||
HEARTBEAT_FRAME = bytes.fromhex("0000000080DA")
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class AdvanceCase:
|
||||
name: str
|
||||
frame: bytes
|
||||
note: str = ""
|
||||
|
||||
|
||||
def default_log_path(suite: str) -> Path:
|
||||
safe_suite = "".join(char if char.isalnum() or char in "-_" else "-" for char in suite)
|
||||
return Path("captures") / f"connect-ok-advance-{safe_suite}-{datetime.now().strftime('%Y%m%d-%H%M%S')}.txt"
|
||||
|
||||
|
||||
def build_arg_parser() -> argparse.ArgumentParser:
|
||||
parser = argparse.ArgumentParser(
|
||||
description=(
|
||||
"Recover the RCP to CONNECT: OK, then sweep one candidate continuation/ACK "
|
||||
"frame from the active report window."
|
||||
)
|
||||
)
|
||||
parser.add_argument("--suite", choices=("core", "special", "latch", "all"), default="core")
|
||||
parser.add_argument("--case", action="append", help="run only matching case names; repeatable")
|
||||
parser.add_argument("--limit", type=int, help="run only the first N selected cases")
|
||||
parser.add_argument("--port", default="COM5", help="RS232 serial port connected to the RCP")
|
||||
parser.add_argument("--baud", type=int, default=38400, help="RCP serial baud rate")
|
||||
add_serial_format_args(parser)
|
||||
parser.add_argument("--relay-port", default="COM6", help="Pico relay serial port")
|
||||
parser.add_argument("--relay-baud", type=int, default=115200, help="Pico relay serial baud rate")
|
||||
parser.add_argument("--no-power-cycle", action="store_true", help="do not power-cycle before the sweep starts")
|
||||
parser.add_argument(
|
||||
"--power-cycle-between-cases",
|
||||
action="store_true",
|
||||
help="power-cycle before each candidate instead of recovering from the current state",
|
||||
)
|
||||
parser.add_argument("--power-off-command", default="off", help="relay command used to remove DUT power")
|
||||
parser.add_argument("--power-on-command", default="on", help="relay command used to apply DUT power")
|
||||
parser.add_argument("--off-seconds", type=float, default=1.5, help="seconds to hold DUT power off")
|
||||
parser.add_argument("--relay-settle", type=float, default=2.0, help="seconds to wait after opening the relay port")
|
||||
parser.add_argument("--ready-timeout", type=float, default=10.0, help="seconds to wait for heartbeat")
|
||||
parser.add_argument("--ready-heartbeats", type=int, default=2, help="heartbeat frames to observe before a case")
|
||||
parser.add_argument("--require-ready", action="store_true", help="abort a case if readiness heartbeats are not observed")
|
||||
parser.add_argument("--pre-case-drain", type=float, default=0.250, help="seconds to drain/log RX before baseline")
|
||||
parser.add_argument(
|
||||
"--baseline-frame",
|
||||
action="append",
|
||||
type=parse_frame,
|
||||
help="override baseline with custom frame; repeatable; default is two selector-zero OK frames",
|
||||
)
|
||||
parser.add_argument("--baseline-gap", type=float, default=0.700, help="seconds to listen between baseline frames")
|
||||
parser.add_argument(
|
||||
"--target-mode",
|
||||
choices=("active", "connect-ok", "non-heartbeat", "none"),
|
||||
default="active",
|
||||
help="which device frame opens the candidate-send window",
|
||||
)
|
||||
parser.add_argument("--target-timeout", type=float, default=2.5, help="seconds to wait for the target window")
|
||||
parser.add_argument("--candidate-guard", type=float, default=0.020, help="seconds to wait after target before candidate")
|
||||
parser.add_argument(
|
||||
"--send-on-target-timeout",
|
||||
action="store_true",
|
||||
help="send the candidate even if no target-mode frame was observed",
|
||||
)
|
||||
parser.add_argument("--post-candidate-read", type=float, default=5.0, help="seconds to listen after candidate")
|
||||
parser.add_argument("--candidate", action="append", type=_parse_candidate, help="custom candidate as name=frame or frame")
|
||||
parser.add_argument("--sync", choices=("checksum", "fixed"), default="checksum", help="RX frame sync strategy")
|
||||
parser.add_argument("--prompt-observation", action="store_true", help="prompt for observed LCD/lamp state after each case")
|
||||
parser.add_argument("--pause-between-cases", action="store_true", help="wait for Enter before the next case")
|
||||
parser.add_argument("--log", type=Path, help="capture log path")
|
||||
parser.add_argument("--result-json", type=Path, help="write machine-readable case summary")
|
||||
parser.add_argument("--dry-run", action="store_true", help="print selected cases without opening serial ports")
|
||||
return parser
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None, *, stdout: TextIO = sys.stdout) -> int:
|
||||
args = build_arg_parser().parse_args(argv)
|
||||
cases = select_cases(args)
|
||||
baseline = tuple(args.baseline_frame or DEFAULT_BASELINE)
|
||||
log_path = args.log or default_log_path(args.suite)
|
||||
|
||||
if args.dry_run:
|
||||
_print_dry_run(args, cases, baseline, log_path, stdout)
|
||||
return 0
|
||||
|
||||
serial = _import_serial()
|
||||
logger = BenchLogger(log_path, stdout=stdout)
|
||||
results: list[dict[str, Any]] = []
|
||||
try:
|
||||
logger.emit("CONNECT: OK advance sweep")
|
||||
logger.emit(
|
||||
f"suite={args.suite} cases={len(cases)} device={args.port} {args.baud} {serial_format_label(args)} "
|
||||
f"relay={args.relay_port} {args.relay_baud} sync={args.sync}"
|
||||
)
|
||||
logger.emit(f"log={log_path}")
|
||||
_emit_baseline_plan(logger, baseline, args.baseline_gap)
|
||||
with open_device_serial(serial, args) as device:
|
||||
relay = None
|
||||
try:
|
||||
if not args.no_power_cycle or args.power_cycle_between_cases:
|
||||
relay = serial.Serial(args.relay_port, args.relay_baud, timeout=0.25)
|
||||
_relay_settle(relay, args.relay_settle, logger)
|
||||
if not args.no_power_cycle and not args.power_cycle_between_cases:
|
||||
_power_cycle(args, device, relay, logger)
|
||||
|
||||
for index, case in enumerate(cases, start=1):
|
||||
if args.pause_between_cases and index > 1:
|
||||
input(f"Press Enter to start case {index}/{len(cases)}: {case.name}")
|
||||
result = _run_case(args, device, relay, logger, case, baseline, index, len(cases))
|
||||
results.append(result)
|
||||
if args.require_ready and not result["ready"]:
|
||||
logger.event("ABORT readiness was required")
|
||||
break
|
||||
finally:
|
||||
if relay is not None:
|
||||
relay.close()
|
||||
_emit_summary(logger, results)
|
||||
if args.result_json:
|
||||
_write_result_json(args.result_json, log_path, args, baseline, results)
|
||||
return 0
|
||||
finally:
|
||||
logger.close()
|
||||
|
||||
|
||||
def select_cases(args: argparse.Namespace) -> list[AdvanceCase]:
|
||||
cases = list(args.candidate or build_cases(args.suite))
|
||||
if args.case:
|
||||
filters = [item.lower() for item in args.case]
|
||||
cases = [case for case in cases if any(fragment in case.name.lower() for fragment in filters)]
|
||||
if args.limit is not None:
|
||||
cases = cases[: max(0, args.limit)]
|
||||
if not cases:
|
||||
raise SystemExit("no advance cases selected")
|
||||
return cases
|
||||
|
||||
|
||||
def build_cases(suite: str) -> list[AdvanceCase]:
|
||||
core = [
|
||||
AdvanceCase("ack-0040", ACK_0040, "pure command-5 continuation ACK candidate"),
|
||||
AdvanceCase("refresh-ok", REFRESH_OK, "command-4 continuation ACK plus selector-zero 0x8080 refresh"),
|
||||
]
|
||||
special = [
|
||||
AdvanceCase("ack-006c", ACK_006C, "command-5 special BE70 selector candidate"),
|
||||
AdvanceCase("ack-006d", ACK_006D, "command-5 special BE70 selector candidate"),
|
||||
AdvanceCase("ack-006e", ACK_006E, "command-5 special BE70 selector candidate"),
|
||||
]
|
||||
latch = [
|
||||
AdvanceCase("ack-006b", ACK_006B, "command-5 latch-clear special selector candidate"),
|
||||
AdvanceCase("ack-0096", ACK_0096, "command-5 F731/F790 latch-clear candidate"),
|
||||
AdvanceCase("ack-0097", ACK_0097, "command-5 F731/F790 latch-clear candidate"),
|
||||
AdvanceCase("ack-00c6", ACK_00C6, "command-5 F731/F790 latch-clear candidate"),
|
||||
AdvanceCase("ack-00f8", ACK_00F8, "command-5 F731/F790 latch-clear candidate"),
|
||||
]
|
||||
suites = {
|
||||
"core": core,
|
||||
"special": special,
|
||||
"latch": latch,
|
||||
"all": core + special + latch,
|
||||
}
|
||||
return suites[suite]
|
||||
|
||||
|
||||
def _run_case(
|
||||
args: argparse.Namespace,
|
||||
device: Any,
|
||||
relay: Any | None,
|
||||
logger: BenchLogger,
|
||||
case: AdvanceCase,
|
||||
baseline: tuple[bytes, ...],
|
||||
index: int,
|
||||
total: int,
|
||||
) -> dict[str, Any]:
|
||||
detector = FrameDetector(sync_mode=args.sync)
|
||||
logger.emit()
|
||||
logger.emit(f"CASE {index}/{total} {case.name}")
|
||||
logger.emit(f"note={case.note or '(none)'}")
|
||||
logger.emit(f"candidate={format_frame(case.frame)} checksum_ok={int(frame_checksum_ok(case.frame))}")
|
||||
logger.emit(
|
||||
f"target_mode={args.target_mode} target_timeout={args.target_timeout:.3f}s "
|
||||
f"candidate_guard={args.candidate_guard:.3f}s"
|
||||
)
|
||||
|
||||
if args.power_cycle_between_cases:
|
||||
_power_cycle(args, device, relay, logger)
|
||||
else:
|
||||
device.reset_input_buffer()
|
||||
logger.event("POWER_CYCLE skipped for case; recovering with baseline")
|
||||
|
||||
ready = _wait_for_ready(device, detector, logger, args.ready_timeout, args.ready_heartbeats)
|
||||
if args.require_ready and not ready:
|
||||
observation = _prompt_observation(args, logger, case)
|
||||
return _case_result(case, detector, ready=ready, target=None, candidate_sent=False, observation=observation)
|
||||
|
||||
if args.pre_case_drain > 0:
|
||||
logger.event(f"DRAIN before baseline {args.pre_case_drain:.3f}s")
|
||||
_read_for(device, detector, logger, args.pre_case_drain)
|
||||
|
||||
for frame_index, frame in enumerate(baseline, start=1):
|
||||
_send_frame(device, frame, logger, f"{case.name}.baseline{frame_index}")
|
||||
_read_for(device, detector, logger, args.baseline_gap)
|
||||
|
||||
target = _wait_for_target_mode(device, detector, logger, args.target_mode, args.target_timeout)
|
||||
candidate_sent = target is not None or args.target_mode == "none" or args.send_on_target_timeout
|
||||
if candidate_sent:
|
||||
if args.candidate_guard > 0:
|
||||
logger.event(f"CANDIDATE guard {args.candidate_guard:.3f}s")
|
||||
_read_for(device, detector, logger, args.candidate_guard)
|
||||
_send_frame(device, case.frame, logger, f"{case.name}.candidate")
|
||||
else:
|
||||
logger.event("CANDIDATE skipped because target window was not observed")
|
||||
|
||||
if args.post_candidate_read > 0:
|
||||
logger.event(f"POST_CANDIDATE_READ {args.post_candidate_read:.3f}s")
|
||||
_read_for(device, detector, logger, args.post_candidate_read)
|
||||
|
||||
observation = _prompt_observation(args, logger, case)
|
||||
result = _case_result(case, detector, ready=ready, target=target, candidate_sent=candidate_sent, observation=observation)
|
||||
logger.event(
|
||||
f"CASE_RESULT {case.name} ready={int(ready)} target_seen={int(target is not None)} "
|
||||
f"candidate_sent={int(candidate_sent)} rx_frames={result['rx_frames']} "
|
||||
f"labels={json.dumps(result['labels'], sort_keys=True)}"
|
||||
)
|
||||
return result
|
||||
|
||||
|
||||
def _wait_for_target_mode(
|
||||
device: Any,
|
||||
detector: FrameDetector,
|
||||
logger: BenchLogger,
|
||||
mode: str,
|
||||
timeout_seconds: float,
|
||||
) -> bytes | None:
|
||||
if mode == "none":
|
||||
logger.event("TARGET disabled")
|
||||
return None
|
||||
logger.event(f"WAIT target_mode={mode} timeout={timeout_seconds:.3f}s")
|
||||
start_index = len(detector.frames)
|
||||
deadline = time.monotonic() + max(0.0, timeout_seconds)
|
||||
while time.monotonic() < deadline:
|
||||
before = len(detector.frames)
|
||||
_read_for(device, detector, logger, 0.050)
|
||||
for frame in detector.frames[max(start_index, before) :]:
|
||||
if _matches_target(frame, mode):
|
||||
logger.event(f"TARGET seen {format_frame(frame)} label={label_frame(frame)}")
|
||||
return frame
|
||||
logger.event("TARGET_TIMEOUT")
|
||||
return None
|
||||
|
||||
|
||||
def _matches_target(frame: bytes, mode: str) -> bool:
|
||||
label = label_frame(frame)
|
||||
if mode == "connect-ok":
|
||||
return label in {"connect_ok_path_response_candidate", "connect_c0_path_response_candidate"}
|
||||
if mode == "non-heartbeat":
|
||||
return frame_checksum_ok(frame) and frame != HEARTBEAT_FRAME
|
||||
if mode == "active":
|
||||
return frame_checksum_ok(frame) and frame != HEARTBEAT_FRAME and frame[0] in {0x01, 0x02, 0x07}
|
||||
raise ValueError(f"unknown target mode {mode!r}")
|
||||
|
||||
|
||||
def _power_cycle(args: argparse.Namespace, device: Any, relay: Any | None, logger: BenchLogger) -> None:
|
||||
if relay is None:
|
||||
raise SystemExit("relay was not opened")
|
||||
_relay_command(relay, args.power_off_command, logger)
|
||||
time.sleep(max(0.0, args.off_seconds))
|
||||
device.reset_input_buffer()
|
||||
_relay_command(relay, args.power_on_command, logger)
|
||||
|
||||
|
||||
def _case_result(
|
||||
case: AdvanceCase,
|
||||
detector: FrameDetector,
|
||||
*,
|
||||
ready: bool,
|
||||
target: bytes | None,
|
||||
candidate_sent: bool,
|
||||
observation: str,
|
||||
) -> dict[str, Any]:
|
||||
return {
|
||||
"name": case.name,
|
||||
"note": case.note,
|
||||
"frame": format_frame(case.frame),
|
||||
"ready": ready,
|
||||
"target_seen": target is not None,
|
||||
"target": format_frame(target) if target is not None else "",
|
||||
"candidate_sent": candidate_sent,
|
||||
"rx_frames": len(detector.frames),
|
||||
"labels": dict(detector.labels),
|
||||
"resync_events": detector.resync_events,
|
||||
"dropped_bytes": detector.dropped_bytes,
|
||||
"trailing_unframed_bytes": len(detector.buffer),
|
||||
"observation": observation,
|
||||
}
|
||||
|
||||
|
||||
def _prompt_observation(args: argparse.Namespace, logger: BenchLogger, case: AdvanceCase) -> str:
|
||||
if not args.prompt_observation:
|
||||
return ""
|
||||
prompt = f"{case.name}: LCD/lamps/readouts observation, or Enter to skip: "
|
||||
observation = input(prompt).strip()
|
||||
logger.event(f"OBSERVATION {case.name}: {observation or '(no note)'}")
|
||||
return observation
|
||||
|
||||
|
||||
def _emit_baseline_plan(logger: BenchLogger, baseline: tuple[bytes, ...], gap: float) -> None:
|
||||
logger.emit(f"baseline_gap={gap:.3f}s baseline_frames={len(baseline)}")
|
||||
for index, frame in enumerate(baseline, start=1):
|
||||
logger.emit(f"baseline[{index}]={format_frame(frame)} checksum_ok={int(frame_checksum_ok(frame))}")
|
||||
|
||||
|
||||
def _emit_summary(logger: BenchLogger, results: list[dict[str, Any]]) -> None:
|
||||
logger.emit()
|
||||
logger.emit("Advance Sweep Summary")
|
||||
logger.emit(f"cases={len(results)}")
|
||||
for result in results:
|
||||
labels = ", ".join(f"{key}={value}" for key, value in sorted(result["labels"].items())) or "no_rx_frames"
|
||||
note = result["observation"] or "(no observation)"
|
||||
logger.emit(
|
||||
f"{result['name']}: ready={int(result['ready'])} target_seen={int(result['target_seen'])} "
|
||||
f"candidate_sent={int(result['candidate_sent'])} rx_frames={result['rx_frames']} "
|
||||
f"{labels} observation={note}"
|
||||
)
|
||||
|
||||
|
||||
def _write_result_json(
|
||||
path: Path,
|
||||
log_path: Path,
|
||||
args: argparse.Namespace,
|
||||
baseline: tuple[bytes, ...],
|
||||
results: list[dict[str, Any]],
|
||||
) -> None:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
payload = {
|
||||
"suite": args.suite,
|
||||
"log": str(log_path),
|
||||
"serial_format": f"{args.baud} {serial_format_label(args)}",
|
||||
"baseline": [format_frame(frame) for frame in baseline],
|
||||
"baseline_gap": args.baseline_gap,
|
||||
"target_mode": args.target_mode,
|
||||
"candidate_guard": args.candidate_guard,
|
||||
"cases": results,
|
||||
}
|
||||
path.write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n", encoding="utf-8")
|
||||
|
||||
|
||||
def _print_dry_run(
|
||||
args: argparse.Namespace,
|
||||
cases: list[AdvanceCase],
|
||||
baseline: tuple[bytes, ...],
|
||||
log_path: Path,
|
||||
stdout: TextIO,
|
||||
) -> None:
|
||||
print(f"suite={args.suite}", file=stdout)
|
||||
print(f"cases={len(cases)}", file=stdout)
|
||||
print(f"device={args.port} {args.baud} {serial_format_label(args)}", file=stdout)
|
||||
print(f"relay={args.relay_port} {args.relay_baud}", file=stdout)
|
||||
print(f"power_cycle_start={int(not args.no_power_cycle)}", file=stdout)
|
||||
print(f"power_cycle_between_cases={int(args.power_cycle_between_cases)}", file=stdout)
|
||||
print(f"target_mode={args.target_mode} target_timeout={args.target_timeout:.3f}s", file=stdout)
|
||||
print(f"candidate_guard={args.candidate_guard:.3f}s post_candidate_read={args.post_candidate_read:.3f}s", file=stdout)
|
||||
print(f"baseline_gap={args.baseline_gap:.3f}s", file=stdout)
|
||||
for index, frame in enumerate(baseline, start=1):
|
||||
print(f"baseline[{index}]={format_frame(frame)} checksum_ok={int(frame_checksum_ok(frame))}", file=stdout)
|
||||
print(f"log={log_path}", file=stdout)
|
||||
for index, case in enumerate(cases, start=1):
|
||||
print(f"case[{index}]={case.name} frame={format_frame(case.frame)} checksum_ok={int(frame_checksum_ok(case.frame))}", file=stdout)
|
||||
if case.note:
|
||||
print(f" note={case.note}", file=stdout)
|
||||
|
||||
|
||||
def _parse_candidate(text: str) -> AdvanceCase:
|
||||
if "=" in text:
|
||||
name, frame_text = text.split("=", 1)
|
||||
name = name.strip()
|
||||
if not name:
|
||||
raise argparse.ArgumentTypeError("custom candidate name cannot be empty")
|
||||
else:
|
||||
name = "custom"
|
||||
frame_text = text
|
||||
return AdvanceCase(name=name, frame=parse_frame(frame_text), note="custom candidate")
|
||||
|
||||
|
||||
__all__ = [
|
||||
"ACK_0040",
|
||||
"ACK_006B",
|
||||
"ACK_006C",
|
||||
"ACK_006D",
|
||||
"ACK_006E",
|
||||
"ACK_0096",
|
||||
"ACK_0097",
|
||||
"ACK_00C6",
|
||||
"ACK_00F8",
|
||||
"AdvanceCase",
|
||||
"REFRESH_OK",
|
||||
"build_arg_parser",
|
||||
"build_cases",
|
||||
"main",
|
||||
"select_cases",
|
||||
]
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user