【免费下载链接】whatcablemacOS menu bar app that tells you, in plain English, what each USB-C cable plugged into your Mac can actually do项目地址https://gitcode.com/gh_mirrors/wh/whatcable点击查看免费下载导读本文讲解 whatcable 开源仓库中一条完整的、可复现的“规范数据 → CSV → Swift 代码”生成管线它从 ANSI/CTA-861-H 与 VESA DMT 1.13 两份规范 PDF 中抽取 VICVideo Identification Code与 DMTDisplay Monitor Timing时序表经过三重来源交叉校验后生成Sources/WhatCableCore/Display/EDIDTimingTables.generated.swift中供运行时查询的时序字典。读完本文你将掌握该管线的每一步命令、每个脚本的解析原理与防御式校验逻辑、行数为什么是 154 而非 219、以及 double-clocked SD 格式这一约定差异的来龙去脉。一、管线概览一份永不手写的数据whatcable 是一个分析 macOS 上 USB-C 线缆能力的菜单栏应用其中显示诊断能力依赖 EDIDExtended Display Identification Data时序解析。时序数据被组织为一条严格的三级生成链路规范 PDFVESA DMT 1.13、ANSI/CTA-861-H是“事实之源source of record”由抽取脚本转录两个 CSVdata/edid-timings/vesa-dmt.csv、data/edid-timings/cta-861-vic.csv是抽取脚本的产物绝不手写Swift 文件Sources/WhatCableCore/Display/EDIDTimingTables.generated.swift由生成脚本从 CSV 产出同样绝不手写。这一设计保证了任何一处数字的变更都必须追溯到规范原文杜绝了“改表一时爽、查错火葬场”的手工数据维护问题。EDIDTimingTables.generated.swift头部注释明确声明只有check-edid-timings.py完成了对 edid-decode 与drm_edid.c的数值交叉校验后该文件才会被生成见 EDIDTimingTables.generated.swift。二、数据来源与三重交叉校验2.1 两份规范 PDF两个 CSV 分别转录自以下规范即项目的事实之源VESA DMT Standard v1.0 Rev 13给出 DMT ID、EDID 标准时序 2 字节码、CVT 3 字节码以及每个 DMT 的完整时序数字ANSI/CTA-861-H其 Table 1 Video Format Timings, Detailed Timing Information 定义了 1–219 号 VIC 的详细时序。2.2 两个独立参考实现CSV 生成后只对数字绝不对结构或文本与两份固定版本pinned的独立参考做交叉核对edid-decodeMIT 许可commitf341ed8e3742118a86619e5f499017db2de30d94对照utils/edid-decode/parse-base-block.cpp中的dmt_timings[]以及parse-cta-block.cpp中的edid_cta_modes1[]/edid_cta_modes2[]Linux 内核drivers/gpu/drm/drm_edid.cGPL-2.0对照drm_dmt_modes[]、edid_cea_modes_1[]、edid_cea_modes_193[]。注意这里只做数值比对不从内核拷贝任何内容这也是 GPL 许可下安全的使用边界见 check-edid-timings.py。2.3 许可声明要点生成后的 Swift 文件与其来源 CSV不携带 MIT 或 GPL 声明因为其内容转录自 VESA 与 CTA 规范而非 edid-decode 或内核后两者仅用于验证转录在数值上正确唯一读取它们的脚本就是check-edid-timings.py见 README。这一点对二次分发非常重要时序表本体遵循的是 VESA/CTA 规范数据的使用条款。三、抽取脚本逐个拆解3.1extract-cta-vic.py从 CTA-861-H Table 1 抽取 VIC 表脚本用pypdf读取本地 PDF逐页寻找包含 Table 1 的连续页区间用正则ROW_RE匹配形如VIC[, VIC] Hactive Vactive I/P Htotal Hblank Vtotal Vblank HFreq VFreq PixelFreq的行见 extract-cta-vic.py。它需要处理两个 PDF 文本抽取特有的脚注陷阱陷阱一H 字段粘连脚注 2。Hactive/Htotal 偶尔会粘连一个无空格的脚注数字 2如 14402代表该 SD 格式被 double-clocked。脚本利用本表唯一不参与脚注的列 Hblank来判定Hblank 必须恰好等于 Htotal − Hactive。先按原始读数尝试若不满足恒等式则去掉 Hactive 与 Htotal 末尾的 2 再验证见strip_h_footnoteextract-cta-vic.py。陷阱二V Freq 粘连脚注 3。该脚注表示“与 1000/1001 缩放的 NTSC 兼容兄弟时序视为同一 Video Timing”。表中所有 V Freq 都打印为 2 或 3 位小数脚注值会多一个尾随数字——因此任何超过 2 位小数的值直接丢弃最后一个字符见strip_v_footnoteextract-cta-vic.py。行变体的归并策略VIC 8、9、12、13、23、24、27、28 在规范中列出两到三个仅在 Vtotal/V Freq 上相差一两行的变体而 CTA-861-H 自身的脚注说明这些属于同一 Video Format。edid-decode 的表将每个 VIC 归并为“第一个列出的变体”本脚本采取相同策略首次出现者获胜后续变体只有在除 Vtotal/V Freq 外全部一致时才被静默接受否则报错见 extract-cta-vic.py。完整性断言脚本强制输出集合严格等于 VIC 1–127 ∪ 193–219EXPECTED_VICSextract-cta-vic.pyVIC 0 与 128–192 被保留reserved任何缺失或多余都会导致脚本以非零状态退出。3.2extract-dmt.py从 VESA DMT 1.13 抽取 DMT 表DMT 表由 PDF 内两个来源联合驱动见 extract-dmt.pyTable 2-1第 10–12 页Summary of DMT ID, Std. 2 Byte CVT 3 Byte Codes给出 DMT ID 及其 EDID 标准时序 2 字节码、CVT 3 字节码并在 Refresh Rate 列以(RB)标记 reduced blankingSection 4 详情页第 18 页起每个 DMT 一页给出实际时序数字EDID ID: DMT ID: XXh、分辨率行、Pixel Clock、Hor/Ver Total Time。脚本的关键设计是两个来源互相印证Table 2-1 与详情页都声明 DMT ID 及其 Std./CVT 码脚本要求二者完全一致而不是只信任其一。值得注意的一个兼容性细节绝大多数详情页把 Std. 2 Byte Code 打印为(XX, YY)h但 DMT 53h、54h、55h 三页打印为XXh, YYhSTD_CODE_ALT同时接受两种形状extract-dmt.py。Reduced blanking 的双重判定脚本曾尝试用详情页的 Method: 行判断 RB但发现该行不可靠——它会在某些真正的 reduced-blanking 非 CVT 模式如 DMT 56h1366x76860 RB上打印 *** NOT CVT COMPLIANT又会在至少一个 CVT reduced-blanking 模式DMT 4Ch2560x160060 RB上完全不提 blanking 风格。最终采用两个独立信号必须同时成立*详情页分辨率行含 REDUCED BLANKING可带 v2且 Table 2-1 的 Refresh Rate 列同一 DMT ID 标(RB)extract-dmt.py。完整性断言DMT ID 必须严格覆盖 0x01–0x58 连续区间EXPECTED_IDSextract-dmt.pyTable 2-1 与详情页两套 ID 集合各自完整且两者在 Std./CVT 码与 RB 标记上零分歧。3.3check-edid-timings.py三方逐行比对该脚本是管线的“质检站”把两个 CSV 的每一行width、height、hTotal、vTotal、pixelClockKHz、interlaced 六个字段与 edid-decode 和内核的表逐行比对COMPARE_FIELDScheck-edid-timings.py。任何一行在 CSV 中存在而在某参考中缺失、或反之、或任一字段不一致都是失败脚本一次性打印所有分歧绝不在第一个分歧处停住check-edid-timings.py这样重新生成 CSV 后只需跑一次即可看到完整问题清单。为解析两个参考实现脚本实现了几个相当精巧的 C 源码解析器通用 C 结构体数组解析通过花括号深度计数抽取var_name[] { ... }的数组体extract_array_body再按顶层花括号切分为条目split_top_level_entries并按顶层逗号切分参数split_top_level_args支持嵌套{}/()与双引号字符串见 check-edid-timings.pyedid-decodestruct timings解析按edid-decode.h中的字段顺序做位置聚合初始化TIMINGS_FIELDS再从各字段推导出与 DMT/VIC 相同的 (width, height, hTotal, vTotal, pixelClockKHz, interlaced)。隔行扫描interlaced的 vTotal 推导是本脚本最容易被误解的一处edid-decode 的vact是整帧高度因此每场高度为vact/2帧 vTotal 2 * (vact/2 vfp vsync vbp) (0 if even_vtotal else 1)——该公式已对照 DMT 0x0F817 行与 CTA VIC 51125 行在规范 PDF 中的原文验证过check-edid-timings.py内核DRM_MODE(...)解析内核的drm_dmt_modes[]不是按 DMT ID 索引的驱动内部数组DMT ID 只能从其/* 0xXX - ... */注释中恢复因此脚本按注释跟踪解析parse_drm_dmt_with_ids而不是像edid_cea_modes_1[]/edid_cea_modes_193[]那样按位置索引check-edid-timings.py。明确的排除范围edid-decode 的established_timings12[]基础块 Established Timings I II即 IBM/Apple 遗留信号DMT ID 0x00不是 DMT 表不在本脚本的比对范围内check-edid-timings.py。四、重新生成四条命令完整走一遍管线共四步全部以本地文件为输入——没有任何脚本会去下载 PDF--pdf永远接收本地路径各脚本的--help会说明从哪里获取 PDF。步骤 1抽取 VIC 表CTA-861-Hpython3 scripts/edid-timings/extract-cta-vic.py --pdf path-to-CTA-861-H.pdf --out data/edid-timings/cta-861-vic.csv步骤 2抽取 DMT 表VESA DMT 1.13python3 scripts/edid-timings/extract-dmt.py --pdf path-to-VESA-DMT-1.13.pdf --out data/edid-timings/vesa-dmt.csv步骤 3三方交叉校验python3 scripts/edid-timings/check-edid-timings.py \ --edid-decode-dir path-to-edid-decode/utils/edid-decode \ --drm-edid path-to-drm_edid.c必须看到以下输出才能继续OK: 88 DMT rows and 154 VIC rows agree with edid-decode and drm_edid.c任何分歧都要对照 CSV 的source_page列所指向的 PDF 页核查并在抽取脚本中修复——CSV 本身绝不手改README。步骤 4重新生成 Swift 表swift scripts/edid-timings/build-edid-timings.swiftCI 防护scripts/ci.sh会以--check模式执行步骤 4重新生成到临时文件再与已提交的生成文件 diff因此“CSV 改了但没重新生成”或“手改了生成文件”都会直接让 CI 失败README。4.1 CSV 实际格式速览data/edid-timings/cta-861-vic.csv的表头与首行VIC 1640x48059.94vic,width,height,interlaced,h_total,v_total,pixel_clock_khz,v_freq_hz,source_page 1,640,480,false,800,525,25175,59.94,42data/edid-timings/vesa-dmt.csv的表头与首行DMT 0x01640x35085dmt_id,width,height,refresh_hz,interlaced,reduced_blanking,h_total,v_total,pixel_clock_khz,std_code,cvt_code,source_page 0x01,640,350,85,false,false,832,445,31500,,,18注意std_code/cvt_code为空表示该 DMT 没有对应的 EDID 标准时序码或 CVT 码source_page列是审计追溯的关键——任何数值争议都能直接定位到规范 PDF 的具体页。五、行数深挖为什么是 154 而不是 219VIC 219 是 CTA-861-H 定义的最高 Video Identification Code但它不是行数。原因VIC 0 与 128–192 被保留——CTA-861-H 的 Table 1 未为它们定义任何 Video Format Timing且 128–192 作为 SVDShort Video Descriptor值在 CTA-861 语义下是 Forbidden这是一条独立但相关的规则。因此真实行数为127VIC 1–127 27VIC 193–219 154这个数字用三种相互独立的方式验证过README规范 PDF 文本本身edid-decode 的edid_cta_modes1[]127 项edid_cta_modes2[]27 项内核的edid_cea_modes_1[]edid_cea_modes_193[]同样 127 27。DMT 侧同理extract-dmt.py的EXPECTED_IDS range(0x01, 0x59)即 0x01–0x58 共 88 个 DMT ID无任何缺口。六、谁在消费这些表运行时查表链路生成出的两张字典被 WhatCableCore 的显示诊断模块在运行时使用EDIDTimingTables.dmt/.vic定义于 EDIDTimingTables.generated.swiftDMTTiming携带id、width、height、hTotal、vTotal、pixelClockKHz、interlaced、reducedBlanking、standardCodeEDID 标准时序 2 字节码大端打印、cvtCode3 字节 CVT 码等字段DisplayID Type IV / Type VIII 解码EDIDDisplayIDTimingDecoders.typeIVorVIII对 codeType 0 查EDIDTimingTables.dmt[id]、对 codeType 1 查EDIDTimingTables.vic[id]任一 id 缺表即返回无模式——与 HDMI VICcodeType 2没有内置表、同样无法解析的模式保持一致EDIDDisplayIDTimingDecoders.swiftCTA 块解析EDIDCTAParser解析 SVD 时以EDIDTimingTables.vic[vic]查表命名了但表中不存在的 VIC 直接跳过EDIDCTAParser.swift标准时序码反查手写的查询扩展dmt(standardCode:)按 EDID 2 字节标准时序码反查 DMTdmt(width:height:refreshHz:reducedBlanking:)则按分辨率、四舍五入刷新率与 reduced-blanking 标志匹配——其中隔行 DMT仅 0x0F1024x76843i按场率匹配存储的 vTotal 是帧总行数故场率是hTotal * vTotal算出的帧率的两倍EDIDTimingTablesLookup.swift。6.1 面向真实 EDID 的终极检验check-edid-timings.py的比对对象是 edid-decode 与内核自带的表不是真实 EDID。对真实 EDID 的交叉检验由Tests/WhatCableDarwinTests/EDIDOracleSweepTests.swift承担该测试用这套表解析语料库中的每一个 EDID并把解析出的声明模式列表与 edid-decode 对同一文件的输出逐项对比README。从源码结构可以推断这是一个“表内数值正确 运行时查表正确 真实样本全量回归”的三层质量防线。七、已知约定差异double-clocked SD 格式这是整个管线中最容易误判为 bug 的约定问题。遗留的 720(1440)xN 模拟血统格式VIC 6、7、8、9、21、22、23、24、44、45、50、51、54、55、58、59是**像素重复pixel-repeated**的每个像素被发送两次。三方对同一事实有两种记数习惯CTA-861-H Table 1 文本与 edid-decode报告翻倍后的水平数字如 VIC 6宽 1440、像素时钟 27 MHz、Htotal 1716项目 CSV 与 Swift 表沿用的是这一约定Linux 内核存储原始的、未翻倍的数字宽 720、像素时钟 13.5 MHz、Htotal 858并用DRM_MODE_FLAG_DBLCLK标记该行。check-edid-timings.py明确知晓这一差异在比较带DRM_MODE_FLAG_DBLCLK的行之前先把内核的水平字段与像素时钟翻倍垂直字段不受影响见drm_fields_to_rowcheck-edid-timings.py。因此这不是解析 bug——一旦计入约定差异两个参考源完全一致README。这提醒所有阅读生成代码的人同一时序在不同生态里有不同的记数惯例跨源比对必须显式处理单位与记数约定。八、给维护者的实操清单想改时序数据永远不要直接编辑 CSV 或.generated.swift改抽取脚本或规范数据本身然后四步重新生成想核对某个 VIC/DMT 的来源查 CSV 的source_page列定位到规范 PDF 的具体页想确认改动不破坏解析先跑check-edid-timings.py看三方比对输出再跑EDIDOracleSweepTests做真实 EDID 回归脚本依赖pypdf解析 PDFextract-cta-vic.py与extract-dmt.py的--pdf参数都要求本地文件路径脚本不会也不应该联网下载规范文档。这条管线的价值在于把“规范原文 → 机器可读数据 → 运行时查表”之间的每一环都变成可审计、可重放、可验证的过程为 whatcable 的显示诊断功能提供了高可信度的时序数据底座。相关实现均可继续在 scripts/edid-timings、data/edid-timings 与 Sources/WhatCableCore/Display 中深入阅读。赞分享【免费下载链接】whatcablemacOS menu bar app that tells you, in plain English, what each USB-C cable plugged into your Mac can actually do项目地址https://gitcode.com/gh_mirrors/wh/whatcable点击查看免费下载相关推荐Swift代码文档生成基于gh_mirrors/swi/swift-style-guide的规范Swift代码文档生成基于gh_mirrors/swi/swift style guide的规范 你是否在团队协作中因代码风格混乱而浪费大量时间是否在接手他教程rippled 代码风格速查表精读从 Form/Function 规范到 XRP Ledger 源码实践rippled 代码风格速查表精读从 Form/Function 规范到 XRP Ledger 源码实践 本篇速查表解读围绕 docs/CheatSheet.区块链Unity游戏适配微信小游戏从技术架构到实战部署的终极指南Unity游戏适配微信小游戏从技术架构到实战部署的终极指南 在移动游戏开发领域微信小游戏已经成为不可忽视的重要平台。微信小游戏Unity WebGL适配方案游戏开发移动开发WebAssembly上一篇如何快速上手MusicFree插件化音乐播放器的终极使用指南下一篇5秒读懂B站视频这款智能总结工具如何改变你的观看习惯创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
