Files
florian.berthold 1ae49dc1bb Add 8HP layout with fully automated routing pipeline
- Update PCB to 8HP format (40x100mm) with v2 component placement
- Add automated routing scripts (autoroute.py runs full pipeline headlessly)
- Update panel spec and SVG for 8HP dimensions
- Board routes in <1 second with 0 unconnected pads

Scripts:
- autoroute.py: Full CLI pipeline (place → export → route → import → DRC)
- autoroute_full.py: Same pipeline for KiCad scripting console
- place_8hp.py: Component placement only
- route.sh/freeroute.sh: Routing helpers
2026-01-23 07:59:50 +01:00

80 lines
2.2 KiB
Python

#!/usr/bin/env python3
"""
SN-L00 Component Placement Script for 8HP Eurorack (40mm x 100mm)
Run in KiCad PCB Editor: Tools → Scripting Console
Then: exec(open('scripts/place_8hp.py').read())
"""
import pcbnew
board = pcbnew.GetBoard()
def mm(val):
return pcbnew.FromMM(val)
def place(x, y):
return pcbnew.VECTOR2I(mm(x), mm(y))
# First, update the board outline to 8HP (40mm x 100mm)
for drawing in board.GetDrawings():
if drawing.GetClass() == "PCB_SHAPE":
if drawing.GetShape() == pcbnew.SHAPE_T_RECT:
drawing.SetStart(pcbnew.VECTOR2I(mm(0), mm(0)))
drawing.SetEnd(pcbnew.VECTOR2I(mm(40), mm(100)))
print("Updated board outline to 40mm x 100mm (8HP)")
# Delete all tracks for fresh routing
tracks = list(board.GetTracks())
for track in tracks:
board.Delete(track)
print(f"Deleted {len(tracks)} tracks")
# Component positions for 8HP (40mm x 100mm) layout v2
placements = {
"MOD3": (20, 15, 90), # OLED display
"J3": (10, 35, 0), # RETURN_IN jack
"J4": (30, 35, 0), # TRIG_OUT jack
"SW1": (20, 48, 0), # Button
"D5": (32, 48, 0), # LED
"MOD2": (20, 62, 0), # RP2040-Zero
"U2": (8, 78, 0), # 74LVC1G17
"U4": (32, 78, 0), # MCP6001
"C4": (4, 78, 90), # Decoupling
"C5": (14, 78, 90),
"C6": (28, 82, 90),
"D3": (4, 82, 0), # Protection diodes
"D4": (36, 78, 0),
"R2": (4, 86, 90), # Resistors
"R3": (10, 86, 90),
"R4": (16, 86, 90),
"R5": (24, 86, 90),
"R6": (30, 86, 90),
"R7": (36, 86, 90),
"J2": (20, 88, 0), # Eurorack power
"D2": (4, 92, 0),
"U3": (32, 94, 180), # LDO
"C2": (10, 94, 90),
"C3": (26, 94, 90),
}
print("\nPlacing components for 8HP Eurorack layout (v2)...")
placed = 0
not_found = []
for ref, (x, y, rot) in placements.items():
fp = board.FindFootprintByReference(ref)
if fp:
fp.SetPosition(place(x, y))
fp.SetOrientationDegrees(rot)
placed += 1
print(f" {ref} -> ({x}, {y}) rot={rot}°")
else:
not_found.append(ref)
print(f"\nPlaced {placed} components")
if not_found:
print(f"Not found: {', '.join(not_found)}")
pcbnew.Refresh()
print("\nDone! Save (Ctrl+S), then run: ./scripts/route.sh")