150 lines
3.6 KiB
Python
150 lines
3.6 KiB
Python
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
|