Beispiel #1
0
def separate(input, output, source, debug):
    """
    Separate a single board out of a multi-board design. The separated board is
    placed in the middle of the sheet.

    You can specify the board via bounding box or annotation. See documentation
    for further details on usage.
    """
    try:
        from kikit import panelize_ui_impl as ki
        from kikit.panelize import Panel
        from pcbnew import LoadBoard, wxPointMM

        preset = ki.obtainPreset([],
                                 validate=False,
                                 source=source,
                                 debug=debug)

        board = LoadBoard(input)
        sourceArea = ki.readSourceArea(preset["source"], board)

        panel = Panel()
        panel.inheritDesignSettings(input)
        panel.inheritProperties(input)
        destination = wxPointMM(150, 100)
        panel.appendBoard(input, destination, sourceArea)
        panel.save(output)
    except Exception as e:
        sys.stderr.write("An error occurred: " + str(e) + "\n")
        sys.stderr.write("No output files produced\n")
        if isinstance(preset, dict) and preset["debug"]["trace"]:
            traceback.print_exc(file=sys.stderr)
        sys.exit(1)
Beispiel #2
0
def separate(input, output, source, page, debug, keepannotations):
    """
    Separate a single board out of a multi-board design. The separated board is
    placed in the middle of the sheet.

    You can specify the board via bounding box or annotation. See documentation
    for further details on usage.
    """
    try:
        from kikit import panelize_ui_impl as ki
        from kikit.panelize import Panel
        from pcbnewTransition.transition import isV6, pcbnew
        from pcbnew import LoadBoard, wxPointMM
        from kikit.common import fakeKiCADGui
        app = fakeKiCADGui()

        preset = ki.obtainPreset([], validate=False, source=source, page=page, debug=debug)

        if preset["debug"]["deterministic"] and isV6():
            pcbnew.KIID.SeedGenerator(42)

        board = LoadBoard(input)
        sourceArea = ki.readSourceArea(preset["source"], board)

        panel = Panel(output)
        panel.inheritDesignSettings(board)
        panel.inheritProperties(board)
        panel.inheritTitleBlock(board)

        destination = wxPointMM(150, 100)
        panel.appendBoard(input, destination, sourceArea,
            interpretAnnotations=(not keepannotations))
        ki.setStackup(preset["source"], panel)
        ki.positionPanel(preset["page"], panel)
        ki.setPageSize(preset["page"], panel, board)

        panel.save(reconstructArcs=True)
    except Exception as e:
        import sys
        sys.stderr.write("An error occurred: " + str(e) + "\n")
        sys.stderr.write("No output files produced\n")
        if isinstance(preset, dict) and preset["debug"]["trace"]:
            traceback.print_exc(file=sys.stderr)
        sys.exit(1)
Beispiel #3
0
def place_switches(c):
    OFFSET = wxPoint(FromMM(100), FromMM(50))
    KEY_DISTANCE = 19.05

    b = LoadBoard(KICAD_PCB)
    for row in range(5):
        for col in range(6):
            i = col + 6 * row + 1
            m = b.FindModuleByReference(f"SW{i}")
            x = FromMM(KEY_DISTANCE * col)
            y = FromMM(KEY_DISTANCE) * row
            m.SetPosition(wxPoint(x, y) + OFFSET)

            m = b.FindModuleByReference(f"D{i}")
            x = FromMM(KEY_DISTANCE) * col + FromMM(KEY_DISTANCE) / 2
            y = FromMM(KEY_DISTANCE) * row
            m.SetPosition(wxPoint(x, y) + OFFSET)
            m.SetOrientation(270 * 10)

    b.Save(b.GetFileName())
