def _generatePad(self):
        if self.chamfer_size[0] >= self.size[0] or self.chamfer_size[1] >= self.size[1]:
            raise ValueError('Chamfer size ({}) too large for given pad size ({})'.format(self.chamfer_size, self.size))

        is_chamfered = False
        if self.corner_selection.isAnySelected() and self.chamfer_size[0] > 0 and self.chamfer_size[1] > 0:
            is_chamfered = True

        shortest_sidlength = min(self.size)
        radius = shortest_sidlength*self.radius_ratio
        if self.maximum_radius and radius > self.maximum_radius:
            radius = self.maximum_radius

        if is_chamfered and self.chamfer_size[0] == self.chamfer_size[1] and self.radius_ratio > 0:
            # We prefer the use of rounded rectangle over chamfered pads.
            r_chamfer = self.chamfer_size[0] + sqrt(2)*self.chamfer_size[0]/2
            if radius >= r_chamfer:
                is_chamfered = False

        if is_chamfered:
            outside = Vector2D(self.size.x/2, self.size.y/2)

            inside = [Vector2D(outside.x, outside.y-self.chamfer_size.y),
                      Vector2D(outside.x-self.chamfer_size.x, outside.y)
                      ]
            polygon_width = 0
            if radius > 0:
                shortest_sidlength = min(self.size-self.chamfer_size)
                if radius > shortest_sidlength/2:
                    radius = shortest_sidlength/2
                polygon_width = radius*2
                outside -= radius
                inside[0] -= radius
                inside[1] -= radius

            points = []
            corner_vectors = [
                Vector2D(-1, -1), Vector2D(1, -1), Vector2D(1, 1), Vector2D(-1, 1)
                ]
            for i in range(4):
                if self.corner_selection[i]:
                    points.append(corner_vectors[i]*inside[i % 2])
                    points.append(corner_vectors[i]*inside[(i+1) % 2])
                else:
                    points.append(corner_vectors[i]*outside)

            primitives = [Polygon(nodes=points, width=polygon_width, **self.mirror)]
            # TODO make size calculation more resilient
            size = min(self.size.x, self.size.y)-max(self.chamfer_size[0], self.chamfer_size[1])/sqrt(2)
            if size <= 0:
                raise ValueError('Anchor pad size calculation failed.'
                                 'Chamfer size ({}) to large for given pad size ({})'
                                 .format(self.size, self.chamfer_size))
            return Pad(primitives=primitives, at=self.at,
                       shape=Pad.SHAPE_CUSTOM, size=size, **self.padargs)
        else:
            return Pad(
                    at=self.at, shape=Pad.SHAPE_ROUNDRECT, size=self.size,
                    **self.padargs
                )
def smd_chip(args):
    # init kicad footprint
    kicad_mod = Footprint(args['name'])
    kicad_mod.setDescription(args['description'])
    kicad_mod.setTags(args['tags'])
    kicad_mod.setAttribute('smd')

    # set general values
    text_x = 0.
    text_y = max([args['pad_y'] / 2., args['part_y'] / 2.]) + args['courtyard'] + 0.75

    kicad_mod.append(Text(type='reference', text='REF**', at=[text_x, -text_y], layer='F.SilkS'))
    kicad_mod.append(Text(type='user', text='%R', at=[text_x, -text_y], layer='F.Fab'))
    kicad_mod.append(Text(type='value', text=args['name'], at=[text_x, text_y], layer='F.Fab'))

    # create silkscreen
    silk_x = args['part_x'] / 2.
    silk_y = max([args['pad_y'] / 2., args['part_y'] / 2.]) + min(max(0.15, args['courtyard'] - 0.05), 0.2)

    kicad_mod.append(Line(start=[silk_x, silk_y], end=[-silk_x, silk_y], layer='F.SilkS'))
    kicad_mod.append(Line(start=[silk_x, -silk_y], end=[-silk_x, -silk_y], layer='F.SilkS'))

    # create fabrication layer
    kicad_mod.append(RectLine(start=[args['part_x'] / 2., args['part_y'] / 2.],
                              end=[-args['part_x'] / 2., -args['part_y'] / 2.],
                              layer='F.Fab'))

    # create courtyard
    courtyard_x = args['courtyard'] + max([args['pad_spacing'] / 2. + args['pad_x'], args['part_x'] / 2.])
    courtyard_y = args['courtyard'] + max([args['pad_y'] / 2., args['part_y'] / 2.])

    kicad_mod.append(RectLine(start=[courtyard_x, courtyard_y],
                              end=[-courtyard_x, -courtyard_y],
                              layer='F.CrtYd'))

    # create pads
    pad_settings = {'type': Pad.TYPE_SMT,
                    'shape': Pad.SHAPE_RECT,
                    'size': [args['pad_x'], args['pad_y']],
                    'layers': Pad.LAYERS_SMT}

    pad_x_center = (args['pad_spacing'] + args['pad_x'])  / 2.

    kicad_mod.append(Pad(number=1, at=[-pad_x_center, 0], **pad_settings))
    kicad_mod.append(Pad(number=2, at=[pad_x_center, 0], **pad_settings))

    # add model
    kicad_mod.append(Model(filename="{model_dir}.3dshapes/{name}.wrl".format(**args),
                           at=[0, 0, 0], scale=[1, 1, 1], rotate=[0, 0, 0]))

    # write file
    file_handler = KicadFileHandler(kicad_mod)
    file_handler.writeFile('{}.kicad_mod'.format(args['name']))
 def getVirtualChilds(self):
     at = self.reference_arc.getMidPoint()
     primitives = self._getArcPrimitives()
     for p in primitives:
         p.translate(-at)
     return [
         Pad(number=self.number,
             type=Pad.TYPE_SMT,
             shape=Pad.SHAPE_CUSTOM,
             at=at,
             size=self.width / 2,
             layers=self.layers,
             primitives=primitives)
     ]
 def getVirtualChilds(self):
     return [
         Pad(number=self.number,
             type=Pad.TYPE_SMT,
             shape=Pad.SHAPE_CUSTOM,
             at=(self.at + Vector2D(self.radius, 0)),
             size=self.width,
             layers=self.layers,
             primitives=[
                 Circle(center=(-self.radius, 0),
                        radius=self.radius,
                        width=self.width)
             ])
     ]
示例#5
0
def buzzer_round_tht(args):
    # some variables
    buzzer_center = args['pad_spacing'] / 2.
    buzzer_radius = args['diameter'] / 2.

    # init kicad footprint
    kicad_mod = Footprint(args['name'])
    kicad_mod.setDescription(args['datasheet'])
    kicad_mod.setTags("buzzer round tht")

    # set general values
    kicad_mod.append(Text(type='reference', text='REF**', at=[buzzer_center, -buzzer_radius - 1], layer='F.SilkS'))
    kicad_mod.append(Text(type='user', text='%R', at=[buzzer_center, -buzzer_radius - 1], layer='F.Fab'))
    kicad_mod.append(Text(type='value', text=args['name'], at=[buzzer_center, buzzer_radius + 1], layer='F.Fab'))

    # create silkscreen
    kicad_mod.append(Circle(center=[buzzer_center, 0], radius=buzzer_radius + 0.1, layer='F.SilkS'))

    kicad_mod.append(Text(type='user', text='+', at=[0, -args['pad_size'] / 2 - 1], layer='F.SilkS'))
    kicad_mod.append(Text(type='user', text='+', at=[0, -args['pad_size']/2 - 1], layer='F.Fab'))

    # create fabrication layer
    kicad_mod.append(Circle(center=[buzzer_center, 0], radius=buzzer_radius, layer='F.Fab'))

    # create courtyard
    kicad_mod.append(Circle(center=[buzzer_center, 0], radius=buzzer_radius + args['courtyard'], layer='F.CrtYd'))

    # create pads
    kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT,
                         at=[0, 0], size=args['pad_size'], drill=args['hole_size'], layers=Pad.LAYERS_THT))
    kicad_mod.append(Pad(number=2, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE,
                         at=[args['pad_spacing'], 0], size=args['pad_size'], drill=args['hole_size'], layers=Pad.LAYERS_THT))

    # write file
    file_handler = KicadFileHandler(kicad_mod)
    file_handler.writeFile('{}.kicad_mod'.format(args['name']))
    def _generatePads(self):
        self.pads = []
        if self.num_paste_zones > 1:
            layers = ['F.Cu', 'F.Mask']
            self._generatePastePads()
        else:
            layers = ['F.Cu', 'F.Mask', 'F.Paste']

        if not self.is_circle:
            self._generateCopperPads()
        else:
            self.pads.append(
                Pad(number=self.number,
                    type=Pad.TYPE_SMT,
                    shape=Pad.SHAPE_CIRCLE,
                    at=(self.at),
                    size=self.size,
                    layers=layers))
    def _generateCopperPads(self):
        # kicad_mod.append(c)
        layers = ['F.Cu']
        if self.num_paste_zones == 1:
            if self.solder_paste_margin == 0:
                layers.append('F.Paste')
            else:
                self.pads.append(
                    RingPadPrimitive(number="",
                                     at=self.at,
                                     width=self.width +
                                     2 * self.solder_paste_margin,
                                     layers=['F.Paste'],
                                     radius=self.radius))

        if self.solder_mask_margin == 0:
            # bug in kicad so any clearance other than 0 needs a workaround
            layers.append('F.Mask')
        else:
            self._generateMaskPads()
        self.pads.append(
            RingPadPrimitive(number=self.number,
                             at=self.at,
                             width=self.width,
                             layers=layers,
                             radius=self.radius))

        a = 360 / self.num_anchor
        pos = Vector2D(self.radius, 0)
        for i in range(1, self.num_anchor):
            pos.rotate(a)
            self.pads.append(
                Pad(
                    number=self.number,
                    type=Pad.TYPE_SMT,
                    shape=Pad.SHAPE_CIRCLE,
                    at=(self.at + pos),
                    size=self.width - 0.0001,
                    layers=['F.Cu'],
                ))
示例#8
0
def create_smd_shielding(name, **kwargs):
    kicad_mod = Footprint(name)

    # init kicad footprint
    kicad_mod.setDescription(kwargs['description'])
    kicad_mod.setTags('Shielding Cabinet')
    kicad_mod.setAttribute('smd')

    # do some pre calculations
    # TODO: when mirror=False, array has to have even number of array elements
    x_pad_positions = calculate_pad_spacer(kwargs['x_pad_spacer'], kwargs.get('x_pad_mirror', True))
    y_pad_positions = calculate_pad_spacer(kwargs['y_pad_spacer'], kwargs.get('y_pad_mirror', True))

    x_pad_min = min(x_pad_positions)
    x_pad_max = max(x_pad_positions)
    y_pad_min = min(y_pad_positions)
    y_pad_max = max(y_pad_positions)

    x_pad_min_center = x_pad_min + kwargs['pads_width']/2.
    x_pad_max_center = x_pad_max - kwargs['pads_width']/2.
    y_pad_min_center = y_pad_min + kwargs['pads_width']/2.
    y_pad_max_center = y_pad_max - kwargs['pads_width']/2.
    
    x_part_min = -kwargs['x_part_size'] / 2.
    x_part_max = kwargs['x_part_size'] / 2.
    y_part_min = -kwargs['y_part_size'] / 2.
    y_part_max = kwargs['y_part_size'] / 2.

    # set general values
    kicad_mod.append(Text(type='reference', text='REF**', at=[0, y_pad_min - kwargs['courtjard'] - 0.75], layer='F.SilkS'))
    kicad_mod.append(Text(type='value', text=name, at=[0, y_pad_max + kwargs['courtjard'] + 0.75], layer='F.Fab'))

    # create courtyard
    x_courtjard_min = round_to(x_pad_min - kwargs['courtjard'], 0.05)
    x_courtjard_max = round_to(x_pad_max + kwargs['courtjard'], 0.05)
    y_courtjard_min = round_to(y_pad_min - kwargs['courtjard'], 0.05)
    y_courtjard_max = round_to(y_pad_max + kwargs['courtjard'], 0.05)

    kicad_mod.append(RectLine(start=[x_courtjard_min, y_courtjard_min],
                              end=[x_courtjard_max, y_courtjard_max],
                              layer='F.CrtYd'))

    # create Fabriaction Layer
    kicad_mod.append(RectLine(start=[x_part_min, y_part_min],
                              end=[x_part_max, y_part_max],
                              layer='F.Fab'))

    # all pads have this kwargs, so we only write them one
    general_kwargs = {'number': 1,
                      'type': Pad.TYPE_SMT,
                      'shape': Pad.SHAPE_RECT,
                      'layers': ['F.Cu', 'F.Mask']}

    # create edge pads
    kicad_mod.append(Pad(at=[x_pad_min_center, y_pad_min_center],
                         size=[kwargs['pads_width'], kwargs['pads_width']], **general_kwargs))
    kicad_mod.append(Pad(at=[x_pad_max_center, y_pad_min_center],
                         size=[kwargs['pads_width'], kwargs['pads_width']], **general_kwargs))
    kicad_mod.append(Pad(at=[x_pad_max_center, y_pad_max_center],
                         size=[kwargs['pads_width'], kwargs['pads_width']], **general_kwargs))
    kicad_mod.append(Pad(at=[x_pad_min_center, y_pad_max_center],
                         size=[kwargs['pads_width'], kwargs['pads_width']], **general_kwargs))

    # iterate pairwise over pads
    for pad_start, pad_end in zip(x_pad_positions[0::2], x_pad_positions[1::2]):
        if pad_start == x_pad_min:
            pad_start += kwargs['pads_width']
        if pad_end == x_pad_max:
            pad_end -= kwargs['pads_width']

        kicad_mod.append(Pad(at=[(pad_start+pad_end)/2., y_pad_min_center],
                         size=[abs(pad_start-pad_end), kwargs['pads_width']], **general_kwargs))
        kicad_mod.append(Pad(at=[(pad_start+pad_end)/2., y_pad_max_center],
                         size=[abs(pad_start-pad_end), kwargs['pads_width']], **general_kwargs))

    for pad_start, pad_end in zip(y_pad_positions[0::2], y_pad_positions[1::2]):
        if pad_start == y_pad_min:
            pad_start += kwargs['pads_width']
        if pad_end == y_pad_max:
            pad_end -= kwargs['pads_width']

        kicad_mod.append(Pad(at=[x_pad_min_center, (pad_start+pad_end)/2.],
                         size=[kwargs['pads_width'], abs(pad_start-pad_end)], **general_kwargs))
        kicad_mod.append(Pad(at=[x_pad_max_center, (pad_start+pad_end)/2.],
                         size=[kwargs['pads_width'], abs(pad_start-pad_end)], **general_kwargs))

    # iterate pairwise over pads for silk screen
    for pad_start, pad_end in zip(x_pad_positions[1::2], x_pad_positions[2::2]):
        pad_start += 0.3
        pad_end -= 0.3

        kicad_mod.append(Line(start=[pad_start, y_part_min - 0.15],
                                  end=[pad_end, y_part_min - 0.15], layer='F.SilkS'))
        kicad_mod.append(Line(start=[pad_start, y_part_max + 0.15],
                                  end=[pad_end, y_part_max + 0.15], layer='F.SilkS'))

    for pad_start, pad_end in zip(y_pad_positions[1::2], y_pad_positions[2::2]):
        pad_start += 0.3
        pad_end -= 0.3

        # check if line has relevant length
        if pad_end - pad_start < 0.5:
            continue

        kicad_mod.append(Line(start=[x_part_min - 0.15, pad_start],
                                  end=[x_part_min - 0.15, pad_end], layer='F.SilkS'))
        kicad_mod.append(Line(start=[x_part_max + 0.15, pad_start],
                                  end=[x_part_max + 0.15, pad_end], layer='F.SilkS'))

    # write file
    file_handler = KicadFileHandler(kicad_mod)
    file_handler.writeFile('{name}.kicad_mod'.format(name=name))
