gokul/cm4-media-carrier
A tscircuit package created by gokul.
- Version
- 0.1.0
- License
- unset
- Stars
- 0
tools/assembly-files.py
"""Generate purchasing and placement files from the final circuit."""
import csv, json, sys
from pathlib import Path
root = Path(sys.argv[1]); out = Path(sys.argv[2]); out.mkdir(parents=True, exist_ok=True)
j = json.loads((root / 'circuit.json').read_text())
native = json.loads((root / 'native-pad-geometry.json').read_text())
sources = {e['source_component_id']: e for e in j if e['type'] == 'source_component'}
components = {e['source_component_id']: e for e in j if e['type'] == 'pcb_component' and e['source_component_id'] in sources}
descriptions = {
'DF40C-100DS-0.4V(51)': ('Hirose', '100-way 0.4mm CM4 socket; 1.5mm stack', 'SMT'),
'TYPE-C-31-M-12': ('Korean Hroparts', 'USB Type-C receptacle; fixed 5V input', 'Hybrid SMT + soldered stakes'),
'690-019-298-412': ('EDAC', 'HDMI Type-A receptacle', 'Hybrid SMT + soldered stakes'),
'690-005-298-486': ('EDAC', 'USB Micro-B receptacle', 'Hybrid SMT + soldered stakes'),
'AP2331W-7': ('Diodes Incorporated', 'SOT-23-3; 0.2A HDMI power switch', 'SMT'),
'APT1608SGC': ('Kingbright', '0603 green LED; pin1 cathode', 'SMT'),
'APT1608SYC/J3-AMT': ('Kingbright', '0603 yellow LED; pin1 cathode', 'SMT'),
'TSW-102-07-G-S': ('Samtec', '1x2 2.54mm vertical header', 'Through-hole'),
'GRM21BR61A106KE19L': ('Murata', '0805 10uF 10V X5R capacitor', 'SMT'),
'GRM155R71C104KA88D': ('Murata', '0402 100nF 16V X7R capacitor', 'SMT'),
'RC0402FR-075K1L': ('Yageo', '0402 5.1kohm 1% resistor', 'SMT'),
'RC0402FR-071KL': ('Yageo', '0402 1kohm 1% resistor', 'SMT'),
'RC0402FR-07220RL': ('Yageo', '0402 220ohm 1% resistor', 'SMT')
}
rows = []; placements = []
for sid, s in sources.items():
c = components[sid]; ref = s['name']; mpn = s['manufacturer_part_number']
maker, description, mount = descriptions[mpn]
pin1 = [p for p in native if p['ref'] == ref and p['pin'] == '1']
assert len(pin1) == 1, (ref, pin1)
p = pin1[0]; note = 'Design angle; assembler maps feeder orientation using physical pin1.'
if ref.startswith('D_'): note = 'Pin1 cathode at right; align with vertical cathode silk bar.'
if ref == 'J_USB': note = 'Internal pin1 is EH2 shield tab; signal aliases A/B in source. Mouth faces +X.'
if ref == 'J_HDMI': note = 'Signal pin1 per EDAC drawing; mouth faces +X.'
if ref == 'J_PROGRAM': note = 'Signal pin1 VBUS intentionally NC; mouth faces -X.'
if ref.startswith('J_CM4'): note = 'Pin1 upper-left in top view. B pins1..100 map to CM4 global101..200.'
rows.append([ref, 1, maker, mpn, description, mount, 'top', ','.join(s.get('supplier_part_numbers', {}).get('jlcpcb', []))])
placements.append([ref, mpn, round(c['center']['x'], 6), round(c['center']['y'], 6), 'top', c['rotation'], round(p['x'], 6), round(p['y'], 6), note])
for filename, header, records in [
('BOM.csv', ['Designator', 'Quantity', 'Manufacturer', 'Manufacturer Part Number', 'Description', 'Mounting', 'Side', 'Supplier reference (not assembly approval)'], rows),
('PLACEMENT.csv', ['Designator', 'Manufacturer Part Number', 'Centre X mm', 'Centre Y mm', 'Side', 'Design rotation CCW degrees', 'Physical pin1 X mm', 'Physical pin1 Y mm', 'Orientation note'], placements)
]:
with (out / filename).open('w', newline='') as f:
writer = csv.writer(f); writer.writerow(header); writer.writerows(records)
assert len(rows) == 19
print('Wrote 19-component BOM and pin-1 placement table')