from itertools import chain, takewhile, dropwhile, filterfalse POWER_SIGNALS = {'GND', 'VDD', 'VCC'} SOURCE_SIGNALS = {'VDD', 'VCC'} SINK_SIGNALS = {'GND'} def split_power(lines): source = [] sink = [] other = [] for pin, signal, type in lines: if signal in SOURCE_SIGNALS: source.append((pin, signal, type)) elif signal in SINK_SIGNALS: sink.append((pin, signal, type)) else: other.append((pin, signal, type)) return source, sink, other def make_pin_left(lines, half_width): for ix, (number, name, type) in enumerate(lines): x = u(-half_width) y = u((-ix + 0) * 2) r = 0 yield pin(x, y, r, number, name, type) def make_pin_right(lines, half_width): for ix, (number, name, type) in enumerate(lines): x = u(half_width) y = u((-ix + 0) * 2) r = 180 yield pin(x, y, r, number, name, type) def make_pin_top(lines): for ix, (number, name, type) in enumerate(lines): x = u((ix) * 2) y = u(6) r = 270 yield pin(x, y, r, number, name, type) def make_pin_bottom(lines, height): for ix, (number, name, type) in enumerate(lines): x = u((ix) * 2) y = u(-((height + 2) * 2)) r = 90 yield pin(x, y, r, number, name, type) def pin_sort_key(s): is_not_numeric = lambda c: not (ord(c) >= ord('0') and ord(c) <= ord('9')) h = ''.join(takewhile(is_not_numeric, s)) t = ''.join(dropwhile(is_not_numeric, s)) return h, int(t) if t else -1 def assert_valid(lines): pins = set() signals = set() types = set([ "power_in", "power_out", "bidirectional", "input", "output" ]) for pin, signal, type in lines: assert type in types, type assert pin not in pins, pins pins.add(pin) if signal not in POWER_SIGNALS: assert signal not in signals, signal signals.add(signal) def read_txt(filename): with open(filename) as f: lines = [l.split() for l in f.read().split('\n') if l] assert_valid(lines) return lines _lib = """ (kicad_symbol_lib (version 20220914) (generator kicad_sym) {symbols} ) """.strip('\n') _symbol = """ (symbol "{name}" (in_bom yes) (on_board yes) (property "Reference" "U" (at 0 -7.62 0) (effects (font (size 1.27 1.27))) ) (property "Value" "{value}" (at 0 -10.16 0) (effects (font (size 1.27 1.27))) ) (property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide) ) (property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide) ) (symbol "{name}_0_1" (rectangle (start {x0} {y0}) (end {x1} {y1}) (stroke (width 0) (type default)) (fill (type none)) ) ) (symbol "{name}_1_1" {pins} ) ) """.strip('\n') _pin = """ (pin {type} line (at {x:.02f} {y:.02f} {r}) (length {length}) (name "{name}" (effects (font (size 1.27 1.27)))) (number "{number}" (effects (font (size 1.27 1.27)))) ) """.strip('\n') def lib(symbols): return _lib.format( symbols="\n".join(symbols) ) def symbol(name, value, pins, x0, y0, x1, y1): return _symbol.format( name=name, value=value, pins="\n".join(pins), x0=x0, y0=y0, x1=x1, y1=y1 ) def pin(x, y, r, number, name, type, length=4): return _pin.format( x=x - u(length) if x < 0 else x + u(length), y=y, r=r, name=name, type=type, number=number, length=u(length) ) def u(n): mul = 1.27 return n * mul