Beispiel #1
0
def insert_keepout_polygon(wx_points, layers=None):

    layers_LSET = pcbnew.LSET()
    if layers is None:
        layers_LSET.AddLayer(pcbnew.F_Cu)
        layers_LSET.AddLayer(pcbnew.B_Cu)
        layers = [pcbnew.F_Cu]
    else:
        for layer in layers:
            layers_LSET.AddLayer(layer)

    board = pcbnew.GetBoard()
    area = board.InsertArea(-1, 0xffff, layers[0], 0, 0,
                            pcbnew.ZONE_CONTAINER.DIAGONAL_FULL)
    area.SetLayerSet(layers_LSET)
    area.SetIsKeepout(True)
    area.SetDoNotAllowTracks(True)
    area.SetDoNotAllowVias(True)
    area.SetDoNotAllowCopperPour(True)
    outline = area.Outline()
    outline.RemoveAllContours()

    for p in wx_points:
        area.AppendCorner(p, -1)
        #print(p)

    if hasattr(area, "BuildFilledSolidAreasPolygons"):
        area.BuildFilledSolidAreasPolygons(board)

    if hasattr(area, "Hatch"):
        area.Hatch()
Beispiel #2
0
    def build(self):
        board = pcbnew.BOARD()

        # outline
        PcbPolygon(self.outline).build(board)

        # Add holes
        for h in self.holes:
            h.build(board)

        # Add ground plane
        signals = {}
        if self.fill_name:
            fill_net = pcbnew.NETINFO_ITEM(board, self.fill_name)
            board.Add(fill_net)
            signals[self.fill_name] = fill_net

            item = pcbnew.ZONE(board, False)
            poly = pcbnew.wxPoint_Vector()
            for x, y in self.outline.exterior.coords:
                poly.append(pcbnew.wxPointMM(x, y))
            item.AddPolygon(poly)
            item.SetNet(fill_net)
            lset = pcbnew.LSET()
            lset.AddLayer(pcbnew.F_Cu)
            lset.AddLayer(pcbnew.B_Cu)
            item.SetLayerSet(lset)
            board.Add(item)

        for component in self.components:
            component.build(board, signals)

        return board
Beispiel #3
0
    def DrawThermalPadSolderPaste(self, x, y, rows, cols, percent):
        # Calculate the paste area given percentage
        x_total_size = x / (math.sqrt(1 / (percent / 100)))
        y_total_size = y / (math.sqrt(1 / (percent / 100)))

        x_box = x_total_size / cols
        y_box = y_total_size / cols

        x_spacer = (x - cols * x_box) / (cols - 1)
        y_spacer = (y - rows * y_box) / (rows - 1)

        x_step = x_spacer + x_box
        y_step = y_spacer + y_box

        # Use PAD as Paste only but Kicad complains
        # Is it a valid use ?
        pastepad = PA.PadMaker(self.module).SMDPad(x_box, y_box,
                                                   pcbnew.PAD_RECT)
        only_paste = pcbnew.LSET(pcbnew.F_Paste)
        pastepad.SetLayerSet(only_paste)

        array = ThermalViasArray(pastepad, cols, rows, x_step, y_step)
        #array.SetFirstPadInArray(self.parameters["Pads"]["*nbpads"]+1)
        array.SetFirstPadInArray('~')
        array.AddPadsToModule(self.draw)
Beispiel #4
0
def _to_LayerSet(layers):
    """Create LayerSet used for defining pad layers"""
    bitset = 0
    for l in layers:
        bitset |= 1 << _get_layer(l)
    hexset = '{0:013x}'.format(bitset)
    lset = pcbnew.LSET()
    lset.ParseHex(hexset, len(hexset))
    return lset
    def smdRectPad(self, module, size, pos, name):
        pad = D_PAD(module)
        pad.SetSize(size)
        pad.SetShape(PAD_SHAPE_RECT)
        pad.SetAttribute(PAD_ATTRIB_SMD)

        layerset = pcbnew.LSET()
        layerset.AddLayer(pcbnew.F_Cu)
        pad.SetLayerSet(layerset)

        pad.SetPos0(pos)
        pad.SetPosition(pos)
        pad.SetName(name)
        return pad