Beispiel #4
0
    def appendBoard(self,
                    filename,
                    destination,
                    sourceArea=None,
                    origin=Origin.Center,
                    rotationAngle=0,
                    shrink=False,
                    tolerance=0,
                    bufferOutline=fromMm(0.001),
                    netRenamer=None,
                    refRenamer=None):
        """
        Appends a board to the panel.

        The sourceArea (wxRect) of the board specified by filename is extracted
        and placed at destination (wxPoint). The source area (wxRect) can be
        auto detected if it is not provided. Only board items which fit entirely
        into the source area are selected. You can also specify rotation. Both
        translation and rotation origin are specified by origin. Origin
        specifies which point of the sourceArea is used for translation and
        rotation (origin it is placed to destination). It is possible to specify
        coarse source area and automatically shrink it if shrink is True.
        Tolerance enlarges (even shrinked) source area - useful for inclusion of
        filled zones which can reach out of the board edges.

        You can also specify functions which will rename the net and ref names.
        By default, nets are renamed to "Board_{n}-{orig}", refs are unchanged.
        The renamers are given board seq number and original name

        Returns bounding box (wxRect) of the extracted area placed at the
        destination and the extracted substrate of the board.
        """
        board = LoadBoard(filename)
        thickness = board.GetDesignSettings().GetBoardThickness()
        if self.boardCounter == 0:
            self.board.GetDesignSettings().SetBoardThickness(thickness)
        else:
            panelThickness = self.board.GetDesignSettings().GetBoardThickness()
            if panelThickness != thickness:
                raise PanelError(f"Cannot append board {filename} as its " \
                                 f"thickness ({toMm(thickness)} mm) differs from " \
                                 f"thickness of the panel ({toMm(panelThickness)}) mm")
        self.boardCounter += 1
        self.inheritCopperLayers(board)

        if not sourceArea:
            sourceArea = findBoardBoundingBox(board)
        elif shrink:
            sourceArea = findBoardBoundingBox(board, sourceArea)
        enlargedSourceArea = expandRect(sourceArea, tolerance)
        originPoint = getOriginCoord(origin, sourceArea)
        translation = wxPoint(destination[0] - originPoint[0],
                              destination[1] - originPoint[1])

        if netRenamer is None:
            netRenamer = lambda x, y: self._uniquePrefix() + y
        renameNets(board, lambda x: netRenamer(self.boardCounter, x))
        if refRenamer is not None:
            renameRefs(board, lambda x: refRenamer(self.boardCounter, x))

        drawings = collectItems(board.GetDrawings(), enlargedSourceArea)
        footprints = collectFootprints(board.GetFootprints(),
                                       enlargedSourceArea)
        tracks = collectItems(board.GetTracks(), enlargedSourceArea)
        zones = collectItems(board.Zones(), enlargedSourceArea)

        edges = []
        for footprint in footprints:
            footprint.Rotate(originPoint, rotationAngle)
            footprint.Move(translation)
            edges += removeCutsFromFootprint(footprint)
            appendItem(self.board, footprint)
        for track in tracks:
            track.Rotate(originPoint, rotationAngle)
            track.Move(translation)
            appendItem(self.board, track)
        for zone in zones:
            zone.Rotate(originPoint, rotationAngle)
            zone.Move(translation)
            appendItem(self.board, zone)
        for netId in board.GetNetInfo().NetsByNetcode():
            self.board.Add(board.GetNetInfo().GetNetItem(netId))

        # Treat drawings differently since they contains board edges
        for drawing in drawings:
            drawing.Rotate(originPoint, rotationAngle)
            drawing.Move(translation)
        edges += [edge for edge in drawings if isBoardEdge(edge)]
        otherDrawings = [edge for edge in drawings if not isBoardEdge(edge)]
        try:
            s = Substrate(edges, bufferOutline)
            self.boardSubstrate.union(s)
            self.substrates.append(s)
        except substrate.PositionError as e:
            point = undoTransformation(e.point, rotationAngle, originPoint,
                                       translation)
            raise substrate.PositionError(filename + ": " + e.origMessage,
                                          point)
        for drawing in otherDrawings:
            appendItem(self.board, drawing)
        return findBoundingBox(edges)
