Beispiel #1
0
    def exportKiCadModule(
            self,
            filename,
            footprint_name='EM-Structure',
            description="EM Structure imported from Gerber file format.",
            tags="em structure gerber"):
        mod = kmt.Footprint(footprint_name)
        mod.setDescription(description)
        mod.setTags(tags)

        # set general values
        mod.append(
            kmt.Text(type='reference',
                     text='REF**',
                     at=[0, -3],
                     layer='F.SilkS'))
        mod.append(
            kmt.Text(type='value',
                     text=footprint_name,
                     at=[1.5, 3],
                     layer='F.Fab'))

        # create silscreen
        #mod.append(kmt.RectLine(start=[-2, -2], end=[5, 2], layer='F.SilkS'))

        (minx, miny, maxx, maxy) = self.boundingBox()
        w = maxx - minx
        h = maxy - miny
        ox = -maxx + w / 2
        oy = -maxy + h / 2

        # create courtyard
        mod.append(
            kmt.RectLine(start=[-w / 2, -h / 2],
                         end=[w / 2, h / 2],
                         layer='F.CrtYd'))
        #mod.append(kmt.FilledRect(start=[-w/2, -h/2], end=[w/2, h/2], layer='F.Mask'))

        n = 1

        # iterate layers
        for layer in self.gerberLayers:
            n = layer.appendKicadLayer(mod,
                                       mod_layer=layer.getID(),
                                       offset_x=ox,
                                       offset_y=oy,
                                       startpad=n)

        # output kicad model
        file_handler = kmt.KicadFileHandler(mod)
        file_handler.writeFile(filename)
def coil_footrpint(name, description, tags, other_parts):
    fp = kmt.Footprint(name)
    fp.setDescription(description)
    fp.setTags(tags)

    # add some text: reference and value
    fp.append(
        kmt.Text(type='reference', text='REF**', at=[0, -2], layer='F.SilkS'))
    fp.append(kmt.Text(type='value', text=name, at=[1.5, 2], layer='F.Fab'))

    for part in other_parts:
        fp.append(part)

    return fp
def coil_pads(start_point, end_point, line_width, drill, pad_type, pad_shape):
    if pad_type == 'SMT':
        pad_type = kmt.Pad.TYPE_THT
        pad_layer = kmt.Pad.LAYERS_THT
        drill_kw = dict(drill=drill)
    elif pad_type == 'THT':
        pad_type = kmt.Pad.TYPE_THT
        pad_layer = kmt.Pad.LAYERS_THT
        drill_kw = dict(drill=drill)
    elif pad_type == 'CONNECT':
        pad_type = kmt.Pad.TYPE_CONNECT
        pad_layer = kmt.Pad.LAYERS_THT
        drill_kw = dict()
    else:
        raise Exception('pad_type must be one of "SMT","THT" or "CONNECT"')
    if pad_shape == 'RECTANGLE':
        pad_shape = kmt.Pad.SHAPE_RECT
    elif pad_shape == 'CIRCLE':
        pad_shape = kmt.Pad.SHAPE_CIRCLE
    else:
        raise Exception('pad_type must be one of "RECTANGLE" or "CIRCLE"')
    if line_width - drill < 0.25:
        raise Exception('The width of the ring has to be greater than 0.25mm')
    pads = []
    for i, pos in enumerate([start_point, end_point]):
        pad = kmt.Pad(number=i + 1,
                      type=pad_type,
                      shape=pad_shape,
                      at=pos,
                      size=[line_width, line_width],
                      layers=pad_layer,
                      **drill_kw)
        pads.append(pad)
    return pads
Beispiel #4
0
    def _boundToKmtPoly(self, bound, layer, offset_x, offset_y):
        # get coordinates in (x, y) form
        m = geo.mapping(bound)
        c = m['coordinates']

        # translate coordinates with offset
        c_transl = []

        for x, y in c:
            c_transl.append([x + offset_x, -y - offset_y])

        return kmt.Polygon(nodes=c_transl, layer=layer, width=0)
