Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
"""Silkscreen-over-pad/via check (G1) — no silkscreen text on a pad or via.
Silk ink on a pad won't solder / can lift; on a via it wicks. `kicad-cli` DRC's `silk_over_copper`
is the full geometric ground truth (used in the routing gate); this is a fast, board-file-direct
check that catches the common case — a reference-designator or graphic text anchored on top of a
pad — by testing each silk text anchor against every pad's rectangle (absolute footprint + pad
position; rotation ignored, a conservative approximation).
Pure Python 3 standard library.
"""
from . import kicad_sexp as K
from .findings import finding
def _pads_and_silk(board):
root = K.parse(K._load(board))
if K._tag(root) != "kicad_pcb":
raise ValueError("not a .kicad_pcb")
pads, silk = [], []
for fp in K._children(root, "footprint"):
fat = K._first(fp, "at")
fx, fy = (float(fat[1]), float(fat[2])) if fat and len(fat) >= 3 else (0.0, 0.0)
ref = K._footprint_ref(fp) or "?"
for pad in K._children(fp, "pad"):
pat, size = K._first(pad, "at"), K._first(pad, "size")
if pat and len(pat) >= 3:
sw, sh = ((float(size[1]), float(size[2])) if size and len(size) >= 3 else (0.5, 0.5))
pads.append((fx + float(pat[1]), fy + float(pat[2]), sw, sh, ref,
pad[1] if len(pad) > 1 else "?"))
for ft in K._children(fp, "fp_text"):
layer, tat = K._first(ft, "layer"), K._first(ft, "at")
if layer and len(layer) >= 2 and "SilkS" in layer[1] and tat and len(tat) >= 3:
silk.append((fx + float(tat[1]), fy + float(tat[2]), ft[2] if len(ft) > 2 else "", ref))
for gt in K._children(root, "gr_text"):
layer, tat = K._first(gt, "layer"), K._first(gt, "at")
if layer and len(layer) >= 2 and "SilkS" in layer[1] and tat and len(tat) >= 3:
silk.append((float(tat[1]), float(tat[2]), gt[1] if len(gt) > 1 else "", "<board>"))
return pads, silk
def run(board):
pads, silk = _pads_and_silk(board)
V = []
for sx, sy, txt, sref in silk:
for px, py, sw, sh, pref, pname in pads:
if abs(sx - px) <= sw / 2 and abs(sy - py) <= sh / 2:
V.append(finding(detector="silk", rule_id="silk_over_pad", category="manufacturability",
severity="error", confidence="deterministic", evidence_source="geometry",
summary=f"silk text '{txt or sref}' overlaps pad {pref}.{pname}",
where=f"{pref}.{pname}", components=[pref],
recommendation="move the silkscreen text off the pad"))
break
return V
7315b96d0This file is pinned to the selected release. Download the original to open it in your design tool.