def run_buzzard(dlg, p_buzzard): if len(dlg.polys) == 0: dlg.EndModal(wx.ID_CANCEL) return if '5.1' in self.kicad_build_version or '5.0' in self.kicad_build_version: # Handle KiCad 5.1 filepath = self.filepath with open(filepath, 'w+') as f: f.write(p_buzzard.create_v5_footprint()) print(os.path.dirname(filepath)) board = pcbnew.GetBoard() footprint = pcbnew.FootprintLoad(os.path.dirname(filepath), 'label') footprint.SetPosition(pcbnew.wxPoint(0, 0)) board.Add(footprint) pcbnew.Refresh() # Zoom doesn't seem to work. #b = footprint.GetBoundingBox() #pcbnew.WindowZoom(b.GetX(), b.GetY(), b.GetWidth(), b.GetHeight()) elif '5.99' in self.kicad_build_version or '6.0' in self.kicad_build_version: footprint_string = p_buzzard.create_v6_footprint() if wx.TheClipboard.Open(): wx.TheClipboard.SetData(wx.TextDataObject(footprint_string)) wx.TheClipboard.Close() dlg.EndModal(wx.ID_OK)
def load_footprint(ref: str): """Load a footprint otherwise raise exception""" library, name = ref.split(":") footprint = pcbnew.FootprintLoad( os.path.join(os.environ.get("RUNFILES_DIR", "external/"), library), name) if not footprint: raise ValueError( f"can not load footprint {name} from library {library}") return footprint
def add_fp(center, footpr, brd): msg="Found Back layer footprint: {} at {}mm,{}mm. Changing to {}".format(footpr, center.x/SCALE, center.y/SCALE, footprint_convert[footpr]) msg+="\n" faceplate_mod = pcbnew.FootprintLoad(footprint_lib, footprint_convert[footpr]) faceplate_mod.SetPosition(center) # pads = faceplate_mod.Pads() # for pad in pads: # pad.SetNet(net) brd.Add(faceplate_mod) print(msg) return msg
def Run(self): pcb = pcbnew.GetBoard() # In some cases, I have seen KIPRJMOD not set correctly here. #projdir = os.environ['KIPRJMOD'] projdir = os.path.dirname(os.path.abspath(pcb.GetFileName())) filehandler = logging.FileHandler( os.path.join(projdir, "component_layout_plugin.log")) filehandler.setLevel(logging.DEBUG) formatter = logging.Formatter( '%(asctime)s %(name)s %(lineno)d:%(message)s') filehandler.setFormatter(formatter) logger = logging.getLogger(__name__) # The log setup is persistent accross plugin runs because the kicad python # kernel keeps running, so clear any existing handlers to avoid multiple # outputs while len(logger.handlers) > 0: logger.removeHandler(logger.handlers[0]) logger.addHandler(filehandler) logger.info( f'Logging to {os.path.join(projdir, "component_layout_plugin.log")}...' ) with open(os.path.join(projdir, 'layout.yaml')) as f: layout = yaml.load(f.read()) logger.info("Executing component_layout_plugin") # Redirect stdout and stderr to logfile stdout_logger = logging.getLogger('STDOUT') sl_out = StreamToLogger(stdout_logger, logging.INFO) sys.stdout = sl_out stderr_logger = logging.getLogger('STDERR') sl_err = StreamToLogger(stderr_logger, logging.ERROR) sys.stderr = sl_err if 'origin' in layout: x0 = layout['origin'][0] y0 = layout['origin'][1] else: x0 = 0.0 y0 = 0.0 if not 'components' in layout: logger.warning("No components field found in layout.yaml") for refdes, props in layout.get('components', {}).items(): mod = pcb.FindModuleByReference(refdes) if mod is None: logger.warning( f"Did not find component {refdes} in PCB design") continue flip = props.get('flip', False) # Generally, flip means put on the bottom if 'footprint' in props: # I think there's no API to map the library nickname to a library # (e.g. using the global and project libraries) so path is passed in. # I also see no way to find the path from which the footprint was # previously found, so we're only comparing the name. This should # be good enough in pretty much all cases, but it is a bit ugly. footprint_path = os.path.join(projdir, props['footprint']['path']) footprint_name = props['footprint']['name'] if mod.GetFPID().GetUniStringLibId() != footprint_name: # As far as I can tell, you can't change the footprint of a module, you have to delete and re-add # Save important properties of the existing module ref = mod.GetReference() pads = list(mod.Pads()) nets = [p.GetNet() for p in pads] value = mod.GetValue() newmod = pcbnew.FootprintLoad(footprint_path, footprint_name) if newmod is None: logging.error( f"Failed to load footprint {footprint_name} from {footprint_path}" ) raise RuntimeError( "Failed to load footprint %s from %s" % (footprint_name, footprint_path)) pcb.Delete(mod) # Restore original props to the new module newmod.SetReference(ref) for p, net in zip(pads, nets): p.SetNet(net) newmod.SetValue(value) pcb.Add(newmod) mod = newmod if 'location' in props: x = props['location'][0] y = props['location'][1] mod.SetPosition(pcbnew.wxPointMM(x0 + x, y0 + y)) if flip and not mod.IsFlipped(): mod.Flip(mod.GetPosition()) if not flip and mod.IsFlipped(): mod.Flip(mod.GetPosition()) if 'rotation' in props: rotation = props['rotation'] mod.SetOrientationDegrees(rotation)
def Run(self): import faceplate_footprint_lib footprint_lib = faceplate_footprint_lib.get_lib_location() railmount_fp = "Faceplate_Rail_Mount_Slot_Plated" SCALE = 1000000.0 msg = "" board = pcbnew.GetBoard() # Find the pcb outline and a list of the drawings on the edgecuts layer pcboutline, edgecuts_dwgs = find_pcb_outline_bbox(board) # Find the center of the pcb outline pcbcenter = pcboutline.Centre() # Move the previous edge cuts to comments layer move_drawings(edgecuts_dwgs, pcbnew.Cmts_User) # Set the fp width to the smallest standard HP size that's larger than the pcb width pcbwidth = pcboutline.GetWidth() fphp, fpwidth = find_width_to_hp(pcbwidth / SCALE) msg += "Faceplate is %d HP wide by 128.5mm high\n" % fphp # Calculate the left and right edges of the faceplate fpleft = pcbcenter.x - fpwidth * SCALE / 2.0 fpright = fpleft + fpwidth * SCALE # Calculate the top and bottom edges of the faceplate (128.5mm height) fpbottom = pcbcenter.y + 128.5 * SCALE / 2.0 fptop = fpbottom - 128.5 * SCALE # Calculate the four corners bottomleft = pcbnew.wxPoint(int(fpleft), int(fpbottom)) bottomright = pcbnew.wxPoint(int(fpright), int(fpbottom)) topleft = pcbnew.wxPoint(int(fpleft), int(fptop)) topright = pcbnew.wxPoint(int(fpright), int(fptop)) # Draw the board outline segments bottomline = pcbnew.PCB_SHAPE(board) board.Add(bottomline) bottomline.SetLayer(pcbnew.Edge_Cuts) bottomline.SetStart(bottomleft) bottomline.SetEnd(bottomright) topline = pcbnew.PCB_SHAPE(board) board.Add(topline) topline.SetLayer(pcbnew.Edge_Cuts) topline.SetStart(topleft) topline.SetEnd(topright) leftline = pcbnew.PCB_SHAPE(board) board.Add(leftline) leftline.SetLayer(pcbnew.Edge_Cuts) leftline.SetStart(topleft) leftline.SetEnd(bottomleft) rightline = pcbnew.PCB_SHAPE(board) board.Add(rightline) rightline.SetLayer(pcbnew.Edge_Cuts) rightline.SetStart(topright) rightline.SetEnd(bottomright) #add rail mount slots railmount_topleft = pcbnew.wxPoint(topleft.x + 0.295 * 25.4 * SCALE, topleft.y + 0.118 * 25.4 * SCALE) railmount_topright = pcbnew.wxPoint(topright.x - 0.295 * 25.4 * SCALE, topright.y + 0.118 * 25.4 * SCALE) railmount_bottomleft = pcbnew.wxPoint( bottomleft.x + 0.295 * 25.4 * SCALE, bottomleft.y - 0.118 * 25.4 * SCALE) railmount_bottomright = pcbnew.wxPoint( bottomright.x - 0.295 * 25.4 * SCALE, bottomright.y - 0.118 * 25.4 * SCALE) mod = pcbnew.FootprintLoad(footprint_lib, railmount_fp) mod.SetPosition(railmount_topleft) board.Add(mod) mod = pcbnew.FootprintLoad(footprint_lib, railmount_fp) mod.SetPosition(railmount_topright) board.Add(mod) mod = pcbnew.FootprintLoad(footprint_lib, railmount_fp) mod.SetPosition(railmount_bottomleft) board.Add(mod) mod = pcbnew.FootprintLoad(footprint_lib, railmount_fp) mod.SetPosition(railmount_bottomright) board.Add(mod) msg += "Creating four rail mount slots (for 8HP and smaller faceplates, delete two of these)" + "\n" msg += "You may need to refresh the display now. Select Legacy mode, then Modern mode" + "\n"
def setup_graphics(self, pcb): graphics = [ Graphic( reference="G1", footprint="oshw-logo-small", library=COZY_FOOTPRINT_LIBRARY_PATH, position=Position(190.5, 53.34, 0), layer=pcbnew.F_SilkS, ), Graphic( reference="G2", footprint="oshw-logo-small", library=COZY_FOOTPRINT_LIBRARY_PATH, position=Position(190.5, 53.34, 180), layer=pcbnew.B_SilkS, ), Graphic( reference="G3", footprint="qmk-badge", library=COZY_FOOTPRINT_LIBRARY_PATH, position=Position(172.973, 133.35, 0), layer=pcbnew.F_SilkS, ), Graphic( reference="G4", footprint="qmk-badge", library=COZY_FOOTPRINT_LIBRARY_PATH, position=Position(172.973, 133.35, 180), layer=pcbnew.B_SilkS, ), Graphic( reference="G5", footprint="speedo-attribution-small", library=COZY_FOOTPRINT_LIBRARY_PATH, position=Position(172.973, 125.73, 0), layer=pcbnew.F_SilkS, ), Graphic( reference="G6", footprint="speedo-attribution-small", library=COZY_FOOTPRINT_LIBRARY_PATH, position=Position(172.973, 125.73, 180), layer=pcbnew.B_SilkS, ), Graphic( reference="G7", footprint="cozykeys-graphic-speedo", library=COZY_FOOTPRINT_LIBRARY_PATH, position=Position(88.9, 74.93, 190), layer=pcbnew.B_SilkS, ), Graphic( reference="G8", footprint="cozykeys-graphic-speedo", library=COZY_FOOTPRINT_LIBRARY_PATH, position=Position(257.046, 74.93, 170), layer=pcbnew.B_SilkS, ), Graphic( reference="G9", footprint="dumplings-small", library=COZY_FOOTPRINT_LIBRARY_PATH, position=Position(172.973, 86.0, 0), layer=pcbnew.F_SilkS, ), Graphic( reference="G10", footprint="dumplings-small", library=COZY_FOOTPRINT_LIBRARY_PATH, position=Position(172.973, 86.0, 180), layer=pcbnew.B_SilkS, ), ] for g in graphics: self.log_info("Setting up graphic {}".format(g.reference)) module = pcb.FindModuleByReference(g.reference) if module != None: self.log_info("Found existing graphic {}, removing".format( g.reference)) pcb.Remove(module) module = pcbnew.FootprintLoad(g.library, g.footprint) if module == None: raise Exception("Failed to create graphic {}".format( g.reference)) module.SetParent(pcb) module.SetReference(g.reference) pcb.Add(module) pos = module.GetPosition() pos.x = int(g.position.x * POSITION_SCALE) pos.y = int(g.position.y * POSITION_SCALE) module.SetPosition(pos) module.SetOrientation(g.position.r * ROTATION_SCALE) module.SetLayer(pcbnew.F_SilkS) if g.layer == pcbnew.B_SilkS: module.Flip(pos)
def kinet2pcb(netlist_origin, brd_filename): """Create a .kicad_pcb from a KiCad netlist file.""" # Get the global and local fp-lib-table file URIs. fp_libs = LibURIs(get_global_fp_lib_table_fn(), os.path.join(".", "fp-lib-table")) # Create a blank KiCad PCB. brd = pcbnew.BOARD() # Get the netlist. if isinstance(netlist_origin, type('')): # Parse the netlist into an object if given a file name string. netlist = kinparse.parse_netlist(netlist_origin) else: # otherwise, the netlist is already an object that can be processed directly. netlist = netlist_origin # Add the components in the netlist to the PCB. for part in netlist.parts: # Get the library and footprint name for the part. fp_lib, fp_name = part.footprint.split(":") # Get the URI of the library directory. lib_uri = fp_libs[fp_lib] # Create a module from the footprint file. fp = pcbnew.FootprintLoad(lib_uri, fp_name) # Set the module parameters based on the part data. #import pdb; pdb.set_trace() fp.SetParent(brd) fp.SetReference(part.ref) fp.SetValue(part.value) # fp.SetTimeStamp(part.sheetpath.tstamps) try: fp.SetPath(part.sheetpath.names) except AttributeError: pass # Add the module to the PCB. brd.Add(fp) # Add the nets in the netlist to the PCB. cnct = brd.GetConnectivity() for net in netlist.nets: # Create a net with the current net name. pcb_net = pcbnew.NETINFO_ITEM(brd, net.name) # Add the net to the PCB. brd.Add(pcb_net) # Connect the part pins on the netlist net to the PCB net. for pin in net.pins: # Find the PCB module pad for the current part pin. module = brd.FindModuleByReference(pin.ref) pad = module.FindPadByName(pin.num) # Connect the pad to the PCB net. cnct.Add(pad) pad.SetNet(pcb_net) # Recalculate the PCB part and net data. brd.BuildListOfNets() cnct.RecalculateRatsnest() pcbnew.Refresh() # Place the board parts into non-overlapping areas that follow the design hierarchy. hierplace.hier_place(brd) # Save the PCB into the KiCad PCB file. pcbnew.SaveBoard(brd_filename, brd)
def setup_graphics(self, pcb): graphics = { TriadPiece.LEFT: [ Graphic( reference="G1", footprint="oshw-logo-small", library=COZY_FOOTPRINT_LIBRARY_PATH, position=Position(MID_X + 55.05, 95, 0), layer=pcbnew.F_SilkS, ), Graphic( reference="G2", footprint="oshw-logo-small", library=COZY_FOOTPRINT_LIBRARY_PATH, position=Position(MID_X + 55.05, 95, 180), layer=pcbnew.B_SilkS, ), Graphic( reference="G3", footprint="qmk-badge", library=COZY_FOOTPRINT_LIBRARY_PATH, position=Position(MID_X - 38.0935, 25.654, 0), layer=pcbnew.F_SilkS, ), Graphic( reference="G4", footprint="qmk-badge", library=COZY_FOOTPRINT_LIBRARY_PATH, position=Position(MID_X - 38.0935, 25.654, 180), layer=pcbnew.B_SilkS, ), Graphic( reference="G5", footprint="triad-attribution-small", library=COZY_FOOTPRINT_LIBRARY_PATH, position=Position(MID_X, 136, 0), layer=pcbnew.F_SilkS, ), Graphic( reference="G6", footprint="triad-attribution-small", library=COZY_FOOTPRINT_LIBRARY_PATH, position=Position(MID_X, 136, 180), layer=pcbnew.B_SilkS, ), ], TriadPiece.CENTER: [], TriadPiece.RIGHT: [ Graphic( reference="G1", footprint="oshw-logo-small", library=COZY_FOOTPRINT_LIBRARY_PATH, position=Position(MID_X - 55.05, 95, 0), layer=pcbnew.F_SilkS, ), Graphic( reference="G2", footprint="oshw-logo-small", library=COZY_FOOTPRINT_LIBRARY_PATH, position=Position(MID_X - 55.05, 95, 180), layer=pcbnew.B_SilkS, ), Graphic( reference="G3", footprint="qmk-badge", library=COZY_FOOTPRINT_LIBRARY_PATH, position=Position(MID_X + 38.0935, 25.654, 0), layer=pcbnew.F_SilkS, ), Graphic( reference="G4", footprint="qmk-badge", library=COZY_FOOTPRINT_LIBRARY_PATH, position=Position(MID_X + 38.0935, 25.654, 180), layer=pcbnew.B_SilkS, ), Graphic( reference="G5", footprint="triad-attribution-small", library=COZY_FOOTPRINT_LIBRARY_PATH, position=Position(MID_X, 136, 0), layer=pcbnew.F_SilkS, ), Graphic( reference="G6", footprint="triad-attribution-small", library=COZY_FOOTPRINT_LIBRARY_PATH, position=Position(MID_X, 136, 180), layer=pcbnew.B_SilkS, ), ], } for g in graphics[self.piece]: module = pcb.FindModuleByReference(g.reference) if module != None: self.log_info("Found existing graphic {}, removing".format( g.reference)) pcb.Remove(module) module = pcbnew.FootprintLoad(g.library, g.footprint) module.SetParent(pcb) module.SetReference(g.reference) pcb.Add(module) pos = module.GetPosition() pos.x = int(g.position.x * POSITION_SCALE) pos.y = int(g.position.y * POSITION_SCALE) module.SetPosition(pos) module.SetOrientation(g.position.r * ROTATION_SCALE) module.SetLayer(pcbnew.F_SilkS) if g.layer == pcbnew.B_SilkS: module.Flip(pos)
def Run(self): self.logger = Logger() self.initialize_dialog() self.log_info("Running version {}".format(self.version)) self.log_info("Running wxPython version {}".format(self.wx_version)) self.log_info("Logging to directory {}".format(self.logger.path)) if self.local_build: self.initialize_footprint_cache() pcb = pcbnew.GetBoard() # -------------------- TODO -------------------- # z = pcb.Zones() # for i in range(0, len(z)): # outline = z[i].Outline() # # outline.RemoveAllContours() # outline.NewOutline() # outline.Append(pcbnew.VECTOR2I(int(0.0 * POSITION_SCALE), int(0.0 * POSITION_SCALE))) # outline.Append(pcbnew.VECTOR2I(int(10.0 * POSITION_SCALE), int(0.0 * POSITION_SCALE))) # outline.Append(pcbnew.VECTOR2I(int(10.0 * POSITION_SCALE), int(10.0 * POSITION_SCALE))) # outline.Append(pcbnew.VECTOR2I(int(0.0 * POSITION_SCALE), int(10.0 * POSITION_SCALE))) # # z[i].SetOutline(outline) # # return # -------------------- TODO -------------------- self.piece = self.detect_piece(pcb) self.log_info("Running Kicad plugin on Triad piece {}".format( self.piece)) self.switch_data = SwitchData(self.piece) # Set switch and diode positions key_count = 13 if self.piece == TriadPiece.CENTER else 37 for i in range(0, key_count): key_id = "K{}".format(str(i).zfill(2)) # key_id = 'K{}'.format(i) key = pcb.FindModuleByReference(key_id) if key == None: raise Exception("No key with id {} found".format(key_id)) self.set_key_position(key) diode_id = "D{}".format(str(i).zfill(2)) # diode_id = 'D{}'.format(i) diode = pcb.FindModuleByReference(diode_id) if diode == None: raise Exception("No diode with id {} found".format(diode_id)) self.set_diode_position(diode) # Set Pin Header positions pin_header_count = 2 if self.piece == TriadPiece.CENTER else 1 for i in range(0, pin_header_count): pin_header_id = "J{}".format(i + 1) pin_header = pcb.FindModuleByReference(pin_header_id) if pin_header == None: raise Exception( "No pin_header with id {} found".format(pin_header_id)) self.set_pin_header_position(pin_header) # Set LED positions for i in range(0, 4): led_id = "L{}".format(i + 1) led = pcb.FindModuleByReference(led_id) if led == None: raise Exception("No led with id {} found".format(led_id)) self.log_info("Found LED {}".format(led_id)) self.set_led_position(led) # Setup M2 spacer holes for i in range(0, 4): hole_id = "H{}".format(i + 1) hole = pcb.FindModuleByReference(hole_id) if hole == None: self.log_info("No hole {} found, creating it".format(hole_id)) hole = pcbnew.FootprintLoad(COZY_FOOTPRINT_LIBRARY_PATH, "HOLE_M2_SPACER") hole.SetParent(pcb) hole.SetReference(hole_id) pcb.Add(hole) else: self.log_info("Found hole {}".format(hole_id)) self.set_hole_position(hole) # Set positions for the electronics on the center piece if self.piece == TriadPiece.CENTER: mcu_id = "U1" mcu = pcb.FindModuleByReference(mcu_id) if mcu == None: self.log_warn("No mcu with id {} found".format(mcu_id)) else: self.log_info("Found MCU {}".format(mcu_id)) self.set_mcu_position(mcu) # Capacitors for i in range(0, 8): capacitor_id = "C{}".format(i + 1) capacitor = pcb.FindModuleByReference(capacitor_id) if capacitor == None: self.log_warn( "No capacitor with id {} found".format(capacitor_id)) self.set_capacitor_position(capacitor) # Resistors for i in range(0, 6): resistor_id = "R{}".format(i + 1) resistor = pcb.FindModuleByReference(resistor_id) if resistor == None: self.log_warn( "No resistor with id {} found".format(resistor_id)) self.set_resistor_position(resistor) # Crystal crystal_id = "X1" crystal = pcb.FindModuleByReference(crystal_id) if crystal == None: self.log_warn("No crystal with id {} found".format(crystal_id)) self.set_crystal_position(crystal) # Reset switch reset_switch_id = "SW1" reset_switch = pcb.FindModuleByReference(reset_switch_id) if reset_switch == None: self.log_warn( "No reset_switch with id {} found".format(reset_switch_id)) self.set_reset_switch_position(reset_switch) # USB port usb_port_id = "J3" usb_port = pcb.FindModuleByReference(usb_port_id) if usb_port == None: self.log_warn( "No usb_port with id {} found".format(usb_port_id)) self.set_usb_port_position(usb_port) # OLED oled_id = "J4" oled = pcb.FindModuleByReference(oled_id) if oled == None: self.log_warn("No oled with id {} found".format(oled_id)) self.set_oled_position(oled) # Remove all existing drawings on the Edge.Cuts line, then add the # desired edge cut segments for d in pcb.GetDrawings(): if d.GetLayerName() == "Edge.Cuts": self.log_info("Found a drawing on Edge.Cuts layer") pcb.Remove(d) self.draw_edge_cuts(pcb) self.setup_text(pcb) self.setup_graphics(pcb)
def run_buzzard(str): import re if self.kicad_version.find("5.99") != -1: str = str + ' -o ki -stdout' else: str = str + ' -o ki-5.1.x -stdout' args = [a.strip('"') for a in re.findall('".+?"|\S+', str)] if sys.platform.startswith('win'): args = [re.sub('([<>])', r'^\1', a) for a in args] # escape '<' or '>' with a caret, '^<' # Execute Buzzard process = None if sys.platform.startswith('linux') or sys.platform == 'darwin': process = subprocess.Popen(['python3', buzzard_script] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) else: process = subprocess.Popen(['python3', buzzard_script] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) stdout, stderr = process.communicate() if stderr: wx.MessageBox(stderr, 'Error', wx.OK | wx.ICON_ERROR) # check for errors error_line = [ s for s in stderr.decode('utf8').split('\n') if 'error' in s ] if len(error_line) > 0: wx.MessageBox(error_line[0], 'Error', wx.OK | wx.ICON_ERROR) else: if self.kicad_version.find("5.99") != -1: # Copy footprint into clipboard if sys.platform.startswith('linux'): clip_args = ['xclip', '-sel', 'clip', '-noutf8'] elif sys.platform == 'darwin': clip_args = ['pbcopy'] else: clip_args = ['clip.exe'] process = subprocess.Popen(clip_args, stdin=subprocess.PIPE) process.communicate(stdout) else: filepath = tempfile.gettempdir( ) + "/" + self.buzzard_label_library_path try: os.mkdir(filepath) except: pass fout = open( filepath + "/" + self.buzzard_label_module_name + ".kicad_mod", "w+") fout.write(stdout.decode('utf-8')) fout.close() board = pcbnew.GetBoard() footprint = pcbnew.FootprintLoad( filepath, self.buzzard_label_module_name) footprint.SetPosition(pcbnew.wxPoint(0, 0)) board.Add(footprint) pcbnew.Refresh() dlg.EndModal(wx.ID_OK)