board
OCuLink Riser for the Supermicro AIOM Slot
Public Unreviewedby John Lauer
Passive OCP NIC 3.0 SFF card that breaks a Supermicro AIOM slot's PCIe x16 into four OCuLink 4i ports (4 x4, Gen4): 6-layer, 85 ohm, length-matched, DRC-clean KiCad project with Gerbers, BOM and CPL.
main
John Lauer
README: component table per the wiki format, open-source section, no duplicate hero; generators at gen/
39a59ef
7d ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
#!/usr/bin/env python3
"""Write an AP214 STEP file made of coloured axis-aligned boxes (plain Python, no CAD kernel).
Used for the AI-generated simplified OCuLink receptacle model (Amphenol G14A42111C12HR): dimensions from Amphenol
drawing G14A421X1BXXXHR rev D. Model frame = KiCad footprint frame turned into KiCad's 3D frame:
x right, y = -(pcb y), z up from the board top."""
import datetime
class Step:
def __init__(self, name):
self.name = name
self.lines = []
self.n = 0
self.solids = [] # (brep_id, rgb)
def add(self, s):
self.n += 1
self.lines.append(f"#{self.n}={s};")
return self.n
def pt(self, x, y, z):
return self.add(f"CARTESIAN_POINT('',({x:.4f},{y:.4f},{z:.4f}))")
def dirn(self, x, y, z):
return self.add(f"DIRECTION('',({x:.1f},{y:.1f},{z:.1f}))")
def box(self, x0, y0, z0, x1, y1, z1, rgb):
P = {}
for i, x in enumerate((x0, x1)):
for j, y in enumerate((y0, y1)):
for k, z in enumerate((z0, z1)):
P[(i, j, k)] = self.add(f"VERTEX_POINT('',#{self.pt(x, y, z)})")
coords = {(i, j, k): ((x0, x1)[i], (y0, y1)[j], (z0, z1)[k]) for i in (0, 1) for j in (0, 1) for k in (0, 1)}
edges = {}
def edge(a, b):
key = tuple(sorted((a, b)))
if key in edges:
return edges[key], key[0] == a
pa, pb = coords[key[0]], coords[key[1]]
d = tuple(pb[t] - pa[t] for t in range(3))
L = max(abs(c) for c in d)
dv = self.dirn(*(c / L for c in d))
vec = self.add(f"VECTOR('',#{dv},{L:.4f})")
ln = self.add(f"LINE('',#{self.pt(*pa)},#{vec})")
e = self.add(f"EDGE_CURVE('',#{P[key[0]]},#{P[key[1]]},#{ln},.T.)")
edges[key] = e
return e, key[0] == a
faces = []
# each face: 4 corners in counter-clockwise order seen from outside, outward normal
F = [
([(0, 0, 0), (0, 1, 0), (1, 1, 0), (1, 0, 0)], (0, 0, -1), (x0, y0, z0)),
([(0, 0, 1), (1, 0, 1), (1, 1, 1), (0, 1, 1)], (0, 0, 1), (x0, y0, z1)),
([(0, 0, 0), (1, 0, 0), (1, 0, 1), (0, 0, 1)], (0, -1, 0), (x0, y0, z0)),
([(0, 1, 0), (0, 1, 1), (1, 1, 1), (1, 1, 0)], (0, 1, 0), (x0, y1, z0)),
([(0, 0, 0), (0, 0, 1), (0, 1, 1), (0, 1, 0)], (-1, 0, 0), (x0, y0, z0)),
([(1, 0, 0), (1, 1, 0), (1, 1, 1), (1, 0, 1)], (1, 0, 0), (x1, y0, z0)),
]
for corners, nrm, org in F:
oes = []
for a, b in zip(corners, corners[1:] + corners[:1]):
e, same = edge(a, b)
oes.append(self.add(f"ORIENTED_EDGE('',*,*,#{e},{'.T.' if same else '.F.'})"))
loop = self.add(f"EDGE_LOOP('',({','.join('#%d' % o for o in oes)}))")
bound = self.add(f"FACE_OUTER_BOUND('',#{loop},.T.)")
ref = (1, 0, 0) if abs(nrm[0]) < 0.5 else (0, 1, 0)
ax = self.add(f"AXIS2_PLACEMENT_3D('',#{self.pt(*org)},#{self.dirn(*nrm)},#{self.dirn(*ref)})")
pl = self.add(f"PLANE('',#{ax})")
faces.append(self.add(f"ADVANCED_FACE('',(#{bound}),#{pl},.T.)"))
shell = self.add(f"CLOSED_SHELL('',({','.join('#%d' % f for f in faces)}))")
brep = self.add(f"MANIFOLD_SOLID_BREP('{self.name}_{len(self.solids)}',#{shell})")
self.solids.append((brep, rgb))
return brep
def write(self, path, description):
head = self.lines
self.lines = []
n0 = self.n
ctx_ids = []
# units and context
lu = self.add("(LENGTH_UNIT()NAMED_UNIT(*)SI_UNIT(.MILLI.,.METRE.))")
au = self.add("(NAMED_UNIT(*)PLANE_ANGLE_UNIT()SI_UNIT($,.RADIAN.))")
su = self.add("(NAMED_UNIT(*)SI_UNIT($,.STERADIAN.)SOLID_ANGLE_UNIT())")
unc = self.add(f"UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(1.E-07),#{lu},'distance_accuracy_value','confusion accuracy')")
ctx = self.add(f"(GEOMETRIC_REPRESENTATION_CONTEXT(3)GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#{unc}))GLOBAL_UNIT_ASSIGNED_CONTEXT((#{lu},#{au},#{su}))REPRESENTATION_CONTEXT('Context #1','3D Context with UNIT and UNCERTAINTY'))")
org = self.add(f"AXIS2_PLACEMENT_3D('',#{self.pt(0, 0, 0)},#{self.dirn(0, 0, 1)},#{self.dirn(1, 0, 0)})")
appctx = self.add("APPLICATION_CONTEXT('core data for automotive mechanical design processes')")
self.add(f"APPLICATION_PROTOCOL_DEFINITION('international standard','automotive_design',2000,#{appctx})")
pctx = self.add(f"PRODUCT_CONTEXT('',#{appctx},'mechanical')")
prod = self.add(f"PRODUCT('{self.name}','{self.name}','',(#{pctx}))")
pdfw = self.add(f"PRODUCT_DEFINITION_FORMATION('','',#{prod})")
pdctx = self.add(f"PRODUCT_DEFINITION_CONTEXT('part definition',#{appctx},'design')")
pd = self.add(f"PRODUCT_DEFINITION('design','',#{pdfw},#{pdctx})")
pds = self.add(f"PRODUCT_DEFINITION_SHAPE('','',#{pd})")
brep_list = ",".join("#%d" % b for b, _ in self.solids)
rep = self.add(f"ADVANCED_BREP_SHAPE_REPRESENTATION('{self.name}',(#{org},{brep_list}),#{ctx})")
self.add(f"SHAPE_DEFINITION_REPRESENTATION(#{pds},#{rep})")
# colours
styled = []
for b, (r, g, bl) in self.solids:
col = self.add(f"COLOUR_RGB('',{r:.3f},{g:.3f},{bl:.3f})")
fas = self.add(f"FILL_AREA_STYLE_COLOUR('',#{col})")
fa = self.add(f"FILL_AREA_STYLE('',(#{fas}))")
ssfa = self.add(f"SURFACE_STYLE_FILL_AREA(#{fa})")
sss = self.add(f"SURFACE_SIDE_STYLE('',(#{ssfa}))")
ssu = self.add(f"SURFACE_STYLE_USAGE(.BOTH.,#{sss})")
psa = self.add(f"PRESENTATION_STYLE_ASSIGNMENT((#{ssu}))")
styled.append(self.add(f"STYLED_ITEM('color',(#{psa}),#{b})"))
self.add(f"MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION('',({','.join('#%d' % s for s in styled)}),#{ctx})")
body = head + self.lines
now = datetime.datetime(2026, 10, 12, 22, 0, 0).strftime("%Y-%m-%dT%H:%M:%S")
with open(path, "w") as fh:
fh.write("ISO-10303-21;\nHEADER;\n")
fh.write(f"FILE_DESCRIPTION(('{description}'),'2;1');\n")
fh.write(f"FILE_NAME('{self.name}.step','{now}',('Adom AI (Claude), generated'),('Adom'),'stepbox.py','stepbox.py','');\n")
fh.write("FILE_SCHEMA(('AUTOMOTIVE_DESIGN { 1 0 10303 214 1 1 1 1 }'));\nENDSEC;\nDATA;\n")
fh.write("\n".join(body))
fh.write("\nENDSEC;\nEND-ISO-10303-21;\n")
def oculink_model(path):
"""Simplified G14A42111C12HR: dimensions from Amphenol drawing G14A421X1BXXXHR rev D."""
s = Step("Amphenol_G14A42111C12HR")
BLACK, NICKEL, GOLD = (0.08, 0.08, 0.09), (0.72, 0.72, 0.70), (0.86, 0.69, 0.25)
W2 = 13.15 / 2
# KiCad 3D frame: y3d = -y_pcb. Body from pcb y -1.98 (mating face) to 7.02 -> y3d +1.98 .. -7.02; height 3.90
s.box(-W2 + 0.25, -7.02, 0.0, W2 - 0.25, 1.70, 3.65, BLACK) # insulator housing
s.box(-W2, -6.90, 3.65, W2, 1.98, 3.90, NICKEL) # shell top
s.box(-W2, -6.90, 0.25, -W2 + 0.25, 1.98, 3.65, NICKEL) # shell sides
s.box(W2 - 0.25, -6.90, 0.25, W2, 1.98, 3.65, NICKEL)
s.box(-W2, 1.73, 0.25, W2, 1.98, 0.75, NICKEL) # shell front lip (bottom)
# shell legs (option C, 2.90 long) at x +/-6.58, pcb y 7.05 and 2.26: 0.5 x 1.1 blades through the board
for sx in (-6.58, 6.58):
for py in (7.05, 2.26):
s.box(sx - 0.25, -py - 0.55, -2.90 + 0.25, sx + 0.25, -py + 0.55, 0.25, NICKEL)
# SMT contact tails: B row at pcb y 7.37, A row at 5.18 (0.2 x 0.7 x 0.15), pitch 0.5
for n in range(21):
xb = 5.25 - 0.5 * n
xa = 4.75 - 0.5 * n
s.box(xb - 0.1, -7.37 - 0.35, 0.0, xb + 0.1, -7.37 + 0.35, 0.15, GOLD)
s.box(xa - 0.1, -5.18 - 0.35, 0.0, xa + 0.1, -5.18 + 0.35, 0.15, GOLD)
# plastic pegs dia 1.00 (as 0.8 squares) at pcb (+5.41, 4.46) and (-5.94, 4.46)
for (px, py) in ((5.41, 4.46), (-5.94, 4.46)):
s.box(px - 0.4, -py - 0.4, -1.2, px + 0.4, -py + 0.4, 0.0, BLACK)
s.write(path, "AI-generated simplified model of Amphenol G14A42111C12HR OCuLink 4X R/A receptacle; dimensions from Amphenol drawing G14A421X1BXXXHR rev D; not a manufacturer model")
return path
if __name__ == "__main__":
import os, sys
out = os.path.join(os.path.dirname(__file__), "..", "kicad", "3d", "Amphenol_G14A42111C12HR.step")
os.makedirs(os.path.dirname(out), exist_ok=True)
oculink_model(out)
print("wrote", out, os.path.getsize(out), "bytes")