main
Caleb Publish 0.1.1 69af80b 1d ago
#!/usr/bin/env python3
"""KiCad 10 footprint for TE Connectivity 2-1445098-3 (Micro MATE-N-LOK, 3 position, 3.00 mm, right angle, plastic
holddown) from TE customer drawing C-1445098 rev C (12 Dec 2025), sheet 2 'PCB LAYOUT FOR 3 POSITION' and sheet 1
views. Adom-authored, CC-BY-SA-4.0.

Land pattern (drawing): 3 holes dia 1.02 +0.20/-0 at 3.00 pitch (6.00 span); one dia 3.00 +-0.08 holddown hole centred
on the middle contact, 4.32 from the contact row on the mating-face side. Recommended board thickness 1.57.
Frame: origin = pad-pattern centre (contact 2); contacts on y = 0, circuit 1 at x = -3.00 (TE: circuit 1 is the
right-hand cavity seen from the mating face; the mating face points to -y here, so circuit 1 is on the -x end).
Drill 1.12 = middle of TE's 1.02 .. 1.22 finished-hole band (a 1.02 drill would plate under the minimum).
Body (F.Fab, courtyard): housing 10.00 wide (DIM Y), mating face 8.92 (REF) from the contact row, rear 0.32 behind it,
side latches to +-6.57 (DIM W 13.14), contacts bend out behind the housing to 0.94.
usage: make_fp_2_1445098_3.py <out.kicad_mod>
"""
import sys, uuid

NAME = '2-1445098-3'
FACE, REAR, BULGE = -8.92, 0.32, 0.94
HW, LAT = 5.00, 6.57
PADS = [('1', -3.0), ('2', 0.0), ('3', 3.0)]
PAD, DRILL = 1.80, 1.12
HOLD = (0.0, -4.32, 3.00)


def u():
    return str(uuid.uuid4())


def line(x1, y1, x2, y2, layer, w):
    return (f'\t(fp_line\n\t\t(start {x1:g} {y1:g})\n\t\t(end {x2:g} {y2:g})\n\t\t(stroke (width {w:g}) (type solid))\n'
            f'\t\t(layer "{layer}")\n\t\t(uuid "{u()}")\n\t)\n')


def poly(pts, layer, w, fill):
    p = ' '.join(f'(xy {x:g} {y:g})' for x, y in pts)
    return (f'\t(fp_poly\n\t\t(pts {p})\n\t\t(stroke (width {w:g}) (type solid))\n\t\t(fill {"yes" if fill else "no"})\n'
            f'\t\t(layer "{layer}")\n\t\t(uuid "{u()}")\n\t)\n')


def circle(cx, cy, r, layer, w):
    return (f'\t(fp_circle\n\t\t(center {cx:g} {cy:g})\n\t\t(end {cx + r:g} {cy:g})\n\t\t(stroke (width {w:g}) (type solid))\n'
            f'\t\t(fill no)\n\t\t(layer "{layer}")\n\t\t(uuid "{u()}")\n\t)\n')


def prop(name, val, x, y, layer, hide=False, size=1.0, th=0.15):
    return (f'\t(property "{name}" "{val}"\n\t\t(at {x:g} {y:g} 0)\n\t\t(layer "{layer}")\n' + ('\t\t(hide yes)\n' if hide else '') +
            f'\t\t(uuid "{u()}")\n\t\t(effects\n\t\t\t(font (size {size:g} {size:g}) (thickness {th:g}))\n\t\t)\n\t)\n')


def body_outline(off):
    """Housing + side latches outline, offset outward by `off` (latch: 2.47 deep centred 4.29 behind the face)."""
    yc = FACE + 4.29
    a, b = yc - 2.47 / 2 - off, yc + 2.47 / 2 + off
    return [(-HW - off, FACE - off), (HW + off, FACE - off), (HW + off, a), (LAT + off, a), (LAT + off, b),
            (HW + off, b), (HW + off, REAR + off), (-HW - off, REAR + off), (-HW - off, b), (-LAT - off, b),
            (-LAT - off, a), (-HW - off, a), (-HW - off, FACE - off)]