Beispiel #5
0
def coil_lines(params, direction=+1):
    """
    Creates a square spiral coil.

    It is assumed that we want to fill as much space as possible,
    and so the length of line is shortened only after full turn.
    The coil starts at corner of the square and ends in "previous"
    corner.
    """
    n_turns = int(params.n_turns)
    if abs(n_turns - params.n_turns) > 0.01:
        print('[WARNING] square coil can only have integer number of turns;'
              ' reducing n_turns to %d' % n_turns)

    points = []
    points.append((params.r_outer, -params.r_outer))
    for i in range(n_turns):
        r = params.r_outer - i * delta_r(params)
        next_r = r - delta_r(params)
        if direction > 0:
            turn_points = [
                (-r, -r),
                (-r, r),
                (r, r),
                (r, -next_r),
            ]
        else:
            turn_points = [
                (r, r),
                (-r, r),
                (-r, -r),
                (next_r, -r),
            ]
        points.extend(turn_points)

    lines = []
    for i in range(len(points) - 1):
        lines.append(
            kmt.Line(start=points[i],
                     end=points[i + 1],
                     width=params.line_width,
                     layer='F.Cu'))

    start_point = points[0]
    end_point = points[-1]

    return lines, start_point, end_point
def coil_pads(start_point, end_point, line_width, drill):

    pad_type = kmt.Pad.TYPE_THT
    pad_layer = kmt.Pad.LAYERS_THT
    drill_kw = dict(drill=drill)

    pad_shape = kmt.Pad.SHAPE_CIRCLE

    pads = []
    for i, pos in enumerate([start_point, end_point]):
        pad = kmt.Pad(number=i + 1,
                      type=pad_type,
                      shape=pad_shape,
                      at=pos,
                      size=[line_width, line_width],
                      layers=pad_layer,
                      **drill_kw)
        pads.append(pad)
    return pads
Beispiel #7
0
    def appendKicadLayer(self,
                         kicad_mod,
                         mod_layer='F.Cu',
                         offset_x=0,
                         offset_y=0,
                         startpad=1):
        '''
        Write the layer to a kicad_mod object from the KicadModTree.
        '''
        n = startpad

        # iterate closed polygons
        for net in self.nets:
            #if len(net.getPads()) == 0:
            # no pad = poly primitive
            # get polygon object
            poly = net.getPolygon()

            # convert to KMT polygon
            kmt_poly = self._polyToKmtPoly(poly, mod_layer, offset_x, offset_y)

            # save
            kicad_mod.append(kmt_poly)

            #else:
            pads = net.getPads()
            #                 # first pad is anchor
            #                 anch = pads[0]
            #
            #                 # center point
            #                 (pxmin, pymin, pxmax, pymax) = anch.bounds
            #                 px = (pxmin + pxmax) / 2
            #                 py = (pymin + pymax) / 2
            #
            #                 # size and rotation
            #                 x1, y1 = anch.boundary.coords[0]
            #                 x2, y2 = anch.boundary.coords[1]
            #                 x3, y3 = anch.boundary.coords[2]
            #                 w = sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)
            #                 h = sqrt((x2 - x3) ** 2 + (y2 - y3) ** 2)
            #                 rot = atan2((y1 - y2), (x1 - x2)) / pi * 180
            #
            #                 # set pad rotation and transform polygon accordingly
            #                 rot_poly = aff.rotate(net.getPolygon(), -rot, (px, py))
            #
            #                 # convert to KMT polygon
            #                 kmt_poly = self._polyToKmtPoly(rot_poly, mod_layer, -px, -py)
            #
            #                 # create pad
            #                 kicad_mod.append(kmt.Pad(number = n, type=kmt.Pad.TYPE_SMT, shape = kmt.Pad.SHAPE_CUSTOM, layers = [mod_layer],
            #                                    at=[px + offset_x, -(py + offset_y)], size=[w, h], rotation=rot, primitives=[kmt_poly], anchor_shape=kmt.Pad.SHAPE_RECT))
            #
            # other pads are simple squares
            #for i in range(1, len(pads)):
            for i in range(len(pads)):
                # center point
                (pxmin, pymin, pxmax, pymax) = pads[i].bounds
                px = (pxmin + pxmax) / 2 + offset_x
                py = -((pymin + pymax) / 2 + offset_y)

                # size and rotation
                x1, y1 = pads[i].boundary.coords[0]
                x2, y2 = pads[i].boundary.coords[1]
                x3, y3 = pads[i].boundary.coords[2]
                w = sqrt((x1 - x2)**2 + (y1 - y2)**2)
                h = sqrt((x2 - x3)**2 + (y2 - y3)**2)
                rot = atan2((y1 - y2), (x1 - x2)) / pi * 180

                kicad_mod.append(
                    kmt.Pad(number=n,
                            type=kmt.Pad.TYPE_SMT,
                            shape=kmt.Pad.SHAPE_RECT,
                            layers=[mod_layer],
                            at=[px, py],
                            size=[w, h],
                            rotation=rot))

            # increase pad number
            n = n + 1

        return n
