1
0
Files
h8-536-decoder/docs/pt2-protocol.md
2026-05-27 12:17:12 +10:00

36 KiB

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

.\.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:

.\.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:

.\.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:

.\.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:

.\.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:

.\.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:

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:

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:
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:

.\.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:

.\.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:

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:

--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:

.\.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:

.\.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:

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:

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:

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