import sys import argparse import csv import datetime as dt from . import mk_parents from ..kicad import pcb, parse_ref from .._utils import run_filters parser = argparse.ArgumentParser(description="Create a pick and place file from a KiCAD schematic") parser.add_argument("--kicad-pcb", required=True, dest="pcb", metavar="PCB", help="The pcb to read") parser.add_argument("--out", metavar="FILE", help="The output file") parser.add_argument("--format", metavar="FORMAT", default="plain", help="The format of the output file. Either 'plain' or 'kicad'") args = parser.parse_args() pcb = pcb.parse(args.pcb) fmt = args.format if fmt != "plain" and fmt != "kicad": print("Bad format: {}".format(fmt), file=sys.stderr) def run(stream): rows = [] modules = [m for m in pcb.modules if m.has_attr("smd")] for m in modules: row = {} ref_fp_text = next(m.filter_fp_text(kind = "reference"), None) row["ref"] = ref= ref_fp_text and ref_fp_text.value row["r"] = parse_ref(ref) value_fp_text = next(m.filter_fp_text(kind = "value"), None) row["value"] = value_fp_text and value_fp_text.value (row["library"], row["footprint"]) = m.footprint.split(":") (x, y, rotation) = m.at # The Y axis is inverted for some unknown reason. (row["x"], row["y"], row["rotation"]) = (float(x), -float(y), float(rotation)) if m.layer == "F.Cu": row["side"] = "top" elif m.layer == "B.Cu": row["side"] = "bottom" else: row["side"] = None rows.append(row) if fmt == "plain": rows = sorted(rows, key=lambda row: row["r"]) out = csv.writer(stream) out.writerow(["ref", "value", "library", "footprint", "x", "y", "rotation", "side"]) for row in rows: del row["r"] out.writerow(row.values()) elif fmt == "kicad": lines = [] for row in rows: row["x"] = "{:>9.4f}".format(row["x"]) row["y"] = "{:>9.4f}".format(row["y"]) row["rotation"] = "{:>9.4f}".format(float(row["rotation"])) def find_max(name, mn): return str(max(mn, max((len(str(row[name])) for row in rows)) + 1)) ref_sz = find_max("ref", 8) value_sz = find_max("value", 8) footprint_sz = find_max("footprint", 16) x_sz = find_max("x", 10) y_sz = find_max("y", 10) rotation_sz = find_max("rotation", 0) fmts = "{ref:" + ref_sz + "}" +\ " {value:" + value_sz + "}" +\ " {footprint:" + footprint_sz + "}" +\ " {x} {y} {rotation}" +\ " {side}" #print("fmts={}".format(fmts)) for row in rows: #print("row={}".format(row)) s = fmts.format(**row) lines.append(s) print("### Module positions - created on {:%Y-%m-%d %H:%M:%S} ###".format(dt.datetime.now()), file=stream) print("### Printed by ee tools", file=stream) print("## Unit = mm, Angle = deg.", file=stream) print("## Side : All", file=stream) print("# Ref Val Package PosX PosY Rot Side", file=stream) for line in lines: print(line, file=stream) print("## End", file=stream) if args.out: mk_parents(args.out) with open(args.out, "w") as f: run(f) else: run(sys.stdout)