Esempio n. 1
0
    def add_pad(self,
                position,
                size,
                name='',
                pad_type='standard',
                shape='circle',
                drill=1.0,
                layers=None):
        """Create a pad on the module

        Args:
            position: pad position in mm
            size: pad size in mm, value if shape == 'circle', tuple otherwise
            name: pad name/number
            pad_type: One of 'standard', 'smd', 'conn', 'hole_not_plated'
            shape: One of 'circle', 'rect', 'oval', 'trapezoid'
            drill: drill size in mm, single value for round hole, or tuple for oblong hole.
            layers: None for default, or a list of layer definitions (for example: ['F.Cu', 'F.Mask'])
        """
        pad = Pad(pcbnew.D_PAD(self._module))

        pad.type = pad_type
        pad.shape = shape
        pad.size = size
        pad.name = name
        pad.position = position
        pad.layers = layers

        self._module.Add(pad._pad)
        return pad
Esempio n. 2
0
 def NPTHRoundPad(self, drill):
     pad = pcbnew.D_PAD(self.module)
     pad.SetSize(pcbnew.wxSize(drill, drill))
     pad.SetShape(pcbnew.PAD_SHAPE_CIRCLE)
     pad.SetAttribute(pcbnew.PAD_ATTRIB_HOLE_NOT_PLATED)
     pad.SetLayerSet(pad.UnplatedHoleMask())
     pad.SetDrillSize(pcbnew.wxSize(drill, drill))
     return pad
Esempio n. 3
0
    def SMDPad(self, Vsize, Hsize, shape=pcbnew.PAD_SHAPE_RECT, rot_degree=0):
        pad = pcbnew.D_PAD(self.module)
        pad.SetSize(pcbnew.wxSize(Hsize, Vsize))
        pad.SetShape(shape)
        pad.SetAttribute(pcbnew.PAD_ATTRIB_SMD)
        pad.SetLayerSet(pad.SMDMask())
        pad.SetOrientation(rot_degree*10)   # rotation is in 0.1 degrees

        return pad
Esempio n. 4
0
    def THPad(self, Vsize, Hsize, drill, shape=pcbnew.PAD_SHAPE_OVAL, rot_degree = 0):
        pad = pcbnew.D_PAD(self.module)
        pad.SetSize(pcbnew.wxSize(Hsize, Vsize))
        pad.SetShape(shape)
        pad.SetAttribute(pcbnew.PAD_ATTRIB_STANDARD)
        pad.SetLayerSet(pad.StandardMask())
        pad.SetDrillSize(pcbnew.wxSize(drill, drill))
        pad.SetOrientation(rot_degree*10)   # rotation is in 0.1 degrees

        return pad
 def smdRectPad(self, module, size, pos, name):
     pad = pcbnew.D_PAD(module)
     pad.SetSize(size)
     pad.SetShape(pcbnew.PAD_SHAPE_RECT)
     pad.SetAttribute(pcbnew.PAD_ATTRIB_SMD)
     pad.SetLayerSet(pad.SMDMask())
     pad.SetPos0(pos)
     pad.SetPosition(pos)
     pad.SetName(name)
     return pad
Esempio n. 6
0
    def SMDPad(self, w, l, shape=pcbnew.PAD_SHAPE_RECT):
        pad = pcbnew.D_PAD(self.module)
        pad.SetSize(pcbnew.wxSize(l, w))

        pad.SetShape(shape)

        pad.SetAttribute(pcbnew.PAD_ATTRIB_SMD)
        pad.SetLayerSet(pad.SMDMask())

        return pad
Esempio n. 7
0
    def THPad(self, w, l, drill, shape=pcbnew.PAD_SHAPE_OVAL):
        pad = pcbnew.D_PAD(self.module)

        pad.SetSize(pcbnew.wxSize(l, w))

        pad.SetShape(shape)

        pad.SetAttribute(pcbnew.PAD_ATTRIB_STANDARD)
        pad.SetLayerSet(pad.StandardMask())
        pad.SetDrillSize(pcbnew.wxSize(drill, drill))

        return pad
Esempio n. 8
0
    def NPTHRoundPad(self, drill):
        """!
        A round non-plated though hole (NPTH)

        @param drill: the drill diameter (equals the NPTH diameter)
        """
        pad = pcbnew.D_PAD(self.module)
        pad.SetSize(pcbnew.wxSize(drill, drill))
        pad.SetShape(pcbnew.PAD_SHAPE_CIRCLE)
        pad.SetAttribute(pcbnew.PAD_ATTRIB_HOLE_NOT_PLATED)
        pad.SetLayerSet(pad.UnplatedHoleMask())
        pad.SetDrillSize(pcbnew.wxSize(drill, drill))
        return pad
Esempio n. 9
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)
Esempio n. 10
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)
Esempio n. 11
0
    def smd_rect_pad(self, module, size, pos, name):
        pad = pcbnew.D_PAD(module)

        pad.SetSize(size)

        if self.parameters['Pads'].get('*oval', "true").lower() == "true":
            pad.SetShape(pcbnew.PAD_OVAL)
        else:
            pad.SetShape(pcbnew.PAD_RECT)

        pad.SetAttribute(pcbnew.PAD_SMD)
        pad.SetLayerMask(pcbnew.PAD_SMD_DEFAULT_LAYERS)
        pad.SetPos0(pos)
        pad.SetPosition(pos)
        pad.SetPadName(name)

        return pad