示例#9
0
 def unserialize_pad(self, node):
     raise NotImplementedError()
     return Pad()
示例#10
0
def create_shielding(name, outer_size, size, attachment_drill,
                     attachment_diameter, attachment_positions):

    attachment_positions = sorted(attachment_positions)

    kicad_mod = Footprint(name)

    # init kicad footprint
    kicad_mod.setDescription(
        'WE-SHC Shielding Cabinet THT {size}x{size}mm'.format(size=size))
    kicad_mod.setTags('Shielding Cabinet')

    courtjard_size = outer_size / 2. + attachment_diameter / 2. + 0.25

    # set general values
    kicad_mod.append(
        Text(type='reference',
             text='REF**',
             at=[0, -courtjard_size - 1],
             layer='F.SilkS'))
    kicad_mod.append(
        Text(type='value',
             text=name,
             at=[0, courtjard_size + 1],
             layer='F.Fab'))

    # create courtyard
    kicad_mod.append(
        RectLine(start=[-courtjard_size, -courtjard_size],
                 end=[courtjard_size, courtjard_size],
                 layer='F.CrtYd'))

    # create Fabriaction Layer
    kicad_mod.append(
        RectLine(start=[-size / 2., -size / 2.],
                 end=[size / 2., size / 2.],
                 layer='F.Fab'))

    general_kwargs = {
        'number': 1,
        'type': Pad.TYPE_THT,
        'shape': Pad.SHAPE_CIRCLE,
        'size': [attachment_diameter, attachment_diameter],
        'drill': attachment_drill,
        'layers': ['*.Cu', '*.Mask']
    }

    # create pads
    for position in attachment_positions:
        kicad_mod.append(
            Pad(at=[outer_size / 2., position / 2.], **general_kwargs))
        kicad_mod.append(
            Pad(at=[-outer_size / 2., position / 2.], **general_kwargs))
        kicad_mod.append(
            Pad(at=[position / 2., outer_size / 2.], **general_kwargs))
        kicad_mod.append(
            Pad(at=[position / 2., -outer_size / 2.], **general_kwargs))

        if position != 0. or 2 * outer_size == 2 * position:
            kicad_mod.append(
                Pad(at=[outer_size / 2., -position / 2.], **general_kwargs))
            kicad_mod.append(
                Pad(at=[-outer_size / 2., -position / 2.], **general_kwargs))
            kicad_mod.append(
                Pad(at=[-position / 2., outer_size / 2.], **general_kwargs))
            kicad_mod.append(
                Pad(at=[-position / 2., -outer_size / 2.], **general_kwargs))

    # create silk screen
    silk_padding = 0.2
    silk_outline = size / 2. + silk_padding

    pad_padding = 0.4

    if attachment_positions[0] != 0.:
        line_end = attachment_positions[
            0] / 2. - attachment_diameter / 2. - pad_padding
        kicad_mod.append(
            Line(start=[silk_outline, line_end],
                 end=[silk_outline, -line_end],
                 layer='F.SilkS'))
        kicad_mod.append(
            Line(start=[-silk_outline, -line_end],
                 end=[-silk_outline, line_end],
                 layer='F.SilkS'))
        kicad_mod.append(
            Line(start=[line_end, silk_outline],
                 end=[-line_end, silk_outline],
                 layer='F.SilkS'))
        kicad_mod.append(
            Line(start=[line_end, -silk_outline],
                 end=[-line_end, -silk_outline],
                 layer='F.SilkS'))

    for begin, end in zip(attachment_positions, attachment_positions[1:]):
        line_begin = begin / 2. + attachment_diameter / 2. + pad_padding
        line_end = end / 2. - attachment_diameter / 2. - pad_padding
        kicad_mod.append(
            Line(start=[silk_outline, line_begin],
                 end=[silk_outline, line_end],
                 layer='F.SilkS'))
        kicad_mod.append(
            Line(start=[silk_outline, -line_begin],
                 end=[silk_outline, -line_end],
                 layer='F.SilkS'))
        kicad_mod.append(
            Line(start=[-silk_outline, line_begin],
                 end=[-silk_outline, line_end],
                 layer='F.SilkS'))
        kicad_mod.append(
            Line(start=[-silk_outline, -line_begin],
                 end=[-silk_outline, -line_end],
                 layer='F.SilkS'))
        kicad_mod.append(
            Line(start=[line_begin, silk_outline],
                 end=[line_end, silk_outline],
                 layer='F.SilkS'))
        kicad_mod.append(
            Line(start=[line_begin, -silk_outline],
                 end=[line_end, -silk_outline],
                 layer='F.SilkS'))
        kicad_mod.append(
            Line(start=[-line_begin, silk_outline],
                 end=[-line_end, silk_outline],
                 layer='F.SilkS'))
        kicad_mod.append(
            Line(start=[-line_begin, -silk_outline],
                 end=[-line_end, -silk_outline],
                 layer='F.SilkS'))

    if attachment_positions[-1] != outer_size:
        line_begin = attachment_positions[
            -1] / 2. + attachment_diameter / 2. + pad_padding
        line_end = outer_size / 2. + silk_padding
        kicad_mod.append(
            Line(start=[silk_outline, line_begin],
                 end=[silk_outline, line_end],
                 layer='F.SilkS'))
        kicad_mod.append(
            Line(start=[silk_outline, -line_begin],
                 end=[silk_outline, -line_end],
                 layer='F.SilkS'))
        kicad_mod.append(
            Line(start=[-silk_outline, line_begin],
                 end=[-silk_outline, line_end],
                 layer='F.SilkS'))
        kicad_mod.append(
            Line(start=[-silk_outline, -line_begin],
                 end=[-silk_outline, -line_end],
                 layer='F.SilkS'))
        kicad_mod.append(
            Line(start=[line_begin, silk_outline],
                 end=[line_end, silk_outline],
                 layer='F.SilkS'))
        kicad_mod.append(
            Line(start=[line_begin, -silk_outline],
                 end=[line_end, -silk_outline],
                 layer='F.SilkS'))
        kicad_mod.append(
            Line(start=[-line_begin, silk_outline],
                 end=[-line_end, silk_outline],
                 layer='F.SilkS'))
        kicad_mod.append(
            Line(start=[-line_begin, -silk_outline],
                 end=[-line_end, -silk_outline],
                 layer='F.SilkS'))

    # fix KLC issue 6.3
    # kicad_mod.insert(Translation(outer_size / 2., attachment_positions[-1] / 2.))

    # write file
    file_handler = KicadFileHandler(kicad_mod)
    file_handler.writeFile('{name}.kicad_mod'.format(name=name))
def create_footprint(name, **kwargs):
    kicad_mod = Footprint(name)

    # init kicad footprint
    kicad_mod.setDescription(kwargs['description'])
    kicad_mod.setTags('Mounting Hole')

    # load some general values
    hole_x = float(kwargs['hole_x'])
    hole_y = float(kwargs['hole_y'])
    anular_ring = float(kwargs['anular_ring'])
    courtjard = float(kwargs['courtjard'])
    create_via = kwargs['via']

    pad_x = hole_x + 2 * anular_ring
    pad_y = hole_y + 2 * anular_ring
    courtjard_x = pad_x + 2 * courtjard
    courtjard_y = pad_y + 2 * courtjard

    # set general values
    kicad_mod.append(
        Text(type='reference',
             text='REF**',
             at=[0, -courtjard_y / 2 - 0.75],
             layer='F.SilkS'))
    kicad_mod.append(
        Text(type='value',
             text=name,
             at=[0, courtjard_y / 2 + 0.75],
             layer='F.Fab'))

    # create courtyard
    if hole_x == hole_y:
        kicad_mod.append(
            Circle(center=[0, 0], radius=courtjard_x / 2., layer='F.CrtYd'))
    elif hole_x > hole_y:
        courtjard_length_x = courtjard_x - courtjard_y
        kicad_mod.append(
            RectLine(start=[courtjard_length_x / 2, courtjard_y / 2],
                     end=[-courtjard_length_x / 2, courtjard_y / 2],
                     layer='F.CrtYd'))
        kicad_mod.append(
            RectLine(start=[courtjard_length_x / 2, -courtjard_y / 2],
                     end=[-courtjard_length_x / 2, -courtjard_y / 2],
                     layer='F.CrtYd'))
        kicad_mod.append(
            Arc(center=[courtjard_length_x / 2, 0],
                start=[courtjard_length_x / 2, -courtjard_y / 2],
                angle=180,
                layer='F.CrtYd'))
        kicad_mod.append(
            Arc(center=[-courtjard_length_x / 2, 0],
                start=[-courtjard_length_x / 2, courtjard_y / 2],
                angle=180,
                layer='F.CrtYd'))
    else:  # hole_x < hole_y
        courtjard_length_y = courtjard_y - courtjard_x
        kicad_mod.append(
            RectLine(start=[courtjard_x / 2, courtjard_length_y / 2],
                     end=[courtjard_x / 2, -courtjard_length_y / 2],
                     layer='F.CrtYd'))
        kicad_mod.append(
            RectLine(start=[-courtjard_x / 2, courtjard_length_y / 2],
                     end=[-courtjard_x / 2, -courtjard_length_y / 2],
                     layer='F.CrtYd'))
        kicad_mod.append(
            Arc(center=[0, courtjard_length_y / 2],
                start=[courtjard_x / 2, courtjard_length_y / 2],
                angle=180,
                layer='F.CrtYd'))
        kicad_mod.append(
            Arc(center=[0, -courtjard_length_y / 2],
                start=[-courtjard_x / 2, -courtjard_length_y / 2],
                angle=180,
                layer='F.CrtYd'))

    # create pads
    pad_kwargs = {
        'number': 1,
        'type': Pad.TYPE_THT,
        'at': [0, 0],
        'size': [pad_x, pad_y],
        'layers': ['*.Cu', '*.Mask']
    }
    if hole_x == hole_y:
        kicad_mod.append(
            Pad(**pad_kwargs, shape=Pad.SHAPE_CIRCLE, drill=hole_x))
    else:
        kicad_mod.append(
            Pad(**pad_kwargs, shape=Pad.SHAPE_OVAL, drill=[hole_x, hole_y]))

    # create via's
    if create_via:
        via_count = int(kwargs['via_count'])
        via_diameter = float(kwargs['via_diameter'])
        x_size = hole_x + anular_ring
        y_size = hole_y + anular_ring

        circle_radius = min(x_size, y_size) / 2
        circle_scope = min(x_size, y_size) * math.pi

        if hole_x > hole_y:
            line_scope_x = 2 * (x_size - y_size)
            line_scope_y = 0
        else:
            line_scope_x = 0
            line_scope_y = 2 * (y_size - x_size)
        line_scope = line_scope_x + line_scope_y
        vias_scope = circle_scope + line_scope

        for step in range(via_count):
            scope_step = (vias_scope / via_count * step - line_scope_y / 4 +
                          vias_scope) % vias_scope  # align on right center

            if scope_step <= circle_scope / 4:
                local_scope_pos = scope_step
                circle_pos = local_scope_pos / circle_scope * 2 * math.pi
                step_x = math.cos(
                    circle_pos) * circle_radius + line_scope_x / 4
                step_y = math.sin(
                    circle_pos) * circle_radius + line_scope_y / 4
            elif scope_step <= circle_scope / 4 + line_scope_x / 2:
                local_scope_pos = scope_step - circle_scope / 4
                step_x = line_scope_x / 4 - local_scope_pos
                step_y = y_size / 2
            elif scope_step <= circle_scope / 2 + line_scope_x / 2:
                local_scope_pos = scope_step - line_scope_x / 2  # angle of circle already included
                circle_pos = local_scope_pos / circle_scope * 2 * math.pi
                step_x = math.cos(
                    circle_pos) * circle_radius - line_scope_x / 4
                step_y = math.sin(
                    circle_pos) * circle_radius + line_scope_y / 4
            elif scope_step <= circle_scope / 2 + line_scope_x / 2 + line_scope_y / 2:
                local_scope_pos = scope_step - circle_scope / 2 - line_scope_x / 2
                step_x = -x_size / 2
                step_y = line_scope_y / 4 - local_scope_pos
            elif scope_step <= 3 * circle_scope / 4 + line_scope_x / 2 + line_scope_y / 2:
                local_scope_pos = scope_step - line_scope_x / 2 - line_scope_y / 2  # angle of circle already included
                circle_pos = local_scope_pos / circle_scope * 2 * math.pi
                step_x = math.cos(
                    circle_pos) * circle_radius - line_scope_x / 4
                step_y = math.sin(
                    circle_pos) * circle_radius - line_scope_y / 4
            elif scope_step <= 3 * circle_scope / 4 + line_scope_x + line_scope_y / 2:
                local_scope_pos = scope_step - 3 * circle_scope / 4 - line_scope_x / 2 - line_scope_y / 2
                step_x = -line_scope_x / 4 + local_scope_pos
                step_y = -y_size / 2
            elif scope_step <= circle_scope + line_scope_x + line_scope_y / 2:
                local_scope_pos = scope_step - line_scope_x - line_scope_y / 2  # angle of circle already included
                circle_pos = local_scope_pos / circle_scope * 2 * math.pi
                step_x = math.cos(
                    circle_pos) * circle_radius + line_scope_x / 4
                step_y = math.sin(
                    circle_pos) * circle_radius - line_scope_y / 4
            elif scope_step < circle_scope + line_scope_x + line_scope_y:
                local_scope_pos = scope_step - circle_scope - line_scope_x - line_scope_y / 2
                step_x = x_size / 2
                step_y = -line_scope_y / 4 + local_scope_pos
            else:  # error
                raise "invalid scope_step"

            kicad_mod.append(
                Pad(number=1,
                    type=Pad.TYPE_THT,
                    shape=Pad.SHAPE_CIRCLE,
                    at=[step_x, step_y],
                    size=[via_diameter + 0.1, via_diameter + 0.1],
                    drill=via_diameter,
                    layers=['*.Cu', '*.Mask']))

    # write file
    file_handler = KicadFileHandler(kicad_mod)
    file_handler.writeFile('{name}.kicad_mod'.format(name=name))
