diff --git a/.gitignore b/.gitignore index 7bf3aac..5392d48 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ dist/ # 发布 zip: 可由 src/package_release.py 重新生成, 只上传 Gitea Release HDMI-Tool/release/*.zip +DLPilot/release/*.zip # ZCode 客户端本地会话数据(计划留档等), 非项目配置 .zcode/ diff --git a/HDMI-Tool/AGENTS.md b/HDMI-Tool/AGENTS.md index a0f535f..447a7f6 100644 --- a/HDMI-Tool/AGENTS.md +++ b/HDMI-Tool/AGENTS.md @@ -1,4 +1,4 @@ -# AGENTS.md — HDMI-Tool 工程档案(供 AI/Agent 使用) +# AGENTS.md — DLPilot 工程档案(供 AI/Agent 使用) > **本文档面向 AI/Agent**,是人类文档 [README.md](README.md) 的姊妹篇,两者不重叠: > README 回答"这是什么、怎么用";本文回答"代码怎么组织、怎么构建发布、改动时哪些约束不能破坏"。 @@ -9,17 +9,17 @@ 仓库 `LT8619C_Debug_Tools` 是 LT8619C(HDMI→RGB888)→ DLPC3421 投影转接板的**调试上位机工具集**, 上游主仓库(固件)为 `hulk/LT8619C_DLPC3421_HDMI`(同 Gitea 实例 `gitea.hulk.wang`), 本仓库本机路径 `E:\Hulk-Coding\LT8619C_DLPC3421_HDMI`。 -HDMI-Tool 工作在两端:HDMI **源端**(PC 显卡侧,EDID/分辨率/图案)与**光机控制端** +DLPilot 工作在两端:HDMI **源端**(PC 显卡侧,EDID/分辨率/图案)与**光机控制端** (RS485 → 板载 GD32E230 网关 → DLPC3421)。寄存器语义判读基线(0x606E 位交换 / 0x606D 整组顺序)与光机协议规程都在上游仓库 `doc/architecture/` 与 `protocols.md`,不在本仓库。 ## 2. 目录契约(重要) ``` -HDMI-Tool/ +DLPilot/ ├── src/ 源代码区 —— 只有这里可以手改(logos/ 改图标源后重跑 make_ico.py) ├── assets/ 生成资产区 —— gen_*.py 的产物(PNG 图案),可随时再生成,改动需提交 -├── release/ 产物区 —— 机器生成,禁止手改:HDMI-Tool.exe、pattern_slots.json、 +├── release/ 产物区 —— 机器生成,禁止手改:DLPilot.exe、pattern_slots.json、 │ bw/solid 图案(package_release.py 从 assets/ 平铺复制来,均入库)、 │ *.zip(gitignore,只上传 Release)。release/ 本身=完整可直接运行的 │ 发布文件夹(exe+附属平铺),内容与 zip 一致 @@ -42,8 +42,8 @@ HDMI-Tool/ | `src/config.py` | 运行目录定位(BASE_DIR)与 pattern_slots.json 读写(slots/area/serial 三键) | | `src/dlpc_rs485.py` | 光机 RS485 协议模块: 帧构造/增量解析/译码表/预设命令/串口线程(DLPC485) | | `src/selftest_rs485.py` | 光机协议自检(对照上游实测帧向量, 无硬件回归, 改协议代码后必跑) | -| `src/build_exe.py` | PyInstaller 打包 → `release/HDMI-Tool.exe`(onefile/noconsole, 内嵌图标+pyserial+customtkinter) | -| `src/package_release.py` | 复制图案到 release/(平铺) → `release/HDMI-Tool-v-win64.zip`(校验栏位引用完整性; release/ 与 zip 内容一致) | +| `src/build_exe.py` | PyInstaller 打包 → `release/DLPilot.exe`(onefile/noconsole, 内嵌图标+pyserial+customtkinter) | +| `src/package_release.py` | 复制图案到 release/(平铺) → `release/DLPilot-v-win64.zip`(校验栏位引用完整性; release/ 与 zip 内容一致) | | `src/publish_gitea.py` | 建/复用 Gitea Release 并上传 zip(tag 默认取 zip 文件名) | | `src/hdmi_source.ps1/.bat` | 独立 PowerShell 命令行工具(自包含,与 GUI 无代码共享) | | `src/gen_bw_patterns.py` | 生成 `assets/bw_*.png` ×5(640x360 黑白,需 Pillow) | @@ -87,7 +87,7 @@ HDMI-Tool/ 纯数组(无 area)与无 serial 键两种历史格式,save 永远写全三键。`serial` 子键为 `{port, baud, bytesize(8/7/6/5), parity(N/E/O), stopbits(1/2)}`,旧配置缺子键按 默认 8-N-1 补齐。 -12. **GUI = app_gui.py 双栏仪表盘**(规格:`HDMI-Tool/UI参考布局.svg`):左列 HDMI 源端 +12. **GUI = app_gui.py 双栏仪表盘**(规格:`DLPilot/UI参考布局.svg`):左列 HDMI 源端 五卡(显示器/模式/EDID 信息/测试图案/hex),右列光机四卡(串口/数据/命令/滑条), 顶栏 Dark/Light/System 切换(ttk.Treeview 颜色随动)。打包必须 `--collect-all customtkinter`(build_exe.py 已内置,勿删)——CTk 主题/字体数据缺失会让 exe 启动即崩。 @@ -111,14 +111,14 @@ HDMI-Tool/ ```powershell python gen_bw_patterns.py ; python gen_solid_colors.py # 仅当改了图案生成逻辑 -python build_exe.py # → ../release/HDMI-Tool.exe(缺 PyInstaller 会自动 pip install) -python build_exe.py --debug # 附加带控制台的 HDMI-Tool-console.exe(调试 --dump 用) -python package_release.py <版本> # → ../release/HDMI-Tool-v<版本>-win64.zip -python publish_gitea.py HDMI-Tool-v<版本>-win64.zip --replace --insecure # 上传(需 GITEA_TOKEN) +python build_exe.py # → ../release/DLPilot.exe(缺 PyInstaller 会自动 pip install) +python build_exe.py --debug # 附加带控制台的 DLPilot-console.exe(调试 --dump 用) +python package_release.py <版本> # → ../release/DLPilot-v<版本>-win64.zip +python publish_gitea.py DLPilot-v<版本>-win64.zip --replace --insecure # 上传(需 GITEA_TOKEN) ``` 发布约定: -- tag/release 命名 `HDMI-Tool-vX.Y.Z`,zip 命名 `HDMI-Tool-vX.Y.Z-win64.zip`(publish_gitea.py +- tag/release 命名 `DLPilot-vX.Y.Z`,zip 命名 `DLPilot-vX.Y.Z-win64.zip`(publish_gitea.py 依赖此命名从文件名推 tag); - **exe、pattern_slots.json 与 release/ 下平铺的图案 png 改动跟随源码/资产生成提交入库; zip 永不入库**(.gitignore 已挡); @@ -151,5 +151,5 @@ python publish_gitea.py HDMI-Tool-v<版本>-win64.zip --replace --insecure # 4. `python hdmi_gui.py --test-pattern Checker --area 800x600 --seconds 3` —— 投图链路; 5. `python hdmi_gui.py --dump` —— EDID 解算不抛异常; 6. `python hdmi_gui.py --dlpc-cmd M999`(不带 --port)—— 应明确报错而非崩溃(无硬件时的优雅降级); -7. `python build_exe.py` → 双击 release/HDMI-Tool.exe 确认图标/双栏布局/投图/光机区渲染; +7. `python build_exe.py` → 双击 release/DLPilot.exe 确认图标/双栏布局/投图/光机区渲染; 8. `python package_release.py <版本>` —— 不报"引用图片缺失"即栏位完整性 OK。 diff --git a/HDMI-Tool/README.md b/HDMI-Tool/README.md index 4eced41..3afd3b1 100644 --- a/HDMI-Tool/README.md +++ b/HDMI-Tool/README.md @@ -1,11 +1,11 @@ -# HDMI-Tool — HDMI 源端调试 + 光机控制工具 +# DLPilot — HDMI 源端调试 + 光机控制工具 > LT8619C(HDMI→RGB888)→ DLPC3421 投影转接板调试配套的 PC 端工具: > HDMI **源端**(EDID 查看、分辨率切换、纯色/测试图案投屏)+ **光机控制** > (RS485 直连板上 GD32 网关,开关光机/设光强/查温度电流)。 > > - **只想用工具**:到 [Gitea Releases](https://gitea.hulk.wang/hulk/LT8619C_Debug_Tools/releases) -> 下载 `HDMI-Tool-vX.Y.Z-win64.zip`,解压双击 `HDMI-Tool.exe` 即可(Windows 10/11 x64,免安装、无需 Python)。 +> 下载 `DLPilot-vX.Y.Z-win64.zip`,解压双击 `DLPilot.exe` 即可(Windows 10/11 x64,免安装、无需 Python)。 > - **要改代码/重新打包**:见 §8、§9。 > > 更新:2026-09-11 @@ -29,15 +29,15 @@ ## 2. 下载与安装 1. 打开 [Releases 页面](https://gitea.hulk.wang/hulk/LT8619C_Debug_Tools/releases),取最新的 - `HDMI-Tool-vX.Y.Z-win64.zip`; + `DLPilot-vX.Y.Z-win64.zip`; 2. 解压到**任意可写目录**(自定义图片与栏位配置会写到 exe 旁边); -3. 双击 `HDMI-Tool.exe`。首次启动比脚本慢一两秒(onefile 解压),属正常现象。 +3. 双击 `DLPilot.exe`。首次启动比脚本慢一两秒(onefile 解压),属正常现象。 包内包含: ``` -HDMI-Tool/ -├── HDMI-Tool.exe 主程序(单文件自包含, 光机控制的 pyserial 已内置) +DLPilot/ +├── DLPilot.exe 主程序(单文件自包含, 光机控制的 pyserial 已内置) ├── pattern_slots.json 预置自定义栏位 + 串口记忆 ├── bw_*.png ×5 640x360 黑白测试图 ├── solid_*.png ×10 800x600 纯色测试图 @@ -72,7 +72,7 @@ HDMI-Tool/ ## 4. 典型测试场景 ``` -1. HDMI 接转接板 → 启动 HDMI-Tool → 刷新 → 选中板卡显示器 +1. HDMI 接转接板 → 启动 DLPilot → 刷新 → 选中板卡显示器 2. 板卡 shadow EDID 首选 640x360@60 → 测试卡区域选 640x360(与光机面板原生 1:1) 3. "光机控制"连接串口 → M999 查版本确认链路通 → M730S0 开光机 4. 点 R/G/B 行纯色按钮投图 → 目视/逻辑分析仪核对 RGB888 输出 @@ -180,7 +180,7 @@ python la_wave_analyzer3.py # 3 通道(RGB 三组同拍, ch8/ ## 8. 目录结构与从源码运行 ``` -HDMI-Tool/ +DLPilot/ ├── src/ # 源代码(人工维护区) │ ├── hdmi_gui.py # 入口与命令行模式(argparse 分发) │ ├── app_gui.py # CustomTkinter 主界面(双栏仪表盘) @@ -202,7 +202,7 @@ HDMI-Tool/ │ ├── bw_*.png ×5 # 640x360 黑白系列 │ └── solid_*.png ×10 # 800x600 纯色系列 ├── release/ # 构建与发布产物(机器生成区, 不手改) -│ ├── HDMI-Tool.exe # 打包单文件版(改动跟随源码提交入库) +│ ├── DLPilot.exe # 打包单文件版(改动跟随源码提交入库) │ ├── pattern_slots.json # exe 运行配置(栏位预置 + 串口记忆) │ ├── *.png / README.md # 附属文件平铺副本(由 package_release.py 从 assets/ 同步) │ └── *.zip # 发布包(不入库, 上传 Gitea Release) @@ -220,11 +220,11 @@ GUI 需 customtkinter(`py -m pip install customtkinter`);光机控制需 p ```powershell cd src python selftest_rs485.py # 光机协议回归(改 dlpc_rs485.py 后必跑) -python build_exe.py # 打包 → ../release/HDMI-Tool.exe(自动装 PyInstaller; +python build_exe.py # 打包 → ../release/DLPilot.exe(自动装 PyInstaller; # 内置 pyserial/customtkinter, CTk 主题数据自动收集) python build_exe.py --debug # 额外出一个带控制台的调试变体(--dump 可见输出) -python package_release.py 0.2.0 # 组装 release/HDMI-Tool-v0.2.0-win64.zip -python publish_gitea.py HDMI-Tool-v0.2.0-win64.zip --insecure # 上传 Gitea Release(需 GITEA_TOKEN) +python package_release.py 0.2.0 # 组装 release/DLPilot-v0.2.0-win64.zip +python publish_gitea.py DLPilot-v0.2.0-win64.zip --insecure # 上传 Gitea Release(需 GITEA_TOKEN) ``` ## 10. 注意事项 / FAQ @@ -235,6 +235,6 @@ python publish_gitea.py HDMI-Tool-v0.2.0-win64.zip --insecure # 上传 Gitea R - **exe 放只读目录会怎样**:自定义图片与 `pattern_slots.json` 写在 exe 旁边,只读目录会导致配置存不下; - **重新打包后图标没变**:Windows 图标缓存,`ie4uinit -show` 或改个名即可; - **多屏序号**:切分辨率前先确认显示器序号(GUI 下拉框与 `hdmi_source.bat -List` 输出一致); -- **残留进程**:修改源码重新打包前先结束残留的 HDMI-Tool 进程(`build_exe.py` 会自动 taskkill); +- **残留进程**:修改源码重新打包前先结束残留的 DLPilot 进程(`build_exe.py` 会自动 taskkill); - **改 logo**:改 `src/logos/logo_ph_orange.svg` → `python src/logos/make_ico.py` → 重新打包; - **配置互不影响**:exe 与源码脚本各自按所在目录保存 `pattern_slots.json`,两份安装互不干扰。 diff --git a/HDMI-Tool/release/HDMI-Tool.exe b/HDMI-Tool/release/DLPilot.exe similarity index 97% rename from HDMI-Tool/release/HDMI-Tool.exe rename to HDMI-Tool/release/DLPilot.exe index 51cc213..7e94f56 100644 Binary files a/HDMI-Tool/release/HDMI-Tool.exe and b/HDMI-Tool/release/DLPilot.exe differ diff --git a/HDMI-Tool/release/README.md b/HDMI-Tool/release/README.md index 4eced41..3afd3b1 100644 --- a/HDMI-Tool/release/README.md +++ b/HDMI-Tool/release/README.md @@ -1,11 +1,11 @@ -# HDMI-Tool — HDMI 源端调试 + 光机控制工具 +# DLPilot — HDMI 源端调试 + 光机控制工具 > LT8619C(HDMI→RGB888)→ DLPC3421 投影转接板调试配套的 PC 端工具: > HDMI **源端**(EDID 查看、分辨率切换、纯色/测试图案投屏)+ **光机控制** > (RS485 直连板上 GD32 网关,开关光机/设光强/查温度电流)。 > > - **只想用工具**:到 [Gitea Releases](https://gitea.hulk.wang/hulk/LT8619C_Debug_Tools/releases) -> 下载 `HDMI-Tool-vX.Y.Z-win64.zip`,解压双击 `HDMI-Tool.exe` 即可(Windows 10/11 x64,免安装、无需 Python)。 +> 下载 `DLPilot-vX.Y.Z-win64.zip`,解压双击 `DLPilot.exe` 即可(Windows 10/11 x64,免安装、无需 Python)。 > - **要改代码/重新打包**:见 §8、§9。 > > 更新:2026-09-11 @@ -29,15 +29,15 @@ ## 2. 下载与安装 1. 打开 [Releases 页面](https://gitea.hulk.wang/hulk/LT8619C_Debug_Tools/releases),取最新的 - `HDMI-Tool-vX.Y.Z-win64.zip`; + `DLPilot-vX.Y.Z-win64.zip`; 2. 解压到**任意可写目录**(自定义图片与栏位配置会写到 exe 旁边); -3. 双击 `HDMI-Tool.exe`。首次启动比脚本慢一两秒(onefile 解压),属正常现象。 +3. 双击 `DLPilot.exe`。首次启动比脚本慢一两秒(onefile 解压),属正常现象。 包内包含: ``` -HDMI-Tool/ -├── HDMI-Tool.exe 主程序(单文件自包含, 光机控制的 pyserial 已内置) +DLPilot/ +├── DLPilot.exe 主程序(单文件自包含, 光机控制的 pyserial 已内置) ├── pattern_slots.json 预置自定义栏位 + 串口记忆 ├── bw_*.png ×5 640x360 黑白测试图 ├── solid_*.png ×10 800x600 纯色测试图 @@ -72,7 +72,7 @@ HDMI-Tool/ ## 4. 典型测试场景 ``` -1. HDMI 接转接板 → 启动 HDMI-Tool → 刷新 → 选中板卡显示器 +1. HDMI 接转接板 → 启动 DLPilot → 刷新 → 选中板卡显示器 2. 板卡 shadow EDID 首选 640x360@60 → 测试卡区域选 640x360(与光机面板原生 1:1) 3. "光机控制"连接串口 → M999 查版本确认链路通 → M730S0 开光机 4. 点 R/G/B 行纯色按钮投图 → 目视/逻辑分析仪核对 RGB888 输出 @@ -180,7 +180,7 @@ python la_wave_analyzer3.py # 3 通道(RGB 三组同拍, ch8/ ## 8. 目录结构与从源码运行 ``` -HDMI-Tool/ +DLPilot/ ├── src/ # 源代码(人工维护区) │ ├── hdmi_gui.py # 入口与命令行模式(argparse 分发) │ ├── app_gui.py # CustomTkinter 主界面(双栏仪表盘) @@ -202,7 +202,7 @@ HDMI-Tool/ │ ├── bw_*.png ×5 # 640x360 黑白系列 │ └── solid_*.png ×10 # 800x600 纯色系列 ├── release/ # 构建与发布产物(机器生成区, 不手改) -│ ├── HDMI-Tool.exe # 打包单文件版(改动跟随源码提交入库) +│ ├── DLPilot.exe # 打包单文件版(改动跟随源码提交入库) │ ├── pattern_slots.json # exe 运行配置(栏位预置 + 串口记忆) │ ├── *.png / README.md # 附属文件平铺副本(由 package_release.py 从 assets/ 同步) │ └── *.zip # 发布包(不入库, 上传 Gitea Release) @@ -220,11 +220,11 @@ GUI 需 customtkinter(`py -m pip install customtkinter`);光机控制需 p ```powershell cd src python selftest_rs485.py # 光机协议回归(改 dlpc_rs485.py 后必跑) -python build_exe.py # 打包 → ../release/HDMI-Tool.exe(自动装 PyInstaller; +python build_exe.py # 打包 → ../release/DLPilot.exe(自动装 PyInstaller; # 内置 pyserial/customtkinter, CTk 主题数据自动收集) python build_exe.py --debug # 额外出一个带控制台的调试变体(--dump 可见输出) -python package_release.py 0.2.0 # 组装 release/HDMI-Tool-v0.2.0-win64.zip -python publish_gitea.py HDMI-Tool-v0.2.0-win64.zip --insecure # 上传 Gitea Release(需 GITEA_TOKEN) +python package_release.py 0.2.0 # 组装 release/DLPilot-v0.2.0-win64.zip +python publish_gitea.py DLPilot-v0.2.0-win64.zip --insecure # 上传 Gitea Release(需 GITEA_TOKEN) ``` ## 10. 注意事项 / FAQ @@ -235,6 +235,6 @@ python publish_gitea.py HDMI-Tool-v0.2.0-win64.zip --insecure # 上传 Gitea R - **exe 放只读目录会怎样**:自定义图片与 `pattern_slots.json` 写在 exe 旁边,只读目录会导致配置存不下; - **重新打包后图标没变**:Windows 图标缓存,`ie4uinit -show` 或改个名即可; - **多屏序号**:切分辨率前先确认显示器序号(GUI 下拉框与 `hdmi_source.bat -List` 输出一致); -- **残留进程**:修改源码重新打包前先结束残留的 HDMI-Tool 进程(`build_exe.py` 会自动 taskkill); +- **残留进程**:修改源码重新打包前先结束残留的 DLPilot 进程(`build_exe.py` 会自动 taskkill); - **改 logo**:改 `src/logos/logo_ph_orange.svg` → `python src/logos/make_ico.py` → 重新打包; - **配置互不影响**:exe 与源码脚本各自按所在目录保存 `pattern_slots.json`,两份安装互不干扰。 diff --git a/HDMI-Tool/src/app_gui.py b/HDMI-Tool/src/app_gui.py index 5eaccf6..e5fb9a0 100644 --- a/HDMI-Tool/src/app_gui.py +++ b/HDMI-Tool/src/app_gui.py @@ -1,9 +1,9 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ -HDMI-Tool 主界面 — CustomTkinter 双栏仪表盘 +DLPilot 主界面 — CustomTkinter 双栏仪表盘 ================================================================ -布局(HDMI-Tool/UI参考布局.svg): +布局(DLPilot/UI参考布局.svg): 左列 显示器选择 | 支持的模式 | EDID 信息 | 测试图案/纯色/自定义 | EDID 原始数据 右列 串口选择与参数 | 串口数据(收发日志) | 预设与自定义命令 | 光强/定时快捷滑条 默认深色外观, 顶栏可切换 Dark/Light/System。 @@ -12,6 +12,7 @@ HDMI-Tool 主界面 — CustomTkinter 双栏仪表盘 投屏窗口在 patterns, 串口协议在 dlpc_rs485, 运行配置在 config。 """ +import ctypes import ctypes import os import queue @@ -63,7 +64,11 @@ def run_gui(auto_close=0): class App(ctk.CTk): def __init__(self, auto_close=0): super().__init__() - self.title('HDMI-Tool — EDID 查看器 + 测试图案 + 光机控制 (LT8619C 转接板调试)') + self.title('DLPilot — 3D 光固化光机调试台 (EDID · 测试图案 · RS485 光机控制)') + try: # 任务栏独立分组 + ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID('hulk.DLPilot') + except Exception: + pass self.geometry('1440x920') self.minsize(1180, 800) ic = get_icon_path() @@ -97,8 +102,10 @@ class App(ctk.CTk): def _set_appearance(self, mode): ctk.set_appearance_mode(mode) - def _card(self, parent, title, button=None, command=None, right_label=None): - """卡片容器: 圆角边框 + 标题行(可带右侧小按钮/右对齐标签), 返回 (卡片, 内容 frame) + def _card(self, parent, title, button=None, command=None, right_label=None, + right_widget=None): + """卡片容器: 圆角边框 + 标题行(可带右侧小按钮/右对齐标签/自定义控件), + 返回 (卡片, 内容 frame) 卡片自身用 grid 参与列布局; 卡片内部(head/content/行控件)一律用 pack。 """ @@ -107,6 +114,8 @@ class App(ctk.CTk): head = ctk.CTkFrame(card, fg_color='transparent') head.pack(fill='x', padx=12, pady=(8, 0)) ctk.CTkLabel(head, text=title, font=BOLD, anchor='w').pack(side='left') + if right_widget is not None: # 自定义控件(如 电流读数+查电流) + right_widget.pack(side='right') if right_label is not None: ctk.CTkLabel(head, textvariable=right_label, text_color='gray60').pack(side='right') @@ -120,7 +129,7 @@ class App(ctk.CTk): def _build(self): top = ctk.CTkFrame(self, fg_color='transparent') top.pack(fill='x', padx=12, pady=(10, 2)) - ctk.CTkLabel(top, text='HDMI-Tool', font=TITLE_FONT).pack(side='left') + ctk.CTkLabel(top, text='DLPilot', font=TITLE_FONT).pack(side='left') ctk.CTkLabel(top, text='EDID · 测试图案 · 光机控制', text_color='gray60').pack(side='left', padx=10, pady=(6, 0)) seg = ctk.CTkSegmentedButton(top, values=['Dark', 'Light', 'System'], @@ -149,8 +158,8 @@ class App(ctk.CTk): ).pack(expand=True) def _build_left(self, col): - col.grid_rowconfigure(1, weight=2) # 支持的模式(与 EDID 信息等高) - col.grid_rowconfigure(2, weight=2) # EDID 信息 + col.grid_rowconfigure(1, weight=2) # 支持的模式 + col.grid_rowconfigure(2, weight=1) # EDID 信息(压缩高度) col.grid_rowconfigure(4, weight=0) # EDID 原始数据(固定高, 压缩) col.grid_columnconfigure(0, weight=1) @@ -218,7 +227,7 @@ class App(ctk.CTk): row3 = ctk.CTkFrame(c, fg_color='transparent') row3.pack(fill='x', pady=(6, 0)) self.slot_buttons = [] - for i in range(config.SLOT_COUNT): + for i in range(3): # 自定义栏位(沿用原 3 槽配置) cell = ctk.CTkFrame(row3, fg_color='transparent') cell.pack(side='left', padx=(0, 10)) btn = ctk.CTkButton(cell, text=self.slots[i]['name'], width=96, @@ -231,6 +240,22 @@ class App(ctk.CTk): self.slot_buttons.append(btn) ctk.CTkLabel(row3, text='点击投图, 齿轮按钮配置图片', text_color='gray50').pack(side='left', padx=4) + # -- 光校图案(预留 5 槽): 3D 光固化打印测试/校准用图 -- + row4 = ctk.CTkFrame(c, fg_color='transparent') + row4.pack(fill='x', pady=(6, 0)) + for i in range(3, config.SLOT_COUNT): + cell = ctk.CTkFrame(row4, fg_color='transparent') + cell.pack(side='left', padx=(0, 10)) + btn = ctk.CTkButton(cell, text=self.slots[i]['name'], width=96, + command=lambda i=i: self._show_custom(i)) + btn.pack(side='left') + ctk.CTkButton(cell, text='\uE713', width=30, height=24, + font=('Segoe MDL2 Assets', 13), + command=lambda i=i: self._configure_slot(i) + ).pack(side='left', padx=(4, 0)) + self.slot_buttons.append(btn) + ctk.CTkLabel(row4, text='校准图案(预留 5 槽, 齿轮改图)', + text_color='gray50').pack(side='left', padx=4) # -- EDID 原始数据 -- card, c = self._card(col, 'EDID 原始数据', @@ -293,12 +318,20 @@ class App(ctk.CTk): '累加和校验; 全部命令见 README"光机控制"') # -- 光机命令 -- - card, c = self._card(col,'光机命令 — 预设 / 自定义 / TEC') + # 标题行右侧: 电流实时读数 + 查电流按钮(okR..G..B.. 应答解析) + cur_frame = ctk.CTkFrame(self, fg_color='transparent') + self.var_current = tk.StringVar(value='电流: —') + ctk.CTkLabel(cur_frame, textvariable=self.var_current, width=168, + anchor='e', text_color='#3B8ED0').pack(side='left') + ctk.CTkButton(cur_frame, text='查电流', width=64, height=24, + command=self._query_current).pack(side='left', padx=(6, 0)) + card, c = self._card(col,'光机命令 — 预设 / 自定义 / TEC', + right_widget=cur_frame) card.grid(row=2, column=0, sticky='ew', pady=(10, 0)) row1 = ctk.CTkFrame(c, fg_color='transparent') row1.pack(fill='x') for name, cmd in (('开光机', 'M730S0'), ('关光机', 'M730S1'), - ('查电流', 'M732'), ('查版本', 'M999'), ('软件重启', 'M888'), + ('查版本', 'M999'), ('软件重启', 'M888'), ('开TEC', 'M7S0'), ('关TEC', 'M7S1'), ('TEC33.0°C', 'M8S330')): ctk.CTkButton(row1, text=name, width=64, command=lambda cc=cmd: self._dlpc_send(cc) @@ -365,7 +398,7 @@ class App(ctk.CTk): textvariable=self.var_light) self.ent_light.pack(side='left') self.ent_light.bind('', self._light_entry_apply) - ctk.CTkButton(rowa, text='下发 M731S', width=110, + ctk.CTkButton(rowa, text='下发电流值', width=110, command=self._dlpc_send_light).pack(side='left', padx=(6, 0)) rowb = ctk.CTkFrame(c, fg_color='transparent') rowb.pack(fill='x', pady=(8, 0)) @@ -395,7 +428,7 @@ class App(ctk.CTk): textvariable=self.var_tec) self.ent_tec.pack(side='left') self.ent_tec.bind('', self._tec_entry_apply) - ctk.CTkButton(rowc, text='下发 M8S', width=110, + ctk.CTkButton(rowc, text='下发温度值', width=110, command=self._dlpc_send_tec).pack(side='left', padx=(6, 0)) # ============================================================ @@ -634,8 +667,16 @@ class App(ctk.CTk): except ValueError: text = f'{which}: {m.group(1)}' self._dlpc_log_q.put(('temp', text)) + # 电流查询应答: okRGB -> 标题行实时读数 + m = re.search(r'← okR(\d+)G(\d+)B(\d+)', line) + if m: + self._dlpc_log_q.put(('current', f'电流 R:{m.group(1)} ' + f'G:{m.group(2)} B:{m.group(3)}')) self._dlpc_log_q.put(('event', line)) + def _query_current(self): + self._dlpc_send('M732') + def _query_dmd(self): self._tl_order.append('DMD') self._dlpc_send('M201') @@ -666,6 +707,8 @@ class App(ctk.CTk): self.var_dmd.set(text) else: self.var_lamp.set(text) + elif kind == 'current': + self.var_current.set(text) self._dlpc_log(text) except queue.Empty: pass diff --git a/HDMI-Tool/src/build_exe.py b/HDMI-Tool/src/build_exe.py index f9dfbef..9c5ee57 100644 --- a/HDMI-Tool/src/build_exe.py +++ b/HDMI-Tool/src/build_exe.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ -把 hdmi_gui.py 打包成单文件 exe(工具名: HDMI-Tool) +把 hdmi_gui.py 打包成单文件 exe(工具名: DLPilot) ================================ 使用 PyInstaller --onefile --noconsole: Python 解释器 + 标准库 + tkinter 全部打进一个 exe, 目标机器无需安装任何依赖。 @@ -10,7 +10,7 @@ python build_exe.py 自动安装 PyInstaller(如缺)并打包 python build_exe.py --debug 额外打一个带控制台的变体(--dump 可用) -产物: release/HDMI-Tool.exe(及 --debug 时的 HDMI-Tool-console.exe) +产物: release/DLPilot.exe(及 --debug 时的 DLPilot-console.exe) 首次运行 onefile exe 会先解压到临时目录, 启动比脚本慢一两秒, 属正常现象。 """ @@ -84,10 +84,10 @@ def main(): build_console = '--debug' in sys.argv ensure_pyinstaller() # 常规版: 双击即用, 无黑框(GUI/图案/自定义栏位全部可用, --dump 除外) - build('HDMI-Tool', ['--noconsole']) + build('DLPilot', ['--noconsole']) if build_console: # 调试版: 带控制台, --dump / 异常栈可见 - build('HDMI-Tool-console', []) + build('DLPilot-console', []) if __name__ == '__main__': diff --git a/HDMI-Tool/src/config.py b/HDMI-Tool/src/config.py index f7a2d9f..aa33656 100644 --- a/HDMI-Tool/src/config.py +++ b/HDMI-Tool/src/config.py @@ -39,7 +39,7 @@ if getattr(sys, 'frozen', False): BASE_DIR = os.path.dirname(os.path.abspath(sys.executable)) else: BASE_DIR = os.path.dirname(os.path.abspath(__file__)) -SLOT_COUNT = 3 +SLOT_COUNT = 8 SLOT_CONFIG = os.path.join(BASE_DIR, 'pattern_slots.json') IMG_EXTS = ['.png', '.gif'] + (['.jpg', '.jpeg', '.bmp', '.webp'] if HAS_PIL else []) diff --git a/HDMI-Tool/src/package_release.py b/HDMI-Tool/src/package_release.py index 90a15de..0da7568 100644 --- a/HDMI-Tool/src/package_release.py +++ b/HDMI-Tool/src/package_release.py @@ -1,22 +1,22 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ -组装 HDMI-Tool 发布包: exe + 附属资产 → 一个文件夹 + 一个 zip(解压即用) +组装 DLPilot 发布包: exe + 附属资产 → 一个文件夹 + 一个 zip(解压即用) ================================================================ 先把 assets/ 的图案复制进 release/(与 exe 平铺), 使 release/ 本身就是 可直接使用的完整文件夹; 再原样压成 zip —— 两者内容始终一致。 -zip 解压后根目录为 HDMI-Tool/, 与 exe 运行目录结构一致: - HDMI-Tool.exe 主程序(先运行 build_exe.py 打包) +zip 解压后根目录为 DLPilot/, 与 exe 运行目录结构一致: + DLPilot.exe 主程序(先运行 build_exe.py 打包) pattern_slots.json 预置自定义栏位(指向前 3 张 bw 图案) bw_*.png 640x360 黑白测试图 ×5(自定义栏位用) solid_*.png 800x600 纯色测试图 ×10(RGB 位交换测试用) README.md 使用说明 用法: - python package_release.py 版本号自动取最近 git tag(HDMI-Tool-v*) + python package_release.py 版本号自动取最近 git tag(DLPilot-v*) python package_release.py 0.1.0 手动指定版本号 -产物: release/HDMI-Tool-v<版本>-win64.zip(zip 不入库, 上传到 Gitea Release) +产物: release/DLPilot-v<版本>-win64.zip(zip 不入库, 上传到 Gitea Release) """ import os @@ -35,23 +35,23 @@ PATTERN_GLOBS = ('bw_*.png', 'solid_*.png') def detect_version(): - """从最近的 HDMI-Tool-v* tag 推断版本号, 无 tag 则报错提示手动指定""" + """从最近的 DLPilot-v* tag 推断版本号, 无 tag 则报错提示手动指定""" try: out = subprocess.check_output( - ['git', 'describe', '--tags', '--abbrev=0', '--match', 'HDMI-Tool-v*'], + ['git', 'describe', '--tags', '--abbrev=0', '--match', 'DLPilot-v*'], cwd=BASE, stderr=subprocess.DEVNULL) - return out.decode().strip().removeprefix('HDMI-Tool-v') + return out.decode().strip().removeprefix('DLPilot-v') except Exception: sys.exit('未能从 git tag 推断版本号, 请手动指定: python package_release.py <版本号>') def main(): version = (sys.argv[1] if len(sys.argv) > 1 else detect_version()).lstrip('v') - exe = os.path.join(RELEASE, 'HDMI-Tool.exe') + exe = os.path.join(RELEASE, 'DLPilot.exe') slots = os.path.join(RELEASE, 'pattern_slots.json') readme = os.path.join(BASE, 'README.md') if not os.path.exists(exe): - sys.exit('缺少 release/HDMI-Tool.exe, 先运行: python build_exe.py') + sys.exit('缺少 release/DLPilot.exe, 先运行: python build_exe.py') for must in (slots, readme): if not os.path.exists(must): sys.exit(f'缺少 {must}') @@ -70,11 +70,11 @@ def main(): shutil.copy2(os.path.join(ASSETS, p), os.path.join(RELEASE, p)) shutil.copy2(readme, os.path.join(RELEASE, 'README.md')) - zip_name = f'HDMI-Tool-v{version}-win64.zip' + zip_name = f'DLPilot-v{version}-win64.zip' zip_path = os.path.join(RELEASE, zip_name) with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as z: - for p in ['HDMI-Tool.exe', 'pattern_slots.json', 'README.md'] + patterns: - z.write(os.path.join(RELEASE, p), f'HDMI-Tool/{p}') + for p in ['DLPilot.exe', 'pattern_slots.json', 'README.md'] + patterns: + z.write(os.path.join(RELEASE, p), f'DLPilot/{p}') print(f'发布文件夹: {RELEASE} (exe+配置+说明+{len(patterns)} 张图案, 平铺即用)') print(f'发布包: {zip_path} ({os.path.getsize(zip_path) / 1024 / 1024:.1f} MB)') print('下一步上传: python publish_gitea.py', zip_name) diff --git a/HDMI-Tool/src/publish_gitea.py b/HDMI-Tool/src/publish_gitea.py index cd1ebaa..87f95c7 100644 --- a/HDMI-Tool/src/publish_gitea.py +++ b/HDMI-Tool/src/publish_gitea.py @@ -4,12 +4,12 @@ 创建/更新 Gitea Release 并上传发布 zip(纯标准库, 无需安装依赖) ================================================================ 用法: - python publish_gitea.py HDMI-Tool-v0.1.0-win64.zip + python publish_gitea.py DLPilot-v0.1.0-win64.zip python publish_gitea.py --notes-file release/notes-v0.1.0.md - python publish_gitea.py --tag HDMI-Tool-v0.1.0 --replace + python publish_gitea.py --tag DLPilot-v0.1.0 --replace 行为: - - tag 与版本默认取 zip 文件名(HDMI-Tool-vX.Y.Z-win64.zip → HDMI-Tool-vX.Y.Z) + - tag 与版本默认取 zip 文件名(DLPilot-vX.Y.Z-win64.zip → DLPilot-vX.Y.Z) - release 不存在则创建(tag 不存在时 Gitea 在默认分支头自动建 tag); 已存在则复用, 仅上传/更新资产 - release 上已有同名资产时: 默认跳过, --replace 删旧再传 @@ -27,16 +27,16 @@ import urllib.error import urllib.request import uuid -DEFAULT_NOTES = """## HDMI-Tool {version} +DEFAULT_NOTES = """## DLPilot {version} HDMI 源端调试工具(LT8619C → DLPC3421 转接板配套): EDID 查看/逐字节解析、 分辨率切换、纯色与测试图案全屏投屏。 ### 安装 -下载 `HDMI-Tool-v{version}-win64.zip`, 解压后双击 `HDMI-Tool.exe`(Windows 10/11 x64, 免安装)。 +下载 `DLPilot-v{version}-win64.zip`, 解压后双击 `DLPilot.exe`(Windows 10/11 x64, 免安装)。 ### 包内容 -- `HDMI-Tool.exe` — 主程序 +- `DLPilot.exe` — 主程序 - `pattern_slots.json` — 预置自定义栏位(指向 bw_*.png) - `bw_*.png` ×5 / `solid_*.png` ×10 — 测试图案 - `README.md` — 完整使用说明 @@ -119,7 +119,7 @@ def main(): sys.exit('缺少 API token: 传 --token 或设环境变量 GITEA_TOKEN') tag = args.tag or re.sub(r'-win64\.zip$', '', os.path.basename(args.zipfile_path)) - version = tag.removeprefix('HDMI-Tool-v') + version = tag.removeprefix('DLPilot-v') notes = open(args.notes_file, encoding='utf-8').read() if args.notes_file \ else DEFAULT_NOTES.format(version=version) @@ -133,7 +133,7 @@ def main(): else: status, rel = api.request('POST', '/releases', json.dumps({ 'tag_name': tag, - 'name': f'HDMI-Tool v{version}', + 'name': f'DLPilot v{version}', 'body': notes, }).encode(), {'Content-Type': 'application/json'}) if status != 201: diff --git a/README.md b/README.md index 829728b..2eccaa1 100644 --- a/README.md +++ b/README.md @@ -7,16 +7,16 @@ LT8619C(HDMI→RGB888)→ DLPC3421 投影转接板调试配套上位机工 | 工具 | 用途 | 获取 | |---|---|---| -| [HDMI-Tool](HDMI-Tool/) | HDMI 源端(EDID 查看/逐字节解析、分辨率切换、纯色与测试图案全屏投屏)+ 光机控制(RS485→GD32 网关→DLPC3421:开关光机/设光强/查温度电流) | 到 [Releases](https://gitea.hulk.wang/hulk/LT8619C_Debug_Tools/releases) 下 `HDMI-Tool-vX.Y.Z-win64.zip`,解压即用;详见 [HDMI-Tool/README.md](HDMI-Tool/README.md) | +| [DLPilot](DLPilot/) | HDMI 源端(EDID 查看/逐字节解析、分辨率切换、纯色与测试图案全屏投屏)+ 光机控制(RS485→GD32 网关→DLPC3421:开关光机/设光强/查温度电流) | 到 [Releases](https://gitea.hulk.wang/hulk/LT8619C_Debug_Tools/releases) 下 `DLPilot-vX.Y.Z-win64.zip`,解压即用;详见 [DLPilot/README.md](DLPilot/README.md) | | [I2C-Inject](I2C-Inject/) | LT8619C 寄存器在线读写:RP2040 注入器在 demo 板 I2C 总线上择机注入(避让主控轮询,写后自动读回校验) | 需配合 RP2040 固件 `rp2040_inject.py`;详见 [I2C-Inject/README.md](I2C-Inject/README.md) | ## 环境要求 - 发布版 zip 开箱即用(Windows 10/11 x64,无需安装 Python) -- 源码运行:Python ≥3.10;HDMI-Tool 命令行/EDID 纯标准库,GUI 需 +- 源码运行:Python ≥3.10;DLPilot 命令行/EDID 纯标准库,GUI 需 `py -m pip install customtkinter`(自定义图片 JPG/BMP 可选 Pillow、光机控制可选 pyserial); I2C-Inject 需 `py -m pip install pyserial` -- 重新打包:`HDMI-Tool/src/build_exe.py`(自动安装 PyInstaller);I2C-Inject 目录内 `python build_exe.py` +- 重新打包:`DLPilot/src/build_exe.py`(自动安装 PyInstaller);I2C-Inject 目录内 `python build_exe.py` ## 目录结构 @@ -25,7 +25,7 @@ LT8619C(HDMI→RGB888)→ DLPC3421 投影转接板调试配套上位机工 ``` LT8619C_Debug_Tools/ -├── HDMI-Tool/ +├── DLPilot/ │ ├── src/ # 源码 + 打包/发布脚本 + 图标源 │ ├── assets/ # 生成的测试图案 PNG(gen_*.py 产物) │ ├── release/ # 打包 exe + 运行配置(入库);发布 zip(不入库) @@ -36,13 +36,13 @@ LT8619C_Debug_Tools/ └── README.md ``` -## 发布流程(HDMI-Tool) +## 发布流程(DLPilot) ```powershell -cd HDMI-Tool/src -python build_exe.py # 打包 → ../release/HDMI-Tool.exe -python package_release.py <版本> # → ../release/HDMI-Tool-v<版本>-win64.zip -python publish_gitea.py HDMI-Tool-v<版本>-win64.zip --insecure # 上传 Gitea Release(需 GITEA_TOKEN) +cd DLPilot/src +python build_exe.py # 打包 → ../release/DLPilot.exe +python package_release.py <版本> # → ../release/DLPilot-v<版本>-win64.zip +python publish_gitea.py DLPilot-v<版本>-win64.zip --insecure # 上传 Gitea Release(需 GITEA_TOKEN) ``` ## 备注