def BuildFootprint(self): """! Actually make the footprint. We defer all but the set-up to the implementing class """ self.buildmessages = "" self.module = pcbnew.FOOTPRINT(None) # create a new module # Perform default checks on all parameters for p in self.params: p.ClearErrors() p.Check() # use defaults self.CheckParameters() # User error checks if self.AnyErrors(): # Errors were detected! self.buildmessages = ("Cannot build footprint: " "Parameters have errors:\n") for p in self.params: if len(p.error_list) > 0: self.buildmessages += "['{page}']['{name}']:\n".format( page=p.page, name=p.name) for error in p.error_list: self.buildmessages += "\t" + error + "\n" return self.buildmessages = ( "Building new {name} footprint with the following parameters:\n". format(name=self.name)) self.buildmessages += self.Show() self.draw = FootprintWizardDrawingAids(self.module) self.module.SetValue(self.GetValue()) self.module.SetReference("%s**" % self.GetReferencePrefix()) fpid = pcbnew.LIB_ID("", self.module.GetValue() ) # the lib name (empty) and the name in library self.module.SetFPID(fpid) self.SetModule3DModel() # add a 3D module if specified thick = self.GetTextThickness() self.module.Reference().SetTextThickness(thick) self.module.Value().SetTextThickness(thick) self.BuildThisFootprint() # implementer's build function return
def compat_libitem_func(instance): try: test_obj = pcbnew.FPID() except AttributeError: test_obj = pcbnew.LIB_ID() if not hasattr(test_obj, "GetLibItemName"): return MethodType(lambda self, x: x.GetFootprintName(), instance) else: return MethodType(lambda self, x: x.GetLibItemName(), instance)
def get_via_module(board, drill, diameter, net): n = 'VIA-{}-{}'.format(fmt(drill), fmt(diameter)) # instantiate new module m = pcbnew.MODULE(board) m.SetReference('REF**') m.SetValue(n) m.SetLastEditTime(pcbnew.GetNewTimeStamp()) # adjust reference and value display settings r = m.Reference() r.SetVisible(False) r.SetTextSize(pcbnew.wxSize(mm2kicad(0.3), mm2kicad(0.3))) r.SetThickness(mm2kicad(0.075)) v = m.Value() v.SetVisible(False) v.SetTextSize(pcbnew.wxSize(mm2kicad(0.3), mm2kicad(0.3))) v.SetThickness(mm2kicad(0.075)) #v.SetLayer() # TODO: Move value to F.Fab layer (F.SilkS is default) lib_id = pcbnew.LIB_ID(n) m.SetFPID(lib_id) # create through-hole pad pad = pcbnew.D_PAD(m) pad.SetPadName('1') pad.SetNet(net) pad.SetPosition(pcbnew.wxPoint(0, 0)) pad.SetShape(pcbnew.PAD_SHAPE_CIRCLE) pad.SetSize(pcbnew.wxSize(diameter, diameter)) pad.SetDrillShape(pcbnew.PAD_DRILL_SHAPE_CIRCLE) pad.SetDrillSize(pcbnew.wxSize(drill, drill)) pad.SetLayerSet(pcbnew.LSET.AllCuMask()) pad.SetZoneConnection(pcbnew.PAD_ZONE_CONN_FULL) # add pad to module m.Add(pad) return m
def BuildFootprint(self): """ Actually make the footprint. We defer all but the setup to the implementing class """ self.buildmessages = "" self.module = pcbnew.MODULE(None) # create a new module # do it first, so if we return early, we don't segfault KiCad if not self.ProcessParameters(): self.buildmessages = "Cannot build footprint: Parameters have errors:\n" self.buildmessages += self._PrintParameterErrors() return self.buildmessages = ( "Building new %s footprint with the following parameters:\n" % self.name) self.buildmessages += self._PrintParameterTable() self.draw = FootprintWizardDrawingAids.FootprintWizardDrawingAids( self.module) self.module.SetValue(self.GetValue()) self.module.SetReference("%s**" % self.GetReferencePrefix()) fpid = pcbnew.LIB_ID(self.module.GetValue()) # the name in library self.module.SetFPID(fpid) self.SetModule3DModel() # add a 3d module if specified thick = self.GetTextThickness() self.module.Reference().SetThickness(thick) self.module.Value().SetThickness(thick) self.BuildThisFootprint() # implementer's build function return
def Run(self): """ The entry function of the plugin that is executed on user action """ board = pcbnew.GetBoard() # TODO also aggregate and bin by optional attributes, like tolerances radii = set() circles = [] # TODO don't add an extra hole in same place -> overwrite # get circles drawn on board # TODO maybe include some means of filtering out possible circular board outline drawing_list = board.DrawingsList() for d in drawing_list: if d.GetLayerName() == 'Edge.Cuts': # to gaurd against random stuff being on edge cuts for some reason # causing weird errors assert type( d) == pcbnew.DRAWSEGMENT, 'non-DRAWSEGMENT on Edge.Cuts' if d.GetShapeStr() == 'Circle': # TODO check these are what i want, and don't need modification # w/ thickness or whatever (check using dxf import) r = d.GetRadius() radii.add(r) c = d.GetCenter() circles.append((c.x, c.y, r)) # TODO make optional # how to do? board.RemoveNative(d) # TODO option to use nearest hole in existing library option / next largest # (report error) # TODO easiest way to get available footprints (and their radii?) # TODO option to take a set of target hole sizes (for DFM purposes) # TODO include either global use next largest / next smallest # (maybe ignore locked, and say that, to complement this?) # or let people check for each hole whether they want to use next up or down # TODO option to make new hole components and put in project specific library # TODO include field for library to be saved to (maybe mandatory if this option?) # TODO fail gracefully if board filename is empty (board not saved yet) target_footprint_lib = '.'.join(str(board.GetFileName()).split('.')[:-1]) \ + '.pretty' if not os.path.exists(target_footprint_lib): print('creating project specific footprint library' + \ ' {}'.format(target_footprint_lib)) pcbnew.PCB_IO().FootprintLibCreate(target_footprint_lib) else: print('using footprint library {}'.format(target_footprint_lib)) # make a new footprint for each distinct hole radius we need # save to project specific library by default for r in radii: r_mm = nm_to_mm(r) print('generating footprint for hole of radius {}mm'.format(r_mm)) footprint = pcbnew.MODULE(None) # for non-electronic parts like these footprint.SetAttributes(pcbnew.MOD_VIRTUAL) footprint.SetLastEditTime() footprint.SetKeywords('non-plated through hole NPTH') # TODO it looks like the module itself needs to be specified to be on F.Cu? # how? (see github for example output) # TODO set tags to include non-plated through hole, npth? #footprint.SetDescription('{}mm diameter non-plated through hole') pad = pcbnew.D_PAD(footprint) # other library mounting hole pads seem to have this pad number pad.SetName('1') # TODO does this change the layers and stuff automatically? pad shape? pad.SetAttribute(pcbnew.PAD_ATTRIB_HOLE_NOT_PLATED) pad.SetShape(pcbnew.PAD_SHAPE_CIRCLE) # TODO do i need setsize / setstartend? # size seems to equal (r, r) for existing npth library parts # all holes in KiCad currently have to reside on one of the (external?) # copper layers (F.Cu should be one of these layers. mask the other?) pad.SetLayerSet(pcbnew.D_PAD_UnplatedHoleMask()) # TODO are holes alone actually rendered, or do you need the other stuff? # there seems to be a PAD_DRILL_SHAPE_CIRCLE and PAD_DRILL_SHAPE_OBLONG # but when are they ever not circular? oblong = limited routing? # would advanced circuits do oblong, for instance? #pad.SetDrillShape() # huh??? # TODO why isn't this a single number? what gens (drill X)? # TODO why is x in (size x x) slightly larger than 1.5? pad.SetDrillSize(pcbnew.wxSize(r, r)) footprint.Add(pad) footprint_id = 'R{}mm_NPTH'.format(r_mm) footprint.SetReference(footprint_id) ''' footprint.Reference().SetPosition(pcbnew.wxPoint()1) footprint.Value().SetPosition(pcbnew.wxPoint()1) ''' # aiming for a visible layer that does not translate into manufacture comment_layer_id = get_layer_id_by_name('Cmts.User') footprint.Reference().SetLayer(comment_layer_id) footprint.Value().SetLayer(comment_layer_id) # this is the filename, preceeding .kicad_mod fpid = pcbnew.LIB_ID(footprint_id) footprint.SetFPID(fpid) # seems to work to lock all imports by default footprint.SetLocked(True) print('saving footprint to {}'.format(os.path.join(\ target_footprint_lib, footprint_id + '.kicad_mod'))) pcbnew.PCB_IO().FootprintSave(target_footprint_lib, footprint) for x, y, r_curr in circles: if r == r_curr: f_new = pcbnew.PCB_IO().FootprintLoad( target_footprint_lib, footprint_id) f_new.SetPosition(pcbnew.wxPoint(x, y)) board.Add(f_new)