Chnages
This commit is contained in:
@@ -104,23 +104,51 @@ def find_clock_edges(t_clk, v_clk, threshold=0.0):
|
||||
|
||||
def find_hs_start(t_dat, v_dat, t_clk=None, window_ns=500.0):
|
||||
"""
|
||||
Find the start of the main HS burst in the DAT trace.
|
||||
Find the start of the post-LP HS burst in the DAT trace.
|
||||
|
||||
The proto capture often starts mid-HS (previous packet), so we:
|
||||
1. Find the LP quiet region (both LP-11 and LP-low have low differential std)
|
||||
2. Find the first sustained oscillation AFTER that quiet region
|
||||
For LP-triggered captures (trigger = DAT D+ falling at LP-11→LP-01 transition):
|
||||
- CLK is in continuous HS mode throughout (215 MHz running)
|
||||
- DAT shows LP-01 (diff ≈ -1 V) near t=0, preceded by HS data from the
|
||||
previous line and possibly an earlier LP-01 at the start of the capture
|
||||
- LP-00 follows LP-01 briefly (~50-200 ns), then the new HS burst begins
|
||||
- To avoid the LP-01 from the previous line (at capture start), search
|
||||
from N//4 onwards — the trigger LP-01 is at the capture midpoint (t=0)
|
||||
|
||||
Returns: index into t_dat of approximate HS burst start, or None.
|
||||
Returns index into t_dat just past LP-00, ready for CLK-edge sampling.
|
||||
Falls back to original std-based method for HS-triggered captures.
|
||||
"""
|
||||
dt_ns = float(np.median(np.diff(t_dat))) * 1e9
|
||||
win = max(1, int(1.0 / dt_ns)) # 1 ns rolling window
|
||||
min_run = max(5, int(5.0 / dt_ns)) # at least 5 ns continuous
|
||||
dt_ns = float(np.median(np.diff(t_dat))) * 1e9
|
||||
N = len(v_dat)
|
||||
|
||||
rstd = np.array([v_dat[max(0, i - win):i + 1].std() for i in range(len(v_dat))])
|
||||
OSC_THRESH = 0.04 # 40 mV — HS oscillation
|
||||
QUIET_THRESH = 0.02 # 20 mV — LP quiet (LP-11 differential ≈ 0, low std)
|
||||
# --- LP-triggered path ---
|
||||
# LP-01: D+ = 0 V, D- = high → diff strongly negative (< -0.5 V for ≥ 20 ns)
|
||||
LP01_THRESH = -0.5
|
||||
min_lp01 = max(2, int(20.0 / dt_ns))
|
||||
search_from = N // 4 # skip any LP-01 fragment at capture start
|
||||
|
||||
run = 0
|
||||
lp01_end = None
|
||||
for i in range(search_from, N):
|
||||
if v_dat[i] < LP01_THRESH:
|
||||
run += 1
|
||||
else:
|
||||
if run >= min_lp01:
|
||||
lp01_end = i
|
||||
break
|
||||
run = 0
|
||||
|
||||
if lp01_end is not None:
|
||||
# Skip 200 ns past LP-01 end to clear LP-00, then hand off to bit decoder
|
||||
skip = max(1, int(200.0 / dt_ns))
|
||||
return min(lp01_end + skip, N - 1)
|
||||
|
||||
# --- Fallback: HS-triggered captures (original rolling-std method) ---
|
||||
win = max(1, int(1.0 / dt_ns))
|
||||
min_run = max(5, int(5.0 / dt_ns))
|
||||
rstd = np.array([v_dat[max(0, i - win):i + 1].std() for i in range(N)])
|
||||
OSC_THRESH = 0.04
|
||||
QUIET_THRESH = 0.02
|
||||
|
||||
# Step 1: find a quiet (LP) region of at least 200 ns
|
||||
quiet_min_run = max(5, int(200.0 / dt_ns))
|
||||
quiet_end = None
|
||||
run_len = 0
|
||||
@@ -133,9 +161,8 @@ def find_hs_start(t_dat, v_dat, t_clk=None, window_ns=500.0):
|
||||
run_len = 0
|
||||
|
||||
if quiet_end is None:
|
||||
return None # no LP region found
|
||||
return None
|
||||
|
||||
# Step 2: find first sustained oscillation after the LP region
|
||||
run_start = None
|
||||
run_len = 0
|
||||
for i in range(quiet_end, len(rstd)):
|
||||
@@ -273,7 +300,7 @@ def decode_capture(cap_num: int, data_dir: Path, verbose: bool = True):
|
||||
dt_ns = float(np.median(np.diff(t_dat))) * 1e9
|
||||
|
||||
if verbose:
|
||||
print(f" Window: {t_dat[0]*1e6:.2f}..{t_dat[-1]*1e6:.2f} µs ({len(t_dat)} samples, {dt_ns:.0f} ps/sample)")
|
||||
print(f" Window: {t_dat[0]*1e6:.2f}..{t_dat[-1]*1e6:.2f} µs ({len(t_dat)} samples, {dt_ns*1000:.0f} ps/sample)")
|
||||
|
||||
# Find HS burst start
|
||||
hs_start_idx = find_hs_start(t_dat, v_dat)
|
||||
@@ -299,18 +326,33 @@ def decode_capture(cap_num: int, data_dir: Path, verbose: bool = True):
|
||||
print(" ERROR: Too few bits decoded")
|
||||
return None
|
||||
|
||||
raw_bytes = bits_to_bytes(bits)
|
||||
# Try all 8 bit-phase offsets to handle framing uncertainty from LP-00 CLK edges.
|
||||
# LP-00 CLK edges before HS starts produce garbage bits; the correct phase is
|
||||
# the one where 0xB8 appears earliest in the byte stream.
|
||||
raw_bytes = None
|
||||
sync_idx = None
|
||||
best_phase = 0
|
||||
best_sync = len(bits) # sentinel: "not found"
|
||||
for phase in range(8):
|
||||
rb = bits_to_bytes(bits[phase:])
|
||||
si = find_sync_byte(rb)
|
||||
if si is not None and si < best_sync:
|
||||
best_sync = si
|
||||
best_phase = phase
|
||||
raw_bytes = rb
|
||||
sync_idx = si
|
||||
|
||||
if raw_bytes is None:
|
||||
raw_bytes = bits_to_bytes(bits)
|
||||
|
||||
# Find sync byte alignment
|
||||
sync_idx = find_sync_byte(raw_bytes)
|
||||
if sync_idx is None:
|
||||
if verbose:
|
||||
print(f" WARNING: HS sync byte (0x{HS_SYNC_BYTE:02X}) not found — using raw byte 0 as start")
|
||||
print(f" WARNING: HS sync byte (0x{HS_SYNC_BYTE:02X}) not found in any bit phase — using raw byte 0")
|
||||
sync_idx = 0
|
||||
else:
|
||||
if verbose:
|
||||
t_sync = raw_bytes[sync_idx][0]
|
||||
print(f" HS sync byte found at byte {sync_idx} (t={t_sync:.0f} ns)")
|
||||
print(f" HS sync byte found at byte {sync_idx} (t={t_sync:.0f} ns, bit phase={best_phase})")
|
||||
|
||||
# Data bytes after sync
|
||||
data_bytes = raw_bytes[sync_idx + 1:] # skip the sync byte itself
|
||||
|
||||
Reference in New Issue
Block a user