#!/usr/bin/env python from jinja2 import Environment, FileSystemLoader, select_autoescape import os, os.path import re import ipc_sm_782 basedir=os.path.dirname(__file__) env = Environment( loader=FileSystemLoader(os.path.join(basedir, 'templates')), lstrip_blocks=True, ) env.globals["rnd2"] = lambda x: round(x, 2) chip = env.get_template('CHIP.j2') resc_heights = { "1005": [0.15, 0.35, 0.37, 0.40], "1608": [0.40], "2012": [0.40], "3216": [0.40], "3225": [0.40], "5025": [0.40], "6332": [0.40], } capc_heights = { "1005": [0.15, 0.35, 0.37, 0.40], "1608": [0.40], "2012": [0.40, 1.35], "3216": [0.40], "3225": [0.40], "5025": [0.40], "6332": [0.40], } ledsc_heights = { # https://www.digikey.com/products/en/optoelectronics/led-indication-discrete/105?k=&pkeyword=&pv16=4&FV=ffe00069%2C1140003&mnonly=0&ColumnSort=0&page=1&quantity=0&ptm=0&fid=0&pageSize=100 "1005": [0.25, 0.35, 0.40, 0.45, 0.50, 0.52, 0.55, 0.60, 0.70, 0.71], "1608": [0.20, 0.25, 0.28, 0.30, 0.35, 0.39, 0.40, 0.42, 0.45, 0.46, 0.50, 0.52, 0.55, 0.60, 0.65, 0.70, 0.71, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00, 1.05, 1.10, 1.15], "2012": [0.40, 0.45, 0.50, 0.70, 0.75, 0.79, 0.80, 0.84, 0.85, 0.90, 1.00, 1.10, 1.20, 1.25, 1.30, 2.10], } def auto_str(cls): def __str__(self): return '%s(%s)' % ( type(self).__name__, ', '.join('%s=%s' % item for item in vars(self).items()) ) cls.__str__ = __str__ return cls class Value(object): def __init__(self, typ, mn, mx): self.typ = typ if typ else (mn + mx) / 2 self.mn = mn self.mx = mx def __str__(self): return "(typ={:0.2f}, min={:0.2f}, max={:0.2f})".format(self.typ, self.mn, self.mx) grid_re = re.compile("([0-9]+)x([0-9]+)") def parse_courtyard(grid): (grid_y, grid_x) = grid_re.match(grid).groups() return (float(grid_x) * 0.5 / 2, float(grid_y) * 0.5 / 2) @auto_str class ChipDimensions(object): def __init__(self, **kw): for k, v in kw.items(): setattr(self, k, v) @staticmethod def from_ipc(data): print("data={}".format(data)) size_mm = data["size_mm"] # print("x={}".format(grid_re.match(data["grid"]).groups())) return ChipLandPattern( key = size_mm, size_x = Value(float(size_mm[0:2]) / 10, data["l_max"], data["l_min"]), size_y = Value(float(size_mm[2:4]) / 10, data["w_max"], data["w_min"]), terminal_size = Value(None, data["t_min"], data["t_max"]), height_max = data["h_max"]) @auto_str class ChipLandPattern(object): def __init__(self, **kw): for k, v in kw.items(): setattr(self, k, v) @staticmethod def from_ipc(data): # print("data={}".format(data)) size_mm = data["size_mm"] (courtyard_x, courtyard_y) = parse_courtyard(data["grid"]) r = lambda x: round(x) return ChipLandPattern( key = size_mm, size_x = float(size_mm[0:2]) / 10, size_y = float(size_mm[2:4]) / 10, pad_pos_x = float(data["c"]) / 2, pad_size_x = float(data["y"]), pad_size_y = float(data["x"]), courtyard_x = courtyard_x, courtyard_y = courtyard_y) #resc_dims = [ChipDimensions.from_ipc(p) for p in ipc_sm_782.data["resc"]["dimensions"]] resc_lp = [ChipLandPattern.from_ipc(p) for p in ipc_sm_782.data["resc"]["land_patterns"]] #capc_dims = [ChipDimensions.from_ipc(p) for p in ipc_sm_782.data["capc"]["dimensions"]] capc_lp = [ChipLandPattern.from_ipc(p) for p in ipc_sm_782.data["capc"]["land_patterns"]] ledsc_lp = [ChipLandPattern.from_ipc(p) for p in ipc_sm_782.data["ledsc"]["land_patterns"]] work = [\ ("RESC", resc_lp, resc_heights), \ ("CAPC", capc_lp, capc_heights), \ ("LEDSC", ledsc_lp, ledsc_heights), \ ] for (kind, lps, heights) in work: basedir = "IPC-7351-{}.pretty".format(kind) if not os.path.isdir(basedir): os.mkdir(basedir) for lp in lps: # print("{}_{}".format(kind, lp.key)) # print("lp={}".format(lp)) # print("lp={}".format(lp.size_x / 8)) for h in heights.get(lp.key, []): key = "{}_{}x{:03}".format(kind, lp.key, int(h * 100)) # print(" " + key) kicad_mod = chip.render({"lp": lp, "key": key}) with open(os.path.join(basedir, "{}.kicad_mod".format(key)), "w") as f: f.write(kicad_mod)