Esempio n. 12
0
    def SMDPad(self, Vsize, Hsize, shape=pcbnew.PAD_SHAPE_RECT, rot_degree=0):
        """
        Create a surface-mount pad of the given size and shape
        @param Vsize: the vertical size of the pad
        @param Hsize: the horizontal size of the pad
        @param drill: the drill diameter
        @param shape: the shape of the pad
        @param rot_degree: the pad rotation, in degrees
        """
        pad = pcbnew.D_PAD(self.module)
        pad.SetSize(pcbnew.wxSize(Hsize, Vsize))
        pad.SetShape(shape)
        pad.SetAttribute(pcbnew.PAD_ATTRIB_SMD)
        pad.SetLayerSet(pad.SMDMask())
        pad.SetOrientation(rot_degree*10)   # rotation is in 0.1 degrees

        return 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)
Esempio n. 14
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()
Esempio n. 15
0
    def THPad(self, Vsize, Hsize, drill, shape=pcbnew.PAD_SHAPE_OVAL,
              rot_degree = 0):
        """!
        A basic through-hole pad of the given size and shape
        @param Vsize: the vertical size of the pad
        @param Hsize: the horizontal size of the pad
        @param drill: the drill diameter
        @param shape: the shape of the pad
        @param rot_degree: the pad rotation, in degrees
        """
        pad = pcbnew.D_PAD(self.module)
        pad.SetSize(pcbnew.wxSize(Hsize, Vsize))
        pad.SetShape(shape)
        pad.SetAttribute(pcbnew.PAD_ATTRIB_STANDARD)
        pad.SetLayerSet(pad.StandardMask())
        pad.SetDrillSize(pcbnew.wxSize(drill, drill))
        pad.SetOrientation(rot_degree*10)   # rotation is in 0.1 degrees

        return pad
Esempio n. 16
0
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
Esempio n. 17
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
Esempio n. 18
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 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)
Esempio n. 20
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()
Esempio n. 21
0
def hole_pad(board,
             module,
             size,
             drill_size,
             pos,
             net,
             pad_type="round"):  # round|first_half|second_half
    pad = pcbnew.D_PAD(module)
    pad.SetSize(size)
    pad.SetDrillSize(drill_size)

    # pad.SetPos0(pos) # don't do this, pcbnew will freak out after save/open
    pad.SetPosition(pos)

    if    net == ensure_net(board, "VCC") \
       or net == ensure_net(board, "GND") \
       or net == 0:
        # thru-holes
        pad.SetAttribute(pcbnew.PAD_ATTRIB_STANDARD)
        pad.SetLayerSet(pad.StandardMask())
        if net == ensure_net(board, "VCC"):
            pad.SetShape(pcbnew.PAD_SHAPE_RECT)
            pad.SetOrientation(deg(45))
        else:
            pad.SetShape(pcbnew.PAD_SHAPE_CIRCLE)
    else:
        # bridge pads
        pad.SetAttribute(pcbnew.PAD_ATTRIB_SMD)

        if pad_type == "round":
            pad.SetShape(pcbnew.PAD_SHAPE_CIRCLE)
        else:
            pad.SetShape(pcbnew.PAD_SHAPE_CUSTOM)
            r = int(size.GetWidth() / 2)
            inverter = 1
            if pad_type == "first_half":
                inverter = -1

            hack_shift = int(r / 2)
            gap = int(GAP / 2) * inverter
            pad.SetPosition(
                pcbnew.wxPoint(pos.x, pos.y + hack_shift * inverter + gap))
            module.SetPosition(
                pcbnew.wxPoint(module.GetPosition().x,
                               module.GetPosition().y +
                               gap))  # XXX yet another hack
            pad.SetSize(pcbnew.wxSize(int(r * 0.9), int(
                r * 0.9)))  # base shape (a tad smaller)
            # ^ base shape size can't be 0 because 3d view asserts != 0
            # ^ base shape size can't be 1 because somehow you'll end up with no copper
            # ^ base shape size can't be small because KiCad will find a way to break apart

            points = pcbnew.wxPoint_Vector()
            points.append(pcbnew.wxPoint(-r, -hack_shift * inverter))
            for x in range(-r + int(COPPER_STEP_EVERY), +r,
                           int(COPPER_STEP_EVERY)):
                # y = sqrt(r**2 - x**2)
                points.append(
                    pcbnew.wxPoint(x,
                                   (int(math.sqrt(r**2 - x**2)) - hack_shift) *
                                   inverter))
            points.append(pcbnew.wxPoint(+r, -hack_shift * inverter))
            pad.AddPrimitive(points, 0)  # 0 thickness = filled

        layer_set = pad.SMDMask().RemoveLayer(board.GetLayerID("F.Paste"))
        if "_B" in board.GetNetsByNetcode()[net].GetNetname():
            # XXX we should be flipping the module, not the pad
            pad.SetLayerSet(pcbnew.FlipLayerMask(layer_set))
            pad.Rotate(pos, 90 * 10)
        else:
            pad.SetLayerSet(layer_set)
            pad.Rotate(pos, 0)

    pad.SetPadName("0")
    pad.SetNet(board.GetNetsByNetcode()[net])
    module.Add(pad)