1
0

isolating lamp behaviour

This commit is contained in:
Aiden
2026-05-26 16:59:09 +10:00
parent 11b6a2dc3b
commit fec48518c1
8 changed files with 657 additions and 21 deletions

View File

@@ -11,7 +11,7 @@ The real panel responds to primary selector `0x008F`:
| `00 01 0F 08 00 5C` | `E000[0x008F].11` | SHUTTER shows observed `EUS`, likely manual `EVS`; iris AUTO lamp on | | `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 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 18 00 4C` | bits 11 and 12 | likely `EVS` wins over `OFF`; iris AUTO lamp on |
| `00 01 0F 00 00 54` | clear candidate | not yet bench-confirmed | | `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: Manual correlation:
@@ -19,7 +19,7 @@ Manual correlation:
- The RCP-TX7 menu table lists `EVS/ECS` under OTHERS for DXC-D30/D30P. - 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. - 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`, and `0x008F.12` is best labeled `shutter_off_display_or_mode`. 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 ## Selector 0x008F ROM Path
@@ -93,6 +93,14 @@ Candidate selectors:
This cluster is a strong candidate for the numeric shutter speed / clear-scan frequency side of the display. It is not yet bench-confirmed. 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 ## Candidate Probe Frames
Readback: Readback:
@@ -120,3 +128,46 @@ Potential display probes after `CONNECT: OK`:
``` ```
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. 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
```
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.
## 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-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 PRESET and black/flare manual/auto side effects, and still gates some ROM-observed shutter/clear-scan report lanes.

View File

@@ -230,9 +230,13 @@ def _step_table_sweep(ctx: ScenarioContext, spec: dict[str, Any]) -> None:
selectors = _selector_list(spec) selectors = _selector_list(spec)
gap = float(spec.get("gap", 0.080)) gap = float(spec.get("gap", 0.080))
ack = _ack_config(spec.get("ack_on", {})) ack = _ack_config(spec.get("ack_on", {}))
ack_note = (
"ack=disabled"
if not ack["enabled"]
else f"ack_targets={len(ack['targets'])} ack_frame={format_frame(ack['frame'])}"
)
ctx.logger.event( ctx.logger.event(
f"TABLE_SWEEP selectors={len(selectors)} gap={gap:.3f}s " f"TABLE_SWEEP selectors={len(selectors)} gap={gap:.3f}s {ack_note}"
f"ack_targets={len(ack['targets'])} ack_frame={format_frame(ack['frame'])}"
) )
for selector in selectors: for selector in selectors:
if ctx.abort_requested: if ctx.abort_requested:
@@ -246,7 +250,10 @@ def _step_table_sweep(ctx: ScenarioContext, spec: dict[str, Any]) -> None:
def _ack_config(raw: Any) -> dict[str, Any]: def _ack_config(raw: Any) -> dict[str, Any]:
spec = raw if isinstance(raw, dict) else {} spec = raw if isinstance(raw, dict) else {}
enabled = bool(spec.get("enabled", True))
targets = _parse_frame_list(spec.get("frames", spec.get("frame", DEFAULT_ACK_TARGET))) targets = _parse_frame_list(spec.get("frames", spec.get("frame", DEFAULT_ACK_TARGET)))
if not enabled:
targets = set()
return { return {
"targets": set(targets), "targets": set(targets),
"frame": _parse_optional_frame(spec.get("ack_frame"), DEFAULT_ACK_FRAME), "frame": _parse_optional_frame(spec.get("ack_frame"), DEFAULT_ACK_FRAME),
@@ -254,7 +261,7 @@ def _ack_config(raw: Any) -> dict[str, Any]:
"poll_interval": float(spec.get("poll_interval", 0.005)), "poll_interval": float(spec.get("poll_interval", 0.005)),
"post_read": float(spec.get("post_ack_read", 0.250)), "post_read": float(spec.get("post_ack_read", 0.250)),
"once_per_selector": bool(spec.get("once_per_selector", True)), "once_per_selector": bool(spec.get("once_per_selector", True)),
"enabled": bool(spec.get("enabled", True)), "enabled": enabled,
"max_acks": _optional_int(spec.get("max_acks")), "max_acks": _optional_int(spec.get("max_acks")),
"max_target_hits": _optional_int(spec.get("max_target_hits")), "max_target_hits": _optional_int(spec.get("max_target_hits")),
"abort_on_limit": bool(spec.get("abort_on_limit", True)), "abort_on_limit": bool(spec.get("abort_on_limit", True)),
@@ -452,23 +459,52 @@ def _print_dry_run(args: argparse.Namespace, scenario: dict[str, Any], log_path:
for index, step in enumerate(_scenario_steps(scenario), start=1): for index, step in enumerate(_scenario_steps(scenario), start=1):
action, spec = _normalize_step(step) action, spec = _normalize_step(step)
print(f"step[{index}]={action}", file=stdout) print(f"step[{index}]={action}", file=stdout)
_print_step_dry_run(action, spec, stdout)
def _print_step_dry_run(action: str, spec: dict[str, Any], stdout: TextIO, *, indent: str = " ") -> None:
if action == "send": if action == "send":
frame = _parse_required_frame(spec.get("frame")) frame = _parse_required_frame(spec.get("frame"))
print(f" frame={format_frame(frame)} checksum_ok={int(frame_checksum_ok(frame))}", file=stdout) print(f"{indent}frame={format_frame(frame)} checksum_ok={int(frame_checksum_ok(frame))}", file=stdout)
if float(spec.get("listen", 0.0)) > 0:
print(f"{indent}listen={float(spec.get('listen', 0.0)):.3f}s", file=stdout)
elif action in {"drain", "listen", "wait"}:
print(f"{indent}seconds={float(spec.get('seconds', spec.get('value', 0.0))):.3f}", file=stdout)
elif action == "wait_ready":
print(
f"{indent}heartbeats={int(spec.get('heartbeats', 2))} "
f"timeout={float(spec.get('timeout', 10.0)):.3f}s "
f"require={int(bool(spec.get('require', False)))}",
file=stdout,
)
elif action == "table_sweep": elif action == "table_sweep":
selectors = _selector_list(spec) selectors = _selector_list(spec)
ack = _ack_config(spec.get("ack_on", {})) ack = _ack_config(spec.get("ack_on", {}))
if selectors: if selectors:
first = selectors[0] first = selectors[0]
last = selectors[-1] last = selectors[-1]
print(f" selectors={len(selectors)} first=0x{first:03X} last=0x{last:03X}", file=stdout) print(f"{indent}selectors={len(selectors)} first=0x{first:03X} last=0x{last:03X}", file=stdout)
else:
print(f"{indent}selectors=0", file=stdout)
print(f"{indent}gap={float(spec.get('gap', 0.080)):.3f}", file=stdout)
if not ack["enabled"]:
print(f"{indent}ack=disabled", file=stdout)
else: else:
print(" selectors=0", file=stdout)
print(f" gap={float(spec.get('gap', 0.080)):.3f}", file=stdout)
for target in sorted(ack["targets"]): for target in sorted(ack["targets"]):
print(f" ack_target={format_frame(target)}", file=stdout) print(f"{indent}ack_target={format_frame(target)}", file=stdout)
print(f" ack_frame={format_frame(ack['frame'])}", file=stdout) print(f"{indent}ack_frame={format_frame(ack['frame'])}", file=stdout)
print(f" max_acks={ack['max_acks']} max_target_hits={ack['max_target_hits']}", file=stdout) print(f"{indent}max_acks={ack['max_acks']} max_target_hits={ack['max_target_hits']}", file=stdout)
elif action == "repeat":
count = max(0, int(spec.get("count", 1)))
steps = spec.get("steps", [])
step_count = len(steps) if isinstance(steps, list) else 0
print(f"{indent}count={count} steps={step_count}", file=stdout)
if not isinstance(steps, list):
return
for child_index, child in enumerate(steps, start=1):
child_action, child_spec = _normalize_step(child)
print(f"{indent}child[{child_index}]={child_action}", file=stdout)
_print_step_dry_run(child_action, child_spec, stdout, indent=indent + " ")
def _emit_summary(ctx: ScenarioContext, logger: BenchLogger) -> None: def _emit_summary(ctx: ScenarioContext, logger: BenchLogger) -> None:

View File

@@ -0,0 +1,48 @@
{
"name": "shutter-008f-evs-clear-control",
"notes": [
"Recover to CONNECT OK, force the likely EVS display via selector 0x008F, then clear selector 0x008F.",
"CONNECT NOT ACT globally clears the panel, so this scenario uses short observation windows to avoid mistaking timeout cleanup for selector clearing.",
"Record the panel within about one second of each write: EVS set, clear, and EVS set again."
],
"steps": [
{
"action": "power_cycle",
"off_seconds": 1.5
},
{
"action": "wait_ready",
"heartbeats": 2,
"timeout": 10.0,
"require": true
},
{
"action": "drain",
"seconds": 0.25
},
{
"action": "send",
"label": "selector_zero_connect_ok_seed",
"frame": "00 00 00 80 00 DA",
"listen": 0.25
},
{
"action": "send",
"label": "e000_008f_likely_evs",
"frame": "00 01 0F 08 00 5C",
"listen": 0.85
},
{
"action": "send",
"label": "e000_008f_clear",
"frame": "00 01 0F 00 00 54",
"listen": 0.85
},
{
"action": "send",
"label": "e000_008f_likely_evs_again",
"frame": "00 01 0F 08 00 5C",
"listen": 0.85
}
]
}

View File

@@ -0,0 +1,36 @@
{
"name": "shutter-008f-evs-timeout-control",
"notes": [
"Recover to CONNECT OK, force likely EVS via selector 0x008F, then deliberately do not clear it.",
"This is the negative control for the adjacent-selector methodology: if the panel later blanks or falls to CONNECT NOT ACT, that is timeout cleanup, not proof that 0x008F clear worked.",
"Record the time from EVS visibility to blank/CONNECT NOT ACT."
],
"steps": [
{
"action": "power_cycle",
"off_seconds": 1.5
},
{
"action": "wait_ready",
"heartbeats": 2,
"timeout": 10.0,
"require": true
},
{
"action": "drain",
"seconds": 0.25
},
{
"action": "send",
"label": "selector_zero_connect_ok_seed",
"frame": "00 00 00 80 00 DA",
"listen": 0.25
},
{
"action": "send",
"label": "e000_008f_likely_evs",
"frame": "00 01 0F 08 00 5C",
"listen": 4.0
}
]
}

View File

@@ -0,0 +1,236 @@
{
"name": "shutter-0093-bit-isolation",
"notes": [
"Recover to CONNECT OK, then isolate likely selector 0x0093 lamp/display bits with a clear and OK seed before each candidate.",
"Record white-balance PRESET, black/flare MANUAL, black/flare AUTO, shutter display, iris AUTO, and LCD state during each candidate window.",
"This follows the 0x0093=0x8000 and 0x0093=0xFFFF bench observations that affected lamps beyond the shutter cluster."
],
"steps": [
{
"action": "power_cycle",
"off_seconds": 1.5
},
{
"action": "wait_ready",
"heartbeats": 2,
"timeout": 10.0,
"require": true
},
{
"action": "drain",
"seconds": 0.25
},
{
"action": "send",
"label": "selector_zero_connect_ok_seed",
"frame": "00 00 00 80 00 DA",
"listen": 0.25
},
{
"action": "repeat",
"count": 1,
"steps": [
{
"action": "send",
"label": "e000_0093_clear_before_bit12",
"frame": "00 01 13 00 00 48",
"listen": 0.20
},
{
"action": "send",
"label": "selector_zero_ok_before_bit12",
"frame": "00 00 00 80 00 DA",
"listen": 0.10
},
{
"action": "send",
"label": "e000_0093_bit12_rom_gate",
"frame": "00 01 13 10 00 58",
"listen": 0.85
},
{
"action": "table_sweep",
"selectors": [
"0x093"
],
"gap": 0.20,
"ack_on": {
"enabled": false
}
},
{
"action": "send",
"label": "e000_0093_clear_before_bit5",
"frame": "00 01 13 00 00 48",
"listen": 0.20
},
{
"action": "send",
"label": "selector_zero_ok_before_bit5",
"frame": "00 00 00 80 00 DA",
"listen": 0.10
},
{
"action": "send",
"label": "e000_0093_bit5_rom_gate",
"frame": "00 01 13 00 20 68",
"listen": 0.85
},
{
"action": "table_sweep",
"selectors": [
"0x093"
],
"gap": 0.20,
"ack_on": {
"enabled": false
}
},
{
"action": "send",
"label": "e000_0093_clear_before_bits12_5",
"frame": "00 01 13 00 00 48",
"listen": 0.20
},
{
"action": "send",
"label": "selector_zero_ok_before_bits12_5",
"frame": "00 00 00 80 00 DA",
"listen": 0.10
},
{
"action": "send",
"label": "e000_0093_bits12_5",
"frame": "00 01 13 10 20 78",
"listen": 0.85
},
{
"action": "table_sweep",
"selectors": [
"0x093"
],
"gap": 0.20,
"ack_on": {
"enabled": false
}
},
{
"action": "send",
"label": "e000_0093_clear_before_bit15",
"frame": "00 01 13 00 00 48",
"listen": 0.20
},
{
"action": "send",
"label": "selector_zero_ok_before_bit15",
"frame": "00 00 00 80 00 DA",
"listen": 0.10
},
{
"action": "send",
"label": "e000_0093_bit15_seen_wb_preset_blackflare_manual",
"frame": "00 01 13 80 00 C8",
"listen": 0.85
},
{
"action": "table_sweep",
"selectors": [
"0x093"
],
"gap": 0.20,
"ack_on": {
"enabled": false
}
},
{
"action": "send",
"label": "e000_0093_clear_before_bits15_5",
"frame": "00 01 13 00 00 48",
"listen": 0.20
},
{
"action": "send",
"label": "selector_zero_ok_before_bits15_5",
"frame": "00 00 00 80 00 DA",
"listen": 0.10
},
{
"action": "send",
"label": "e000_0093_bits15_5",
"frame": "00 01 13 80 20 E8",
"listen": 0.85
},
{
"action": "table_sweep",
"selectors": [
"0x093"
],
"gap": 0.20,
"ack_on": {
"enabled": false
}
},
{
"action": "send",
"label": "e000_0093_clear_before_bits15_12",
"frame": "00 01 13 00 00 48",
"listen": 0.20
},
{
"action": "send",
"label": "selector_zero_ok_before_bits15_12",
"frame": "00 00 00 80 00 DA",
"listen": 0.10
},
{
"action": "send",
"label": "e000_0093_bits15_12",
"frame": "00 01 13 90 00 D8",
"listen": 0.85
},
{
"action": "table_sweep",
"selectors": [
"0x093"
],
"gap": 0.20,
"ack_on": {
"enabled": false
}
},
{
"action": "send",
"label": "e000_0093_clear_before_bits15_12_5",
"frame": "00 01 13 00 00 48",
"listen": 0.20
},
{
"action": "send",
"label": "selector_zero_ok_before_bits15_12_5",
"frame": "00 00 00 80 00 DA",
"listen": 0.10
},
{
"action": "send",
"label": "e000_0093_bits15_12_5",
"frame": "00 01 13 90 20 F8",
"listen": 0.85
},
{
"action": "table_sweep",
"selectors": [
"0x093"
],
"gap": 0.20,
"ack_on": {
"enabled": false
}
}
]
},
{
"action": "listen",
"seconds": 0.75
}
]
}

View File

@@ -0,0 +1,87 @@
{
"name": "shutter-0093-gate-8000",
"notes": [
"Recover to CONNECT OK, read the shutter cluster, set primary selector 0x0093 to 0x8000, then read the cluster again.",
"ROM trace shows E000[0x0093] gates adjacent shutter/clear-scan value lanes, but the exact bit meaning is not bench-confirmed.",
"CONNECT NOT ACT can clear the panel, so a fresh selector-zero OK seed is sent immediately before the 0x0093 write.",
"Record visual changes during the short post-write window, then use the second sweep for table evidence."
],
"steps": [
{
"action": "power_cycle",
"off_seconds": 1.5
},
{
"action": "wait_ready",
"heartbeats": 2,
"timeout": 10.0,
"require": true
},
{
"action": "drain",
"seconds": 0.25
},
{
"action": "send",
"label": "selector_zero_connect_ok_seed",
"frame": "00 00 00 80 00 DA",
"listen": 0.25
},
{
"action": "table_sweep",
"selectors": [
"0x08F",
"0x093",
"0x0A3",
"0x0A4",
"0x0A5",
"0x0D8",
"0x080",
"0x0D9",
"0x0A6",
"0x0DA",
"0x081"
],
"gap": 0.10,
"ack_on": {
"enabled": false
}
},
{
"action": "send",
"label": "selector_zero_connect_ok_seed_before_gate",
"frame": "00 00 00 80 00 DA",
"listen": 0.15
},
{
"action": "send",
"label": "e000_0093_gate_high_bit",
"frame": "00 01 13 80 00 C8",
"listen": 0.85
},
{
"action": "table_sweep",
"selectors": [
"0x08F",
"0x093",
"0x0A3",
"0x0A4",
"0x0A5",
"0x0D8",
"0x080",
"0x0D9",
"0x0A6",
"0x0DA",
"0x081"
],
"gap": 0.12,
"ack_on": {
"enabled": false
}
},
{
"action": "listen",
"seconds": 0.75
}
]
}

View File

@@ -0,0 +1,87 @@
{
"name": "shutter-0093-gate-ffff",
"notes": [
"Recover to CONNECT OK, read the shutter cluster, set primary selector 0x0093 to 0xFFFF, then read the cluster again.",
"This enables both ROM-observed gate bits 12 and 5, plus unknown bits, so run after shutter-0093-gate-8000.",
"CONNECT NOT ACT can clear the panel, so a fresh selector-zero OK seed is sent immediately before the 0x0093 write.",
"Record visual changes during the short post-write window, then use the second sweep for table evidence."
],
"steps": [
{
"action": "power_cycle",
"off_seconds": 1.5
},
{
"action": "wait_ready",
"heartbeats": 2,
"timeout": 10.0,
"require": true
},
{
"action": "drain",
"seconds": 0.25
},
{
"action": "send",
"label": "selector_zero_connect_ok_seed",
"frame": "00 00 00 80 00 DA",
"listen": 0.25
},
{
"action": "table_sweep",
"selectors": [
"0x08F",
"0x093",
"0x0A3",
"0x0A4",
"0x0A5",
"0x0D8",
"0x080",
"0x0D9",
"0x0A6",
"0x0DA",
"0x081"
],
"gap": 0.10,
"ack_on": {
"enabled": false
}
},
{
"action": "send",
"label": "selector_zero_connect_ok_seed_before_gate",
"frame": "00 00 00 80 00 DA",
"listen": 0.15
},
{
"action": "send",
"label": "e000_0093_all_bits",
"frame": "00 01 13 FF FF 48",
"listen": 0.85
},
{
"action": "table_sweep",
"selectors": [
"0x08F",
"0x093",
"0x0A3",
"0x0A4",
"0x0A5",
"0x0D8",
"0x080",
"0x0D9",
"0x0A6",
"0x0DA",
"0x081"
],
"gap": 0.12,
"ack_on": {
"enabled": false
}
},
{
"action": "listen",
"seconds": 0.75
}
]
}

View File

@@ -0,0 +1,55 @@
{
"name": "shutter-adjacent-readback",
"notes": [
"Recover to CONNECT OK, then read the currently known shutter/clear-scan selector cluster.",
"This is read-only after the selector-zero CONNECT seed and should be the first adjacent-selector bench run.",
"CONNECT NOT ACT can clear the panel during/after the sweep, so treat visual state at the end as timeout-contaminated.",
"Use this primarily for table readback rows and non-heartbeat frames, not for proving display clearing."
],
"steps": [
{
"action": "power_cycle",
"off_seconds": 1.5
},
{
"action": "wait_ready",
"heartbeats": 2,
"timeout": 10.0,
"require": true
},
{
"action": "drain",
"seconds": 0.25
},
{
"action": "send",
"label": "selector_zero_connect_ok_seed",
"frame": "00 00 00 80 00 DA",
"listen": 0.25
},
{
"action": "table_sweep",
"selectors": [
"0x08F",
"0x093",
"0x0A3",
"0x0A4",
"0x0A5",
"0x0D8",
"0x080",
"0x0D9",
"0x0A6",
"0x0DA",
"0x081"
],
"gap": 0.12,
"ack_on": {
"enabled": false
}
},
{
"action": "listen",
"seconds": 0.75
}
]
}