文件
zhou yang和Claude Opus 5 efcba30a0c R2 底板改 4 层(D15):规则 / 几何 / 背面摆位 / 4 层布线与铺铜,已下发
- 规则:铜层 2→4,差分 0.28/0.18,间距 0.15,过孔 0.3/0.2(rules_base)
- 几何:98×98 板框 + 4×M3,槽阵居中,L1 12V 大铜 + 指头(pcb_base)
- 摆位:五插槽留 L1,其余 133 件翻到 L4;背面镜像规则实测;Hub 放走廊 2、
  东移 2.5 mm;扇出圈 / 小件间距 1.5(去耦例外)/ 9 A 过孔阵禁区(place_base)
- 叠层按用户决定改为 L1 槽面 / L2 整层 +3V3 / L3 整层 GND / L4 器件面
- 布线:D± 七对按构造布通(USB3 掉头、USB1/2 北去掉头、USB4/5 东绕、
  J23 桥),+3V3 / GND / +12V 平面网每脚一孔,0.125 网格 + PathFinder
  开关(route_base、remote_route.ps1);剩 37 个网待手工补
- 铺铜:4 层重写,入口链自南向北切段 + 断面校核(pour_base);
  已下发布线 / 缝合孔 / 铜面轮廓,填铜未成功(待查)
- 工具:plot_base / plot_routes / shot_base,board_check 通孔两层都算

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_0168Bu6SEx3cXXCJLkdnE6zB
2026-09-10 21:02:10 +08:00

