mirror of
https://github.com/whowechina/popn_pico.git
synced 2025-03-03 16:43:49 +01:00
208 lines
5.8 KiB
Python
208 lines
5.8 KiB
Python
|
"""
|
||
|
build_mod_picoblade.py
|
||
|
Copyright 2019 Adam Greig
|
||
|
Licensed under the MIT licence, see LICENSE file for details.
|
||
|
|
||
|
Generate foorprints for Molex Picoblade connectors.
|
||
|
"""
|
||
|
|
||
|
from __future__ import print_function, division
|
||
|
|
||
|
import os
|
||
|
import sys
|
||
|
import time
|
||
|
import math
|
||
|
import argparse
|
||
|
|
||
|
from sexp import parse as sexp_parse, generate as sexp_generate
|
||
|
from kicad_mod import fp_line, fp_text, pad, draw_square, model
|
||
|
|
||
|
|
||
|
# Settings ====================================================================
|
||
|
|
||
|
# Courtyard clearance
|
||
|
# Use 0.25 for IPC nominal and 0.10 for IPC least
|
||
|
ctyd_gap = 0.25
|
||
|
|
||
|
# Courtyard grid
|
||
|
ctyd_grid = 0.05
|
||
|
|
||
|
# Courtyard line width
|
||
|
ctyd_width = 0.01
|
||
|
|
||
|
# Silk line width
|
||
|
silk_width = 0.15
|
||
|
|
||
|
# Fab layer line width
|
||
|
fab_width = 0.01
|
||
|
|
||
|
# Ref/Val font size (width x height)
|
||
|
font_size = (1.0, 1.0)
|
||
|
|
||
|
# Ref/Val font thickness
|
||
|
font_thickness = 0.15
|
||
|
|
||
|
# Ref/Val font spacing from centre to top/bottom edge
|
||
|
font_halfheight = 0.7
|
||
|
|
||
|
|
||
|
# End Settings ================================================================
|
||
|
|
||
|
|
||
|
def top_smd_refs(name):
|
||
|
out = []
|
||
|
ctyd_h = 3.0 + 0.6 + 1.3 + 2*ctyd_gap
|
||
|
ctyd_y = ctyd_h/2 - 1.3/2 - ctyd_gap
|
||
|
y = ctyd_h / 2.0 + font_halfheight
|
||
|
out.append(fp_text("reference", "REF**", (0, -y+ctyd_y),
|
||
|
"F.Fab", font_size, font_thickness))
|
||
|
out.append(fp_text("value", name, (0, y+ctyd_y),
|
||
|
"F.Fab", font_size, font_thickness))
|
||
|
return out
|
||
|
|
||
|
|
||
|
def top_smd_pads(pins):
|
||
|
x = -(pins-1)/2 * 1.25
|
||
|
pads = []
|
||
|
for pin in range(pins):
|
||
|
pads.append(pad(pin+1, "smd", "rect", (x, 0), [0.8, 1.3],
|
||
|
["F.Cu", "F.Mask", "F.Paste"]))
|
||
|
x += 1.25
|
||
|
return pads
|
||
|
|
||
|
|
||
|
def top_smd_mount(pins):
|
||
|
x = -(pins-1)/2 * 1.25 - 3.6 + 2.1/2
|
||
|
out = []
|
||
|
for xx in (x, -x):
|
||
|
out.append(pad("", "smd", "rect", (xx, 0.6+3.0/2+1.3/2), (2.1, 3.0),
|
||
|
["F.Cu", "F.Mask", "F.Paste"]))
|
||
|
return out
|
||
|
|
||
|
|
||
|
def top_smd_silk(pins):
|
||
|
out = []
|
||
|
w = silk_width
|
||
|
lyr = "F.SilkS"
|
||
|
box_w = (pins-1)*1.25 + 2*3.6 - 2*2.1 - silk_width
|
||
|
box_h = 3.5 # XXX
|
||
|
box_y = box_h/2 + 0.2
|
||
|
nw, ne, se, sw, _ = draw_square(box_w, box_h, (0, box_y), lyr, w)
|
||
|
out.append(fp_line((nw[0]+0.8, nw[1]), nw, lyr, w))
|
||
|
out.append(fp_line(nw, sw, lyr, w))
|
||
|
out.append(fp_line(sw, se, lyr, w))
|
||
|
out.append(fp_line(se, ne, lyr, w))
|
||
|
out.append(fp_line((ne[0]-0.8, ne[1]), ne, lyr, w))
|
||
|
return out
|
||
|
|
||
|
|
||
|
def top_smd_fab(pins):
|
||
|
out = []
|
||
|
w = fab_width
|
||
|
lyr = "F.Fab"
|
||
|
# Outline box
|
||
|
box_w = (pins-1)*1.25 + 2*3.6 - 2*2.1
|
||
|
box_h = 3.5 # XXX
|
||
|
box_y = box_h/2 + 0.2
|
||
|
nw, ne, se, sw, sq = draw_square(box_w, box_h, (0, box_y), lyr, w)
|
||
|
out += sq
|
||
|
# Mounting pins
|
||
|
_, _, _, _, sq = draw_square(1.8, 2.8, (nw[0]-1.8/2, sw[1]-2.8/2), lyr, w)
|
||
|
out += sq
|
||
|
_, _, _, _, sq = draw_square(1.8, 2.8, (ne[0]+1.8/2, sw[1]-2.8/2), lyr, w)
|
||
|
out += sq
|
||
|
# Connector pins
|
||
|
x = -(pins-1)/2 * 1.25
|
||
|
for pin in range(pins):
|
||
|
_, _, _, _, sq = draw_square(0.32, 0.6, (x, 2.6), lyr, w)
|
||
|
out += sq
|
||
|
x += 1.25
|
||
|
return out
|
||
|
|
||
|
|
||
|
def top_smd_ctyd(pins):
|
||
|
w = 1.25*(pins-1) + 2*3.6 + 2*ctyd_gap
|
||
|
h = 3.0 + 0.6 + 1.3 + 2*ctyd_gap
|
||
|
grid = 2 * ctyd_grid
|
||
|
w = grid * int(math.ceil(w / (2*ctyd_grid)))
|
||
|
h = grid * int(math.ceil(h / (2*ctyd_grid)))
|
||
|
y = h/2 - 1.3/2 - ctyd_gap
|
||
|
centre = (0, y)
|
||
|
_, _, _, _, sq = draw_square(w, h, centre, "F.CrtYd", ctyd_width)
|
||
|
return sq
|
||
|
|
||
|
|
||
|
def top_smd_model(pins):
|
||
|
return [
|
||
|
model(
|
||
|
"${KISYS3DMOD}/Connector_Molex.3dshapes/" +
|
||
|
"Molex_PicoBlade_53398-{:02d}71_1x{:02d}".format(pins, pins) +
|
||
|
"-1MP_P1.25mm_Vertical.step",
|
||
|
(0, -1.3/25.4, 0),
|
||
|
(1, 1, 1),
|
||
|
(0, 0, 0))]
|
||
|
|
||
|
|
||
|
def top_smd_fp(pins):
|
||
|
name = "MOLEX-PICOBLADE-53398-{:02d}71".format(pins)
|
||
|
tedit = format(int(time.time()), 'X')
|
||
|
sexp = ["module", name, ("layer", "F.Cu"), ("tedit", tedit)]
|
||
|
sexp += top_smd_refs(name)
|
||
|
sexp += top_smd_silk(pins)
|
||
|
sexp += top_smd_fab(pins)
|
||
|
sexp += top_smd_ctyd(pins)
|
||
|
sexp += top_smd_mount(pins)
|
||
|
sexp += top_smd_pads(pins)
|
||
|
sexp += top_smd_model(pins)
|
||
|
return name, sexp_generate(sexp)
|
||
|
|
||
|
|
||
|
def main(prettypath, verify=False, verbose=False):
|
||
|
for pins in range(2, 15):
|
||
|
for generator in (top_smd_fp,):
|
||
|
# Generate the footprint
|
||
|
name, fp = generator(pins)
|
||
|
path = os.path.join(prettypath, name + ".kicad_mod")
|
||
|
|
||
|
if verify and verbose:
|
||
|
print("Verifying", path)
|
||
|
|
||
|
# Check if the file already exists and isn't changed
|
||
|
if os.path.isfile(path):
|
||
|
with open(path) as f:
|
||
|
old = f.read()
|
||
|
old = [n for n in sexp_parse(old) if n[0] != "tedit"]
|
||
|
new = [n for n in sexp_parse(fp) if n[0] != "tedit"]
|
||
|
if new == old:
|
||
|
continue
|
||
|
|
||
|
# If not, either verification failed or we should output the new fp
|
||
|
if verify:
|
||
|
return False
|
||
|
else:
|
||
|
with open(path, "w") as f:
|
||
|
f.write(fp)
|
||
|
|
||
|
# If we finished and didn't return yet, verification has succeeded
|
||
|
if verify:
|
||
|
return True
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
parser = argparse.ArgumentParser()
|
||
|
parser.add_argument("prettypath", type=str,
|
||
|
help="Path to footprints to process")
|
||
|
parser.add_argument("--verify", action="store_true",
|
||
|
help="Verify libraries are up to date")
|
||
|
parser.add_argument("--verbose", action="store_true",
|
||
|
help="Print out every library verified")
|
||
|
args = vars(parser.parse_args())
|
||
|
result = main(**args)
|
||
|
if args['verify']:
|
||
|
if result:
|
||
|
print("OK: all footprints up-to-date.")
|
||
|
sys.exit(0)
|
||
|
else:
|
||
|
print("Error: footprints not up-to-date.", file=sys.stderr)
|
||
|
sys.exit(1)
|