Changes
This commit is contained in:
@@ -37,7 +37,8 @@ from dotenv import load_dotenv
|
||||
import ai_mgmt
|
||||
import rigol_scope
|
||||
from csv_preprocessor import (analyze_lp_file, LPMetrics,
|
||||
HS_BURST_AMPLITUDE_MIN_MV, FLICKER_LP_LOW_MAX_NS)
|
||||
HS_BURST_AMPLITUDE_MIN_MV, FLICKER_LP_LOW_MAX_NS,
|
||||
analyze_int_file, CLK_LP_LOW_MIN_NS)
|
||||
|
||||
load_dotenv(Path(__file__).parent / ".env")
|
||||
|
||||
@@ -573,6 +574,94 @@ def _fetch_registers(ts: str, iteration: int) -> None:
|
||||
print(f" REGISTERS: error — {e}")
|
||||
|
||||
|
||||
def _arm_scope_for_clk_startup() -> None:
|
||||
"""
|
||||
Configure scope for CLK lane LP startup and arm with :SINGle (non-blocking).
|
||||
Trigger: CLK+ (Ch1) falling edge — fires as CLK leaves LP-11, before DAT0+.
|
||||
Call this BEFORE display ON so the trigger is armed when the LP-11→HS sequence starts.
|
||||
"""
|
||||
for ch in (1, 2, 3, 4):
|
||||
scope.write(f":CHANnel{ch}:SCALe {LP_V_SCALE:.3f}")
|
||||
scope.write(f":CHANnel{ch}:OFFSet {LP_V_OFFSET:.3f}")
|
||||
time.sleep(0.05)
|
||||
scope.write(":TRIGger:EDGE:SOURce CHANnel1")
|
||||
scope.write(":TRIGger:EDGE:SLOPe NEGative")
|
||||
scope.write(f":TRIGger:EDGE:LEVel {LP_TRIG_LEVEL:.3f}")
|
||||
scope.write(":TRIGger:SWEep NORMal")
|
||||
scope.write(f":TIMebase:SCALe {LP_SCALE:.3E}")
|
||||
scope.write(f":ACQuire:POINts {LP_POINTS}")
|
||||
time.sleep(0.3)
|
||||
scope.write(":SINGle")
|
||||
time.sleep(0.1)
|
||||
print(" CLK STARTUP: scope armed on CLK+ falling edge.")
|
||||
|
||||
|
||||
def _collect_clk_startup(ts: str, iteration: int, timeout: float = 10.0) -> list[str]:
|
||||
"""
|
||||
Poll for CLK startup trigger, save, transfer, and analyse the capture.
|
||||
Returns LP summary strings (empty list if trigger timed out).
|
||||
The CLK LP-00 duration is checked against the 300 ns SN65DSI83 lock minimum.
|
||||
"""
|
||||
print(" CLK STARTUP: waiting for trigger...")
|
||||
deadline = time.time() + timeout
|
||||
triggered = False
|
||||
while time.time() < deadline:
|
||||
try:
|
||||
status = scope.ask(":TRIGger:STATus?").strip().upper()
|
||||
if status in ("STOP", "TD"):
|
||||
triggered = True
|
||||
break
|
||||
except Exception:
|
||||
pass
|
||||
time.sleep(0.1)
|
||||
|
||||
if not triggered:
|
||||
print(" CLK STARTUP: trigger timeout — CLK may already be in continuous HS.")
|
||||
_restore_hs_config()
|
||||
return []
|
||||
|
||||
_save_pass_channels("lp", iteration, ts)
|
||||
_restore_hs_config()
|
||||
|
||||
try:
|
||||
copied, _ = ai_mgmt.transfer_csv_files()
|
||||
print(f" CLK STARTUP: {copied} file(s) transferred.")
|
||||
except Exception as e:
|
||||
print(f" CLK STARTUP TRANSFER ERROR: {e}")
|
||||
|
||||
summaries = []
|
||||
for channel in ("clk", "dat"):
|
||||
path = DATA_DIR / f"{ts}_lp_{iteration:04d}_{channel}.csv"
|
||||
if not path.exists():
|
||||
continue
|
||||
try:
|
||||
m = analyze_lp_file(path)
|
||||
summaries.append(m.summary())
|
||||
if m.clk_lp_startup_ok is False:
|
||||
print(f"\n *** CLK STARTUP WARNING: CLK LP-00 too short "
|
||||
f"({m.lp_low_duration_ns:.0f} ns < {CLK_LP_LOW_MIN_NS:.0f} ns) — "
|
||||
f"SN65DSI83 may fail to lock CLK lane ***\n")
|
||||
except Exception as e:
|
||||
print(f" CLK STARTUP ANALYSIS ERROR ({channel}): {e}")
|
||||
|
||||
return summaries
|
||||
|
||||
|
||||
def _analyze_int_file(ts: str, iteration: int) -> None:
|
||||
"""Print IRQ pin summary and alert if the SN65DSI83 asserted the IRQ line."""
|
||||
path = DATA_DIR / f"{ts}_int_{iteration:04d}.csv"
|
||||
if not path.exists():
|
||||
return
|
||||
try:
|
||||
m = analyze_int_file(path)
|
||||
print(m.summary())
|
||||
if m.int_asserted:
|
||||
print(f"\n *** IRQ ASSERTED: SN65DSI83 flagged a bridge error at "
|
||||
f"capture {iteration:04d} — check CSR 0xE5 for error bits ***\n")
|
||||
except Exception as e:
|
||||
print(f" INT ANALYSIS ERROR: {e}")
|
||||
|
||||
|
||||
def dual_capture(iteration: int) -> str:
|
||||
"""
|
||||
Three-pass capture per test iteration.
|
||||
@@ -603,7 +692,13 @@ def dual_capture(iteration: int) -> str:
|
||||
if n:
|
||||
print(f" SAVED: {v18_path.name} ({n} samples)")
|
||||
else:
|
||||
print(" RIGOL: Waveform read failed — check connection and probe.")
|
||||
print(" RIGOL CH1: waveform read failed — check connection and probe.")
|
||||
int_path = DATA_DIR / f"{ts}_int_{iteration:04d}.csv"
|
||||
n_int = rigol_scope.read_int_csv(int_path)
|
||||
if n_int:
|
||||
print(f" SAVED: {int_path.name} ({n_int} samples)")
|
||||
else:
|
||||
print(" RIGOL CH2: IRQ read failed.")
|
||||
_restore_hs_config()
|
||||
|
||||
# ── Pass 2: HS signal quality ──────────────────────────────────────────
|
||||
@@ -1193,12 +1288,19 @@ def run_interactive_test() -> None:
|
||||
|
||||
try:
|
||||
while True:
|
||||
# ── Arm scope for CLK startup BEFORE display ON ────────────────
|
||||
ts_startup = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
_arm_scope_for_clk_startup()
|
||||
|
||||
# ── Display ON ─────────────────────────────────────────────────
|
||||
try:
|
||||
requests.put(URL, json={"state": "on"}, timeout=2)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f" WARNING: display ON failed: {e}")
|
||||
|
||||
# ── Collect CLK startup (polls, saves, transfers, analyses) ────
|
||||
_collect_clk_startup(ts_startup, iteration)
|
||||
|
||||
# ── Three-pass capture ─────────────────────────────────────────
|
||||
ts = dual_capture(iteration)
|
||||
|
||||
@@ -1210,6 +1312,9 @@ def run_interactive_test() -> None:
|
||||
except Exception as e:
|
||||
print(f" TRANSFER ERROR: {e}")
|
||||
|
||||
# ── IRQ pin analysis ───────────────────────────────────────────
|
||||
_analyze_int_file(ts, iteration)
|
||||
|
||||
# ── Rule-based LP analysis ─────────────────────────────────────
|
||||
lp_summaries, suspects = _analyze_lp_files(ts, iteration)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user