v6 T9 power input (submodule b92a187) + T9 script
This commit is contained in:
parent
a29f65d953
commit
0823de6c29
@ -1 +1 @@
|
|||||||
Subproject commit ab2e67ab20986ff3068355eb97bc2acdfd0e92bb
|
Subproject commit b92a18710b694d80c59c840183378a00efddc3ac
|
||||||
340
scripts/2026-08-31_v6_T9_pwr_input.py
Normal file
340
scripts/2026-08-31_v6_T9_pwr_input.py
Normal file
@ -0,0 +1,340 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""v6 T9 - Block T: on-board vehicle power input 9-36V -> 5V/3A (replaces external
|
||||||
|
Mean Well SD-15B-5, 18-36V 5V/3A).
|
||||||
|
|
||||||
|
Chain: /24V_IN (P1, existing SMBJ33A D10 at entry) -> F2 2A fuse -> Q23 IRFR5305
|
||||||
|
reverse-polarity P-FET (D=battery, S=load; R119 100k G->GND, D33 BZX84C15 G->S clamp)
|
||||||
|
-> /VIN_PROT (SMCJ33A D32 + 2x2.2uF/100V + 100uF/50V bulk) -> U25 TPS54360B (60V 3.5A,
|
||||||
|
600kHz) -> L22 SRP1265A-100M 10uH -> /VEH5V (LTC4040 input; P2 Meanwell jack stays as
|
||||||
|
bench backup - populate one source at a time).
|
||||||
|
|
||||||
|
Values = TI TPS54360B datasheet 5V/3.5A design example: RT 162k (600kHz), FB 53.6k/10.2k
|
||||||
|
(5.00V), COMP 13k+6.8nF+39pF, boot 100nF, catch B560C, Cout 2x47uF. EN floating =
|
||||||
|
enabled (int. UVLO 4.3V, max cranking ride-through; Vin(min) for 5V reg = 5.56V);
|
||||||
|
optional UVLO divider R124 523k / R125 84.5k fitted DNP.
|
||||||
|
|
||||||
|
Also REPAIRS the corrupted D_Zener_ANK pin numbers (@@@A1@@/@@@K3@@ -> 1/3) so DzG1
|
||||||
|
finally connects to its SOT-23 pads, and re-adds the RF / PWR_MODEM netclasses that were
|
||||||
|
lost from the .kicad_pro, plus new PWR_IN class.
|
||||||
|
|
||||||
|
Prereq: easyeda2kicad --full --lcsc_id C840531 (Bourns SRP1265A-100M) into Drogheda-v6
|
||||||
|
libs, so the L22 footprint exists. Run with --tbd to skip that check (footprint TBD).
|
||||||
|
|
||||||
|
Usage: python3 2026-08-31_v6_T9_pwr_input.py [--apply] [--tbd]
|
||||||
|
"""
|
||||||
|
import os, sys, shutil, uuid, re, json, glob
|
||||||
|
|
||||||
|
KI = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '03-Architecture-Hardware', 'kicad')
|
||||||
|
SCH = os.path.join(KI, 'hbox-watchdog-v6.kicad_sch')
|
||||||
|
DSYM= os.path.join(KI, 'Drogheda-sym.kicad_sym')
|
||||||
|
PRO = os.path.join(KI, 'hbox-watchdog-v6.kicad_pro')
|
||||||
|
APPLY = '--apply' in sys.argv
|
||||||
|
TBD = '--tbd' in sys.argv
|
||||||
|
ROOT = '/561403b3-895e-4153-a7be-3876ae930d43'
|
||||||
|
NC = '<NC>'
|
||||||
|
|
||||||
|
def f(v):
|
||||||
|
v = 0.0 if abs(v) < 1e-9 else v
|
||||||
|
return '%.10g' % v
|
||||||
|
|
||||||
|
def bal(t):
|
||||||
|
d=0; instr=False; esc=False
|
||||||
|
for ch in t:
|
||||||
|
if esc: esc=False; continue
|
||||||
|
if ch=='\\': esc=True; continue
|
||||||
|
if ch=='"': instr = not instr; continue
|
||||||
|
if instr: continue
|
||||||
|
if ch=='(': d+=1
|
||||||
|
elif ch==')': d-=1
|
||||||
|
return d
|
||||||
|
|
||||||
|
def span_from(text, i):
|
||||||
|
d=0; instr=False; esc=False; j=i
|
||||||
|
while j < len(text):
|
||||||
|
ch=text[j]
|
||||||
|
if esc: esc=False
|
||||||
|
elif ch=='\\': esc=True
|
||||||
|
elif ch=='"': instr = not instr
|
||||||
|
elif not instr:
|
||||||
|
if ch=='(': d+=1
|
||||||
|
elif ch==')':
|
||||||
|
d-=1
|
||||||
|
if d==0: return j+1
|
||||||
|
j+=1
|
||||||
|
raise ValueError('unbalanced')
|
||||||
|
|
||||||
|
PIN_RE2= re.compile(r'\(pin \w+ \w+\s*\n\s*\(at ([-\d.]+) ([-\d.]+) (\d+)\)(?:(?!\(pin ).)*?\(number "([^"]+)"', re.S)
|
||||||
|
|
||||||
|
def libpins(libsrc, name):
|
||||||
|
i = libsrc.find('(symbol "%s"' % name)
|
||||||
|
if i < 0: return None
|
||||||
|
j = libsrc.find('\n (symbol "', i+10)
|
||||||
|
if j < 0: j = libsrc.find('\n\t\t(symbol "', i+10)
|
||||||
|
body = libsrc[i: j if j>0 else len(libsrc)]
|
||||||
|
pins = PIN_RE2.findall(body)
|
||||||
|
return [(num, float(x), float(y)) for x,y,rot,num in pins]
|
||||||
|
|
||||||
|
sch = open(SCH, encoding='utf-8').read()
|
||||||
|
dsym = open(DSYM, encoding='utf-8').read()
|
||||||
|
|
||||||
|
# UUID integrity guard: any change to the set of UUIDs already present = abort at write
|
||||||
|
uuids_before = set(re.findall(r'\(uuid "([0-9a-f-]+)"\)', sch))
|
||||||
|
|
||||||
|
# ---------- 0a. repair corrupted D_Zener_ANK pin numbers (cache + DzG1 instance) ----------
|
||||||
|
zfix = sch.count('"@@@A1@@"') + sch.count('"@@@K3@@"')
|
||||||
|
sch = sch.replace('"@@@A1@@"', '"1"').replace('"@@@K3@@"', '"3"')
|
||||||
|
|
||||||
|
# ---------- 0b. new symbols into Drogheda-sym ----------
|
||||||
|
def simple_sym(name, desc, fp, pins, w=7.62, h=8.89):
|
||||||
|
s = ' (symbol "%s"\n (exclude_from_sim no)\n (in_bom yes)\n (on_board yes)\n' % name
|
||||||
|
for pn,pv,px,py,hide in [('Reference','U',0,h+3.81,''),('Value',name,0,h+1.27,''),
|
||||||
|
('Footprint',fp,0,-h-2.54,'\n (hide yes)'),
|
||||||
|
('Datasheet','~',0,-h-5.08,'\n (hide yes)'),
|
||||||
|
('Description',desc,0,-h-7.62,'\n (hide yes)')]:
|
||||||
|
s += (' (property "%s" "%s"\n (at %s %s 0)%s\n (effects (font (size 1.27 1.27)))\n )\n'
|
||||||
|
) % (pn,pv,f(px),f(py),hide)
|
||||||
|
s += (' (symbol "%s_0_1"\n (rectangle\n (start %s %s)\n (end %s %s)\n'
|
||||||
|
' (stroke (width 0.254) (type default))\n (fill (type background))\n )\n )\n'
|
||||||
|
' (symbol "%s_1_1"\n') % (name,f(-w),f(h),f(w),f(-h),name)
|
||||||
|
for num,nm,tp,px,py,rot in pins:
|
||||||
|
s += (' (pin %s line\n (at %s %s %d)\n (length 5.08)\n'
|
||||||
|
' (name "%s"\n (effects (font (size 1.27 1.27)))\n )\n'
|
||||||
|
' (number "%s"\n (effects (font (size 1.27 1.27)))\n )\n )\n') % (tp,f(px),f(py),rot,nm,num)
|
||||||
|
s += ' )\n )\n'
|
||||||
|
return s
|
||||||
|
|
||||||
|
TPS_PINS=[('2','VIN','power_in',-12.7,5.08,0),('3','EN','input',-12.7,0,0),('4','RT/CLK','passive',-12.7,-5.08,0),
|
||||||
|
('1','BOOT','passive',12.7,5.08,180),('8','SW','passive',12.7,2.54,180),
|
||||||
|
('5','FB','passive',12.7,-2.54,180),('6','COMP','passive',12.7,-5.08,180),
|
||||||
|
('7','GND','power_in',-2.54,-13.97,90),('9','EP','passive',2.54,-13.97,90)]
|
||||||
|
TPS = simple_sym('TPS54360B','TI 60V 3.5A step-down, SOIC-8-EP (DDA). LCSC C524806. 4.5-60V in, 0.8V ref.',
|
||||||
|
'Drogheda-v6:SO-8_L4.9-W3.9-P1.27-LS6.0-BL-EP', TPS_PINS)
|
||||||
|
FUSE_PINS=[('1','~','passive',0,8.89,270),('2','~','passive',0,-8.89,90)]
|
||||||
|
FUS = simple_sym('Fuse_CER','Ceramic SMD fuse (one-time). Distinct from PPTC Polyfuse.',
|
||||||
|
'Fuse:Fuse_1812_4532Metric', FUSE_PINS, w=2.54, h=3.81)
|
||||||
|
|
||||||
|
added_syms=[]
|
||||||
|
for name, body in (('TPS54360B',TPS),('Fuse_CER',FUS)):
|
||||||
|
if '(symbol "%s"' % name not in dsym:
|
||||||
|
end = dsym.rstrip(); assert end.endswith(')')
|
||||||
|
dsym = end[:-1].rstrip('\n') + '\n' + body + ')\n'
|
||||||
|
added_syms.append(name)
|
||||||
|
|
||||||
|
# ---------- 1. cache new symbols into schematic lib_symbols ----------
|
||||||
|
def grab(libsrc, name, prefix):
|
||||||
|
i = libsrc.find(' (symbol "%s"\n' % name)
|
||||||
|
if i < 0: sys.exit('symbol %s not found in source lib' % name)
|
||||||
|
j = libsrc.index('(', i)
|
||||||
|
k = span_from(libsrc, j)
|
||||||
|
return libsrc[j:k].replace('(symbol "%s"' % name, '(symbol "%s:%s"' % (prefix,name), 1)
|
||||||
|
|
||||||
|
cache_add = ''
|
||||||
|
for nm in ('TPS54360B','Fuse_CER'):
|
||||||
|
if '(symbol "Drogheda-sym:%s"' % nm not in sch:
|
||||||
|
cache_add += '\n\t\t' + grab(dsym, nm, 'Drogheda-sym')
|
||||||
|
m = re.search(r'\n\t\(lib_symbols\n', sch)
|
||||||
|
k = span_from(sch, sch.index('(', m.start()))
|
||||||
|
sch = sch[:k-1] + cache_add + '\n\t' + sch[k-1:]
|
||||||
|
|
||||||
|
lib_cached = sch.split('(lib_symbols',1)[1]
|
||||||
|
def cachedpins(name): return libpins(lib_cached, name)
|
||||||
|
|
||||||
|
# ---------- 2. L22 footprint: resolve from Drogheda-v6.pretty ----------
|
||||||
|
l22_fp = 'Drogheda-v6:IND-SMD_SRP1265A_TBD'
|
||||||
|
hits = [p for p in glob.glob(os.path.join(KI,'Drogheda-v6.pretty','*.kicad_mod'))
|
||||||
|
if re.search(r'1265|SRP|IND-SMD_L13', os.path.basename(p), re.I)]
|
||||||
|
if hits:
|
||||||
|
l22_fp = 'Drogheda-v6:' + os.path.basename(hits[0])[:-len('.kicad_mod')]
|
||||||
|
elif not TBD:
|
||||||
|
sys.exit('L22 footprint not found in Drogheda-v6.pretty - run on the Mac first:\n'
|
||||||
|
' easyeda2kicad --full --lcsc_id C840531 --output ~/Documents/Claude/Projects/Drogheda/03-Architecture-Hardware/kicad/Drogheda-v6\n'
|
||||||
|
'or re-run this script with --tbd to use a placeholder footprint.')
|
||||||
|
|
||||||
|
# ---------- 3. guards: refdes free? nets/labels/wires/pins ----------
|
||||||
|
inst = {}
|
||||||
|
for b in re.finditer(r'\n\t\(symbol\n(?:(?!\n\t\(symbol\n).)*', sch, re.S):
|
||||||
|
blk=b.group(0)
|
||||||
|
r=re.search(r'\(property "Reference" "([^"]+)"',blk); l=re.search(r'\(lib_id "([^"]+)"',blk); a=re.search(r'\(at ([-\d.]+) ([-\d.]+) (\d+)\)',blk)
|
||||||
|
if r and l and a: inst[r.group(1)]=(l.group(1),float(a.group(1)),float(a.group(2)))
|
||||||
|
NEWREFS = ['F2','Q23','D32','D33','D34','L22','U25','PF19',
|
||||||
|
'R119','R120','R121','R122','R123','R124','R125',
|
||||||
|
'C149','C150','C151','C152','C153','C154','C155','C156']
|
||||||
|
clash = [r for r in NEWREFS if r in inst]
|
||||||
|
if clash: sys.exit('refdes already in use: %s' % clash)
|
||||||
|
|
||||||
|
def find_labels(text):
|
||||||
|
d={}
|
||||||
|
for m in re.finditer(r'\n\t\((label|global_label) "([^"]+)"\s*\n\s*\(at ([-\d.]+) ([-\d.]+) (\d+)\)', text):
|
||||||
|
d[(round(float(m.group(3)),3), round(float(m.group(4)),3))] = (m.group(2), m.start()+1)
|
||||||
|
return d
|
||||||
|
wire_vts = set()
|
||||||
|
for m in re.finditer(r'\(wire\s*\n\s*\(pts\s*\n((?:\s*\(xy [-\d.]+ [-\d.]+\)\s*\n?)+)', sch):
|
||||||
|
for a,b in re.findall(r'\(xy ([-\d.]+) ([-\d.]+)\)', m.group(1)):
|
||||||
|
wire_vts.add((round(float(a),3), round(float(b),3)))
|
||||||
|
pin_coords = set()
|
||||||
|
for ref,(lb_,X_,Y_) in inst.items():
|
||||||
|
for num,px,py in (cachedpins(lb_) or []):
|
||||||
|
pin_coords.add((round(X_+px,3), round(Y_-py,3)))
|
||||||
|
|
||||||
|
# ---------- 4. build additions ----------
|
||||||
|
add = ''
|
||||||
|
nlab = nnc = 0
|
||||||
|
newlabels = []
|
||||||
|
def add_lab(net,x,y,rot,just):
|
||||||
|
global add,nlab
|
||||||
|
add += ('\n\t(label "%s"\n\t\t(at %s %s %d)\n\t\t(effects\n\t\t\t(font\n\t\t\t\t(size 1.27 1.27)\n'
|
||||||
|
'\t\t\t)\n\t\t\t(justify %s)\n\t\t)\n\t\t(uuid "%s")\n\t)') % (net,f(x),f(y),rot,just,uuid.uuid4())
|
||||||
|
nlab += 1; newlabels.append((net,round(x,3),round(y,3)))
|
||||||
|
def add_nc(x,y):
|
||||||
|
global add,nnc
|
||||||
|
add += '\n\t(no_connect\n\t\t(at %s %s)\n\t\t(uuid "%s")\n\t)' % (f(x),f(y),uuid.uuid4())
|
||||||
|
nnc += 1
|
||||||
|
|
||||||
|
def mksym(lib_id, ref, val, x, y, fp, npins, lcsc='', dnp=False):
|
||||||
|
props=[('Reference',ref,x-3,y-3,''),('Value',val,x+3,y-3,''),('Footprint',fp,x,y,'\n\t\t\t(hide yes)'),
|
||||||
|
('Datasheet','~',x,y,'\n\t\t\t(hide yes)'),('Description','',x,y,'\n\t\t\t(hide yes)')]
|
||||||
|
if lcsc: props.append(('LCSC',lcsc,x,y,'\n\t\t\t(hide yes)'))
|
||||||
|
p=''
|
||||||
|
for nm,v,px,py,hide in props:
|
||||||
|
p += ('\t\t(property "%s" "%s"\n\t\t\t(at %s %s 0)%s\n\t\t\t(show_name no)\n\t\t\t(do_not_autoplace no)\n'
|
||||||
|
'\t\t\t(effects\n\t\t\t\t(font\n\t\t\t\t\t(size 1.27 1.27)\n\t\t\t\t)\n\t\t\t)\n\t\t)\n') % (nm,v,f(px),f(py),hide)
|
||||||
|
pn=''.join('\t\t(pin "%s"\n\t\t\t(uuid "%s")\n\t\t)\n' % (n,uuid.uuid4()) for n in npins)
|
||||||
|
return ('\n\t(symbol\n\t\t(lib_id "%s")\n\t\t(at %s %s 0)\n\t\t(unit 1)\n\t\t(body_style 1)\n'
|
||||||
|
'\t\t(exclude_from_sim no)\n\t\t(in_bom yes)\n\t\t(on_board yes)\n\t\t(in_pos_files yes)\n'
|
||||||
|
'\t\t(dnp %s)\n\t\t(uuid "%s")\n%s%s\t\t(instances\n\t\t\t(project "hbox-watchdog-v6"\n'
|
||||||
|
'\t\t\t\t(path "%s"\n\t\t\t\t\t(reference "%s")\n\t\t\t\t\t(unit 1)\n\t\t\t\t)\n\t\t\t)\n\t\t)\n\t)'
|
||||||
|
) % (lib_id,f(x),f(y),'yes' if dnp else 'no',uuid.uuid4(),p,pn,ROOT,ref)
|
||||||
|
|
||||||
|
def orient(px,py):
|
||||||
|
if abs(px) < 0.01: return 90,'left bottom'
|
||||||
|
return (0,'left bottom') if px>0 else (180,'right bottom')
|
||||||
|
|
||||||
|
def place(lib, ref, val, x, y, fp, nets, lcsc='', dnp=False, src='cache'):
|
||||||
|
"""nets: dict pin-number -> net (or NC)."""
|
||||||
|
pp = cachedpins(lib) if src=='cache' else libpins(dsym, lib.split(':')[1])
|
||||||
|
if not pp: sys.exit('no pins for %s' % lib)
|
||||||
|
global add
|
||||||
|
add += mksym(lib,ref,val,x,y,fp,[num for num,_,_ in pp],lcsc,dnp=dnp)
|
||||||
|
for num,px,py in pp:
|
||||||
|
rot,just = orient(px,py)
|
||||||
|
n = nets[num]
|
||||||
|
if n == NC: add_nc(x+px,y-py)
|
||||||
|
else: add_lab(n,x+px,y-py,rot,just)
|
||||||
|
|
||||||
|
# ----- Block T title -----
|
||||||
|
add += ('\n\t(text "BLOCK T - VEHICLE POWER INPUT 9-36V -> 5V/3A (replaces Mean Well SD-15B-5). '
|
||||||
|
'F2+Q23 rev-pol+SMCJ33A -> TPS54360B 600kHz -> VEH5V. P2 = bench backup, one source at a time."\n'
|
||||||
|
'\t\t(exclude_from_sim no)\n\t\t(at 40 322 0)\n\t\t(effects\n\t\t\t(font\n\t\t\t\t(size 1.6 1.6)\n'
|
||||||
|
'\t\t\t)\n\t\t\t(justify left bottom)\n\t\t)\n\t\t(uuid "%s")\n\t)') % uuid.uuid4()
|
||||||
|
|
||||||
|
# ----- protection front end -----
|
||||||
|
place('Drogheda-sym:Fuse_CER','F2','2A/63V-slow-1812',55.0,345.0,'Fuse:Fuse_1812_4532Metric',
|
||||||
|
{'1':'24V_IN','2':'VIN_FUSED'},'TBD-2A-1812',src='dsym')
|
||||||
|
place('Device:Q_PMOS_GDS','Q23','IRFR5305',72.0,345.0,'Package_TO_SOT_SMD:TO-252-2',
|
||||||
|
{'1':'Q23_GATE','2':'VIN_FUSED','3':'VIN_PROT'})
|
||||||
|
place('Device:R','R119','100k',85.0,352.0,'Resistor_SMD:R_0603_1608Metric',
|
||||||
|
{'1':'Q23_GATE','2':'GND'})
|
||||||
|
place('Device:D_Zener_ANK','D33','BZX84C15',92.0,352.0,'Package_TO_SOT_SMD:SOT-23',
|
||||||
|
{'1':'Q23_GATE','3':'VIN_PROT'}) # repaired ANK symbol: 1=A (gate), 3=K (source)
|
||||||
|
place('Device:D_TVS','D32','SMCJ33A',100.0,352.0,'Diode_SMD:D_SMC',
|
||||||
|
{'1':'VIN_PROT','2':'GND'},'C699039')
|
||||||
|
place('Device:C','C149','2.2uF/100V',108.0,352.0,'Capacitor_SMD:C_1210_3225Metric',
|
||||||
|
{'1':'VIN_PROT','2':'GND'})
|
||||||
|
place('Device:C','C150','2.2uF/100V',114.0,352.0,'Capacitor_SMD:C_1210_3225Metric',
|
||||||
|
{'1':'VIN_PROT','2':'GND'})
|
||||||
|
place('Device:C_Polarized','C151','100uF/50V',121.0,352.0,'Capacitor_SMD:CP_Elec_8x10',
|
||||||
|
{'1':'VIN_PROT','2':'GND'})
|
||||||
|
|
||||||
|
# ----- buck -----
|
||||||
|
place('Drogheda-sym:TPS54360B','U25','TPS54360B',145.0,348.0,
|
||||||
|
'Drogheda-v6:SO-8_L4.9-W3.9-P1.27-LS6.0-BL-EP',
|
||||||
|
{'1':'BOOT_PWRIN','2':'VIN_PROT','3':'EN_PWRIN','4':'RT_PWRIN','5':'FB_PWRIN',
|
||||||
|
'6':'COMP_PWRIN','7':'GND','8':'SW_PWRIN','9':'GND'},'C524806',src='dsym')
|
||||||
|
place('Device:C','C152','100nF',162.0,338.0,'Capacitor_SMD:C_0603_1608Metric',
|
||||||
|
{'1':'BOOT_PWRIN','2':'SW_PWRIN'})
|
||||||
|
place('Device:D_Schottky','D34','B560C',166.0,352.0,'Diode_SMD:D_SMC',
|
||||||
|
{'1':'SW_PWRIN','2':'GND'},'C85100') # 1=K on SW, 2=A on GND
|
||||||
|
place('Device:L','L22','10uH/SRP1265A',174.0,348.0,l22_fp,
|
||||||
|
{'1':'SW_PWRIN','2':'VEH5V'},'C840531')
|
||||||
|
place('Device:C','C153','47uF/16V',182.0,352.0,'Capacitor_SMD:C_1210_3225Metric',
|
||||||
|
{'1':'VEH5V','2':'GND'})
|
||||||
|
place('Device:C','C154','47uF/16V',188.0,352.0,'Capacitor_SMD:C_1210_3225Metric',
|
||||||
|
{'1':'VEH5V','2':'GND'})
|
||||||
|
|
||||||
|
# ----- control passives -----
|
||||||
|
place('Device:R','R120','162k/1%',120.0,368.0,'Resistor_SMD:R_0603_1608Metric',
|
||||||
|
{'1':'RT_PWRIN','2':'GND'})
|
||||||
|
place('Device:R','R124','523k/1%-DNP',128.0,368.0,'Resistor_SMD:R_0603_1608Metric',
|
||||||
|
{'1':'VIN_PROT','2':'EN_PWRIN'},dnp=True)
|
||||||
|
place('Device:R','R125','84.5k/1%-DNP',134.0,368.0,'Resistor_SMD:R_0603_1608Metric',
|
||||||
|
{'1':'EN_PWRIN','2':'GND'},dnp=True)
|
||||||
|
place('Device:R','R123','13k',140.0,368.0,'Resistor_SMD:R_0603_1608Metric',
|
||||||
|
{'1':'COMP_PWRIN','2':'COMP_PWRIN_RC'})
|
||||||
|
place('Device:C','C155','6.8nF',146.0,368.0,'Capacitor_SMD:C_0402_1005Metric',
|
||||||
|
{'1':'COMP_PWRIN_RC','2':'GND'})
|
||||||
|
place('Device:C','C156','39pF',152.0,368.0,'Capacitor_SMD:C_0402_1005Metric',
|
||||||
|
{'1':'COMP_PWRIN','2':'GND'})
|
||||||
|
place('Device:R','R121','53.6k/1%',160.0,368.0,'Resistor_SMD:R_0603_1608Metric',
|
||||||
|
{'1':'VEH5V','2':'FB_PWRIN'})
|
||||||
|
place('Device:R','R122','10.2k/1%',166.0,368.0,'Resistor_SMD:R_0603_1608Metric',
|
||||||
|
{'1':'FB_PWRIN','2':'GND'})
|
||||||
|
|
||||||
|
# ----- power flag on the buck input net -----
|
||||||
|
pf = cachedpins('power:PWR_FLAG')
|
||||||
|
add += mksym('power:PWR_FLAG','PF19','PWR_FLAG',60.0,332.0,'',[num for num,_,_ in pf])
|
||||||
|
add_lab('VIN_PROT',60.0+pf[0][1],332.0-pf[0][2],90,'left bottom')
|
||||||
|
|
||||||
|
# ---------- 5. collision check ----------
|
||||||
|
existing = set(find_labels(sch).keys()) | wire_vts | pin_coords
|
||||||
|
coll = [(n,x,y) for n,x,y in newlabels if (x,y) in existing]
|
||||||
|
if coll: sys.exit('LABEL COLLISION with existing labels/wires/pins: %s' % coll[:8])
|
||||||
|
|
||||||
|
end = sch.rstrip(); assert end.endswith(')')
|
||||||
|
sch = end[:-1].rstrip('\n') + add + '\n)\n'
|
||||||
|
|
||||||
|
# UUID integrity: all pre-existing uuids still present
|
||||||
|
uuids_after = set(re.findall(r'\(uuid "([0-9a-f-]+)"\)', sch))
|
||||||
|
lost = uuids_before - uuids_after
|
||||||
|
if lost: sys.exit('REFUSING: %d pre-existing UUIDs vanished' % len(lost))
|
||||||
|
|
||||||
|
# ---------- 6. .kicad_pro netclasses ----------
|
||||||
|
pro = json.load(open(PRO, encoding='utf-8'))
|
||||||
|
ns = pro.setdefault('net_settings', {})
|
||||||
|
classes = ns.setdefault('classes', [])
|
||||||
|
have = {c.get('name') for c in classes}
|
||||||
|
def clone_base():
|
||||||
|
for c in classes:
|
||||||
|
if c.get('name')=='PWR_MID': return dict(c)
|
||||||
|
return dict(classes[0])
|
||||||
|
pro_added=[]
|
||||||
|
for nm, tw, vd in (('RF',0.35,0.4),('PWR_MODEM',1.5,0.6),('PWR_IN',1.5,0.6)):
|
||||||
|
if nm not in have:
|
||||||
|
c = clone_base(); c['name']=nm; c['track_width']=tw
|
||||||
|
if 'via_diameter' in c and vd: c['via_diameter']=max(c.get('via_diameter',vd), vd)
|
||||||
|
classes.append(c); pro_added.append(nm)
|
||||||
|
pats = ns.setdefault('netclass_patterns', [])
|
||||||
|
patset = {(p['netclass'],p['pattern']) for p in pats}
|
||||||
|
WANT = ([('RF',n) for n in ('/RF_GNSS','/RF_ANT_GNSS','/RF_LTE','/RF_ANT_LTE')] +
|
||||||
|
[('PWR_MODEM',n) for n in ('/VBAT_MODEM','/VIN_MODEM','/SW_MODEM')] +
|
||||||
|
[('PWR_IN',n) for n in ('/VIN_FUSED','/VIN_PROT','/SW_PWRIN')])
|
||||||
|
pro_pats=0
|
||||||
|
for cls,net in WANT:
|
||||||
|
if (cls,net) not in patset:
|
||||||
|
pats.append({'netclass':cls,'pattern':net}); pro_pats+=1
|
||||||
|
|
||||||
|
# ---------- report ----------
|
||||||
|
print('D_Zener_ANK pin-number repairs (@@@ -> 1/3): %d replacements (expect 4: 2 cache + 2 DzG1 instance)' % zfix)
|
||||||
|
print('new lib symbols in Drogheda-sym: %s' % (added_syms or 'none (already present)'))
|
||||||
|
print('L22 footprint: %s' % l22_fp)
|
||||||
|
print('symbols placed: F2 Q23 D32 D33 D34 L22 U25 PF19 + 15 passives (R124/R125 DNP)')
|
||||||
|
print('labels: %d no_connects: %d' % (nlab,nnc))
|
||||||
|
print('netclasses added to pro: %s ; patterns added: %d' % (pro_added or 'none', pro_pats))
|
||||||
|
print('paren: sch=%d dsym=%d' % (bal(sch),bal(dsym)))
|
||||||
|
if not APPLY:
|
||||||
|
print('\nDRY RUN - nothing written. Re-run with --apply.'); sys.exit(0)
|
||||||
|
if bal(sch)!=0 or bal(dsym)!=0: sys.exit('REFUSING: paren imbalance')
|
||||||
|
shutil.copy2(SCH,SCH+'.T9bak'); shutil.copy2(DSYM,DSYM+'.T9bak'); shutil.copy2(PRO,PRO+'.T9bak')
|
||||||
|
open(SCH,'w',encoding='utf-8').write(sch)
|
||||||
|
open(DSYM,'w',encoding='utf-8').write(dsym)
|
||||||
|
json.dump(pro, open(PRO,'w',encoding='utf-8'), indent=2)
|
||||||
|
print('\nAPPLIED. Backups: *.T9bak')
|
||||||
Loading…
Reference in New Issue
Block a user