imrishabh18/pedometer
This code defines and assembles a simple radio receiver hardware circuit using specific imported capacitors, inductors, RF connectors, and oscillator components with precise footprints and schematic attributes.
- Version
- 1.1.3
- License
- unset
- Stars
- 0
scripts/package-cam.py
"""Package the reviewed prototype for factory CAM; does not authorize an order."""
import csv,hashlib,io,json,zipfile
from pathlib import Path
root=Path('.')
sha=lambda p:hashlib.sha256(p.read_bytes()).hexdigest()
circuit=root/'dist/index/circuit.json'
c=json.loads(circuit.read_text());h=sha(circuit)
assert not any(e['type'].endswith('_error') for e in c), 'Circuit has errors'
review=json.loads((root/'review/fabrication-review.json').read_text())
assert review['circuitSha256']==h, 'Stale fabrication review'
assert review['manufacturingCircuitSha256']==sha(root/'review/manufacturing/circuit.json'), 'Stale manufacturing review'
for name in ['imported-footprint-audit','passive-gerber-audit','programming-check','fabrication-metrics','copper-clearance','drill-export-audit','bga-via-inventory']:
report=json.loads((root/f'review/{name}.json').read_text())
assert report['circuitSha256']==h, f'Stale {name}'
assert json.loads((root/'review/programming-check.json').read_text())['result']=='PASS'
metrics=json.loads((root/'review/fabrication-metrics.json').read_text())
assert not any(metrics[k] for k in ['viaPairsBelow02mm','viaHoleToOtherNetTraceBelow02mm','viaHoleToOtherNetPadBelow02mm','viaHoleToOtherNetPourBelow02mm'])
clearance=json.loads((root/'review/copper-clearance.json').read_text())
assert min(clearance['padToTraceMinimum']['mm'],clearance['traceToTraceMinimum']['mm'])>=.09-1e-6
pcb_refs={e['name'] for e in c if e['type']=='source_component'}
cpl=list(csv.DictReader((root/'review/jlc-cpl.csv').open()))
bom=list(csv.DictReader((root/'review/jlc-bom.csv').open()))
assert {r['Designator'] for r in cpl}==pcb_refs
assert {ref for row in bom for ref in row['Designator'].split(',')}==pcb_refs
assert all(row['LCSC Part #'] and row['Comment'] for row in bom)
out=root/'fabrication';out.mkdir(exist_ok=True)
files={}
gerbers=io.BytesIO()
with zipfile.ZipFile(gerbers,'w',zipfile.ZIP_DEFLATED) as z:
for p in sorted((root/'review/manufacturing').iterdir()):
if p.suffix in ['.gbr','.drl'] and p.name!='F_Fab.gbr':z.write(p,p.name)
files['pedometer-gerbers.zip']=gerbers.getvalue()
for src,dest in [('review/jlc-bom.csv','assembly/BOM.csv'),('review/jlc-cpl.csv','assembly/CPL.csv'),('review/assembly.svg','assembly/placement-reference.svg'),('review/manufacturing/F_Fab.gbr','assembly/F_Fab.gbr'),('docs/footprint-correction.md','docs/footprint-correction.md'),('review/footprint-comparison.svg','assembly/footprint-comparison.svg'),('docs/assembly-requirements.md','docs/assembly-requirements.md'),('docs/programming.md','docs/programming.md'),('docs/fabrication-review.md','docs/fabrication-review.md'),('docs/interfaces.md','docs/interfaces.md'),('docs/bare-cc2340r5.md','docs/bare-cc2340r5.md'),('docs/firmware-and-bringup.md','docs/firmware-and-bringup.md')]:files[dest]=(root/src).read_bytes()
for p in sorted((root/'review').glob('schematic-[1-5]-*.svg')):files['schematics/'+p.name]=p.read_bytes()
for name in ['fabrication-review','imported-footprint-audit','passive-gerber-audit','programming-check','fabrication-metrics','copper-clearance','drill-export-audit','bga-aperture-audit','bga-via-inventory','routing-completeness','validation']:
files['review/'+name+'.json']=(root/f'review/{name}.json').read_bytes()
files['README.txt']=('Stride Rev B / local v1.1.3 - corrected passive footprints\n\n40 x 38 mm, four layers, 1.0 mm, ENIG.\nUse these Gerbers, BOM and CPL together; supersedes the rejected pad geometry.\nRead docs/footprint-correction.md and docs/assembly-requirements.md before tooling.\nBGA via-in-pad is intentional: resin fill, planarize and copper cap.\nFactory acceptance of mask registration, stencil and RF stackup is pending.\nCPL and Gerbers use the board-center origin, in millimeters.\nUSB-C is power only; program through J4 SWD.\nNo complete target firmware binary or physical bring-up is claimed.\n\nCircuit SHA256: '+h+'\n').encode()
manifest={'circuitSha256':h,'manufacturingCircuitSha256':review['manufacturingCircuitSha256'],'status':'factory-cam-review','files':{n:hashlib.sha256(b).hexdigest() for n,b in files.items()}}
files['manifest.json']=json.dumps(manifest,indent=2).encode()
path=out/'pedometer-rev-b-cam-review.zip'
with zipfile.ZipFile(path,'w',zipfile.ZIP_DEFLATED) as z:
for n,b in files.items():z.writestr(n,b)
(out/'manifest.json').write_text(json.dumps(manifest,indent=2))
print(f'{path}: {len(files)} files; {len(pcb_refs)} assembly references; factory acceptance pending')