This commit is contained in:
david rice
2026-05-07 09:01:32 +01:00
parent 9c75598728
commit dd93fbd893
4 changed files with 531 additions and 64 deletions

View File

@@ -1535,37 +1535,30 @@ def run_interactive_test() -> None:
def run_continuous_test() -> None:
"""
Continuous LP capture loop — no kiosk restart between iterations.
Continuous LP capture loop — pipeline restart per iteration.
Designed for periodic flicker that repeats roughly every second once the
display pipeline has started. The kiosk is started once; the scope
re-arms on the NORMAL LP trigger (VBLANK LP-11 → LP-01 falling edge on
Ch3) after each capture, effectively sampling one random display frame
every ~7 s.
The pipeline (kiosk) is stopped and restarted on every iteration so the
scope captures the startup LP-11→LP-01 transition that triggers the flicker.
The scope is configured and armed BEFORE _start_video() is called so that
the first HS burst after pipeline load is always captured.
With flicker on ~1/60 frames the expected time to first catch is
~60 × 7 s ≈ 7 minutes of unattended running.
Sequence per iteration:
1. _stop_video() — tear down pipeline
2. _configure_for_lp() — set scope channels + trigger (takes ~400 ms)
3. _start_video() — reload pipeline (LP transition fires ~1-2 s later)
4. _arm_and_wait() — scope captures first LP-11→LP-01 on Ch3
5. Transfer + LP analysis
6. If suspect: LP bit decode + byte comparison vs last clean capture
When the LP rule-based detector flags a suspect:
• The LP file already on disk (10 GSa/s, 100 ps/sample) is decoded
directly using single-ended CLK+/DAT0+ thresholds — no extra capture.
• proto_decoder checks the HS-SYNC byte position (misalignment) and the
Lane 0 pixel content (corruption).
• compare_lp_captures() shows byte-level diffs vs the last clean capture.
Press Ctrl+C to stop. No report is written (raw LP/proto CSVs are kept).
Press Ctrl+C to stop. No HTML report is written; raw LP CSVs are kept in data/.
"""
import proto_decoder as _pd
print("\n===== CONTINUOUS CAPTURE MODE =====")
print("Kiosk starts once. Scope re-arms on each VBLANK trigger (no restart).")
print("LP-only per iteration; LP bit decode fires directly on LP suspect files.")
print("Pipeline restart per iteration — captures startup LP transition.")
print("LP bit decode fires automatically on flicker suspects.")
print("Press Ctrl+C to stop.\n")
_start_video()
print("Waiting 5 s for display pipeline to stabilise...")
time.sleep(5.0)
iteration = 1
clean_count = 0
flicker_count = 0
@@ -1575,11 +1568,20 @@ def run_continuous_test() -> None:
while True:
ts = datetime.now().strftime("%Y%m%d_%H%M%S")
# ── LP capture ──────────────────────────────────────────────────
# ── Stop pipeline, configure scope, then restart pipeline ─────────
_stop_video()
time.sleep(0.3)
# Configure scope while pipeline is down — scope will be ready before
# the first LP edge fires after _start_video().
_configure_for_lp()
_set_timebase(LP_SCALE, LP_POINTS)
scope.write(f":TIMebase:POSition {LP_TRIG_OFFSET:.2E}")
ok = _arm_and_wait(timeout=5)
_start_video()
# ── LP capture on startup transition ─────────────────────────────
ok = _arm_and_wait(timeout=10)
scope.write(":TIMebase:POSition 0")
_restore_hs_config()
@@ -1598,7 +1600,7 @@ def run_continuous_test() -> None:
iteration += 1
continue
# ── LP analysis (quiet) ──────────────────────────────────────────
# ── LP analysis ──────────────────────────────────────────────────
lp_summaries, suspects = _analyze_lp_files(ts, iteration)
if not suspects:
@@ -1662,7 +1664,7 @@ def main_menu() -> None:
print("3. CONFIGURE PSU (DEFAULT 24V / 1.5A)")
print("4. PSU OUTPUT ON/OFF (CH1)")
print("5. START INTERACTIVE FLICKER TEST (kiosk restart per iteration)")
print("6. START CONTINUOUS CAPTURE TEST (no restart; LP bit decode on flicker)")
print("6. START CONTINUOUS CAPTURE TEST (no restart; proto decode on flicker)")
print("7. EXIT")
choice = input("\nSELECT OPTION (1-7): ").strip()