Beispiel #6
0
 def _drawSolderMaskOpening(self, sizex, sizey, radius):
     # Draw the solder mask opening
     pad = pcbnew.D_PAD(self.module)
     pad.SetSize(pcbnew.wxSize(sizex, sizey))
     #TODO: Add fancy radius, once I figure out where to set the radius...
     # pad.SetShape(pcbnew.PAD_SHAPE_ROUNDRECT)
     pad.SetShape(pcbnew.PAD_SHAPE_RECT)
     pad.SetAttribute(pcbnew.PAD_ATTRIB_SMD)
     layerset = pcbnew.LSET()
     layerset.AddLayer(pcbnew.F_Mask)
     pad.SetLayerSet( layerset )
     pad.SetLocalSolderMaskMargin( -1 )
     pad.SetPosition(pcbnew.wxPoint(0, 0))
     pad.SetPadName("")
     self.module.Add(pad)
    def smdTrianglePad(self, module, size, pos, name, up_down=1, left_right=0):
        pad = D_PAD(module)
        pad.SetSize(wxSize(size[0], size[1]))
        pad.SetShape(PAD_SHAPE_TRAPEZOID)
        pad.SetAttribute(PAD_ATTRIB_SMD)

        layerset = pcbnew.LSET()
        layerset.AddLayer(currentLayer)
        pad.SetLayerSet(layerset)

        pad.SetPos0(pos)
        pad.SetPosition(pos)
        pad.SetName(name)
        pad.SetDelta(wxSize(left_right * size[1], up_down * size[0]))
        return pad
Beispiel #8
0
 def _drawPixel(self, xposition, yposition):
     # build a rectangular pad: as a dot
     pad = pcbnew.D_PAD(self.module)
     pad.SetSize(pcbnew.wxSize(self.X, self.X))
     pad.SetShape(pcbnew.PAD_SHAPE_RECT)
     pad.SetAttribute(pcbnew.PAD_ATTRIB_SMD)
     layerset = pcbnew.LSET()
     if self.UseCu:
         layerset.AddLayer(pcbnew.F_Cu)
     if self.UseSilkS:
         layerset.AddLayer(pcbnew.F_SilkS)
     pad.SetLayerSet( layerset )
     pad.SetLocalSolderMaskMargin( -1 )
     pad.SetPosition(pcbnew.wxPoint(xposition,yposition))
     pad.SetPadName("")
     self.module.Add(pad)
 def _drawPixel(self, xposition, yposition):
     # build a rectangular pad as a dot on copper layer,
     # and a polygon (a square) on silkscreen
     if self.UseCu:
         pad = pcbnew.D_PAD(self.module)
         pad.SetSize(pcbnew.wxSize(self.X, self.X))
         pad.SetPosition(pcbnew.wxPoint(xposition,yposition))
         pad.SetShape(pcbnew.PAD_SHAPE_RECT)
         pad.SetAttribute(pcbnew.PAD_ATTRIB_SMD)
         pad.SetName("")
         layerset = pcbnew.LSET()
         layerset.AddLayer(pcbnew.F_Cu)
         layerset.AddLayer(pcbnew.F_Mask)
         pad.SetLayerSet( layerset )
         self.module.Add(pad)
     if self.UseSilkS:
         polygon=self.drawSquareArea(pcbnew.F_SilkS, self.X, xposition, yposition)
         self.module.Add(polygon)