示例#12
0
    def _generatePad(self):
        if self.chamfer_size[0] >= self.size[0] or self.chamfer_size[
                1] >= self.size[1]:
            raise ValueError(
                'Chamfer size ({}) too large for given pad size ({})'.format(
                    self.chamfer_size, self.size))

        is_chamfered = False
        if self.corner_selection.isAnySelected(
        ) and self.chamfer_size[0] > 0 and self.chamfer_size[1] > 0:
            is_chamfered = True

        radius = self.round_radius_handler.getRoundRadius(min(self.size))

        if is_chamfered:
            outside = Vector2D(self.size.x / 2, self.size.y / 2)

            inside = [
                Vector2D(outside.x, outside.y - self.chamfer_size.y),
                Vector2D(outside.x - self.chamfer_size.x, outside.y)
            ]

            polygon_width = 0
            if self.round_radius_handler.roundingRequested():
                if self.chamfer_size[0] != self.chamfer_size[1]:
                    raise NotImplementedError(
                        'Rounded chamfered pads are only supported for 45 degree chamfers.'
                        ' Chamfer {}'.format(self.chamfer_size))
                # We prefer the use of rounded rectangle over chamfered pads.
                r_chamfer = self.chamfer_size[0] + sqrt(
                    2) * self.chamfer_size[0] / 2
                if radius >= r_chamfer:
                    is_chamfered = False
                elif radius > 0:
                    shortest_sidlength = min(
                        min(self.size - self.chamfer_size),
                        self.chamfer_size[0] * sqrt(2))
                    if radius > shortest_sidlength / 2:
                        radius = shortest_sidlength / 2
                    polygon_width = radius * 2
                    outside -= radius
                    inside[0].y -= radius * (2 / sqrt(2) - 1)
                    inside[0].x -= radius
                    inside[1].x -= radius * (2 / sqrt(2) - 1)
                    inside[1].y -= radius

        if is_chamfered:
            points = []
            corner_vectors = [
                Vector2D(-1, -1),
                Vector2D(1, -1),
                Vector2D(1, 1),
                Vector2D(-1, 1)
            ]
            for i in range(4):
                if self.corner_selection[i]:
                    points.append(corner_vectors[i] * inside[i % 2])
                    points.append(corner_vectors[i] * inside[(i + 1) % 2])
                else:
                    points.append(corner_vectors[i] * outside)

            primitives = [
                Polygon(nodes=points, width=polygon_width, **self.mirror)
            ]
            # TODO make size calculation more resilient
            size = min(self.size.x, self.size.y) - max(
                self.chamfer_size[0], self.chamfer_size[1]) / sqrt(2)
            if size <= 0:
                raise ValueError(
                    'Anchor pad size calculation failed.'
                    'Chamfer size ({}) to large for given pad size ({})'.
                    format(self.size, self.chamfer_size))
            return Pad(primitives=primitives,
                       at=self.at,
                       shape=Pad.SHAPE_CUSTOM,
                       size=size,
                       **self.padargs)
        else:
            return Pad(at=self.at,
                       shape=Pad.SHAPE_ROUNDRECT,
                       size=self.size,
                       round_radius_handler=self.round_radius_handler,
                       **self.padargs)
示例#13
0
def create_shielding(name, outer_size, size, attachment_width,
                     attachment_length, attachment_positions,
                     outer_attachment_length):

    kicad_mod = Footprint(name)

    # init kicad footprint
    kicad_mod.setDescription(
        'WE-SHC Shielding Cabinet SMD {size}x{size}mm'.format(size=size))
    kicad_mod.setTags('Shielding Cabinet')
    kicad_mod.setAttribute('smd')

    # set general values
    kicad_mod.append(
        Text(type='reference',
             text='REF**',
             at=[0, -outer_size / 2. - 1],
             layer='F.SilkS'))
    kicad_mod.append(
        Text(type='value',
             text=name,
             at=[0, outer_size / 2. + 1],
             layer='F.Fab'))

    # create courtyard
    kicad_mod.append(
        RectLine(start=[-outer_size / 2. - 0.25, -outer_size / 2. - 0.25],
                 end=[outer_size / 2. + 0.25, outer_size / 2. + 0.25],
                 layer='F.CrtYd'))

    # create Fabriaction Layer
    kicad_mod.append(
        RectLine(start=[-size / 2., -size / 2.],
                 end=[size / 2., size / 2.],
                 layer='F.Fab'))

    outer_pointing_pos = outer_size / 2. - attachment_width / 2.

    general_kwargs = {
        'number': 1,
        'type': Pad.TYPE_SMT,
        'shape': Pad.SHAPE_RECT,
        'layers': ['F.Cu', 'F.Mask']
    }

    vertical_kwargs = {
        'number': 1,
        'type': Pad.TYPE_SMT,
        'shape': Pad.SHAPE_RECT,
        'size': [attachment_width, attachment_length],
        'layers': ['F.Cu', 'F.Mask']
    }

    horizontal_kwargs = {
        'number': 1,
        'type': Pad.TYPE_SMT,
        'shape': Pad.SHAPE_RECT,
        'size': [attachment_length, attachment_width],
        'layers': ['F.Cu', 'F.Mask']
    }

    # create inner pads
    for position in attachment_positions:
        kicad_mod.append(
            Pad(at=[outer_pointing_pos, position / 2.], **vertical_kwargs))
        kicad_mod.append(
            Pad(at=[outer_pointing_pos, -position / 2.], **vertical_kwargs))
        kicad_mod.append(
            Pad(at=[-outer_pointing_pos, position / 2.], **vertical_kwargs))
        kicad_mod.append(
            Pad(at=[-outer_pointing_pos, -position / 2.], **vertical_kwargs))

        kicad_mod.append(
            Pad(at=[position / 2., outer_pointing_pos], **horizontal_kwargs))
        kicad_mod.append(
            Pad(at=[position / 2., -outer_pointing_pos], **horizontal_kwargs))
        kicad_mod.append(
            Pad(at=[-position / 2., outer_pointing_pos], **horizontal_kwargs))
        kicad_mod.append(
            Pad(at=[-position / 2., -outer_pointing_pos], **horizontal_kwargs))

    # create edge pads
    kicad_mod.append(
        Pad(at=[outer_pointing_pos, outer_pointing_pos],
            size=[attachment_width, attachment_width],
            **general_kwargs))
    kicad_mod.append(
        Pad(at=[outer_pointing_pos, -outer_pointing_pos],
            size=[attachment_width, attachment_width],
            **general_kwargs))
    kicad_mod.append(
        Pad(at=[-outer_pointing_pos, outer_pointing_pos],
            size=[attachment_width, attachment_width],
            **general_kwargs))
    kicad_mod.append(
        Pad(at=[-outer_pointing_pos, -outer_pointing_pos],
            size=[attachment_width, attachment_width],
            **general_kwargs))

    inner_edge_pos = outer_size / 2 - attachment_width - (
        outer_attachment_length - attachment_width) / 2.
    inner_edge_length = outer_attachment_length - attachment_width

    kicad_mod.append(
        Pad(at=[inner_edge_pos, outer_pointing_pos],
            size=[inner_edge_length, attachment_width],
            **general_kwargs))
    kicad_mod.append(
        Pad(at=[inner_edge_pos, -outer_pointing_pos],
            size=[inner_edge_length, attachment_width],
            **general_kwargs))
    kicad_mod.append(
        Pad(at=[-inner_edge_pos, outer_pointing_pos],
            size=[inner_edge_length, attachment_width],
            **general_kwargs))
    kicad_mod.append(
        Pad(at=[-inner_edge_pos, -outer_pointing_pos],
            size=[inner_edge_length, attachment_width],
            **general_kwargs))

    kicad_mod.append(
        Pad(at=[outer_pointing_pos, inner_edge_pos],
            size=[attachment_width, inner_edge_length],
            **general_kwargs))
    kicad_mod.append(
        Pad(at=[outer_pointing_pos, -inner_edge_pos],
            size=[attachment_width, inner_edge_length],
            **general_kwargs))
    kicad_mod.append(
        Pad(at=[-outer_pointing_pos, inner_edge_pos],
            size=[attachment_width, inner_edge_length],
            **general_kwargs))
    kicad_mod.append(
        Pad(at=[-outer_pointing_pos, -inner_edge_pos],
            size=[attachment_width, inner_edge_length],
            **general_kwargs))

    # write file
    file_handler = KicadFileHandler(kicad_mod)
    file_handler.writeFile('{name}.kicad_mod'.format(name=name))
