def render(layers, name, mirror): # Export new files pctl = pcbnew.PLOT_CONTROLLER(board) popt = pctl.GetPlotOptions() popt.SetOutputDirectory(plotDir) popt.SetPlotFrameRef(False) popt.SetLineWidth(pcbnew.FromMM(0.15)) popt.SetAutoScale(False) popt.SetScale(1) popt.SetMirror(mirror) popt.SetUseGerberAttributes(True) popt.SetExcludeEdgeLayer(False) popt.SetUseAuxOrigin(False) popt.SetUseAuxOrigin(False) popt.SetPlotReference(True) popt.SetPlotValue(True) popt.SetPlotInvisibleText(False) popt.SetPlotFrameRef(False) pctl.SetLayer(Dwgs_User) pctl.OpenPlotfile(name, PLOT_FORMAT_PDF, name) pctl.SetColorMode(True) for layer_info in layers: pctl.SetLayer(layer_info[1]) pctl.PlotLayer() pctl.ClosePlot()
def plot_fab_drawings(self, pcb): "plot fab drawings" pctl = pcbnew.PLOT_CONTROLLER(pcb) popt = pctl.GetPlotOptions() fab_path = os.path.dirname(pcb.GetFileName()) + PCB_MAN_PACK_DIR popt.SetOutputDirectory(fab_path) # Set some important plot options: popt.SetPlotFrameRef(True) popt.SetLineWidth(pcbnew.FromMM(0.1)) popt.SetAutoScale(False) popt.SetScale(1) popt.SetMirror(False) popt.SetExcludeEdgeLayer(False) popt.SetPlotValue(False) popt.SetPlotReference(True) #Create a pdf file of the top fab Layer pctl.SetLayer(pcbnew.Dwgs_User) pctl.OpenPlotfile("Fab_Drawings", pcbnew.PLOT_FORMAT_PDF, "Fab_Drawings") pctl.PlotLayer() pctl.ClosePlot()
def Run(self): self.pcb = pcbnew.GetBoard() a = CircularZoneDlg(None) x = 0 y = 0 reference = None for module in self.pcb.GetModules(): if module.IsSelected(): x = module.GetPosition().x y = module.GetPosition().y reference = module.GetReference() break if reference is None: a.m_comment.SetLabel("No reference position: start at origin") else: a.m_comment.SetLabel("Using %s as position reference" % reference) a.m_radiusMM.SetValue("10") modal_result = a.ShowModal() segment = self.CheckInput(a.m_textCtrl_seg.GetValue(), "segment number") radius = self.CheckInput(a.m_radiusMM.GetValue(), "radius") if segment is not None and radius is not None: if modal_result == wx.ID_OK: self.build(x, y, pcbnew.FromMM(radius), a.m_radio_out.GetValue(), segment) else: None # Cancel else: None # Invalid input a.Destroy()
def Run(self): """ """ _pcbnew_frame = [ x for x in wx.GetTopLevelWindows() if x.GetName() == 'PcbFrame' ][0] # _pcbnew_frame = [ # x # for x in wx.GetTopLevelWindows() # if x.GetTitle().lower().startswith("pcbnew") # ][0] wx_params = TraceClearance_Dlg(_pcbnew_frame) wx_params.m_clearance.SetValue("0.2") wx_params.m_bitmap.SetBitmap( wx.Bitmap( os.path.join( os.path.dirname(os.path.realpath(__file__)), "trace_clearance_dialog.png", ))) modal_res = wx_params.ShowModal() clearance = pcbnew.FromMM( self.InputValid(wx_params.m_clearance.GetValue())) if clearance is not None: pcb = pcbnew.GetBoard() if modal_res == wx.ID_OK: tracks = selected_tracks(pcb) if len(tracks) > 0: set_keepouts(pcb, tracks, clearance) else: self.Warn("At least one track must be selected.") elif modal_res == wx.ID_CANCEL: wx_params.Destroy()
def plot(board_filename=None, layers=None): if board_filename is None: board = pcbnew.GetBoard() else: board = pcbnew.LoadBoard(os.path.expanduser(board_filename)) if layers is None: layers = LAYERS elif isinstance(layers, list): layers = layers.keys() plot_ctrl = pcbnew.PLOT_CONTROLLER(board) plot_opts = plot_ctrl.GetPlotOptions() plot_opts.SetPlotFrameRef(False) plot_opts.SetLineWidth(pcbnew.FromMM(0.35)) plot_opts.SetAutoScale(False) plot_opts.SetScale(1) plot_opts.SetUseGerberAttributes(True) plot_opts.SetExcludeEdgeLayer(False) plot_opts.SetUseAuxOrigin(False) plot_opts.SetPlotViaOnMaskLayer(True) for layer, layer_info in layers.items(): layer_name = layers.get('name', board.GetLayerName(layer)) plot_opts.SetMirror(layer_info.get('mirrored', False)) plot_opts.SetNegative(layer_info.get('negative', False)) plot_ctrl.SetLayer(layer) plot_ctrl.OpenPlotfile(layer_name, pcbnew.PLOT_FORMAT_PDF, layer_info.get('description', layer_name)) plot_ctrl.PlotLayer()
def BoxWithOpenCorner(self, x, y, w, h, setback=pcbnew.FromMM(1.27), flip=flipNone): """! Draw a box with an opening at the top left corner @param x: the x co-ordinate of the circle's centre @param y: the y co-ordinate of the circle's centre @param w: the width of the box @param h: the height of the box @param setback: the set-back of the opening, in both x and y @param flip: one of flipNone, flipX, flipY or flipBoth to change the open corner position """ self.TransformTranslate(x, y) self.TransformFlipOrigin(flip) pts = [[-w / 2, -h / 2 + setback], [-w / 2, +h / 2], [+w / 2, +h / 2], [+w / 2, -h / 2], [-w / 2 + setback, -h / 2]] self.Polyline(pts) self.PopTransform(num=2)
def GetTextSize(self): """! Get the default text size for the footprint. Override to change it. Defaults to IPC nominal of 1.0mm """ return pcbnew.FromMM(1.0)
def BuildThisFootprint(self): pads = self.parameters["Pads"] rows = pads["*row count"] cols = pads["*column count"] pad_size = pads["pad size"] pad_size = pcbnew.wxSize(pad_size, pad_size) pad_pitch = pads["pad pitch"] # add in the pads pad = PA.PadMaker(self.module).SMTRoundPad(pads["pad size"]) pin1_pos = pcbnew.wxPoint(-((cols - 1) * pad_pitch) / 2, -((rows - 1) * pad_pitch) / 2) array = BGAPadGridArray(pad, cols, rows, pad_pitch, pad_pitch) array.AddPadsToModule(self.draw) #box ssx = -pin1_pos.x + pads["outline x margin"] ssy = -pin1_pos.y + pads["outline y margin"] self.draw.BoxWithDiagonalAtCorner(0, 0, ssx * 2, ssy * 2, pads["outline x margin"]) #reference and value text_size = pcbnew.FromMM(1.2) # IPC nominal self.draw.Value(0, -ssy - text_size, text_size) self.draw.Reference(0, ssy + text_size, text_size)
def add_back_keepout(pattern, corners, radius, no_tracks=True): """ Add keepout area under the pads. @param corners number of corners in approximate circle @param radius circle radius """ r = pcbnew.FromMM(radius) hatch_type = pcbnew.CPolyLine.NO_HATCH layer_inverter = {pcbnew.F_Cu: pcbnew.B_Cu, pcbnew.B_Cu: pcbnew.F_Cu} board = pcbnew.GetBoard() for sw in ref_iter(board, pattern): try: pos = sw.GetPosition() insert_circular_keepout(board, pos.x, pos.y, r, corners, layer_inverter[sw.GetLayer()], hatch_type=hatch_type, no_tracks=no_tracks, no_vias=True, no_pour=True) # no need to rotate circular keepout area except Exception as e: print(e)
def add_gnd_tracks(pattern, width): """ Connect GND pads. @param pattern matching pattern @param width width of track """ def find_gnd_pads(mod): pads = [pad for pad in mod.Pads() if pad.GetPadName() == "0"] for i, pad in enumerate(pads): if pad.GetPosition() == mod.GetPosition(): del pads[i] return pad, pads board = pcbnew.GetBoard() track_width = pcbnew.FromMM(width) netcode = board.GetNetcodeFromNetname("GND") for sw in ref_iter(board, pattern): layer = sw.GetLayer() try: center_gnd, gnds = find_gnd_pads(sw) add_track_pos(board, layer, netcode, center_gnd.GetPosition(), gnds[0].GetPosition(), track_width) add_track_pos(board, layer, netcode, center_gnd.GetPosition(), gnds[1].GetPosition(), track_width) except Exception as e: print(e)
def Run(self): pcb = pcbnew.GetBoard() pctl = pcbnew.PLOT_CONTROLLER(pcb) popt = pctl.GetPlotOptions() popt.SetOutputDirectory("Outputs/PCB_Manufacturing/") # Set some important plot options: popt.SetPlotFrameRef(True) popt.SetLineWidth(pcbnew.FromMM(0.1)) popt.SetAutoScale(False) popt.SetScale(1) popt.SetMirror(False) popt.SetExcludeEdgeLayer(False) popt.SetPlotValue(False) popt.SetPlotReference(True) #Create a pdf file of the top fab Layer pctl.SetLayer(pcbnew.Dwgs_User) pctl.OpenPlotfile("Fab_Drawings", pcbnew.PLOT_FORMAT_PDF, "Fab_Drawings") pctl.PlotLayer() pctl.ClosePlot()
def BoxWithDiagonalAtCorner(self, x, y, w, h, setback=pcbnew.FromMM(1.27), flip=flipNone): """! Draw a box with a diagonal at the top left corner. @param x: the x co-ordinate of the circle's centre @param y: the y co-ordinate of the circle's centre @param w: the width of the box @param h: the height of the box @param setback: the set-back of the diagonal, in both x and y @param flip: one of flipNone, flipX, flipY or flipBoth to change the diagonal corner """ self.TransformFlip(x, y, flip, push=True) pts = [[x - w / 2 + setback, y - h / 2], [x - w / 2, y - h / 2 + setback], [x - w / 2, y + h / 2], [x + w / 2, y + h / 2], [x + w / 2, y - h / 2], [x - w / 2 + setback, y - h / 2]] self.Polyline(pts) self.PopTransform()
def AddParam(self, section, param, unit, default, hint=''): """ Add a parameter with some properties. TODO: Hints are not supported, as there is as yet nowhere to put them in the KiCAD interface """ val = None if unit == self.uMM: val = pcbnew.FromMM(default) elif unit == self.uMils: val = pcbnew.FromMils(default) elif unit == self.uNatural: val = default elif unit == self.uString: val = str(default) elif unit == self.uBool: val = "True" if default else "False" # ugly stringing else: print "Warning: Unknown unit type: %s" % unit return if unit in [self.uNatural, self.uBool, self.uString]: param = "*%s" % param # star prefix for natural if section not in self.parameters: self.parameters[section] = {} self.parameters[section][param] = val
def BuildThisFootprint(self): pads = self.parameters['Pads'] numbering = self.parameters['Numbering'] outline = self.parameters['Outline'] padRotation = self.parameters['Pad rotation'] pad_size = pads['diameter'] pad_shape = pcbnew.PAD_SHAPE_RECT if pads["rectangle"] else pcbnew.PAD_SHAPE_OVAL pad = PA.PadMaker(self.module).THPad(pads['diameter'], pads['diameter'], pads['drill'], shape=pad_shape) array = PA.PadCircleArray( pad, pads['count'], pads['center diameter'] / 2, angle_offset=pads["angle"], centre=pcbnew.wxPoint(0, 0), clockwise=numbering["clockwise"], padRotationEnable= padRotation["pad rotation"], padRotationOffset = padRotation["pad angle offset"]) array.SetFirstPadInArray(numbering["initial"]) array.AddPadsToModule(self.draw) # Draw the outline body_radius = outline['diameter'] / 2 self.draw.SetLayer(pcbnew.F_Fab) self.draw.GetLineThickness() self.draw.Circle(0, 0, body_radius) #silkscreen body_radius += pcbnew.FromMM(0.15) self.draw.SetLayer(pcbnew.F_SilkS) self.draw.Circle(0, 0, body_radius) # courtyard self.draw.SetLayer(pcbnew.F_CrtYd) self.draw.SetLineThickness(pcbnew.FromMM(0.05)) self.draw.Circle(0, 0, body_radius + outline['margin']) # Text size text_size = self.GetTextSize() # IPC nominal thickness = self.GetTextThickness() textposy = body_radius + self.draw.GetLineThickness()/2 + self.GetTextSize()/2 + thickness + + outline['margin'] self.draw.Value( 0, textposy, text_size ) self.draw.Reference( 0, -textposy, text_size )
def splitLine(linestring, point, tolerance=pcbnew.FromMM(0.01)): splitted = split(linestring, point.buffer(tolerance, resolution=1)) if len(splitted) != 3: print(splitted) raise RuntimeError("Expected 3 segments in line spitting") p1 = LineString(list(splitted[0].coords) + [point]) p2 = LineString([point] + list(splitted[2].coords)) return shapely.geometry.collection.GeometryCollection([p1, p2])
def Run(self): pcb = pcbnew.GetBoard() # Board outline frame = pcb.GetDrawings() for f in frame: if (f.GetLayerName() == "Edge.Cuts"): f.SetWidth(pcbnew.FromMM(0.01))
def PutOnGridMM(self, value, gridSizeMM=0.05): """ Round the value (in KiCAD internal units 1nm) according to the provided gridSize in mm. """ thresh = pcbnew.FromMM(gridSizeMM) res = round(value / thresh) * thresh return res
def plot_drill(self, pcb): "plot drill files" pctl = pcbnew.PLOT_CONTROLLER(pcb) drill_path = os.path.dirname( pcb.GetFileName()) + PCB_MAN_PACK_DIR + "Drill/" if not os.path.exists(drill_path): os.makedirs(drill_path) report_path = os.path.dirname(pcb.GetFileName()) + REPORTS_DIR if not os.path.exists(report_path): os.makedirs(report_path) pctl = pcbnew.PLOT_CONTROLLER(pcb) popt = pctl.GetPlotOptions() popt.SetOutputDirectory(drill_path) # Set some important plot options: popt.SetPlotFrameRef(False) popt.SetLineWidth(pcbnew.FromMM(0.1)) popt.SetAutoScale(False) popt.SetScale(1) popt.SetMirror(False) popt.SetExcludeEdgeLayer(False) popt.SetPlotValue(False) popt.SetPlotReference(False) popt.SetUseGerberAttributes(True) popt.SetUseGerberProtelExtensions(False) popt.SetUseAuxOrigin(True) # Fabricators need drill files. # sometimes a drill map file is asked (for verification purpose) drlwriter = pcbnew.EXCELLON_WRITER(pcb) drlwriter.SetMapFileFormat(pcbnew.PLOT_FORMAT_PDF) mirror = False minimalHeader = False offset = pcb.GetAuxOrigin() # False to generate 2 separate drill files (one for plated holes, one for non plated holes) # True to generate only one drill file mergeNPTH = True drlwriter.SetOptions(mirror, minimalHeader, offset, mergeNPTH) metricFmt = True drlwriter.SetFormat(metricFmt) genDrl = True genMap = True drlwriter.CreateDrillandMapFilesSet(drill_path, genDrl, genMap) # One can create a text file to report drill statistics rptfn = report_path + 'drill_report.rpt' drlwriter.GenDrillReportFile(rptfn) pctl.ClosePlot()
def processBoard(boardName, plotDir): """Convert layers of KiCad PCB to SVGs""" print(boardName) print(plotDir) # Load board and initialize plot controller board = pcbnew.LoadBoard(boardName) boardBox = board.ComputeBoundingBox() boardXl = boardBox.GetX() boardYl = boardBox.GetY() boardWidth = boardBox.GetWidth() boardHeight = boardBox.GetHeight() print(boardXl, boardYl, boardWidth, boardHeight) pctl = pcbnew.PLOT_CONTROLLER(board) pctl.SetColorMode(True) popt = pctl.GetPlotOptions() popt.SetOutputDirectory(plotDir) popt.SetPlotFrameRef(False) popt.SetLineWidth(pcbnew.FromMM(0.15)) popt.SetAutoScale(False) popt.SetScale(2) popt.SetMirror(False) popt.SetUseGerberAttributes(True) popt.SetExcludeEdgeLayer(False) popt.SetUseAuxOrigin(True) layers = [ ("F_Cu", pcbnew.F_Cu, "Top layer"), ("B_Cu", pcbnew.B_Cu, "Bottom layer"), ("B_Paste", pcbnew.B_Paste, "Paste bottom"), ("F_Paste", pcbnew.F_Paste, "Paste top"), ("F_SilkS", pcbnew.F_SilkS, "Silk top"), ("B_SilkS", pcbnew.B_SilkS, "Silk top"), ("B_Mask", pcbnew.B_Mask, "Mask bottom"), ("F_Mask", pcbnew.F_Mask, "Mask top"), ("Edge_Cuts", pcbnew.Edge_Cuts, "Edges"), ("Margin", pcbnew.Margin, "Margin"), ("In1_Cu", pcbnew.In1_Cu, "Inner1"), ("In2_Cu", pcbnew.In2_Cu, "Inner2"), ("Dwgs_User", pcbnew.Dwgs_User, "Dwgs_User"), ("Cmts_User", pcbnew.Cmts_User, "Comments_User"), ("Eco1_User", pcbnew.Eco1_User, "ECO1"), ("Eco2_User", pcbnew.Eco2_User, "ECO2"), ("B_Fab", pcbnew.B_Fab, "Fab bottom"), ("F_Fab", pcbnew.F_Fab, "Fab top"), ("B_Adhes", pcbnew.B_Adhes, "Adhesive bottom"), ("F_Adhes", pcbnew.F_Adhes, "Adhesive top"), ("B_CrtYd", pcbnew.B_CrtYd, "Courtyard bottom"), ("F_CrtYd", pcbnew.F_CrtYd, "Courtyard top"), ] for layer_info in layers: pctl.SetLayer(layer_info[1]) pctl.OpenPlotfile(layer_info[0], pcbnew.PLOT_FORMAT_SVG, layer_info[2]) pctl.PlotLayer() return (boardXl, boardYl, boardWidth, boardHeight)
def plotLayers( board, gerberDirPath, useAuxOrigin, gerberProtelExtensions, layerRenameRules, boardProjectName, ): targetLayerCount = board.GetCopperLayerCount() + 5 pc = pcbnew.PLOT_CONTROLLER(board) po = pc.GetPlotOptions() po.SetOutputDirectory(gerberDirPath) po.SetPlotValue(True) po.SetPlotReference(True) po.SetExcludeEdgeLayer(False) if hasattr(po, "SetLineWidth"): po.SetLineWidth(pcbnew.FromMM(0.1)) else: po.SetSketchPadLineWidth(pcbnew.FromMM(0.1)) po.SetSubtractMaskFromSilk(True) po.SetUseAuxOrigin(useAuxOrigin) po.SetUseGerberProtelExtensions(gerberProtelExtensions) plotFiles = [] for i in range(targetLayerCount): layerId = layers[i][0] layerTypeName = layers[i][1] pc.SetLayer(layerId) pc.OpenPlotfile(layerTypeName, pcbnew.PLOT_FORMAT_GERBER, layerTypeName) pc.PlotLayer() plotFiles.append(pc.GetPlotFileName()) pc.ClosePlot() if len(layerRenameRules) > 0: for i in range(targetLayerCount): plotFilePath = plotFiles[i] layerId = layers[i][0] if layerId in layerRenameRules: newFileName = layerRenameRules[layerId] newFileName = newFileName.replace('[boardProjectName]', boardProjectName) newFilePath = '%s/%s' % (gerberDirPath, newFileName) renameFile(plotFilePath, newFilePath)
def line_width(self, value): """ Set the line width, in mm """ if self._supports_line_width: self._line_width = pcbnew.FromMM(value) else: raise KiPlotConfigurationError( "This output doesn't support setting line width")
def arrange_diodes(): for i in range(1, 46 + 1): r = "SW" + str(i) sw = FindModuleByReference("SW" + str(i)) d = FindModuleByReference("D" + str(i)) angle = sw.GetOrientationDegrees() tmp_pos = pcbnew.ToMM(sw.GetPosition()) sw_pos = MyPosition(tmp_pos[0], tmp_pos[1]) d_pos = sw_pos + SwitchPosition(0, 0, -angle).up(-0.3).to_mm() d.SetPosition(pcbnew.wxPointMM(d_pos.x, d_pos.y)) d.SetOrientationDegrees(angle) # ref position (relative from switch position) ref = d.Reference() ref.SetTextAngle(0) ref_pos_mm = (4.1, 0) if len(str(i)) == 1 else (4.6, 0) ref_pos = pcbnew.wxPoint(pcbnew.FromMM(ref_pos_mm[0]), pcbnew.FromMM(ref_pos_mm[1])) ref.SetPos0(ref_pos)
def make_via(self, position, net_code): v = pcb.VIA(self.board) self.board.Add(v) v.SetPosition(position) v.SetViaType(pcb.VIA_THROUGH) v.SetLayerPair(LayerFCu, LayerBCu) v.SetNetCode(net_code) v.SetWidth(pcb.FromMM(DEFAULT_TRACK_WIDTH_MM)) return position
def __init__(self, module): self.module = module # drawing context defaults self.dc = { 'layer': pcbnew.F_SilkS, 'width': pcbnew.FromMM(0.2), 'transforms': [], 'transform': self.xfrmIDENTITY }
def RemovePadsIntersections(self, lines, clearance=pcbnew.FromMM(0.2), minlength=pcbnew.FromMM(0.2)): # loop stops when no more intersection was found iline = 0 while iline < len(lines): line = lines[iline] iline = iline + 1 for p in self.module.Pads(): segments = [] if self.IntersectPad(line, p, clearance, segments) == True: # found an intersection, push it at the bottom of the list and rewind the loop from the beginning lines.remove(line) for s in segments: lines.append(s) iline = 0 break
def DrawBox(self, ssx, ssy): # ---------- # |8 7 6 5 | # |1 2 3 4 | # \--------- self.draw.BoxWithDiagonalAtCorner(0, 0, ssx * 2, ssy * 2, pcbnew.FromMM(1))
def make_track_segment(self, start, end, net_code, layer): t = pcb.TRACK(self.board) self.board.Add(t) t.SetStart(start) t.SetEnd(end) t.SetNetCode(net_code) t.SetLayer(layer) t.SetWidth(pcb.FromMM(DEFAULT_TRACK_WIDTH_MM)) return end
def generate_pcb_gerber(args): logging.info('Generating PCB gerber files') check_args(args) output_dir = os.path.join(args.output_dir, 'gerber') if not os.path.exists(output_dir): os.makedirs(output_dir) logging.info(' Reading %s', args.input_pcb) board = pcbnew.LoadBoard(args.input_pcb) plot_controller = pcbnew.PLOT_CONTROLLER(board) plot_options = plot_controller.GetPlotOptions() plot_options.SetOutputDirectory(output_dir) plot_options.SetPlotFrameRef(False) plot_options.SetLineWidth(pcbnew.FromMM(0.1)) plot_options.SetAutoScale(False) plot_options.SetScale(1) plot_options.SetMirror(False) plot_options.SetUseGerberAttributes(True) plot_options.SetUseGerberProtelExtensions(True) plot_options.SetExcludeEdgeLayer(True) plot_options.SetUseAuxOrigin(False) plot_controller.SetColorMode(True) plot_options.SetSubtractMaskFromSilk(True) plot_options.SetPlotReference(True) plot_options.SetPlotValue(False) layers = [ ("F.Cu", pcbnew.F_Cu, "Top layer"), ("B.Cu", pcbnew.B_Cu, "Bottom layer"), ("F.Paste", pcbnew.F_Paste, "Paste top"), ("B.Paste", pcbnew.B_Paste, "Paste bottom"), ("F.SilkS", pcbnew.F_SilkS, "Silk top"), ("B.SilkS", pcbnew.B_SilkS, "Silk top"), ("F.Mask", pcbnew.F_Mask, "Mask top"), ("B.Mask", pcbnew.B_Mask, "Mask bottom"), ("Edge.Cuts", pcbnew.Edge_Cuts, "Edges"), ] logging.info(' Writing to %s' % output_dir) for layer_info in layers: plot_controller.SetLayer(layer_info[1]) plot_controller.OpenPlotfile(layer_info[0], pcbnew.PLOT_FORMAT_GERBER, layer_info[2]) plot_controller.PlotLayer() plot_controller.ClosePlot()
def generatePdf(plotControl, plotOptions, ): # Set some important plot options: plotOptions.SetPlotFrameRef(False) plotOptions.SetLineWidth(pcbnew.FromMM(0.35)) plotOptions.SetAutoScale(False) plotOptions.SetScale(1) plotOptions.SetMirror(False) plotOptions.SetUseGerberAttributes(True) plotOptions.SetExcludeEdgeLayer(False) plotOptions.SetScale(1) # plotOptions.SetUseAuxOrigin(True) plotOptions.SetUseAuxOrigin(False) # drill file and pdf should be the same # This by gerbers only (also the name is truly horrid!) plotOptions.SetSubtractMaskFromSilk(False) ######################### #### CuBottom.gbr #### #### CuTop.gbr #### #### EdgeCuts.gbr #### #### MaskBottom.gbr #### #### MaskTop.gbr #### #### PasteBottom.gbr #### #### PasteTop.gbr #### #### SilkBottom.gbr #### #### SilkTop.gbr #### ######################### # Once the defaults are set it become pretty easy... # I have a Turing-complete programming language here: I'll use it... # param 0 is a string added to the file base name to identify the drawing # param 1 is the layer ID plot_plan = [ # ( "CuTop", F_Cu, "Top layer" ), ( "CuBottom", pcbnew.B_Cu, "Bottom layer" ), # ( "PasteBottom", B_Paste, "Paste Bottom" ), # ( "PasteTop", F_Paste, "Paste top" ), # ( "SilkTop", F_SilkS, "Silk top" ), # ( "SilkBottom", B_SilkS, "Silk top" ), # ( "MaskTop", F_Mask, "Mask top" ), # ( "MaskBottom", B_Mask, "Mask bottom" ), # ( "EdgeCuts", Edge_Cuts, "Edges" ), ] for layer_info in plot_plan: plotControl.SetLayer(layer_info[1]) plotControl.OpenPlotfile(layer_info[0], pcbnew.PLOT_FORMAT_PDF, layer_info[2]) plotControl.PlotLayer() # plot Top inverted plotOptions.SetMirror(True) plotControl.SetLayer(pcbnew.F_Cu) plotControl.OpenPlotfile("CuTop", pcbnew.PLOT_FORMAT_PDF, "Top layer") plotControl.PlotLayer()
def BuildThisFootprint(self): pads = self.parameters["Pads"] rows = pads["*row count"] cols = pads["*column count"] pad_size = pads["pad size"] pad_size = pcbnew.wxSize(pad_size, pad_size) pad_pitch = pads["pad pitch"] # add in the pads pad = PA.PadMaker(self.module).SMTRoundPad(pads["pad size"]) pin1_pos = pcbnew.wxPoint(-((cols - 1) * pad_pitch) / 2, -((rows - 1) * pad_pitch) / 2) array = BGAPadGridArray(pad, cols, rows, pad_pitch, pad_pitch) array.AddPadsToModule(self.draw) #box ssx = -pin1_pos.x + pads["outline x margin"] ssy = -pin1_pos.y + pads["outline y margin"] self.draw.BoxWithDiagonalAtCorner(0, 0, ssx*2, ssy*2, pads["outline x margin"]) # Courtyard cmargin = self.draw.GetLineTickness() self.draw.SetLayer(pcbnew.F_CrtYd) sizex = (ssx + cmargin) * 2 sizey = (ssy + cmargin) * 2 # set courtyard line thickness to the one defined in KLC self.draw.SetLineTickness(pcbnew.FromMM(0.05)) self.draw.Box(0, 0, sizex, sizey) # restore line thickness to previous value self.draw.SetLineTickness(pcbnew.FromMM(cmargin)) #reference and value text_size = self.GetTextSize() # IPC nominal ypos = ssy + text_size self.draw.Value(0, ypos, text_size) self.draw.Reference(0, -ypos, text_size)