Files
HW-Debug-Tools/HDMI-Tool/AGENTS.md
T

110 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AGENTS.md — HDMI-Tool 工程档案(供 AI/Agent 使用)
> **本文档面向 AI/Agent**,是人类文档 [README.md](README.md) 的姊妹篇,两者不重叠:
> README 回答"这是什么、怎么用";本文回答"代码怎么组织、怎么构建发布、改动时哪些约束不能破坏"。
> 任何 Agent 在修改本目录代码前应先读完本文。
## 1. 项目定位
仓库 `LT8619C_Debug_Tools` 是 LT8619C(HDMI→RGB888)→ DLPC3421 投影转接板的**调试上位机工具集**,
上游主仓库(固件)为 `hulk/LT8619C_DLPC3421_HDMI`(同 Gitea 实例 `gitea.hulk.wang`)。
本工具工作在 HDMI **源端**(PC 显卡侧),与固件侧寄存器调试(I2C-Inject 工具)配合。
寄存器语义判读基线(0x606E 位交换 / 0x606D 整组顺序)在上游仓库 `doc/architecture/`,不在本仓库。
## 2. 目录契约(重要)
```
HDMI-Tool/
├── src/ 源代码区 —— 只有这里可以手改(logos/ 改图标源后重跑 make_ico.py)
├── assets/ 生成资产区 —— gen_*.py 的产物(PNG 图案),可随时再生成,改动需提交
├── release/ 产物区 —— 机器生成,禁止手改:HDMI-Tool.exe(入库)、
│ pattern_slots.json(exe 运行配置,入库)、*.zip(gitignore,只上传 Release)
├── README.md 人类文档
└── AGENTS.md 本文
```
划分原则:**"人写的"在 src/,"生成的"按去向分 assets/(随包分发)与 release/(直接交付)**。
新文件必须落对区域;不要在 src/ 外新建源码,不要手改 assets/ 下的 PNG(改生成脚本再跑)。
### 文件角色速查
| 文件 | 角色 |
|---|---|
| `src/hdmi_gui.py` | 单文件主程序:GUI(tkinter) + 命令行,约 1500 行,纯标准库 |
| `src/build_exe.py` | PyInstaller 打包 → `release/HDMI-Tool.exe`(onefile/noconsole,内嵌图标) |
| `src/package_release.py` | exe+图案+说明 → `release/HDMI-Tool-v<ver>-win64.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) |
| `src/gen_solid_colors.py` | 生成 `assets/solid_*.png` ×10(800x600 纯色,需 Pillow) |
| `src/la_wave_analyzer*.py` | 逻辑分析仪 CSV 波形判读(2/3 通道,40MHz 像素时钟假设) |
| `src/logos/make_ico.py` | svg/png → ico(写在其自身目录) |
| `release/pattern_slots.json` | 预置栏位:西门子星/波带片/综合测试卡,area=640x360 |
## 3. 代码不变量(改 hdmi_gui.py 必须维持)
1. **纯标准库**:hdmi_gui.py 只准 import 标准库(ctypes/winreg/tkinter/…)。Pillow 是
*可选*加速(仅扩展自定义图片格式 PNG/GIF 之外的 JPG/BMP/WebP),缺失时必须照常工作。
2. **BASE_DIR 语义**:frozen(PyInstaller onefile)时 `BASE_DIR=exe 所在目录`(`sys.executable`),
源码运行时 `=hdmi_gui.py 所在目录`(`__file__`)。所有用户数据(pattern_slots.json、
自定义图片)都写/读自 BASE_DIR **平铺**存放,不建子目录。
3. **自定义栏位 `file` 字段是裸文件名**:加载时 `os.path.join(BASE_DIR, file)` 解析,
因此 pattern_slots.json 引用的图片必须与 exe 同目录 —— package_release.py 正是按此平铺打包。
4. **exe 自包含**:图标经 `--add-data` 内嵌(运行时从 `_MEIPASS` 读);内置五种图案
(红/绿/蓝/棋盘格/网格线)由程序绘制,运行时**不依赖** assets/;solid/bw PNG 只服务自定义栏位。
5. **DPI 感知**:进程启动即 `SetProcessDpiAwareness(2)`,图案窗口按物理像素定位,勿移除。
6. **启动强制扩展拓扑**:`SetDisplayConfig(SDC_TOPOLOGY_EXTEND|SDC_APPLY)`,静默容错
(失败不阻断启动)。动机:LT8619C 热插拔后 Windows 可能停留在"仅电脑屏幕"。
7. **分辨率切换是临时的**:走 `CHANGEDISPLAYSETTINGS`(不写注册表),"恢复"用会话开始时快照。
8. **EDID 来源是注册表**(`HKLM\SYSTEM\CurrentControlSet\Enum\DISPLAY\...\Device Parameters\EDID`),
不是 WMI/DDC;exe 的 noconsole 版无 stdout,`--dump/--edid-fields` 只在源码/控制台版可用。
## 4. 领域语义(测试值都有含义,勿"顺手改")
- 纯色值 55/AA/FF:55(01010101) 与 AA(10101010) 互为字节镜像对(检出位序颠倒/位交换),
FF(11111111) 全高基准;R/G/B 三行对应 RGB888 三字节组(R=D[23:16]/G=D[15:8]/B=D[7:0])。
- 800x600@60:demo 板 shadow EDID 首选时序(solid 系列分辨率与之一致)。
- 640x360:测试卡区域默认值(16:9 半分辨率,点对点检查用);full=铺满所选屏。
- bw 系列图案各自目的见 `src/gen_bw_patterns.py` 顶部清单注释。
## 5. 构建 / 发布流水线(全部在 src/ 下执行)
```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)
```
发布约定:
- tag/release 命名 `HDMI-Tool-vX.Y.Z`,zip 命名 `HDMI-Tool-vX.Y.Z-win64.zip`(publish_gitea.py
依赖此命名从文件名推 tag);
- **exe 与 pattern_slots.json 改动跟随源码提交入库;zip 永不入库**(.gitignore 已挡);
- publish_gitea.py 幂等:release 已存在则复用,同名资产默认跳过,`--replace` 删旧重传;
- token 读环境变量 `GITEA_TOKEN`:本机已用 setx 持久化为用户级变量(新开的会话/终端自动
继承,值不入库;在 setx 之前启动的进程读不到,需重开终端),急用时也可临时传 `--token`;
- Gitea 实例 `gitea.hulk.wang`,API 走 https(443),git 走 ssh(1234)——从 origin 远程自动解析;
python urllib 连该实例会在部分请求上报 `SSL: UNEXPECTED_EOF`,**实际发布需加 `--insecure`**;
- 本实例 Gitea 的 API 兼容性怪癖:`GET /releases/tags/{tag}` 返回的 `assets` 是纯数组,
而 `GET /releases/{id}` 是 `{items:[...]}` —— publish_gitea.py 已按两种形状兼容,勿"简化"回去。
## 6. 已知坑(历史踩过,勿重蹈)
- onefile 运行时 `__file__` 指向临时解压目录 `_MEIPASS`,定位 exe 必须用 `sys.executable`(§3.2);
- 重新打包前旧 exe 可能被残留进程占用 → build_exe.py 会 taskkill 同名进程,手改打包脚本时保留;
- 打包后本机图标缓存不刷新:`ie4uinit -show`,不是产物问题;
- 改图标流程:改 svg → `make_ico.py` 生成 ico → 重新打包(ico 同时是文件图标与运行时窗口图标);
- GUI 与 hdmi_source.ps1 各自独立实现显示器枚举,行为可能微差(GUI 与 `-List` 序号一致,
但与"设置"面板序号无保证);多屏操作前先确认序号;
- `pattern_slots.json` 兼容两种格式:新 `{area, slots[]}`,旧纯数组(无 area)——load_slots 已兼容,
但写出只应写新格式。
## 7. 验证清单(改完代码后)
1. `python hdmi_gui.py --seconds 5` —— GUI 冒烟(自动开关);
2. `python hdmi_gui.py --test-pattern Checker --area 800x600 --seconds 3` —— 投图链路;
3. `python hdmi_gui.py --dump` —— EDID 解算不抛异常;
4. `python build_exe.py` → 双击 release/HDMI-Tool.exe 确认图标/启动/投图;
5. `python package_release.py <版本>` —— 不报"引用图片缺失"即栏位完整性 OK。