Author SHA1 Message Date
hulk 8e91e661f1 fix(SerialMate): v0.1.2 解析模式不再吞数据——不成帧字节透传显示
背景: 用户接非 DLPilot 协议设备(COM25)开解析模式接收区一片空白——_dispatch_rx 在解析模式只上抛完整合法帧, 不成帧字节(纯文本日志/别的协议/波特率不符乱码)被 FrameParser 重同步时静默丢弃。用户明确定位: 首先是基础串口调试工具, 自定义协议解析是附加项, 附加能力不得影响本体功能。

修复: protocol.py FrameParser 丢弃字节累积进 garbage(新增 drain_garbage(), feed() 返回值不变); link.py 新增 on_garbage(data, ts) 回调, 每批无条件 drain(未接回调也不累积); main.py 把 on_garbage 并入 raw 事件与透传行同格式显示, 解析协议帧开关补 tooltip, 版本 0.1.2。半帧前缀扣留语义有意保留(可能补全成真帧, 至多扣一个前缀长度)。

自检: selftest 8b +10 项(纯文本全透出/噪声+帧+尾字节/坏CRC帧字节全透出/半帧头扣留补全), loop 3b +3 项, gui 5b +2 项; 全量 67+21+68 项 PASS; exe 已重建。README/AGENTS.md(不变量 5a) 同步。
2026-10-16 19:08:55 +08:00
hulk ac76c10132 docs(DLPilot): 面向二供的使用说明入库——使用说明.md 从解压安装包写起(安装/硬件连接/界面总览与快速开始/左列HDMI源端/右列光机控制/命令参考/典型流程/数据判读/FAQ/版本沿革),§3 嵌标注版主界面截图(manual-img/)并配四条上手要点;拓扑表述按勘误校准:HDMI 与 RS485 同接转接板、GD32E230 为板上主控 MCU(逻辑控制),不用 GD32 网关说法;记录转接板上电默认开光机(§3/§7.1);PDF 不入库、本地保留(暂存时排除,md 可随时重出);AGENTS.md 进度登记 2026-10-14 11:18:00 +08:00
hulk 7ba01eae5e chore: 全仓约束 exe 不入库——.gitignore 全局挡 *.exe,历史 39 个 exe blob 已用 git filter-repo 清除(仓库 1.1 GiB -> ~1 MB);各文档发布约定同步;agent.md 哈希引用按重写后映射更新 2026-10-13 16:31:45 +08:00
hulk 42ff258b35 feat: I2C-Lab v0.1.0 代码入库——RP2040 PIO 被动监控 probe 固件(pico-sdk C, 250MHz 双核) + Fluent 上位机(事务流/波形快照/CSV/演示模式);release/ 交付物(exe/UF2/BIN/zip)不入库、本地保留待真机验收发布;根 README 工具表与 agent.md 登记;I2C-Inject README 标注后续并入 I2C-Lab;移除误登记的 OBI-1/ui-style-demo 相关内容 2026-10-13 15:41:29 +08:00
hulk 74469cfe66 feat: DLPilot 校准测试图案(CeramixNano 系列 6 张)入库——assets 存档+release 平铺+自定义栏位接入(预置配置);package_release 收集规则同步扩展 2026-10-13 14:09:32 +08:00
hulk 2a9a5f5b96 docs(agent): 记录 DLPilot v0.4.3 与 SerialMate v0.1.1 已发布(tag 指向 296e220 / e5b2e45);踩坑表新增 PySide6 6.11 实例级枚举访问条目 2026-10-13 11:46:44 +08:00
hulk e5b2e45f57 fix: SerialMate v0.1.1 接收路径修复——时间戳改 link 线程到达时刻打戳、接收日志批量插入+5000行上限+积压折叠、通道配置缓存;自测扩至 selftest_gui 69 项,新增 ISSUE 报告与 _sim_periodic 复现脚本;重打包 2026-10-13 11:44:29 +08:00
hulk 296e220f20 fix: v0.4.3 修复长会话越跑越卡/命令无响应——日志手工 cursor 裁剪在 PySide6 6.11 必抛异常且打断 _poll_dlpc 消费;改 setMaximumBlockCount(500) 环形裁剪+逐事件兜底;新增 selftest_log 回归;重打包 2026-10-13 11:40:19 +08:00
hulk e3ef359df4 feat: 接入 gd32e230f8_firmware_merge_tool 子模块(GD32E230 固件合成+DAPLink Flash GUI,独立仓库管理);README 工具表/目录结构与 agent.md 登记子模块用法 2026-09-30 11:44:52 +08:00
hulk be32efa806 docs(agent): 记录 DLPilot v0.4.2 已发布(tag 指向 8fde79c) 2026-09-28 18:53:27 +08:00
hulk 8fde79c071 fix: v0.4.2 串口日志清空按钮并入标题行对齐;恢复光机命令快捷按钮排(开/关光机等7个, v0.4.0 重写时丢失);重打包 2026-09-28 18:51:48 +08:00
hulk b4328b8be6 docs(agent): 记录 DLPilot v0.4.1 已发布(tag 指向 4149d20) 2026-09-28 15:26:49 +08:00
hulk 4149d203b0 fix: v0.4.1 修复主题切换丢 swatch 底色与连接失败长错误串撑爆布局;新增 selftest_theme;重打包 2026-09-28 15:20:11 +08:00
hulk 264a0c74a6 docs(readme): 工具一览表增加各工具图标列;更新日期戳 2026-09-28 11:00:18 +08:00
hulk 190cf29aa5 chore: 仓库更名 LT8619C_Debug_Tools → HW-Debug-Tools
- Gitea 仓库已改名(旧地址自动重定向),git remote 同步更新
2026-09-28 10:01:16 +08:00
hulk d658fd459a feat: 图标改为家族版式绿色款(同 FlashTool 色系)并重打包
- 黑底/绿色圆角框 rgb(0,200,120)/框内黑字 Serial + 白字 Mate, 与 DLPilot/EDID-Viewer/FlashTool 同版式
2026-09-28 09:37:54 +08:00
hulk b627f79dad docs(agent): 记录 SerialMate v0.1.0 已推送并发布 Release 2026-09-27 18:58:44 +08:00
hulk c26d2cdbaa feat: 新增 SerialMate 串口调试助手 v0.1.0
- 协议帧构成令牌序列可定制(包头/板ID/LEN口径/5种CRC x 3种覆盖), 默认兼容 DLPilot 光机协议
2026-09-27 18:52:54 +08:00
hulk 372cb6b7a0 docs: 关闭 0x606E 0x40/0x80 位交换实测待办(用户确认现状符合预期);M305 自测向量降为低优先 2026-09-25 02:12:25 +08:00
hulk 68fb81fb13 docs(agent): 记录画面镜像新需求 —— DLPC3421 14h 原生支持横/纵独立翻转,含 39h 命名陷阱警示 2026-09-25 02:08:44 +08:00
hulk 733847a58c docs: agent 文档体系按用户级默认工作约定重整为开发需求与进度管理 2026-09-25 01:48:18 +08:00
hulk f594f60fdd docs(I2C-Inject): 标记暂停开发 —— 代码与固件保留备查,根 README 同步状态 2026-09-25 01:41:43 +08:00
hulk e92fa9f349 docs: 根 README 补充 EDID-Viewer(工具一览/环境/目录/发布流程) 2026-09-25 01:40:17 +08:00
hulk fe4bca5a33 feat(EDID-Viewer): v0.1.0 入库 — Fluent EDID 查看器,目录对齐 DLPilot
- src/ 人写代码:main.py(Fluent 界面、Light/Dark/dark1/dark2/跟随系统主题、
  关于按钮;主题三件套 = setTheme + QPalette/应用级 QSS + DWM 标题栏,
  修复 Light 下窗口背景/页签/标题栏仍为系统深色的问题)、edid.py
  (EDID/CTA/HDMI/HDR 解析)、windows_edid.py(WMI 只读)、theme.py、
  test_edid.py(9 项解析测试,含随机畸形数据无崩溃检查)
- assets/ 图标与生成脚本;release/ 交付:EDID-Viewer.exe(onefile 63.7MB,
  启动/图标/主题已验证)+ README,与 DLPilot/release 同约定 exe 直接入库
- 流水线对齐 DLPilot:src/build_exe.py(spec 由脚本生成不入库,剔除 PATH 上
  Poppler/Conda 版本化 ICU,避免 QtCore 报 WinError 127)→
  package_release.py(组装 EDID-Viewer-v*-win64.zip,zip 只上传 Gitea)→
  publish_gitea.py(token 走 GITEA_TOKEN,自签证书 --insecure)
