Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e6107b490 | ||
|
|
9772a2bf83 | ||
|
|
cd14ed2ca4 | ||
|
|
4cc418f863 | ||
|
|
040b628d54 | ||
|
|
51e2f1c51c | ||
|
|
8497b1979a | ||
|
|
05e4f3ae92 | ||
|
|
059ce6a540 | ||
|
|
b167ce3401 | ||
|
|
a6721415a6 | ||
|
|
f0f8073afc | ||
|
|
3f35ad2c21 | ||
|
|
c1a5712f76 | ||
|
|
8e8811a4a0 | ||
|
|
b70cf102fd | ||
|
|
b36dd3911f | ||
|
|
cda1e72f17 | ||
|
|
744fbfd298 | ||
|
|
90433064ec | ||
|
|
68c7909922 | ||
|
|
e131646156 | ||
|
|
96df14caea | ||
|
|
d92156e0cd | ||
|
|
f549ddf48b | ||
|
|
84838e3e74 | ||
|
|
1a9927d9bb | ||
|
|
22d0969569 | ||
|
|
d9ecff4e49 | ||
|
|
2459b33162 | ||
|
|
efaf4d658f | ||
|
|
a14e3e7621 | ||
|
|
a1f6fdd34a | ||
|
|
0977b275ee | ||
|
|
736b43efe4 | ||
|
|
d0cefeebf3 |
@@ -8,8 +8,10 @@ dist/
|
|||||||
*.spec
|
*.spec
|
||||||
|
|
||||||
# 发布 zip: 可由 src/package_release.py 重新生成, 只上传 Gitea Release
|
# 发布 zip: 可由 src/package_release.py 重新生成, 只上传 Gitea Release
|
||||||
HDMI-Tool/release/*.zip
|
|
||||||
DLPilot/release/*.zip
|
DLPilot/release/*.zip
|
||||||
|
|
||||||
|
# 源码模式运行时的配置写入(config.BASE_DIR=src/), 与 release/ 下入库的预置栏位区分
|
||||||
|
DLPilot/src/pattern_slots.json
|
||||||
|
|
||||||
# ZCode 客户端本地会话数据(计划留档等), 非项目配置
|
# ZCode 客户端本地会话数据(计划留档等), 非项目配置
|
||||||
.zcode/
|
.zcode/
|
||||||
|
|||||||
@@ -101,11 +101,16 @@ DLPilot/
|
|||||||
**同时是转接板光机 DLPC3421 的 nHD 面板原生分辨率**(该板 shadow EDID 只声明 640x360@60),
|
**同时是转接板光机 DLPC3421 的 nHD 面板原生分辨率**(该板 shadow EDID 只声明 640x360@60),
|
||||||
投 640x360 图案 + RS485 开光机 = 整链路 1:1 验证。
|
投 640x360 图案 + RS485 开光机 = 整链路 1:1 验证。
|
||||||
- bw 系列图案各自目的见 `src/gen_bw_patterns.py` 顶部清单注释。
|
- bw 系列图案各自目的见 `src/gen_bw_patterns.py` 顶部清单注释。
|
||||||
- 光机 RS485 命令集(M730/M731/M732/M201/M202/M737/M999/M888/M7/M8/M1)语义、
|
- 光机 RS485 命令集(M730/M731/M732/M201/M202/M737/M999/M888/M7/M8/M1/**M303/M304**)语义、
|
||||||
帧格式 `D5 01 LEN <ASCII> CRC`(累加和校验)、错误码与**就绪门禁**
|
帧格式 `D5 01 LEN <ASCII> CRC`(累加和校验)、错误码与**就绪门禁**
|
||||||
(DLPC 未就绪时 M730/M731/M732 被拒回 0xFF)以上游 `protocols.md` 为唯一权威,
|
(DLPC 未就绪时 M730/M731/M732 被拒回 0xFF)以上游 `protocols.md` 为唯一权威,
|
||||||
本仓不维护协议文档副本;注意 **M7S0 是"开启"TEC 自动控温**(方向反直觉)、
|
本仓不维护协议文档副本;注意 **M7S0 是"开启"TEC 自动控温**(方向反直觉)、
|
||||||
M737 在定时投光中延迟应答(CLI 等待上限 35s)。
|
M737 在定时投光中延迟应答(CLI 等待上限 35s)。
|
||||||
|
- **M303/M304 载荷是二进制例外**(SQ52205 电源实测):成功载荷 2 字节大端原始值,
|
||||||
|
**不是 ASCII**——Frame.payload 解出来是乱码,必须走 `payload_bytes()` 取原始字节;
|
||||||
|
M303=u16 mV(12V 轨窗口 11400~12600),M304=s16 补码 mA(正=正向,固件原样上总线,
|
||||||
|
上位机按有符号解析,FF 06=−250)。封装在 `payload_u16_be/payload_s16_be/format_power`,
|
||||||
|
回归向量在 selftest_rs485.py(真机抓取帧)。
|
||||||
|
|
||||||
## 5. 构建 / 发布流水线(全部在 src/ 下执行)
|
## 5. 构建 / 发布流水线(全部在 src/ 下执行)
|
||||||
|
|
||||||
@@ -61,7 +61,8 @@ DLPilot/
|
|||||||
1. 左上显示器下拉选择目标屏(多屏时注意别选成主屏),"刷新"重新枚举;
|
1. 左上显示器下拉选择目标屏(多屏时注意别选成主屏),"刷新"重新枚举;
|
||||||
2. **切分辨率**:"支持的模式"卡片里选模式 → "应用";测完点"恢复";
|
2. **切分辨率**:"支持的模式"卡片里选模式 → "应用";测完点"恢复";
|
||||||
3. **投测试图**:"测试图案"卡片先选**测试卡区域**(640x360 / 800x600 / full)→
|
3. **投测试图**:"测试图案"卡片先选**测试卡区域**(640x360 / 800x600 / full)→
|
||||||
点图案按钮全屏投放,按 **ESC** 或点击退出;R/G/B 纯色按钮(55/AA/FF,按通道着色)
|
点图案按钮全屏投放(新图案自动替换旧图案),按 **ESC** 或点"停止测试图像"退出;
|
||||||
|
R/G/B 纯色按钮(55/AA/FF,按通道着色)
|
||||||
用于 RGB 位交换类测试;自定义图片点齿轮按钮配置(图片自动复制到 exe 旁),
|
用于 RGB 位交换类测试;自定义图片点齿轮按钮配置(图片自动复制到 exe 旁),
|
||||||
"校准图案"一排为 3D 光固化测试/校准图预留槽位;
|
"校准图案"一排为 3D 光固化测试/校准图预留槽位;
|
||||||
4. **光机控制**:右列选串口与参数(波特率/数据位/校验/停止位,默认 115200 8-N-1)→ 连接 →
|
4. **光机控制**:右列选串口与参数(波特率/数据位/校验/停止位,默认 115200 8-N-1)→ 连接 →
|
||||||
@@ -105,6 +106,8 @@ GUI"光机控制"区:选串口 → 连接 → 点快捷按钮或命令下拉/
|
|||||||
| `M731S100` | 设光强 54-800(RGB 同值,写后读回复核) | `ok` / `err:R..G..B..` |
|
| `M731S100` | 设光强 54-800(RGB 同值,写后读回复核) | `ok` / `err:R..G..B..` |
|
||||||
| `M732` | 查三路电流设置值(0-65535) | `okR110G110B110` |
|
| `M732` | 查三路电流设置值(0-65535) | `okR110G110B110` |
|
||||||
| `M201` / `M202` | 查 DMD / LAMP 温度(0.1°C) | `okTL:246` = 24.6°C |
|
| `M201` / `M202` | 查 DMD / LAMP 温度(0.1°C) | `okTL:246` = 24.6°C |
|
||||||
|
| `M303` | 查母线电压(SQ52205 实测,**2 字节大端二进制载荷**) | 0x2EF4 = 12020 mV = 12.02 V(12V 轨窗口 11400~12600) |
|
||||||
|
| `M304` | 查负载电流(SQ52205 实测,**2 字节大端二进制载荷**) | s16 补码 mA:0x0034=+52;FF 06=−250(正=正向) |
|
||||||
| `M999` | 查固件版本 | `okv20.0.0.1` |
|
| `M999` | 查固件版本 | `okv20.0.0.1` |
|
||||||
| `M737` | 查投光是否结束(投光中延迟应答) | `ok` |
|
| `M737` | 查投光是否结束(投光中延迟应答) | `ok` |
|
||||||
| `M7S0` / `M7S1` | TEC 自动控温开 / 关(注意 S0=开) | `ok` |
|
| `M7S0` / `M7S1` | TEC 自动控温开 / 关(注意 S0=开) | `ok` |
|
||||||
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
@@ -61,7 +61,8 @@ DLPilot/
|
|||||||
1. 左上显示器下拉选择目标屏(多屏时注意别选成主屏),"刷新"重新枚举;
|
1. 左上显示器下拉选择目标屏(多屏时注意别选成主屏),"刷新"重新枚举;
|
||||||
2. **切分辨率**:"支持的模式"卡片里选模式 → "应用";测完点"恢复";
|
2. **切分辨率**:"支持的模式"卡片里选模式 → "应用";测完点"恢复";
|
||||||
3. **投测试图**:"测试图案"卡片先选**测试卡区域**(640x360 / 800x600 / full)→
|
3. **投测试图**:"测试图案"卡片先选**测试卡区域**(640x360 / 800x600 / full)→
|
||||||
点图案按钮全屏投放,按 **ESC** 或点击退出;R/G/B 纯色按钮(55/AA/FF,按通道着色)
|
点图案按钮全屏投放(新图案自动替换旧图案),按 **ESC** 或点"停止测试图像"退出;
|
||||||
|
R/G/B 纯色按钮(55/AA/FF,按通道着色)
|
||||||
用于 RGB 位交换类测试;自定义图片点齿轮按钮配置(图片自动复制到 exe 旁),
|
用于 RGB 位交换类测试;自定义图片点齿轮按钮配置(图片自动复制到 exe 旁),
|
||||||
"校准图案"一排为 3D 光固化测试/校准图预留槽位;
|
"校准图案"一排为 3D 光固化测试/校准图预留槽位;
|
||||||
4. **光机控制**:右列选串口与参数(波特率/数据位/校验/停止位,默认 115200 8-N-1)→ 连接 →
|
4. **光机控制**:右列选串口与参数(波特率/数据位/校验/停止位,默认 115200 8-N-1)→ 连接 →
|
||||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
@@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"area": "640x360",
|
||||||
|
"slots": [
|
||||||
|
{
|
||||||
|
"name": "西门子星",
|
||||||
|
"file": "bw_star.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "BW_ZONE",
|
||||||
|
"file": "bw_zoneplate.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "BW_TEST",
|
||||||
|
"file": "bw_testcard.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "自定义4",
|
||||||
|
"file": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "自定义5",
|
||||||
|
"file": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "自定义6",
|
||||||
|
"file": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "自定义7",
|
||||||
|
"file": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "自定义8",
|
||||||
|
"file": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "自定义9",
|
||||||
|
"file": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "自定义10",
|
||||||
|
"file": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"serial": {
|
||||||
|
"port": "COM15",
|
||||||
|
"baud": 115200,
|
||||||
|
"bytesize": 8,
|
||||||
|
"parity": "N",
|
||||||
|
"stopbits": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
@@ -33,8 +33,14 @@ MONO = ('Consolas', 12)
|
|||||||
BOLD = ('Microsoft YaHei UI', 13, 'bold')
|
BOLD = ('Microsoft YaHei UI', 13, 'bold')
|
||||||
TITLE_FONT = ('Microsoft YaHei UI', 18, 'bold')
|
TITLE_FONT = ('Microsoft YaHei UI', 18, 'bold')
|
||||||
|
|
||||||
|
# 电源自检状态位配色: 灰=未检测, 绿=正常回包, 红=错误/超时
|
||||||
|
CHIP_IDLE = ('gray78', 'gray34')
|
||||||
|
CHIP_IDLE_TEXT = ('#333333', '#E8E8E8')
|
||||||
|
CHIP_OK = '#2FA574'
|
||||||
|
CHIP_ERR = '#D9534F'
|
||||||
|
|
||||||
APP_NAME = 'DLPilot'
|
APP_NAME = 'DLPilot'
|
||||||
APP_VERSION = '0.3.0'
|
APP_VERSION = '0.3.4'
|
||||||
REPO_URL = 'https://gitea.hulk.wang/hulk/LT8619C_Debug_Tools'
|
REPO_URL = 'https://gitea.hulk.wang/hulk/LT8619C_Debug_Tools'
|
||||||
|
|
||||||
|
|
||||||
@@ -67,13 +73,14 @@ def run_gui(auto_close=0):
|
|||||||
class App(ctk.CTk):
|
class App(ctk.CTk):
|
||||||
def __init__(self, auto_close=0):
|
def __init__(self, auto_close=0):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.title('DLPilot — 3D 光固化光机调试台 (EDID · 测试图案 · RS485 光机控制)')
|
self.title(f'DLPilot v{APP_VERSION} — 3D 光固化光机调试台 '
|
||||||
|
f'(EDID · 测试图案 · RS485 光机控制)')
|
||||||
try: # 任务栏独立分组
|
try: # 任务栏独立分组
|
||||||
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID('hulk.DLPilot')
|
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID('hulk.DLPilot')
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
self.geometry('1440x920')
|
self.geometry('1440x1010') # 右列新增电源检查卡, 窗口加高
|
||||||
self.minsize(1180, 800)
|
self.minsize(1180, 860)
|
||||||
ic = get_icon_path()
|
ic = get_icon_path()
|
||||||
if ic:
|
if ic:
|
||||||
try:
|
try:
|
||||||
@@ -92,8 +99,12 @@ class App(ctk.CTk):
|
|||||||
self._dlpc_connected = False
|
self._dlpc_connected = False
|
||||||
self._poll_job = None
|
self._poll_job = None
|
||||||
self._tl_order = [] # 温度查询应答顺序: 'DMD'/'LAMP' 先到先得
|
self._tl_order = [] # 温度查询应答顺序: 'DMD'/'LAMP' 先到先得
|
||||||
|
self._pd_seq = [] # 电源自检待执行步骤: [(命令, kind), ...]
|
||||||
|
self._pd_timer = None # 自检单步超时定时器
|
||||||
self._build()
|
self._build()
|
||||||
self._load_displays()
|
self._load_displays()
|
||||||
|
# 主窗口按 ESC 也能关闭所有投屏(投屏窗口失焦时的兜底出口)
|
||||||
|
self.bind('<Escape>', lambda _e: patterns.close_all())
|
||||||
if dlpc_rs485.HAS_SERIAL:
|
if dlpc_rs485.HAS_SERIAL:
|
||||||
self._poll_dlpc()
|
self._poll_dlpc()
|
||||||
if auto_close > 0:
|
if auto_close > 0:
|
||||||
@@ -208,7 +219,8 @@ class App(ctk.CTk):
|
|||||||
self.edid_scroll.pack(fill='both', expand=True)
|
self.edid_scroll.pack(fill='both', expand=True)
|
||||||
|
|
||||||
# -- 测试图案 --
|
# -- 测试图案 --
|
||||||
card, c = self._card(col,'测试图案 — 黑底 1:1 居中, 按 ESC 退出')
|
card, c = self._card(col,'测试图案 — 黑底 1:1 居中, 投屏按 ESC 或"停止测试图像"退出',
|
||||||
|
button='停止测试图像', command=patterns.close_all)
|
||||||
card.grid(row=3, column=0, sticky='ew', pady=(10, 0))
|
card.grid(row=3, column=0, sticky='ew', pady=(10, 0))
|
||||||
row1 = ctk.CTkFrame(c, fg_color='transparent')
|
row1 = ctk.CTkFrame(c, fg_color='transparent')
|
||||||
row1.pack(fill='x')
|
row1.pack(fill='x')
|
||||||
@@ -315,6 +327,31 @@ class App(ctk.CTk):
|
|||||||
self._dlpc_log('帧格式: D5 01 LEN <命令> CRC / B5 TYPE LEN <payload> CRC, '
|
self._dlpc_log('帧格式: D5 01 LEN <命令> CRC / B5 TYPE LEN <payload> CRC, '
|
||||||
'累加和校验; 全部命令见 README"光机控制"')
|
'累加和校验; 全部命令见 README"光机控制"')
|
||||||
|
|
||||||
|
# -- 电源检查 --
|
||||||
|
card, c = self._card(col, '电源检查 — PD 自检 / 功率读数')
|
||||||
|
card.grid(row=2, column=0, sticky='ew', pady=(10, 0))
|
||||||
|
rowp1 = ctk.CTkFrame(c, fg_color='transparent')
|
||||||
|
rowp1.pack(fill='x')
|
||||||
|
ctk.CTkButton(rowp1, text='电源自检', width=90,
|
||||||
|
command=self._pd_selftest).pack(side='left')
|
||||||
|
ctk.CTkLabel(rowp1, text='协议:').pack(side='left', padx=(10, 4))
|
||||||
|
self.chip_pd = ctk.CTkLabel(rowp1, text='PD', width=60, height=26,
|
||||||
|
corner_radius=6, fg_color=CHIP_IDLE,
|
||||||
|
text_color=CHIP_IDLE_TEXT)
|
||||||
|
self.chip_pd.pack(side='left')
|
||||||
|
self.var_fpdo = tk.StringVar(value='FPDO: —')
|
||||||
|
ctk.CTkLabel(rowp1, textvariable=self.var_fpdo, anchor='w',
|
||||||
|
text_color='#3B8ED0').pack(side='left', padx=(12, 0))
|
||||||
|
rowp2 = ctk.CTkFrame(c, fg_color='transparent')
|
||||||
|
rowp2.pack(fill='x', pady=(6, 0))
|
||||||
|
ctk.CTkButton(rowp2, text='功率检测', width=90,
|
||||||
|
command=self._pwr_query).pack(side='left')
|
||||||
|
self.var_pwr = tk.StringVar(value='电压: — 电流: — 功率: —')
|
||||||
|
ctk.CTkLabel(rowp2, textvariable=self.var_pwr, height=28,
|
||||||
|
corner_radius=6, fg_color=('#F2F2F2', '#181818'),
|
||||||
|
anchor='w').pack(side='left', fill='x', expand=True,
|
||||||
|
padx=(8, 0))
|
||||||
|
|
||||||
# -- 光机命令 --
|
# -- 光机命令 --
|
||||||
# 标题行右侧: 电流实时读数 + 查电流按钮(okR..G..B.. 应答解析)
|
# 标题行右侧: 电流实时读数 + 查电流按钮(okR..G..B.. 应答解析)
|
||||||
cur_frame = ctk.CTkFrame(self, fg_color='transparent')
|
cur_frame = ctk.CTkFrame(self, fg_color='transparent')
|
||||||
@@ -325,7 +362,7 @@ class App(ctk.CTk):
|
|||||||
command=self._query_current).pack(side='left', padx=(6, 0))
|
command=self._query_current).pack(side='left', padx=(6, 0))
|
||||||
card, c = self._card(col,'光机命令 — 预设 / 自定义 / TEC',
|
card, c = self._card(col,'光机命令 — 预设 / 自定义 / TEC',
|
||||||
right_widget=cur_frame)
|
right_widget=cur_frame)
|
||||||
card.grid(row=2, column=0, sticky='ew', pady=(10, 0))
|
card.grid(row=3, column=0, sticky='ew', pady=(10, 0))
|
||||||
row1 = ctk.CTkFrame(c, fg_color='transparent')
|
row1 = ctk.CTkFrame(c, fg_color='transparent')
|
||||||
row1.pack(fill='x')
|
row1.pack(fill='x')
|
||||||
for name, cmd in (('开光机', 'M730S0'), ('关光机', 'M730S1'),
|
for name, cmd in (('开光机', 'M730S0'), ('关光机', 'M730S1'),
|
||||||
@@ -382,7 +419,7 @@ class App(ctk.CTk):
|
|||||||
|
|
||||||
# -- 快捷滑条 --
|
# -- 快捷滑条 --
|
||||||
card, c = self._card(col,'快捷滑条 — 光强 / 定时投光 / TEC 温度')
|
card, c = self._card(col,'快捷滑条 — 光强 / 定时投光 / TEC 温度')
|
||||||
card.grid(row=3, column=0, sticky='ew', pady=(10, 0))
|
card.grid(row=4, column=0, sticky='ew', pady=(10, 0))
|
||||||
rowa = ctk.CTkFrame(c, fg_color='transparent')
|
rowa = ctk.CTkFrame(c, fg_color='transparent')
|
||||||
rowa.pack(fill='x')
|
rowa.pack(fill='x')
|
||||||
ctk.CTkLabel(rowa, text='光强(54-800):').pack(side='left')
|
ctk.CTkLabel(rowa, text='光强(54-800):').pack(side='left')
|
||||||
@@ -729,6 +766,9 @@ class App(ctk.CTk):
|
|||||||
elif kind == 'current':
|
elif kind == 'current':
|
||||||
self.var_current.set(text)
|
self.var_current.set(text)
|
||||||
self._dlpc_log(text)
|
self._dlpc_log(text)
|
||||||
|
if (self._pd_seq and kind == 'event'
|
||||||
|
and text.startswith('← ')):
|
||||||
|
self._pd_on_reply(text) # 电源自检: 应答路由到状态机
|
||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
pass
|
pass
|
||||||
connected = self.dlpc.is_connected()
|
connected = self.dlpc.is_connected()
|
||||||
@@ -810,6 +850,91 @@ class App(ctk.CTk):
|
|||||||
if cmd:
|
if cmd:
|
||||||
self._dlpc_send(cmd)
|
self._dlpc_send(cmd)
|
||||||
|
|
||||||
|
# -- 电源检查: 自检序列 + 功率读数 --
|
||||||
|
|
||||||
|
def _pd_selftest(self):
|
||||||
|
"""电源自检: 按序自动执行 M301/M302(电压检测命令待固件定义后在序列追加),
|
||||||
|
每步应答刷新状态位: 绿=正常回包, 红=错误/超时, 灰=未检测"""
|
||||||
|
if not self.dlpc.is_connected():
|
||||||
|
self.lbl_dlpc_st.configure(text='未连接串口', text_color='#E07A3F')
|
||||||
|
return
|
||||||
|
if self._pd_seq:
|
||||||
|
return # 进行中, 忽略重复触发
|
||||||
|
self._pd_seq = [('M301', 'pd'), ('M302', 'fpdo')]
|
||||||
|
self._pd_chip_reset()
|
||||||
|
self._dlpc_log('电源自检: 开始')
|
||||||
|
self._pd_step_next()
|
||||||
|
|
||||||
|
def _pd_chip_reset(self):
|
||||||
|
self.chip_pd.configure(fg_color=CHIP_IDLE,
|
||||||
|
text_color=CHIP_IDLE_TEXT, text='PD')
|
||||||
|
self.var_fpdo.set('FPDO: —')
|
||||||
|
|
||||||
|
def _pd_step_next(self):
|
||||||
|
if not self._pd_seq:
|
||||||
|
self._dlpc_log('电源自检: 完成')
|
||||||
|
return
|
||||||
|
self.dlpc.send(self._pd_seq[0][0])
|
||||||
|
self._pd_timer = self.after(3000, lambda: self._pd_step_done(False, '超时'))
|
||||||
|
|
||||||
|
def _pd_on_reply(self, line):
|
||||||
|
self._pd_step_done(self._pd_reply_ok(line), line)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _pd_reply_ok(line):
|
||||||
|
"""应答行 -> 是否成功帧(TYPE=0xF0): 成功行正文是 payload 原文(如 'PD'/'okTL:246',
|
||||||
|
不必有 ok 前缀), 失败行正文是 TYPE 译码词或带 err:, 据此区分"""
|
||||||
|
body = line[2:].split(' [')[0].strip()
|
||||||
|
if 'err:' in body:
|
||||||
|
return False
|
||||||
|
return not any(n in body for n in dlpc_rs485.TYPE_NAMES.values()
|
||||||
|
if n != '成功') # '成功' 不会出现在日志正文, 仅防 payload 撞词
|
||||||
|
|
||||||
|
def _pd_step_done(self, ok, line=''):
|
||||||
|
if not self._pd_seq:
|
||||||
|
return
|
||||||
|
if self._pd_timer:
|
||||||
|
self.after_cancel(self._pd_timer)
|
||||||
|
self._pd_timer = None
|
||||||
|
_cmd, kind = self._pd_seq.pop(0)
|
||||||
|
payload = ''
|
||||||
|
if ok:
|
||||||
|
body = line[2:].split(' [')[0].strip() # 去 '← ' 与尾部 hex
|
||||||
|
payload = '' if body.lower() == 'ok' else \
|
||||||
|
(body[2:].strip() if body[:2].lower() == 'ok' else body)
|
||||||
|
if kind == 'pd':
|
||||||
|
self.chip_pd.configure(fg_color=CHIP_OK if ok else CHIP_ERR,
|
||||||
|
text_color='#FFFFFF',
|
||||||
|
text=payload if ok and payload else 'PD')
|
||||||
|
elif kind == 'fpdo':
|
||||||
|
mv = re.search(r'(\d+(?:\.\d+)?)\s*V', payload, re.I)
|
||||||
|
ma = re.search(r'(\d+(?:\.\d+)?)\s*A', payload, re.I)
|
||||||
|
if not ok:
|
||||||
|
self.var_fpdo.set('FPDO: 应答错误')
|
||||||
|
elif mv and ma: # 电压 + 电源宣称最大电流 -> FPDO 功率
|
||||||
|
v, a = float(mv.group(1)), float(ma.group(1))
|
||||||
|
self.var_fpdo.set(f'FPDO: {v:g}V / {a:g}A ({v * a:.0f}W)')
|
||||||
|
elif payload:
|
||||||
|
self.var_fpdo.set(f'FPDO: {payload}')
|
||||||
|
if ok:
|
||||||
|
self._pd_step_next()
|
||||||
|
else: # 出错即中止, 后续状态位保持未检测灰
|
||||||
|
self._pd_seq.clear()
|
||||||
|
why = '超时无应答' if not line.startswith('← ') else '应答错误'
|
||||||
|
self._dlpc_log(f'电源自检: {why}, 序列中止')
|
||||||
|
|
||||||
|
def _pwr_query(self):
|
||||||
|
"""功率检测: 命令待固件实现, 先占位(定义后在此发送并接 _pwr_update)"""
|
||||||
|
if not self.dlpc.is_connected():
|
||||||
|
self.lbl_dlpc_st.configure(text='未连接串口', text_color='#E07A3F')
|
||||||
|
return
|
||||||
|
self._dlpc_log('功率检测: 命令待固件实现')
|
||||||
|
|
||||||
|
def _pwr_update(self, volts, amps):
|
||||||
|
"""功率读数框更新入口: 电压/电流到手后换算功率并刷新"""
|
||||||
|
self.var_pwr.set(f'电压: {volts:.1f} V 电流: {amps:.2f} A '
|
||||||
|
f'功率: {volts * amps:.1f} W')
|
||||||
|
|
||||||
def _light_entry_apply(self, _evt=None):
|
def _light_entry_apply(self, _evt=None):
|
||||||
"""滑条数值输入框回车: 校验并限幅 54-800, 同步回滑条"""
|
"""滑条数值输入框回车: 校验并限幅 54-800, 同步回滑条"""
|
||||||
try:
|
try:
|
||||||
@@ -875,9 +1000,11 @@ class App(ctk.CTk):
|
|||||||
self._dlpc_send(f'M8S{v}')
|
self._dlpc_send(f'M8S{v}')
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
try: # 取消待触发的轮询回调, 避免销毁后 Tcl 报错
|
try: # 取消待触发的轮询/自检超时回调, 避免销毁后 Tcl 报错
|
||||||
if self._poll_job:
|
if self._poll_job:
|
||||||
self.after_cancel(self._poll_job)
|
self.after_cancel(self._poll_job)
|
||||||
|
if self._pd_timer:
|
||||||
|
self.after_cancel(self._pd_timer)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
try: # 两种退出路径(关窗/--seconds 自动关)都收掉串口线程
|
try: # 两种退出路径(关窗/--seconds 自动关)都收掉串口线程
|
||||||
@@ -7,7 +7,9 @@ DLPC3421 光机 RS485 控制链路(板上 GD32E230 作 RS485→I2C 网关)
|
|||||||
响应语义/错误码/就绪门禁与实测帧示例):
|
响应语义/错误码/就绪门禁与实测帧示例):
|
||||||
物理层 RS485 半双工 115200 8N1(PC 经 USB-RS485 转换器接板, DE 由 MCU 硬件换向)
|
物理层 RS485 半双工 115200 8N1(PC 经 USB-RS485 转换器接板, DE 由 MCU 硬件换向)
|
||||||
命令帧 D5 01 LEN <ASCII命令> CRC 01=板类型, LEN=命令字节数
|
命令帧 D5 01 LEN <ASCII命令> CRC 01=板类型, LEN=命令字节数
|
||||||
响应帧 B5 TYPE LEN <payload> CRC payload 为 ASCII(ok / err:OL / okTL:246 ...)
|
响应帧 B5 TYPE LEN <payload> CRC payload 为 ASCII(ok / err:OL / okTL:246 ...),
|
||||||
|
例外: M303/M304 载荷为 2 字节大端二进制
|
||||||
|
(SQ52205 电源实测, 见 POWER_COMMANDS)
|
||||||
CRC 帧内第 2 字节(板类型)起累加到最后一个 payload 字节, 取低 8 位
|
CRC 帧内第 2 字节(板类型)起累加到最后一个 payload 字节, 取低 8 位
|
||||||
帧长 最小 6 字节, 最大 32 字节
|
帧长 最小 6 字节, 最大 32 字节
|
||||||
就绪门禁: DLPC3421 启动完成前 M730/M731/M732 被拒(回 0xFF), 属预期。
|
就绪门禁: DLPC3421 启动完成前 M730/M731/M732 被拒(回 0xFF), 属预期。
|
||||||
@@ -81,6 +83,42 @@ PRESETS = (
|
|||||||
Frame = collections.namedtuple('Frame', 'type_code payload raw')
|
Frame = collections.namedtuple('Frame', 'type_code payload raw')
|
||||||
|
|
||||||
|
|
||||||
|
# --- M303/M304(SQ52205 电源实测值查询): 成功载荷为 2 字节原始二进制(非 ASCII) ---
|
||||||
|
# M303 母线电压: u16 大端, 单位 mV; 12V 轨正常窗口 11400~12600(标称 ±5%)
|
||||||
|
# M304 负载电流: s16 大端补码, 单位 mA; 正=正向, 负=反向(固件原样上总线,
|
||||||
|
# 上位机必须按有符号解析)。例: 载荷 FF 06 = -250 mA
|
||||||
|
# 错误时 TYPE=0xFF, 载荷为错误信息字节串(走通用译码路径)
|
||||||
|
POWER_COMMANDS = ('M303', 'M304')
|
||||||
|
|
||||||
|
|
||||||
|
def payload_bytes(fr):
|
||||||
|
"""响应帧的原始载荷字节(Frame.payload 是 ASCII 解码视图, 二进制载荷请用本函数)"""
|
||||||
|
return fr.raw[3:-1]
|
||||||
|
|
||||||
|
|
||||||
|
def payload_u16_be(raw):
|
||||||
|
return (raw[0] << 8) | raw[1]
|
||||||
|
|
||||||
|
|
||||||
|
def payload_s16_be(raw):
|
||||||
|
v = payload_u16_be(raw)
|
||||||
|
return v - 0x10000 if v & 0x8000 else v
|
||||||
|
|
||||||
|
|
||||||
|
def format_power(cmd, fr):
|
||||||
|
"""M303/M304 成功应答 -> 人读文本; 非 POWER 命令/失败/载荷异常返回 None"""
|
||||||
|
if cmd not in POWER_COMMANDS:
|
||||||
|
return None
|
||||||
|
raw = payload_bytes(fr)
|
||||||
|
if fr.type_code != 0xF0 or len(raw) != 2:
|
||||||
|
return None
|
||||||
|
if cmd == 'M303':
|
||||||
|
mv = payload_u16_be(raw)
|
||||||
|
return f'{mv} mV ({mv / 1000:.2f} V)'
|
||||||
|
ma = payload_s16_be(raw)
|
||||||
|
return f'{ma:+d} mA'
|
||||||
|
|
||||||
|
|
||||||
def sum_crc(data):
|
def sum_crc(data):
|
||||||
"""帧内第 2 字节(板类型)起累加到末 payload 字节, 取低 8 位(不含包头与 CRC)"""
|
"""帧内第 2 字节(板类型)起累加到末 payload 字节, 取低 8 位(不含包头与 CRC)"""
|
||||||
return sum(data) & 0xFF
|
return sum(data) & 0xFF
|
||||||
@@ -279,7 +317,12 @@ class DLPC485:
|
|||||||
self.on_event(f'← {describe(fr)} '
|
self.on_event(f'← {describe(fr)} '
|
||||||
f'[{fr.raw.hex(" ").upper()}]')
|
f'[{fr.raw.hex(" ").upper()}]')
|
||||||
except OSError:
|
except OSError:
|
||||||
|
try:
|
||||||
|
self.ser.close()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
self.ser = None
|
self.ser = None
|
||||||
|
self._open_key = None # 必须同步清除, 否则同参数重连被当作已打开而跳过
|
||||||
with self._lock:
|
with self._lock:
|
||||||
self._target = None
|
self._target = None
|
||||||
self.on_status('串口丢失(设备拔出?), 请重新连接')
|
self.on_status('串口丢失(设备拔出?), 请重新连接')
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
================================================================
|
================================================================
|
||||||
配合 demo 板当前 EDID 首选时序 800x600@60, 全屏纯色输出。
|
配合 demo 板当前 EDID 首选时序 800x600@60, 全屏纯色输出。
|
||||||
用法: python gen_solid_colors.py → 输出到 ../assets/solid_*.png
|
用法: python gen_solid_colors.py → 输出到 ../assets/solid_*.png
|
||||||
在 HDMI-Tool 中通过自定义栏位(⚙ 换图)加载, 发布包随附。
|
在 DLPilot 中通过自定义栏位(⚙ 换图)加载, 发布包随附。
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.9 KiB |
@@ -9,6 +9,19 @@
|
|||||||
|
|
||||||
from config import DEFAULT_AREA, HAS_PIL, Image, ImageTk, PAT_W, PAT_H
|
from config import DEFAULT_AREA, HAS_PIL, Image, ImageTk, PAT_W, PAT_H
|
||||||
|
|
||||||
|
# 当前打开的投屏窗口集合: 支持"新图案替换旧图案"与 close_all() 一键恢复桌面
|
||||||
|
_OPEN = set()
|
||||||
|
|
||||||
|
|
||||||
|
def close_all():
|
||||||
|
"""关闭所有打开的投屏窗口, 恢复桌面"""
|
||||||
|
for top in list(_OPEN):
|
||||||
|
try:
|
||||||
|
top.destroy()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
_OPEN.clear()
|
||||||
|
|
||||||
|
|
||||||
PATTERN_NAMES = {'Red': '纯红', 'Green': '纯绿', 'Blue': '纯蓝',
|
PATTERN_NAMES = {'Red': '纯红', 'Green': '纯绿', 'Blue': '纯蓝',
|
||||||
'Checker': '黑白棋盘格', 'Grid': '网格线'}
|
'Checker': '黑白棋盘格', 'Grid': '网格线'}
|
||||||
@@ -43,8 +56,9 @@ def _area_box(spec, w, h):
|
|||||||
def _open_fullscreen(parent, rect, auto_close=0):
|
def _open_fullscreen(parent, rect, auto_close=0):
|
||||||
"""创建覆盖 rect(x,y,w,h) 的无边框全屏黑底窗口, 返回 (top, cv)
|
"""创建覆盖 rect(x,y,w,h) 的无边框全屏黑底窗口, 返回 (top, cv)
|
||||||
|
|
||||||
只支持 ESC 退出: overrideredirect 窗口必须 focus_force 强取键盘焦点,
|
ESC 退出(需窗口持有键盘焦点); overrideredirect 窗口必须 focus_force
|
||||||
否则收不到按键(Windows 上该组合有效)。
|
强取键盘焦点, 否则收不到按键(Windows 上该组合有效)。
|
||||||
|
窗口登记进 _OPEN: 打开新投屏前会关旧的(替换语义), close_all() 一键全关。
|
||||||
"""
|
"""
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
rx, ry, rw, rh = rect
|
rx, ry, rw, rh = rect
|
||||||
@@ -58,9 +72,16 @@ def _open_fullscreen(parent, rect, auto_close=0):
|
|||||||
cv.pack(fill='both', expand=True)
|
cv.pack(fill='both', expand=True)
|
||||||
|
|
||||||
def close(_evt=None):
|
def close(_evt=None):
|
||||||
|
_OPEN.discard(top)
|
||||||
top.destroy()
|
top.destroy()
|
||||||
|
|
||||||
|
def _on_destroy(e):
|
||||||
|
if e.widget is top: # 子控件销毁也冒泡到此, 只认窗口本身
|
||||||
|
_OPEN.discard(top)
|
||||||
|
|
||||||
top.bind('<Escape>', close)
|
top.bind('<Escape>', close)
|
||||||
|
top.bind('<Destroy>', _on_destroy)
|
||||||
|
_OPEN.add(top)
|
||||||
if auto_close > 0:
|
if auto_close > 0:
|
||||||
top.after(auto_close * 1000, close)
|
top.after(auto_close * 1000, close)
|
||||||
top.focus_force()
|
top.focus_force()
|
||||||
@@ -68,7 +89,9 @@ def _open_fullscreen(parent, rect, auto_close=0):
|
|||||||
|
|
||||||
|
|
||||||
def show_pattern(parent, rect, kind, auto_close=0, area=DEFAULT_AREA):
|
def show_pattern(parent, rect, kind, auto_close=0, area=DEFAULT_AREA):
|
||||||
"""在 rect 指定的屏幕上全屏出居中测试卡(无任何 OSD 修饰), 区域由 area 指定"""
|
"""在 rect 指定的屏幕上全屏出居中测试卡(无任何 OSD 修饰), 区域由 area 指定。
|
||||||
|
打开前先关闭已有投屏窗口(替换语义, 不会多层叠罗汉)。"""
|
||||||
|
close_all()
|
||||||
top, cv = _open_fullscreen(parent, rect, auto_close)
|
top, cv = _open_fullscreen(parent, rect, auto_close)
|
||||||
|
|
||||||
def draw(_evt=None):
|
def draw(_evt=None):
|
||||||
@@ -107,7 +130,9 @@ def show_pattern(parent, rect, kind, auto_close=0, area=DEFAULT_AREA):
|
|||||||
def show_pattern_image(parent, rect, path, auto_close=0, area=DEFAULT_AREA):
|
def show_pattern_image(parent, rect, path, auto_close=0, area=DEFAULT_AREA):
|
||||||
"""全屏黑底, 图片 1:1 居中于 area 指定的测试卡区域:
|
"""全屏黑底, 图片 1:1 居中于 area 指定的测试卡区域:
|
||||||
小于区域 -> 真实像素居中, 四周黑边;
|
小于区域 -> 真实像素居中, 四周黑边;
|
||||||
大于区域 -> 等效从中心截取(区域外用黑矩形遮挡)"""
|
大于区域 -> 等效从中心截取(区域外用黑矩形遮挡)。
|
||||||
|
打开前先关闭已有投屏窗口(替换语义)。"""
|
||||||
|
close_all()
|
||||||
top, cv = _open_fullscreen(parent, rect, auto_close)
|
top, cv = _open_fullscreen(parent, rect, auto_close)
|
||||||
|
|
||||||
def draw(_evt=None):
|
def draw(_evt=None):
|
||||||
@@ -23,6 +23,7 @@ import re
|
|||||||
import ssl
|
import ssl
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
import urllib.error
|
import urllib.error
|
||||||
import urllib.request
|
import urllib.request
|
||||||
import uuid
|
import uuid
|
||||||
@@ -59,15 +60,22 @@ class Api:
|
|||||||
self.headers = {'Authorization': f'token {token}'}
|
self.headers = {'Authorization': f'token {token}'}
|
||||||
self.ctx = ssl._create_unverified_context() if insecure else None
|
self.ctx = ssl._create_unverified_context() if insecure else None
|
||||||
|
|
||||||
def request(self, method, path, data=None, headers=None):
|
def request(self, method, path, data=None, headers=None, retries=4):
|
||||||
req = urllib.request.Request(self.api + path, data=data, method=method,
|
"""发请求; 实例 TLS 间歇性抽风(SSL UNEXPECTED_EOF), 连接级错误自动重试"""
|
||||||
headers={**self.headers, **(headers or {})})
|
last = None
|
||||||
try:
|
for attempt in range(retries):
|
||||||
with urllib.request.urlopen(req, context=self.ctx) as resp:
|
req = urllib.request.Request(self.api + path, data=data, method=method,
|
||||||
body = resp.read()
|
headers={**self.headers, **(headers or {})})
|
||||||
return resp.status, json.loads(body) if body else None
|
try:
|
||||||
except urllib.error.HTTPError as e:
|
with urllib.request.urlopen(req, context=self.ctx) as resp:
|
||||||
return e.code, json.loads(e.read() or b'{}')
|
body = resp.read()
|
||||||
|
return resp.status, json.loads(body) if body else None
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
return e.code, json.loads(e.read() or b'{}')
|
||||||
|
except (urllib.error.URLError, ssl.SSLError, OSError) as e:
|
||||||
|
last = e
|
||||||
|
time.sleep(1.0 + attempt)
|
||||||
|
raise RuntimeError(f'Gitea 请求连续 {retries} 次失败: {last}')
|
||||||
|
|
||||||
def get_json(self, path):
|
def get_json(self, path):
|
||||||
status, data = self.request('GET', path)
|
status, data = self.request('GET', path)
|
||||||
@@ -73,5 +73,19 @@ for _name, cmd, _note in d.PRESETS:
|
|||||||
d.build_frame(cmd)
|
d.build_frame(cmd)
|
||||||
print(f'预设 {len(d.PRESETS)} 条全部可组帧: PASS')
|
print(f'预设 {len(d.PRESETS)} 条全部可组帧: PASS')
|
||||||
|
|
||||||
|
# 8) M303/M304(SQ52205 电源实测)回归向量: 上游真机抓取帧
|
||||||
|
check('build_frame(M303)', d.build_frame('M303').hex(' ').upper(),
|
||||||
|
'D5 01 04 4D 33 30 33 E8')
|
||||||
|
check('build_frame(M304)', d.build_frame('M304').hex(' ').upper(),
|
||||||
|
'D5 01 04 4D 33 30 34 E9')
|
||||||
|
frames = d.FrameParser().feed(bytes.fromhex('B5 F0 02 2E F4 14'))
|
||||||
|
check('M303 应答帧', len(frames), 1)
|
||||||
|
check('M303 电压(0x2EF4=12020mV)', d.format_power('M303', frames[0]),
|
||||||
|
'12020 mV (12.02 V)')
|
||||||
|
frames = d.FrameParser().feed(bytes.fromhex('B5 F0 02 00 34 26'))
|
||||||
|
check('M304 应答帧', len(frames), 1)
|
||||||
|
check('M304 电流(0x0034=+52mA)', d.format_power('M304', frames[0]), '+52 mA')
|
||||||
|
check('M304 负值(FF06=-250mA 补码)', d.payload_s16_be(bytes.fromhex('FF 06')), -250)
|
||||||
|
|
||||||
print('RESULT:', 'FAIL:' + ','.join(fails) if fails else 'ALL PASS')
|
print('RESULT:', 'FAIL:' + ','.join(fails) if fails else 'ALL PASS')
|
||||||
sys.exit(1 if fails else 0)
|
sys.exit(1 if fails else 0)
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"area": "640x360",
|
|
||||||
"slots": [
|
|
||||||
{
|
|
||||||
"name": "西门子星",
|
|
||||||
"file": "bw_star.png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "BW_ZONE",
|
|
||||||
"file": "bw_zoneplate.png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "BW_TEST",
|
|
||||||
"file": "bw_testcard.png"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -12,7 +12,7 @@ PORT = sys.argv[1] if len(sys.argv) > 1 else 'COM9'
|
|||||||
FULL = len(sys.argv) > 2 and sys.argv[2].lower() == 'full'
|
FULL = len(sys.argv) > 2 and sys.argv[2].lower() == 'full'
|
||||||
|
|
||||||
BANK, REG = '60', '6E'
|
BANK, REG = '60', '6E'
|
||||||
STEPS = [ # (写值, 含义, 写入后 HDMI-Tool 应投的图, LA 预期变化 vs 基线)
|
STEPS = [ # (写值, 含义, 写入后 DLPilot 应投的图, LA 预期变化 vs 基线)
|
||||||
('00', '关闭交换(基准)', 'solid_0000AA / solid_000055',
|
('00', '关闭交换(基准)', 'solid_0000AA / solid_000055',
|
||||||
'D0:AA=13%/55=84%, D1:AA=72%/55=0.9% (基线)'),
|
'D0:AA=13%/55=84%, D1:AA=72%/55=0.9% (基线)'),
|
||||||
('80', 'B通道镜像', 'solid_0000AA',
|
('80', 'B通道镜像', 'solid_0000AA',
|
||||||
|
|||||||