Skip to content

Commit

Permalink
LayerToPlot enum for plot_plan
Browse files Browse the repository at this point in the history
  • Loading branch information
Wannes Sels committed Jun 16, 2022
1 parent d52b7c9 commit ad7bc25
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 75 deletions.
144 changes: 82 additions & 62 deletions kikit/export.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,41 @@
# Based on https://github.com/KiCad/kicad-source-mirror/blob/master/demos/python_scripts_examples/gen_gerber_and_drill_files_board.py
import sys
import os
from enum import Enum

from pcbnewTransition import pcbnew
from pcbnew import *


class LayerToPlot(Enum):
CuTop = (pcbnew.F_Cu, "Top layer")
CuBottom = (pcbnew.B_Cu, "Bottom layer")
PasteTop = (pcbnew.F_Paste, "Paste top")
PasteBottom = (pcbnew.B_Paste, "Paste bottom")
SilkTop = (pcbnew.F_SilkS, "Silk top")
SilkBottom = (pcbnew.B_SilkS, "Silk bottom")
MaskTop = (pcbnew.F_Mask, "Mask top")
MaskBottom = (pcbnew.B_Mask, "Mask bottom")
EdgeCuts = (pcbnew.Edge_Cuts, "Edges")
CmtUser = (pcbnew.Cmts_User, "V-CUT")
AdhesiveTop = (pcbnew.F_Adhes, "Adhesive top")
AdhesiveBottom = (pcbnew.B_Adhes, "Adhesive bottom")

def __init__(self, id: int, description: str):
self.id = id
self.description = description

fullGerberPlotPlan = [
# name, id, comment
("CuTop", F_Cu, "Top layer"),
("CuBottom", B_Cu, "Bottom layer"),
("PasteBottom", B_Paste, "Paste Bottom"),
("PasteTop", F_Paste, "Paste top"),
("SilkTop", F_SilkS, "Silk top"),
("SilkBottom", B_SilkS, "Silk top"),
("MaskBottom", B_Mask, "Mask bottom"),
("MaskTop", F_Mask, "Mask top"),
("EdgeCuts", Edge_Cuts, "Edges"),
("CmtUser", Cmts_User, "V-CUT")
LayerToPlot.CuTop,
LayerToPlot.CuBottom,
LayerToPlot.PasteBottom,
LayerToPlot.PasteTop,
LayerToPlot.SilkTop,
LayerToPlot.SilkBottom,
LayerToPlot.MaskBottom,
LayerToPlot.MaskTop,
LayerToPlot.EdgeCuts,
LayerToPlot.CmtUser
]

exportSettingsJlcpcb = {
Expand Down Expand Up @@ -50,13 +70,14 @@
}


def hasCopper(plotPlan):
for _, layer, _ in plotPlan:
if layer in [F_Cu, B_Cu]:
def hasCopper(plotPlan: list[LayerToPlot]):
for layer_to_plot in plotPlan:
if layer_to_plot.id in [F_Cu, B_Cu]:
return True
return False

def gerberImpl(boardfile, outputdir, plot_plan=fullGerberPlotPlan, drilling=True, settings=exportSettingsJlcpcb):