def main(out):
    s = f'(footprint "{NAME}"\n\t(version 20241229)\n\t(generator "adom")\n\t(generator_version "1.0")\n\t(layer "F.Cu")\n'
    s += ('\t(descr "TE Connectivity 2-1445098-3 Micro MATE-N-LOK header, 3 position, 3.00 mm pitch, right angle, plastic '
          'holddown; land pattern per TE customer drawing C-1445098 rev C sheet 2 (PCB layout for 3 position): 1.02 +0.20/-0 '
          'holes at 3.00, 3.00 +-0.08 holddown hole 4.32 from the contact row; board 1.57 mm")\n')
    s += '\t(tags "TE Micro MATE-N-LOK 1445098 3.00mm right angle header holddown THT")\n'
    s += prop('Reference', 'REF**', 0, FACE - 1.6, 'F.SilkS')
    s += prop('Value', NAME, 0, BULGE + 2.4, 'F.Fab')
    s += prop('Datasheet', 'https://www.te.com/commerce/DocumentDelivery/DDEController?Action=srchrtrv&DocNm=1445098&DocType=Customer+Drawing&DocLang=English&DocFormat=pdf', 0, 0, 'F.Fab', True, 1.27)
    s += prop('Description', 'TE Micro MATE-N-LOK right-angle header, 3 position, 3.00 mm pitch, plastic holddown', 0, 0, 'F.Fab', True, 1.27)
    s += '\t(attr through_hole)\n\t(duplicate_pad_numbers_are_jumpers no)\n'
    # F.Fab body + pin-1 chamfer at the rear corner by circuit 1, holddown hole, contact row
    fab = body_outline(0.0)
    for (x1, y1), (x2, y2) in zip(fab, fab[1:]):
        s += line(x1, y1, x2, y2, 'F.Fab', 0.1)
    s += line(-3.0 - 0.6, REAR, -3.0, REAR - 0.6, 'F.Fab', 0.1) + line(-3.0, REAR - 0.6, -3.0 + 0.6, REAR, 'F.Fab', 0.1)
    s += circle(HOLD[0], HOLD[1], HOLD[2] / 2, 'F.Fab', 0.1)
    s += (f'\t(fp_text user "${{REFERENCE}}"\n\t\t(at 0 {FACE / 2 - 0.5:g} 0)\n\t\t(layer "F.Fab")\n\t\t(uuid "{u()}")\n'
          f'\t\t(effects\n\t\t\t(font (size 1 1) (thickness 0.15))\n\t\t)\n\t)\n')
    # F.SilkS: body outline +0.11, rear edge broken round the pads (0.2 clearance from copper)
    sk = body_outline(0.11)
    rear_y = REAR + 0.11
    for (x1, y1), (x2, y2) in zip(sk, sk[1:]):
        if abs(y1 - rear_y) < 1e-9 and abs(y2 - rear_y) < 1e-9:
            continue
        s += line(x1, y1, x2, y2, 'F.SilkS', 0.12)
    import math
    half = math.sqrt(max(0.0, (PAD / 2 + 0.2) ** 2 - rear_y ** 2))   # pad copper + clearance at the rear silk line
    xs = [-HW - 0.11] + [v for _, x in PADS for v in (x - half, x + half)] + [HW + 0.11]
    for i in range(0, len(xs), 2):
        if xs[i + 1] - xs[i] > 0.15:
            s += line(xs[i], rear_y, xs[i + 1], rear_y, 'F.SilkS', 0.12)
    # pin-1 mark: filled triangle behind contact 1 pointing at it
    s += poly([(-3.0, PAD / 2 + 0.3), (-3.0 - 0.45, PAD / 2 + 0.95), (-3.0 + 0.45, PAD / 2 + 0.95)], 'F.SilkS', 0.12, True)
    # courtyard: body + latches + contact bulge + pads, 0.5 clearance, on a 0.01 grid
    cx0, cx1 = -LAT - 0.5, LAT + 0.5
    cy0, cy1 = FACE - 0.5, max(BULGE, PAD / 2) + 0.5
    for a, b in (((cx0, cy0), (cx1, cy0)), ((cx1, cy0), (cx1, cy1)), ((cx1, cy1), (cx0, cy1)), ((cx0, cy1), (cx0, cy0))):
        s += line(round(a[0], 2), round(a[1], 2), round(b[0], 2), round(b[1], 2), 'F.CrtYd', 0.05)
    # pads
    for n, x in PADS:
        shape = 'roundrect' if n == '1' else 'circle'
        s += (f'\t(pad "{n}" thru_hole {shape}\n\t\t(at {x:g} 0)\n\t\t(size {PAD:g} {PAD:g})\n\t\t(drill {DRILL:g})\n'
              f'\t\t(layers "*.Cu" "*.Mask")\n' + ('\t\t(roundrect_rratio 0.138889)\n' if n == '1' else '') +
              f'\t\t(remove_unused_layers no)\n\t\t(uuid "{u()}")\n\t)\n')
    s += (f'\t(pad "" np_thru_hole circle\n\t\t(at {HOLD[0]:g} {HOLD[1]:g})\n\t\t(size {HOLD[2]:g} {HOLD[2]:g})\n'
          f'\t\t(drill {HOLD[2]:g})\n\t\t(layers "*.Cu" "*.Mask")\n\t\t(uuid "{u()}")\n\t)\n')
    s += ('\t(embedded_fonts no)\n\t(model "${KIPRJMOD}/2-1445098-3.step"\n\t\t(offset\n\t\t\t(xyz 0 0 0)\n\t\t)\n\t\t(scale\n'
          '\t\t\t(xyz 1 1 1)\n\t\t)\n\t\t(rotate\n\t\t\t(xyz 0 0 0)\n\t\t)\n\t)\n)\n')
    open(out, 'w').write(s)


if __name__ == '__main__':
    main(sys.argv[1])