35 lines
1023 B
Python
35 lines
1023 B
Python
#!/usr/bin/env python3
|
|
"""Analyze a captured frame: extract pulse timing structure.
|
|
|
|
Usage: .venv/bin/python tools/analyze.py captures/<name>.npz
|
|
"""
|
|
import sys
|
|
|
|
import numpy as np
|
|
|
|
path = sys.argv[1]
|
|
d = np.load(path)
|
|
volts = d["volts"]
|
|
srate = float(d["srate"])
|
|
dt_us = 1e6 / srate
|
|
|
|
# threshold midway between the two dominant plateaus
|
|
hi_level = np.median(volts) # idle dominates the frame -> median = idle (high)
|
|
lo_level = np.percentile(volts, 10)
|
|
thr = (hi_level + lo_level) / 2
|
|
bits = (volts > thr).astype(np.int8)
|
|
print(f"levels: high~{hi_level:.2f} low~{lo_level:.2f} thr={thr:.2f} (raw units)")
|
|
|
|
# run-length encode
|
|
edges = np.flatnonzero(np.diff(bits)) + 1
|
|
starts = np.concatenate(([0], edges))
|
|
ends = np.concatenate((edges, [len(bits)]))
|
|
levels = bits[starts]
|
|
dur_us = (ends - starts) * dt_us
|
|
|
|
print(f"{len(levels)} runs total")
|
|
print("\nidx level dur_us (first/last runs are idle padding)")
|
|
for i, (lv, du) in enumerate(zip(levels, dur_us)):
|
|
tag = "H" if lv else "L"
|
|
print(f"{i:4d} {tag} {du:10.2f}")
|