def save_footprint(footprint, file_name):
    if not file_name.endswith('.kicad_mod'):
        file_name = file_name + '.kicad_mod'

    file_handler = kmt.KicadFileHandler(footprint)
    file_handler.writeFile(file_name)
Beispiel #9
0
lines = [''] * 4
for name, color in colors.items():
    parts = get_ball_desc(grid[m][n])
    for i in range(1):
        cstr = '\033[38;2;' + color[0] + 'm' + '\033[48;2;' + color[1] + 'm'
        end = '\033[0m'
        print('██' + cstr + '{:<8}'.format(name) + end, end='')

print('██')
print('█' * (10 * len(colors.items()) + 2))
print()
print('Device Name: ' + device_name)
print('Package: ' + package)

if kicadMod:
    mod = kmt.Footprint(package)
    mod.setDescription(package + ' package')

    border = 1  # 1 mm space around edges, approximately enough for every package

    mod.append(
        kmt.Text(type='reference',
                 text='REF**',
                 at=[(max_m + 1) / 2 * pitch, pitch - border - 3],
                 layer='F.SilkS'))
    mod.append(
        kmt.Text(type='value',
                 text=package,
                 at=[(max_m + 1) / 2 * pitch, pitch - border - 1],
                 layer='F.Fab'))
def rectangle_coil_lines(coil_params, board_layer, via_offset,
                         winding_direction):

    width = coil_params[0]
    height = coil_params[1]
    line_width = coil_params[2]
    line_spacing = coil_params[3]
    n_turns = int(coil_params[4])

    points = []

    #####################
    ## FRONT POSITIVE
    if (board_layer == 'F.Cu') and (winding_direction == 1):
        points.append((-width / 2, height / 2 + via_offset))
        points.append((-width / 2, height / 2))

        for i in np.arange(n_turns):
            x = width / 2 - i * (line_width + line_spacing)
            y = height / 2 - i * (line_width + line_spacing)
            next_y = y - (line_width + line_spacing)
            turn_points = [(x, y), (x, -y), (-x, -y), (-x, next_y)]
            points.extend(turn_points)

        #For the last point, add an offset for the Via
        points.append((0, next_y))
        next_y = y - via_offset
        points.append((0, next_y))

#####################
## BACK POSITIVE
    elif (board_layer == 'B.Cu') and (winding_direction == 1):
        points.append((width / 2, height / 2 + via_offset))
        points.append((width / 2, height / 2))

        for i in np.arange(n_turns):
            x = width / 2 - i * (line_width + line_spacing)
            y = height / 2 - i * (line_width + line_spacing)
            next_y = y - (line_width + line_spacing)
            # turn_points = [(x, -y),(x, -y),(-x, -y),(-x, next_y)]

            turn_points = [(-x, y), (-x, -y), (x, -y), (x, next_y)]

            points.extend(turn_points)

        #For the last point, add an offset for the Via
        points.append((0, next_y))
        next_y = y - via_offset
        points.append((0, next_y))

