feat: 产品更名 DLPilot(3D 光固化光机调试台) + 按标记调整界面
This commit is contained in:
@@ -9,6 +9,7 @@ dist/
|
||||
|
||||
# 发布 zip: 可由 src/package_release.py 重新生成, 只上传 Gitea Release
|
||||
HDMI-Tool/release/*.zip
|
||||
DLPilot/release/*.zip
|
||||
|
||||
# ZCode 客户端本地会话数据(计划留档等), 非项目配置
|
||||
.zcode/
|
||||
|
||||
+13
-13
@@ -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<ver>-win64.zip`(校验栏位引用完整性; release/ 与 zip 内容一致) |
|
||||
| `src/build_exe.py` | PyInstaller 打包 → `release/DLPilot.exe`(onefile/noconsole, 内嵌图标+pyserial+customtkinter) |
|
||||
| `src/package_release.py` | 复制图案到 release/(平铺) → `release/DLPilot-v<ver>-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。
|
||||
|
||||
+13
-13
@@ -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 <capture.csv> # 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`,两份安装互不干扰。
|
||||
|
||||
Binary file not shown.
+13
-13
@@ -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 <capture.csv> # 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`,两份安装互不干扰。
|
||||
|
||||
+56
-13
@@ -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('<Return>', 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('<Return>', 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))
|
||||
# 电流查询应答: okR<n>G<n>B<n> -> 标题行实时读数
|
||||
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
|
||||
|
||||
@@ -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__':
|
||||
|
||||
@@ -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 [])
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 <zip> --notes-file release/notes-v0.1.0.md
|
||||
python publish_gitea.py <zip> --tag HDMI-Tool-v0.1.0 --replace
|
||||
python publish_gitea.py <zip> --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:
|
||||
|
||||
@@ -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)
|
||||
```
|
||||
|
||||
## 备注
|
||||
|
||||
Reference in New Issue
Block a user