chore: 文件夹更名 HDMI-Tool -> DLPilot(路径与文档此前已对齐)

This commit is contained in:
2026-09-14 15:25:05 +08:00
parent f0f8073afc
commit a6721415a6
57 changed files with 0 additions and 0 deletions
+120
View File
@@ -0,0 +1,120 @@
# Kingst VIS 压缩边沿流分析: 数字波形按占空比签名自动分段, 输出行结构/占空比/消隐明细
# 用法: python la_wave_analyzer.py <capture.csv>
# CSV 列: Time[s], 通道A, 通道B (时间分辨率 10ns; 默认抓 B 通道 D0/D1)
# 判读基线见 doc/architecture/rgb_bit_swap_test.md §1.1
import csv, statistics, time, sys
PATH = sys.argv[1] if len(sys.argv) > 1 else \
r"E:\Hulk-Coding\LT8619C_DLPC3421_HDMI\tools\wave\B-D0-D7.csv"
CLK_NS = 25.0 # 40MHz 像素时钟
t0 = time.time()
rows = []
with open(PATH, encoding='utf-8-sig', errors='replace') as f:
r = csv.reader(f)
next(r) # header
for row in r:
if len(row) < 3:
continue
rows.append((float(row[0]) * 1e9, int(row[1]), int(row[2]))) # ns
n = len(rows)
t_start, t_stop = rows[0][0], rows[-1][0] + 1000.0 # 末行状态延续按1us估
print(f"rows={n} span={t_stop - t_start / 1e9:.9f}s")
# ---- 按行区间累计高低时间, 50ms 窗口计算占空比 ----
W = 50_000_000.0 # ns
win = {'t0': t_start, 'hi0': 0.0, 'hi1': 0.0}
wins = []
for i in range(n - 1):
t, d0, d1 = rows[i]
dt = min(rows[i + 1][0], t_stop) - t
if dt <= 0:
continue
win['hi0'] += dt if d0 else 0.0
win['hi1'] += dt if d1 else 0.0
if rows[i + 1][0] - win['t0'] >= W:
span = rows[i + 1][0] - win['t0']
wins.append((win['t0'], win['hi0'] / span, win['hi1'] / span))
win = {'t0': rows[i + 1][0], 'hi0': 0.0, 'hi1': 0.0}
# ---- 窗口分类: 依 (d0duty, d1duty) 签名 ----
def classify(a, b):
hi = lambda x: x > 0.5
if hi(a) and hi(b):
return 'FF'
if hi(a) and not hi(b):
return '55'
if not hi(a) and hi(b):
return 'AA'
return '00'
segs = []
for t, a, b in wins:
c = classify(a, b)
if segs and segs[-1][0] == c:
segs[-1][1].append((t, a, b))
else:
segs.append((c, [(t, a, b)]))
print(f"\n{'':<4}{'签名':<6}{'时长(s)':<10}{'D0占空':<10}{'D1占空':<10}")
for i, (c, ws) in enumerate(segs):
dur = (ws[-1][0] - ws[0][0]) / 1e9
a = statistics.mean(x[1] for x in ws)
b = statistics.mean(x[2] for x in ws)
print(f"{i:<6}{c:<8}{dur:<12.2f}{a:<12.1%}{b:<12.1%}")
# ---- 每段: 行周期 + 有效区宽度(长高电平段) ----
print(f"\n按段结构分析 (时钟数 @40MHz):")
for i, (c, ws) in enumerate(segs):
seg_t0 = ws[0][0] - W / 2
seg_t1 = ws[-1][0] + W / 2
ch = 0 if c in ('FF', '55') else 1 # 选有效区为高的通道
# 找长高电平段(>=15us)及其起点
starts, widths = [], []
for j in range(n - 1):
t, d0, d1 = rows[j]
if t < seg_t0 or t > seg_t1:
continue
lvl = d0 if ch == 0 else d1
if lvl and rows[j + 1][0] - t >= 15_000.0:
starts.append(t)
widths.append(rows[j + 1][0] - t)
if len(starts) < 3:
print(f"{i} [{c}]: 线段不足({len(starts)}), 跳过")
continue
periods = [b - a for a, b in zip(starts, starts[1:]) if 20_000 < b - a < 35_000]
mp = statistics.median(periods)
mw = statistics.median(widths)
print(f"{i} [{c}]: 行数~{len(starts)} 行周期={mp:.0f}ns={mp/CLK_NS:.1f}clk "
f"有效高={mw:.0f}ns={mw/CLK_NS:.1f}clk 消隐={(mp-mw)/CLK_NS:.1f}clk")
# ---- 每段抽一行: 消隐区的边沿明细 ----
print(f"\n消隐区边沿明细(每段第一行, ns 相对行起点, clk=时钟数):")
for i, (c, ws) in enumerate(segs):
seg_t0 = ws[0][0] - W / 2
ch = 0 if c in ('FF', '55') else 1
line_start = None
for j in range(n - 1):
t, d0, d1 = rows[j]
if t < seg_t0:
continue
lvl = d0 if ch == 0 else d1
if lvl and rows[j + 1][0] - t >= 15_000.0:
line_start = t
break
if line_start is None:
continue
print(f"{i} [{c}] 行起点+有效区之后:")
j0 = next(k for k in range(n - 1) if rows[k][0] >= line_start)
out = []
for k in range(j0, min(j0 + 30, n - 1)):
t, d0, d1 = rows[k]
dt = rows[k + 1][0] - t
rel = t - line_start
out.append(f" +{rel/1000:8.2f}us D0={d0} D1={d1} 持续{dt/CLK_NS:6.1f}clk")
if rel > 30_000:
break
print('\n'.join(out[:18]))
print(f"\n耗时 {time.time()-t0:.1f}s")