#!/usr/bin/env python import sys import os import argparse from pcbnew import * parser = argparse.ArgumentParser(description='KiCAD PCB to GERBER converter') parser.add_argument('--pcb', required=True, dest='pcb', action='store', help='A foo.kicad_pcb file') parser.add_argument('--output-directory', required=True, dest='output_directory', action='store', help='Directory to store output files') parser.add_argument('--detect-files-only', dest='detect_files_only', action='store_true', help='Don\'t create the GERBER files, just list the files to be created') parser.add_argument('--create-drill-map-file', dest='create_drill_map_file', action='store_true', help='Create drill map file') parser.add_argument('--protel-extensions', dest='protel_extensions', action='store_true', help='Use Protel filename extensions') args = parser.parse_args() filename = args.pcb board = LoadBoard(filename) plot_plan = [ ("GTO", board.GetLayerName(F_SilkS), F_SilkS, "Silk front"), ("GTS", board.GetLayerName(F_Mask), F_Mask, "Mask front"), ("GBO", board.GetLayerName(B_SilkS), B_SilkS, "Silk bottom"), ("GBS", board.GetLayerName(B_Mask), B_Mask, "Mask bottom"), ("GBR", board.GetLayerName(Edge_Cuts), Edge_Cuts, "Edges"), ] layers = board.GetEnabledLayers() for i in layers.CuStack(): name = board.GetLayerName(i) plot_plan.append(("", name, i, "Copper Layer " + name)) pctl = PLOT_CONTROLLER(board) popt = pctl.GetPlotOptions() popt.SetOutputDirectory(args.output_directory) # A nasty hack to get the base filename pctl.SetLayer(F_Cu) pctl.OpenPlotfile("", PLOT_FORMAT_GERBER, "") filename = pctl.GetPlotFileName() try: os.remove(filename) except: pass pctl.ClosePlot() basename = filename.replace('.gbr', '') drlFile = basename + ".drl" drlFileProtel = basename + ".txt" if args.protel_extensions: popt.SetUseGerberProtelExtensions(True) if args.detect_files_only: for layer_info in plot_plan: filenamePostfix = layer_info[1] layer_num = layer_info[2] pctl.SetLayer(layer_num) pctl.OpenPlotfile(filenamePostfix, PLOT_FORMAT_GERBER, layer_info[3]) filename = pctl.GetPlotFileName() print filename try: os.remove(filename) except: pass pctl.ClosePlot() if args.protel_extensions: print drlFileProtel else: print drlFile sys.exit(0) # Set some important plot options: popt.SetPlotFrameRef(False) popt.SetLineWidth(FromMM(0.35)) popt.SetAutoScale(False) popt.SetScale(1) popt.SetMirror(False) popt.SetUseGerberAttributes(True) popt.SetExcludeEdgeLayer(False) popt.SetScale(1) popt.SetUseAuxOrigin(True) # This by gerbers only (also the name is truly horrid!) popt.SetSubtractMaskFromSilk(False) for layer_info in plot_plan: filenamePostfix = layer_info[1] layer_num = layer_info[2] pctl.SetLayer(layer_num) pctl.OpenPlotfile(filenamePostfix, PLOT_FORMAT_GERBER, layer_info[3]) pctl.PlotLayer() pctl.ClosePlot() popt.SetDrillMarksType(PCB_PLOT_PARAMS.FULL_DRILL_SHAPE) drlwriter = EXCELLON_WRITER(board) # drlwriter.SetMapFileFormat(PLOT_FORMAT_PDF) drlwriter.SetMapFileFormat(PLOT_FORMAT_GERBER) mirror = False minimalHeader = False offset = wxPoint(0, 0) # False to generate 2 separate drill files (one for plated holes, one for non plated holes) # True to generate only one drill file mergeNPTH = False drlwriter.SetOptions(mirror, minimalHeader, offset, mergeNPTH) metricFmt = True drlwriter.SetFormat(metricFmt) genDrl = True genMap = args.create_drill_map_file drlwriter.CreateDrillandMapFilesSet(pctl.GetPlotDirName(), genDrl, genMap) if args.protel_extensions: os.rename(drlFile, basename + ".txt") pass