- agent.md 更名 AGENTS.md(DLPilot 双文档约定:README 给人 / AGENTS.md 给
  Agent);根 .gitignore 增加 EDID-viewer/release/*.zip
- validation/ 保留 EDID 本机/合成样本与窗口截图、关于对话框自检脚本
2026-09-24 22:34:02 +08:00
hulk b58cdc42b6 feat(DLPilot): v0.4.0 — PySide6-Fluent-Widgets UI and Light theme 2026-09-24 19:09:24 +08:00
hulk 21c1b7bcc1 落盘agent.md文件 2026-09-20 00:26:02 +08:00
hulk 144730fb3a fix(DLPilot): 二进制载荷日志行以 hex 展示 —— 修复复制被 NUL 截断 2026-09-18 15:32:34 +08:00
hulk ca898be299 chore(DLPilot): v0.3.6 打包(M305 功率检测三步序列 + 功率 W 两位小数显示) 2026-09-18 15:16:42 +08:00
hulk 511e7dfa44 feat(DLPilot): M305 实测负载功率对接(功率检测三步序列) 2026-09-18 15:10:14 +08:00
hulk 6d1e2c6f8d feat(DLPilot): v0.3.5 — 电源读数框等长自适应 + 最大化卡顿治理 2026-09-18 01:23:45 +08:00
hulk a0d64c322a fix(DLPilot): 修复电源自检卡死 —— 帧路由引用未定义变量 payload 2026-09-18 01:17:08 +08:00
hulk a666ed7c43 fix(DLPilot): 单实例锁 + 串口占用提示 —— 修复'断不开'的实际根源 2026-09-18 01:13:05 +08:00
hulk 1f68665860 fix(DLPilot): 串口卡死与序列互相干扰修复 2026-09-18 01:08:51 +08:00
hulk 668a7e1ca5 feat(DLPilot): 功率检测读数暂不计算功率值(待固件功率命令返回), 占位显示 2026-09-18 01:04:27 +08:00
hulk bf9d70722c feat(DLPilot): 电源自检补全 FPDO 挡位判定; 功率检测实现 2026-09-18 00:58:42 +08:00
hulk 5d06e69a41 feat(DLPilot): M303/M304 SQ52205 电源实测协议对接(规则先行, 按钮后续排版) 2026-09-18 00:41:09 +08:00
hulk a3430d15e0 fix(DLPilot): 电源自检误把成功帧判为错误(实机 M301 回包 payload='PD' 无 ok 前缀, 改按 TYPE 译码分类) 2026-09-17 11:16:11 +08:00
hulk 419c902a38 chore: gitignore 源码模式运行时配置 src/pattern_slots.json 2026-09-17 10:46:09 +08:00
hulk b1bb320b50 feat(DLPilot): 新增电源检查卡(PD 自检序列 M301/M302 状态位 + FPDO, 功率检测占位); 窗口加高; 版本 0.3.4 打包 2026-09-17 10:43:31 +08:00
hulk 2d1d8f83b1 chore(DLPilot): v0.3.3 打包(修复 USB 拔出后重连失效) 2026-09-17 10:17:56 +08:00
hulk d991d57447 fix(DLPilot): 串口设备拔出后同参数重连无响应(掉线分支同步清 _open_key); 版本 0.3.3 2026-09-17 10:17:52 +08:00
hulk 43d78de045 chore: 移除临时诊断脚本 2026-09-14 15:44:27 +08:00
hulk 739fdeedf3 chore(DLPilot): v0.3.2 打包(exe 含标题栏版本号, 停止测试图像更名) 2026-09-14 15:44:04 +08:00
hulk b7eda91ca7 feat(DLPilot): 标题栏显示版本号(与关于弹窗同源 APP_VERSION) 2026-09-14 15:37:10 +08:00
hulk 763d80534c feat(DLPilot): '停止投屏'更名'停止测试图像'; 版本 0.3.2; 清理残余 HDMI-Tool 引用 2026-09-14 15:30:58 +08:00
hulk 31fcd93607 chore: 文件夹更名 HDMI-Tool -> DLPilot(路径与文档此前已对齐) 2026-09-14 15:25:05 +08:00
hulk df6a5f4343 fix(DLPilot): publish_gitea 请求自动重试(实例 TLS 间歇性 SSL EOF) 2026-09-14 15:12:16 +08:00
hulk 32d0d26c5a feat(DLPilot): '恢复桌面'更名'停止投屏'; 版本 0.3.1 2026-09-14 15:02:54 +08:00
hulk afb6513e56 fix(DLPilot): 投屏退出体验 — 替换语义 + 一键恢复桌面 2026-09-14 14:55:30 +08:00
hulk 584fd32ebe merge: DLPilot v0.3.0 — CustomTkinter 双栏界面重构 + 光机串口参数化 + TEC 控制 2026-09-12 03:45:46 +08:00
hulk b12bc584b8 feat(DLPilot): 图标更新为 DLP/Pilot 双行设计; 图案栏位两排各 5 个等宽 2026-09-12 03:28:52 +08:00
hulk 13dab778c6 style(DLPilot): 关于弹窗补作者/硬件正式命名; 卡片标题行垂直居中 2026-09-12 03:21:20 +08:00
hulk 607767ce19 feat(DLPilot): 关于按钮 + 外观默认 System + 校准图案行压缩 2026-09-12 03:15:07 +08:00
hulk 210e901ede feat: 产品更名 DLPilot(3D 光固化光机调试台) + 按标记调整界面 2026-09-12 03:05:32 +08:00
hulk 9a70efc6de fix(HDMI-Tool): 下拉菜单配色统一为深色主题 2026-09-12 02:36:46 +08:00
hulk 19afeed294 style(HDMI-Tool): 按用户标记统一左列高度与温度实时显示 2026-09-12 02:19:51 +08:00
hulk cca7cbc962 feat(HDMI-Tool): 光机串口参数可选(默认8-N-1) + TEC 控制与温度读取 2026-09-12 02:07:26 +08:00
hulk aff31656ed style(HDMI-Tool): 串口下拉贯通卡片宽度; 参数行补全 8-N-1(板卡固件固定标注) 2026-09-12 01:50:15 +08:00
hulk bb8efa7392 style(HDMI-Tool): 按用户标记微调 CTk 界面 2026-09-12 01:42:01 +08:00
hulk 7051aa1774 feat(HDMI-Tool): CustomTkinter 双栏仪表盘界面重构(feature/ctk-ui) 2026-09-12 01:30:50 +08:00
hulk 222d452f63 feat(HDMI-Tool): 光机串口下拉显示设备描述, CH344 多路口可辨 2026-09-11 00:46:03 +08:00
hulk 0a7b1f576a chore(HDMI-Tool): package_release 平铺复制图案/说明到 release/ — 与 zip 内容一致, 文件夹开箱即用 2026-09-11 00:40:48 +08:00
hulk 4520ca970d fix(HDMI-Tool): 启动拓扑改智能判定 — 仅转接板(XLS)未激活时强制扩展, 家里仅第二屏零打扰 2026-09-11 00:37:48 +08:00
hulk cdef23b80a feat(HDMI-Tool): v0.2.0 集成光机控制(RS485→GD32网关→DLPC3421) — 本地提交, 待验证后再推送发布 2026-09-11 00:25:28 +08:00
hulk 0ca7ea8675 docs(HDMI-Tool): AGENTS.md 记录本机已持久化 GITEA_TOKEN 用户级环境变量 2026-09-10 23:55:10 +08:00
hulk a39a4a665a fix(HDMI-Tool): publish_gitea 兼容 assets 纯数组返回; 文档补记本实例需 --insecure 2026-09-10 23:51:39 +08:00
hulk 7ab8264752 refactor(HDMI-Tool): 划分 src/assets/release 三区目录, 补齐人读/AI 读双文档与发布流水线 2026-09-10 23:44:56 +08:00
hulk 1f7e697558 feat: HDMI-Tool 启动时强制扩展显示拓扑 + 收录波形/注入脚本 2026-09-10 19:47:39 +08:00
hulk 65c85c2844 feat(I2C-Inject): 归档 RP2040 固件到 mcu-rp2040 并补齐说明 2026-09-03 17:33:17 +08:00
hulk c38f12b230 feat: HDMI-Tool 与 I2C-Inject 首版工具集 2026-09-03 17:24:33 +08:00
22 changed files with 544 additions and 27 deletions
+5 -1
View File
@@ -2,11 +2,15 @@
__pycache__/
*.pyc
# PyInstaller 工作目录(打包产物 exe 已直接入库, 构建中间物不入库)
# PyInstaller 工作目录(构建中间物不入库)
build/
dist/
*.spec
# exe 一律不入库(2026-10-13 起): 交付物只走 Gitea Release 附件, 本地保留。
# 历史 39 个 exe blob 已用 git filter-repo 清除(仓库 1.1 GiB -> ~1 MB (pack 实测))
*.exe
# 发布 zip: 可由 src/package_release.py 重新生成, 只上传 Gitea Release
DLPilot/release/*.zip
EDID-viewer/release/*.zip
+13 -2
View File
@@ -145,8 +145,9 @@ python publish_gitea.py ../release/DLPilot-v<版本>-win64.zip --replace --insec
发布约定:
- 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 已挡);
- **pattern_slots.json 与 release/ 下平铺的图案 png 改动跟随源码/资产生成提交入库;
exe 不入库**(2026-10-13 起全仓 `.gitignore` 挡 `*.exe`,交付物只走 Gitea
Release 附件,本地保留);**zip 永不入库**(.gitignore 已挡);
- publish_gitea.py 幂等:release 已存在则复用,同名资产默认跳过,`--replace` 删旧重传;
- token 读环境变量 `GITEA_TOKEN`:本机已用 setx 持久化为用户级变量(新开的会话/终端自动
继承,值不入库;在 setx 之前启动的进程读不到,需重开终端),急用时也可临时传 `--token`;
@@ -255,3 +256,13 @@ python publish_gitea.py ../release/DLPilot-v<版本>-win64.zip --replace --insec
为预置 COM15 配置,本机 COM5 运行态已还原未入库)。遗留(未随本版处理):
`dlpc_rs485.py` 的 `except OSError` 把写超时(SerialTimeoutException)与设备
拔出混判,一次转换器停滞即断链误报"设备拔出"。
- 2026-10-14 新增面向二供的独立使用手册 `使用说明.md` + `使用说明.pdf`(基于
README 与 v0.4.3 Release 编写,从解压安装包写起的操作级文档,含命令参考/典型
流程/FAQ/版本沿革;不随发布 zip 分发,单独发给供应商)。PDF 由 md 生成:
python-markdown → Chrome headless 矢量打印 → pymupdf 回填目录页码/页脚/元数据,
两遍编译(第一遍定位各章节页码,第二遍回填目录),构建脚本为一次性临时产物
未入库;后续改 md 后需按同流程重出 PDF。文档拓扑表述已按用户勘误校准:
HDMI 与 RS485 接同一块转接板,GD32E230 是板上主控 MCU(逻辑控制),无独立
"GD32 网关"说法(README/根 README/本文其他处旧措辞待同步)。§3 界面总览含
标注版主界面截图(`manual-img/ui-overview-quickstart.png`,手册配图目录)与
四条快速开始要点;已记录"转接板上电默认开光机"新事实(§3/§7.1)。现 11 页。
+1 -1
View File
@@ -218,7 +218,7 @@ DLPilot/
│ ├── bw_*.png ×5 # 640x360 黑白系列
│ └── solid_*.png ×10 # 800x600 纯色系列
├── release/ # 构建与发布产物(机器生成区, 不手改)
│ ├── DLPilot.exe # 打包单文件版(改动跟随源码提交入库)
│ ├── DLPilot.exe # 打包单文件版(不入库,本地保留;随发布上传 Gitea Release)
│ ├── pattern_slots.json # exe 运行配置(栏位预置 + 串口记忆)
│ ├── *.png / README.md # 附属文件平铺副本(由 package_release.py 从 assets/ 同步)
│ └── *.zip # 发布包(不入库, 上传 Gitea Release)
Binary file not shown.

After

Width:  |  Height:  |  Size: 247 KiB

Binary file not shown.
+393
View File
@@ -0,0 +1,393 @@
# DLPilot 使用说明
**HDMI 源端调试 + 光机控制工具**
| 项目 | 说明 |
|---|---|
| 适用版本 | v0.4.3(2026-10-13 发布) |
| 适用系统 | Windows 10 / 11 x64,免安装、无需 Python |
| 适用对象 | LT8619C(HDMI→RGB888)→ DLPC3421 投影转接板的调试、测试与校准人员 |
| 文档日期 | 2026-10-14 |
DLPilot 是配套投影转接板调试的 PC 端工具,一台电脑同时完成两件事:
- **HDMI 源端**:查看板卡上报的 EDID、切换输出分辨率、向板卡全屏投放测试图案
(纯色、黑白测试图、自定义校准图);
- **光机控制**:通过 USB-RS485 控制光机——开关光机、设光强、查温度/电流、
PD 电源自检与功率读数、TEC 温控。
界面上左右两列分别对应这两个功能域,互不干扰,可以只用其中一列。
---
[TOC]
---
## 1. 安装(从压缩包开始)
### 1.1 拿到安装包
安装包为 `DLPilot-v0.4.3-win64.zip`(约 67 MB),由我方对接工程师提供。
收到后请先核对文件名中的版本号,本文档对应 **v0.4.3**;若版本更新,以随包说明为准。
### 1.2 解压
1. 在电脑上选择一个**可写**的本地目录,例如 `D:\Tools\`(不要解压到只读目录、
网络共享盘或需要管理员权限才能写入的系统目录,原因见 1.5 节);
2. 右键压缩包 →「全部解压」→ 目标路径填 `D:\Tools\`,确认后完成解压;
3. 解压后得到一个 `DLPilot` 文件夹。
> **注意:不要在压缩包预览窗口里直接双击运行 exe。**
> 直接从压缩包内运行时程序被解压到临时目录,你配置的自定义图片和串口参数
> 会写到临时目录并随其清空而丢失。务必先完整解压,再运行解压后的 exe。
解压后的文件夹内容如下:
| 文件 | 作用 |
|---|---|
| `DLPilot.exe` | 主程序,双击运行(单文件自包含,光机控制所需串口库已内置) |
| `pattern_slots.json` | 运行配置:自定义图案栏位、测试卡区域、串口参数记忆。**删除它会丢失你的全部本地配置** |
| `bw_*.png`(5 张) | 640×360 黑白测试图:西门子星、频率扫描条纹、渐变棋盘、波带片、综合测试卡 |
| `solid_*.png`(10 张) | 800×600 纯色测试图(R/G/B 各 55/AA/FF + 三原色),供自定义栏位加载 |
| `CeramixNano-*.png`(如包含) | 光机校准图案(black / white / contrast / circle_640p / caliPoint / sharpness),新版本安装包已预置到自定义栏位 |
| `README.md` | 随包说明(与本文档内容同源) |
### 1.3 首次启动
双击 `DLPilot.exe`:
- 首次启动比之后慢一两秒(单文件程序需要先自解压),属正常现象;
- 程序没有数字签名,首次运行 Windows SmartScreen 可能弹出
「Windows 已保护你的电脑」——点「更多信息」→「仍要运行」即可;
- 个别杀毒软件可能对加壳的单文件 exe 误报,如遇拦截请放行或将安装目录加入白名单。
程序启动后出现双栏主界面(见第 3 节),即安装成功。
### 1.4 升级新版本
1. 关闭正在运行的 DLPilot;
2. 解压新版本压缩包到**新的空目录**(不要直接覆盖旧目录,避免新旧文件混杂);
3. 如需保留旧版的自定义栏位与串口记忆:把旧目录里的 `pattern_slots.json`
和你自己添加的图片文件复制到新目录,覆盖同名文件即可;
4. 双击新目录的 `DLPilot.exe`。
### 1.5 为什么必须放在可写目录
程序的所有本地数据(`pattern_slots.json` 配置、你添加的自定义图片)都保存在
**exe 所在目录**,不写注册表、不写用户目录。放在只读目录会导致配置保存失败。
两份不同目录的安装(比如两台工位电脑、或同一台电脑解压了两份)各自独立保存配置,互不影响。
## 2. 硬件连接
### 2.1 整体链路
```
PC(DLPilot) ──HDMI──→ LT8619C(HDMI→RGB888)──RGB888 视频──→ DLPC3421 光机
PC(DLPilot) ──USB-RS485──→ GD32E230 主控 ───I2C 控制(0x1B)──→ DLPC3421 光机
```
HDMI 与 RS485 接的是**同一块转接板**:LT8619C 负责把 HDMI 视频转换为 RGB888;
GD32E230 是板上的主控 MCU,负责整板逻辑控制——DLPilot 的 RS485 命令由它解析,
再经 I2C 总线控制光机(DLPC3421)。
### 2.2 HDMI 连接
1. 用 HDMI 线把电脑显卡输出接到转接板 HDMI 输入;
2. 板卡正常上电。板卡 shadow EDID 只声明 640×360@60 一种模式;
3. 如果 Windows 没有自动点亮这块"显示器"(显示设置里看不到):
启动 DLPilot,工具检测到是本系列板卡(EDID 厂商签名)接入但未进桌面时,
会自动把它以扩展屏方式拉回桌面;仍不行时在 Windows「显示设置」里手动改为「扩展这些显示器」。
### 2.3 RS485 连接(光机控制)
1. USB-RS485 转换器接电脑 USB,其 A/B 端子对应接转接板的 RS485 A/B 端子;
2. 串口参数固定 **115200 波特率、8 数据位、无校验、1 停止位(115200 8N1)**,
软件默认值即为此,一般无需修改;
3. 板卡供电建议使用满足 **PD 12V / ≥3A** 的电源适配器——软件的"电源自检"
就是以该挡位为正常判据(见 5.3 节)。
### 2.4 上电时序(重要)
DLPC3421 光机芯片启动需要几秒钟。**上电后立即发开光机/设光强/查电流命令会收到
拒绝应答(0xFF),这是正常保护,不是故障**——稍等几秒待光机就绪后再发。
## 3. 界面总览
主窗口为双栏仪表盘,顶栏可切换 Dark / Light / System 外观(跟随系统为默认),
顶栏右侧「关于」按钮内有软件版本信息:
| 左列(HDMI 源端) | 右列(光机控制 RS485) |
|---|---|
| 显示器选择:显示器下拉 + 刷新 | 串口选择:串口下拉 + 波特率等参数 + 连接 |
| 支持的模式(默认折叠):分辨率下拉 + 应用 / 恢复 + 时序明细 | 电源检查:电源自检 + 功率检测 |
| EDID 信息(默认折叠):解算结果一览 | 串口数据:收发日志(译码 + hex)+ 清空 |
| 测试图案:内置图案 / R·G·B 色值 / 自定义与校准栏位 / 测试卡区域选择 | 光机命令:快捷按钮排 + 预设下拉 + 自定义输入 + 温度读取 |
| EDID 原始数据:hex 显示 + 逐字节解析 | 快捷滑条:光强 / 定时 / TEC 温度 |
![DLPilot 主界面(红框标注为快速开始要点)](manual-img/ui-overview-quickstart.png)
*图 1 主界面与快速开始要点*
红框与编号对应四个上手要点:
1. **选显示器**:左上「显示器选择」卡的下拉框选中接转接板的显示器
(Generic PnP Monitor),下方会显示当前实际输出分辨率/刷新率;
多屏或热插拔后点「刷新」重新枚举;
2. **投测试图案**:现在的转接板**上电默认打开光机**,无需先连串口——
在「测试图案」卡选好测试卡区域后即可直接投放指定图案
(点「停止」按钮或按 ESC 退出全屏);
3. **连串口**:需要控制光机光强、查温度/电流等才需要串口——USB-RS485
转换器接好后,在「串口」卡选口(参数保持默认 115200 8N1)点「连接」;
4. **控光机**:常用光机控制都集中在「光机命令」卡(开/关光机、查版本、
软件重启、TEC、温度读取、预设下拉与自定义输入),下方「快捷滑条」
可便捷调光强、定时投光、TEC 温度。
「支持的模式」「EDID 信息」两张卡片默认折叠,点卡片标题展开。
左列只操作显卡输出(不碰光机),右列只操作光机(不碰显卡)。
## 4. HDMI 源端操作(左列)
### 4.1 选择显示器
1. 左上下拉框列出当前所有显示器,选中**接转接板的那一块**;
多屏时注意核对型号/分辨率,不要选成你的主屏;
2. 热插拔后列表没刷新时点「刷新」重新枚举;
3. 下拉框内容与系统识别一致;如对序号有疑问,可在 Windows「显示设置」中
点「识别」核对。
### 4.2 查看支持的模式 / 切换分辨率
1. 展开「支持的模式」卡片,下拉框列出显卡按该屏 EDID 提供的全部模式
(板卡正常时可见 640×360@60);
2. 选中模式后点「应用」即切换。**切换是临时的**:不写注册表,重启电脑或
重新插拔即还原,不会永久改动你的桌面设置;
3. 测试完成后点「恢复」,回到本次打开软件时的原始模式;
4. 卡片同时显示选中模式的时序明细,可核对像素时钟、刷新率等。
### 4.3 查看 EDID
- 「EDID 信息」卡片:显示从该显示器读到的 EDID 解算结果——厂商、型号、
尺寸、Gamma、输入类型、支持的全部模式、首选时序完整参数、校验和;
- 「EDID 原始数据」卡片:显示 128 字节(含扩展块)原始 hex;
点右上「逐字节解析」按钮,可按偏移逐字段展开基础块与 CTA-861 扩展块,
每个字段附原始字节,适合核对板卡 EDID 是否按规格上报。
### 4.4 投放测试图案
1. 先在「测试卡区域」选择投放区域:
- `640x360`(默认)——与光机面板原生分辨率 1:1,**链路验证/校准用这个**;
- `800x600`——对应 demo 板首选时序;
- `full`——铺满所选显示器的整个屏幕;
2. 点「测试图案」卡片中的按钮即全屏投放到所选显示器:
- 内置图案:纯红、纯绿、纯蓝、黑白棋盘格、网格线(程序直接绘制);
- R/G/B 三行 `55 / AA / FF` 色值按钮:按通道着色的纯色,用途见 7.2 节;
- 自定义/校准图片栏位:见 4.5 节;
3. 投放新图案会自动替换当前旧图案;按 **ESC** 键或点「停止测试图像」退出全屏。
### 4.5 自定义图片栏位(含校准图案)
「测试图案」卡片提供 **10 个可配置栏位**,每个栏位一个图案按钮 + 一个齿轮按钮:
1. 点某个栏位的**齿轮**按钮,弹出配置对话框;
2. 填写栏位名称(显示在按钮上),选择图片文件(推荐 PNG;JPG/BMP/WebP
依运行环境而定,PNG 最稳妥);
3. 保存后图片自动**复制到 exe 所在目录**,栏位按钮即可点按投放。
因此不要事后手动移动/删除 exe 旁的图片文件,否则栏位失效;
4. 安装包已预置常用栏位(黑白测试图与校准图案,具体以包内为准),
可按上述步骤改成你自己的图。
栏位配置、测试卡区域选择会自动保存在 exe 旁的 `pattern_slots.json`。
## 5. 光机控制操作(右列)
### 5.1 连接串口
1. 「串口选择」卡片:下拉框列出所有串口,显示为 `COMx + 设备描述`。
多路 USB 转换器(如 CH344 四路)每一路描述不同(serial-A/B/C/D),
据此选口;描述相同时软件自动附物理位置区分;
2. 波特率等参数默认 115200 8N1,与板卡固件约定一致,保持默认即可;
3. 点「连接」。连接失败会给出简短原因(串口被占用/不存在等),
完整错误信息进收发日志;
4. 上次使用的串口与参数会被记住,下次启动自动带出(预置配置带的串口如与
你现场不符,第一次使用时改成你的实际串口即可)。
### 5.2 收发日志
「串口数据 · 收发日志」卡片实时显示:
- `→` 发出的命令;
- `←` 收到的应答:**可读译码 + 原始 hex** 对照显示;
- 错误自动附释义,例如 `err:3(I2C NACK)` 表示光机侧 I2C 无应答;
- 点「清空」清屏。日志超过 500 行自动滚动淘汰旧条目,长时间联机不会卡顿。
协议帧格式(判读 hex 时参考):命令帧 `D5 01 LEN <ASCII命令> CRC`,
应答帧 `B5 TYPE LEN <payload> CRC`,CRC 为自第 2 字节起的累加和低 8 位。
### 5.3 电源检查
「电源检查」卡片有两个按钮:
- **电源自检**:自动依次查询供电协议(M301)→ PD 挡位最大电流(M302)→
实测母线电压(M303),并按实测电压就近判定 PD 固定挡(5/9/12/15/20/28V):
| 显示 | 含义 |
|---|---|
| 绿底,如 `FPDO: 12V@3A` | 供电正常:12V 挡且电流 ≥3A |
| 红底,如 `FPDO: 9V@3A` | 挡位不符:电源没有协商到 12V 挡,请换符合要求的 PD 电源 |
| `ERR` | 实测电压不落在任何标准 PD 挡内,检查供电 |
说明:取电芯片的电压配置寄存器只写不可读,挡位只能靠实测电压判定,
所以以自检结果为准,而不是电源标称。
- **功率检测**:自动依次读母线电压(M303)/ 负载电流(M304)/ 负载功率(M305),
读数框显示 电压(V)、电流(mA)、功率(W)。功率量程 0~295 W。
### 5.4 光机命令
「光机命令」卡片从上到下:
1. **快捷按钮排**(最常用操作一键完成):
`开光机`、`关光机`、`查版本`、`软件重启`、`开TEC`、`关TEC`、`TEC33.0°C`;
2. **温度读取**:`查DMD温度`、`查LAMP温度`,应答数值(0.1°C 单位换算后)
实时填入按钮旁的显示框;
3. **预设下拉**:常用命令清单,选中即发送;
4. **自定义输入框**:手动输入任意命令(见第 6 节命令表),**回车即发送**。
### 5.5 快捷滑条
「快捷滑条」卡片三个滑条,拖到目标值后点对应按钮下发:
- **光强**:拖动后点「下发电流值」(有效范围 54–800,RGB 三路同值);
- **定时**:设定毫秒数后点「开光机(定时)」——开光机并在到时后自动关,
0 表示不限时;上限 32700 ms;
- **TEC 温度**:滑条/输入框设定凝露点 200–350(对应 20.0–35.0°C),
点「下发温度值」。
滑条旁的数值输入框支持直接键入,回车后自动限制到有效范围并与滑条同步。
## 6. 光机命令参考
| 命令 | 功能 | 应答示例 / 说明 |
|---|---|---|
| `M1` | 协议握手 | `ok` |
| `M730S0` / `M730S1` | 开 / 关光机 | `ok` |
| `M730S0T2000` | 开光机并定时 2000ms 自动关 | `ok`;定时 ≤32700 ms |
| `M731S100` | 设光强(54–800,RGB 同值) | `ok`;失败回 `err:R..G..B..` |
| `M732` | 查三路电流设置值 | `okR110G110B110` |
| `M737` | 查投光是否结束 | 投光进行中会**延迟应答**,属正常 |
| `M201` / `M202` | 查 DMD / LAMP 温度 | `okTL:246` = 24.6°C |
| `M7S0` / `M7S1` | TEC 自动控温 **开** / 关 | 注意 **S0 是开**,方向与直觉相反 |
| `M8S330` | TEC 凝露点 33.0°C | 范围 200–350,超范围回 `err:OL` |
| `M301` | 查供电协议(PD/QC3.0/EPR…) | ASCII 文本 |
| `M302` | 查 PD 挡位最大电流 | mA(50mA/LSB 已换算) |
| `M303` | 查母线电压(实测) | 如 12020 mV = 12.02 V |
| `M304` | 查负载电流(实测) | mA,带符号(正=正向) |
| `M305` | 查负载功率(实测) | mW,软件换算显示为 W |
| `M999` | 查固件版本 | 如 `okv20.0.0.1` |
| `M888` | 软件重启 | `ok` 后约 100ms 复位 |
> **注意:**
>
> 1. 光机上电后几秒内处于启动期,此时 `M730/M731/M732` 会被就绪门禁拒绝(回 0xFF),
> 等几秒再发即可;
> 2. USB-RS485 转换器是半双工的:本机发送期间板上回包不会回环显示,属正常现象;
> 3. 设光强等带数值的命令,超范围值会被板卡拒绝,请按表中范围下发。
## 7. 典型操作流程
### 7.1 首次整链路验证(新板卡点灯)
```
1. HDMI 接转接板,USB-RS485 接板卡 A/B,板卡上电(PD 12V/≥3A),等数秒
2. 启动 DLPilot → 「刷新」→ 显示器下拉选中板卡(640x360@60)
3. 光机控制:选串口 → 连接 → 点「查版本」(M999)
应答 okv... 即 RS485→光机 链路通;无应答见第 9 节排查
4. 点「电源自检」:绿底 FPDO: 12V@3A 即供电合格
5. 测试卡区域选 640x360(与光机面板原生 1:1);转接板目前上电默认开光机,
可直接投图,若光机已被关闭再点「开光机」
6. 投放测试图案目视检查 → 设光强/查温度电流(按需)
7. 测完:「关光机」→ 分辨率「恢复」→ 停止测试图像
```
### 7.2 RGB 通道与位序检查
用「测试图案」里的 R/G/B 行色值按钮(`55 / AA / FF` 三档):
1. **纯红/纯绿/纯蓝**:验证 RGB 三通道映射是否正确
(硬件约定 R=D[23:16]、G=D[15:8]、B=D[7:0],投纯红时仅 R 通道应有输出);
2. **55 与 AA 配对**:`0x55`(01010101)与 `0xAA`(10101010)互为字节镜像,
专用于检出位序颠倒——位交换设置(0x606E)正确时图像应为 50% 灰阶占空比;
3. **FF**:全高基准,配合电流读数核对满幅输出。
### 7.3 校准图案投放
1. 「测试卡区域」选 `640x360`(校准图按光机原生分辨率制作);
2. 安装包已预置校准栏位(black / white / contrast / circle_640p / caliPoint /
sharpness,以包内为准);如需换用自己的校准图,按 4.5 节齿轮按钮配置;
3. 依次点栏位按钮投放,按校准规程判读(新图案自动替换旧图案,无需先停止);
4. 完成后 ESC 退出。
## 8. 数据判读速查
| 现象/读数 | 判读 |
|---|---|
| 开机后发命令回 `0xFF` | 光机启动中,就绪门禁拒绝,等几秒重发 |
| 日志出现 `err:3(I2C NACK)` | 光机侧 I2C 无应答:光机未上电/未就绪,或板卡故障 |
| 温度应答 `okTL:246` | 24.6°C(0.1°C 单位) |
| 电流应答 `okR110G110B110` | R/G/B 三路电流设置值均为 110 |
| 电源自检红底 `FPDO: 9V@3A` | PD 只协商到 9V 挡,未到 12V,更换/检查电源与线材 |
| 定时投光中 M737 无立即应答 | 正常:投光结束才应答,勿反复重发 |
## 9. 常见问题(FAQ)
**Q1:双击 exe 没反应 / 被 Windows 拦截。**
SmartScreen 弹窗点「更多信息」→「仍要运行」;杀毒软件误报时放行或加白名单;
仍不行则确认解压完整(exe 约 67 MB)。
**Q2:光机命令发出去没反应。**
按顺序排查:① 串口选对没有(115200 8N1)、A/B 线接对没有;② 先点「查版本」
(M999)验证链路,M999 都不通就是串口/接线问题;③ M999 通但开光机回 0xFF——
光机启动中,等几秒重试;④ 半双工转换器发送期间看不到回环是正常的。
**Q3:显示器下拉里找不到板卡。**
检查 HDMI 线与板卡供电;点「刷新」;启动 DLPilot 会自动把本系列板卡拉回扩展桌面,
仍不行到 Windows 显示设置手动改「扩展这些显示器」,然后回软件刷新。
**Q4:切了分辨率,桌面布局乱了。**
软件的切换是临时的:点「恢复」立即还原;重启电脑或重插 HDMI 也会还原。
不会永久改动系统设置。
**Q5:自定义栏位点了没图。**
该栏位未配置图片(点齿轮配置);或 exe 旁的图片文件被移动/删除——重新配置一次,
图片会重新复制到 exe 旁。
**Q6:串口下拉里好几个 COM 口,选哪个?**
下拉项带设备描述(如 USB-SERIAL CH340 / serial-A~D),选你的 USB-RS485
转换器对应的口;描述相同的会附物理位置。拿不准就拔插一次看哪个口出现/消失。
**Q7:两台电脑/两个目录各解压了一份,配置会串吗?**
不会。配置保存在各自 exe 旁的 `pattern_slots.json`,互相独立。
**Q8:软件用久了变卡。**
v0.4.2 及更早版本存在长会话卡顿问题,v0.4.3 已修复;请确认用的是 v0.4.3
(顶栏「关于」可查版本),旧版本请升级。
**Q9:换电脑要带走哪些东西?**
整个安装目录打包即可;至少要 `DLPilot.exe` + `pattern_slots.json`(含你的栏位
与串口记忆)+ 你添加的自定义图片。
## 10. 版本沿革
| 版本 | 日期 | 要点 |
|---|---|---|
| v0.4.3(当前) | 2026-10-13 | 修复长会话越用越卡、命令点击无响应的问题(收发日志积压);新增日志回归自检 |
| v0.4.2 | 2026-09-28 | 收发日志「清空」按钮归位;恢复光机快捷按钮排(开/关光机、查版本、TEC 等) |
| v0.4.1 | 2026-09-28 | 修复切换 Light/Dark 主题后色值按钮底色丢失;串口连接失败改为简短提示,不再撑破窗口 |
| v0.4.0 | 2026-09-24 | 界面重写为双栏仪表盘(Fluent 风格),功能基线版本 |
## 附录:技术支持
遇到本文未覆盖的问题,请联系我方对接工程师反馈:
软件版本号(顶栏「关于」)、操作步骤、收发日志截图(含原始 hex),
光机问题请同时提供「查版本」(M999)与温度读数。
+1 -1
View File
@@ -21,7 +21,7 @@ Windows 10/11 显示器 EDID 查看器。使用 **PySide6 / PySide6-Fluent-Widge
- `src/` — 人写代码:界面(main.py)、EDID 解析(edid.py)、Windows 读取(windows_edid.py)、主题(theme.py)、解析测试(test_edid.py)和打包流水线。
- `assets/` — 图标与生成脚本(可再生)。
- `release/` — 交付物:`EDID-Viewer.exe` 入库;发布 zip 只上传 Gitea Release,不入库。
- `release/` — 交付物:`EDID-Viewer.exe` 本地保留不入库;发布 zip 只上传 Gitea Release,不入库。
- `AGENTS.md` — 工程约定与任务边界(改代码前必读);`VALIDATION.md` — 验证记录。
## 环境与构建
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -21,7 +21,7 @@
核1 取时间戳并跑解码状态机(与 GUI 解码同语义) + 核0 USB CDC 命令行。
250MHz/vreg 1.15V。修改引脚/波特/协议时注意 `README.md` §5 与 GUI 同步。
- **pyserial 是唯一第三方运行依赖**(缺失降级提示); GUI/解码全标准库+PySide6。
- **release/ 交付物不入库**(2026-10-13 起, 与 DLPilot/SerialMate 的 exe 入库约定不同):
- **release/ 交付物不入库**(2026-10-13 起全仓统一: `.gitignore` 全局挡 `*.exe`):
exe/UF2/BIN/zip 留本地, 待真机验收正式发布时再走流水线(`.gitignore` 已挡
`I2C-Lab/release/`)。
+1 -1
View File
@@ -129,4 +129,4 @@ copy build\i2c_lab.uf2 ..\release\firmware\
| `src/` | PC 端: main.py(GUI)/i2cdec.py(解码权威)/probelink.py(链路)/waveview.py(波形)/theme.py + 自检/打包/发布脚本 |
| `firmware/` | probe 固件: main.c + bus_watch.pio + CMakeLists + make_uf2.py + pico_sdk_import.cmake |
| `assets/` | 图标(沿用 I2C 橙色母题) |
| `release/` | I2C-Lab.exe(入库) + firmware/i2c_lab.uf2/.bin(入库); zip 不入库 |
| `release/` | I2C-Lab.exe + firmware/i2c_lab.uf2/.bin(交付物本地保留,不入库); zip 不入库 |
+4 -4
View File
@@ -39,18 +39,18 @@ HW-Debug-Tools/
├── DLPilot/
│ ├── src/ # 源码 + 打包/发布脚本 + 图标源
│ ├── assets/ # 生成的测试图案 PNG(gen_*.py 产物)
│ ├── release/ # 打包 exe + 运行配置(入库);发布 zip(不入库)
│ ├── release/ # 交付物(exe/zip 不入库,本地保留;只上传 Gitea Release 附件)
│ ├── README.md # 使用说明
│ └── AGENTS.md # 工程档案
├── EDID-viewer/
│ ├── src/ # 界面/解析/WMI 读取 + 打包/发布脚本
│ ├── assets/ # 图标与生成脚本
│ ├── release/ # EDID-Viewer.exe + README(入库);发布 zip(不入库)
│ ├── release/ # 交付物(exe/zip 不入库,本地保留;只上传 Gitea Release 附件)
│ ├── README.md # 使用说明
│ └── AGENTS.md # 工程档案
├── SerialMate/
│ ├── src/ # 协议/串口线程/曲线控件/GUI + 自检 + 打包/发布脚本
│ ├── release/ # SerialMate.exe + README(入库);发布 zip(不入库)
│ ├── release/ # 交付物(exe/zip 不入库,本地保留;只上传 Gitea Release 附件)
│ ├── README.md # 使用说明
│ └── AGENTS.md # 工程档案
├── I2C-Lab/
@@ -81,7 +81,7 @@ python publish_gitea.py <工具>-v<版本>-win64.zip --insecure # 上传 Gite
## 备注
- 源码与打包产物(exe、pattern_slots.json)均入库;发布 zip 不入库,只上传 Gitea Release
- 源码与运行配置入库;exe/zip 等交付物不入库(本地保留),发布只上传 Gitea Release 附件
- `gd32e230f8_firmware_merge_tool/` 是 git 子模块([独立仓库](https://gitea.hulk.wang/hulk/gd32e230f8_firmware_merge_tool),
代码与发布均在其仓内管理,本仓只锁定指针):
新克隆后需 `git submodule update --init` 拉取内容;
+39 -4
View File
@@ -18,7 +18,7 @@ SerialMate 是其中的**通用串口/RS485 调试助手**:收发 + 协议解
```
SerialMate/
├── src/ 源代码区 —— 只有这里可以手改
├── release/ 产物区 —— SerialMate.exe + README.md(入库),
├── release/ 产物区 —— SerialMate.exe + README.md(exe 不入库本地保留,README 入库),
│ *-win64.zip(gitignore,只上传 Release)
├── assets/ 图标等生成资产(暂无;build_exe.py 已预留 assets/serial-mate.ico)
├── README.md 人类文档
@@ -93,6 +93,14 @@ SerialMate/
5. **解析重同步策略**:前缀令牌逐位对齐(HDR/字面量须匹配、ID 通配),LEN 值经
口径换算为 payload 长度,负值视为伪帧头逐出;CRC 失配丢 1 字节重同步——
通用工具不预设合法 LEN 区间(与 DLPilot 的 LEN 范围预判不同)。
5a. **解析不吞数据(v0.1.2 起的产品语义)**:串口助手是本体、协议解析是附加层。
FrameParser 重同步丢弃的字节累积进 `garbage`,`link.SerialLink._dispatch_rx`
每批 `drain_garbage()` 无条件取走(未接回调也不许在解析器里无限累积),
经 `on_garbage(data, ts)` 上抛;GUI 把它并入 `('raw', ...)` 事件,与透传行
同格式显示。纯文本设备/波特率不符的乱码在解析模式下必须全可见。
例外:只匹配上前缀、还在等后续字节的"半帧"缓冲不算垃圾(可能补全成真帧),
字节流恰好在帧头后截断时会扣留至多一个前缀长度的字节——可接受,勿改成
超时强制吐出(会把慢速真帧撕碎)。改此语义需同步 selftest 8b / loop 3b。
6. **ID 位不校验只透出**:`Frame.code` 原样上抛(布局无 ID 时为 None,GUI 日志
与 selftest 均需兼容 None),TYPE_NAMES 仅用于显示译码(DLPilot 语义)。
7. **BASE_DIR 语义**(config.py):frozen 时 =exe 所在目录,源码运行时 =src/;
@@ -150,9 +158,9 @@ SerialMate/
```powershell
python -m compileall -q . # 全模块可编译
python selftest.py # 协议回归(47 项, 改 protocol.py 后必跑)
python selftest_loop.py # 链路回环(需 pyserial, 改 link.py 后必跑)
python selftest_gui.py # GUI 功能回归(offscreen, 改 main.py 后建议重跑)
python selftest.py # 协议回归(67 项, 改 protocol.py 后必跑)
python selftest_loop.py # 链路回环(21 项, 需 pyserial, 改 link.py 后必跑)
python selftest_gui.py # GUI 功能回归(68 项, offscreen, 改 main.py 后建议重跑)
python main.py --seconds 5 # GUI 冒烟(源码); offscreen: set QT_QPA_PLATFORM=offscreen
python build_exe.py # → ../release/SerialMate.exe(缺 PyInstaller 自动装)
python package_release.py <版本> # → ../release/SerialMate-v<版本>-win64.zip
@@ -196,6 +204,33 @@ tag/release 命名 `SerialMate-vX.Y.Z`,zip 命名
## 7. 进度记录
### v0.1.2(2026-10-16,接收语义修复:解析模式不再吞数据)
背景:用户接 COM25(非 DLPilot 协议设备)开解析模式,接收区一片空白——
`_dispatch_rx` 在解析模式只上抛完整合法帧,不成帧的字节被 FrameParser 静默
丢弃;用户明确产品定位:**首先是基础串口调试工具,自定义协议解析是附加项**,
附加能力不得影响本体功能。
已完成:
- protocol.py:FrameParser 丢弃字节不再销毁——重同步逐出的字节累积进
`garbage`,新增 `drain_garbage()` 取走清空;`clear()` 一并清垃圾;
`feed()` 返回值不变(旧用法零改动)。
- link.py:新增 `on_garbage(data, ts)` 回调(区别于透传模式的 `on_raw`,
语义可分但 GUI 同样并入 raw 事件显示);`_dispatch_rx` 每批 drain 无条件
执行(未接回调也不累积),有字节且接了回调才上抛,ts=同一批到达时刻。
- main.py:接线 `on_garbage → ('raw', ...)`;"解析协议帧(收)"补 tooltip
说明两模式语义;APP_VERSION 0.1.2。
- 例外语义(有意为之):只匹配前缀、等待后续字节的半帧缓冲不算垃圾
(可能补全成真帧);字节流恰在帧头后截断时扣留至多一个前缀长度。
- 自检扩充:selftest 8b(纯文本全透出/噪声+帧+尾字节/坏CRC帧字节全透出/
半帧头扣留后补全成帧)+10 项;selftest_loop 3b(解析模式非帧字节经
on_garbage 透出、回环 TX 帧只算非帧字节)+3 项;selftest_gui 5b
(on_garbage 接线+非帧字节日志行)+2 项;全部通过。
- README 协议解析段同步"解析不吞数据"语义;exe 重建(v0.1.2);
zip/Release 未发布(待用户验收)。
待办 / 计划:无新增,沿用 v0.1.0 待办。
### v0.1.1(2026-10-10,接收路径修复:时间戳失真 + 显示延迟累积)
背景:FilmForge 固件联调(GD32F405 RS485 115200,M2 连续温度上报 2~10 帧/s)
+3 -1
View File
@@ -9,8 +9,10 @@
- **串口收发**:端口自动枚举、波特率 1200~921600、数据位/校验/停止位可选,
参数热切换;半双工 RS485 友好(每周期最多写一帧,留应答间隙)。
- **协议解析**(可关,关=原始透传):
增量字节流定界 + CRC 校验,失败逐字节重同步,噪声自动丢弃;
增量字节流定界 + CRC 校验,失败逐字节重同步;
接收帧 ID 位按 DLPilot 语义译码显示(0xF0=成功、0xFD=参数越界…)。
**解析模式不吞数据**:不成帧的字节(纯文本设备、波特率不符的乱码、
总线噪声)以原始行照常显示,协议解析只是附加层,不影响串口助手本体。
- **帧构成定制**(协议卡,发送/接收共用同一布局,仅包头值分方向):
帧构成用**令牌序列**定义,默认 `HDR ID LEN PAYLOAD CRC`(即 DLPilot 五段式):
Binary file not shown.
+9
View File
@@ -33,6 +33,8 @@ class SerialLink:
"""串口工作线程。回调(后台线程触发, 第二参数 ts=事件发生的 epoch 秒):
on_status(text, ts) 连接状态变化(已连接/断开/失败/设备拔出)
on_frame(fr, ts) 解析模式: 完整 Frame(protocol.Frame); ts=本批字节到达时刻
on_garbage(data, ts) 解析模式: 不成帧的原始 bytes(重同步丢弃字节, 不吞数据);
ts=到达时刻
on_raw(data, ts) 透传模式: 原始接收 bytes; ts=到达时刻
on_tx(label, data, ts) 发送回显: label=payload 字符串(自动包装)/None(HEX直发);
ts=写入串口时刻
@@ -43,6 +45,7 @@ class SerialLink:
def __init__(self, cfg, on_status):
self.on_status = on_status
self.on_frame = None
self.on_garbage = None
self.on_raw = None
self.on_tx = None
self.q = queue.Queue()
@@ -222,5 +225,11 @@ class SerialLink:
for fr in self.parser.feed(data):
if self.on_frame is not None:
self.on_frame(fr, ts)
# 不成帧的字节也透出: 串口助手是本体、协议解析是附加层, 解析不能
# 让收到的字节凭空消失(纯文本设备/波特率不符的乱码全在这里可见)。
# drain 必须无条件执行, 未接回调时也不能在解析器里无限累积。
junk = self.parser.drain_garbage()
if junk and self.on_garbage is not None:
self.on_garbage(junk, ts)
elif self.on_raw is not None:
self.on_raw(data, ts)
+7 -2
View File
@@ -8,7 +8,8 @@ SerialMate — RS485/串口调试助手(Fluent UI)
功能:
- 串口收发, 参数热切换; 半双工 RS485 友好(每个工作周期最多写一帧, 留应答间隙)
- 接收: 协议解析(包头+LEN 定界+CRC 校验, 坏帧重同步) / 原始透传 两模式切换
- 接收: 协议解析(包头+LEN 定界+CRC 校验, 坏帧重同步; 不成帧字节以原始行透出,
不吞数据) / 原始透传 两模式切换
- payload 显示 字符串/HEX 切换, 原始帧 hex 可选, 日志可保存
- 曲线: 4 通道, 二进制定长 / 文本数字 / 正则 三种提取方式 + 倍率
- 发送: 自动包装(payload 即协议载荷, '/' 分隔多条依次组帧) / HEX 直发,
@@ -49,7 +50,7 @@ from protocol import (BIN_FORMATS, CRC_ALGOS, CRC_ALGO_LABELS, CRC_SCOPE_LABELS,
from theme import ThemeManager
APP_NAME = 'SerialMate'
APP_VERSION = '0.1.1'
APP_VERSION = '0.1.2'
REPO_URL = 'https://gitea.hulk.wang/hulk/HW-Debug-Tools'
BAUDS = (1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600)
@@ -250,6 +251,7 @@ class Window(QMainWindow):
self.link = SerialLink(cfg=self._proto_from_store(),
on_status=lambda s, ts: self.events.put(('status', s, ts)))
self.link.on_frame = lambda fr, ts: self.events.put(('frame', fr, ts))
self.link.on_garbage = lambda b, ts: self.events.put(('raw', b, ts))
self.link.on_raw = lambda b, ts: self.events.put(('raw', b, ts))
self.link.on_tx = lambda lb, d, ts: self.events.put(('tx', lb, d, ts))
self._build_ui()
@@ -470,6 +472,9 @@ class Window(QMainWindow):
self.combo_crc.currentIndexChanged.connect(self._apply_proto)
self.combo_scope.currentIndexChanged.connect(self._apply_proto)
self.chk_parse = CheckBox('解析协议帧(收)')
self.chk_parse.setToolTip(
'勾选=按协议格式解析, 合法帧结构化显示; 不成帧的字节不丢弃, 以原始行透出\n'
'不勾选=原始透传, 收到什么显示什么(基础串口助手模式)')
self.chk_parse.stateChanged.connect(self._on_parse_toggle)
self._row(lay, CaptionLabel('CRC'), self.combo_crc,
CaptionLabel('覆盖'), self.combo_scope, self.chk_parse)
+19 -3
View File
@@ -331,6 +331,9 @@ class FrameParser:
"""增量字节流 -> 完整帧: 前缀令牌逐位对齐(帧头/字面量, ID 为通配) + LEN 定长
+ CRC 校验; 任一处失配丢 1 字节重新同步。LEN 值经口径换算后即 payload 长度,
负值视为伪帧头逐出 —— 伪帧头最多滞留一帧即被逐出重同步, 对调试工具可接受。
丢弃字节不销毁: 累积进 self.garbage, 由上层 drain_garbage() 取走透出 ——
本工具首先是串口助手, 协议解析是附加层, 不成帧的字节也必须可见。
(仅匹配上前缀、还在等后续字节的"半帧"缓冲不算垃圾, 可能补全成真帧)
"""
def __init__(self, cfg):
@@ -349,9 +352,22 @@ class FrameParser:
self._len_pos = lay.len_pos
self._extra = lay.len_extra(cfg.len_sem, cs)
self._buf = bytearray()
self.garbage = bytearray() # 重同步丢弃的非帧字节(调用方定期取走)
def clear(self):
self._buf.clear()
self.garbage.clear()
def drain_garbage(self):
"""取走累积的非帧字节(bytes)并清空; 解析模式不吞数据的取数入口"""
out = bytes(self.garbage)
self.garbage.clear()
return out
def _drop_head(self):
"""丢缓冲首字节重同步; 丢弃字节记入 garbage(可能正是用户要看的输出)"""
self.garbage.append(self._buf[0])
del self._buf[:1]
def _aligned(self):
"""把缓冲对齐到前缀匹配; 字节不足且已匹配部分则保持等待(返回 True),
@@ -365,7 +381,7 @@ class FrameParser:
break # 失配 -> 丢 1 字节
else:
return True
del buf[:1]
self._drop_head()
if not buf:
return False
@@ -378,7 +394,7 @@ class FrameParser:
break # LEN 字节未到齐
plen = self._buf[self._len_pos] - self._extra
if plen < 0: # LEN 为负 -> 伪帧头, 逐出重同步
del self._buf[:1]
self._drop_head()
continue
total = cfg.layout.total_size(plen, cfg.crc_size)
if len(self._buf) < total:
@@ -388,7 +404,7 @@ class FrameParser:
frames.append(cfg.parse_frame(raw))
del self._buf[:total]
else:
del self._buf[:1] # CRC 失配 -> 丢帧头重同步
self._drop_head() # CRC 失配 -> 丢帧头重同步
return frames
+18
View File
@@ -93,6 +93,24 @@ frames = d.FrameParser(cfg).feed(bytes(bad) + good)
check('bad-crc then good', len(frames), 1)
check('recovered code', frames[0].code, 0xF0)
# 8b) 非帧字节不吞: 重同步丢弃的字节累积进 garbage 可整体取回(串口助手是本体,
# 协议解析只是附加层——纯文本设备接入时所有字节都从这里透出显示)
p = d.FrameParser(cfg)
check('纯文本不成帧', p.feed(b'hello serial\r\n'), [])
check('纯文本全入 garbage', p.drain_garbage(), b'hello serial\r\n')
check('garbage 取后清空', p.drain_garbage(), b'')
p = d.FrameParser(cfg)
frames = p.feed(b'\x00\x01' + good + b'tail')
check('噪声+帧+尾字节 帧数', len(frames), 1)
check('噪声与尾字节可取回', p.drain_garbage(), b'\x00\x01tail')
p = d.FrameParser(cfg)
p.feed(bytes(bad) + good)
check('坏CRC帧字节全透出', p.drain_garbage(), bytes(bad))
p = d.FrameParser(cfg)
p.feed(b'\xB5') # 只到帧头: 可能补全成真帧, 扣留不算垃圾
check('半帧头扣留待补全', p.drain_garbage(), b'')
check('补全后成帧', [f.code for f in p.feed(good[1:])], [0xF0])
# 9) 伪帧头与帧头字节入载荷
# 9a 小 LEN 伪帧头(B5 AA 01 55,CRC 应为 00 而实为 01)失败后逐字节重同步到真帧
frames = d.FrameParser(cfg).feed(b'\xB5\xAA\x01\x55\x01' + good)
+7
View File
@@ -165,6 +165,13 @@ win._on_raw(b'\x11\x22')
win._flush_rx()
check('透传HEX行', win.text_rx.toPlainText().splitlines()[-1].endswith('11 22'), True)
# 5b) 解析模式非帧字节: link.on_garbage 与透传同走 raw 事件, 日志不丢任何字节
# (v0.1.2 起协议解析是附加层, 串口助手本体语义优先)
check('on_garbage 已接线', win.link.on_garbage is not None, True)
win.events.put(('raw', b'\xAB\xCD', _time.time()))
win._drain_events()
check('非帧字节日志行', win.text_rx.toPlainText().splitlines()[-1].endswith('AB CD'), True)
# 6) 未连接发送丢弃
win._send()
win._drain_events()
+17 -2
View File
@@ -3,7 +3,8 @@
"""链路自检(无硬件): pyserial loop:// 虚拟回环验证 组帧→发送→接收→解析→曲线提取
====================================================================
缺 pyserial 时跳过(退出码 0)。loop:// 回环口写即读, 发出的帧同样回到
接收侧, 但 TX 帧头(D5)不是 RX 帧头(B5), 会被解析器当噪声丢弃, 不影响判定。
接收侧, 但 TX 帧头(D5)不是 RX 帧头(B5), 会作为非帧字节经 on_garbage 透出
(v0.1.2 起解析模式不吞数据), 不影响判定。
用法: python selftest_loop.py (全部通过退出码 0)
"""
@@ -38,10 +39,11 @@ def wait_for(pred, timeout=5.0):
return False
got = {'status': [], 'frames': [], 'tx': [], 'raw': []}
got = {'status': [], 'frames': [], 'tx': [], 'raw': [], 'garbage': []}
cfg = d.ProtoConfig()
link = SerialLink(cfg, on_status=lambda s, ts: got['status'].append((s, ts)))
link.on_frame = lambda fr, ts: got['frames'].append((fr, ts))
link.on_garbage = lambda b, ts: got['garbage'].append((b, ts))
link.on_raw = lambda b, ts: got['raw'].append((b, ts))
link.on_tx = lambda lb, data, ts: got['tx'].append((lb, data, ts))
@@ -75,6 +77,19 @@ if got['frames']:
v = d.extract_value(fr.payload, 'num', index=1, scale=0.1)
check('曲线提取(×0.1)', v is not None and abs(v - 24.6) < 1e-9, True)
# 3b) 解析模式下非帧字节不吞: 以 garbage 原样透出(带到达时刻)——
# 纯文本设备接入解析模式也全可见, 这是 v0.1.2 的核心语义
link.ser.write(b'plain text\n')
check('解析模式非帧字节透出',
wait_for(lambda: b'plain text\n'
in b''.join(b for b, _t in got['garbage'])), True)
if got['garbage']:
check('非帧字节携带到达时刻',
isinstance(got['garbage'][-1][1], float)
and 0 < time.time() - got['garbage'][-1][1] < 60, True)
# 回环回来的 TX 帧(D5 头)在解析模式下同样只算非帧字节, 不应进 frames
check('回环TX帧不算合法帧', all(fr.raw[0] == 0xB5 for fr, _t in got['frames']), True)
# 4) 透传模式切换: 关解析后收到原始字节
link.set_parse(False)
raw = bytes([0x11, 0x22, 0xB5, 0x00])
+6 -4
View File
@@ -49,7 +49,9 @@
FluentIcon 白名单、文本内用单色 Unicode 符号(→ ← ⚠ ⏳ ⚙)。**唯一权威 `icons/`**:
约定文档 `icons/README.md` + 统一生成器 `icons/make_icon.py`(含 `--check`
复现校验与 `--preview` 家族预览图;各工具内旧 make_ico 脚本保留作历史对照,不再维护)。
- 发布约定:源码与打包产物(exe、运行配置)入库;发布 zip 不入库,只上传 Gitea Release。
- 发布约定:源码与运行配置入库;**exe/zip 等交付物一律不入库**(2026-10-13 起
`.gitignore` 全局挡 `*.exe`;历史 39 个 exe blob 已用 git filter-repo 清除,
仓库 1.1 GiB → ~1 MB (pack 实测)),发布只上传 Gitea Release 附件。
## 2. 开发进度(已完成功能清单)
@@ -68,7 +70,7 @@
cursor 裁剪用实例级枚举访问,PySide6 6.11 必抛 AttributeError 且异常打断
`_poll_dlpc` 队列消费(FilmForge 同案);改 `setMaximumBlockCount(500)`
环形裁剪 + 逐事件兜底 + 新增 `selftest_log.py` 回归。tag `DLPilot-v0.4.3`
指向 `c91b4aa`。详见 `DLPilot/AGENTS.md` §9。
指向 `296e220`(历史哈希为 filter-repo 重写前记录)。详见 `DLPilot/AGENTS.md` §9。
### 2.2 EDID-Viewer — 最新发布 v0.1.0(2026-09-25)
- 解析:EDID 1.x 基础身份/时序、CTA(音频 SAD/HDMI VSDB/CEC/HF-VSDB)、HDR 与
@@ -111,7 +113,7 @@
- **v0.1.1(2026-10-13)发布**:接收路径修复(时间戳改 link 线程到达时刻打戳、
接收日志批量插入+5000 行上限+积压折叠、通道配置缓存),详见
`SerialMate/ISSUE_rx_timestamp_and_lag.md` 与其 AGENTS.md §7。tag
`SerialMate-v0.1.1` 指向 `7a236a6`,Release 附件
`SerialMate-v0.1.1` 指向 `e5b2e45`(历史哈希为重写前记录),Release 附件
`SerialMate-v0.1.1-win64.zip`(63.6 MB)。
### 2.4 I2C-Inject — ⏸ 暂停开发(2026-09-25)
@@ -165,7 +167,7 @@
## 3. 开发需求与计划(已提出、尚未实现)
### 3.1 DLPilot
- ~~【待素材】校准图案~~(已完成,2026-10-13 `bcb03e2`):CeramixNano 系列 6 张
- ~~【待素材】校准图案~~(已完成,2026-10-13 `74469cf`):CeramixNano 系列 6 张
校准图(黑/白/caliPoint/circle_640p/contrast/Sharpness_XY_3)二进制直存
assets/+release/ 平铺(用户素材,无生成脚本),slots 栏位接入、
package_release 收集规则扩展;随 v0.4.3 之后的下次发布进 zip。