Beispiel #10
0
    def TaperFootprint(self, center=pcbnew.wxPoint(0,0), angle_deg=0):
        self.module = pcbnew.MODULE(None)

        #                6
        # 5 +------------+
        #   |            |\
        #   |            | \ 7
        #   |            |  +---+ 0
        #   |            |  |   |
        #   |            |  +---+ 1
        #   |            | / 2
        #   |            |/
        # 4 +------------+
        #                3
        points = [(self.w2/2, -self.w2/2), (self.w2/2, self.w2/2), (-self.w2/2, self.w2/2), \
                  (-self.w2/2 - self.tlen, self.w1/2), (-(self.w1/2 + self.tlen + self.w2/2), self.w1/2), \
                  (-(self.w1/2 + self.tlen + self.w2/2), -self.w1/2), (-self.w2/2 - self.tlen, -self.w1/2), \
                  (-self.w2/2, -self.w2/2)]

        points = [pcbnew.wxPoint(*point) for point in points]

        # Custom pad for smaller W2 x W2 pad
        cs_pad = pcbnew.D_PAD(self.module)
        cs_pad.SetSize(pcbnew.wxSize(self.w2, self.w2))
        cs_pad.SetShape(pcbnew.PAD_SHAPE_CUSTOM)
        cs_pad.SetAnchorPadShape(pcbnew.PAD_SHAPE_RECT)
        cs_pad.SetAttribute(pcbnew.PAD_ATTRIB_SMD)
        cs_pad.SetLayerSet(pcbnew.LSET(pcbnew.F_Cu))
        cs_pad.AddPrimitive(points, 0)
        cs_pad.SetLocalClearance(1)
        cs_pad.SetNet(self.net)
        cs_pad.SetPadName("1")

        self.module.Add(cs_pad)
        self.module.Add(Layout.smdRectPad(self.module, pcbnew.wxSize(self.w1, self.w1), pcbnew.wxPoint(-(self.w1/2 + self.tlen + self.w2/2), 0), "1", angle_deg, self.net))

        # TODO: Address other layers...

        self.module.SetPosition(center)

        # Add to pcbnew
        pcbnew.GetBoard().Add(self.module)
        pcbnew.Refresh()
Beispiel #11
0
    def loadsetsfromfolder(self):
        board = pcbnew.GetBoard()
        f = []
        for (dirpath, dirnames, filenames) in os.walk(savepath):
            f.extend(filenames)
            break
        for filename in f:
            layerarray = []
            rendervalue = None
            with open(os.path.join(dirpath,filename),'r') as f:
                for line in f:
                    line=line.strip()
                    if line.startswith('#'):
                        continue
                    # line here is 3 values separated by commas
                    (type,name,visible) = map(str.strip,line.split(','))
                    if type=='layer':
                        id = board.GetLayerID(name)
                        layerarray.append((id,visible))
                    elif type=='render':
                        rendervalue = int(name, 2)
                    else:
                        pass
                        # type is unrecognized
                # Generate the lset and the render values, and assign them to an element
                # element is (layerset,rendervalue,widget,name,file)
                if layerarray:
                    layerset = pcbnew.LSET()
                    for layer,visible in layerarray:
                        layerset.addLayer(layer)
                else:
                    layerset = None
            widget = self.get_viewset_widget(
              self._nameparent,
              filename,
              self.get_tool_tip(layerset,rendervalue))

            #Element = collections.namedtuple('Element','layers items widget name filepath')

            element = Element(layerset,rendervalue,widget,filename,os.path.join(dirpath,filename))
            self._layersetsaved.append(element)
Beispiel #12
0
    def createPad(self, number, name):
        top = number % 2 == 1

        if self.omitPin(number):
            return None

        padTotalHeight = topPadHeight if top else bottomPadHeight
        padHeight = padTotalHeight - padVerticalOffset

        padSize = pcbnew.wxSize(padWidth, padHeight)

        padOneCenterX = pcbnew.FromMM(18 * 0.5 + 0.25)
        padTwoCenterX = padOneCenterX + pcbnew.FromMM(0.25)

        pad = pcbnew.D_PAD(self.module)

        layerSet = pcbnew.LSET()

        if top:
            # On the top, 0.0 is centered between pads 35 and 37.
            padOffset = (number - 1) / 2
            padCenterX = padOneCenterX - pcbnew.FromMM(padOffset * 0.5)
            layerSet.AddLayer(pcbnew.F_Cu)
        else:
            # On the bottom, 0.0 is the center of pad 36.
            padOffset = (number) / 2
            padCenterX = padTwoCenterX - pcbnew.FromMM(padOffset * 0.5)
            layerSet.AddLayer(pcbnew.B_Cu)

        padCenterY = -(padVerticalOffset + padHeight / 2.0)
        padCenter = pcbnew.wxPoint(padCenterX, padCenterY)

        pad.SetSize(padSize)
        pad.SetPos0(padCenter)
        pad.SetPosition(padCenter)
        pad.SetShape(pcbnew.PAD_SHAPE_RECT)
        pad.SetAttribute(pcbnew.PAD_ATTRIB_SMD)
        pad.SetLayerSet(layerSet)
        pad.SetPadName(name)
        return pad
