diff options
-rw-r--r-- | cmake/kicad_gerber.cmake | 25 | ||||
-rwxr-xr-x | py/kicad_gerber.py | 160 |
2 files changed, 130 insertions, 55 deletions
diff --git a/cmake/kicad_gerber.cmake b/cmake/kicad_gerber.cmake index 330c5bd..580fa10 100644 --- a/cmake/kicad_gerber.cmake +++ b/cmake/kicad_gerber.cmake @@ -1,7 +1,7 @@ function(kicad_gerber) - set(options ALL) + set(options ALL UPPERCASE_EXTENSIONS) set(one_value_args TARGET PCB_FILE DIR ZIP_FILE NAMING_STYLE) - set(multi_value_args) + set(multi_value_args LAYER_EXTENSION) cmake_parse_arguments(ARGS "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN}) if (NOT ARGS_PCB_FILE) @@ -15,7 +15,7 @@ function(kicad_gerber) if (ARGS_NAMING_STYLE STREQUAL MODERN) elseif (ARGS_NAMING_STYLE STREQUAL PROTEL) - set(protel --protel-extension) + set(protel --protel-extensions) else () message(SEND_ERROR "Unsupported NAMING_STYLE: ${ARGS_NAMING_STYLE}") return() @@ -36,11 +36,19 @@ function(kicad_gerber) return() endif () + foreach (le ${ARGS_LAYER_EXTENSION}) + list(APPEND les --layer-extension ${le}) + endforeach () + + if (ARGS_UPPERCASE_EXTENSIONS) + set(uppercase_extensions --uppercase-extensions) + endif () + set(out_dir "${ARGS_DIR}") set(prefix "${out_dir}/${basename}") execute_process( - COMMAND "${KicadUtilsPyDir}/kicad_gerber.py" --pcb "${pcb_file}" --output-directory "${out_dir}" ${protel} --detect-files-only + COMMAND "${KicadUtilsPyDir}/kicad_gerber.py" --pcb "${pcb_file}" --output-directory "${out_dir}" ${protel} ${uppercase_extensions} ${les} --detect-files-only OUTPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/${target}-gerber-index.txt OUTPUT_VARIABLE out ERROR_VARIABLE err @@ -53,16 +61,11 @@ function(kicad_gerber) return() endif () -# foreach (o ${out}) -# list(APPEND outputs ${prefix}${o}) -# endforeach () - - # message("out=${out}") - message("outputs=${outputs}") + message("outputs=${outputs}") add_custom_command( OUTPUT ${outputs} COMMAND cmake -E make_directory "${out_dir}" - COMMAND "${KicadUtilsPyDir}/kicad_gerber.py" --pcb "${pcb_file}" --output-directory "${out_dir}" ${protel} + COMMAND "${KicadUtilsPyDir}/kicad_gerber.py" --pcb "${pcb_file}" --output-directory "${out_dir}" ${protel} ${uppercase_extensions} ${les} MAIN_DEPENDENCY "${pcb_file}") if (ARGS_ALL) diff --git a/py/kicad_gerber.py b/py/kicad_gerber.py index 45358c0..e963be7 100755 --- a/py/kicad_gerber.py +++ b/py/kicad_gerber.py @@ -4,6 +4,13 @@ import os import argparse from pcbnew import * +def layer_name_parser(s): + parts = s.split('=') + if len(parts) != 2: + raise argparse.ArgumentTypeError("Invalid layer renaming: " + s) + else: + return parts + parser = argparse.ArgumentParser(description='KiCAD PCB to GERBER converter') parser.add_argument('--pcb', @@ -31,26 +38,60 @@ parser.add_argument('--create-drill-map-file', parser.add_argument('--protel-extensions', dest='protel_extensions', action='store_true', - help='Use Protel filename extensions') - -args = parser.parse_args() + help='Use Protel filename extensions instead of .gbr') -filename = args.pcb +parser.add_argument('--uppercase-extensions', + action='store_true', + help='Uppercase all extensions') -board = LoadBoard(filename) +parser.add_argument('--layer-extension', + dest='layer_extensions', + metavar='LAYER_AND_EXTENSION', + action='append', + type=layer_name_parser, + help='Set the file extension of a KiCAD layer. Format: <KiCAD Layer>=<extension>, example: F.SilkS=GSILK') -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"), -] +args = parser.parse_args() +# print "args: " + str(args) +# print "args.name_layer: " + str(args.name_layers) + +renames = {} +if args.layer_extensions is not None: + for s in args.layer_extensions: + renames[s[0]] = s[1] +# print("renames: " + str(renames)) + +board = LoadBoard(args.pcb) + +class Plan: + def __init__(self, layerNum, layerName, description): + self.layerNum = layerNum + self.layerName = layerName + self.description = description + self.postfix = "" + self.ext = None + + @staticmethod + def standard(layerNum, description): + layerName = board.GetLayerName(layerNum) + return Plan(layerNum, layerName, description) + + @staticmethod + def copper(layerNum): + layerName = board.GetLayerName(layerNum) + description = "Copper Layer " + layerName + return Plan(layerNum, layerName, description) + +plot_plan = [Plan.standard(layerNum, description) for (layerNum, description) in [ + (F_SilkS, "Silk front"), + (F_Mask, "Mask front"), + (B_SilkS, "Silk bottom"), + (B_Mask, "Mask bottom"), + (Edge_Cuts, "Edges")]] layers = board.GetEnabledLayers() -for i in layers.CuStack(): - name = board.GetLayerName(i) - plot_plan.append(("", name, i, "Copper Layer " + name)) +for layerNum in layers.CuStack(): + plot_plan.append(Plan.copper(layerNum)) pctl = PLOT_CONTROLLER(board) popt = pctl.GetPlotOptions() @@ -66,32 +107,58 @@ except: pass pctl.ClosePlot() -basename = filename.replace('.gbr', '') -drlFile = basename + ".drl" -drlFileProtel = basename + ".txt" - if args.protel_extensions: popt.SetUseGerberProtelExtensions(True) +basename = os.path.splitext(filename)[0] + +drlFileOut = drlFile = basename + ".drl" + +if args.protel_extensions: + n, e = os.path.splitext(drlFileOut) + drlFileOut = n + ".txt" + +if args.uppercase_extensions: + n, e = os.path.splitext(drlFileOut) + drlFileOut = n + e.upper() + +values = vars(args) +for plan in plot_plan: + pctl.SetLayer(plan.layerNum) + pctl.OpenPlotfile("", PLOT_FORMAT_GERBER, plan.description) + filename = pctl.GetPlotFileName() + pctl.ClosePlot() + # By opening and closing the plot we create an empty plot file. + try: + os.remove(filename) + except: + pass + + filename, ext = os.path.splitext(filename) + if args.uppercase_extensions: + ext = ext.upper() + + if plan.layerName in renames: + ext = "." + renames[plan.layerName] + + # if plan.arg is not None: + # newExt = values[plan.arg] + # if newExt is not None: + # ext = "." + newExt + + # if not args.protel_extensions: + plan.postfix = plan.layerName + plan.filename = basename + "-" + plan.postfix + ext + + # print "filename = " + plan.filename + ", postfix=" + plan.postfix + # print "filename: " + plan.filename + 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() + for plan in plot_plan: + print plan.filename + if args.protel_extensions: - print drlFileProtel - else: - print drlFile + print drlFileOut sys.exit(0) # Set some important plot options: @@ -108,19 +175,24 @@ 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) +for plan in plot_plan: + pctl.SetLayer(plan.layerNum) + + # print "filename = " + plan.filename + ", postfix=" + plan.postfix + pctl.OpenPlotfile(plan.postfix, PLOT_FORMAT_GERBER, plan.description) + + actualFilename = pctl.GetPlotFileName() + expectedFilename = plan.filename + + if expectedFilename != actualFilename: + os.rename(actualFilename, expectedFilename) - 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 @@ -139,6 +211,6 @@ genMap = args.create_drill_map_file drlwriter.CreateDrillandMapFilesSet(pctl.GetPlotDirName(), genDrl, genMap) -if args.protel_extensions: - os.rename(drlFile, basename + ".txt") +if drlFile != drlFileOut: + os.rename(drlFile, drlFileOut) pass |