component
TPS16850VMAR - 9 V to 80 V, 20 A eFuse
Public Made by Adomby adom
Texas Instruments TPS16850VMAR: 9 V to 80 V, 20 A stackable integrated hot-swap eFuse with a 3.5 mOhm FET, fast current monitor and auto-retry fault response, LQFN-CLIP-23 (VMA, 6.0 x 5.0 mm). KiCad symbol and footprint, Fusion and Altium libraries, datasheet-built 3D model and datasheet.
main
#!/usr/bin/env python3
"""Put every pin of an adom-symbol 1.2.6 .kicad_sym on the 2.54 mm grid (known adom-symbol bug: the first pin of
each column sits at y = -2.00 and group gaps are 8.35 mm, so every pin after it is off grid).
Per column (left x < 0, right x > 0), pins are walked top to bottom: the first goes to the nearest grid point, each
next one keeps its distance to the previous one rounded to whole grid steps (2.54 -> 1 step, the 8.35 group gap ->
3 steps). Group captions move with the pin they label, the body rectangle's bottom becomes the lowest pin - 2.54,
and properties drawn below the body move with that bottom. Footprint and Value are set to the page's values.
usage: snap_symbol.py in.kicad_sym out.kicad_sym MPN LIB:FOOTPRINT"""
import re, sys
src, out, mpn, fp = sys.argv[1:5]
s = open(src).read()
G = 2.54
PIN = r"(\(pin \w+ line )\(at (-?[\d.]+) (-?[\d.]+) (\d+)\)"
pins = [(float(m.group(2)), float(m.group(3))) for m in re.finditer(PIN, s)]
newy = {}
for right in (False, True):
col = sorted([p for p in pins if (p[0] > 0) == right], key=lambda p: -p[1])
prev_old = prev_new = None
for x, y in col:
ny = round(y / G) * G if prev_old is None else prev_new - max(1, round((prev_old - y) / G)) * G
newy[(x, y)] = round(ny, 2); prev_old, prev_new = y, ny
s2 = re.sub(PIN, lambda m: f"{m.group(1)}(at {m.group(2)} {newy[(float(m.group(2)), float(m.group(3)))]:.2f} {m.group(4)})", s)
def cap_sub(m):
x, y = float(m.group(2)), float(m.group(3))
py, ny = max((py, ny) for (px, py), ny in newy.items() if (px > 0) == (x > 0) and py < y)
return f'{m.group(1)}(at {m.group(2)} {ny + (y - py):.2f} 0)'
s2 = re.sub(r'(\(text "[^"]+" )\(at (-?[\d.]+) (-?[\d.]+) 0\)', cap_sub, s2)
rm = re.search(r"\(rectangle \(start (-?[\d.]+) (-?[\d.]+)\) \(end (-?[\d.]+) (-?[\d.]+)\)", s2)
old_bot = float(rm.group(4)); new_bot = round(min(newy.values()) - G, 2); d = new_bot - old_bot
s2 = s2[:rm.start()] + f"(rectangle (start {rm.group(1)} {rm.group(2)}) (end {rm.group(3)} {new_bot:.2f})" + s2[rm.end():]
def prop_sub(m):
y = float(m.group(3))
return f'{m.group(1)}(at {m.group(2)} {y + d:.2f}' if y < old_bot else m.group(0)
s2 = re.sub(r'(\(property "[^"]+" "[^"]*"\s*)\(at (-?[\d.]+) (-?[\d.]+)', prop_sub, s2)
s2 = re.sub(r'\(property "Value" "[^"]*"', f'(property "Value" "{mpn}"', s2, count=1)
s2 = re.sub(r'\(property "Footprint" "[^"]*"', f'(property "Footprint" "{fp}"', s2, count=1)
open(out, "w").write(s2)
off = [(k, v) for k, v in newy.items() if abs(v / G - round(v / G)) > 1e-6]
print("moved", sum(1 for k, v in newy.items() if abs(k[1] - v) > 1e-6), "of", len(newy), "pins; off grid after:", off,
"; body bottom", old_bot, "->", new_bot, "; x on grid:", all(abs(k[0] / G - round(k[0] / G)) < 1e-6 for k in newy))