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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
"""Minimal S-expression reader/writer for KiCad files."""
import re
class Sym(str):
"""Unquoted atom (keyword / number / bare word)."""
__slots__ = ()
_tok = re.compile(r'\s*(?:(\()|(\))|("(?:[^"\\]|\\.)*")|([^\s()"]+))', re.S)
def parse(text):
pos = 0
stack = [[]]
n = len(text)
while pos < n:
m = _tok.match(text, pos)
if not m:
if text[pos:].strip() == '':
break
raise ValueError('bad token at %d: %r' % (pos, text[pos:pos+40]))
pos = m.end()
if m.group(1):
stack.append([])
elif m.group(2):
lst = stack.pop()
stack[-1].append(lst)
elif m.group(3) is not None:
s = m.group(3)[1:-1]
s = s.replace('\\"', '"').replace('\\n', '\n').replace('\\\\', '\\')
stack[-1].append(s)
else:
stack[-1].append(Sym(m.group(4)))
assert len(stack) == 1, 'unbalanced'
return stack[0][0] if len(stack[0]) == 1 else stack[0]
def q(s):
return '"' + str(s).replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n') + '"'
def dumps(node, indent=0):
"""Serialize: lists -> (..), Sym -> bare, str -> quoted, numbers -> bare."""
if isinstance(node, list):
if not node:
return '()'
# short lists on one line
parts = [dumps(x, indent + 1) for x in node]
oneline = '(' + ' '.join(parts) + ')'
if len(oneline) < 100 and '\n' not in oneline:
return oneline
head = parts[0]
out = '(' + head
i = 1
# keep leading atoms on the first line
while i < len(node) and not isinstance(node[i], list):
out += ' ' + parts[i]
i += 1
for p in parts[i:]:
out += '\n' + '\t' * (indent + 1) + p
out += '\n' + '\t' * indent + ')'
return out
if isinstance(node, Sym):
return str(node)
if isinstance(node, bool):
return 'yes' if node else 'no'
if isinstance(node, int):
return str(node)
if isinstance(node, float):
s = ('%.6f' % node).rstrip('0').rstrip('.')
return s if s not in ('-0', '') else '0'
return q(node)
def find(node, key):
"""First child list whose head == key."""
for x in node:
if isinstance(x, list) and x and x[0] == key:
return x
return None
def findall(node, key):
return [x for x in node if isinstance(x, list) and x and x[0] == key]