Beispiel #5
0
    def appendBoard(self,
                    filename,
                    destination,
                    sourceArea=None,
                    origin=Origin.Center,
                    rotationAngle=0,
                    shrink=False,
                    tolerance=0):
        """
        Appends a board to the panel.

        The sourceArea (wxRect) of the board specified by filename is extracted
        and placed at destination (wxPoint). The source area (wxRect) can be
        auto detected if it is not provided. Only board items which fit entirely
        into the source area are selected. You can also specify rotation. Both
        translation and rotation origin are specified by origin. Origin
        specifies which point of the sourceArea is used for translation and
        rotation (origin it is placed to destination). It is possible to specify
        coarse source area and automatically shrink it if shrink is True.
        Tolerance enlarges (even shrinked) source area - useful for inclusion of
        filled zones which can reach out of the board edges.

        Returns bounding box (wxRect) of the extracted area placed at the
        destination.
        """
        board = LoadBoard(filename)
        self.boardCounter += 1

        if not sourceArea:
            sourceArea = findBoardBoundingBox(board)
        elif shrink:
            sourceArea = findBoardBoundingBox(board, sourceArea)
        tightSourceArea = findBoardBoundingBox(
            board, expandRect(sourceArea, fromMm(1)))
        enlargedSourceArea = expandRect(sourceArea, tolerance)
        originPoint = getOriginCoord(origin, sourceArea)
        translation = wxPoint(destination[0] - originPoint[0],
                              destination[1] - originPoint[1])
        tightSourceArea = translateRect(tightSourceArea, translation)

        self._makeNetNamesUnique(board)

        drawings = collectItems(board.GetDrawings(), enlargedSourceArea)
        modules = collectItems(board.GetModules(), enlargedSourceArea)
        tracks = collectItems(board.GetTracks(), enlargedSourceArea)
        zones = collectItems(board.Zones(), enlargedSourceArea)

        for module in modules:
            module.Rotate(originPoint, rotationAngle)
            module.Move(translation)
            appendItem(self.board, module)
        for track in tracks:
            track.Rotate(originPoint, rotationAngle)
            track.Move(translation)
            appendItem(self.board, track)
        for zone in zones:
            zone.Rotate(originPoint, rotationAngle)
            zone.Move(translation)
            appendItem(self.board, zone)
        for netId in board.GetNetInfo().NetsByNetcode():
            self.board.Add(board.GetNetInfo().GetNetItem(netId))

        # Treat drawings differently since they contains board edges
        for drawing in drawings:
            drawing.Rotate(originPoint, rotationAngle)
            drawing.Move(translation)
        edges = [
            edge for edge in drawings if edge.GetLayerName() == "Edge.Cuts"
        ]
        otherDrawings = [
            edge for edge in drawings if edge.GetLayerName() != "Edge.Cuts"
        ]
        self.boardSubstrate.union(Substrate(edges))
        for drawing in otherDrawings:
            appendItem(self.board, drawing)
        return tightSourceArea
Beispiel #6
0
 Edge_Cuts as Cutout, wxPoint as wxPt, FromMils, FromMM
from os import path as pt
import re

# generate vectors from dimensions
step_vector = wxPt(Units(step_x), Units(step_y))
offset_vector = wxPt(Units(offset_x), Units(offset_y))
center = wxPt(Units(center_x), Units(center_y))

# derived file names
fileNameSave = "%s-panelized.%s" % tuple(fileNamePCB.rsplit('.', 1))
fileNameCommonParts = "%s-panel-common.%s" % tuple(fileNamePCB.rsplit('.', 1))

# load PCB
print("Reading file: '%s'\n" % fileNamePCB)
pcb = LoadBoard(fileNamePCB)
print("\n")

# get all items
lsItems = brdItemize(pcb)

# delete original items
for Item in lsItems:
    pcb.Remove(Item)

boardcount = 0
# global variable is fine here for counting boards

