- 规则:铜层 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
119 行
5.8 KiB
Python
119 行
5.8 KiB
Python
# -*- 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))
|