def create_footprint(name, configuration, **kwargs):
    kicad_mod = Footprint(name)

    # init kicad footprint
    datasheet = ""
    if 'datasheet' in kwargs:
        datasheet = kwargs['datasheet']
    kicad_mod.setDescription(kwargs['description'] + " " + datasheet)
    kicad_mod.setTags('Capacitor Electrolytic')
    kicad_mod.setAttribute('smd')

    # set general values
    text_offset_y = kwargs['width'] / 2. + configuration['courtyard_offset'][
        'default'] + 0.8

    #silkscreen REF**
    silk_text_size = configuration['references'][0]['size']
    silk_text_thickness = silk_text_size[0] * configuration['references'][0][
        'fontwidth']
    kicad_mod.append(
        Text(type='reference',
             text='REF**',
             at=[0, -text_offset_y],
             layer='F.SilkS',
             size=[silk_text_size[0], silk_text_size[1]],
             thickness=silk_text_thickness))
    #fab value
    fab_text_size = configuration['values'][0]['size']
    fab_text_thickness = fab_text_size[0] * configuration['values'][0][
        'fontwidth']
    kicad_mod.append(
        Text(type='value',
             text=name,
             at=[0, text_offset_y],
             layer='F.Fab',
             size=[fab_text_size[0], fab_text_size[1]],
             thickness=fab_text_thickness))
    #fab REF**
    fab_text_size = kwargs['diameter'] / 5.
    fab_text_size = min(fab_text_size,
                        configuration['references'][1]['size_max'][0])
    fab_text_size = max(fab_text_size,
                        configuration['references'][1]['size_min'][0])
    fab_text_thickness = fab_text_size * configuration['references'][1][
        'thickness_factor']
    kicad_mod.append(
        Text(type='user',
             text='%R',
             at=[0, 0],
             layer='F.Fab',
             size=[fab_text_size, fab_text_size],
             thickness=fab_text_thickness))

    # create fabrication layer
    fab_x = kwargs['length'] / 2.
    fab_y = kwargs['width'] / 2.

    if kwargs['pin1_chamfer'] == 'auto':
        fab_edge = min(fab_x / 2, fab_y / 2,
                       configuration['fab_pin1_marker_length'])
    else:
        fab_edge = kwargs['pin1_chamfer']
    fab_x_edge = fab_x - fab_edge
    fab_y_edge = fab_y - fab_edge
    kicad_mod.append(
        Line(start=[fab_x, -fab_y],
             end=[fab_x, fab_y],
             layer='F.Fab',
             width=configuration['fab_line_width']))
    kicad_mod.append(
        Line(start=[-fab_x_edge, -fab_y],
             end=[fab_x, -fab_y],
             layer='F.Fab',
             width=configuration['fab_line_width']))
    kicad_mod.append(
        Line(start=[-fab_x_edge, fab_y],
             end=[fab_x, fab_y],
             layer='F.Fab',
             width=configuration['fab_line_width']))
    if fab_edge > 0:
        kicad_mod.append(
            Line(start=[-fab_x, -fab_y_edge],
                 end=[-fab_x, fab_y_edge],
                 layer='F.Fab',
                 width=configuration['fab_line_width']))
        kicad_mod.append(
            Line(start=[-fab_x, -fab_y_edge],
                 end=[-fab_x_edge, -fab_y],
                 layer='F.Fab',
                 width=configuration['fab_line_width']))
    kicad_mod.append(
        Line(start=[-fab_x, fab_y_edge],
             end=[-fab_x_edge, fab_y],
             layer='F.Fab',
             width=configuration['fab_line_width']))
    kicad_mod.append(
        Circle(center=[0, 0],
               radius=kwargs['diameter'] / 2.,
               layer='F.Fab',
               width=configuration['fab_line_width']))

    #fab polarity marker
    fab_pol_size = kwargs['diameter'] / 10.
    fab_pol_wing = fab_pol_size / 2.
    fab_pol_distance = kwargs['diameter'] / 2. - fab_pol_wing - configuration[
        'fab_line_width']
    fab_pol_pos_y = fab_text_size / 2 + configuration[
        'silk_pad_clearance'] + fab_pol_size
    fab_pol_pos_x = math.sqrt(fab_pol_distance * fab_pol_distance -
                              fab_pol_pos_y * fab_pol_pos_y)
    fab_pol_pos_x = -fab_pol_pos_x
    fab_pol_pos_y = -fab_pol_pos_y
    kicad_mod.append(
        Line(start=[fab_pol_pos_x - fab_pol_wing, fab_pol_pos_y],
             end=[fab_pol_pos_x + fab_pol_wing, fab_pol_pos_y],
             layer='F.Fab',
             width=configuration['fab_line_width']))
    kicad_mod.append(
        Line(start=[fab_pol_pos_x, fab_pol_pos_y - fab_pol_wing],
             end=[fab_pol_pos_x, fab_pol_pos_y + fab_pol_wing],
             layer='F.Fab',
             width=configuration['fab_line_width']))

    # create silkscreen
    fab_to_silk_offset = configuration['silk_fab_offset']
    silk_x = kwargs['length'] / 2. + fab_to_silk_offset
    silk_y = kwargs['width'] / 2. + fab_to_silk_offset
    silk_y_start = kwargs['pad_width'] / 2. + configuration[
        'silk_pad_clearance'] + configuration['silk_line_width'] / 2.
    silk_45deg_offset = fab_to_silk_offset * math.tan(math.radians(22.5))
    silk_x_edge = fab_x - fab_edge + silk_45deg_offset
    silk_y_edge = fab_y - fab_edge + silk_45deg_offset

    kicad_mod.append(
        Line(start=[silk_x, silk_y],
             end=[silk_x, silk_y_start],
             layer='F.SilkS',
             width=configuration['silk_line_width']))
    kicad_mod.append(
        Line(start=[silk_x, -silk_y],
             end=[silk_x, -silk_y_start],
             layer='F.SilkS',
             width=configuration['silk_line_width']))
    kicad_mod.append(
        Line(start=[-silk_x_edge, -silk_y],
             end=[silk_x, -silk_y],
             layer='F.SilkS',
             width=configuration['silk_line_width']))
    kicad_mod.append(
        Line(start=[-silk_x_edge, silk_y],
             end=[silk_x, silk_y],
             layer='F.SilkS',
             width=configuration['silk_line_width']))

    if silk_y_edge > silk_y_start:
        kicad_mod.append(
            Line(start=[-silk_x, silk_y_edge],
                 end=[-silk_x, silk_y_start],
                 layer='F.SilkS',
                 width=configuration['silk_line_width']))
        kicad_mod.append(
            Line(start=[-silk_x, -silk_y_edge],
                 end=[-silk_x, -silk_y_start],
                 layer='F.SilkS',
                 width=configuration['silk_line_width']))

        kicad_mod.append(
            Line(start=[-silk_x, -silk_y_edge],
                 end=[-silk_x_edge, -silk_y],
                 layer='F.SilkS',
                 width=configuration['silk_line_width']))
        kicad_mod.append(
            Line(start=[-silk_x, silk_y_edge],
                 end=[-silk_x_edge, silk_y],
                 layer='F.SilkS',
                 width=configuration['silk_line_width']))
    else:
        silk_x_cut = silk_x - (
            silk_y_start - silk_y_edge
        )  # because of the 45 degree edge we can user a simple apporach
        silk_y_edge_cut = silk_y_start

        kicad_mod.append(
            Line(start=[-silk_x_cut, -silk_y_edge_cut],
                 end=[-silk_x_edge, -silk_y],
                 layer='F.SilkS',
                 width=configuration['silk_line_width']))
        kicad_mod.append(
            Line(start=[-silk_x_cut, silk_y_edge_cut],
                 end=[-silk_x_edge, silk_y],
                 layer='F.SilkS',
                 width=configuration['silk_line_width']))

    #silk polarity marker
    silk_pol_size = kwargs['diameter'] / 8.
    silk_pol_wing = silk_pol_size / 2.
    silk_pol_pos_y = silk_y_start + silk_pol_size
    silk_pol_pos_x = silk_x + silk_pol_wing + configuration[
        'silk_line_width'] * 2
    silk_pol_pos_x = -silk_pol_pos_x
    silk_pol_pos_y = -silk_pol_pos_y
    kicad_mod.append(
        Line(start=[silk_pol_pos_x - silk_pol_wing, silk_pol_pos_y],
             end=[silk_pol_pos_x + silk_pol_wing, silk_pol_pos_y],
             layer='F.SilkS',
             width=configuration['silk_line_width']))
    kicad_mod.append(
        Line(start=[silk_pol_pos_x, silk_pol_pos_y - silk_pol_wing],
             end=[silk_pol_pos_x, silk_pol_pos_y + silk_pol_wing],
             layer='F.SilkS',
             width=configuration['silk_line_width']))

    # create courtyard
    courtyard_offset = configuration['courtyard_offset']['default']
    courtyard_x = kwargs['length'] / 2. + courtyard_offset
    courtyard_y = kwargs['width'] / 2. + courtyard_offset
    courtyard_pad_x = kwargs['pad_spacing'] / 2. + kwargs[
        'pad_length'] + courtyard_offset
    courtyard_pad_y = kwargs['pad_width'] / 2. + courtyard_offset
    courtyard_45deg_offset = courtyard_offset * math.tan(math.radians(22.5))
    courtyard_x_edge = fab_x - fab_edge + courtyard_45deg_offset
    courtyard_y_edge = fab_y - fab_edge + courtyard_45deg_offset
    courtyard_x_lower_edge = courtyard_x
    if courtyard_y_edge < courtyard_pad_y:
        courtyard_x_lower_edge = courtyard_x_lower_edge - courtyard_pad_y + courtyard_y_edge
        courtyard_y_edge = courtyard_pad_y
    #rounding
    courtyard_x = float(format(courtyard_x, ".2f"))
    courtyard_y = float(format(courtyard_y, ".2f"))
    courtyard_pad_x = float(format(courtyard_pad_x, ".2f"))
    courtyard_pad_y = float(format(courtyard_pad_y, ".2f"))
    courtyard_x_edge = float(format(courtyard_x_edge, ".2f"))
    courtyard_y_edge = float(format(courtyard_y_edge, ".2f"))
    courtyard_x_lower_edge = float(format(courtyard_x_lower_edge, ".2f"))

    # drawing courtyard
    kicad_mod.append(
        Line(start=[courtyard_x, -courtyard_y],
             end=[courtyard_x, -courtyard_pad_y],
             layer='F.CrtYd',
             width=configuration['courtyard_line_width']))
    kicad_mod.append(
        Line(start=[courtyard_x, -courtyard_pad_y],
             end=[courtyard_pad_x, -courtyard_pad_y],
             layer='F.CrtYd',
             width=configuration['courtyard_line_width']))
    kicad_mod.append(
        Line(start=[courtyard_pad_x, -courtyard_pad_y],
             end=[courtyard_pad_x, courtyard_pad_y],
             layer='F.CrtYd',
             width=configuration['courtyard_line_width']))
    kicad_mod.append(
        Line(start=[courtyard_pad_x, courtyard_pad_y],
             end=[courtyard_x, courtyard_pad_y],
             layer='F.CrtYd',
             width=configuration['courtyard_line_width']))
    kicad_mod.append(
        Line(start=[courtyard_x, courtyard_pad_y],
             end=[courtyard_x, courtyard_y],
             layer='F.CrtYd',
             width=configuration['courtyard_line_width']))

    kicad_mod.append(
        Line(start=[-courtyard_x_edge, courtyard_y],
             end=[courtyard_x, courtyard_y],
             layer='F.CrtYd',
             width=configuration['courtyard_line_width']))
    kicad_mod.append(
        Line(start=[-courtyard_x_edge, -courtyard_y],
             end=[courtyard_x, -courtyard_y],
             layer='F.CrtYd',
             width=configuration['courtyard_line_width']))
    if fab_edge > 0:
        kicad_mod.append(
            Line(start=[-courtyard_x_lower_edge, courtyard_y_edge],
                 end=[-courtyard_x_edge, courtyard_y],
                 layer='F.CrtYd',
                 width=configuration['courtyard_line_width']))
        kicad_mod.append(
            Line(start=[-courtyard_x_lower_edge, -courtyard_y_edge],
                 end=[-courtyard_x_edge, -courtyard_y],
                 layer='F.CrtYd',
                 width=configuration['courtyard_line_width']))
    if courtyard_y_edge > courtyard_pad_y:
        kicad_mod.append(
            Line(start=[-courtyard_x, -courtyard_y_edge],
                 end=[-courtyard_x, -courtyard_pad_y],
                 layer='F.CrtYd',
                 width=configuration['courtyard_line_width']))
        kicad_mod.append(
            Line(start=[-courtyard_x, courtyard_pad_y],
                 end=[-courtyard_x, courtyard_y_edge],
                 layer='F.CrtYd',
                 width=configuration['courtyard_line_width']))
    kicad_mod.append(
        Line(start=[-courtyard_x_lower_edge, -courtyard_pad_y],
             end=[-courtyard_pad_x, -courtyard_pad_y],
             layer='F.CrtYd',
             width=configuration['courtyard_line_width']))
    kicad_mod.append(
        Line(start=[-courtyard_pad_x, -courtyard_pad_y],
             end=[-courtyard_pad_x, courtyard_pad_y],
             layer='F.CrtYd',
             width=configuration['courtyard_line_width']))
    kicad_mod.append(
        Line(start=[-courtyard_pad_x, courtyard_pad_y],
             end=[-courtyard_x_lower_edge, courtyard_pad_y],
             layer='F.CrtYd',
             width=configuration['courtyard_line_width']))

    # all pads have this kwargs, so we only write them once
    pad_kwargs = {
        'type': Pad.TYPE_SMT,
        'shape': Pad.SHAPE_RECT,
        'layers': ['F.Cu', 'F.Mask', 'F.Paste']
    }

    # create pads
    x_pad_spacing = kwargs['pad_spacing'] / 2. + kwargs['pad_length'] / 2.
    kicad_mod.append(
        Pad(number=1,
            at=[-x_pad_spacing, 0],
            size=[kwargs['pad_length'], kwargs['pad_width']],
            **pad_kwargs))
    kicad_mod.append(
        Pad(number=2,
            at=[x_pad_spacing, 0],
            size=[kwargs['pad_length'], kwargs['pad_width']],
            **pad_kwargs))

    lib_name = 'Capacitor_SMD'
    # add model
    modelname = name.replace("_HandSoldering", "")
    kicad_mod.append(
        Model(filename="{model_prefix:s}{lib_name:s}.3dshapes/{name:s}.wrl".
              format(model_prefix=configuration['3d_model_prefix'],
                     lib_name=lib_name,
                     name=modelname),
              at=[0, 0, 0],
              scale=[1, 1, 1],
              rotate=[0, 0, 0]))

    # write file
    output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name)
    if not os.path.isdir(
            output_dir
    ):  #returns false if path does not yet exist!! (Does not check path validity)
        os.makedirs(output_dir)

    filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir,
                                                        fp_name=name)
    file_handler = KicadFileHandler(kicad_mod)
    file_handler.writeFile(filename)
    def generateFootprints(self):
        fab_line_width = self.configuration.get('fab_line_width', 0.1)
        silk_line_width = self.configuration.get('silk_line_width', 0.12)

        for group_name in self.footprint_group_definitions:
            #print(device_group)
            footprint_group_data = self.footprint_group_definitions[group_name]

            device_size_docs = footprint_group_data['size_definitions']
            package_size_defintions = {}
            for device_size_doc in device_size_docs:
                with open(size_definition_path + device_size_doc,
                          'r') as size_stream:
                    try:
                        package_size_defintions.update(
                            yaml.safe_load(size_stream))
                    except yaml.YAMLError as exc:
                        print(exc)

            for size_name in package_size_defintions:
                device_size_data = package_size_defintions[size_name]

                device_dimensions = TwoTerminalSMDchip.deviceDimensions(
                    device_size_data)

                ipc_reference = footprint_group_data['ipc_reference']
                ipc_density = footprint_group_data['ipc_density']
                ipc_data_set = self.ipc_defintions[ipc_reference][ipc_density]
                ipc_round_base = self.ipc_defintions[ipc_reference][
                    'round_base']

                pad_details, paste_details = self.calcPadDetails(
                    device_dimensions, ipc_data_set, ipc_round_base,
                    footprint_group_data)
                #print(calc_pad_details())
                #print("generate {name}.kicad_mod".format(name=footprint))

                suffix = footprint_group_data.get('suffix', '').format(
                    pad_x=pad_details['size'][0], pad_y=pad_details['size'][1])
                prefix = footprint_group_data['prefix']

                model3d_path_prefix = self.configuration.get(
                    '3d_model_prefix', '${KISYS3DMOD}')
                suffix_3d = suffix if footprint_group_data.get(
                    'include_suffix_in_3dpath', 'True') == 'True' else ""

                code_metric = device_size_data.get('code_metric')
                code_letter = device_size_data.get('code_letter')
                code_imperial = device_size_data.get('code_imperial')

                if 'code_letter' in device_size_data:
                    name_format = self.configuration[
                        'fp_name_tantal_format_string']
                else:
                    if 'code_metric' in device_size_data:
                        name_format = self.configuration[
                            'fp_name_format_string']
                    else:
                        name_format = self.configuration[
                            'fp_name_non_metric_format_string']

                fp_name = name_format.format(prefix=prefix,
                                             code_imperial=code_imperial,
                                             code_metric=code_metric,
                                             code_letter=code_letter,
                                             suffix=suffix)
                fp_name_2 = name_format.format(prefix=prefix,
                                               code_imperial=code_imperial,
                                               code_letter=code_letter,
                                               code_metric=code_metric,
                                               suffix=suffix_3d)
                model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format(
                    model3d_path_prefix=model3d_path_prefix,
                    lib_name=footprint_group_data['fp_lib_name'],
                    fp_name=fp_name_2)
                #print(fp_name)
                #print(pad_details)

                kicad_mod = Footprint(fp_name)

                # init kicad footprint
                kicad_mod.setDescription(
                    footprint_group_data['description'].format(
                        code_imperial=code_imperial,
                        code_metric=code_metric,
                        code_letter=code_letter,
                        size_info=device_size_data.get('size_info')))
                kicad_mod.setTags(footprint_group_data['keywords'])
                kicad_mod.setAttribute('smd')

                pad_shape_details = {}
                pad_shape_details['shape'] = Pad.SHAPE_ROUNDRECT
                pad_shape_details['radius_ratio'] = configuration.get(
                    'round_rect_radius_ratio', 0)
                if 'round_rect_max_radius' in configuration:
                    pad_shape_details['maximum_radius'] = configuration[
                        'round_rect_max_radius']

                if paste_details is not None:
                    layers_main = ['F.Cu', 'F.Mask']

                    kicad_mod.append(
                        Pad(number='',
                            type=Pad.TYPE_SMT,
                            layers=['F.Paste'],
                            **merge_dicts(paste_details, pad_shape_details)))
                    paste_details['at'][0] *= (-1)
                    kicad_mod.append(
                        Pad(number='',
                            type=Pad.TYPE_SMT,
                            layers=['F.Paste'],
                            **merge_dicts(paste_details, pad_shape_details)))
                else:
                    layers_main = Pad.LAYERS_SMT

                P1 = Pad(number=1,
                         type=Pad.TYPE_SMT,
                         layers=layers_main,
                         **merge_dicts(pad_details, pad_shape_details))
                pad_radius = P1.getRoundRadius()

                kicad_mod.append(P1)
                pad_details['at'][0] *= (-1)
                kicad_mod.append(
                    Pad(number=2,
                        type=Pad.TYPE_SMT,
                        layers=layers_main,
                        **merge_dicts(pad_details, pad_shape_details)))

                fab_outline = self.configuration.get('fab_outline', 'typical')
                if fab_outline == 'max':
                    outline_size = [
                        device_dimensions['body_length'].maximum,
                        device_dimensions['body_width'].maximum
                    ]
                elif fab_outline == 'min':
                    outline_size = [
                        device_dimensions['body_length'].minimum,
                        device_dimensions['body_width'].minimum
                    ]
                else:
                    outline_size = [
                        device_dimensions['body_length'].nominal,
                        device_dimensions['body_width'].nominal
                    ]

                if footprint_group_data.get('polarization_mark',
                                            'False') == 'True':
                    polararity_marker_size = self.configuration.get(
                        'fab_polarity_factor', 0.25)
                    polararity_marker_size *= (
                        outline_size[1] if outline_size[1] < outline_size[0]
                        else outline_size[0])

                    polarity_marker_thick_line = False

                    polarity_max_size = self.configuration.get(
                        'fab_polarity_max_size', 1)
                    if polararity_marker_size > polarity_max_size:
                        polararity_marker_size = polarity_max_size
                    polarity_min_size = self.configuration.get(
                        'fab_polarity_min_size', 0.25)
                    if polararity_marker_size < polarity_min_size:
                        if polararity_marker_size < polarity_min_size * 0.6:
                            polarity_marker_thick_line = True
                        polararity_marker_size = polarity_min_size

                    silk_x_left = -abs(pad_details['at'][0]) - pad_details['size'][0]/2 - \
                        self.configuration['silk_pad_clearance'] - silk_line_width/2

                    silk_y_bottom = max(
                        self.configuration['silk_pad_clearance'] +
                        silk_line_width / 2 + pad_details['size'][1] / 2,
                        outline_size[1] / 2 +
                        self.configuration['silk_fab_offset'])

                    if polarity_marker_thick_line:
                        kicad_mod.append(
                            RectLine(start=[
                                -outline_size[0] / 2, outline_size[1] / 2
                            ],
                                     end=[
                                         outline_size[0] / 2,
                                         -outline_size[1] / 2
                                     ],
                                     layer='F.Fab',
                                     width=fab_line_width))
                        x = -outline_size[0] / 2 + fab_line_width
                        kicad_mod.append(
                            Line(start=[x, outline_size[1] / 2],
                                 end=[x, -outline_size[1] / 2],
                                 layer='F.Fab',
                                 width=fab_line_width))
                        x += fab_line_width
                        if x < -fab_line_width / 2:
                            kicad_mod.append(
                                Line(start=[x, outline_size[1] / 2],
                                     end=[x, -outline_size[1] / 2],
                                     layer='F.Fab',
                                     width=fab_line_width))

                        kicad_mod.append(
                            Circle(center=[silk_x_left - 0.05, 0],
                                   radius=0.05,
                                   layer="F.SilkS",
                                   width=0.1))
                    else:
                        poly_fab = [{
                            'x': outline_size[0] / 2,
                            'y': -outline_size[1] / 2
                        }, {
                            'x':
                            polararity_marker_size - outline_size[0] / 2,
                            'y':
                            -outline_size[1] / 2
                        }, {
                            'x':
                            -outline_size[0] / 2,
                            'y':
                            polararity_marker_size - outline_size[1] / 2
                        }, {
                            'x': -outline_size[0] / 2,
                            'y': outline_size[1] / 2
                        }, {
                            'x': outline_size[0] / 2,
                            'y': outline_size[1] / 2
                        }, {
                            'x': outline_size[0] / 2,
                            'y': -outline_size[1] / 2
                        }]
                        kicad_mod.append(
                            PolygoneLine(polygone=poly_fab,
                                         layer='F.Fab',
                                         width=fab_line_width))

                        poly_silk = [{
                            'x': outline_size[0] / 2,
                            'y': -silk_y_bottom
                        }, {
                            'x': silk_x_left,
                            'y': -silk_y_bottom
                        }, {
                            'x': silk_x_left,
                            'y': silk_y_bottom
                        }, {
                            'x': outline_size[0] / 2,
                            'y': silk_y_bottom
                        }]
                        kicad_mod.append(
                            PolygoneLine(polygone=poly_silk,
                                         layer='F.SilkS',
                                         width=silk_line_width))
                else:
                    kicad_mod.append(
                        RectLine(
                            start=[-outline_size[0] / 2, outline_size[1] / 2],
                            end=[outline_size[0] / 2, -outline_size[1] / 2],
                            layer='F.Fab',
                            width=fab_line_width))

                    silk_outline_y = outline_size[1] / 2 + self.configuration[
                        'silk_fab_offset']
                    default_clearance = self.configuration.get(
                        'silk_pad_clearance', 0.2)
                    silk_point_top_right = nearestSilkPointOnOrthogonalLineSmallClerance(
                        pad_size=pad_details['size'], pad_position=pad_details['at'], pad_radius=pad_radius,
                        fixed_point=Vector2D(0, silk_outline_y),
                        moving_point=Vector2D(outline_size[0]/2, silk_outline_y),
                        silk_pad_offset_default=(silk_line_width/2+default_clearance),
                        silk_pad_offset_reduced=(silk_line_width/2\
                            +self.configuration.get('silk_clearance_small_parts', default_clearance)),
                        min_lenght=configuration.get('silk_line_lenght_min', 0)/2)

                    if silk_point_top_right:
                        kicad_mod.append(
                            Line(start=[
                                -silk_point_top_right.x,
                                -silk_point_top_right.y
                            ],
                                 end=[
                                     silk_point_top_right.x,
                                     -silk_point_top_right.y
                                 ],
                                 layer='F.SilkS',
                                 width=silk_line_width))
                        kicad_mod.append(
                            Line(start=[
                                -silk_point_top_right.x, silk_point_top_right.y
                            ],
                                 end=silk_point_top_right,
                                 layer='F.SilkS',
                                 width=silk_line_width))

                CrtYd_rect = [None, None]
                CrtYd_rect[0] = roundToBase(2 * abs(pad_details['at'][0]) + \
                    pad_details['size'][0] + 2 * ipc_data_set['courtyard'], 0.02)
                if pad_details['size'][1] > outline_size[1]:
                    CrtYd_rect[1] = pad_details['size'][
                        1] + 2 * ipc_data_set['courtyard']
                else:
                    CrtYd_rect[
                        1] = outline_size[1] + 2 * ipc_data_set['courtyard']

                CrtYd_rect[1] = roundToBase(CrtYd_rect[1], 0.02)

                kicad_mod.append(
                    RectLine(start=[-CrtYd_rect[0] / 2, CrtYd_rect[1] / 2],
                             end=[CrtYd_rect[0] / 2, -CrtYd_rect[1] / 2],
                             layer='F.CrtYd',
                             width=self.configuration['courtyard_line_width']))

                ######################### Text Fields ###############################

                addTextFields(kicad_mod=kicad_mod,
                              configuration=configuration,
                              body_edges={
                                  'left': -outline_size[0] / 2,
                                  'right': outline_size[0] / 2,
                                  'top': -outline_size[1] / 2,
                                  'bottom': outline_size[1] / 2
                              },
                              courtyard={
                                  'top': -CrtYd_rect[1] / 2,
                                  'bottom': CrtYd_rect[1] / 2
                              },
                              fp_name=fp_name,
                              text_y_inside_position='center')

                kicad_mod.append(Model(filename=model_name))
                output_dir = '{lib_name:s}.pretty/'.format(
                    lib_name=footprint_group_data['fp_lib_name'])
                if not os.path.isdir(
                        output_dir
                ):  #returns false if path does not yet exist!! (Does not check path validity)
                    os.makedirs(output_dir)
                filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(
                    outdir=output_dir, fp_name=fp_name)

                file_handler = KicadFileHandler(kicad_mod)
                file_handler.writeFile(filename)
