cartridge/kicad_sym.py
2023-07-13 08:27:27 -07:00

164 lines
4.2 KiB
Python

from itertools import chain, takewhile, dropwhile, filterfalse
SOURCE_SIGNALS = {'VDD', 'VCC', 'VCCIO', 'VCORE', 'VPHY', 'VPLL'}
SINK_SIGNALS = {'GND', 'AGND'}
POWER_SIGNALS = SOURCE_SIGNALS | SINK_SIGNALS
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 - (len(lines) / 2)) * 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 - (len(lines) / 2)) * 2)
y = u(-((height + 2) * 2))
r = 90
yield pin(x, y, r, number, name, type)
input_p = lambda lnt: lnt[2] in {"input", "power_in"}
def make_pins(lines, half_width, split_p=input_p):
pin_sort = lambda l: pin_sort_key(l[1])
lines = sorted(lines, key=pin_sort)
left = list(filter(split_p, lines))
right = list(filterfalse(split_p, lines))
pins = chain(
make_pin_left(left, half_width),
make_pin_right(right, half_width)
)
return pins, max(len(left), len(right))
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 line in lines:
pin, signal, type = line[:3]
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