def gerberImpl(boardfile, outputdir, plot_plan: list[LayerToPlot]=fullGerberPlotPlan, drilling=True, settings=exportSettingsJlcpcb):
"""
Export board to gerbers.
Expand All @@ -71,62 +92,62 @@ def gerberImpl(boardfile, outputdir, plot_plan=fullGerberPlotPlan, drilling=True

board = LoadBoard(boardfile)

pctl = PLOT_CONTROLLER(board)
popt = pctl.GetPlotOptions()

popt.SetOutputDirectory(plotDir)

popt.SetPlotFrameRef(False)
popt.SetSketchPadLineWidth(FromMM(0.35))
popt.SetAutoScale(False)
popt.SetScale(1)
popt.SetMirror(False)
popt.SetUseGerberAttributes(False)
popt.SetIncludeGerberNetlistInfo(True)
popt.SetCreateGerberJobFile(True)
popt.SetUseGerberProtelExtensions(settings["UseGerberProtelExtensions"])
popt.SetExcludeEdgeLayer(settings["ExcludeEdgeLayer"])
popt.SetScale(1)
popt.SetUseAuxOrigin(settings["UseAuxOrigin"])
popt.SetUseGerberX2format(False)
popt.SetDrillMarksType(0) # NO_DRILL_SHAPE
plot_controller = PLOT_CONTROLLER(board)
plot_options = plot_controller.GetPlotOptions()

plot_options.SetOutputDirectory(plotDir)

plot_options.SetPlotFrameRef(False)
plot_options.SetSketchPadLineWidth(FromMM(0.35))
plot_options.SetAutoScale(False)
plot_options.SetScale(1)
plot_options.SetMirror(False)
plot_options.SetUseGerberAttributes(False)
plot_options.SetIncludeGerberNetlistInfo(True)
plot_options.SetCreateGerberJobFile(True)
plot_options.SetUseGerberProtelExtensions(settings["UseGerberProtelExtensions"])
plot_options.SetExcludeEdgeLayer(settings["ExcludeEdgeLayer"])
plot_options.SetScale(1)
plot_options.SetUseAuxOrigin(settings["UseAuxOrigin"])
plot_options.SetUseGerberX2format(False)
plot_options.SetDrillMarksType(0) # NO_DRILL_SHAPE

# This by gerbers only
popt.SetSubtractMaskFromSilk(False)
popt.SetDrillMarksType(PCB_PLOT_PARAMS.NO_DRILL_SHAPE)
popt.SetSkipPlotNPTH_Pads(False)
plot_options.SetSubtractMaskFromSilk(False)
plot_options.SetDrillMarksType(PCB_PLOT_PARAMS.NO_DRILL_SHAPE)
plot_options.SetSkipPlotNPTH_Pads(False)

# prepare the gerber job file
jobfile_writer = GERBER_JOBFILE_WRITER(board)

for name, id, comment in plot_plan:
if id <= B_Cu:
popt.SetSkipPlotNPTH_Pads(True)
for layer_to_plot in plot_plan:
if layer_to_plot.id <= B_Cu:
plot_options.SetSkipPlotNPTH_Pads(True)
else:
popt.SetSkipPlotNPTH_Pads(False)
plot_options.SetSkipPlotNPTH_Pads(False)

pctl.SetLayer(id)
suffix = "" if settings["NoSuffix"] else name
pctl.OpenPlotfile(suffix, PLOT_FORMAT_GERBER, comment)
jobfile_writer.AddGbrFile(id, os.path.basename(pctl.GetPlotFileName()))
if pctl.PlotLayer() == False:
plot_controller.SetLayer(layer_to_plot.id)
suffix = "" if settings["NoSuffix"] else layer_to_plot.name
plot_controller.OpenPlotfile(suffix, PLOT_FORMAT_GERBER, layer_to_plot.description)
jobfile_writer.AddGbrFile(layer_to_plot.id, os.path.basename(plot_controller.GetPlotFileName()))
if plot_controller.PlotLayer() == False:
print("plot error")

if hasCopper(plot_plan):
#generate internal copper layers, if any
lyrcnt = board.GetCopperLayerCount()
for innerlyr in range (1, lyrcnt - 1):
popt.SetSkipPlotNPTH_Pads(True)
pctl.SetLayer(innerlyr)
plot_options.SetSkipPlotNPTH_Pads(True)
plot_controller.SetLayer(innerlyr)
lyrname = "" if settings["NoSuffix"] else 'inner{}'.format(innerlyr)
pctl.OpenPlotfile(lyrname, PLOT_FORMAT_GERBER, "inner")
jobfile_writer.AddGbrFile(innerlyr, os.path.basename(pctl.GetPlotFileName()))
if pctl.PlotLayer() == False:
plot_controller.OpenPlotfile(lyrname, PLOT_FORMAT_GERBER, "inner")
jobfile_writer.AddGbrFile(innerlyr, os.path.basename(plot_controller.GetPlotFileName()))
if plot_controller.PlotLayer() == False:
print("plot error")

# At the end you have to close the last plot, otherwise you don't know when
# the object will be recycled!
pctl.ClosePlot()
plot_controller.ClosePlot()

if drilling:
# Fabricators need drill files.
Expand All @@ -152,13 +173,13 @@ def gerberImpl(boardfile, outputdir, plot_plan=fullGerberPlotPlan, drilling=True
drlwriter.SetFormat(metricFmt, zerosFmt)
genDrl = True
genMap = True
drlwriter.CreateDrillandMapFilesSet(pctl.GetPlotDirName(), genDrl, genMap)
drlwriter.CreateDrillandMapFilesSet(plot_controller.GetPlotDirName(), genDrl, genMap)

# One can create a text file to report drill statistics
rptfn = pctl.GetPlotDirName() + 'drill_report.rpt'
rptfn = plot_controller.GetPlotDirName() + 'drill_report.rpt'
drlwriter.GenDrillReportFile(rptfn)

job_fn=os.path.dirname(pctl.GetPlotFileName()) + '/' + os.path.basename(boardfile)
job_fn=os.path.dirname(plot_controller.GetPlotFileName()) + '/' + os.path.basename(boardfile)
job_fn=os.path.splitext(job_fn)[0] + '.gbrjob'
jobfile_writer.CreateJobFile(job_fn)

Expand All @@ -176,16 +197,15 @@ def pasteDxfExport(board, plotDir):
popt.SetDXFPlotPolygonMode(False)

plot_plan = [
# name, id, comment
("PasteBottom", B_Paste, "Paste Bottom"),
("PasteTop", F_Paste, "Paste top"),
("EdgeCuts", Edge_Cuts, "Edges"),
LayerToPlot.PasteBottom,
LayerToPlot.PasteTop,
LayerToPlot.EdgeCuts
]

output = []
for name, id, comment in plot_plan:
pctl.SetLayer(id)
pctl.OpenPlotfile(name, PLOT_FORMAT_DXF, comment)
for layer_to_plot in plot_plan:
pctl.SetLayer(layer_to_plot.id)
pctl.OpenPlotfile(layer_to_plot.name, PLOT_FORMAT_DXF, layer_to_plot.description)
output.append(pctl.GetPlotFileName())
if pctl.PlotLayer() == False:
print("plot error")
Expand Down
4 changes: 2 additions & 2 deletions kikit/fab/oshpark.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
import os
import shutil
from pathlib import Path
from kikit.export import gerberImpl, exportSettingsOSHPark, fullGerberPlotPlan
from kikit.export import gerberImpl, exportSettingsOSHPark, fullGerberPlotPlan, LayerToPlot
from kikit.fab.common import ensurePassingDrc

plotPlanNoVCuts = [(name, id, comment) for name, id, comment in fullGerberPlotPlan if name != "CmtUser"]
plotPlanNoVCuts = [layer_to_plot for layer_to_plot in fullGerberPlotPlan if layer_to_plot is not LayerToPlot.CmtUser]

def exportOSHPark(board, outputdir, nametemplate, drc):
"""
Expand Down
18 changes: 7 additions & 11 deletions kikit/stencil.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import shutil

