component
LTC2945CMS#PBF - Wide Range I2C Power Monitor
Public Made by Adomby adom
Analog Devices (Linear Technology) LTC2945CMS#PBF: wide range I2C power monitor, 0 V to 80 V current and voltage sensing, 12-bit ADC, 24-bit power, min/max and alerts, split SDA for opto-isolation, 0 C to 70 C, MSOP-12. KiCad, Fusion and Altium libraries, 3D model and datasheet.
main
#!/usr/bin/env python3
"""Put every pin of an adom-symbol 1.2.6 two-column .kicad_sym on the 2.54 mm grid (1.2.6 starts each column at
y = -2.00 and spaces groups 8.35 mm apart, so most pins land off grid; a known bug).
Per column (pins sharing an x), keeping the tool's order and grouping (a gap > 2.6 mm starts a new group):
first pin at y = -2.54, pins in a group 2.54 mm apart, 7.62 mm from the last pin of a group to the first of the next
(the Adom three-grid-step group gap). Each group caption keeps its 2.00 mm offset above the group's first pin. The
body bottom becomes 2.54 mm below the lowest pin; the Value field and the hidden field column below the body move
by the same amount. Value is set to the exact MPN and Footprint to the page's library footprint.
usage: snap_symbol_groups.py in.kicad_sym out.kicad_sym MPN LIB:FOOTPRINT"""
import re, sys, json
src, out, mpn, fp = sys.argv[1:5]
s = open(src).read()
G = 2.54
pin_re = re.compile(r"(\(pin \w+ line )\(at (-?[\d.]+) (-?[\d.]+) (\d+)\)")
cols = {}
for m in pin_re.finditer(s):
cols.setdefault(m.group(2), []).append(float(m.group(3)))
newy = {}; captions = {}
for x, ys in cols.items():
ys = sorted(set(ys), reverse=True)
y_new = -G; prev = None
for y in ys:
if prev is not None:
if prev - y > 2.6:
y_new -= 3 * G
captions[(x, round(y, 2))] = y_new
else:
y_new -= G
else:
captions[(x, round(y, 2))] = y_new
newy[(x, round(y, 2))] = round(y_new, 2); prev = y
s = pin_re.sub(lambda m: f"{m.group(1)}(at {m.group(2)} {newy[(m.group(2), round(float(m.group(3)), 2))]:.2f} {m.group(4)})", s)
first = {}
for (x, y), ny in captions.items():
first[(1 if float(x) > 0 else -1, round(y + 2.0, 2))] = round(ny + 2.0, 2)
def cap(m):
x, y = float(m.group(2)), float(m.group(3)); key = (1 if x > 0 else -1, round(y, 2))
return f"{m.group(1)}(at {m.group(2)} {first.get(key, y):.2f} 0)"
s = re.sub(r'(\(text "[^"]+" )\(at (-?[\d.]+) (-?[\d.]+) 0\)', cap, s)
low = min(newy.values())
rm = re.search(r"\(rectangle \(start (-?[\d.]+) (-?[\d.]+)\) \(end (-?[\d.]+) (-?[\d.]+)\)", s)
old_bottom = float(rm.group(4)); new_bottom = round(low - G, 2); shift = round(new_bottom - old_bottom, 2)
s = s[:rm.start()] + f"(rectangle (start {rm.group(1)} {rm.group(2)}) (end {rm.group(3)} {new_bottom:.2f})" + s[rm.end():]
def prop(m):
name, val, ws, x, y = m.group(1), m.group(2), m.group(3), m.group(4), float(m.group(5))
if name == "Reference": return m.group(0)
return f'(property "{name}" "{val}"{ws}(at {x} {y + shift:.2f}'
s = re.sub(r'\(property "([^"]+)" "([^"]*)"(\s*)\(at (\S+) (-?[\d.]+)', prop, s)
s = re.sub(r'\(property "Value" "[^"]*"', f'(property "Value" "{mpn}"', s, count=1)
s = re.sub(r'\(property "Footprint" "[^"]*"', f'(property "Footprint" "{fp}"', s, count=1)
open(out, "w").write(s)
print(json.dumps({"pin_moves": {f"{k[0]},{k[1]}": v for k, v in newy.items()}, "body_bottom": [old_bottom, new_bottom]}, indent=1))