#####################
## FRONT NEGATIVE
    elif (board_layer == 'F.Cu') and (winding_direction == -1):
        points.append((-width / 2, height / 2 + via_offset))
        points.append((-width / 2, height / 2))

        for i in np.arange(n_turns):
            x = width / 2 - i * (line_width + line_spacing)
            y = height / 2 - i * (line_width + line_spacing)
            next_x = x - (line_width + line_spacing)
            turn_points = [(-x, -y), (x, -y), (x, y), (-next_x, y)]
            points.extend(turn_points)

        #For the last point, add an offset for the Via
        next_y = height / 2 - (n_turns) * (
            line_width + line_spacing)  #next_y not defined for direction == -1
        next_y = y - via_offset
        points.append((-next_x, next_y))
        next_x = next_x - via_offset
        points.append((-next_x, next_y))


#####################
## BACK NEGATIVE
    elif (board_layer == 'B.Cu') and (winding_direction == -1):
        points.append((-width / 2, height / 2 + via_offset))
        points.append((-width / 2, height / 2))

        for i in np.arange(n_turns):
            x = width / 2 - i * (line_width + line_spacing)
            y = height / 2 - i * (line_width + line_spacing)
            next_x = x - (line_width + line_spacing)
            turn_points = [(-x, -y), (x, -y), (x, y), (-next_x, y)]
            points.extend(turn_points)

        #For the last point, add an offset for the Via
        next_y = height / 2 - (n_turns) * (
            line_width + line_spacing)  #next_y not defined for direction == -1
        next_y = y - via_offset
        points.append((-next_x, next_y))
        next_x = next_x - via_offset
        points.append((-next_x, next_y))

    lines = []
    for i in np.arange(len(points) - 1):
        lines.append(
            kmt.Line(start=points[i],
                     end=points[i + 1],
                     width=line_width,
                     layer=board_layer))

    start_point = points[0]
    end_point = points[-1]

    return lines, start_point, end_point
Beispiel #11
0
def coil_arcs(params, points_per_turn=4, direction=+1):
    """
    Approximates Archimedean spiral by a sequence of arcs.
    For each spiral revolution 'points_per_turn' are taken and an arc
    for each pair is drawn.

    The coordinates of start and end points of the line are returned as (x, y).

    Archimedean spiral is defined in polar coordinates by equation:
        r = a + b*theta
    where 'a' is the inner radius.

    We can calculate the outer radius as:
        R = a + b*total_theta
    And solve for b:
        b = (R - a) / total_theta

    We first define the spiral as if it had 0 line width,
    only when generating footprint we draw with the actual width.
    """
    total_angle = 360 * params.n_turns
    b = (params.r_outer - params.r_inner) / math.radians(total_angle) * direction

    # calculate all the angles at which we evaluate points
    angle_increment = 360.0 / points_per_turn
    n_increments = int(total_angle / angle_increment)
    angles = [angle_increment * i for i in range(n_increments)]
    if angles[-1] < total_angle:
        angles += [total_angle]

    def cartesian_coords_for_angle(angle_deg):
        theta = math.radians(angle_deg)
        r = params.r_inner + b * theta
        x, y = polar2cartesian(r, theta)
        return x, y

    arcs = []
    for i in range(len(angles) - 1):
        start_angle = angles[i]
        end_angle = angles[i + 1]
        mid_angle = (start_angle + end_angle) / 2

        start = cartesian_coords_for_angle(start_angle)
        mid = cartesian_coords_for_angle(mid_angle)
        end = cartesian_coords_for_angle(end_angle)

        # calculate the center and angle of the arc
        center, angle_rad = arc_through_3_points(start, mid, end)
        if direction > 0:
            if angle_rad < 0:
                angle_rad += 2 * pi
        else:
            if angle_rad > 0:
                angle_rad -= 2 * pi

        # just draw everything on front copper layer
        layer = 'F.Cu'

        arcs.append(kmt.Arc(center=center, start=start, angle=math.degrees(angle_rad),
                            layer=layer, width=params.line_width))

    start_point = cartesian_coords_for_angle(angles[0])
    end_point = cartesian_coords_for_angle(angles[-1])

    return arcs, start_point, end_point