119 行
5.8 KiB
Python

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
# -*- coding: utf-8 -*-
u"""建「PCI-E x4 金手指」器件(R2 刀片的 `J1`)。
金手指不是买来的连接器,是**刀片 PCB 板边本身**:
· 符号借用系统库 `PCIE-064-02-F-D-TH`(Samtec x4 插座)的 64 脚符号 ——
脚号正好就是 `A1~A32` / `B1~B32`,和 CEM 的命名一一对应,不用自己画。
· 封装是**自建金手指**(64 个板边焊盘,1.0 mm 间距,正反两面),
⛔ **还没画**,属于 M4 的活 —— 但 **T3 已定(2026-09-08)**:做斜边 20°/1.0 mm、
金手指区**电镀硬金**(不是 ENIG)、板厚 1.6 mm,所以前置条件已经清空。
⚠ 斜边吃掉手指前端约 1.0 mm 的镀层 ⇒ 金手指长度按 PCIe CEM 画,别自己缩短。
· 不进 BOM(没有东西可买),进 PCB(要出板边焊盘)。
用法:
/c/Python314/python .claude/r2/dev_edge.py # 只查
/c/Python314/python .claude/r2/dev_edge.py --push # 建器件 + 写回 eda-parts.json
"""
import io
import json
import os
import sys
import time
HERE = os.path.dirname(os.path.abspath(__file__))
# ⚠ `.claude` 下有和 r2 同名的 R1 脚本(pcb_pour / pcb_rules / pcb_place)。
# 只插父目录的话,**后面任何一个 `import pcb_rules` 都会拿到 R1 那一份**,
# 而且不报错,只在调到 R2 专有的函数时才炸(2026-09-08 踩过)。
# 规矩:两行都要写,HERE 后插(在 sys.path 最前)。
sys.path.insert(0, os.path.dirname(HERE))
sys.path.insert(0, HERE)
from eda import run # noqa: E402
LIB_ME = '543725e8f0454017a5691e7e570aeef6' # 个人库
LIB_SYS = '0819f05c4eef4c71ace90d822a990e87' # 立创系统库
DEV_NAME = 'PCIE-X4-EDGE-64P'
SYM_SRC = '55d057aaabd3475584df3055eba749d6' # PCIE-064-02-F-D-TH 的符号(A1~A32/B1~B32)
PARTS_JSON = os.path.join(os.path.dirname(HERE), 'eda-parts.json')
DESC = (u'PCI-E x4 金手指(刀片板边,非采购件)。符号借用 Samtec PCIE-064-02-F-D-TH,'
u'脚号 A1~A32/B1~B32 对齐 PCIe CEM。封装待建(M4)。')
def call(js, timeout=120):
r = run(js, timeout=timeout)
if not r.get('success'):
raise RuntimeError(json.dumps(r, ensure_ascii=False)[:600])
return r['result']
def find_dev(retries=6):
for _i in range(retries):
r = call("const r = await eda.lib_Device.search('%s', '%s', undefined, undefined, 20, 1);"
"return (r||[]).map(d => [d.uuid, d.name, d.libraryUuid]);" % (DEV_NAME, LIB_ME))
for u, n, _l in r:
if n == DEV_NAME:
return u
time.sleep(2)
return None
def push():
dev = find_dev(retries=2)
if not dev:
# ⚠️ create() 返回 undefined 但器件已建(skill §9y),判据是 search
call("try { await eda.lib_Device.create('%s', '%s', undefined, "
"{symbol: {uuid: '%s', libraryUuid: '%s'}}, %s); } catch (e) {}"
"return 1;" % (LIB_ME, DEV_NAME, SYM_SRC, LIB_SYS,
json.dumps(DESC, ensure_ascii=False)), timeout=60)
dev = find_dev()
assert dev, u'器件建了但搜不到'
print(u'器件已建: %s %s' % (DEV_NAME, dev))
else:
print(u'器件已存在: %s %s' % (DEV_NAME, dev))
prop = {'name': DEV_NAME, 'designator': 'J?',
'addIntoBom': 'no', 'addIntoPcb': 'yes',
'manufacturer': '-', 'manufacturerId': 'PCB edge finger',
'otherProperty': {'Note': u'刀片板边金手指,不采购;封装待建(M4)'}}
call("try { await eda.lib_Device.modify('%s', '%s', undefined, undefined, undefined, undefined, %s); }"
"catch (e) {} return 1;"
% (dev, LIB_ME, json.dumps(prop, ensure_ascii=False)), timeout=60)
g = call("const d = await eda.lib_Device.get('%s', '%s'); return {assoc: d.association, prop: d.property};"
% (dev, LIB_ME))
a, p = g['assoc'], g['prop']
sym = (a.get('symbol') or {}).get('uuid')
print(u'读回:符号 %s / 封装 %s / designator %s / BOM %s / PCB %s'
% (sym, (a.get('footprint') or {}).get('uuid'),
p.get('designator'), p.get('addIntoBom'), p.get('addIntoPcb')))
# ⚠ create() 会把系统库符号**复制一份进个人库**(uuid 变了,不是引用),
# 所以判据是「有符号 + 放下去 64 个脚对得上」,不是「uuid 等于源符号」。
assert sym, u'符号没挂上'
if sym != SYM_SRC:
print(u' (符号已复制进个人库:%s ← %s)' % (sym, SYM_SRC))
if p.get('addIntoBom') != 'no':
print(u'⚠ addIntoBom 仍是 %s —— 和 MI8-KEY-PAD 一样,BOM 字段 API 改不动,'
u'要在客户端手工改(否则 BOM 里会多一颗买不到的东西)' % p.get('addIntoBom'))
d = json.load(io.open(PARTS_JSON, encoding='utf-8'))
d['parts'][DEV_NAME] = {
'name': DEV_NAME, 'uuid': dev, 'lib': LIB_ME,
'lib_note': u'个人库,不是系统库 —— 放元件时 libraryUuid 要用这个',
'symbol': sym,
'role': (u'R2 刀片 J1:PCI-E x4 金手指(板边本身,不采购)。符号借自系统库 '
u'PCIE-064-02-F-D-TH,脚号 A1~A32 在左列(自上而下,pitch 10)、'
u'B1~B32 在右列,与 PCIe CEM 命名一一对应。'
u'⛔ 封装还没建(64 个板边焊盘,1.0 mm 间距,正反两面),等 T3 定了斜边再画,属 M4。'),
}
with io.open(PARTS_JSON, 'w', encoding='utf-8') as f:
f.write(json.dumps(d, ensure_ascii=False, indent=1))
print(u'已写回 eda-parts.json')
return dev
if __name__ == '__main__':
if '--push' in sys.argv:
push()
else:
print(u'当前: %s' % find_dev(retries=1))