from pcbnewTransition import pcbnew
from pcbnew import wxPoint
import numpy as np
Expand All @@ -7,7 +9,7 @@
from kikit.common import *
from kikit.defs import *
from kikit.substrate import Substrate, extractRings, toShapely, linestringToKicad
from kikit.export import gerberImpl, pasteDxfExport
from kikit.export import gerberImpl, pasteDxfExport, LayerToPlot
from kikit.export import exportSettingsJlcpcb
import solid
import solid.utils
Expand Down Expand Up @@ -370,22 +372,16 @@ def create(inputboard, outputdir, jigsize, jigthickness, pcbthickness,
stencilFile = os.path.join(outputdir, "stencil.kicad_pcb")
board.Save(stencilFile)

setStencilLayerVisibility(stencilFile)
setStencilLayerVisibility(inputboard)
plot_plan = [LayerToPlot.PasteTop, LayerToPlot.PasteBottom]

plotPlan = [
# name, id, comment
("PasteBottom", pcbnew.B_Paste, "Paste Bottom"),
("PasteTop", pcbnew.F_Paste, "Paste top"),
]
# get a copy of exportSettingsJlcpcb dictionary and
# exclude the Edge.Cuts layer for creation of stencil gerber files
exportSettings = exportSettingsJlcpcb.copy()
exportSettings["ExcludeEdgeLayer"] = True
gerberDir = os.path.join(outputdir, "gerber")
gerberImpl(stencilFile, gerberDir, plotPlan, False, exportSettings)
gerbers = [os.path.join(gerberDir, x) for x in os.listdir(gerberDir)]
subprocess.check_call(["zip", "-j",
os.path.join(outputdir, "gerbers.zip")] + gerbers)
gerberImpl(stencilFile, gerberDir, plot_plan, False, exportSettings)
shutil.make_archive(os.path.join(outputdir, "gerbers"), "zip", gerberDir)

jigthickness = fromMm(jigthickness)
pcbthickness = fromMm(pcbthickness)
Expand Down

0 comments on commit ad7bc25

Please sign in to comment.