示例#16
0
def generateFootprint(config, fp_params, fp_id):
    print('Building footprint for parameter set: {}'.format(fp_id))
    
    pkgWidth = fp_params["pkg_width"]
    pkgHeight = fp_params["pkg_height"]
    layoutX = fp_params["layout_x"]
    layoutY = fp_params["layout_y"]
    
    if "row_names" in fp_params:
        rowNames = fp_params["row_names"]
    else:
        rowNames = config['row_names']
    
    if "row_skips" in fp_params:
        rowSkips = fp_params["row_skips"]
    else:
        rowSkips = []

    # must be given pitch (equal in X and Y) or a unique pitch in both X and Y
    if "pitch" in fp_params:
        if "pitch_x" and "pitch_y" in fp_params:
            raise KeyError('{}: Either pitch or both pitch_x and pitch_y must be given.'.format(fp_id))
        else:
            pitch_string = str(fp_params["pitch"])
            pitch_x = fp_params["pitch"]
            pitch_y = fp_params["pitch"]
    else:
        if "pitch_x" and "pitch_y" in fp_params:
            pitch_string = str(fp_params["pitch_x"]) + "x" + str(fp_params["pitch_y"])
            pitch_x = fp_params["pitch_x"]
            pitch_y = fp_params["pitch_y"]
        else:
            raise KeyError('{}: Either pitch or both pitch_x and pitch_y must be given.'.format(fp_id))

    f = Footprint(fp_id)
    f.setDescription(fp_params["description"])
    f.setAttribute("smd")
    if "mask_margin" in fp_params: f.setMaskMargin(fp_params["mask_margin"])
    if "paste_margin" in fp_params: f.setPasteMargin(fp_params["paste_margin"])
    if "paste_ratio" in fp_params: f.setPasteMarginRatio(fp_params["paste_ratio"])

    s1 = [1.0, 1.0]
    s2 = [min(1.0, round(pkgWidth / 4.3, 2))] * 2

    t1 = 0.15 * s1[0]
    t2 = 0.15 * s2[0]

    padShape = Pad.SHAPE_CIRCLE
    if "pad_shape" in fp_params:
        if fp_params["pad_shape"] == "rect":
            padShape = Pad.SHAPE_RECT
        if fp_params["pad_shape"] == "roundrect":
            padShape = Pad.SHAPE_ROUNDRECT

    chamfer = min(config['fab_bevel_size_absolute'], min(pkgWidth, pkgHeight) * config['fab_bevel_size_relative'])
    
    silkOffset = config['silk_fab_offset']
    crtYdOffset = config['courtyard_offset']['bga']
    
    def crtYdRound(x):
        # Round away from zero for proper courtyard calculation
        neg = x < 0
        if neg:
            x = -x
        x = math.ceil(x * 100) / 100.0
        if neg:
            x = -x
        return x

    xCenter = 0.0
    xLeftFab = xCenter - pkgWidth / 2.0
    xRightFab = xCenter + pkgWidth / 2.0
    xChamferFab = xLeftFab + chamfer
    xPadLeft = xCenter - pitch_x * ((layoutX - 1) / 2.0)
    xPadRight = xCenter + pitch_x * ((layoutX - 1) / 2.0)
    xLeftCrtYd = crtYdRound(xCenter - (pkgWidth / 2.0 + crtYdOffset))
    xRightCrtYd = crtYdRound(xCenter + (pkgWidth / 2.0 + crtYdOffset))

    yCenter = 0.0
    yTopFab = yCenter - pkgHeight / 2.0
    yBottomFab = yCenter + pkgHeight / 2.0
    yChamferFab = yTopFab + chamfer
    yPadTop = yCenter - pitch_y * ((layoutY - 1) / 2.0)
    yPadBottom = yCenter + pitch_y * ((layoutY - 1) / 2.0)
    yTopCrtYd = crtYdRound(yCenter - (pkgHeight / 2.0 + crtYdOffset))
    yBottomCrtYd = crtYdRound(yCenter + (pkgHeight / 2.0 + crtYdOffset))
    yRef = yTopFab - 1.0
    yValue = yBottomFab + 1.0

    xLeftSilk = xLeftFab - silkOffset
    xRightSilk = xRightFab + silkOffset
    xChamferSilk = xLeftSilk + chamfer
    yTopSilk = yTopFab - silkOffset
    yBottomSilk = yBottomFab + silkOffset
    yChamferSilk = yTopSilk + chamfer

    wFab = configuration['fab_line_width']
    wCrtYd = configuration['courtyard_line_width']
    wSilkS = configuration['silk_line_width']

    # Text
    f.append(Text(type="reference", text="REF**", at=[xCenter, yRef],
                  layer="F.SilkS", size=s1, thickness=t1))
    f.append(Text(type="value", text=fp_id, at=[xCenter, yValue],
                  layer="F.Fab", size=s1, thickness=t1))
    f.append(Text(type="user", text="%R", at=[xCenter, yCenter],
                  layer="F.Fab", size=s2, thickness=t2))

    # Fab
    f.append(PolygoneLine(polygone=[[xRightFab, yBottomFab],
                                    [xLeftFab, yBottomFab],
                                    [xLeftFab, yChamferFab],
                                    [xChamferFab, yTopFab],
                                    [xRightFab, yTopFab],
                                    [xRightFab, yBottomFab]],
                          layer="F.Fab", width=wFab))

    # Courtyard
    f.append(RectLine(start=[xLeftCrtYd, yTopCrtYd],
                      end=[xRightCrtYd, yBottomCrtYd],
                      layer="F.CrtYd", width=wCrtYd))

    # Silk
    f.append(PolygoneLine(polygone=[[xChamferSilk, yTopSilk],
                                    [xRightSilk, yTopSilk],
                                    [xRightSilk, yBottomSilk],
                                    [xLeftSilk, yBottomSilk],
                                    [xLeftSilk, yChamferSilk]],
                          layer="F.SilkS", width=wSilkS))

    # Pads
    balls = layoutX * layoutY
    if rowSkips == []:
        for _ in range(layoutY):
            rowSkips.append([])
    for rowNum, row in zip(range(layoutY), rowNames):
        rowSet = set(range(1, layoutX + 1))
        for item in rowSkips[rowNum]:
            try:
                # If item is a range, remove that range
                rowSet -= set(range(*item))
                balls -= item[1] - item[0]
            except TypeError:
                # If item is an int, remove that int
                rowSet -= {item}
                balls -= 1
        for col in rowSet:
            f.append(Pad(number="{}{}".format(row, col), type=Pad.TYPE_SMT,
                         shape=padShape,
                         at=[xPadLeft + (col-1) * pitch_x, yPadTop + rowNum * pitch_y],
                         size=[fp_params["pad_diameter"], fp_params["pad_diameter"]],
                         layers=Pad.LAYERS_SMT, 
                         radius_ratio=config['round_rect_radius_ratio']))

    # If this looks like a CSP footprint, use the CSP 3dshapes library
    package_type = 'CSP' if 'BGA' not in fp_id and 'CSP' in fp_id else 'BGA'

    f.append(Model(filename="{}Package_{}.3dshapes/{}.wrl".format(
                  config['3d_model_prefix'], package_type, fp_id)))

    f.setTags("{} {} {}".format(package_type, balls, pitch_string))

    output_dir = 'Package_{lib_name:s}.pretty/'.format(lib_name=package_type)
    if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity)
        os.makedirs(output_dir)
    filename = '{outdir:s}{fp_id:s}.kicad_mod'.format(outdir=output_dir, fp_id=fp_id)
    
    file_handler = KicadFileHandler(f)
    file_handler.writeFile(filename)
