molecule
AM/FM Receiver Molecule
Public Made by Adomby adom
USB-powered AM/FM receiver on an Adom Molecule: discrete BJT and op-amp superhet (10.7 MHz and 455 kHz IFs), STM32G0B1 tuning, self-calibration and USB audio over one USB-C cable. 96 x 96 mm pin grid, 4 layers, KiCad 10.
main
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
"""Export the netlist with kicad-cli and compare every pin against design.DESIGN."""
import os, subprocess, sys, tempfile
from sexp import parse, find, findall
from design import DESIGN
HERE = os.path.dirname(os.path.abspath(__file__))
PROJ = os.path.abspath(os.path.join(HERE, '..'))
def export_netlist(path):
out = os.path.join(tempfile.gettempdir(), 'amfm_check.net')
subprocess.run(['kicad-cli', 'sch', 'export', 'netlist', '--format', 'kicadsexpr', '-o', out, path],
check=True, capture_output=True)
return parse(open(out).read())
def main():
n = export_netlist(os.path.join(PROJ, 'amfm_receiver.kicad_sch'))
kic = {} # (ref, pin) -> net
kic_nets = {}
for net in findall(find(n, 'nets'), 'net'):
name = find(net, 'name')[1]
short = name.split('/')[-1]
if short.startswith('unconnected-') or short.startswith('Net-('):
short = None
for nd in findall(net, 'node'):
key = (find(nd, 'ref')[1], find(nd, 'pin')[1])
kic[key] = short
kic_nets.setdefault(name, []).append(key)
comps = {find(c, 'ref')[1]: c for c in findall(find(n, 'components'), 'comp')}
errors = 0
for p in DESIGN.parts:
if p.ref not in comps:
if p.pins:
print('MISSING component', p.ref)
errors += 1
continue
c = comps[p.ref]
fp = find(c, 'footprint')
if fp is None or fp[1] != p.footprint:
print('FOOTPRINT mismatch', p.ref, fp and fp[1], p.footprint)
errors += 1
for pin, net in p.pins.items():
got = kic.get((p.ref, pin), None)
if got != net:
print('NET mismatch %s.%s: design=%s kicad=%s' % (p.ref, pin, net, got))
errors += 1
# local nets must not be split: a design net must map to one KiCad net
dn = DESIGN.nets()
for net, nodes in dn.items():
names = set()
for nm, keys in kic_nets.items():
if any(k in keys for k in nodes):
names.add(nm)
if len(names) != 1:
print('NET split/merged', net, names)
errors += 1
print('checked %d parts, %d design nets, %d KiCad nets: %d errors' % (
len(DESIGN.parts), len(dn), len(kic_nets), errors))
return errors
if __name__ == '__main__':
sys.exit(1 if main() else 0)