Beispiel #12
0
    def exportToKicadMod(
            self,
            filename,
            footprint_name='EM-Structure',
            description="EM Structure imported from Gerber file format.",
            tags="em structure gerber"):
        mod = kmt.Footprint(footprint_name)
        mod.setDescription(description)
        mod.setTags(tags)

        # set general values
        mod.append(
            kmt.Text(type='reference',
                     text='REF**',
                     at=[0, -3],
                     layer='F.SilkS'))
        mod.append(
            kmt.Text(type='value',
                     text=footprint_name,
                     at=[1.5, 3],
                     layer='F.Fab'))

        # create silscreen
        #mod.append(kmt.RectLine(start=[-2, -2], end=[5, 2], layer='F.SilkS'))

        (minx, miny, maxx, maxy) = self.boundingBox()
        w = maxx - minx
        h = maxy - miny
        ox = -maxx + w / 2
        oy = -maxy + h / 2

        # create courtyard
        mod.append(
            kmt.RectLine(start=[-w / 2, -h / 2],
                         end=[w / 2, h / 2],
                         layer='F.CrtYd'))
        #mod.append(kmt.FilledRect(start=[-w/2, -h/2], end=[w/2, h/2], layer='F.Mask'))

        n = 1

        # iterate closed polygons
        for poly in self.closedPolygons:
            # find pads
            pads = []

            for p in self.pads:
                if (p.distance(poly) < self.tolerance):
                    pads.append(p)

            if len(pads) == 0:
                # poly primitive
                map = geo.mapping(poly)
                coords = []

                for x, y in map['coordinates'][0]:
                    coords.append([x + ox, -y - oy])

                mod.append(kmt.Polygon(nodes=coords, layer='F.Cu', width=0))

            else:
                # first pad is anchor
                anch = pads[0]

                # center point
                (pxmin, pymin, pxmax, pymax) = anch.bounds
                px = (pxmin + pxmax) / 2
                py = (pymin + pymax) / 2

                # size and rotation
                x1, y1 = anch.boundary.coords[0]
                x2, y2 = anch.boundary.coords[1]
                l = sqrt((x1 - x2)**2 + (y1 - y2)**2)
                rot = atan2((y1 - y2), (x1 - x2)) / pi * 180

                # set pad rotation and transform polygon accordingly
                rot_poly = aff.rotate(poly, -rot, (px, py))

                # poly primitive
                map = geo.mapping(rot_poly)
                coords = []

                for x, y in map['coordinates'][0]:
                    coords.append([x - px, -(y - py)])

                kipoly = kmt.Polygon(nodes=coords)

                # create pad
                mod.append(
                    kmt.Pad(number=n,
                            type=kmt.Pad.TYPE_SMT,
                            shape=kmt.Pad.SHAPE_CUSTOM,
                            layers=['F.Cu'],
                            at=[px + ox, -(py + oy)],
                            size=[l, l],
                            rotation=rot,
                            primitives=[kipoly],
                            anchor_shape=kmt.Pad.SHAPE_RECT))

                # other pads are simple squares
                for i in range(1, len(pads)):
                    # center point
                    (pxmin, pymin, pxmax, pymax) = pads[i].bounds
                    px = (pxmin + pxmax) / 2 + ox
                    py = -((pymin + pymax) / 2 + oy)

                    # size and rotation
                    x1, y1 = pads[i].boundary.coords[0]
                    x2, y2 = pads[i].boundary.coords[1]
                    l = sqrt((x1 - x2)**2 + (y1 - y2)**2)
                    rot = atan2((y1 - y2), (x1 - x2)) / pi * 180

                    mod.append(
                        kmt.Pad(number=n,
                                type=kmt.Pad.TYPE_SMT,
                                shape=kmt.Pad.SHAPE_RECT,
                                layers=['F.Cu'],
                                at=[px, py],
                                size=[l, l],
                                rotation=rot))

                # increase pad number
                n = n + 1

        # output kicad model
        file_handler = kmt.KicadFileHandler(mod)
        file_handler.writeFile(filename)