示例#17
0
def create_footprint(name, **kwargs):
    kicad_mod = Footprint(name)

    # init kicad footprint
    kicad_mod.setDescription(kwargs['description'])
    kicad_mod.setTags('Capacitor Electrolytic')
    kicad_mod.setAttribute('smd')

    # set general values
    text_offset_y = kwargs['width'] / 2. + kwargs['courtjard'] + 0.8

    kicad_mod.append(
        Text(type='reference',
             text='REF**',
             at=[0, -text_offset_y],
             layer='F.SilkS'))
    kicad_mod.append(
        Text(type='value', text=name, at=[0, text_offset_y], layer='F.Fab'))

    # create fabrication layer
    fab_x = kwargs['length'] / 2.
    fab_y = kwargs['width'] / 2.
    fab_edge = 1
    fab_x_edge = fab_x - fab_edge
    fab_y_edge = fab_y - fab_edge
    kicad_mod.append(
        Line(start=[fab_x, -fab_y], end=[fab_x, fab_y], layer='F.Fab'))
    kicad_mod.append(
        Line(start=[-fab_x_edge, -fab_y], end=[fab_x, -fab_y], layer='F.Fab'))
    kicad_mod.append(
        Line(start=[-fab_x_edge, fab_y], end=[fab_x, fab_y], layer='F.Fab'))
    kicad_mod.append(
        Line(start=[-fab_x, -fab_y_edge],
             end=[-fab_x, fab_y_edge],
             layer='F.Fab'))

    kicad_mod.append(
        Line(start=[-fab_x, -fab_y_edge],
             end=[-fab_x_edge, -fab_y],
             layer='F.Fab'))
    kicad_mod.append(
        Line(start=[-fab_x, fab_y_edge],
             end=[-fab_x_edge, fab_y],
             layer='F.Fab'))

    fab_text_x = kwargs['pad_spacing'] / 2. + kwargs['pad_length'] / 4.
    kicad_mod.append(
        Text(type='user', text='+', at=[-fab_text_x, 0], layer='F.Fab'))

    # create silkscreen
    silk_x = kwargs['length'] / 2. + 0.11
    silk_y = kwargs['width'] / 2. + 0.11
    silk_y_start = kwargs['pad_width'] / 2. + 0.3
    silk_x_edge = fab_x - fab_edge + 0.05
    silk_y_edge = fab_y - fab_edge + 0.05

    kicad_mod.append(
        Line(start=[silk_x, silk_y],
             end=[silk_x, silk_y_start],
             layer='F.SilkS'))
    kicad_mod.append(
        Line(start=[silk_x, -silk_y],
             end=[silk_x, -silk_y_start],
             layer='F.SilkS'))
    kicad_mod.append(
        Line(start=[-silk_x_edge, -silk_y],
             end=[silk_x, -silk_y],
             layer='F.SilkS'))
    kicad_mod.append(
        Line(start=[-silk_x_edge, silk_y],
             end=[silk_x, silk_y],
             layer='F.SilkS'))

    if silk_y_edge > silk_y_start:
        kicad_mod.append(
            Line(start=[-silk_x, silk_y_edge],
                 end=[-silk_x, silk_y_start],
                 layer='F.SilkS'))
        kicad_mod.append(
            Line(start=[-silk_x, -silk_y_edge],
                 end=[-silk_x, -silk_y_start],
                 layer='F.SilkS'))

        kicad_mod.append(
            Line(start=[-silk_x, -silk_y_edge],
                 end=[-silk_x_edge, -silk_y],
                 layer='F.SilkS'))
        kicad_mod.append(
            Line(start=[-silk_x, silk_y_edge],
                 end=[-silk_x_edge, silk_y],
                 layer='F.SilkS'))
    else:
        silk_x_cut = silk_x - (
            silk_y_start - silk_y_edge
        )  # because of the 45 degree edge we can user a simple apporach
        silk_y_edge_cut = silk_y_start

        kicad_mod.append(
            Line(start=[-silk_x_cut, -silk_y_edge_cut],
                 end=[-silk_x_edge, -silk_y],
                 layer='F.SilkS'))
        kicad_mod.append(
            Line(start=[-silk_x_cut, silk_y_edge_cut],
                 end=[-silk_x_edge, silk_y],
                 layer='F.SilkS'))

    silk_cane_x_start = math.cos(
        math.asin(silk_y_start /
                  (kwargs['diameter'] / 2.))) * (kwargs['diameter'] / 2.)
    silk_cane_angle = 180 - math.acos(
        2 *
        (silk_cane_x_start / kwargs['diameter'])) * 360. / math.pi  # TODO 180

    kicad_mod.append(
        Arc(center=[0, 0],
            start=[-silk_cane_x_start, -silk_y_start],
            angle=silk_cane_angle,
            layer='F.SilkS'))
    kicad_mod.append(
        Arc(center=[0, 0],
            start=[silk_cane_x_start, silk_y_start],
            angle=silk_cane_angle,
            layer='F.SilkS'))

    # create courtyard
    courtjard_x = kwargs['pad_spacing'] / 2. + kwargs['pad_length'] + kwargs[
        'courtjard']
    courtjard_y = kwargs['width'] / 2. + kwargs['courtjard']

    kicad_mod.append(
        RectLine(start=[courtjard_x, courtjard_y],
                 end=[-courtjard_x, -courtjard_y],
                 layer='F.CrtYd'))

    # '+' sign on silkscreen
    silk_text_x = courtjard_x - 0.6
    silk_text_y = courtjard_y - 0.6
    kicad_mod.append(
        Text(type='user',
             text='+',
             at=[-silk_text_x, silk_text_y],
             layer='F.SilkS'))

    # all pads have this kwargs, so we only write them once
    pad_kwargs = {
        'type': Pad.TYPE_SMT,
        'shape': Pad.SHAPE_RECT,
        'layers': ['F.Cu', 'F.Mask', 'F.Paste']
    }

    # create pads
    x_pad_spacing = kwargs['pad_spacing'] / 2. + kwargs['pad_length'] / 2.
    kicad_mod.append(
        Pad(number=1,
            at=[-x_pad_spacing, 0],
            size=[kwargs['pad_length'], kwargs['pad_width']],
            **pad_kwargs))
    kicad_mod.append(
        Pad(number=2,
            at=[x_pad_spacing, 0],
            size=[kwargs['pad_length'], kwargs['pad_width']],
            **pad_kwargs))

    # add model
    kicad_mod.append(
        Model(filename="example.3dshapes/{name}.wrl".format(name=name),
              at=[0, 0, 0],
              scale=[1, 1, 1],
              rotate=[0, 0, 0]))

    # write file
    file_handler = KicadFileHandler(kicad_mod)
    file_handler.writeFile('{name}.kicad_mod'.format(name=name))
