# MAG160C 逆向交接文档 v3(2026-08-12) > **本文件是最新、最完整上下文快照。** 上一版:handoff_20260811.md。 > 本轮(2026-08-11 晚)完成**官方"读取→显示"完整管线逆向,全部实机 > 像素级验证(100.0% 精确),并交付 demo3(官方管线版)**。 ## 1. 本轮成果(概览) 1. **同帧配对 harness**(tsdk_pair2.exe):同一帧抓官方 gray + RGB24 + raw counts + palette + per-pixel 温度(m°C)+ 窗口/LUT 字段。 2. **完整显示管线逆向完毕**(Windows CoreSDKLib.dll + 实机验证): ``` USB counts → NUC: nuc[i] = clamp((counts[i]-ref[i])*3 + comp, 0, 65535) → 统计: mean/min/max(每帧) → 窗口: lo = min(max, mean-312), hi = max(min, mean+312) (X=624) → 灰度: idx = (nuc[i]-lo) * (0xFFC00000/(hi-lo)) >> 22 (u32 截断!) gray = LUT1024[dev+0x4284c][idx] (非线性对比度曲线) → 颜色: palette[dev+0xb18][gray] (256×4 BGR,含 alpha=0) → 2x bilinear 放大 → 320x240 输出 ``` 3. **像素级验证**:raw→gray 重建 = **100.0% 精确**(与官方同帧 gray 逐像素一致,mean|diff|=0.000);palette 渲染 vs 官方 RGB24 = **100.0% 精确**。 4. **温度公式**:temp_mC = T2E[3*raw - C],C≈5797(5784-5812 会话 漂移)。12 帧验证 mean|err| = 1.3 mC。 5. **demo3**(mag160c_demo3.c,已编译运行):完整官方管线 + 修正了 **像素偏移 bug**(旧代码 +28 是错的,正确从 data[0] 开始,探针 验证:read1=28B 头,read2=38400 像素+28B 尾)。 6. **鬼影结论**:官方 NUC 参考帧只在 FFC 时更新(冻结),无时域滤波 → 无鬼影。demo3 沿用此机制(FFC 后重采集参考帧)。 ## 2. 官方显示管线(权威,全部实机验证) ### 2.1 关键内存布局(Windows CoreSDKLib.dll 运行时对象 dev) | 偏移 | 内容 | 说明 | |---|---|---| | dev+0x220 | 灰度缓冲指针 | 8-bit,显示尺寸(此处 320x240) | | dev+0x270 | NUC 后帧指针 | u16,160x120,NUC 输出 | | dev+0x2a0 | (另一缓冲,MapTemperature 输出目标之一) | | | dev+0xaf0 | 显示结构 | +4 w,+8 h(此处 320x240) | | dev+0xb18 | 调色板 | 256×4 BGRα,与渲染 100% 一致 | | dev+0xf18 | 色彩条 | 128 级灰度渐变 RGBA | | dev+0x42010 | 帧 min | u32(0x1800108a0 统计输出) | | dev+0x42014 | 帧 max | u32 | | dev+0x42018 | 帧 mean | u32 | | dev+0x4201c | 帧 std | u32 | | dev+0x4202c | 窗口 hi | u32(实测 ~10088-10116) | | dev+0x42030 | 窗口 lo | u32(实测 ~9464-9492) | | dev+0x4204c | 直方图 | 256×u32(灰度 idx>>2) | | dev+0x4284c | **LUT1024** | 1024 字节,非线性对比度曲线 | | dev+0x41ef0 | NUC 参考帧指针 | dev+0x41f0c=是否有参考帧 | | dev+0x47938 | 像素数 | 19200 | | dev+0x47948/0x4794c | comp 参数 | comp=(0xc350-offset)>>shift | | [0x18006ea60] | NUC 增益(全局) | 会话自适应,实测=3,饱和时 -1 | ### 2.2 帧处理流程(0x180017040 = NUC+增益) ``` nuc[i] = clamp((frame[i] - ref[i]) * gain + comp, 0, 0xffff) frame = USB 原始帧(参数),ref = dev+0x41ef0 参考帧, gain = [0x18006ea60](饱和像素 >0x100 时减 1), comp = (0xc350 - dev+0x47948) >> dev+0x4794c (clamp>=0) 输出写 dev+0x270 指向的缓冲 ``` 之后 0x180017200 做 3x3 加权滤波(系数 1/3,1/6,1/7 等,写回 dev+0x270)。 ### 2.3 灰度生成(0x180010e85 = Windows MapTemperature) ``` S = 0xFFC00000 / (hi - lo) ; u32 除法 idx = (nuc[i] - lo) * S >> 22 ; u32 截断乘法! gray[i] = LUT1024[dev+0x4284c + idx] 直方图[dev+0x4204c + (idx>>2)]++ ``` ### 2.4 窗口自适应(0x1800109c0/0x180010b0d) ``` 统计(0x1800108a0):min→0x42010, max→0x42014, mean→0x42018, std→0x4201c half = X/2, X 来自积分时间×增益(0x1800108a0 内部,会话恒定,实测 624) lo = min(max, mean - 312); hi = max(min, mean + 312) clamp lo>=0, hi<=0xffff ``` 实测窗口中心 == 帧 mean(9804.8→9804 ✓),X=624 恒定。 ### 2.5 温度(实测公式) ``` temp_mC = T2E[3*raw - C], C≈5797(5784-5812 逐帧漂移) T2E:646 项 int32 表(analysis/official_t2e_table.txt,已转 C 头) slope = (0x1000000 + span/2) / span; temp = slope*diff>>12 + (i<<12) - 0x249f0 验证:12 帧 × 19200 像素 mean|err| = 1.3 mC ``` ## 3. 已导出资源(csdk/src/) - `mag160c_official_palette256.h`:256×4 BGR(dev+0xb18,12 帧一致) - `mag160c_official_lut1024.h`:1024 字节(dev+0x4284c,非线性曲线) - `mag160c_official_t2e.h`:646 项(已有) - 验证脚本:`analysis/temp/`(Python)与本次新增: - `tsdk_pair2.c`(harness)→ `build-artifacts/tsdk_pair2.exe` - `mag160c_demo3.c` → `build-artifacts/mag160c_demo3.exe` - 配对数据:`analysis/pairs2/`(12 帧 × gray/rgb/raw/pal/t32), `analysis/pairs_win/`(窗口/LUT/直方图字段), `analysis/pairs_ffc/`(FFC 前后) ## 4. 帧解码修正(重要 bug) **像素从第二次 bulk read 的 data[0] 开始**(探针 mag160c_layout_probe2 实测:read1 恰 28B 头,read2 = 38400 像素 + 28B 尾,尾魔数 0x1bb1b11c @ offset 38400)。 - `mag160c_demo2.c` 的 `decode_live`(+28)是错的 → demo3 已改为 +0。 - `mag160c_frame_dump.c` 的 `fwrite(frame+28)` 也是错的(错位 14 u16), 统计均值看似正常是因为行 mura 平滑,但像素错位。 - 注意:这与官方 SDK 内部不同(官方 buf+0x1c 起拷像素,因为官方 的帧缓冲含 28B 头)。 ## 5. 温度/窗口剩余问题(未完全确定) 1. **LUT 高端/低端形态**:场景只有 26-28°C,只覆盖 LUT 部分 idx。 LUT 已直接从内存取全 1024 项,无需外推 ✓(这个已经解决了)。 2. **X=624 的来源**:会话恒定,但可能随积分时间/增益模式变化。 已从 dev+0x4202c/0x42030 实测;demo3 硬编码 312 half。 3. **comp 绝对校准**:官方 comp=(0xc350-offset)>>shift 自适应; demo3 简化为 ref 捕获时 comp=9804(官方 NUC 中心水平)。 4. **ref 捕获时机**:官方在 FFC 后捕获;demo3 沿用"FFC(1)后 30 帧 中值"方案(已验证 mura std 3560→29)。 ## 6. 下一步建议 1. 实机对比 demo3 画面与官方 app(用户操作,目视确认)。 2. 若需要长期稳定性:把 comp 校准改为跟随窗口中心 (mean±312 自动居中,comp 只影响绝对温度显示,画面自适应)。 3. Linux 移植:管线纯 C 已在 csdk/src(display/t2e/palette/lut), 把 demo3 的 render 逻辑移植到 mag160c_display.c 官方版 API。 4. 热源实验(可选):宽温度范围数据可验证 LUT 外推与窗口 clamp 行为(idx 溢出回绕)。 ## 7. 环境与工具 - 设备检测:`Get-PnpDevice | ? InstanceId -match 833C` - 官方 harness:`build-artifacts\tsdk_pair2.exe ` (可选第 4-6 参数 SetTempBoundary) - 官方 SDK:`IR_Camera_SDK-1.0.1\windows\windows\app\`(ThermalSDK/ CoreSDKLib/CameraSDK + libusb0.dll) - 反汇编:objdump -d -Mintel;RVA 表见各 disasm_*.txt - Python 3.10 + numpy/scipy/PIL