# instantiate boards @ different rotations
for angle in angles:
    pcb_instanciate_multiple_boards(pcb, lsItems, nx, ny, step_vector,
Beispiel #7
0
def panelize(input, output, preset, layout, source, tabs, cuts, framing,
             tooling, fiducials, text, post, debug, dump):
    """
    Panelize boards
    """
    try:
        # Hide the import in the function to make KiKit start faster
        from kikit import panelize_ui_impl as ki
        from kikit.panelize import Panel
        from pcbnew import LoadBoard, wxPointMM
        import json
        import commentjson
        import sys
        from itertools import chain

        preset = ki.obtainPreset(preset,
                                 layout=layout,
                                 source=source,
                                 tabs=tabs,
                                 cuts=cuts,
                                 framing=framing,
                                 tooling=tooling,
                                 fiducials=fiducials,
                                 text=text,
                                 post=post,
                                 debug=debug)

        board = LoadBoard(input)

        panel = Panel()
        panel.inheritDesignSettings(input)
        panel.inheritProperties(input)

        sourceArea = ki.readSourceArea(preset["source"], board)
        substrates = ki.buildLayout(preset["layout"], panel, input, sourceArea)
        framingSubstrates = ki.dummyFramingSubstrate(
            substrates, ki.frameOffset(preset["framing"]))
        panel.buildPartitionLineFromBB(framingSubstrates)

        tabCuts = ki.buildTabs(preset["tabs"], panel, substrates,
                               framingSubstrates)
        backboneCuts = ki.buildBackBone(preset["layout"], panel, substrates,
                                        ki.frameOffset(preset["framing"]))
        frameCuts = ki.buildFraming(preset["framing"], panel)

        ki.buildTooling(preset["tooling"], panel)
        ki.buildFiducials(preset["fiducials"], panel)
        ki.buildText(preset["text"], panel)
        ki.buildPostprocessing(preset["post"], panel)

        ki.makeTabCuts(preset["cuts"], panel, tabCuts)
        ki.makeOtherCuts(preset["cuts"], panel, chain(backboneCuts, frameCuts))

        ki.runUserScript(preset["post"], panel)

        ki.buildDebugAnnotation(preset["debug"], panel)

        panel.save(output)

        if (dump):
            with open(dump, "w") as f:
                f.write(ki.dumpPreset(preset))
    except Exception as e:
        import sys
        sys.stderr.write("An error occurred: " + str(e) + "\n")
        sys.stderr.write("No output files produced\n")
        if isinstance(preset, dict) and preset["debug"]["trace"]:
            traceback.print_exc(file=sys.stderr)
        sys.exit(1)
Beispiel #8
0
def processBoard(boardName, plotDir, quiet):
    '''Load board and initialize plot controller'''

    board = LoadBoard(boardName)
    boardbox = board.ComputeBoundingBox()
    boardxl = boardbox.GetX()
    boardyl = boardbox.GetY()
    boardwidth = boardbox.GetWidth()
    boardheight = boardbox.GetHeight()

    if not quiet:
        print(boardxl, boardyl, boardwidth, boardheight)

    pctl = PLOT_CONTROLLER(board)
    pctl.SetColorMode(True)

    popt = pctl.GetPlotOptions()
    popt.SetOutputDirectory(plotDir)
    popt.SetPlotFrameRef(False)
    popt.SetLineWidth(FromMM(0.15))
    popt.SetAutoScale(False)
    popt.SetScale(2)
    popt.SetMirror(False)
    popt.SetUseGerberAttributes(True)
    popt.SetExcludeEdgeLayer(False)
    popt.SetUseAuxOrigin(True)

    layers = [
        ("F_Cu",      F_Cu,      "Top copper"),
        ("In1_Cu",    In1_Cu,    "Inner1 copper"),
        ("In2_Cu",    In2_Cu,    "Inner2 copper"),
        ("In3_Cu",    In3_Cu,    "Inner3 copper"),
        ("In4_Cu",    In4_Cu,    "Inner4 copper"),
        ("B_Cu",      B_Cu,      "Bottom copper"),
        ("F_Adhes",   F_Adhes,   "Adhesive top"),
        ("B_Adhes",   B_Adhes,   "Adhesive bottom"),
        ("F_Paste",   F_Paste,   "Paste top"),
        ("B_Paste",   B_Paste,   "Paste bottom"),
        ("F_SilkS",   F_SilkS,   "Silk top"),
        ("B_SilkS",   B_SilkS,   "Silk top"),
        ("F_Mask",    F_Mask,    "Mask top"),
        ("B_Mask",    B_Mask,    "Mask bottom"),
        ("Dwgs_User", Dwgs_User, "User drawings"),
        ("Cmts_User", Cmts_User, "User comments"),
        ("Eco1_User", Eco1_User, "Eng change order 1"),
        ("Eco2_User", Eco2_User, "Eng change order 1"),
        ("Edge_Cuts", Edge_Cuts, "Edges"),
        ("Margin",    Margin,    "Margin"),
        ("F_CrtYd",   F_CrtYd,   "Courtyard top"),
        ("B_CrtYd",   B_CrtYd,   "Courtyard bottom"),
        ("F_Fab",     F_Fab,     "Fab top"),
        ("B_Fab",     B_Fab,     "Fab bottom")
    ]

    for layer_info in layers:
        pctl.SetLayer(layer_info[1])
        pctl.OpenPlotfile(layer_info[0], PLOT_FORMAT_SVG, layer_info[2])
        layer_name = board.GetLayerName(layer_info[1]).replace(".", "_")
        if layer_info[0] != layer_name:
            pctl.OpenPlotfile(layer_name, PLOT_FORMAT_SVG, layer_info[2])
        pctl.PlotLayer()

    return (boardxl, boardyl, boardwidth, boardheight)
Beispiel #9
0
def doPanelization(input, output, preset, plugins=[]):
    """
    The panelization logic is separated into a separate function so we can
    handle errors based on the context; e.g., CLI vs GUI
    """
    from kikit import panelize_ui_impl as ki
    from kikit.panelize import Panel
    from pcbnewTransition.transition import isV6, pcbnew
    from pcbnew import LoadBoard
    from itertools import chain

    if preset["debug"]["deterministic"] and isV6():
        pcbnew.KIID.SeedGenerator(42)
    if preset["debug"]["drawtabfail"]:
        import kikit.substrate
        kikit.substrate.TABFAIL_VISUAL = True

    board = LoadBoard(input)
    panel = Panel(output)

    useHookPlugins = ki.loadHookPlugins(plugins, board, preset)

    useHookPlugins(lambda x: x.prePanelSetup(panel))

    # Register extra footprints for annotations
    for tabFootprint in preset["tabs"]["tabfootprints"]:
        panel.annotationReader.registerTab(tabFootprint.lib, tabFootprint.footprint)

    panel.inheritDesignSettings(board)
    panel.inheritProperties(board)
    panel.inheritTitleBlock(board)

    useHookPlugins(lambda x: x.afterPanelSetup(panel))

    sourceArea = ki.readSourceArea(preset["source"], board)
    substrates, framingSubstrates, backboneCuts = \
        ki.buildLayout(preset, panel, input, sourceArea)

    useHookPlugins(lambda x: x.afterLayout(panel, substrates))

    tabCuts = ki.buildTabs(preset, panel, substrates,
        framingSubstrates, ki.frameOffset(preset["framing"]))

    useHookPlugins(lambda x: x.afterTabs(panel, tabCuts, backboneCuts))

    frameCuts = ki.buildFraming(preset, panel)

    useHookPlugins(lambda x: x.afterFraming(panel, frameCuts))

    ki.buildTooling(preset, panel)
    ki.buildFiducials(preset, panel)
    ki.buildText(preset["text"], panel)
    ki.buildPostprocessing(preset["post"], panel)

    ki.makeTabCuts(preset, panel, tabCuts)
    ki.makeOtherCuts(preset, panel, chain(backboneCuts, frameCuts))

    useHookPlugins(lambda x: x.afterCuts(panel))

    ki.buildCopperfill(preset["copperfill"], panel)

    ki.setStackup(preset["source"], panel)
    ki.positionPanel(preset["page"], panel)
    ki.setPageSize(preset["page"], panel, board)

    ki.runUserScript(preset["post"], panel)
    useHookPlugins(lambda x: x.finish(panel))

    ki.buildDebugAnnotation(preset["debug"], panel)

    panel.save(reconstructArcs=preset["post"]["reconstructarcs"],
               refillAllZones=preset["post"]["refillzones"])
Beispiel #10
0
#!/usr/bin/env python

import sys
import transparency
import drill
import gerbers
import images
from common import maybe_create_dir

from pcbnew import LoadBoard

try:
    filename = sys.argv[1]
except IndexError:
    print 'kicad_pcb source is required'
    sys.exit(1)

maybe_create_dir('outputs')

transparency.generate(LoadBoard(filename), 'outputs/pdf/')
drill.generate(LoadBoard(filename), 'outputs/drill/')
gerbers.generate(LoadBoard(filename), 'outputs/gerbers/')
images.generate('outputs/gerbers/', 'outputs/images/')