示例#18
0
def create_footprint(name, configuration, **kwargs):
    kicad_mod = Footprint(name)

    # init kicad footprint
    datasheet = ", " + kwargs['datasheet'] if 'datasheet' in kwargs else ""
    description = "SMD capacitor, aluminum electrolytic"
    tags = 'capacitor electrolytic'
    if name[:2] == "C_":
        description += " nonpolar"
        tags += " nonpolar"
    if 'extra_description' in kwargs:
        description += ", " + kwargs['extra_description']

    # ensure all provided dimensions are fully toleranced
    device_dimensions = {
        'body_length': TolerancedSize.fromYaml(kwargs,
                                               base_name='body_length'),
        'body_width': TolerancedSize.fromYaml(kwargs, base_name='body_width'),
        'body_height': TolerancedSize.fromYaml(kwargs,
                                               base_name='body_height'),
        'body_diameter': TolerancedSize.fromYaml(kwargs,
                                                 base_name='body_diameter')
    }

    # for ease of use, capture nominal body and pad sizes
    body_size = {
        'length': device_dimensions['body_length'].nominal,
        'width': device_dimensions['body_width'].nominal,
        'height': device_dimensions['body_height'].nominal,
        'diameter': device_dimensions['body_diameter'].nominal
    }

    description += ", " + str(body_size['diameter']) + "x" + str(
        body_size['height']) + "mm"
    kicad_mod.setDescription(description + datasheet)
    kicad_mod.setTags(tags)
    kicad_mod.setAttribute('smd')

    # set general values
    text_offset_y = body_size['width'] / 2.0 + configuration[
        'courtyard_offset']['default'] + 0.8

    #silkscreen REF**
    silk_text_size = configuration['references'][0]['size']
    silk_text_thickness = silk_text_size[0] * configuration['references'][0][
        'fontwidth']
    kicad_mod.append(
        Text(type='reference',
             text='REF**',
             at=[0, -text_offset_y],
             layer='F.SilkS',
             size=[silk_text_size[0], silk_text_size[1]],
             thickness=silk_text_thickness))
    #fab value
    fab_text_size = configuration['values'][0]['size']
    fab_text_thickness = fab_text_size[0] * configuration['values'][0][
        'fontwidth']
    kicad_mod.append(
        Text(type='value',
             text=name,
             at=[0, text_offset_y],
             layer='F.Fab',
             size=[fab_text_size[0], fab_text_size[1]],
             thickness=fab_text_thickness))
    #fab REF**
    fab_text_size = body_size['diameter'] / 5.0
    fab_text_size = min(fab_text_size,
                        configuration['references'][1]['size_max'][0])
    fab_text_size = max(fab_text_size,
                        configuration['references'][1]['size_min'][0])
    fab_text_thickness = fab_text_size * configuration['references'][1][
        'thickness_factor']
    kicad_mod.append(
        Text(type='user',
             text='%R',
             at=[0, 0],
             layer='F.Fab',
             size=[fab_text_size, fab_text_size],
             thickness=fab_text_thickness))

    # create pads
    # all pads have these properties
    pad_params = {
        'type': Pad.TYPE_SMT,
        'layers': Pad.LAYERS_SMT,
        'shape': Pad.SHAPE_RECT
    }

    # prefer IPC-7351C compliant rounded rectangle pads
    if not configuration['force_rectangle_pads']:
        pad_params['shape'] = Pad.SHAPE_ROUNDRECT
        pad_params['radius_ratio'] = 0.25
        pad_params['maximum_radius'] = 0.25

    # prefer calculating pads from lead dimensions per IPC
    # fall back to using pad sizes directly if necessary
    if ('lead_length' in kwargs) and ('lead_width'
                                      in kwargs) and ('lead_spacing'
                                                      in kwargs):
        # gather IPC data (unique parameters for >= 10mm tall caps)
        ipc_density_suffix = '' if body_size['height'] < 10 else '_10mm'
        ipc_density = configuration['ipc_density']
        ipc_data = ipc_defintions['ipc_spec_capae_crystal'][ipc_density +
                                                            ipc_density_suffix]
        ipc_round_base = ipc_defintions['ipc_spec_capae_crystal']['round_base']

        manf_tol = {
            'F': configuration.get('manufacturing_tolerance', 0.1),
            'P': configuration.get('placement_tolerance', 0.05)
        }

        # # fully tolerance lead dimensions; leads are dimensioned like SOIC so use gullwing calculator
        device_dimensions['lead_width'] = TolerancedSize.fromYaml(
            kwargs, base_name='lead_width')
        device_dimensions['lead_spacing'] = TolerancedSize.fromYaml(
            kwargs, base_name='lead_spacing')
        device_dimensions['lead_length'] = TolerancedSize.fromYaml(
            kwargs, base_name='lead_length')
        device_dimensions['lead_outside'] = TolerancedSize(
            maximum=device_dimensions['lead_spacing'].maximum +
            device_dimensions.get('lead_length').maximum * 2,
            minimum=device_dimensions['lead_spacing'].minimum +
            device_dimensions.get('lead_length').minimum * 2)

        Gmin, Zmax, Xmax = ipc_gull_wing(
            ipc_data,
            ipc_round_base,
            manf_tol,
            device_dimensions['lead_width'],
            device_dimensions['lead_outside'],
            lead_len=device_dimensions.get('lead_length'))

        pad_params['size'] = [(Zmax - Gmin) / 2.0, Xmax]

        x_pad_spacing = (Zmax + Gmin) / 4.0
    elif ('pad_length'
          in kwargs) and ('pad_width' in kwargs) and ('pad_spacing' in kwargs):
        x_pad_spacing = kwargs['pad_spacing'] / 2.0 + kwargs['pad_length'] / 2.0
        pad_params['size'] = [kwargs['pad_length'], kwargs['pad_width']]
    else:
        raise KeyError(
            "Provide all three 'pad' or 'lead' properties ('_spacing', '_length', and '_width')"
        )

    kicad_mod.append(Pad(number=1, at=[-x_pad_spacing, 0], **pad_params))
    kicad_mod.append(Pad(number=2, at=[x_pad_spacing, 0], **pad_params))

    # create fabrication layer
    fab_x = body_size['length'] / 2.0
    fab_y = body_size['width'] / 2.0

    if kwargs['pin1_chamfer'] == 'auto':
        fab_edge = min(fab_x / 2.0, fab_y / 2.0,
                       configuration['fab_pin1_marker_length'])
    else:
        fab_edge = kwargs['pin1_chamfer']
    fab_x_edge = fab_x - fab_edge
    fab_y_edge = fab_y - fab_edge
    kicad_mod.append(
        Line(start=[fab_x, -fab_y],
             end=[fab_x, fab_y],
             layer='F.Fab',
             width=configuration['fab_line_width']))
    kicad_mod.append(
        Line(start=[-fab_x_edge, -fab_y],
             end=[fab_x, -fab_y],
             layer='F.Fab',
             width=configuration['fab_line_width']))
    kicad_mod.append(
        Line(start=[-fab_x_edge, fab_y],
             end=[fab_x, fab_y],
             layer='F.Fab',
             width=configuration['fab_line_width']))
    if fab_edge > 0:
        kicad_mod.append(
            Line(start=[-fab_x, -fab_y_edge],
                 end=[-fab_x, fab_y_edge],
                 layer='F.Fab',
                 width=configuration['fab_line_width']))
        kicad_mod.append(
            Line(start=[-fab_x, -fab_y_edge],
                 end=[-fab_x_edge, -fab_y],
                 layer='F.Fab',
                 width=configuration['fab_line_width']))
    kicad_mod.append(
        Line(start=[-fab_x, fab_y_edge],
             end=[-fab_x_edge, fab_y],
             layer='F.Fab',
             width=configuration['fab_line_width']))
    kicad_mod.append(
        Circle(center=[0, 0],
               radius=body_size['diameter'] / 2.0,
               layer='F.Fab',
               width=configuration['fab_line_width']))

    #fab polarity marker for polarized caps
    if name[:2].upper() == "CP":
        fab_pol_size = body_size['diameter'] / 10.0
        fab_pol_wing = fab_pol_size / 2.0
        fab_pol_distance = body_size[
            'diameter'] / 2.0 - fab_pol_wing - configuration['fab_line_width']
        fab_pol_pos_y = fab_text_size / 2.0 + configuration[
            'silk_pad_clearance'] + fab_pol_size
        fab_pol_pos_x = math.sqrt(fab_pol_distance * fab_pol_distance -
                                  fab_pol_pos_y * fab_pol_pos_y)
        fab_pol_pos_x = -fab_pol_pos_x
        fab_pol_pos_y = -fab_pol_pos_y
        kicad_mod.append(
            Line(start=[fab_pol_pos_x - fab_pol_wing, fab_pol_pos_y],
                 end=[fab_pol_pos_x + fab_pol_wing, fab_pol_pos_y],
                 layer='F.Fab',
                 width=configuration['fab_line_width']))
        kicad_mod.append(
            Line(start=[fab_pol_pos_x, fab_pol_pos_y - fab_pol_wing],
                 end=[fab_pol_pos_x, fab_pol_pos_y + fab_pol_wing],
                 layer='F.Fab',
                 width=configuration['fab_line_width']))

    # create silkscreen
    fab_to_silk_offset = configuration['silk_fab_offset']
    silk_x = body_size['length'] / 2.0 + fab_to_silk_offset
    silk_y = body_size['width'] / 2.0 + fab_to_silk_offset
    silk_y_start = pad_params['size'][1] / 2.0 + configuration[
        'silk_pad_clearance'] + configuration['silk_line_width'] / 2.0
    silk_45deg_offset = fab_to_silk_offset * math.tan(math.radians(22.5))
    silk_x_edge = fab_x - fab_edge + silk_45deg_offset
    silk_y_edge = fab_y - fab_edge + silk_45deg_offset

    kicad_mod.append(
        Line(start=[silk_x, silk_y],
             end=[silk_x, silk_y_start],
             layer='F.SilkS',
             width=configuration['silk_line_width']))
    kicad_mod.append(
        Line(start=[silk_x, -silk_y],
             end=[silk_x, -silk_y_start],
             layer='F.SilkS',
             width=configuration['silk_line_width']))
    kicad_mod.append(
        Line(start=[-silk_x_edge, -silk_y],
             end=[silk_x, -silk_y],
             layer='F.SilkS',
             width=configuration['silk_line_width']))
    kicad_mod.append(
        Line(start=[-silk_x_edge, silk_y],
             end=[silk_x, silk_y],
             layer='F.SilkS',
             width=configuration['silk_line_width']))

    if silk_y_edge > silk_y_start:
        kicad_mod.append(
            Line(start=[-silk_x, silk_y_edge],
                 end=[-silk_x, silk_y_start],
                 layer='F.SilkS',
                 width=configuration['silk_line_width']))
        kicad_mod.append(
            Line(start=[-silk_x, -silk_y_edge],
                 end=[-silk_x, -silk_y_start],
                 layer='F.SilkS',
                 width=configuration['silk_line_width']))

        kicad_mod.append(
            Line(start=[-silk_x, -silk_y_edge],
                 end=[-silk_x_edge, -silk_y],
                 layer='F.SilkS',
                 width=configuration['silk_line_width']))
        kicad_mod.append(
            Line(start=[-silk_x, silk_y_edge],
                 end=[-silk_x_edge, silk_y],
                 layer='F.SilkS',
                 width=configuration['silk_line_width']))
    else:
        silk_x_cut = silk_x - (
            silk_y_start - silk_y_edge
        )  # because of the 45 degree edge we can user a simple apporach
        silk_y_edge_cut = silk_y_start

        kicad_mod.append(
            Line(start=[-silk_x_cut, -silk_y_edge_cut],
                 end=[-silk_x_edge, -silk_y],
                 layer='F.SilkS',
                 width=configuration['silk_line_width']))
        kicad_mod.append(
            Line(start=[-silk_x_cut, silk_y_edge_cut],
                 end=[-silk_x_edge, silk_y],
                 layer='F.SilkS',
                 width=configuration['silk_line_width']))

    #silk polarity marker
    if name[:2].upper() == "CP":
        silk_pol_size = body_size['diameter'] / 8.0
        silk_pol_wing = silk_pol_size / 2.0
        silk_pol_pos_y = silk_y_start + silk_pol_size
        silk_pol_pos_x = silk_x + silk_pol_wing + configuration[
            'silk_line_width'] * 2
        silk_pol_pos_x = -silk_pol_pos_x
        silk_pol_pos_y = -silk_pol_pos_y
        kicad_mod.append(
            Line(start=[silk_pol_pos_x - silk_pol_wing, silk_pol_pos_y],
                 end=[silk_pol_pos_x + silk_pol_wing, silk_pol_pos_y],
                 layer='F.SilkS',
                 width=configuration['silk_line_width']))
        kicad_mod.append(
            Line(start=[silk_pol_pos_x, silk_pol_pos_y - silk_pol_wing],
                 end=[silk_pol_pos_x, silk_pol_pos_y + silk_pol_wing],
                 layer='F.SilkS',
                 width=configuration['silk_line_width']))

    # create courtyard
    courtyard_offset = configuration['courtyard_offset']['default']
    courtyard_x = body_size['length'] / 2.0 + courtyard_offset
    courtyard_y = body_size['width'] / 2.0 + courtyard_offset
    courtyard_pad_x = x_pad_spacing + pad_params['size'][
        0] / 2.0 + courtyard_offset
    courtyard_pad_y = pad_params['size'][1] / 2.0 + courtyard_offset
    courtyard_45deg_offset = courtyard_offset * math.tan(math.radians(22.5))
    courtyard_x_edge = fab_x - fab_edge + courtyard_45deg_offset
    courtyard_y_edge = fab_y - fab_edge + courtyard_45deg_offset
    courtyard_x_lower_edge = courtyard_x
    if courtyard_y_edge < courtyard_pad_y:
        courtyard_x_lower_edge = courtyard_x_lower_edge - courtyard_pad_y + courtyard_y_edge
        courtyard_y_edge = courtyard_pad_y
    #rounding
    courtyard_x = float(format(courtyard_x, ".2f"))
    courtyard_y = float(format(courtyard_y, ".2f"))
    courtyard_pad_x = float(format(courtyard_pad_x, ".2f"))
    courtyard_pad_y = float(format(courtyard_pad_y, ".2f"))
    courtyard_x_edge = float(format(courtyard_x_edge, ".2f"))
    courtyard_y_edge = float(format(courtyard_y_edge, ".2f"))
    courtyard_x_lower_edge = float(format(courtyard_x_lower_edge, ".2f"))

    # drawing courtyard
    kicad_mod.append(
        Line(start=[courtyard_x, -courtyard_y],
             end=[courtyard_x, -courtyard_pad_y],
             layer='F.CrtYd',
             width=configuration['courtyard_line_width']))
    kicad_mod.append(
        Line(start=[courtyard_x, -courtyard_pad_y],
             end=[courtyard_pad_x, -courtyard_pad_y],
             layer='F.CrtYd',
             width=configuration['courtyard_line_width']))
    kicad_mod.append(
        Line(start=[courtyard_pad_x, -courtyard_pad_y],
             end=[courtyard_pad_x, courtyard_pad_y],
             layer='F.CrtYd',
             width=configuration['courtyard_line_width']))
    kicad_mod.append(
        Line(start=[courtyard_pad_x, courtyard_pad_y],
             end=[courtyard_x, courtyard_pad_y],
             layer='F.CrtYd',
             width=configuration['courtyard_line_width']))
    kicad_mod.append(
        Line(start=[courtyard_x, courtyard_pad_y],
             end=[courtyard_x, courtyard_y],
             layer='F.CrtYd',
             width=configuration['courtyard_line_width']))

    kicad_mod.append(
        Line(start=[-courtyard_x_edge, courtyard_y],
             end=[courtyard_x, courtyard_y],
             layer='F.CrtYd',
             width=configuration['courtyard_line_width']))
    kicad_mod.append(
        Line(start=[-courtyard_x_edge, -courtyard_y],
             end=[courtyard_x, -courtyard_y],
             layer='F.CrtYd',
             width=configuration['courtyard_line_width']))
    if fab_edge > 0:
        kicad_mod.append(
            Line(start=[-courtyard_x_lower_edge, courtyard_y_edge],
                 end=[-courtyard_x_edge, courtyard_y],
                 layer='F.CrtYd',
                 width=configuration['courtyard_line_width']))
        kicad_mod.append(
            Line(start=[-courtyard_x_lower_edge, -courtyard_y_edge],
                 end=[-courtyard_x_edge, -courtyard_y],
                 layer='F.CrtYd',
                 width=configuration['courtyard_line_width']))
    if courtyard_y_edge > courtyard_pad_y:
        kicad_mod.append(
            Line(start=[-courtyard_x, -courtyard_y_edge],
                 end=[-courtyard_x, -courtyard_pad_y],
                 layer='F.CrtYd',
                 width=configuration['courtyard_line_width']))
        kicad_mod.append(
            Line(start=[-courtyard_x, courtyard_pad_y],
                 end=[-courtyard_x, courtyard_y_edge],
                 layer='F.CrtYd',
                 width=configuration['courtyard_line_width']))
    kicad_mod.append(
        Line(start=[-courtyard_x_lower_edge, -courtyard_pad_y],
             end=[-courtyard_pad_x, -courtyard_pad_y],
             layer='F.CrtYd',
             width=configuration['courtyard_line_width']))
    kicad_mod.append(
        Line(start=[-courtyard_pad_x, -courtyard_pad_y],
             end=[-courtyard_pad_x, courtyard_pad_y],
             layer='F.CrtYd',
             width=configuration['courtyard_line_width']))
    kicad_mod.append(
        Line(start=[-courtyard_pad_x, courtyard_pad_y],
             end=[-courtyard_x_lower_edge, courtyard_pad_y],
             layer='F.CrtYd',
             width=configuration['courtyard_line_width']))

    lib_name = 'Capacitor_SMD'
    # add model
    modelname = name.replace("_HandSoldering", "")
    kicad_mod.append(
        Model(filename="{model_prefix:s}{lib_name:s}.3dshapes/{name:s}.wrl".
              format(model_prefix=configuration['3d_model_prefix'],
                     lib_name=lib_name,
                     name=modelname),
              at=[0, 0, 0],
              scale=[1, 1, 1],
              rotate=[0, 0, 0]))

    # write file
    output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name)
    if not os.path.isdir(
            output_dir
    ):  #returns false if path does not yet exist!! (Does not check path validity)
        os.makedirs(output_dir)

    filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir,
                                                        fp_name=name)
    file_handler = KicadFileHandler(kicad_mod)
    file_handler.writeFile(filename)
    def generateFootprints(self):
        fab_line_width = self.configuration.get('fab_line_width', 0.1)
        silk_line_width = self.configuration.get('silk_line_width', 0.12)

        for group_name in self.footprint_group_definitions:
            #print(device_group)
            footprint_group_data = self.footprint_group_definitions[group_name]

            device_size_docs = footprint_group_data['size_definitions']
            package_size_defintions={}
            for device_size_doc in device_size_docs:
                with open(size_definition_path+device_size_doc, 'r') as size_stream:
                    try:
                        package_size_defintions.update(yaml.load(size_stream))
                    except yaml.YAMLError as exc:
                        print(exc)

            for size_name in package_size_defintions:
                device_size_data = package_size_defintions[size_name]

                ipc_reference = footprint_group_data['ipc_reference']
                ipc_density = footprint_group_data['ipc_density']
                ipc_data_set = self.ipc_defintions[ipc_reference][ipc_density]
                ipc_round_base = self.ipc_defintions[ipc_reference]['round_base']

                pad_details, paste_details = self.calcPadDetails(device_size_data, ipc_data_set, ipc_round_base, footprint_group_data)
                #print(calc_pad_details())
                #print("generate {name}.kicad_mod".format(name=footprint))

                suffix = footprint_group_data.get('suffix', '').format(pad_x=pad_details['size'][0],
                    pad_y=pad_details['size'][1])
                prefix = footprint_group_data['prefix']

                model3d_path_prefix = self.configuration.get('3d_model_prefix','${KISYS3DMOD}')
                suffix_3d = suffix if footprint_group_data.get('include_suffix_in_3dpath', 'True') == 'True' else ""

                code_metric = device_size_data.get('code_metric')
                code_letter = device_size_data.get('code_letter')
                code_imperial = device_size_data.get('code_imperial')

                if 'code_letter' in device_size_data:
                    name_format = self.configuration['fp_name_tantal_format_string']
                else:
                    if 'code_metric' in device_size_data:
                        name_format = self.configuration['fp_name_format_string']
                    else:
                        name_format = self.configuration['fp_name_non_metric_format_string']

                fp_name = name_format.format(prefix=prefix,
                    code_imperial=code_imperial, code_metric=code_metric,
                    code_letter=code_letter, suffix=suffix)
                fp_name_2 = name_format.format(prefix=prefix,
                    code_imperial=code_imperial, code_letter=code_letter,
                    code_metric=code_metric, suffix=suffix_3d)
                model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format(
                    model3d_path_prefix=model3d_path_prefix, lib_name=footprint_group_data['fp_lib_name'], fp_name=fp_name_2)
                #print(fp_name)
                #print(pad_details)

                kicad_mod = Footprint(fp_name)

                # init kicad footprint
                kicad_mod.setDescription(footprint_group_data['description'].format(code_imperial=code_imperial,
                    code_metric=code_metric, code_letter=code_letter,
                    size_info=device_size_data.get('size_info')))
                kicad_mod.setTags(footprint_group_data['keywords'])
                kicad_mod.setAttribute('smd')

                if paste_details is not None:
                    kicad_mod.append(Pad(number= 1, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT,
                        layers=['F.Cu', 'F.Mask'], **pad_details))
                    pad_details['at'][0] *= (-1)
                    kicad_mod.append(Pad(number= 2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT,
                        layers=['F.Cu', 'F.Mask'], **pad_details))

                    kicad_mod.append(Pad(number= '', type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT,
                        layers=['F.Paste'], **paste_details))
                    paste_details['at'][0] *= (-1)
                    kicad_mod.append(Pad(number= '', type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT,
                        layers=['F.Paste'], **paste_details))
                else:
                    kicad_mod.append(Pad(number= 1, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT,
                        layers=Pad.LAYERS_SMT, **pad_details))
                    pad_details['at'][0] *= (-1)
                    kicad_mod.append(Pad(number= 2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT,
                        layers=Pad.LAYERS_SMT, **pad_details))

                fab_outline = self.configuration.get('fab_outline', 'typical')
                if fab_outline == 'max':
                    outline_size = [device_size_data['body_length_max'], device_size_data['body_width_max']]
                elif fab_outline == 'min':
                    outline_size = [device_size_data['body_length_min'], device_size_data['body_width_min']]
                else:
                    outline_size = [device_size_data['body_length'], device_size_data['body_width']]

                if footprint_group_data.get('polarization_mark', 'False') == 'True':
                    polararity_marker_size = self.configuration.get('fab_polarity_factor', 0.25)
                    polararity_marker_size *= (outline_size[1] if outline_size[1] < outline_size[0] else outline_size[0])

                    polarity_marker_thick_line = False

                    polarity_max_size = self.configuration.get('fab_polarity_max_size', 1)
                    if polararity_marker_size > polarity_max_size:
                        polararity_marker_size = polarity_max_size
                    polarity_min_size = self.configuration.get('fab_polarity_min_size', 0.25)
                    if polararity_marker_size < polarity_min_size:
                        if polararity_marker_size < polarity_min_size*0.6:
                            polarity_marker_thick_line = True
                        polararity_marker_size = polarity_min_size

                    silk_x_left = -abs(pad_details['at'][0]) - pad_details['size'][0]/2 - \
                        self.configuration['pad_silk_clearance'] - silk_line_width/2

                    silk_y_bottom = self.configuration['pad_silk_clearance'] + silk_line_width/2 + \
                        (outline_size[1] if outline_size[1]> pad_details['size'][1] else pad_details['size'][1])/2

                    if polarity_marker_thick_line:
                        kicad_mod.append(RectLine(start=[-outline_size[0]/2, outline_size[1]/2],
                            end=[outline_size[0]/2, -outline_size[1]/2],
                            layer='F.Fab', width=fab_line_width))
                        x = -outline_size[0]/2 + fab_line_width
                        kicad_mod.append(Line(start=[x, outline_size[1]/2],
                            end=[x, -outline_size[1]/2],
                            layer='F.Fab', width=fab_line_width))
                        x += fab_line_width
                        if x < -fab_line_width/2:
                            kicad_mod.append(Line(start=[x, outline_size[1]/2],
                                end=[x, -outline_size[1]/2],
                                layer='F.Fab', width=fab_line_width))

                        kicad_mod.append(Circle(center=[silk_x_left-0.05, 0],
                            radius=0.05, layer="F.SilkS", width=0.1))
                    else:
                        poly_fab= [
                            {'x':outline_size[0]/2,'y':-outline_size[1]/2},
                            {'x':polararity_marker_size - outline_size[0]/2,'y':-outline_size[1]/2},
                            {'x':-outline_size[0]/2,'y':polararity_marker_size-outline_size[1]/2},
                            {'x':-outline_size[0]/2,'y':outline_size[1]/2},
                            {'x':outline_size[0]/2,'y':outline_size[1]/2},
                            {'x':outline_size[0]/2,'y':-outline_size[1]/2}
                        ]
                        kicad_mod.append(PolygoneLine(polygone=poly_fab, layer='F.Fab', width=fab_line_width))

                        poly_silk = [
                            {'x':outline_size[0]/2,'y':-silk_y_bottom},
                            {'x':silk_x_left,'y':-silk_y_bottom},
                            {'x':silk_x_left,'y':silk_y_bottom},
                            {'x':outline_size[0]/2,'y':silk_y_bottom}
                        ]
                        kicad_mod.append(PolygoneLine(polygone=poly_silk, layer='F.SilkS', width=silk_line_width))
                else:
                    kicad_mod.append(RectLine(start=[-outline_size[0]/2, outline_size[1]/2],
                        end=[outline_size[0]/2, -outline_size[1]/2],
                        layer='F.Fab', width=fab_line_width))

                    pad_spacing = 2*abs(pad_details['at'][0])-pad_details['size'][0]
                    if pad_spacing > 2*self.configuration['pad_silk_clearance'] + \
                            self.configuration['silk_line_lenght_min'] + self.configuration['silk_line_width']:
                        silk_outline_x = pad_spacing/2 - silk_line_width - self.configuration['pad_silk_clearance']
                        silk_outline_y = outline_size[1]/2 + self.configuration['silk_fab_offset']

                        kicad_mod.append(Line(start=[-silk_outline_x, -silk_outline_y],
                            end=[silk_outline_x, -silk_outline_y], layer='F.SilkS', width=silk_line_width))
                        kicad_mod.append(Line(start=[-silk_outline_x, silk_outline_y],
                            end=[silk_outline_x, silk_outline_y], layer='F.SilkS', width=silk_line_width))

                CrtYd_rect = [None,None]
                CrtYd_rect[0] = roundToBase(2 * abs(pad_details['at'][0]) + \
                    pad_details['size'][0] + 2 * ipc_data_set['courtyard'], 0.02)
                if pad_details['size'][1] > outline_size[1]:
                    CrtYd_rect[1] = pad_details['size'][1] + 2 * ipc_data_set['courtyard']
                else:
                    CrtYd_rect[1] = outline_size[1] + 2 * ipc_data_set['courtyard']

                CrtYd_rect[1] = roundToBase(CrtYd_rect[1], 0.02)

                kicad_mod.append(RectLine(start=[-CrtYd_rect[0]/2, CrtYd_rect[1]/2],
                    end=[CrtYd_rect[0]/2, -CrtYd_rect[1]/2],
                    layer='F.CrtYd', width=self.configuration['courtyard_line_width']))

                reference_fields = self.configuration['references']
                kicad_mod.append(Text(type='reference', text='REF**',
                    **self.getTextFieldDetails(reference_fields[0], outline_size)))

                for additional_ref in reference_fields[1:]:
                    kicad_mod.append(Text(type='user', text='%R',
                    **self.getTextFieldDetails(additional_ref, outline_size)))

                value_fields = self.configuration['values']
                kicad_mod.append(Text(type='value', text=fp_name,
                    **self.getTextFieldDetails(value_fields[0], outline_size)))

                for additional_value in value_fields[1:]:
                    kicad_mod.append(Text(type='user', text='%V',
                        **self.getTextFieldDetails(additional_value, outline_size)))

                kicad_mod.append(Model(filename=model_name))
                output_dir = '{lib_name:s}.pretty/'.format(lib_name=footprint_group_data['fp_lib_name'])
                if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity)
                    os.makedirs(output_dir)
                filename =  '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=fp_name)

                file_handler = KicadFileHandler(kicad_mod)
                file_handler.writeFile(filename)