Beispiel #13
0
    def smdRectPad(module, size, pos, name, angle, net):
        '''Build a rectangular pad.'''
        pad = pcbnew.D_PAD(module)
        pad.SetSize(size)
        pad.SetShape(pcbnew.PAD_SHAPE_RECT)
        pad.SetAttribute(pcbnew.PAD_ATTRIB_SMD)
        # Set only the copper layer without mask
        # since nothing is mounted on these pads
        pad.SetLayerSet(pcbnew.LSET(pcbnew.F_Cu))  # Get active layer
        pad.SetPos0(pos)
        pad.SetPosition(pos)
        pad.SetPadName(name)

        pad.Rotate(pos, angle)
        # Set clearance to small value, because
        # pads can be very close together.
        # If distance is smaller than clearance
        # DRC doesn't allow routing the pads
        pad.SetLocalClearance(1)
        pad.SetNet(net)

        return pad
    def BuildThisFootprint(self):

        pad_pitch = self.pads["pitch"]
        pad_length = self.pads["length"]
        # offset allows to define how much of the pad is outside of the package
        pad_offset = self.pads["offset"]
        pad_width = self.pads["width"]

        v_pitch = self.package["height"]
        h_pitch = self.package["width"]

        pads_per_row = int(self.pads["n"] // 4)

        row_len = (pads_per_row - 1) * pad_pitch

        pad_shape = pcbnew.PAD_SHAPE_OVAL if self.pads[
            "oval"] else pcbnew.PAD_SHAPE_RECT

        h_pad = PA.PadMaker(self.module).SMDPad(pad_length,
                                                pad_width,
                                                shape=pad_shape,
                                                rot_degree=90.0)
        v_pad = PA.PadMaker(self.module).SMDPad(pad_length,
                                                pad_width,
                                                shape=pad_shape)

        h_pitch = h_pitch / 2 - pad_length + pad_offset + pad_length / 2
        v_pitch = v_pitch / 2 - pad_length + pad_offset + pad_length / 2

        #left row
        pin1Pos = pcbnew.wxPoint(-h_pitch, 0)
        array = PA.PadLineArray(h_pad, pads_per_row, pad_pitch, True, pin1Pos)
        array.SetFirstPadInArray(1)
        array.AddPadsToModule(self.draw)

        #bottom row
        pin1Pos = pcbnew.wxPoint(0, v_pitch)
        array = PA.PadLineArray(v_pad, pads_per_row, pad_pitch, False, pin1Pos)
        array.SetFirstPadInArray(pads_per_row + 1)
        array.AddPadsToModule(self.draw)

        #right row
        pin1Pos = pcbnew.wxPoint(h_pitch, 0)
        array = PA.PadLineArray(h_pad, pads_per_row, -pad_pitch, True, pin1Pos)
        array.SetFirstPadInArray(2 * pads_per_row + 1)
        array.AddPadsToModule(self.draw)

        #top row
        pin1Pos = pcbnew.wxPoint(0, -v_pitch)
        array = PA.PadLineArray(v_pad, pads_per_row, -pad_pitch, False,
                                pin1Pos)
        array.SetFirstPadInArray(3 * pads_per_row + 1)
        array.AddPadsToModule(self.draw)

        lim_x = self.package["width"] / 2
        lim_y = self.package["height"] / 2
        inner = (row_len / 2) + pad_pitch

        # epad
        epad_width = self.epad["width"]
        epad_length = self.epad["length"]

        epad_ny = self.epad["x divisions"]
        epad_nx = self.epad["y divisions"]

        epad_via_drill = self.epad["thermal vias drill"]

        # Create a central exposed pad?
        if self.epad['epad'] == True:

            epad_num = self.pads['n'] + 1

            epad_w = epad_length / epad_nx
            epad_l = epad_width / epad_ny

            # Create the epad
            epad = PA.PadMaker(self.module).SMDPad(epad_w,
                                                   epad_l,
                                                   shape=pcbnew.PAD_SHAPE_RECT)
            epad.SetLocalSolderPasteMargin(-1 * self.epad['paste margin'])
            # set pad layers
            layers = pcbnew.LSET(pcbnew.F_Mask)
            layers.AddLayer(pcbnew.F_Cu)
            layers.AddLayer(pcbnew.F_Paste)
            epad.SetName(epad_num)

            array = PA.EPADGridArray(epad, epad_ny, epad_nx, epad_l, epad_w,
                                     pcbnew.wxPoint(0, 0))
            array.SetFirstPadInArray(epad_num)
            array.AddPadsToModule(self.draw)

            if self.epad['thermal vias']:

                # create the thermal via
                via_diam = min(epad_w, epad_l) / 2
                via_drill = min(via_diam / 2, epad_via_drill)
                via = PA.PadMaker(self.module).THRoundPad(via_diam, via_drill)
                layers = pcbnew.LSET.AllCuMask()
                layers.AddLayer(pcbnew.B_Mask)
                layers.AddLayer(pcbnew.F_Mask)
                via.SetLayerSet(layers)

                via_array = PA.EPADGridArray(via, epad_ny, epad_nx, epad_l,
                                             epad_w, pcbnew.wxPoint(0, 0))
                via_array.SetFirstPadInArray(epad_num)
                via_array.AddPadsToModule(self.draw)

        # Draw the package outline on the F.Fab layer
        bevel = min(pcbnew.FromMM(1.0), self.package['width'] / 2,
                    self.package['height'] / 2)

        self.draw.SetLayer(pcbnew.F_Fab)

        w = self.package['width']
        h = self.package['height']

        self.draw.BoxWithDiagonalAtCorner(0, 0, w, h, bevel)

        # Silkscreen
        self.draw.SetLayer(pcbnew.F_SilkS)

        offset = self.draw.GetLineThickness()
        clip = row_len / 2 + self.pads['pitch']

        self.draw.SetLineThickness(
            pcbnew.FromMM(0.12))  #Default per KLC F5.1 as of 12/2018
        self.draw.Polyline([[clip, -h / 2 - offset],
                            [w / 2 + offset, -h / 2 - offset],
                            [w / 2 + offset, -clip]])  # top right
        self.draw.Polyline([[clip, h / 2 + offset],
                            [w / 2 + offset, h / 2 + offset],
                            [w / 2 + offset, clip]])  # bottom right
        self.draw.Polyline([[-clip, h / 2 + offset],
                            [-w / 2 - offset, h / 2 + offset],
                            [-w / 2 - offset, clip]])  # bottom left

        # Add pin-1 indication as per IPC-7351C
        self.draw.Line(-clip, -h / 2 - offset, -w / 2 - pad_length / 2,
                       -h / 2 - offset)
        self.draw.SetLineThickness(offset)  #Restore default

        # Courtyard
        cmargin = self.package["margin"]
        self.draw.SetLayer(pcbnew.F_CrtYd)

        sizex = (lim_x + cmargin) * 2 + pad_length
        sizey = (lim_y + cmargin) * 2 + pad_length

        # round size to nearest 0.1mm, rectangle will thus land on a 0.05mm grid
        sizex = pcbnew.PutOnGridMM(sizex, 0.1)
        sizey = pcbnew.PutOnGridMM(sizey, 0.1)
        # set courtyard line thickness to the one defined in KLC
        thick = self.draw.GetLineThickness()
        self.draw.SetLineThickness(pcbnew.FromMM(0.05))
        self.draw.Box(0, 0, sizex, sizey)
        # restore line thickness to previous value
        self.draw.SetLineThickness(pcbnew.FromMM(thick))

        #reference and value
        text_size = self.GetTextSize()  # IPC nominal
        text_offset = sizey / 2 + text_size

        self.draw.Value(0, text_offset, text_size)
        self.draw.Reference(0, -text_offset, text_size)

        # set SMD attribute
        self.module.SetAttributes(pcbnew.MOD_SMD)
Beispiel #15
0
    def BuildThisFootprint(self):
        pads = self.parameters["Pads"]

        pad_pitch = pads["pad pitch"]
        pad_length = pads["pad length"]
        pad_width = pads["pad width"]

        v_pitch = self.parameters["Package"]["package height"]
        h_pitch = self.parameters["Package"]["package width"]

        pads_per_row = pads["*n"] // 4

        row_len = (pads_per_row - 1) * pad_pitch

        pad_shape = pcbnew.PAD_SHAPE_OVAL if pads[
            "*oval"] else pcbnew.PAD_SHAPE_RECT

        h_pad = PA.PadMaker(self.module).SMDPad(pad_length,
                                                pad_width,
                                                shape=pad_shape,
                                                rot_degree=90.0)
        v_pad = PA.PadMaker(self.module).SMDPad(pad_length,
                                                pad_width,
                                                shape=pad_shape)

        #left row
        pin1Pos = pcbnew.wxPoint(-h_pitch / 2, 0)
        array = PA.PadLineArray(h_pad, pads_per_row, pad_pitch, True, pin1Pos)
        array.SetFirstPadInArray(1)
        array.AddPadsToModule(self.draw)

        #bottom row
        pin1Pos = pcbnew.wxPoint(0, v_pitch / 2)
        array = PA.PadLineArray(v_pad, pads_per_row, pad_pitch, False, pin1Pos)
        array.SetFirstPadInArray(pads_per_row + 1)
        array.AddPadsToModule(self.draw)

        #right row
        pin1Pos = pcbnew.wxPoint(h_pitch / 2, 0)
        array = PA.PadLineArray(h_pad, pads_per_row, -pad_pitch, True, pin1Pos)
        array.SetFirstPadInArray(2 * pads_per_row + 1)
        array.AddPadsToModule(self.draw)

        #top row
        pin1Pos = pcbnew.wxPoint(0, -v_pitch / 2)
        array = PA.PadLineArray(v_pad, pads_per_row, -pad_pitch, False,
                                pin1Pos)
        array.SetFirstPadInArray(3 * pads_per_row + 1)
        array.AddPadsToModule(self.draw)

        lim_x = self.parameters["Package"]["package width"] / 2
        lim_y = self.parameters["Package"]["package height"] / 2
        inner = (row_len / 2) + pad_pitch

        # epad
        epad_width = self.parameters["Package"]["package height"] - (
            2 * pad_length)
        epad_length = self.parameters["Package"]["package width"] - (
            2 * pad_length)
        epad_subdv_x = pads["*epad subdiv x"]
        epad_subdv_y = pads["*epad subdiv y"]
        epad_via_drill = pads["thermal vias drill"]

        if (epad_subdv_y != 0 and epad_subdv_x != 0) and (epad_subdv_y != 1 or
                                                          epad_subdv_x != 1):
            # Create the master pad (one area) on front solder mask, and perhaps of front copper layer
            # at location 0,0
            emasterpad = PA.PadMaker(self.module).SMDPad(
                epad_length,
                epad_width,
                shape=pcbnew.PAD_SHAPE_RECT,
                rot_degree=0.0)
            emasterpad.SetLayerSet(pcbnew.LSET(
                pcbnew.F_Mask))  # currently, only on solder mask
            emasterpad.SetPadName(pads["*n"] + 1)
            self.module.Add(emasterpad)

            px = pcbnew.FromMM(0.1)
            py = pcbnew.FromMM(0.1)
            esubpad_size_x = epad_length / epad_subdv_x - px
            esubpad_size_y = epad_width / epad_subdv_y - py
            epad1_pos = pcbnew.wxPoint(
                -(esubpad_size_x * (epad_subdv_x - 1) / 2),
                -esubpad_size_y * (epad_subdv_y - 1) / 2)
            epad = PA.PadMaker(self.module).SMDPad(esubpad_size_y,
                                                   esubpad_size_x,
                                                   shape=pcbnew.PAD_SHAPE_RECT,
                                                   rot_degree=0.0)
            array = PA.EPADGridArray(epad, epad_subdv_x, epad_subdv_y,
                                     esubpad_size_x + px, esubpad_size_y + py,
                                     pcbnew.wxPoint(0, 0))
            array.SetFirstPadInArray(pads["*n"] + 1)
            array.AddPadsToModule(self.draw)
            if pads["*thermal vias"]:
                via_diam = min(esubpad_size_y, esubpad_size_x) / 3.
                thpad = PA.PadMaker(self.module).THRoundPad(
                    via_diam, min(via_diam / 2, epad_via_drill))
                layerset = pcbnew.LSET.AllCuMask()
                layerset.AddLayer(pcbnew.B_Mask)
                layerset.AddLayer(pcbnew.F_Mask)
                thpad.SetLayerSet(layerset)
                array2 = PA.EPADGridArray(thpad, epad_subdv_x, epad_subdv_y,
                                          esubpad_size_x + px,
                                          esubpad_size_y + py,
                                          pcbnew.wxPoint(0, 0))
                array2.SetFirstPadInArray(pads["*n"] + 1)
                array2.AddPadsToModule(self.draw)
        else:
            epad = PA.PadMaker(self.module).SMDPad(epad_length, epad_width)
            epad_pos = pcbnew.wxPoint(0, 0)
            array = PA.PadLineArray(epad, 1, 1, False, epad_pos)
            array.SetFirstPadInArray(pads["*n"] + 1)
            array.AddPadsToModule(self.draw)
            if pads["*thermal vias"]:
                via_diam = min(epad_length, epad_width) / 3.
                thpad = PA.PadMaker(self.module).THRoundPad(
                    via_diam, min(via_diam / 2, epad_via_drill))
                layerset = pcbnew.LSET.AllCuMask()
                layerset.AddLayer(pcbnew.B_Mask)
                layerset.AddLayer(pcbnew.F_Mask)
                thpad.SetLayerSet(layerset)
                array2 = PA.PadLineArray(thpad, 1, 1, False, epad_pos)
                array2.SetFirstPadInArray(pads["*n"] + 1)
                array2.AddPadsToModule(self.draw)

        #top left - diagonal
        self.draw.Line(-lim_x, -inner, -inner, -lim_y)
        # top right
        self.draw.Polyline([(inner, -lim_y), (lim_x, -lim_y), (lim_x, -inner)])
        # bottom left
        self.draw.Polyline([(-inner, lim_y), (-lim_x, lim_y), (-lim_x, inner)])
        # bottom right
        self.draw.Polyline([(inner, lim_y), (lim_x, lim_y), (lim_x, inner)])

        # Courtyard
        cmargin = self.parameters["Package"]["courtyard margin"]
        self.draw.SetLayer(pcbnew.F_CrtYd)
        sizex = (lim_x + cmargin) * 2 + pad_length / 2.
        sizey = (lim_y + cmargin) * 2 + pad_length / 2.
        # round size to nearest 0.1mm, rectangle will thus land on a 0.05mm grid
        sizex = self.PutOnGridMM(sizex, 0.1)
        sizey = self.PutOnGridMM(sizey, 0.1)
        # set courtyard line thickness to the one defined in KLC
        thick = self.draw.GetLineThickness()
        self.draw.SetLineThickness(pcbnew.FromMM(0.05))
        self.draw.Box(0, 0, sizex, sizey)
        # restore line thickness to previous value
        self.draw.SetLineThickness(pcbnew.FromMM(thick))

        #reference and value
        text_size = self.GetTextSize()  # IPC nominal
        text_offset = v_pitch / 2 + text_size + pad_length / 2

        self.draw.Value(0, text_offset, text_size)
        self.draw.Reference(0, -text_offset, text_size)

        # set SMD attribute
        self.module.SetAttributes(pcbnew.MOD_CMS)
Beispiel #16
0
    def ChamferFootprint(self, center=pcbnew.wxPoint(0, 0)):
        self.module = pcbnew.MODULE(None)  # Create new module
        self.angle = m.radians(self.angle_deg)

        # Calculate the miter
        w = self.width

        # Width of the corner from edge of the corner to inside corner
        corner_width = pcbnew.ToMM(w) / m.cos(self.angle / 2)

        # Get proportion of width to cut
        cut = self.OptimalMiter()
        print("Cut: {0:.2f}%".format(cut * 100))

        # Distance from uncut outside corner point to point 7
        cut = pcbnew.FromMM(cut * corner_width / m.cos(
            (m.pi - self.angle) / 2))

        # Distance between points 2 and 3 and points 3 and 4
        # Minimum of w/2 to satisfy DRC, otherwise pads are too close
        # and track connected to other pad overlaps the other one.
        # Rounded trace end can also stick out of the cut area
        # if a is too small.
        a = max(cut - self.width * m.tan(self.angle / 2), w / 2)

        # Distance between points 3 and 4
        x34 = a * m.sin(self.angle)
        y34 = a * m.cos(self.angle)

        # Distance between points 4 and 5
        x45 = self.width * m.cos(self.angle)
        y45 = self.width * m.sin(self.angle)

        # Distance from point 7 to 1 (no x-component)
        d71 = a + self.width * m.tan(self.angle / 2) - cut

        #   1  2
        #   +--+
        #   |  |3
        # 7 \  --+ 4
        #    \   |
        #     \--+ 5
        #     6
        dW = w / 55  # To prevent tracks from over-extending
        points = [
            (-w / 2, -d71 / 2), (w / 2, -d71 / 2), (w / 2, a - d71 / 2 + dW),
            (w / 2 + x34 - (d71 / 2 - d71 / 1e5 - dW) * m.sin(self.angle),
             a + y34 - d71 / 2 -
             (d71 / 2 - d71 / 1e5 - dW) * m.cos(self.angle) + dW),
            (w / 2 + x34 - x45 -
             (d71 / 2 - d71 / 1e5 - dW) * m.sin(self.angle), a + y34 + y45 -
             d71 / 2 - (d71 / 2 - d71 / 1e5 - dW) * m.cos(self.angle) + dW),
            (cut * m.sin(self.angle) - w / 2,
             a + self.width * m.tan(self.angle / 2) + cut * m.cos(self.angle) -
             d71 / 2 + dW),
            (-w / 2,
             a + self.width * m.tan(self.angle / 2) - cut - d71 / 2 + dW)
        ]

        # Last two points can be equal
        if points[-2] == points[-1]:
            points = points[:-1]

        points = [pcbnew.wxPoint(*point) for point in points]

        # Custom pad
        cs_pad = pcbnew.D_PAD(self.module)
        cs_pad.SetSize(pcbnew.wxSize(w, d71))
        cs_pad.SetShape(pcbnew.PAD_SHAPE_CUSTOM)
        cs_pad.SetAnchorPadShape(pcbnew.PAD_SHAPE_RECT)
        cs_pad.SetAttribute(pcbnew.PAD_ATTRIB_SMD)
        cs_pad.SetLayerSet(pcbnew.LSET(pcbnew.F_Cu))
        cs_pad.AddPrimitive(points, 0)
        cs_pad.SetLocalClearance(1)
        cs_pad.SetNet(self.net)
        cs_pad.SetPadName("1")

        self.module.Add(cs_pad)

        # Halfway between points 4 and 5
        posx = ((w / 2 + x34) + (w / 2 + x34 - x45)) / 2
        posy = ((a + y34 - d71 / 2) + (a + y34 + y45 - d71 / 2)) / 2

        # Position pad so that pad edge touches polygon edge
        posx -= (d71 / 2 - dW) * m.sin(self.angle)
        posy -= (d71 / 2 - dW) * m.cos(self.angle) - dW
        size_pad = pcbnew.wxSize(d71, w)
        self.module.Add(
            Layout.smdRectPad(self.module, pcbnew.wxSize(w, d71),
                              pcbnew.wxPoint(0, 0), "1", 0,
                              self.net))  # Alignment pad
        self.module.Add(
            Layout.smdRectPad(self.module, size_pad,
                              pcbnew.wxPoint(posx, posy), "1",
                              (self.angle_deg - 90) * 10, self.net))

        self.module.Rotate(self.module.GetPosition(),
                           (90 + self.angle_deg) * 100)

        # self.module.MoveAnchorPosition(pcbnew.wxPoint((d71/2 - a - w/2)*m.sin(self.angle), \
        #                                (d71/2 - a - w/2)*m.cos(self.angle)))
        self.module.SetPosition(center)

        if self.layer == pcbnew.B_Cu: self.module.Flip(self.module.GetCenter())
        elif self.layer == pcbnew.F_Cu:
            self.module.Rotate(self.module.GetPosition(),
                               (90 + self.angle_deg) * 100)

        # Find center of bounding box for placement

        # Add to Pcbnew
        pcbnew.GetBoard().Add(self.module)
        pcbnew.Refresh()