def generate_one_footprint(pincount, configuration): silk_x_min = x_min - configuration['silk_fab_offset'] silk_y_min = y_min - configuration['silk_fab_offset'] silk_y_max = y_max + configuration['silk_fab_offset'] x_mid = (pincount - 1) * pitch / 2.0 x_max = (pincount - 1) * pitch + 1.95 silk_x_max = x_max + configuration['silk_fab_offset'] # Through-hole type shrouded header, Top entry type mpn = "B{n}B-PH-K".format(n=pincount) #JST part number format string orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format( man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount, mounting_pad="", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription( "JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator" .format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format( series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) # create Silkscreen kicad_mod.append( RectLine(start=[silk_x_min, silk_y_min], end=[silk_x_max, silk_y_max], layer='F.SilkS', width=configuration['silk_line_width'])) silk_inner_left = -1.45 silk_inner_right = x_max - 0.5 poly_silk_p1_protrusion = [{ 'x': -0.3, 'y': silk_y_min }, { 'x': -0.3, 'y': silk_y_min - 0.2 }, { 'x': -0.6, 'y': silk_y_min - 0.2 }, { 'x': -0.6, 'y': silk_y_min }] kicad_mod.append( PolygoneLine(polygone=poly_silk_p1_protrusion, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( Line(start=[-0.3, silk_y_min - 0.1], end=[-0.6, silk_y_min - 0.1], layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['allow_silk_below_part'] == 'tht' or configuration[ 'allow_silk_below_part'] == 'both': poly_silk_inner_outline = [{ 'x': 0.5, 'y': silk_y_min }, { 'x': 0.5, 'y': -1.2 }, { 'x': silk_inner_left, 'y': -1.2 }, { 'x': silk_inner_left, 'y': 2.3 }, { 'x': silk_inner_right, 'y': 2.3 }, { 'x': silk_inner_right, 'y': -1.2 }, { 'x': x_max - 2.45, 'y': -1.2 }, { 'x': x_max - 2.45, 'y': silk_y_min }] kicad_mod.append( PolygoneLine(polygone=poly_silk_inner_outline, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( Line(start=[silk_x_min, -0.5], end=[silk_inner_left, -0.5], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( Line(start=[silk_x_min, 0.8], end=[silk_inner_left, 0.8], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( Line(start=[silk_x_max, -0.5], end=[silk_inner_right, -0.5], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( Line(start=[silk_x_max, 0.8], end=[silk_inner_right, 0.8], layer='F.SilkS', width=configuration['silk_line_width'])) for i in range(0, pincount - 1): middle_x = 1 + i * 2 start_x = middle_x - 0.1 end_x = middle_x + 0.1 poly_silk_inner_protrusion = [{ 'x': start_x, 'y': 2.3 }, { 'x': start_x, 'y': 1.8 }, { 'x': end_x, 'y': 1.8 }, { 'x': end_x, 'y': 2.3 }] kicad_mod.append( PolygoneLine(polygone=poly_silk_inner_protrusion, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( Line(start=[middle_x, 2.3], end=[middle_x, 1.8], layer='F.SilkS', width=configuration['silk_line_width'])) ########################### Pin 1 marker ################################ poly_pin1_marker = [{ 'x': silk_x_min - pin1_marker_offset + pin1_marker_linelen, 'y': silk_y_min - pin1_marker_offset }, { 'x': silk_x_min - pin1_marker_offset, 'y': silk_y_min - pin1_marker_offset }, { 'x': silk_x_min - pin1_marker_offset, 'y': silk_y_min - pin1_marker_offset + pin1_marker_linelen }] kicad_mod.append( PolygoneLine(polygone=poly_pin1_marker, layer='F.SilkS', width=configuration['silk_line_width'])) if fab_pin1_marker_type == 1: kicad_mod.append( PolygoneLine(polygone=poly_pin1_marker, layer='F.Fab', width=configuration['fab_line_width'])) if fab_pin1_marker_type == 2: poly_pin1_marker_type2 = [{ 'x': -1, 'y': y_min }, { 'x': 0, 'y': y_min + 1 }, { 'x': 1, 'y': y_min }] kicad_mod.append( PolygoneLine(polygone=poly_pin1_marker_type2, layer='F.Fab', width=configuration['fab_line_width'])) ########################## Fab Outline ############################### kicad_mod.append( RectLine(start=[x_min, y_min], end=[x_max, y_max], layer='F.Fab', width=configuration['fab_line_width'])) ############################# CrtYd ################################## part_x_min = x_min part_x_max = x_max part_y_min = y_min part_y_max = y_max cx1 = roundToBase( part_x_min - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase( part_y_min - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase( part_x_max + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase( part_y_max + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append( RectLine(start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ############################# Pads ################################## pad_size = [ pitch - pad_to_pad_clearance, drill_size + 2 * pad_copper_y_solder_length ] if pad_size[0] - drill_size < 2 * min_annular_ring: pad_size[0] = drill_size + 2 * min_annular_ring # kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, # at=[0, 0], size=pad_size, # drill=drill_size, layers=Pad.LAYERS_THT)) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append( PadArray(initial=1, start=[0, 0], x_spacing=pitch, pincount=pincount, size=pad_size, drill=drill_size, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT, **optional_pad_params)) ######################### Text Fields ############################### text_center_y = 1.5 body_edge = { 'left': part_x_min, 'right': part_x_max, 'top': part_y_min, 'bottom': part_y_max } addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={ 'top': cy1, 'bottom': cy2 }, fp_name=footprint_name, text_y_inside_position=text_center_y) model3d_path_prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins, configuration): mpn = part_base.format(n=pins) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s}, shrouded ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate dimensions A = (pins - 1) * pitch B = A + 5.84 #coordinate locations (latch is not drawn but is 2.3mm above y5 and width varies) # x1 x5 x3 x4 x6 x2 # y1 ______ ______ # y3 | O |_____________| | # y5 | ___________________ | # | | 1 2 3 4 5 6 7 8 | | # y4 | |__________________| | # y2 |_______________________| #draw the component outline x1 = A/2 - B/2 x2 = x1 + B x3 = x1 + 2.9 x4 = x2 - 2.9 x5 = -2 x6 = pitch * (pins - 1) + 2 y2 = 5.2 y1 = y2 - 9.7 y3 = y1 + 1.2 y4 = 4.3 y5 = y4 - 6.4 body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} #draw outline on F.Fab layer kicad_mod.append(PolygoneLine(polygone=[{'x':x1,'y':y2}, {'x':x1,'y':y1}, {'x':x3,'y':y1}, {'x':x3,'y':y3}, {'x':x4,'y':y3}, {'x':x4,'y':y1}, {'x':x2,'y':y1}, {'x':x2,'y':y2}, {'x':x1,'y':y2}], layer='F.Fab',width=configuration['fab_line_width'])) #draw rectangle on F.Fab for shroud walls kicad_mod.append(RectLine(start=[x5,y4],end=[x6,y5],layer='F.Fab',width=configuration['fab_line_width'])) #draw pin1 mark on F.Fab kicad_mod.append(PolygoneLine(polygone=[{'x':x1,'y':-1},{'x':(x1+1),'y':0}],layer='F.Fab',width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=[{'x':x1,'y':1},{'x':(x1+1),'y':0}],layer='F.Fab',width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #draw silk outline off = configuration['silk_fab_offset'] x1 -= off y1 -= off x2 += off y2 += off x3 += off y3 -= off x4 -= off kicad_mod.append(PolygoneLine(polygone=[{'x':x1,'y':y2}, {'x':x1,'y':y1}, {'x':x3,'y':y1}, {'x':x3,'y':y3}, {'x':x4,'y':y3}, {'x':x4,'y':y1}, {'x':x2,'y':y1}, {'x':x2,'y':y2}, {'x':x1,'y':y2}], layer='F.SilkS', width=configuration['silk_line_width'])) #add pin1 mark on silk px = x1 - 0.2 m = 0.3 marker = [{'x': px,'y': 0},{'x': px-2*m,'y': m},{'x': px-2*m,'y': -m},{'x': px,'y': 0}] kicad_mod.append(PolygoneLine(polygone=marker,layer="F.SilkS", width=configuration['silk_line_width'])) #generate tht pads (1.65mm drill with 2.35x3mm oval pads) pad_size = [pitch - pad_to_pad_clearance, drill + 2*pad_copper_y_solder_length] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*pad_copper_y_solder_length: pad_size[0] = drill + 2*pad_copper_y_solder_length shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: shape=Pad.SHAPE_CIRCLE optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray( pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) #generate mounting post post = Pad(at=mh_at, type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=mh_drill, drill=mh_drill, layers=Pad.LAYERS_NPTH) kicad_mod.append(post) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position=2.5) ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pincount, configuration): if pincount in [6, 8]: number_of_rows = 2 pin_per_row = int(pincount / 2) else: number_of_rows = 1 pin_per_row = pincount mpn = part_base.format(n=pincount) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pin_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) conn_width = jwpf_widths[pincount] conn_length = jwpf_lengths[pincount] mount_hole_offset_y = 2.05 if number_of_rows == 1 else 2.45 # Add texts x_mid = (number_of_rows-1) * row_spacing / 2 y_mid = (pin_per_row - 1) * pitch / 2.0 # Connector outline y1 = y_mid - conn_length / 2 y2 = y_mid + conn_length / 2 x1 = -5.4 # measured from 3D model alignment x2 = x1 + conn_width body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} y_ref = -3 if number_of_rows == 1 else -4 pad_size = [pad_drill + 2*pad_copper_x_solder_length, pitch - pad_to_pad_clearance] if number_of_rows > 1: if pad_size[0] - pad_drill > 2*pad_copper_x_solder_length: pad_size[0] = pad_drill + 2*pad_copper_x_solder_length if pad_size[0] - pad_drill < 2*min_annular_ring: pad_size[0] = pad_drill + 2*min_annular_ring if pad_size[1] - pad_drill < 2*min_annular_ring: pad_size[1] = pad_drill + 2*min_annular_ring if pad_size[0] == pad_size[1]: pad_shape = Pad.SHAPE_CIRCLE else: pad_shape = Pad.SHAPE_OVAL optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT # Create pins for i in range(number_of_rows): kicad_mod.append(PadArray( initial=1+i*pin_per_row, start=[i*row_spacing, 0], pincount=pin_per_row, y_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=pad_drill, layers=Pad.LAYERS_THT, **optional_pad_params)) # Add mounting hole mx = -mount_hole_offset_x my = (pin_per_row - 1) * pitch + mount_hole_offset_y kicad_mod.append(Pad(at=[mx, my], size=mount_hole_size, drill=mount_hole_size, shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_NPTH, layers=Pad.LAYERS_NPTH)) # Tab dimensions tw = 7 tt = 0.5 ########################### CrtYd ################################# cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) def draw_outline(offset=0, layer='F.Fab', width=configuration['fab_line_width']): O = offset R = 1.0 if pincount == 2: poly = [ {'x': x2 + O - R, 'y': y1 - O}, {'x': x1 - O, 'y': y1 - O}, {'x': x1 - O, 'y': y2 + O}, {'x': x2 + O - R, 'y': y2 + O}, ] kicad_mod.append(PolygoneLine(polygone=poly, layer=layer, width=width)) else: # top line kicad_mod.append(Line(start=[tt+x1-O+R, y1-O], end=[x2+O-R, y1-O], layer=layer, width=width)) # bottom line kicad_mod.append(Line(start=[tt+x1-O+R, y2+O], end=[x2+O-R, y2+O], layer=layer, width=width)) # left line (including tab) poly = [ {'x': tt+x1-O, 'y': y1-O+R}, {'x': tt+x1-O, 'y': y_mid - tw/2.0 - O}, {'x': x1-O, 'y': y_mid - tw/2.0 - O}, {'x': x1-O, 'y': y_mid + tw/2.0 + O}, {'x': tt+x1-O, 'y': y_mid + tw/2.0 + O}, {'x': tt+x1-O, 'y': y2+O-R} ] kicad_mod.append(PolygoneLine(polygone=poly, width=width, layer=layer)) # top left kicad_mod.append(Arc(center=[tt+x1-O+R, y1-O+R], start=[tt+x1-O, y1-O+R], angle=90.0, layer=layer, width=width)) # bottom left kicad_mod.append(Arc(center=[tt+x1-O+R, y2+O-R], start=[tt+x1-O+R, y2+O], angle=90.0, layer=layer, width=width)) # right line kicad_mod.append(Line(start=[x2+O, y1-O+R], end=[x2+O, y2+O-R], layer=layer, width=width)) # top right kicad_mod.append(Arc(center=[x2+O-R, y1-O+R], start=[x2+O-R, y1-O], angle=90.0, layer=layer, width=width)) # bottom right kicad_mod.append(Arc(center=[x2+O-R, y2+O-R], start=[x2+O, y2+O-R], angle=90.0, layer=layer, width=width)) draw_outline() draw_outline(offset=configuration['silk_fab_offset'], layer='F.SilkS', width=configuration['silk_line_width']) # Add pin-1 marker on F.SilkS Q = 0.35 # offset L = 1.5 p1 = [ {'x': x1 - Q, 'y': y1 - Q + L}, {'x': x1 - Q, 'y': y1 - Q}, {'x': x1 - Q + L, 'y': y1 - Q}, ] kicad_mod.append(PolygoneLine(polygone=p1, layer='F.SilkS', width=configuration['silk_line_width'])) # Add pin-1 marker on F.Fab D = -0.5 - pad_size[1] / 2 M = 0.75 p1 = [ {'x': -M/2, 'y': D - M}, {'x': M/2, 'y': D - M}, {'x': 0, 'y': D}, {'x': -M/2, 'y': D - M}, ] kicad_mod.append(PolygoneLine(polygone=p1, layer='F.Fab', width=configuration['fab_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='left') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins, configuration): mpn = part_code.format(n=pins) off = configuration['silk_fab_offset'] pad_silk_off = configuration['silk_line_width']/2 + configuration['silk_pad_clearance'] pad_silk_off = configuration['silk_line_width']/2 + configuration['silk_pad_clearance'] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "", pitch=pitch, orientation=orientation_str) footprint_name = footprint_name.replace("__",'_') kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #vertical center of connector y2 = 3.25 + mount_size / 2 y1 = y2 - 7.05 yt = y2 - 8 #Major dimensions B = ( pins - 1 ) * pitch A = B + 4.7 #calculate major dimensions x1 = (B - A) / 2 x2 = x1 + A body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() bounding_box['top'] = yt #pins optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append( PadArray( pincount=pins, initial = 1, start = [0, 0], x_spacing = pitch, type = Pad.TYPE_THT, layers = Pad.LAYERS_THT, shape = pad_shape, size = pad_size, drill = drill, **optional_pad_params ) ) #mounting hole if pins > 1: kicad_mod.append(Pad(at=[-1.5,3.25],type=Pad.TYPE_NPTH,layers=Pad.LAYERS_NPTH,shape=Pad.SHAPE_CIRCLE,size=mount_size,drill=mount_size)) #connector outline #tab thickness t = 1.2 def outline(offset=0): outline = [ {'x': B/2, 'y': y2 + offset}, {'x': x1 - offset, 'y': y2 + offset}, {'x': x1 - offset, 'y': yt - offset}, {'x': x1 + t + offset, 'y': yt - offset}, {'x': x1 + t + offset, 'y': y1 - offset}, {'x': B/2, 'y': y1 - offset}, ] return outline kicad_mod.append(PolygoneLine(polygone=outline(),layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=outline(),x_mirror=B/2, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=outline(offset=off), layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=outline(offset=off),x_mirror=B/2, layer='F.SilkS', width=configuration['silk_line_width'])) #draw lines between pads on F.Fab for i in range(pins - 1): x = (i + 0.5) * pitch kicad_mod.append(Line(start=[x,y1], end=[x,y2], layer='F.Fab', width=configuration['fab_line_width'])) #pin-1 indicator kicad_mod.append(Circle(center=[0,-3.75], radius=0.25, layer='F.SilkS', width=configuration['silk_line_width'])) sl=2 pin = [ {'y': body_edge['top'], 'x': -sl/2}, {'y': body_edge['top'] + sl/sqrt(2), 'x': 0}, {'y': body_edge['top'], 'x': sl/2} ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position=-3.75) ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generateFootprint(self, device_params): fab_line_width = self.configuration.get('fab_line_width', 0.1) silk_line_width = self.configuration.get('silk_line_width', 0.12) lib_name = self.configuration['lib_name_format_string'].format(category=category) if 'body_size_x' in device_params: size_x = device_params['body_size_x'] else: size_x = (device_params['body_size_x_max'] + device_params['body_size_x_min'])/2 if 'body_size_y' in device_params: size_y = device_params['body_size_y'] else: size_y = (device_params['body_size_y_max'] + device_params['body_size_y_min'])/2 pincount = device_params['num_pins_x']*2 + device_params['num_pins_y']*2 ipc_reference = 'ipc_spec_j_lead' ipc_data_set = self.ipc_defintions[ipc_reference][ipc_density] ipc_round_base = self.ipc_defintions[ipc_reference]['round_base'] pad_details = self.calcPadDetails(device_params, ipc_data_set, ipc_round_base) suffix = device_params.get('suffix', '').format(pad_x=pad_details['left']['size'][0], pad_y=pad_details['left']['size'][1]) suffix_3d = suffix if device_params.get('include_suffix_in_3dpath', 'True') == 'True' else "" model3d_path_prefix = self.configuration.get('3d_model_prefix','${KISYS3DMOD}') name_format = self.configuration['fp_name_format_string'] fp_name = name_format.format( man=device_params.get('manufacturer',''), mpn=device_params.get('part_number',''), pkg=device_params['device_type'], pincount=pincount, size_y=size_y, size_x=size_x, pitch=device_params['pitch'], suffix=suffix ).replace('__','_').lstrip('_') fp_name_2 = name_format.format( man=device_params.get('manufacturer',''), mpn=device_params.get('part_number',''), pkg=device_params['device_type'], pincount=pincount, size_y=size_y, size_x=size_x, pitch=device_params['pitch'], suffix=suffix_3d ).replace('__','_').lstrip('_') model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'\ .format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=fp_name_2) #print(fp_name) #print(pad_details) kicad_mod = Footprint(fp_name) # init kicad footprint kicad_mod.setDescription( "{manufacturer} {mpn} {package}, {pincount} Pin ({datasheet}), generated with kicad-footprint-generator {scriptname}"\ .format( manufacturer = device_params.get('manufacturer',''), package = device_params['device_type'], mpn = device_params.get('part_number',''), pincount = pincount, datasheet = device_params['size_source'], scriptname = os.path.basename(__file__).replace(" ", " ") ).lstrip()) kicad_mod.setTags(self.configuration['keyword_fp_string']\ .format( man=device_params.get('manufacturer',''), package=device_params['device_type'], category=category ).lstrip()) 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'] init = 1 kicad_mod.append(PadArray( initial= init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=int(math.ceil(device_params['num_pins_x']/2)), x_spacing=-device_params['pitch'], y_spacing=0, **pad_details['first'], **pad_shape_details)) init += int(math.ceil(device_params['num_pins_x']/2)) kicad_mod.append(PadArray( initial= init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_y'], x_spacing=0, y_spacing=device_params['pitch'], **pad_details['left'], **pad_shape_details)) init += device_params['num_pins_y'] kicad_mod.append(PadArray( initial= init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_x'], y_spacing=0, x_spacing=device_params['pitch'], **pad_details['bottom'], **pad_shape_details)) init += device_params['num_pins_x'] kicad_mod.append(PadArray( initial= init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_y'], x_spacing=0, y_spacing=-device_params['pitch'], **pad_details['right'], **pad_shape_details)) init += device_params['num_pins_y'] kicad_mod.append(PadArray( initial= init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=int(math.floor(device_params['num_pins_x']/2)), y_spacing=0, x_spacing=-device_params['pitch'], **pad_details['top'], **pad_shape_details)) body_edge = { 'left': -size_x/2, 'right': size_x/2, 'top': -size_y/2, 'bottom': size_y/2 } bounding_box = { 'left': pad_details['left']['center'][0] - pad_details['left']['size'][0]/2, 'right': pad_details['right']['center'][0] + pad_details['right']['size'][0]/2, 'top': pad_details['top']['start'][1] - pad_details['top']['size'][1]/2, 'bottom': pad_details['bottom']['center'][1] + pad_details['bottom']['size'][1]/2 } pad_width = pad_details['top']['size'][0] p1_x = pad_details['first']['start'][0] # ############################ SilkS ################################## silk_pad_offset = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 silk_offset = configuration['silk_fab_offset'] sx1 = -(device_params['pitch']*(device_params['num_pins_x']-1)/2.0 + pad_width/2.0 + silk_pad_offset) sy1 = -(device_params['pitch']*(device_params['num_pins_y']-1)/2.0 + pad_width/2.0 + silk_pad_offset) poly_silk = [ {'x': sx1, 'y': body_edge['top']-silk_offset}, {'x': body_edge['left']-silk_offset, 'y': body_edge['top']-silk_offset}, {'x': body_edge['left']-silk_offset, 'y': sy1} ] kicad_mod.append(PolygoneLine( polygone=poly_silk, width=configuration['silk_line_width'], layer="F.SilkS", x_mirror=0)) kicad_mod.append(PolygoneLine( polygone=poly_silk, width=configuration['silk_line_width'], layer="F.SilkS", y_mirror=0)) kicad_mod.append(PolygoneLine( polygone=poly_silk, width=configuration['silk_line_width'], layer="F.SilkS", x_mirror=0, y_mirror=0)) silk_off_45 = silk_offset/sqrt(2) poly_silk_tl = [ {'x': sx1, 'y': body_edge['top']-silk_offset}, {'x': body_edge['left']+device_params['body_chamfer']-silk_off_45, 'y': body_edge['top']-silk_offset}, {'x': body_edge['left']-silk_offset, 'y': body_edge['top']+device_params['body_chamfer']-silk_off_45}, {'x': body_edge['left']-silk_offset, 'y': sy1} ] kicad_mod.append(PolygoneLine( polygone=poly_silk_tl, width=configuration['silk_line_width'], layer="F.SilkS")) # # ######################## Fabrication Layer ########################### fab_bevel_size = min(configuration['fab_bevel_size_absolute'], configuration['fab_bevel_size_relative']*min(size_x, size_y)) fab_bevel_y = fab_bevel_size/sqrt(2) poly_fab = [ {'x': p1_x, 'y': body_edge['top']+fab_bevel_y}, {'x': p1_x+fab_bevel_size/2, 'y': body_edge['top']}, {'x': body_edge['right'], 'y': body_edge['top']}, {'x': body_edge['right'], 'y': body_edge['bottom']}, {'x': body_edge['left'], 'y': body_edge['bottom']}, {'x': body_edge['left'], 'y': body_edge['top']+device_params['body_chamfer']}, {'x': body_edge['left']+device_params['body_chamfer'], 'y': body_edge['top']}, {'x': p1_x-fab_bevel_size/2, 'y': body_edge['top']}, {'x': p1_x, 'y': body_edge['top']+fab_bevel_y} ] kicad_mod.append(PolygoneLine( polygone=poly_fab, width=configuration['fab_line_width'], layer="F.Fab")) # # ############################ CrtYd ################################## off = ipc_data_set['courtyard'] grid = configuration['courtyard_grid'] off_45 = off*math.tan(math.radians(45.0/2)) cy1=roundToBase(bounding_box['top']-off, grid) cy2=roundToBase(body_edge['top']-off, grid) cy3=-roundToBase( device_params['pitch']*(device_params['num_pins_y']-1)/2.0 + pad_width/2.0 + off, grid) cy4=roundToBase(body_edge['top']+device_params['body_chamfer']-off_45, grid) cx1=-roundToBase( device_params['pitch']*(device_params['num_pins_x']-1)/2.0 + pad_width/2.0 + off, grid) cx2=roundToBase(body_edge['left']-off, grid) cx3=roundToBase(bounding_box['left']-off, grid) cx4=roundToBase(body_edge['left']+device_params['body_chamfer']-off_45, grid) crty_poly_tl = [ {'x':0, 'y':cy1}, {'x':cx1, 'y':cy1}, {'x':cx1, 'y':cy2}, {'x':cx2, 'y':cy2}, {'x':cx2, 'y':cy3}, {'x':cx3, 'y':cy3}, {'x':cx3, 'y':0} ] kicad_mod.append(PolygoneLine(polygone=crty_poly_tl, layer='F.CrtYd', width=configuration['courtyard_line_width'], x_mirror=0)) kicad_mod.append(PolygoneLine(polygone=crty_poly_tl, layer='F.CrtYd', width=configuration['courtyard_line_width'], y_mirror=0)) kicad_mod.append(PolygoneLine(polygone=crty_poly_tl, layer='F.CrtYd', width=configuration['courtyard_line_width'], x_mirror=0, y_mirror=0)) crty_poly_tl_ch = [ {'x':0, 'y':cy1}, {'x':cx1, 'y':cy1}, {'x':cx1, 'y':cy2}, {'x':cx4, 'y':cy2}, {'x':cx2, 'y':cy4}, {'x':cx2, 'y':cy3}, {'x':cx3, 'y':cy3}, {'x':cx3, 'y':0} ] kicad_mod.append(PolygoneLine(polygone=crty_poly_tl_ch, layer='F.CrtYd', width=configuration['courtyard_line_width'])) # ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top': cy1, 'bottom': -cy1}, fp_name=fp_name, text_y_inside_position='center') ##################### Output and 3d model ############################ kicad_mod.append(Model(filename=model_name)) 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=fp_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins, params, configuration): pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 mpn = part_code.format(n=pins*number_of_rows) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) footprint_name += params['fp_name_suffix'] kicad_mod = Footprint(footprint_name) desc_format_str = "Molex {:s}, {:s}{:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription(desc_format_str.format(series_long, mpn, params['description'], pins, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) # Dimensions P = (pins - 1) * pitch B = pins * pitch + 0.90 # connector length W = 21.00 # connector width tab_side_w = 1.46 yt1 = 0 - (B - P) / 2 # left yt2 = yt1 - tab_side_w yb1 = P + (B - P) / 2 # right yb2 = yb1 + tab_side_w xr1 = ret_dx + 13.56 # bottom xl1 = xr1 - W # top xl2 = xl1 - 7.6 body_edge={ 'left':xl1, 'right':xr1, 'bottom':yb1, 'top': yt1 } bounding_box = { 'top': -(ret_dy + ret_size/2), 'bottom': P + (ret_dy + ret_size/2), 'left': -pad_size[0]/2, 'right': body_edge['right'] } ################################## Pins ################################## for row_idx in range(2): kicad_mod.append(PadArray(pincount=pins, start=[row_idx*offset_second_pad, 0], y_spacing=pitch, size=pad_size, drill=drill, shape=Pad.SHAPE_RECT, type=Pad.TYPE_THT, layers=Pad.LAYERS_THT, tht_pad1_shape=Pad.SHAPE_RECT)) d_small = 0.3 s_small = d_small + 2*min_annular_ring thermal_to_pad_edge = s_small/2 + 0.15 if params['thermals']: for yi in range(pins): n = yi + 1 pad_center_x = offset_second_pad/2 pad_center_y = yi*pitch pad_l = offset_second_pad + pad_size[0] dy = (pad_size[1] - 2*thermal_to_pad_edge)/2 dx = (pad_l - 2*thermal_to_pad_edge)/4 #draw rectangle on F.Fab layer # kicad_mod.append(RectLine( # start=[pad_center_x - pad_l/2, pad_center_y - pad_size[1]/2], # end=[pad_center_x + pad_l/2, pad_center_y + pad_size[1]/2], # layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PadArray(center=[pad_center_x, pad_center_y], pincount=3, x_spacing=dx*2, drill=d_small, size=s_small, initial=n, increment=0, shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_THT, layers=Pad.LAYERS_THT)) kicad_mod.append(PadArray(center=[pad_center_x, pad_center_y - dy], pincount=5, x_spacing=dx, drill=d_small, size=s_small, initial=n, increment=0, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_THT)) kicad_mod.append(PadArray(center=[pad_center_x, pad_center_y + dy], pincount=5, x_spacing=dx, drill=d_small, size=s_small, initial=n, increment=0, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_THT)) kicad_mod.append(Pad(at=[ret_dx, -ret_dy], type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, size=ret_size, drill=ret_drill, layers=Pad.LAYERS_THT)) kicad_mod.append(Pad(at=[ret_dx, P+ret_dy], type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, size=ret_size, drill=ret_drill, layers=Pad.LAYERS_THT)) kicad_mod.append(RectLine(start=[-pad_size[0]/2, -pad_size[1]/2], end=[offset_second_pad + pad_size[0]/2,pad_size[1]/2],offset=pad_silk_off, width=configuration['silk_line_width'], layer='B.SilkS')) ############################ Outline ############################## #kicad_mod.append(RectLine(start=[xl1, yt1], end=[xr1, yb1], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(RectLine(start=[xl1, yt2], end=[xr1, yb2], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[xl1, yt1], end=[xr1, yt1], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[xl1, yb1], end=[xr1, yb1], layer='F.Fab', width=configuration['fab_line_width'])) off = configuration['silk_fab_offset'] silk1 = [ {'y': -pad_size[1]/2 - pad_silk_off, 'x': xl1-off}, {'y': yt2-off, 'x': xl1-off}, {'y': yt2-off, 'x': ret_dx-ret_size/2}, ] kicad_mod.append(PolygoneLine(polygone=silk1, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=silk1, layer='F.SilkS', width=configuration['silk_line_width'], y_mirror=P/2)) silk2 = [ {'y': yt2-off, 'x': ret_dx+ret_size/2}, {'y': yt2-off, 'x': xr1+off}, {'y': P/2, 'x': xr1+off}, ] kicad_mod.append(PolygoneLine(polygone=silk2, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=silk2, layer='F.SilkS', width=configuration['silk_line_width'], y_mirror=P/2)) for i in range(pins - 1): kicad_mod.append(Line(start=[xl1-off, i*pitch+pad_size[1]/2+pad_silk_off], end=[xl1-off, (i+1)*pitch-pad_size[1]/2-pad_silk_off], layer='F.SilkS', width=configuration['silk_line_width'])) for i in range(pins): w_pin = 3.8 kicad_mod.append(RectLine(start=[xl1, i*pitch-w_pin/2], end=[xl2, i*pitch+w_pin/2], layer='F.Fab', width=configuration['fab_line_width'])) ############################ Pin 1 ################################ # Pin 1 designator pin1_sl = 2.4 pin1 = [ {'x': body_edge['left'], 'y': -pin1_sl/2}, {'x': body_edge['left'] - pin1_sl/sqrt(2), 'y': 0}, {'x': body_edge['left'], 'y': pin1_sl/2} ] kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.Fab', width=configuration['fab_line_width'], x_mirror=(body_edge['left']+xl2)/2)) pin1 = [ {'y': -pad_size[1]/2 - pad_silk_off, 'x': xl1-off}, {'y': -pad_size[1]/2 - pad_silk_off, 'x': -pad_size[0]/2} ] kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.SilkS', width=configuration['silk_line_width'])) # pin1 = [ # {'x': 0, 'y': 8}, # {'x': 0.5, 'y': 9}, # {'x': -0.5, 'y': 9}, # {'x': 0, 'y': 8}, # ] # kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.SilkS', width=configuration['silk_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins_per_row, variant, configuration): peg = variant_params[variant]['mount_pins'] == 'plastic_peg' silk_pad_off = configuration['silk_pad_clearance']+configuration['silk_line_width']/2 mpn = variant_params[variant]['part_code']['mpn'].format(n=pins_per_row*2) old_mpn = variant_params[variant]['part_code']['eng_num'].format(n=pins_per_row*2) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=old_mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) descr_format_str = "Molex {:s}, old mpn/engineering number: {:s}, example for new mpn: {:s}, {:d} Pins per row, Mounting: {:s} ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription(descr_format_str.format( series_long, old_mpn, mpn, pins_per_row, variant_params[variant]['descriptive_name'], variant_params[variant]['datasheet'])) tags = configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation]) tags += variant_params[variant]['mount_pins'] kicad_mod.setTags(tags) #calculate fp dimensions #connector length A = pins_per_row * pitch + 1.2 #pin centers B = (pins_per_row - 1) * pitch #plasic pin-lock C = A + 4 #connector width W = 9.6 #corner positions x1 = -(A-B)/2 x2 = x1 + A y2 = row + 1.85 y1 = y2 - W #tab length tab_l = 3.4 #tab width tab_w = 1.4 body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() bounding_box['bottom'] = body_edge['bottom'] + tab_w off = configuration['silk_fab_offset'] #generate the pads optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for row_idx in range(2): kicad_mod.append(PadArray( pincount=pins_per_row, initial=row_idx*pins_per_row+1, start=[0, row_idx*row], x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) #add PCB locators if needed pad_silk_offset = configuration['silk_pad_clearance']+configuration['silk_line_width']/2 if peg: loc = 3.00 mounting_pin_y = row - 0.46 lx1 = B/2-C/2 lx2 = B/2+C/2 kicad_mod.append(Pad(at=[lx1, mounting_pin_y],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=loc,drill=loc, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(at=[lx2, mounting_pin_y],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=loc,drill=loc, layers=Pad.LAYERS_NPTH)) bounding_box['left'] = lx1-loc/2 bounding_box['right'] = lx2+loc/2 ######################## Fab ############################ mount_pin_radius = loc/2 kicad_mod.append(Arc(center=[lx1,mounting_pin_y], start=[lx1,mounting_pin_y+mount_pin_radius], angle=180, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[lx1,mounting_pin_y-mount_pin_radius], end=[x1,mounting_pin_y-mount_pin_radius], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[lx1,mounting_pin_y+mount_pin_radius], end=[x1,mounting_pin_y+mount_pin_radius], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Arc(center=[lx2,mounting_pin_y], start=[lx2,mounting_pin_y-mount_pin_radius], angle=180, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[lx2,mounting_pin_y-mount_pin_radius], end=[x2,mounting_pin_y-mount_pin_radius], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[lx2,mounting_pin_y+mount_pin_radius], end=[x2,mounting_pin_y+mount_pin_radius], layer='F.Fab', width=configuration['fab_line_width'])) ######################## Silk ############################ mount_pin_radius = loc/2 + silk_pad_off kicad_mod.append(Arc(center=[lx1,mounting_pin_y], start=[lx1,mounting_pin_y+mount_pin_radius], angle=180, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[lx1,mounting_pin_y-mount_pin_radius], end=[x1-off,mounting_pin_y-mount_pin_radius], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[lx1,mounting_pin_y+mount_pin_radius], end=[x1-off,mounting_pin_y+mount_pin_radius], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Arc(center=[lx2,mounting_pin_y], start=[lx2,mounting_pin_y-mount_pin_radius], angle=180, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[lx2,mounting_pin_y-mount_pin_radius], end=[x2+off,mounting_pin_y-mount_pin_radius], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[lx2,mounting_pin_y+mount_pin_radius], end=[x2+off,mounting_pin_y+mount_pin_radius], layer='F.SilkS', width=configuration['silk_line_width'])) #draw the outline of the shape kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2],layer='F.Fab',width=configuration['fab_line_width'])) #draw the outline of the tab kicad_mod.append(PolygoneLine(polygone=[ {'x': B/2 - tab_l/2,'y': y2}, {'x': B/2 - tab_l/2,'y': y2 + tab_w}, {'x': B/2 + tab_l/2,'y': y2 + tab_w}, {'x': B/2 + tab_l/2,'y': y2}, ], layer='F.Fab', width=configuration['fab_line_width'])) #draw the outline of each pin slot (alternating shapes) #slot size S = 3.3 def square_slot(x,y): kicad_mod.append(RectLine(start=[x-S/2,y-S/2], end=[x+S/2,y+S/2], layer='F.Fab', width=configuration['fab_line_width'])) def notch_slot(x,y): kicad_mod.append(PolygoneLine(polygone=[ {'x': x-S/2, 'y': y+S/2}, {'x': x-S/2, 'y': y-S/4}, {'x': x-S/4, 'y': y-S/2}, {'x': x+S/4, 'y': y-S/2}, {'x': x+S/2, 'y': y-S/4}, {'x': x+S/2, 'y': y+S/2}, {'x': x-S/2, 'y': y+S/2}, ], layer='F.Fab', width=configuration['fab_line_width'])) q = 1 notch = True for i in range(pins_per_row): if notch: y_square = row/2 - 4.2/2 y_notch = row/2 + 4.2/2 else: y_square = row/2 + 4.2/2 y_notch = row/2 - 4.2/2 square_slot(i * pitch, y_square) notch_slot(i*pitch, y_notch) q -= 1 if (q == 0): q = 2 notch = not notch #draw the outline of the connector on the silkscreen outline = [ {'x': B/2,'y': y1-off}, {'x': x1-off,'y': y1-off}, {'x': x1-off,'y': y2+off}, {'x': B/2 - tab_l/2 - off,'y': y2+off}, {'x': B/2 - tab_l/2 - off,'y': y2 + off + tab_w}, {'x': B/2, 'y': y2 + off + tab_w}, ] kicad_mod.append(PolygoneLine(polygone=outline, layer="F.SilkS", width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=outline, x_mirror=B/2, layer="F.SilkS", width=configuration['silk_line_width'])) #pin-1 marker L = 2.5 O = 0.35 pin = [ {'x': x1 + L,'y': y1 - O}, {'x': x1 - O,'y': y1 - O}, {'x': x1 - O,'y': y1 + L}, ] kicad_mod.append(PolygoneLine(polygone=pin, layer="F.SilkS", width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# CrtYd_offset = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] cx1 = roundToBase(bounding_box['left'] - CrtYd_offset, CrtYd_grid) cy1 = roundToBase(bounding_box['top'] - CrtYd_offset, CrtYd_grid) cx2 = roundToBase(bounding_box['right'] + CrtYd_offset, CrtYd_grid) cy2 = roundToBase(bounding_box['bottom'] + CrtYd_offset, CrtYd_grid) if peg: cx3 = roundToBase(body_edge['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx4 = roundToBase(body_edge['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) mount_pin_radius = loc/2 cy3=roundToBase(mounting_pin_y - mount_pin_radius - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) poly_crtyd = [ {'x': cx3, 'y': cy1}, {'x': cx3, 'y': cy3}, {'x': cx1, 'y': cy3}, {'x': cx1, 'y': cy2}, {'x': cx2, 'y': cy2}, {'x': cx2, 'y': cy3}, {'x': cx4, 'y': cy3}, {'x': cx4, 'y': cy1}, {'x': cx3, 'y': cy1} ] kicad_mod.append(PolygoneLine(polygone=poly_crtyd, layer='F.CrtYd', width=configuration['courtyard_line_width'])) else: kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins, configuration): mpn = part_code.format(n=pins * 2) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format( man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription( "Molex {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator" .format(series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format( series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) A = (pins - 1) * pitch B = A + 1.8 C = A + 3 #connector width W = 3.2 #side thickness T = 0.4 #corner positions x1 = (A - C) / 2 x2 = x1 + C y2 = 1.15 y1 = y2 - W off = configuration['silk_fab_offset'] pad_silk_off = configuration[ 'silk_pad_clearance'] + configuration['silk_line_width'] / 2 body_edge = {'left': x1, 'right': x2, 'bottom': y2, 'top': y1} bounding_box = body_edge.copy() # generate the pads kicad_mod.append( PadArray(start=[0, 0], pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT)) # outline on Fab kicad_mod.append( RectLine(start=[x1, y1], end=[x2, y2], layer='F.Fab', width=configuration['fab_line_width'])) # outline on SilkScreen kicad_mod.append( RectLine(start=[x1, y1], end=[x2, y2], offset=off, layer='F.SilkS', width=configuration['silk_line_width'])) inline = [ { 'x': A / 2, 'y': y2 - T }, { 'x': x1 + T, 'y': y2 - T }, { 'x': x1 + T, 'y': 0 }, { 'x': x1 + T / 2, 'y': 0 }, { 'x': x1 + T / 2, 'y': -2 * T }, { 'x': x1 + T, 'y': -2 * T }, { 'x': x1 + T, 'y': y1 + T }, { 'x': A / 2, 'y': y1 + T }, ] kicad_mod.append( PolygoneLine(polygone=inline, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=inline, x_mirror=A / 2, layer='F.SilkS', width=configuration['silk_line_width'])) #pin-1 mark L = 1 kicad_mod.append( Line(start=[x1 - 0.4, y2 + 0.4], end=[x1 - 0.4, y2 + 0.4 - L], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( Line(start=[x1 - 0.4, y2 + 0.4], end=[x1 - 0.4 + L, y2 + 0.4], layer='F.SilkS', width=configuration['silk_line_width'])) sl = 1 pin = [{ 'y': body_edge['bottom'], 'x': -sl / 2 }, { 'y': body_edge['bottom'] - sl / sqrt(2), 'x': 0 }, { 'y': body_edge['bottom'], 'x': sl / 2 }] kicad_mod.append( PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# cx1 = roundToBase( bounding_box['left'] - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase( bounding_box['top'] - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase( bounding_box['right'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase( bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append( RectLine(start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={ 'top': cy1, 'bottom': cy2 }, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pincount, configuration): mpn = eng_mpn.format(n=pincount) new_mpn = new_mpn_example.format(n=pincount) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format( man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount, pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) descr_format_str = "Molex {:s}, old/engineering part number: {:s} example for new part number: {:s}, {:d} Pins ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription( descr_format_str.format(series_long, mpn, new_mpn, pincount, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format( series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) # calculate working values end_pos_x = (pincount - 1) * pitch centre_x = (end_pos_x - start_pos_x) / 2.0 nudge = configuration['silk_fab_offset'] silk_w = configuration['silk_line_width'] fab_w = configuration['fab_line_width'] body_edge = { 'left': start_pos_x - pitch / 2, 'right': end_pos_x + pitch / 2, 'bottom': 1.88 + 1 } body_edge['top'] = body_edge['bottom'] - 5.8 # create pads # kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, # at=[0, 0], size=pad_size, # drill=drill, layers=Pad.LAYERS_THT)) kicad_mod.append( PadArray(initial=1, start=[start_pos_x, 0], x_spacing=pitch, pincount=pincount, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT)) # create fab outline kicad_mod.append(RectLine(start=[body_edge['left'], body_edge['top']],\ end=[body_edge['right'], body_edge['bottom']], layer='F.Fab', width=fab_w)) # create silkscreen kicad_mod.append(RectLine(start=[body_edge['left']-nudge, body_edge['top']-nudge],\ end=[body_edge['right']+nudge, body_edge['bottom']+nudge], layer='F.SilkS', width=silk_w)) # pin 1 markers kicad_mod.append(Line(start=[body_edge['left']-0.4, -2.0],\ end=[body_edge['left']-0.4, 2.0], layer='F.SilkS', width=silk_w)) sl = 1 poly_pin1_marker = [{ 'x': body_edge['left'], 'y': -sl / 2 }, { 'x': body_edge['left'] + sl / sqrt(2), 'y': 0 }, { 'x': body_edge['left'], 'y': sl / 2 }] kicad_mod.append( PolygoneLine(polygone=poly_pin1_marker, layer='F.Fab', width=fab_w)) yr1 = body_edge['bottom'] + nudge yr2 = yr1 - 1 yr3 = yr2 - 0.53 if pincount <= 6: # one ramp kicad_mod.append(PolygoneLine(polygone=[[start_pos_x, yr1], [start_pos_x, yr2],\ [end_pos_x, yr2], [end_pos_x, yr1]], layer='F.SilkS', width=silk_w)) kicad_mod.append(PolygoneLine(polygone=[[start_pos_x, yr2], [start_pos_x+0.25, yr3],\ [end_pos_x-0.25, yr3], [end_pos_x, yr2] ],layer='F.SilkS', width=silk_w)) kicad_mod.append(PolygoneLine(polygone=[[start_pos_x+0.25, yr1],\ [start_pos_x+0.25, yr2]], layer='F.SilkS', width=silk_w)) kicad_mod.append(PolygoneLine(polygone=[[end_pos_x-0.25, yr1],\ [end_pos_x-0.25, yr2]], layer='F.SilkS', width=silk_w)) else: # two ramps poly1 = [{ 'x': start_pos_x, 'y': yr1 }, { 'x': start_pos_x, 'y': yr2 }, { 'x': start_pos_x + 2 * pitch, 'y': yr2 }, { 'x': start_pos_x + 2 * pitch, 'y': yr1 }] poly2 = [{ 'x': start_pos_x, 'y': yr2 }, { 'x': start_pos_x + 0.25, 'y': yr3 }, { 'x': start_pos_x + 2 * pitch, 'y': yr3 }, { 'x': start_pos_x + 2 * pitch, 'y': yr2 }] poly3 = [{ 'x': start_pos_x + 0.25, 'y': yr1 }, { 'x': start_pos_x + 0.25, 'y': yr2 }] kicad_mod.append( PolygoneLine(polygone=poly1, layer='F.SilkS', width=silk_w)) kicad_mod.append( PolygoneLine(polygone=poly2, layer='F.SilkS', width=silk_w)) kicad_mod.append( PolygoneLine(polygone=poly3, layer='F.SilkS', width=silk_w)) kicad_mod.append( PolygoneLine(polygone=poly1, x_mirror=centre_x, layer='F.SilkS', width=silk_w)) kicad_mod.append( PolygoneLine(polygone=poly2, x_mirror=centre_x, layer='F.SilkS', width=silk_w)) kicad_mod.append( PolygoneLine(polygone=poly3, x_mirror=centre_x, layer='F.SilkS', width=silk_w)) for i in range(0, pincount): middle_x = start_pos_x + i * pitch start_x = middle_x - 1.6 / 2 end_x = middle_x + 1.6 / 2 y1 = body_edge['top'] - nudge y2 = y1 + 0.6 kicad_mod.append(PolygoneLine(polygone=[[start_x, y1], [start_x, y2],\ [end_x, y2], [end_x, y1]], layer='F.SilkS', width=silk_w)) ########################### CrtYd ################################# cx1 = roundToBase( body_edge['left'] - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase( body_edge['top'] - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase( body_edge['right'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase( body_edge['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append( RectLine(start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={ 'top': cy1, 'bottom': cy2 }, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins, configuration): #calculate fp dimensions A = (pins - 1) * pitch B = A + 5.2 #generate the name mpn = part_base.format(n=number_of_rows * pins) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format( man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad="", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription( "JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator" .format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format( series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) pad_size = [pitch - pad_to_pad_clearance, row_pitch - pad_to_pad_clearance] if pad_size[0] - drill < 2 * min_annular_ring: pad_size[0] = drill + 2 * min_annular_ring if pad_size[1] - drill > 2 * pad_copper_y_solder_length: pad_size[1] = drill + 2 * pad_copper_y_solder_length if pad_size[1] - drill < 2 * min_annular_ring: pad_size[1] = drill + 2 * min_annular_ring if pad_size[0] == pad_size[1]: pad_shape = Pad.SHAPE_CIRCLE else: pad_shape = Pad.SHAPE_OVAL optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for row_idx in range(2): kicad_mod.append( PadArray(initial=ROW_NAMES[row_idx] + '1', start=[0, -(row_idx) * row_pitch], x_spacing=pitch, pincount=pins, increment=incrementPadNumber, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=pad_shape, layers=Pad.LAYERS_THT, tht_pad1_id=ROW_NAMES[0] + '1', **optional_pad_params)) #draw the component outline x1 = A / 2 - B / 2 x2 = x1 + B y1 = -2.5 - 0.62 y2 = y1 + 17.8 body_edge = {'left': x1, 'right': x2, 'top': y1, 'bottom': y2} #draw the main outline around the footprint kicad_mod.append( RectLine(start=[x1, y1], end=[x2, y2], layer='F.Fab', width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(x1 - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) if y1 < -row_pitch - pad_size[1] / 2: cy1 = roundToBase(y1 - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) else: cy1 = roundToBase( -row_pitch - pad_size[1] / 2 - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2 + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2 + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append( RectLine(start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #offset off off = configuration['silk_fab_offset'] x1 -= off y1 -= off x2 += off y2 += off #outline side = [ { 'x': -1, 'y': y1 }, { 'x': x1, 'y': y1 }, { 'x': x1, 'y': y2 }, { 'x': A / 2, 'y': y2 }, ] kicad_mod.append( PolygoneLine(polygone=side, layer="F.SilkS", width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=side, x_mirror=A / 2, layer="F.SilkS", width=configuration['silk_line_width'])) #add mounting holes if pins == 3: m = Pad(at=[pitch, 7], layers=["*.Cu", "*.Mask"], shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_THT, size=mh_size, drill=mh_drill) kicad_mod.append(m) else: m1 = Pad(at=[0, 7], layers=["*.Cu", '*.Mask'], shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_THT, size=mh_size, drill=mh_drill) m2 = Pad(at=[A, 7], layers=["*.Cu", '*.Mask'], shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_THT, size=mh_size, drill=mh_drill) kicad_mod.append(m1) kicad_mod.append(m2) #add p1 marker px = -3 m = 0.3 marker = [ { 'x': px, 'y': 0 }, { 'x': px - 2 * m, 'y': m }, { 'x': px - 2 * m, 'y': -m }, { 'x': px, 'y': 0 }, ] kicad_mod.append( PolygoneLine(polygone=marker, layer="F.SilkS", width=configuration['silk_line_width'])) sl = 1 marker = [{ 'x': body_edge['left'], 'y': sl / 2 }, { 'x': body_edge['left'] + sl / sqrt(2), 'y': 0 }, { 'x': body_edge['left'], 'y': -sl / 2 }] kicad_mod.append( PolygoneLine(polygone=marker, layer='F.Fab', width=configuration['fab_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={ 'top': cy1, 'bottom': cy2 }, fp_name=footprint_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins, configuration): mpn = part_code.format(n=pins) pad_silk_off = configuration['silk_line_width'] / 2 + configuration[ 'silk_pad_clearance'] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format( man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad="", pitch=pitch, orientation=orientation_str) footprint_name = footprint_name.replace("__", '_') kicad_mod = Footprint(footprint_name) kicad_mod.setDescription( "Molex {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator" .format(series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format( series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) A = (pins - 1) * pitch B = A + 2.9 # create pads #createNumberedPadsTHT(kicad_mod, pincount, pitch, drill, {'x':x_dia, 'y':y_dia}) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append( PadArray(start=[0, 0], pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) x1 = -(B - A) / 2 y1 = -2.2 x2 = x1 + B y2 = 1.2 body_edge = {'left': x1, 'right': x2, 'bottom': y2, 'top': y1} bounding_box = body_edge.copy() kicad_mod.append( RectLine(start={ 'x': x1, 'y': y1 }, end={ 'x': x2, 'y': y2 }, layer='F.Fab', width=configuration['fab_line_width'])) #line offset off = 0.1 x1 -= off y1 -= off x2 += off y2 += off #draw the main outline around the footprint kicad_mod.append( RectLine(start={ 'x': x1, 'y': y1 }, end={ 'x': x2, 'y': y2 }, layer='F.SilkS', width=configuration['silk_line_width'])) #add pin-1 marker p1_off = configuration['silk_fab_offset'] + 0.3 L = 1.5 pin = [{ 'y': body_edge['bottom'] - L, 'x': body_edge['left'] - p1_off }, { 'y': body_edge['bottom'] + p1_off, 'x': body_edge['left'] - p1_off }, { 'y': body_edge['bottom'] + p1_off, 'x': body_edge['left'] + L }] kicad_mod.append( PolygoneLine(polygone=pin, layer='F.SilkS', width=configuration['silk_line_width'])) sl = 1 pin = [{ 'y': body_edge['bottom'], 'x': -sl / 2 }, { 'y': body_edge['bottom'] - sl / sqrt(2), 'x': 0 }, { 'y': body_edge['bottom'], 'x': sl / 2 }] kicad_mod.append( PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) #side-wall thickness S S = 0.3 #bottom line kicad_mod.append( PolygoneLine(polygone=[{ 'x': x1, 'y': 0 }, { 'x': x1 + S, 'y': 0 }, { 'x': x1 + S, 'y': y2 - S }, { 'x': x2 - S, 'y': y2 - S }, { 'x': x2 - S, 'y': 0 }, { 'x': x2, 'y': 0 }], layer='F.SilkS', width=configuration['silk_line_width'])) #left mark #gap g g = 0.75 kicad_mod.append( PolygoneLine(polygone=[{ 'x': x1, 'y': -g }, { 'x': x1 + S, 'y': -g }, { 'x': x1 + S, 'y': y1 + S * 1.5 }, { 'x': x1 + 2 * S, 'y': y1 + S * 1.5 }, { 'x': x1 + 2 * S, 'y': y1 }], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=[{ 'x': x2, 'y': -g }, { 'x': x2 - S, 'y': -g }, { 'x': x2 - S, 'y': y1 + S * 1.5 }, { 'x': x2 - 2 * S, 'y': y1 + S * 1.5 }, { 'x': x2 - 2 * S, 'y': y1 }], layer='F.SilkS', width=configuration['silk_line_width'])) #middle line kicad_mod.append( PolygoneLine(polygone=[{ 'x': x1 + 2 * S, 'y': y1 + 1.5 * S }, { 'x': 0.2 * pitch, 'y': y1 + 1.5 * S }, { 'x': 0.2 * pitch, 'y': y1 + 0.5 * S }, { 'x': 0.8 * pitch, 'y': y1 + 0.5 * S }, { 'x': 0.8 * pitch, 'y': y1 + 1.5 * S }, { 'x': A - 0.8 * pitch, 'y': y1 + 1.5 * S }, { 'x': A - 0.8 * pitch, 'y': y1 + 0.5 * S }, { 'x': A - 0.2 * pitch, 'y': y1 + 0.5 * S }, { 'x': A - 0.2 * pitch, 'y': y1 + 1.5 * S }, { 'x': x2 - 2 * S, 'y': y1 + 1.5 * S }], layer='F.SilkS', width=configuration['silk_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase( bounding_box['left'] - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase( bounding_box['top'] - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase( bounding_box['right'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase( bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append( RectLine(start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={ 'top': cy1, 'bottom': cy2 }, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins_per_row, configuration): mpn = part_code.format(n=pins_per_row * number_of_rows) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format( man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad="", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription( "Molex {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator" .format(series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format( series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) A = (pins_per_row - 1) * pitch B = A + 2 * 1.75 C = A + 2 * 2.45 #connector width W = 4.9 chamfer_pin_n = {'x': 1, 'y': 1} off = configuration['silk_fab_offset'] pad_silk_off = configuration[ 'silk_pad_clearance'] + configuration['silk_line_width'] / 2 body_edge = {} body_edge['left'] = (A - C) / 2 body_edge['right'] = body_edge['left'] + C body_edge['top'] = -3.1 body_edge['bottom'] = body_edge['top'] + W bounding_box = body_edge.copy() # generate the pads kicad_mod.append( PadArray(start=[0, 0], pincount=pins_per_row, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT)) def generateOutline(off=0, grid=0): poly = [ { 'x': body_edge['left'] - off, 'y': body_edge['top'] - off }, { 'x': body_edge['left'] - off, 'y': body_edge['bottom'] + off }, { 'x': body_edge['right'] - chamfer_pin_n['x'] + off, 'y': body_edge['bottom'] + off }, { 'x': body_edge['right'] + off, 'y': body_edge['bottom'] - chamfer_pin_n['y'] + off }, { 'x': body_edge['right'] + off, 'y': body_edge['top'] - off }, { 'x': body_edge['left'] - off, 'y': body_edge['top'] - off }, ] if grid == 0: return poly else: return [{ 'x': roundToBase(p['x'], grid), 'y': roundToBase(p['y'], grid) } for p in poly] # outline on Fab kicad_mod.append( PolygoneLine(polygone=generateOutline(), layer='F.Fab', width=configuration['fab_line_width'])) # outline on SilkScreen kicad_mod.append( PolygoneLine(polygone=generateOutline(off=off), layer='F.SilkS', width=configuration['silk_line_width'])) #pin-1 mark sl = 2 o = off + 0.3 pin = [{ 'y': body_edge['bottom'] - sl, 'x': body_edge['left'] - o }, { 'y': body_edge['bottom'] + o, 'x': body_edge['left'] - o }, { 'y': body_edge['bottom'] + o, 'x': body_edge['left'] + sl }] kicad_mod.append( PolygoneLine(polygone=pin, layer='F.SilkS', width=configuration['silk_line_width'])) sl = 1 pin = [{ 'y': body_edge['bottom'], 'x': -sl / 2 }, { 'y': body_edge['bottom'] - sl / sqrt(2), 'x': 0 }, { 'y': body_edge['bottom'], 'x': sl / 2 }] kicad_mod.append( PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# poly_crtyd = generateOutline( configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = poly_crtyd[0]['y'] cy2 = poly_crtyd[1]['y'] kicad_mod.append( PolygoneLine(polygone=poly_crtyd, layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={ 'top': cy1, 'bottom': cy2 }, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def make_module(pins_per_row, configuration): pad_silk_off = configuration['silk_line_width'] / 2 + configuration[ 'silk_pad_clearance'] off = configuration['silk_fab_offset'] mpn = part_code.format(pins_per_row * 2) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format( man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad="", pitch=pitch, orientation=orientation_str) footprint_name = footprint_name.replace("__", '_') kicad_mod = Footprint(footprint_name) kicad_mod.setDescription( "Molex {:s}, {:s}, {:d} Circuits ({:s}), generated with kicad-footprint-generator" .format(series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format( series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) W = 5.3 Wi = 4.2 body_edge = {} body_edge['left'] = -(W - pitch_row) / 2 body_edge['right'] = body_edge['left'] + W A = (pins_per_row - 1) * pitch B = (A - 8) if A >= 8 else 0 C = (A - 4.6) if A >= 4.6 else 0 D = A + 2.6 E = A + 3.6 body_edge['top'] = -(E - A) / 2 body_edge['bottom'] = body_edge['top'] + E bounding_box = body_edge.copy() ############################## Pins ############################### for i in range(pins_per_row): y = i * pitch kicad_mod.append( Pad(at=[0, y], number='a{:d}'.format(i + 1), type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, size=pad_size, drill=drill, layers=Pad.LAYERS_THT)) kicad_mod.append( Pad(at=[pitch_row, y], number='b{:d}'.format(i + 1), type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, size=pad_size, drill=drill, layers=Pad.LAYERS_THT)) ############################ Outline ############################## kicad_mod.append( RectLine(start=[body_edge['left'], body_edge['top']], end=[body_edge['right'], body_edge['bottom']], layer="F.Fab", width=configuration['fab_line_width'])) kicad_mod.append( RectLine(start=[body_edge['left'], body_edge['top']], end=[body_edge['right'], body_edge['bottom']], layer="F.SilkS", width=configuration['silk_line_width'], offset=off)) # inside CW = 1 xil = body_edge['left'] + (W - Wi) / 2 xir = xil + Wi yit = body_edge['top'] + (E - D) / 2 yt1 = A / 2 - C / 2 yb1 = A / 2 + C / 2 yt2 = A / 2 - B / 2 poly_left_t = [ { 'x': pitch_row - CW / 2, 'y': body_edge['top'] - off }, { 'x': pitch_row - CW / 2, 'y': yit }, { 'x': xil, 'y': yit }, { 'x': xil, 'y': yt1 }, { 'x': body_edge['left'] - off, 'y': yt1 }, ] if C == 0: del poly_left_t[-1] kicad_mod.append( PolygoneLine(polygone=poly_left_t, layer="F.SilkS", width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=poly_left_t, y_mirror=A / 2, layer="F.SilkS", width=configuration['silk_line_width'])) poly_right_t = [ { 'x': pitch_row + CW / 2, 'y': body_edge['top'] - off }, { 'x': pitch_row + CW / 2, 'y': yit }, { 'x': xir, 'y': yit }, { 'x': xir, 'y': yt2 }, { 'x': body_edge['right'] + off, 'y': yt2 }, ] if B == 0: del poly_right_t[-1] else: kicad_mod.append( Line(start={ 'x': body_edge['right'] + off, 'y': yt1 }, end={ 'x': xir, 'y': yt1 }, layer="F.SilkS", width=configuration['silk_line_width'])) kicad_mod.append( Line(start={ 'x': body_edge['right'] + off, 'y': yb1 }, end={ 'x': xir, 'y': yb1 }, layer="F.SilkS", width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=poly_right_t, layer="F.SilkS", width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=poly_right_t, y_mirror=A / 2, layer="F.SilkS", width=configuration['silk_line_width'])) ########################### Pin 1 ################################# p1s_sl = 2 p1s_off = off + 0.3 kicad_mod.append( PolygoneLine(polygone=[{ 'x': body_edge['left'] + p1s_sl, 'y': body_edge['top'] - p1s_off }, { 'x': body_edge['left'] - p1s_off, 'y': body_edge['top'] - p1s_off }, { 'x': body_edge['left'] - p1s_off, 'y': body_edge['top'] + p1s_sl }], layer="F.SilkS", width=configuration['silk_line_width'])) p1f_sl = 1 kicad_mod.append( PolygoneLine(polygone=[{ 'x': body_edge['left'], 'y': p1f_sl / 2 }, { 'x': body_edge['left'] + p1f_sl / sqrt(2), 'y': 0 }, { 'x': body_edge['left'], 'y': -p1f_sl / 2 }], layer="F.Fab", width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase( bounding_box['left'] - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase( bounding_box['top'] - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase( bounding_box['right'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase( bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append( RectLine(start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={ 'top': cy1, 'bottom': cy2 }, fp_name=footprint_name, text_y_inside_position='right') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins_per_row, params, configuration): mpn = part_code.format(n=pins_per_row, shield=params['mpn_option']) CrtYd_off = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] off = configuration['silk_fab_offset'] pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 body_edge = {} bounding_box = {} # handle arguments orientation_str = configuration['orientation_options'][orientation] if params['shield_pad']: footprint_name = configuration['fp_name_format_string_shielded'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, pitch=pitch, orientation=orientation_str, shield_pins=1) else: footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) footprint_name = footprint_name.replace('__','_') kicad_mod = Footprint(footprint_name) kicad_mod.setAttribute('smd') kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) A = (pins_per_row-1)*pitch B = A + 2.5 C = A + 5.45 D = A + 6.75 E = A + 5.2 pad_to_pad_inside = 1.95+0.25 pad_y = (pad_to_pad_inside + pad_size[1])/2 boss_x = B/2 boss_y = -pad_y + pad_size[1]/2 + 0.25 shield_pad_x = C/2 shield_pad_y = boss_y + 2 body_chamfer = 0.3 body_edge['left'] = -D/2 if params['shield_pad'] else -E/2 body_edge['right'] = -body_edge['left'] body_edge['top'] = -4.98/2 body_edge['bottom'] = -body_edge['top'] bounding_box['left'] = (-shield_pad_x - shield_pad_size/2) if params['shield_pad'] else body_edge['left'] bounding_box['right'] = -bounding_box['left'] bounding_box['top'] = -pad_y - pad_size[1]/2 bounding_box['bottom'] = -bounding_box['top'] ################################ Pads ##################################### kicad_mod.append(PadArray(initial=1, increment=2, center=[0, -pad_y], x_spacing=pitch, pincount=pins_per_row, size=pad_size, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_SMT)) kicad_mod.append(PadArray(initial=2, increment=2, center=[0, pad_y], x_spacing=pitch, pincount=pins_per_row, size=pad_size, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_SMT)) kicad_mod.append(Pad(number ='""', type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=[boss_x, boss_y], size=boss_drill, drill=boss_drill, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(number ='""', type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=[-boss_x, boss_y], size=boss_drill, drill=boss_drill, layers=Pad.LAYERS_NPTH)) if params['shield_pad']: kicad_mod.append(Pad(number = pin_number_shield, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, at=[shield_pad_x, shield_pad_y], size=shield_pad_size, drill=shield_pad_drill, layers=Pad.LAYERS_THT)) kicad_mod.append(Pad(number = pin_number_shield, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, at=[-shield_pad_x, shield_pad_y], size=shield_pad_size, drill=shield_pad_drill, layers=Pad.LAYERS_THT)) ########################### Outline ################################ poly_fab = [ {'x': 0, 'y': body_edge['top']}, {'x': body_edge['left']+body_chamfer, 'y': body_edge['top']}, {'x': body_edge['left'], 'y': body_edge['top']+body_chamfer}, {'x': body_edge['left'], 'y': body_edge['bottom']-body_chamfer}, {'x': body_edge['left']+body_chamfer, 'y': body_edge['bottom']}, {'x': 0, 'y': body_edge['bottom']} ] kicad_mod.append(PolygoneLine(polygone=poly_fab, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly_fab, x_mirror=0, layer='F.Fab', width=configuration['fab_line_width'])) pad_x_outside_edge = A/2 + pad_size[0]/2 + pad_silk_off if not params['shield_pad']: poly_silk = [ {'x': -pad_x_outside_edge, 'y': body_edge['top']-off}, {'x': body_edge['left']+body_chamfer-off, 'y': body_edge['top']-off}, {'x': body_edge['left']-off, 'y': body_edge['top']+body_chamfer-off}, {'x': body_edge['left']-off, 'y': body_edge['bottom']-body_chamfer+off}, {'x': body_edge['left']+body_chamfer-off, 'y': body_edge['bottom']+off}, {'x': -pad_x_outside_edge, 'y': body_edge['bottom']+off} ] kicad_mod.append(PolygoneLine(polygone=poly_silk, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly_silk, x_mirror=0, layer='F.SilkS', width=configuration['silk_line_width'])) else: r = (shield_pad_size/2 + pad_silk_off) x = (D-C)/2 dy = sqrt(r**2 - x**2) poly_silk_top = [ {'x': -pad_x_outside_edge, 'y': body_edge['top']-off}, {'x': body_edge['left']+body_chamfer-off, 'y': body_edge['top']-off}, {'x': body_edge['left']-off, 'y': body_edge['top']+body_chamfer-off}, {'x': body_edge['left']-off, 'y': shield_pad_y-dy}, ] kicad_mod.append(PolygoneLine(polygone=poly_silk_top, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly_silk_top, x_mirror=0, layer='F.SilkS', width=configuration['silk_line_width'])) poly_silk_bottom = [ {'x': body_edge['left']-off, 'y': shield_pad_y+dy}, {'x': body_edge['left']-off, 'y': body_edge['bottom']-body_chamfer+off}, {'x': body_edge['left']+body_chamfer-off, 'y': body_edge['bottom']+off}, {'x': -pad_x_outside_edge, 'y': body_edge['bottom']+off} ] kicad_mod.append(PolygoneLine(polygone=poly_silk_bottom, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly_silk_bottom, x_mirror=0, layer='F.SilkS', width=configuration['silk_line_width'])) ########################### Pin 1 ################################# p1s_sl = 0.4 p1s_y = -pad_y - pad_size[1]/2 - pad_silk_off p1_x = -A/2 p1s_poly = [ {'x': p1_x, 'y':p1s_y}, {'x': p1_x-p1s_sl/2, 'y':p1s_y-p1s_sl/sqrt(2)}, {'x': p1_x+p1s_sl/2, 'y':p1s_y-p1s_sl/sqrt(2)}, {'x': p1_x, 'y':p1s_y} ] kicad_mod.append(PolygoneLine(polygone=p1s_poly, layer='F.SilkS', width=configuration['silk_line_width'])) p1f_sl = 2*pitch p1f_poly = [ {'x': p1_x-p1f_sl/2, 'y':body_edge['top']}, {'x': p1_x, 'y':body_edge['top']+p1f_sl/sqrt(2)}, {'x': p1_x+p1f_sl/2, 'y':body_edge['top']} ] kicad_mod.append(PolygoneLine(polygone=p1f_poly, layer='F.Fab', width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for variant in variant_params: for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, variant_params[variant], configuration)
def generate_one_footprint(pins_per_row, variant, configuration): silk_pad_off = configuration['silk_pad_clearance']+configuration['silk_line_width']/2 mpn = variant_params[variant]['part_code']['mpn'].format(n=pins_per_row*2) old_mpn = variant_params[variant]['part_code']['eng_num'].format(n=pins_per_row*2) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=old_mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) descr_format_str = "Molex {:s}, old mpn/engineering number: {:s}, example for new mpn: {:s}, {:d} Pins per row, Mounting: {:s} ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription(descr_format_str.format( series_long, old_mpn, mpn, pins_per_row, variant_params[variant]['descriptive_name'], variant_params[variant]['datasheet'])) tags = configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation]) tags += variant_params[variant]['mount_pins'] kicad_mod.setTags(tags) peg = variant_params[variant]['mount_pins'] == 'plastic_peg' #calculate fp dimensions #connector length A = pins_per_row * pitch + 1.2 #pin centers B = (pins_per_row - 1) * pitch #plasic pin-lock C = A + 4 #connector width W = 9.6 #corner positions x1 = -(A-B)/2 x2 = x1 + A y1 = -7.3 - 6.6 y2 = y1 + 12.8 body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() bounding_box['bottom'] = row + pad_size[1]/2 #generate the pads optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for row_idx in range(2): kicad_mod.append(PadArray( pincount=pins_per_row, initial=row_idx*pins_per_row+1, start=[0, row_idx*row], x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) off = configuration['silk_fab_offset'] #draw the 'peg' version #http://www.molex.com/pdm_docs/sd/026013127_sd.pdf #draw the outline of the shape kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2], layer='F.Fab', width=configuration['fab_line_width'])) if peg: loc = 3.00 if pins_per_row > 2: # two mounting holes kicad_mod.append(Pad(at=[0,-7.3],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=loc,drill=loc, layers=Pad.LAYERS_NPTH)) #kicad_mod.append(Circle(center=[0,-7.3],radius=loc/2+0.1)) kicad_mod.append(Pad(at=[B,-7.3],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=loc,drill=loc, layers=Pad.LAYERS_NPTH)) #kicad_mod.append(Circle(center=[B,-7.3],radius=loc/2+0.1)) else: #single hole kicad_mod.append(Pad(at=[B/2,-7.3],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=loc,drill=loc, layers=Pad.LAYERS_NPTH)) #kicad_mod.append(Circle(center=[B/2,-7.3],radius=loc/2+0.1)) #draw the outline of the connector on the silkscreen poly = [ {'x': -2,'y': y2+off}, {'x': x1-off,'y': y2+off}, {'x': x1-off,'y': y1-off}, {'x': B/2,'y': y1-off}, ] kicad_mod.append(PolygoneLine(polygone=poly, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly, x_mirror=B/2, layer='F.SilkS', width=configuration['silk_line_width'])) #draw the 'screw' version #http://www.molex.com/pdm_docs/sd/039291027_sd.pdf else: loc = 3.2 kicad_mod.append(Pad(at=[-4.5, -4.2],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=loc, drill=loc, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(at=[B+4.5, -4.2],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=loc, drill=loc, layers=Pad.LAYERS_NPTH)) bounding_box['left'] = -15.4/2 bounding_box['right'] = B + 15.4/2 #draw the connector outline on silkscreen layer poly = [ {'x': x1,'y': y2-6.2}, {'x': -15.4/2,'y': y2-6.2}, {'x': -15.4/2,'y': y2}, {'x': x1,'y': y2} ] kicad_mod.append(PolygoneLine(polygone=poly, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly, x_mirror=B/2, layer='F.Fab', width=configuration['fab_line_width'])) poly = [ {'x': B/2,'y': y1-off}, {'x': x1-off,'y': y1-off}, {'x': x1-off,'y': y2-6.2-off}, {'x': -15.4/2 - off,'y': y2-6.2-off}, {'x': -15.4/2 - off,'y': y2+off}, {'x': -2,'y': y2+off}, ] kicad_mod.append(PolygoneLine(polygone=poly)) kicad_mod.append(PolygoneLine(polygone=poly, x_mirror=B/2, layer='F.SilkS', width=configuration['silk_line_width'])) #draw the pins_per_row on the Silkscreen layer o = pad_size[1]/2+silk_pad_off w = 0.3 for i in range(pins_per_row): x = i * pitch ya = o yb = row - o kicad_mod.append(Line(start=[x-w,ya],end=[x-w,yb], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x+w,ya],end=[x+w,yb], layer='F.SilkS', width=configuration['silk_line_width'])) #draw lines between each pin off = 0.1 for i in range(pins_per_row-1): xa = i * pitch + pad_size[0] / 2 + silk_pad_off xb = (i+1) * pitch - pad_size[0] / 2 - silk_pad_off kicad_mod.append(Line(start=[xa,y2+off],end=[xb,y2+off], layer='F.SilkS', width=configuration['silk_line_width'])) #pin-1 marker x = -2 m = 0.3 arrow = [ {'x': x,'y': 0}, {'x': x-2*m,'y': +m}, {'x': x-2*m,'y': -m}, {'x': x,'y': 0}, ] kicad_mod.append(PolygoneLine(polygone=arrow, layer='F.SilkS', width=configuration['silk_line_width'])) sl = 2 pin = [ {'x': -sl/2, 'y': body_edge['bottom']}, {'x': 0, 'y': body_edge['bottom']-sl/sqrt(2)}, {'x': sl/2, 'y': body_edge['bottom']}, ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# CrtYd_offset = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] cx1 = roundToBase(bounding_box['left'] - CrtYd_offset, CrtYd_grid) cy1 = roundToBase(bounding_box['top'] - CrtYd_offset, CrtYd_grid) cx2 = roundToBase(bounding_box['right'] + CrtYd_offset, CrtYd_grid) cy2 = roundToBase(bounding_box['bottom'] + CrtYd_offset, CrtYd_grid) if peg: kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) else: cxb_left = roundToBase(body_edge['left'] - CrtYd_offset, CrtYd_grid) cxp_left = roundToBase(-pad_size[0]/2 - CrtYd_offset, CrtYd_grid) cyb_bottom = roundToBase(body_edge['bottom'] + CrtYd_offset, CrtYd_grid) cyb_mount_top = roundToBase(body_edge['bottom'] -6.2 - CrtYd_offset, CrtYd_grid) poly_crtyd = [ {'x': B/2, 'y': cy1}, {'x': cxb_left, 'y': cy1}, {'x': cxb_left, 'y': cyb_mount_top}, {'x': cx1, 'y': cyb_mount_top}, {'x': cx1, 'y': cyb_bottom}, {'x': cxp_left, 'y': cyb_bottom}, {'x': cxp_left, 'y': cy2}, {'x': B/2, 'y': cy2}, ] kicad_mod.append(PolygoneLine( polygone=poly_crtyd, layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(PolygoneLine( polygone=poly_crtyd, x_mirror=B/2 if B/2 != 0 else 0.000000001, layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins, configuration, keying): #calculate fp dimensions pins_per_row = int(pins / number_of_rows) A = (pins_per_row - 1) * pitch B = A + 5.2 mpn = part_base.format(n=pins, s=keying) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_dual_pitch_format_string'].format( man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad="", pitch_x=pitch, pitch_y=row_pitch, orientation=orientation_str) print('Building footprint: {}'.format(footprint_name)) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription( "JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator" .format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format( series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) pad_size = [pitch - pad_to_pad_clearance, row_pitch - pad_to_pad_clearance] if pad_size[0] - drill < 2 * min_annular_ring: pad_size[0] = drill + 2 * min_annular_ring if pad_size[1] - drill > 2 * pad_copper_y_solder_length: pad_size[1] = drill + 2 * pad_copper_y_solder_length if pad_size[1] - drill < 2 * min_annular_ring: pad_size[1] = drill + 2 * min_annular_ring if pad_size[0] == pad_size[1]: pad_shape = Pad.SHAPE_CIRCLE else: pad_shape = Pad.SHAPE_OVAL optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for row_idx in range(2): #if pin1_row_to_mh == 'near': if keying == 'X': position_y = (row_idx) * row_pitch elif keying == 'Y': position_y = -(row_idx) * row_pitch kicad_mod.append( PadArray(initial=row_idx * pins_per_row + 1, start=[0, position_y], x_spacing=pitch, pincount=pins_per_row, increment=1, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=pad_shape, layers=Pad.LAYERS_THT, **optional_pad_params)) #draw the component outline x1 = A / 2 - B / 2 x2 = x1 + B y1 = -4.48 #if pin1_row_to_mh == 'near': if keying == 'Y': y1 -= row_pitch y2 = y1 + 14.4 body_edge = {'left': x1, 'right': x2, 'top': y1, 'bottom': y2} #draw the main outline around the footprint kicad_mod.append( RectLine(start=[x1, y1], end=[x2, y2], layer='F.Fab', width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(x1 - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y1 - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2 + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2 + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append( RectLine(start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #offset off off = configuration['silk_fab_offset'] x1 -= off y1 -= off x2 += off y2 += off #outline ol = RectLine(start=[x1, y1], end=[x2, y2], layer="F.SilkS", width=configuration['silk_line_width']) kicad_mod.append(ol) #courtyard #add mounting holes mh_y = 3.3 #if pin1_row_to_mh != 'near': if keying == 'X': mh_y += row_pitch m1 = Pad(at=[0, mh_y], layers=Pad.LAYERS_THT, shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_THT, size=3, drill=2) m2 = Pad(at=[A, mh_y], layers=Pad.LAYERS_THT, shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_THT, size=3, drill=2) kicad_mod.append(m1) kicad_mod.append(m2) #add p1 marker px = -3 m = 0.3 marker = [ { 'x': px, 'y': 0 }, { 'x': px - 2 * m, 'y': m }, { 'x': px - 2 * m, 'y': -m }, { 'x': px, 'y': 0 }, ] kicad_mod.append( PolygoneLine(polygone=marker, layer="F.SilkS", width=configuration['silk_line_width'])) sl = 1 marker = [{ 'x': body_edge['left'], 'y': sl / 2 }, { 'x': body_edge['left'] + sl / sqrt(2), 'y': 0 }, { 'x': body_edge['left'], 'y': -sl / 2 }] kicad_mod.append( PolygoneLine(polygone=marker, layer='F.Fab', width=configuration['fab_line_width'])) #line offset o o = 1 ya = o yb = -o - row_pitch #if pin1_row_to_mh != 'near': if keying == 'X': ya += row_pitch yb = -o #draw lines between pin pairs for i in range(pins_per_row - 1): x = (i + 0.5) * pitch kicad_mod.append( Line(start=[x, ya], end=[x, yb], width=configuration['fab_line_width'], layer='F.Fab')) #draw the inside of the connector #connector thickness t t = 0.45 #notch size n n = 1.2 inside = [{ 'x': A / 2 - n / 2, 'y': y1 }, { 'x': A / 2 - n / 2, 'y': y1 + t }, { 'x': x1 + t, 'y': y1 + t }, { 'x': x1 + t, 'y': y2 - t }, { 'x': x1 + t + n, 'y': y2 - t }, { 'x': x1 + t + n, 'y': y2 - 2 * t }, { 'x': A / 2, 'y': y2 - 2 * t }] kicad_mod.append( PolygoneLine(polygone=inside, layer="F.SilkS", width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=inside, x_mirror=A / 2, layer="F.SilkS", width=configuration['silk_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={ 'top': cy1, 'bottom': cy2 }, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins, configuration): mpn = part_code.format(n=pins) pad_silk_off = configuration['silk_line_width']/2 + configuration['silk_pad_clearance'] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "", pitch=pitch, orientation=orientation_str) footprint_name = footprint_name.replace("__",'_') kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) A = (pins - 1) * pitch B = A + 2.9 # create pads #createNumberedPadsTHT(kicad_mod, pincount, pitch, drill, {'x':x_dia, 'y':y_dia}) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(start=[0,0], pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) x1 = -(B-A) / 2 y1 = -2.2 x2 = x1 + B y2 = 1.2 body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() kicad_mod.append(RectLine( start={'x': x1,'y': y1}, end={'x': x2,'y': y2}, layer='F.Fab', width=configuration['fab_line_width'])) #line offset off = 0.1 x1 -= off y1 -= off x2 += off y2 += off #draw the main outline around the footprint kicad_mod.append(RectLine(start={'x':x1,'y':y1},end={'x':x2,'y':y2}, layer='F.SilkS', width=configuration['silk_line_width'])) #add pin-1 marker p1_off = configuration['silk_fab_offset'] + 0.3 L = 1.5 pin = [ {'y': body_edge['bottom'] - L, 'x': body_edge['left'] - p1_off}, {'y': body_edge['bottom'] + p1_off, 'x': body_edge['left'] - p1_off}, {'y': body_edge['bottom'] + p1_off, 'x': body_edge['left'] + L} ] kicad_mod.append(PolygoneLine(polygone=pin, layer='F.SilkS', width=configuration['silk_line_width'])) sl=1 pin = [ {'y': body_edge['bottom'], 'x': -sl/2}, {'y': body_edge['bottom'] - sl/sqrt(2), 'x': 0}, {'y': body_edge['bottom'], 'x': sl/2} ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) #side-wall thickness S S = 0.3 #bottom line kicad_mod.append(PolygoneLine( polygone=[ {'x':x1,'y':0}, {'x':x1+S,'y':0}, {'x':x1+S,'y':y2-S}, {'x':x2-S,'y':y2-S}, {'x':x2-S,'y':0}, {'x':x2,'y':0}], layer='F.SilkS', width=configuration['silk_line_width'])) #left mark #gap g g = 0.75 kicad_mod.append(PolygoneLine( polygone=[ {'x':x1,'y':-g}, {'x':x1+S,'y':-g}, {'x':x1+S,'y':y1+S*1.5}, {'x':x1+2*S,'y':y1+S*1.5}, {'x':x1+2*S,'y':y1}], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine( polygone=[ {'x':x2,'y':-g}, {'x':x2-S,'y':-g}, {'x':x2-S,'y':y1+S*1.5}, {'x':x2-2*S,'y':y1+S*1.5}, {'x':x2-2*S,'y':y1}], layer='F.SilkS', width=configuration['silk_line_width'])) #middle line kicad_mod.append(PolygoneLine( polygone=[ {'x':x1+2*S,'y':y1+1.5*S}, {'x':0.2*pitch,'y':y1+1.5*S}, {'x':0.2*pitch,'y':y1+0.5*S}, {'x':0.8*pitch,'y':y1+0.5*S}, {'x':0.8*pitch,'y':y1+1.5*S}, {'x':A-0.8*pitch,'y':y1+1.5*S}, {'x':A-0.8*pitch,'y':y1+0.5*S}, {'x':A-0.2*pitch,'y':y1+0.5*S}, {'x':A-0.2*pitch,'y':y1+1.5*S}, {'x':x2-2*S,'y':y1+1.5*S}], layer='F.SilkS', width=configuration['silk_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins, series_params, configuration): #calculate dimensions A = (pins - 1) * pitch B = A + 3.9 #generate name mpn = part_base.format(n=pins, suffix=series_params[1]) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format( man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription( "JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator" .format(series_params[2], mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format( series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #coordinate locations # x1 x3 x4 x2 # y3 ____________________ # y1 __|____________________|__ # | 1 2 3 4 5 6 7 8 | # y2 |________________________| #draw the component outline x1 = A / 2 - B / 2 x2 = x1 + B y2 = 4.8 y1 = y2 - 6.8 y3 = y1 - 1.7 body_edge = {'left': x1, 'right': x2, 'top': y1, 'bottom': y2} #draw outline on F.Fab layer kicad_mod.append( RectLine(start=[x1, y1], end=[x2, y2], layer='F.Fab', width=configuration['fab_line_width'])) #draw rectangle on F.Fab for latch x3 = -0.75 x4 = pitch * (pins - 1) + 0.75 kicad_mod.append( PolygoneLine(polygone=[{ 'x': x3, 'y': y1 }, { 'x': x3, 'y': y3 }, { 'x': x4, 'y': y3 }, { 'x': x4, 'y': y1 }], layer='F.Fab', width=configuration['fab_line_width'])) #draw pin1 mark on F.Fab kicad_mod.append( PolygoneLine(polygone=[{ 'x': x1, 'y': -1 }, { 'x': (x1 + 1), 'y': 0 }], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append( PolygoneLine(polygone=[{ 'x': x1, 'y': 1 }, { 'x': (x1 + 1), 'y': 0 }], layer='F.Fab', width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(x1 - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y3 - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2 + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2 + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append( RectLine(start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #draw silk outline off = configuration['silk_fab_offset'] x1 -= off y1 -= off x2 += off y2 += off x3 -= off y3 -= off x4 += off kicad_mod.append( PolygoneLine(polygone=[{ 'x': x1, 'y': y2 }, { 'x': x1, 'y': y1 }, { 'x': x3, 'y': y1 }, { 'x': x3, 'y': y3 }, { 'x': x4, 'y': y3 }, { 'x': x4, 'y': y1 }, { 'x': x2, 'y': y1 }, { 'x': x2, 'y': y2 }, { 'x': x1, 'y': y2 }], layer='F.SilkS', width=configuration['silk_line_width'])) #add pin1 mark on silk px = x1 - 0.2 m = 0.3 marker = [{ 'x': px, 'y': 0 }, { 'x': px - 2 * m, 'y': m }, { 'x': px - 2 * m, 'y': -m }, { 'x': px, 'y': 0 }] kicad_mod.append( PolygoneLine(polygone=marker, layer='F.SilkS', width=configuration['silk_line_width'])) pad_size = [ pitch - pad_to_pad_clearance, drill + 2 * pad_copper_y_solder_length ] if pad_size[0] - drill < 2 * min_annular_ring: pad_size[0] = drill + 2 * min_annular_ring if pad_size[0] - drill > 2 * pad_copper_y_solder_length: pad_size[0] = drill + 2 * pad_copper_y_solder_length shape = Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: shape = Pad.SHAPE_CIRCLE pa = PadArray(pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT) kicad_mod.append(pa) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={ 'top': cy1, 'bottom': cy2 }, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(fpid, rows, datasheet, configuration): pins = [] if fpid == "IAxxxxS" and rows == "SIP" : casetolerance = 0.5 casemaxwidth = 6.09 casemaxlength = 19.30 x_max = 1.40 x_min = x_max - (casemaxwidth - casetolerance) y_min = -1.53 y_max = y_min + (casemaxlength - casetolerance) pins = [1, 2, 4, 5, 6] xpos = [1, 1, 1, 1, 1] ypos = [1, 2, 4, 5, 6] elif fpid == "IA48xxS" and rows == "SIP" : casetolerance = 0.5 casemaxwidth = 7.20 casemaxlength = 19.30 x_max = 1.40 x_min = x_max - (casemaxwidth - casetolerance) y_min = -1.53 y_max = y_min + (casemaxlength - casetolerance) pins = [1, 2, 4, 5, 6] xpos = [1, 1, 1, 1, 1] ypos = [1, 2, 4, 5, 6] elif fpid == "IAxxxxD" and rows == "DIP" : casetolerance = 0.5 casemaxwidth = 10.16 casemaxlength = 20.32 x_min = -(casemaxwidth-casetolerance-xpitch)/2 x_max = x_min + (casemaxwidth - casetolerance) y_min = -(casemaxlength-casetolerance-15.24)/2 y_max = y_min + (casemaxlength - casetolerance) pins = [1, 2, 3, 4, 5, 6] xpos = [1, 1, 2, 2, 2, 2] ypos = [1, 7, 1, 4, 6, 7] elif fpid == "IA48xxD" and rows == "DIP" : casetolerance = 0.5 casemaxwidth = 10.16 casemaxlength = 20.32 x_min = -(casemaxwidth-casetolerance-xpitch)/2 x_max = x_min + (casemaxwidth - casetolerance) y_min = -(casemaxlength-casetolerance-15.24)/2 y_max = y_min + (casemaxlength - casetolerance) pins = [1, 2, 3, 4, 5, 6] xpos = [1, 1, 2, 2, 2, 2] ypos = [1, 7, 1, 4, 6, 7] elif fpid == "IHxxxxS" and rows == "SIP" : casetolerance = 0.5 casemaxwidth = 7.20 casemaxlength = 19.5 x_max = 1.25 x_min = x_max - (casemaxwidth - casetolerance) y_min = -2.29 y_max = y_min + (casemaxlength - casetolerance) pins = [1, 2, 4, 5, 6] xpos = [1, 1, 1, 1, 1] ypos = [1, 2, 4, 5, 6] elif fpid == "IHxxxxSH" and rows == "SIP" : casetolerance = 0.5 casemaxwidth = 7.62 casemaxlength = 19.5 x_max = 1.25 x_min = x_max - (casemaxwidth - casetolerance) y_min = -2.29 y_max = y_min + (casemaxlength - casetolerance) pins = [1, 2, 4, 5, 6] xpos = [1, 1, 1, 1, 1] ypos = [1, 2, 5, 6, 7] elif fpid == "IHxxxxD" and rows == "DIP" : casetolerance = 0.5 casemaxwidth = 10.16 casemaxlength = 20.32 x_min = -(casemaxwidth-casetolerance-xpitch)/2 x_max = x_min + (casemaxwidth - casetolerance) y_min = -(casemaxlength-casetolerance-15.24)/2 y_max = y_min + (casemaxlength - casetolerance) pins = [1, 2, 3, 4, 5, 6] xpos = [1, 1, 2, 2, 2, 2] ypos = [1, 7, 1, 4, 6, 7] elif fpid == "IHxxxxDH" and rows == "DIP" : casetolerance = 0.5 casemaxwidth = 10.16 casemaxlength = 20.32 x_min = -(casemaxwidth-casetolerance-xpitch)/2 x_max = x_min + (casemaxwidth - casetolerance) y_min = -(casemaxlength-casetolerance-15.24)/2 y_max = y_min + (casemaxlength - casetolerance) pins = [1, 2, 3, 4, 5, 6] xpos = [1, 1, 2, 2, 2, 2] ypos = [1, 7, 1, 5, 7, 6] elif fpid == "ITQxxxxS-H" and rows == "SIP" : casetolerance = 0.5 casewidth = 9.20 caselength = 21.85 x_max = 3.20 x_min = x_max - casewidth y_min = -(caselength - 17.78)/2 y_max = y_min + caselength pins = [1, 2, 3, 6, 7, 8] xpos = [1, 1, 1, 1, 1, 1] ypos = [1, 2, 3, 6, 7, 8] elif fpid == "ITxxxxxS" and rows == "SIP" : casetolerance = 0.5 casewidth = 9.20 caselength = 21.85 x_max = 3.20 x_min = x_max - casewidth y_min = -(caselength - 17.78)/2 y_max = y_min + caselength pins = [1, 2, 3, 6, 7] xpos = [1, 1, 1, 1, 1] ypos = [1, 2, 3, 6, 7] elif fpid == "ITXxxxxSA" and rows == "SIP" : casetolerance = 0.5 casewidth = 9.20 caselength = 21.85 x_max = 3.20 x_min = x_max - casewidth y_min = -(caselength - 17.78)/2 y_max = y_min + caselength pins = [1, 2, 6, 7, 8] xpos = [1, 1, 1, 1, 1] ypos = [1, 2, 6, 7, 8] silk_x_min = x_min - configuration['silk_fab_offset'] silk_x_max = x_max + configuration['silk_fab_offset'] silk_y_min = y_min - configuration['silk_fab_offset'] silk_y_max = y_max + configuration['silk_fab_offset'] footprint_name = "Converter_DCDC_XP_POWER-{:s}_THT".format(fpid) ser = "" if fpid.startswith("IA_"): ser="SF_IA" elif fpid.startswith("IH_"): ser="SF_IH" elif fpid.startswith("ITX_"): ser="SF_ITX" elif fpid.startswith("ITQ_"): ser="SF_ITQ" kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("XP_POWER {:s} {:s}, {:s}, ({:s}), generated with kicad-footprint-generator".format(ser,fpid, rows, datasheet)) kicad_mod.setTags("XP_POWER {:s} {:s} {:s} DCDC-Converter".format(ser,fpid,rows)) # create Silkscreen kicad_mod.append(RectLine(start=[silk_x_min,silk_y_min], end=[silk_x_max,silk_y_max], layer='F.SilkS', width=configuration['silk_line_width'])) ########################### Pin 1 marker ################################ poly_pin1_marker = [ {'x':silk_x_min-pin1_marker_offset+pin1_marker_linelen, 'y':silk_y_min-pin1_marker_offset}, {'x':silk_x_min-pin1_marker_offset, 'y':silk_y_min-pin1_marker_offset}, {'x':silk_x_min-pin1_marker_offset, 'y':silk_y_min-pin1_marker_offset+pin1_marker_linelen} ] kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.SilkS', width=configuration['silk_line_width'])) if fab_pin1_marker_type == 1: kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.Fab', width=configuration['fab_line_width'])) if fab_pin1_marker_type == 2: poly_pin1_marker_type2 = [ {'x':-1, 'y':y_min}, {'x':0, 'y':y_min+1}, {'x':1, 'y':y_min} ] kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker_type2, layer='F.Fab', width=configuration['fab_line_width'])) ########################## Fab Outline ############################### kicad_mod.append(RectLine(start=[x_min,y_min], end=[x_max,y_max], layer='F.Fab', width=configuration['fab_line_width'])) ############################# CrtYd ################################## part_x_min = x_min part_x_max = x_max part_y_min = y_min part_y_max = y_max #Note, we use the connector courtyard clearance of 0.5 mm because the unusually large case tolerance of 0.5mm of XP Powers DC DC converters cx1 = roundToBase(part_x_min-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(part_y_min-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(part_x_max+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(part_y_max+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ############################# Pads ################################## pad_size = [ypitch - pad_to_pad_clearance, drill_size + 2*pad_copper_y_solder_length] if pad_size[0] - drill_size < 2*min_annular_ring: pad_size[0] = drill_size + 2*min_annular_ring optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for i in range(len(pins)): pshape = Pad.SHAPE_OVAL if pins[i] == 1: pshape = Pad.SHAPE_RECT kicad_mod.append(Pad(number=pins[i], type=Pad.TYPE_THT, shape=pshape, at=[(xpos[i]-1)*xpitch, (ypos[i]-1)*ypitch], size=pad_size, drill=drill_size, layers=Pad.LAYERS_THT, **optional_pad_params)) ######################### Text Fields ############################### text_center_y = 1.5 body_edge={'left':part_x_min, 'right':part_x_max, 'top':part_y_min, 'bottom':part_y_max} addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position=text_center_y) model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=ser) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) print(filename)
def generate_one_footprint(pins_per_row, variant, configuration): silk_pad_off = configuration[ 'silk_pad_clearance'] + configuration['silk_line_width'] / 2 mpn = variant_params[variant]['part_code']['mpn'].format(n=pins_per_row * 2) old_mpn = variant_params[variant]['part_code']['eng_num'].format( n=pins_per_row * 2) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format( man=manufacturer, series=series, mpn=old_mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) descr_format_str = "Molex {:s}, old mpn/engineering number: {:s}, example for new mpn: {:s}, {:d} Pins per row, Mounting: {:s} ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription( descr_format_str.format(series_long, old_mpn, mpn, pins_per_row, variant_params[variant]['descriptive_name'], variant_params[variant]['datasheet'])) tags = configuration['keyword_fp_string'].format( series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation]) tags += variant_params[variant]['mount_pins'] kicad_mod.setTags(tags) peg = variant_params[variant]['mount_pins'] == 'plastic_peg' #calculate fp dimensions #connector length A = pins_per_row * pitch + 1.2 #pin centers B = (pins_per_row - 1) * pitch #plasic pin-lock C = A + 4 #connector width W = 9.6 #corner positions x1 = -(A - B) / 2 x2 = x1 + A y1 = -7.3 - 6.6 y2 = y1 + 12.8 body_edge = {'left': x1, 'right': x2, 'bottom': y2, 'top': y1} bounding_box = body_edge.copy() bounding_box['bottom'] = row + pad_size[1] / 2 #generate the pads kicad_mod.append( PadArray(pincount=pins_per_row, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT)) kicad_mod.append( PadArray(pincount=pins_per_row, initial=pins_per_row + 1, start=[0, row], x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT)) off = configuration['silk_fab_offset'] #draw the 'peg' version #http://www.molex.com/pdm_docs/sd/026013127_sd.pdf #draw the outline of the shape kicad_mod.append( RectLine(start=[x1, y1], end=[x2, y2], layer='F.Fab', width=configuration['fab_line_width'])) if peg: loc = 3.00 if pins_per_row > 2: # two mounting holes kicad_mod.append( Pad(at=[0, -7.3], type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=loc, drill=loc, layers=Pad.LAYERS_NPTH)) #kicad_mod.append(Circle(center=[0,-7.3],radius=loc/2+0.1)) kicad_mod.append( Pad(at=[B, -7.3], type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=loc, drill=loc, layers=Pad.LAYERS_NPTH)) #kicad_mod.append(Circle(center=[B,-7.3],radius=loc/2+0.1)) else: #single hole kicad_mod.append( Pad(at=[B / 2, -7.3], type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=loc, drill=loc, layers=Pad.LAYERS_NPTH)) #kicad_mod.append(Circle(center=[B/2,-7.3],radius=loc/2+0.1)) #draw the outline of the connector on the silkscreen poly = [ { 'x': -2, 'y': y2 + off }, { 'x': x1 - off, 'y': y2 + off }, { 'x': x1 - off, 'y': y1 - off }, { 'x': B / 2, 'y': y1 - off }, ] kicad_mod.append( PolygoneLine(polygone=poly, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=poly, x_mirror=B / 2 if B / 2 != 0 else 0.000000001, layer='F.SilkS', width=configuration['silk_line_width'])) #draw the 'screw' version #http://www.molex.com/pdm_docs/sd/039291027_sd.pdf else: loc = 3.2 kicad_mod.append( Pad(at=[-4.5, -4.2], type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=loc, drill=loc, layers=Pad.LAYERS_NPTH)) kicad_mod.append( Pad(at=[B + 4.5, -4.2], type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=loc, drill=loc, layers=Pad.LAYERS_NPTH)) bounding_box['left'] = -15.4 / 2 bounding_box['right'] = B + 15.4 / 2 #draw the connector outline on silkscreen layer poly = [{ 'x': x1, 'y': y2 - 6.2 }, { 'x': -15.4 / 2, 'y': y2 - 6.2 }, { 'x': -15.4 / 2, 'y': y2 }, { 'x': x1, 'y': y2 }] kicad_mod.append( PolygoneLine(polygone=poly, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append( PolygoneLine(polygone=poly, x_mirror=B / 2 if B / 2 != 0 else 0.000000001, layer='F.Fab', width=configuration['fab_line_width'])) poly = [ { 'x': B / 2, 'y': y1 - off }, { 'x': x1 - off, 'y': y1 - off }, { 'x': x1 - off, 'y': y2 - 6.2 - off }, { 'x': -15.4 / 2 - off, 'y': y2 - 6.2 - off }, { 'x': -15.4 / 2 - off, 'y': y2 + off }, { 'x': -2, 'y': y2 + off }, ] kicad_mod.append(PolygoneLine(polygone=poly)) kicad_mod.append( PolygoneLine(polygone=poly, x_mirror=B / 2 if B / 2 != 0 else 0.000000001, layer='F.SilkS', width=configuration['silk_line_width'])) #draw the pins_per_row on the Silkscreen layer o = pad_size[1] / 2 + silk_pad_off w = 0.3 for i in range(pins_per_row): x = i * pitch ya = o yb = row - o kicad_mod.append( Line(start=[x - w, ya], end=[x - w, yb], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( Line(start=[x + w, ya], end=[x + w, yb], layer='F.SilkS', width=configuration['silk_line_width'])) #draw lines between each pin off = 0.1 for i in range(pins_per_row - 1): xa = i * pitch + pad_size[0] / 2 + silk_pad_off xb = (i + 1) * pitch - pad_size[0] / 2 - silk_pad_off kicad_mod.append( Line(start=[xa, y2 + off], end=[xb, y2 + off], layer='F.SilkS', width=configuration['silk_line_width'])) #pin-1 marker x = -2 m = 0.3 arrow = [ { 'x': x, 'y': 0 }, { 'x': x - 2 * m, 'y': +m }, { 'x': x - 2 * m, 'y': -m }, { 'x': x, 'y': 0 }, ] kicad_mod.append( PolygoneLine(polygone=arrow, layer='F.SilkS', width=configuration['silk_line_width'])) sl = 2 pin = [ { 'x': -sl / 2, 'y': body_edge['bottom'] }, { 'x': 0, 'y': body_edge['bottom'] - sl / sqrt(2) }, { 'x': sl / 2, 'y': body_edge['bottom'] }, ] kicad_mod.append( PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# CrtYd_offset = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] cx1 = roundToBase(bounding_box['left'] - CrtYd_offset, CrtYd_grid) cy1 = roundToBase(bounding_box['top'] - CrtYd_offset, CrtYd_grid) cx2 = roundToBase(bounding_box['right'] + CrtYd_offset, CrtYd_grid) cy2 = roundToBase(bounding_box['bottom'] + CrtYd_offset, CrtYd_grid) if peg: kicad_mod.append( RectLine(start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) else: cxb_left = roundToBase(body_edge['left'] - CrtYd_offset, CrtYd_grid) cxp_left = roundToBase(-pad_size[0] / 2 - CrtYd_offset, CrtYd_grid) cyb_bottom = roundToBase(body_edge['bottom'] + CrtYd_offset, CrtYd_grid) cyb_mount_top = roundToBase(body_edge['bottom'] - 6.2 - CrtYd_offset, CrtYd_grid) poly_crtyd = [ { 'x': B / 2, 'y': cy1 }, { 'x': cxb_left, 'y': cy1 }, { 'x': cxb_left, 'y': cyb_mount_top }, { 'x': cx1, 'y': cyb_mount_top }, { 'x': cx1, 'y': cyb_bottom }, { 'x': cxp_left, 'y': cyb_bottom }, { 'x': cxp_left, 'y': cy2 }, { 'x': B / 2, 'y': cy2 }, ] kicad_mod.append( PolygoneLine(polygone=poly_crtyd, layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append( PolygoneLine(polygone=poly_crtyd, x_mirror=B / 2 if B / 2 != 0 else 0.000000001, layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={ 'top': cy1, 'bottom': cy2 }, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins_per_row, configuration): mpn = part_code.format(n=pins_per_row*number_of_rows) alt_mpn = [code.format(n=pins_per_row*number_of_rows) for code in alternative_codes] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s} (compatible alternatives: {:s}), {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, ', '.join(alt_mpn), pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate fp dimensions A = (pins_per_row - 1) * pitch B = A + 3.1 C = A + 4 #connector thickness T = 5.75 #corners x1 = -2 x2 = x1 + C T = 3.65 y1 = -1.5 y2 = y1 + T off = configuration['silk_fab_offset'] pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() #add simple outline to F.Fab layer kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2],layer='F.Fab', width=configuration['fab_line_width'])) #wall-thickness W w = 0.4 #offset o = configuration['silk_fab_offset'] x1 -= o y1 -= o x2 += o y2 += o #generate the pads optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray( pincount=pins_per_row, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) #draw the courtyard #draw the connector outline out = RectLine(start=[x1,y1], end=[x2,y2], width=configuration['silk_line_width'], layer="F.SilkS") kicad_mod.append(out) #pin-1 marker y = -2 m = 0.3 O = 0.3 L = 2 pin = [ {'x': x1 + L, 'y': y1 - O}, {'x': x1 - O, 'y': y1 - O}, {'x': x1 - O, 'y': y1 + L}, ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['silk_line_width'], layer="F.SilkS")) p1m_sl = 1 pin =[ {'x': -p1m_sl/2, 'y': body_edge['top']}, {'x': 0, 'y': body_edge['top'] + p1m_sl/sqrt(2)}, {'x': p1m_sl/2, 'y': body_edge['top']} ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) kicad_mod.append(Line(start=[x1,2*w],end=[x1+w,2*w], width=configuration['silk_line_width'], layer="F.SilkS")) kicad_mod.append(Line(start=[x2,2*w],end=[x2-w,2*w], width=configuration['silk_line_width'], layer="F.SilkS")) #add the 'wall' wall = [ {'x': A/2,'y': y1+w}, {'x': x1+w,'y': y1+w}, {'x': x1+w,'y': 0}, {'x': x1+2*w,'y': 0}, {'x': x1+2*w,'y': w}, {'x': x1+w,'y': w}, {'x': x1+w,'y': y2}, ] kicad_mod.append(PolygoneLine(polygone=wall, width=configuration['silk_line_width'], layer="F.SilkS")) kicad_mod.append(PolygoneLine(polygone=wall,x_mirror=A/2, width=configuration['silk_line_width'], layer="F.SilkS")) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generateFootprint(self, device_params): fab_line_width = self.configuration.get('fab_line_width', 0.1) silk_line_width = self.configuration.get('silk_line_width', 0.12) lib_name = self.configuration['lib_name_format_string'].format( category=category) if 'body_size_x' in device_params: size_x = device_params['body_size_x'] else: size_x = (device_params['body_size_x_max'] + device_params['body_size_x_min']) / 2 if 'body_size_y' in device_params: size_y = device_params['body_size_y'] else: size_y = (device_params['body_size_y_max'] + device_params['body_size_y_min']) / 2 pincount = device_params['num_pins_x'] * 2 + device_params[ 'num_pins_y'] * 2 ipc_reference = 'ipc_spec_j_lead' ipc_data_set = self.ipc_defintions[ipc_reference][ipc_density] ipc_round_base = self.ipc_defintions[ipc_reference]['round_base'] pad_details = self.calcPadDetails(device_params, ipc_data_set, ipc_round_base) suffix = device_params.get('suffix', '').format( pad_x=pad_details['left']['size'][0], pad_y=pad_details['left']['size'][1]) suffix_3d = suffix if device_params.get('include_suffix_in_3dpath', 'True') == 'True' else "" model3d_path_prefix = self.configuration.get('3d_model_prefix', '${KISYS3DMOD}') name_format = self.configuration['fp_name_format_string'] fp_name = name_format.format(man=device_params.get('manufacturer', ''), mpn=device_params.get('part_number', ''), pkg=device_params['device_type'], pincount=pincount, size_y=size_y, size_x=size_x, pitch=device_params['pitch'], suffix=suffix).replace('__', '_').lstrip('_') fp_name_2 = name_format.format( man=device_params.get('manufacturer', ''), mpn=device_params.get('part_number', ''), pkg=device_params['device_type'], pincount=pincount, size_y=size_y, size_x=size_x, pitch=device_params['pitch'], suffix=suffix_3d).replace('__', '_').lstrip('_') model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'\ .format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=fp_name_2) #print(fp_name) #print(pad_details) kicad_mod = Footprint(fp_name) # init kicad footprint kicad_mod.setDescription( "{manufacturer} {mpn} {package}, {pincount} Pin ({datasheet}), generated with kicad-footprint-generator {scriptname}"\ .format( manufacturer = device_params.get('manufacturer',''), package = device_params['device_type'], mpn = device_params.get('part_number',''), pincount = pincount, datasheet = device_params['size_source'], scriptname = os.path.basename(__file__).replace(" ", " ") ).lstrip()) kicad_mod.setTags(self.configuration['keyword_fp_string']\ .format( man=device_params.get('manufacturer',''), package=device_params['device_type'], category=category ).lstrip()) 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'] init = 1 kicad_mod.append( PadArray(initial=init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=int(math.ceil(device_params['num_pins_x'] / 2)), x_spacing=-device_params['pitch'], y_spacing=0, **pad_details['first'], **pad_shape_details)) init += int(math.ceil(device_params['num_pins_x'] / 2)) kicad_mod.append( PadArray(initial=init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_y'], x_spacing=0, y_spacing=device_params['pitch'], **pad_details['left'], **pad_shape_details)) init += device_params['num_pins_y'] kicad_mod.append( PadArray(initial=init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_x'], y_spacing=0, x_spacing=device_params['pitch'], **pad_details['bottom'], **pad_shape_details)) init += device_params['num_pins_x'] kicad_mod.append( PadArray(initial=init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_y'], x_spacing=0, y_spacing=-device_params['pitch'], **pad_details['right'], **pad_shape_details)) init += device_params['num_pins_y'] kicad_mod.append( PadArray(initial=init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=int(math.floor(device_params['num_pins_x'] / 2)), y_spacing=0, x_spacing=-device_params['pitch'], **pad_details['top'], **pad_shape_details)) body_edge = { 'left': -size_x / 2, 'right': size_x / 2, 'top': -size_y / 2, 'bottom': size_y / 2 } bounding_box = { 'left': pad_details['left']['center'][0] - pad_details['left']['size'][0] / 2, 'right': pad_details['right']['center'][0] + pad_details['right']['size'][0] / 2, 'top': pad_details['top']['start'][1] - pad_details['top']['size'][1] / 2, 'bottom': pad_details['bottom']['center'][1] + pad_details['bottom']['size'][1] / 2 } pad_width = pad_details['top']['size'][0] p1_x = pad_details['first']['start'][0] # ############################ SilkS ################################## silk_pad_offset = configuration[ 'silk_pad_clearance'] + configuration['silk_line_width'] / 2 silk_offset = configuration['silk_fab_offset'] sx1 = -(device_params['pitch'] * (device_params['num_pins_x'] - 1) / 2.0 + pad_width / 2.0 + silk_pad_offset) sy1 = -(device_params['pitch'] * (device_params['num_pins_y'] - 1) / 2.0 + pad_width / 2.0 + silk_pad_offset) poly_silk = [{ 'x': sx1, 'y': body_edge['top'] - silk_offset }, { 'x': body_edge['left'] - silk_offset, 'y': body_edge['top'] - silk_offset }, { 'x': body_edge['left'] - silk_offset, 'y': sy1 }] kicad_mod.append( PolygoneLine(polygone=poly_silk, width=configuration['silk_line_width'], layer="F.SilkS", x_mirror=0)) kicad_mod.append( PolygoneLine(polygone=poly_silk, width=configuration['silk_line_width'], layer="F.SilkS", y_mirror=0)) kicad_mod.append( PolygoneLine(polygone=poly_silk, width=configuration['silk_line_width'], layer="F.SilkS", x_mirror=0, y_mirror=0)) silk_off_45 = silk_offset / sqrt(2) poly_silk_tl = [{ 'x': sx1, 'y': body_edge['top'] - silk_offset }, { 'x': body_edge['left'] + device_params['body_chamfer'] - silk_off_45, 'y': body_edge['top'] - silk_offset }, { 'x': body_edge['left'] - silk_offset, 'y': body_edge['top'] + device_params['body_chamfer'] - silk_off_45 }, { 'x': body_edge['left'] - silk_offset, 'y': sy1 }] kicad_mod.append( PolygoneLine(polygone=poly_silk_tl, width=configuration['silk_line_width'], layer="F.SilkS")) # # ######################## Fabrication Layer ########################### fab_bevel_size = min( configuration['fab_bevel_size_absolute'], configuration['fab_bevel_size_relative'] * min(size_x, size_y)) fab_bevel_y = fab_bevel_size / sqrt(2) poly_fab = [{ 'x': p1_x, 'y': body_edge['top'] + fab_bevel_y }, { 'x': p1_x + fab_bevel_size / 2, 'y': body_edge['top'] }, { 'x': body_edge['right'], 'y': body_edge['top'] }, { 'x': body_edge['right'], 'y': body_edge['bottom'] }, { 'x': body_edge['left'], 'y': body_edge['bottom'] }, { 'x': body_edge['left'], 'y': body_edge['top'] + device_params['body_chamfer'] }, { 'x': body_edge['left'] + device_params['body_chamfer'], 'y': body_edge['top'] }, { 'x': p1_x - fab_bevel_size / 2, 'y': body_edge['top'] }, { 'x': p1_x, 'y': body_edge['top'] + fab_bevel_y }] kicad_mod.append( PolygoneLine(polygone=poly_fab, width=configuration['fab_line_width'], layer="F.Fab")) # # ############################ CrtYd ################################## off = ipc_data_set['courtyard'] grid = configuration['courtyard_grid'] off_45 = off * math.tan(math.radians(45.0 / 2)) cy1 = roundToBase(bounding_box['top'] - off, grid) cy2 = roundToBase(body_edge['top'] - off, grid) cy3 = -roundToBase( device_params['pitch'] * (device_params['num_pins_y'] - 1) / 2.0 + pad_width / 2.0 + off, grid) cy4 = roundToBase( body_edge['top'] + device_params['body_chamfer'] - off_45, grid) cx1 = -roundToBase( device_params['pitch'] * (device_params['num_pins_x'] - 1) / 2.0 + pad_width / 2.0 + off, grid) cx2 = roundToBase(body_edge['left'] - off, grid) cx3 = roundToBase(bounding_box['left'] - off, grid) cx4 = roundToBase( body_edge['left'] + device_params['body_chamfer'] - off_45, grid) crty_poly_tl = [{ 'x': 0, 'y': cy1 }, { 'x': cx1, 'y': cy1 }, { 'x': cx1, 'y': cy2 }, { 'x': cx2, 'y': cy2 }, { 'x': cx2, 'y': cy3 }, { 'x': cx3, 'y': cy3 }, { 'x': cx3, 'y': 0 }] kicad_mod.append( PolygoneLine(polygone=crty_poly_tl, layer='F.CrtYd', width=configuration['courtyard_line_width'], x_mirror=0)) kicad_mod.append( PolygoneLine(polygone=crty_poly_tl, layer='F.CrtYd', width=configuration['courtyard_line_width'], y_mirror=0)) kicad_mod.append( PolygoneLine(polygone=crty_poly_tl, layer='F.CrtYd', width=configuration['courtyard_line_width'], x_mirror=0, y_mirror=0)) crty_poly_tl_ch = [{ 'x': 0, 'y': cy1 }, { 'x': cx1, 'y': cy1 }, { 'x': cx1, 'y': cy2 }, { 'x': cx4, 'y': cy2 }, { 'x': cx2, 'y': cy4 }, { 'x': cx2, 'y': cy3 }, { 'x': cx3, 'y': cy3 }, { 'x': cx3, 'y': 0 }] kicad_mod.append( PolygoneLine(polygone=crty_poly_tl_ch, layer='F.CrtYd', width=configuration['courtyard_line_width'])) # ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={ 'top': cy1, 'bottom': -cy1 }, fp_name=fp_name, text_y_inside_position='center') ##################### Output and 3d model ############################ kicad_mod.append(Model(filename=model_name)) 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=fp_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins, params, configuration): pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 off = configuration['silk_fab_offset'] mpn = params['mpn'].format(n=pins*number_of_rows) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) footprint_name += params['fp_name_suffix'] kicad_mod = Footprint(footprint_name) desc_format_str = "Molex {:s}, {:s}{:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription(desc_format_str.format(series_long, mpn, params['description'], pins, params['datasheet'])) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) # Dimensions P = (pins - 1) * pitch B = P + 2*6.79 # connector length W = 11.53 # connector width TW = 1.85 TL = 3.05 body_edge={} body_edge['left'] = (P-B)/2 body_edge['right'] = body_edge['left'] + B body_edge['top'] = -4.47 - offset_second_pad body_edge['bottom'] = body_edge['top'] + W bounding_box = body_edge.copy() bounding_box['top'] = body_edge['top'] - TW ################################## Pins ################################## kicad_mod.append(PadArray(pincount=pins, start=[0,0], x_spacing=pitch, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_THT)) kicad_mod.append(PadArray(pincount=pins, start=[0, -offset_second_pad], x_spacing=pitch, size=pad_size, drill=drill, shape=Pad.SHAPE_RECT, type=Pad.TYPE_THT, layers=Pad.LAYERS_THT)) d_small = 0.3 s_small = d_small + 2*min_annular_ring thermal_to_pad_edge = s_small/2 + 0.15 if params['thermals']: for xi in range(pins): n = xi + 1 pad_center_y = -offset_second_pad/2 pad_center_x = xi*pitch pad_h = offset_second_pad + pad_size[1] dx = (pad_size[0] - 2*thermal_to_pad_edge)/2 dy = (pad_h - 2*thermal_to_pad_edge)/4 #draw rectangle on F.Fab layer # kicad_mod.append(RectLine( # start=[pad_center_x - pad_l/2, pad_center_y - pad_size[1]/2], # end=[pad_center_x + pad_l/2, pad_center_y + pad_size[1]/2], # layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PadArray(center=[pad_center_x, pad_center_y], pincount=3, y_spacing=dy*2, drill=d_small, size=s_small, initial=n, increment=0, shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_THT, layers=Pad.LAYERS_THT)) kicad_mod.append(PadArray(center=[pad_center_x - dx, pad_center_y], pincount=5, y_spacing=dy, drill=d_small, size=s_small, initial=n, increment=0, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_THT)) kicad_mod.append(PadArray(center=[pad_center_x + dx, pad_center_y], pincount=5, y_spacing=dy, drill=d_small, size=s_small, initial=n, increment=0, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_THT)) if params['lock']: kicad_mod.append(Pad(at=[-ret_dx, ret_dy], type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, size=ret_size, drill=ret_drill, layers=Pad.LAYERS_THT)) kicad_mod.append(Pad(at=[P+ret_dx, ret_dy], type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, size=ret_size, drill=ret_drill, layers=Pad.LAYERS_THT)) kicad_mod.append(RectLine(start=[-pad_size[0]/2, -offset_second_pad-pad_size[1]/2], end=[pad_size[0]/2,pad_size[1]/2],offset=pad_silk_off, width=configuration['silk_line_width'], layer='B.SilkS')) ############################ Outline ############################## #kicad_mod.append(RectLine(start=[xl1, yt1], end=[xr1, yb1], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(RectLine( start=[body_edge['left'], body_edge['top']], end=[body_edge['right'], body_edge['bottom']], layer='F.Fab', width=configuration['fab_line_width'])) tab = [ {'x': P/2 - TL/2, 'y': body_edge['top']}, {'x': P/2 - TL/2, 'y': body_edge['top'] - TW}, {'x': P/2 + TL/2, 'y': body_edge['top'] - TW}, {'x': P/2 + TL/2, 'y': body_edge['top']} ] kicad_mod.append(PolygoneLine(polygone=tab, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(RectLine( start=[body_edge['left'], body_edge['top']], end=[body_edge['right'], body_edge['bottom']], offset = off, layer='F.SilkS', width=configuration['silk_line_width'])) tab = [ {'x': P/2 - TL/2 - off, 'y': body_edge['top'] - off}, {'x': P/2 - TL/2 - off, 'y': body_edge['top'] - TW - off}, {'x': P/2 + TL/2 + off, 'y': body_edge['top'] - TW - off}, {'x': P/2 + TL/2 + off, 'y': body_edge['top'] - off} ] kicad_mod.append(PolygoneLine(polygone=tab, layer='F.SilkS', width=configuration['silk_line_width'])) ############################ Pin 1 ################################ # Pin 1 designator pin1_sl = 2.4 pin1 = [ {'x': -pin1_sl/2, 'y': body_edge['top']}, {'x': 0, 'y': body_edge['top'] + pin1_sl/sqrt(2)}, {'x': pin1_sl/2, 'y': body_edge['top']} ] kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.Fab', width=configuration['fab_line_width'])) pin1_sl = 0.8 yp1 = body_edge['top'] - off - 0.3 pin1 = [ {'x': 0,'y': yp1}, {'x': pin1_sl/2,'y': yp1-pin1_sl/sqrt(2)}, {'x': -pin1_sl/2,'y': yp1-pin1_sl/sqrt(2)}, {'x': 0,'y': yp1}, ] kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.SilkS', width=configuration['silk_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pincount, configuration): mpn = part_code.format(n=pincount) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount//2, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Pins ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pincount, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) kicad_mod.setAttribute('smd') # calculate working values pad_x_spacing = pitch pad_y_spacing = 4.4 + 1.1 pad_width = 0.3 pad_height = 1.1 pad_x_span = (pad_x_spacing * ((pincount / 2) - 1)) h_body_width = 5.0 / 2.0 h_body_length = (pad_x_span / 2.0) + 1.05 + 0.5 fab_width = configuration['fab_line_width'] #outline_x = 1.2 outline_x = h_body_length - (pad_x_span / 2.0) - pad_width/2 - (configuration['silk_pad_clearance'] + configuration['silk_line_width']/2) marker_y = 0.8 silk_width = configuration['silk_line_width'] nudge = configuration['silk_fab_offset'] courtyard_width = configuration['courtyard_line_width'] courtyard_precision = configuration['courtyard_grid'] courtyard_clearance = configuration['courtyard_offset']['connector'] courtyard_x = roundToBase(h_body_length + courtyard_clearance, courtyard_precision) courtyard_y = roundToBase((pad_y_spacing + pad_height) / 2.0 + courtyard_clearance, courtyard_precision) # create pads kicad_mod.append(PadArray(pincount=pincount//2, x_spacing=pad_x_spacing, y_spacing=0,\ center=[0,-pad_y_spacing/2.0], initial=1, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[pad_width, pad_height],\ layers=Pad.LAYERS_SMT)) kicad_mod.append(PadArray(pincount=pincount//2, x_spacing=pad_x_spacing, y_spacing=0,\ center=[0,pad_y_spacing/2.0], initial=2, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[pad_width, pad_height],\ layers=Pad.LAYERS_SMT)) # create fab outline and pin 1 marker kicad_mod.append(RectLine(start=[-h_body_length, -h_body_width], end=[h_body_length, h_body_width], layer='F.Fab', width=fab_width)) body_edge={ 'left':-h_body_length, 'top':-h_body_width } body_edge['right'] = -body_edge['left'] body_edge['bottom'] = -body_edge['top'] kicad_mod.append(Line(start=[-h_body_length+outline_x, -h_body_width-nudge], end=[-h_body_length+outline_x, -h_body_width-marker_y], layer='F.Fab', width=fab_width)) # create silkscreen outline and pin 1 marker left_outline = [[-h_body_length+outline_x, h_body_width+nudge], [-h_body_length-nudge, h_body_width+nudge], [-h_body_length-nudge, -h_body_width-nudge],\ [-h_body_length+outline_x, -h_body_width-nudge], [-h_body_length+outline_x, -h_body_width-marker_y]] right_outline = [[h_body_length-outline_x, h_body_width+nudge], [h_body_length+nudge, h_body_width+nudge], [h_body_length+nudge, -h_body_width-nudge],\ [h_body_length-outline_x, -h_body_width-nudge]] kicad_mod.append(PolygoneLine(polygone=left_outline, layer='F.SilkS', width=silk_width)) kicad_mod.append(PolygoneLine(polygone=right_outline, layer='F.SilkS', width=silk_width)) # create courtyard kicad_mod.append(RectLine(start=[-courtyard_x, -courtyard_y], end=[courtyard_x, courtyard_y], layer='F.CrtYd', width=courtyard_width)) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':-courtyard_y, 'bottom':+courtyard_y}, fp_name=footprint_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def make_module(pins_per_row, configuration): pad_silk_off = configuration['silk_line_width']/2 + configuration['silk_pad_clearance'] off = configuration['silk_fab_offset'] mpn = part_code.format(pins_per_row*2) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) footprint_name = footprint_name.replace("__",'_') kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Circuits ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) Wi = 4.8 T = 2.8 W = Wi + T body_edge = {} body_edge['right'] = pitch_row + 2.2 + T body_edge['left'] = body_edge['right'] - W A = (pins_per_row-1)*pitch B = (A - 8) if A >= 8 else 0 C = (A - 4.6) if A >= 4.6 else 0 D = A + 2.6 E = A + 3.6 body_edge['top'] = -(E - A)/2 body_edge['bottom'] = body_edge['top'] + E bounding_box = body_edge.copy() ############################## Pins ############################### optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for row_idx in range(2): kicad_mod.append(PadArray( initial=ROW_NAMES[row_idx]+'1', start=[(row_idx)*pitch_row, 0], y_spacing=pitch, pincount=pins_per_row, increment=incrementPadNumber, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=pad_shape, layers=Pad.LAYERS_THT, tht_pad1_id=ROW_NAMES[0]+'1', **optional_pad_params)) ############################ Outline ############################## kicad_mod.append(RectLine( start=[body_edge['left'], body_edge['top']], end=[body_edge['right'], body_edge['bottom']], layer="F.Fab", width=configuration['fab_line_width'] )) r_no_silk = max(pad_size)/2 + pad_silk_off dx = abs(body_edge['left']) + off pin_center_silk_y = 0 if dx >= r_no_silk else sqrt(r_no_silk**2-dx**2) pin1_center_silk_y = pad_size[1]/2 + pad_silk_off YCb = A/2+C/2 YCt = A/2-C/2 YBb = A/2+B/2 poly_silk_b = [ {'x': body_edge['left']-off, 'y': body_edge['bottom']+off}, {'x': body_edge['right']+off, 'y': body_edge['bottom']+off}, {'x': body_edge['right']+off, 'y': YCb}, ] if C > 0: poly_silk_b.extend([ {'x': body_edge['right']-T, 'y': YCb}, {'x': body_edge['right']-T, 'y': A/2}, ]) kicad_mod.append(PolygoneLine(polygone=poly_silk_b, layer="F.SilkS", width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly_silk_b, y_mirror=A/2, layer="F.SilkS", width=configuration['silk_line_width'])) if pin_center_silk_y == 0: kicad_mod.append(Line( start=[body_edge['left']-off, body_edge['top']], end=[body_edge['left']-off, body_edge['bottom']], layer="F.SilkS", width=configuration['silk_line_width'] )) else: kicad_mod.append(Line( start=[body_edge['left']-off, body_edge['top']-off], end=[body_edge['left']-off, -pin1_center_silk_y], layer="F.SilkS", width=configuration['silk_line_width'] )) kicad_mod.append(Line( start=[body_edge['left']-off, pin1_center_silk_y], end=[body_edge['left']-off, pitch-pin_center_silk_y], layer="F.SilkS", width=configuration['silk_line_width'] )) kicad_mod.append(Line( start=[body_edge['left']-off, A+pin_center_silk_y], end=[body_edge['left']-off, body_edge['bottom']+off], layer="F.SilkS", width=configuration['silk_line_width'] )) for i in range(1, pins_per_row-1): yt = i*pitch + pin_center_silk_y yb = (i+1)*pitch - pin_center_silk_y kicad_mod.append(Line( start=[body_edge['left']-off, yt], end=[body_edge['left']-off, yb], layer="F.SilkS", width=configuration['silk_line_width'] )) x1 = body_edge['right']-T pin_w = 0.5 pin_L = 2.7 pin_chamfer_x = pin_w/3 if B>0: x2 = x1 + 2 # estimated from drawing poly = [ {'x': x2, 'y':YCb}, {'x': x2, 'y':YBb+pin_w/2} ] kicad_mod.append(PolygoneLine(polygone=poly, layer="F.SilkS", width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly, y_mirror=A/2, layer="F.SilkS", width=configuration['silk_line_width'])) #pins if C>0: for i in range(pins_per_row): ypc = i*pitch x3 = x1 + pin_L x2 = x3 - pin_chamfer_x if ypc - pin_w/2 >= YCt and ypc + pin_w/2 <= YCb: pin_poly = [ {'x': x1, 'y': ypc-pin_w/2}, {'x': x2, 'y': ypc-pin_w/2}, {'x': x3, 'y': ypc}, {'x': x2, 'y': ypc+pin_w/2}, {'x': x1, 'y': ypc+pin_w/2} ] kicad_mod.append(PolygoneLine(polygone=pin_poly, layer="F.SilkS", width=configuration['silk_line_width'])) ########################### Pin 1 ################################# p1s_sl = 2 p1s_off = off + 0.3 kicad_mod.append(PolygoneLine( polygone=[ {'x': body_edge['left'] + p1s_sl, 'y': body_edge['top'] - p1s_off}, {'x': body_edge['left'] - p1s_off, 'y': body_edge['top'] - p1s_off}, {'x': body_edge['left'] - p1s_off, 'y': body_edge['top'] + p1s_sl} ], layer="F.SilkS", width=configuration['silk_line_width'])) p1f_sl = 1 kicad_mod.append(PolygoneLine( polygone=[ {'x': body_edge['left'], 'y': p1f_sl/2}, {'x': body_edge['left'] + p1f_sl/sqrt(2), 'y': 0}, {'x': body_edge['left'], 'y': -p1f_sl/2} ], layer="F.Fab", width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins_per_row, variant_param, configuration): silk_pad_off = configuration['silk_pad_clearance']+configuration['silk_line_width']/2 off = configuration['silk_fab_offset'] number_of_rows = variant_param['number_of_rows'] pad_size = [row - pad_to_pad_clearance, pitch - pad_to_pad_clearance] if number_of_rows == 1: pad_size[0] = drill + 2*max_annular_ring if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring if pad_size[1] - drill < 2*min_annular_ring: pad_size[1] = drill + 2*min_annular_ring if pad_size[1] - drill > 2*max_annular_ring: pad_size[1] = drill + 2*max_annular_ring pad_shape = Pad.SHAPE_OVAL if pad_size[0] == pad_size[1]: pad_shape = Pad.SHAPE_CIRCLE first_to_last_pad_y = (pins_per_row-1)*pitch first_to_last_pad_x = (number_of_rows-1)*row peg_pos = [[0, -peg_to_nearest_pin if variant_param['style'] != 'in_line' else (first_to_last_pad_y + peg_to_nearest_pin)]] if variant_param['number_pegs'] == 2: peg_pos.append([0, first_to_last_pad_y + peg_to_nearest_pin]) mpn = variant_param['part_code'][pins_per_row*number_of_rows].format(n=pins_per_row*2) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=man_short_fp_name, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) descr_format_str = "Molex {:s}, old mpn/engineering number: {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription(descr_format_str.format( series_long, mpn, pins_per_row, datasheet)) tags = configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=man_short_fp_name, entry=configuration['entry_direction'][orientation]) kicad_mod.setTags(tags) x1 = -(variant_param['width']-first_to_last_pad_x)/2 x2 = x1 + variant_param['width'] body_lenght = (9.83-pitch)+first_to_last_pad_y y1 = -(body_lenght - first_to_last_pad_y)/2 y2 = y1 + body_lenght peg_predrusion = 2.591 # from 3d model peg_d = 3.94 # from 3d model, rounded peg_from_body = 0.66 # from 3d model peg_conn_w = 1.6 # from 3d model, rounded stabalizer_width = 2.54 # from 3d model stabalizer_len = 2.591 # from 3d model TW = 3 # from 3d model, rounded TL = 1.3 # from 3d model, rounded BW = 1.14 # from 3d model, rounded BL = 0.76 # from 3d model, rounded #calculate fp dimensions body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = {} if variant_param['style'] != 'in_line': bounding_box['top'] = peg_pos[0][1]-peg_drill/2 bounding_box['left'] = body_edge['left'] - TL bounding_box['right'] = body_edge['right'] + BL if variant_param['number_pegs'] == 2: bounding_box['bottom'] = peg_pos[1][1]+peg_drill/2 else: bounding_box['bottom'] = body_edge['bottom'] + peg_predrusion else: bounding_box['bottom'] = peg_pos[0][1]+peg_drill/2 bounding_box['top'] = body_edge['top'] - TL bounding_box['left'] = body_edge['left'] - BL bounding_box['right'] = body_edge['right'] #generate the pads optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for row_idx in range(variant_param['number_of_rows']): initial = row_idx*pins_per_row + 1 kicad_mod.append(PadArray( pincount=pins_per_row, initial=initial, start=[row_idx*row, 0], y_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) for peg in peg_pos: kicad_mod.append(Pad(at=peg, type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) #draw the outline of the shape kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2], layer='F.Fab',width=configuration['fab_line_width'])) dy = peg_to_nearest_pin + body_edge['top'] - off if dy < (peg_drill/2 + silk_pad_off): dx = sqrt((peg_drill/2 + silk_pad_off)**2-dy**2) else: dx = 0 sl_poly=[ {'x': 0, 'y': body_edge['top']-off}, {'x': body_edge['left']-off, 'y': body_edge['top']-off}, {'x': body_edge['left']-off, 'y': body_edge['bottom']+off}, {'x': 0, 'y': body_edge['bottom']+off}, ] sr_poly=[ {'x': 0, 'y': body_edge['top']-off}, {'x': body_edge['right']+off, 'y': body_edge['top']-off}, {'x': body_edge['right']+off, 'y': body_edge['bottom']+off}, {'x': 0, 'y': body_edge['bottom']+off}, ] if variant_param['style'] == 'in_line' or variant_param['number_pegs'] == 2: sl_poly[3]['x']=-dx sr_poly[3]['x']=dx if variant_param['style'] != 'in_line': sl_poly[0]['x']=-dx sr_poly[0]['x']=dx kicad_mod.append(PolygoneLine(polygone=sl_poly, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=sr_poly, layer='F.SilkS', width=configuration['silk_line_width'])) def peg_outline(kicad_mod, center_y): edge = body_edge['top'] if center_y < 0 else body_edge['bottom'] dir = -1 if center_y < 0 else 1 sy=edge + dir*peg_from_body y3 = edge +dir*peg_predrusion kicad_mod.append(Line( start=[peg_conn_w/2, edge], end=[peg_conn_w/2, sy], layer='F.Fab',width=configuration['fab_line_width'] )) kicad_mod.append(Line( start=[-peg_conn_w/2, edge], end=[-peg_conn_w/2, sy], layer='F.Fab',width=configuration['fab_line_width'] )) dy = center_y - sy sx = sqrt((peg_d/2)**2-dy**2) dy2 = y3 - center_y ex = sqrt((peg_d/2)**2-dy2**2) a1 = degrees(asin(abs(dy2)/(peg_d/2))) a2 = degrees(asin(abs(dy)/(peg_d/2))) a = a1+a2 kicad_mod.append(Line( start=[sx, sy], end=[-sx, sy], layer='F.Fab',width=configuration['fab_line_width'] )) kicad_mod.append(Line( start=[ex, y3], end=[-ex, y3], layer='F.Fab',width=configuration['fab_line_width'] )) kicad_mod.append(Arc(center=[0,center_y], start=[sx,sy], angle=dir*a, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Arc(center=[0,center_y], start=[-sx,sy], angle=-a*dir, layer='F.Fab', width=configuration['fab_line_width'])) # #draw the outline of the tab if variant_param['style'] == 'in_line': tab_poly = [ {'x': -TW/2,'y': body_edge['top']}, {'x': -TW/2,'y': body_edge['top']-TL}, {'x': TW/2,'y': body_edge['top']-TL}, {'x': TW/2,'y': body_edge['top']}, ] kicad_mod.append(PolygoneLine(polygone=tab_poly, layer='F.Fab', width=configuration['fab_line_width'])) tab_poly = [ {'x': -TW/2-off,'y': body_edge['top']-off}, {'x': -TW/2-off,'y': body_edge['top']-TL-off}, {'x': TW/2+off,'y': body_edge['top']-TL-off}, {'x': TW/2+off,'y': body_edge['top']-off}, ] kicad_mod.append(PolygoneLine(polygone=tab_poly, layer='F.SilkS', width=configuration['silk_line_width'])) b_poly = [ {'x': body_edge['left'],'y': body_edge['top']}, {'x': body_edge['left']-BL,'y': body_edge['top']}, {'x': body_edge['left']-BL,'y': body_edge['top']+BW}, {'x': body_edge['left'],'y': body_edge['top']+BW}, ] kicad_mod.append(PolygoneLine(polygone=b_poly, layer='F.Fab', width=configuration['fab_line_width'])) b_poly = [ {'x': body_edge['left']-off,'y': body_edge['top']-off}, {'x': body_edge['left']-BL-off,'y': body_edge['top']-off}, {'x': body_edge['left']-BL-off,'y': body_edge['top']+BW+off}, {'x': body_edge['left']-off,'y': body_edge['top']+BW+off}, ] kicad_mod.append(PolygoneLine(polygone=b_poly, layer='F.SilkS', width=configuration['silk_line_width'])) for i in range(pins_per_row): yc = i*pitch+pitch/2 b_poly = [ {'x': body_edge['left'],'y': yc - BW/2}, {'x': body_edge['left']-BL,'y': yc - BW/2}, {'x': body_edge['left']-BL,'y': yc + BW/2}, {'x': body_edge['left'],'y': yc + BW/2}, ] kicad_mod.append(PolygoneLine(polygone=b_poly, layer='F.Fab', width=configuration['fab_line_width'])) b_poly = [ {'x': body_edge['left']-off,'y': yc - BW/2-off}, {'x': body_edge['left']-BL-off,'y': yc - BW/2-off}, {'x': body_edge['left']-BL-off,'y': yc + BW/2+off}, {'x': body_edge['left']-off,'y': yc + BW/2+off}, ] kicad_mod.append(PolygoneLine(polygone=b_poly, layer='F.SilkS', width=configuration['silk_line_width'])) else: cy = first_to_last_pad_y/2 tab_poly = [ {'x': body_edge['left'],'y': cy-TW/2}, {'x': body_edge['left']-TL,'y': cy-TW/2}, {'x': body_edge['left']-TL,'y': cy+TW/2}, {'x': body_edge['left'],'y': cy+TW/2}, ] kicad_mod.append(PolygoneLine(polygone=tab_poly, layer='F.Fab', width=configuration['fab_line_width'])) tab_poly = [ {'x': body_edge['left']-off,'y': cy-TW/2-off}, {'x': body_edge['left']-TL-off,'y': cy-TW/2-off}, {'x': body_edge['left']-TL-off,'y': cy+TW/2+off}, {'x': body_edge['left']-off,'y': cy+TW/2+off}, ] kicad_mod.append(PolygoneLine(polygone=tab_poly, layer='F.SilkS', width=configuration['silk_line_width'])) b_poly = [ {'x': body_edge['right'],'y': body_edge['top']}, {'x': body_edge['right']+BL,'y': body_edge['top']}, {'x': body_edge['right']+BL,'y': body_edge['top']+BW}, {'x': body_edge['right'],'y': body_edge['top']+BW}, ] kicad_mod.append(PolygoneLine(polygone=b_poly, layer='F.Fab', width=configuration['fab_line_width'])) b_poly = [ {'x': body_edge['right']+off,'y': body_edge['top']-off}, {'x': body_edge['right']+BL+off,'y': body_edge['top']-off}, {'x': body_edge['right']+BL+off,'y': body_edge['top']+BW+off}, {'x': body_edge['right']+off,'y': body_edge['top']+BW+off}, ] kicad_mod.append(PolygoneLine(polygone=b_poly, layer='F.SilkS', width=configuration['silk_line_width'])) if len(peg_pos) == 1: center_stabalizer = (number_of_rows-1)*row stab_x1 = center_stabalizer - stabalizer_width/2 stab_x2 = center_stabalizer + stabalizer_width/2 stab_y1 = body_edge['bottom'] + stabalizer_len stab_poly = [ {'x': stab_x1,'y': body_edge['bottom']}, {'x': stab_x1,'y': stab_y1}, {'x': stab_x2,'y': stab_y1}, {'x': stab_x2,'y': body_edge['bottom']} ] kicad_mod.append(PolygoneLine(polygone=stab_poly, layer='F.Fab', width=configuration['fab_line_width'])) stab_poly = [ {'x': stab_x1-off,'y': body_edge['bottom']+off}, {'x': stab_x1-off,'y': stab_y1+off}, {'x': stab_x2+off,'y': stab_y1+off}, {'x': stab_x2+off,'y': body_edge['bottom']+off} ] kicad_mod.append(PolygoneLine(polygone=stab_poly, layer='F.SilkS', width=configuration['silk_line_width'])) for i in range(pins_per_row): yc = i*pitch+pitch/2 b_poly = [ {'x': body_edge['right'],'y': yc - BW/2}, {'x': body_edge['right']+BL,'y': yc - BW/2}, {'x': body_edge['right']+BL,'y': yc + BW/2}, {'x': body_edge['right'],'y': yc + BW/2}, ] kicad_mod.append(PolygoneLine(polygone=b_poly, layer='F.Fab', width=configuration['fab_line_width'])) b_poly = [ {'x': body_edge['right']+off,'y': yc - BW/2-off}, {'x': body_edge['right']+BL+off,'y': yc - BW/2-off}, {'x': body_edge['right']+BL+off,'y': yc + BW/2+off}, {'x': body_edge['right']+off,'y': yc + BW/2+off}, ] kicad_mod.append(PolygoneLine(polygone=b_poly, layer='F.SilkS', width=configuration['silk_line_width'])) for peg in peg_pos: peg_outline(kicad_mod, peg[1]) if variant_param['style'] != 'in_line': L = 2.5 O = off + 0.3 dy = peg_to_nearest_pin + body_edge['top'] - O if dy < (peg_drill/2 + silk_pad_off): dx = sqrt((peg_drill/2 + silk_pad_off)**2-dy**2) pin = [ {'x': -dx,'y': body_edge['top'] - O}, {'x': body_edge['left'] - O,'y': body_edge['top'] - O}, {'x': body_edge['left'] - O,'y': body_edge['top'] + L} ] else: sl = 0.6 xs = body_edge['left']-(off + 0.3) pin = [ {'x': xs,'y': 0}, {'x': xs - sl/sqrt(2),'y': sl/2}, {'x': xs - sl/sqrt(2),'y': -sl/2}, {'x': xs,'y': 0} ] kicad_mod.append(PolygoneLine(polygone=pin, layer="F.SilkS", width=configuration['silk_line_width'])) sl = 2 pin = [ {'x': body_edge['left'],'y': -sl/2}, {'x': body_edge['left'] +sl/sqrt(2),'y': 0}, {'x': body_edge['left'],'y': sl/2} ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# CrtYd_offset = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] cx1 = roundToBase(bounding_box['left'] - CrtYd_offset, CrtYd_grid) cy1 = roundToBase(bounding_box['top'] - CrtYd_offset, CrtYd_grid) cx2 = roundToBase(bounding_box['right'] + CrtYd_offset, CrtYd_grid) cy2 = roundToBase(bounding_box['bottom'] + CrtYd_offset, CrtYd_grid) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='right') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=man_lib) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins, variant, configuration): V=variant_params[variant]['V'] #calculate fp dimensions A = (pins - 1) * pitch B = A + 4.9 #Thickness of connector T = 11.5 #corners x1 = -2.45 x2 = x1 + B x_mid = (x1 + x2) / 2 y2 = V y1= y2 - T #y at which the plastic tabs end y3 = y2 - 7 #generate the name mpn = part_base.format(n=pins, variant=variant) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) if pins == 2: drill = 1.0 else: drill = 0.95 pad_size = [pitch - pad_to_pad_clearance, drill + 2*pad_copper_y_solder_length] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring #generate the pads ############################# Pads ################################## # kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, # at=[0, 0], size=pad_size, # drill=drill, layers=Pad.LAYERS_THT)) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(initial=1, start=[0, 0], x_spacing=pitch, pincount=pincount, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT, **optional_pad_params)) #draw the courtyard cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #offset the outline around the connector off = configuration['silk_fab_offset'] xo1 = x1 - off yo1 = y1 - off xo2 = x2 + off yo2 = y2 + off #thickness of the notches notch = 1.5 #wall thickness of the outline wall = 1.2 #draw the outline of the connector outline = [ {'x': x_mid,'y': yo2}, {'x': xo1,'y': yo2}, {'x': xo1,'y': yo1}, {'x': xo1+wall+2*off,'y': yo1}, {'x': xo1+wall+2*off,'y': y3 - off}, {'x': A/2,'y': y3 - off}, #{'x': -1.1,'y': y3 + off} ] if variant == 'A-1': outline = outline[:-1] kicad_mod.append(PolygoneLine(polygone=outline, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=outline, x_mirror=x_mid, layer='F.SilkS', width=configuration['silk_line_width'])) outline = [ {'x': x_mid,'y': y2}, {'x': x1,'y': y2}, {'x': x1,'y': y1}, {'x': x1+wall,'y': y1}, {'x': x1+wall,'y': y3}, {'x': A/2,'y': y3}, #{'x': -1.1,'y': y3 + off} ] kicad_mod.append(PolygoneLine(polygone=outline, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=outline, x_mirror=x_mid, layer='F.Fab', width=configuration['fab_line_width'])) #draw the pinsss for i in range(pins): x = i * pitch w = 0.25 kicad_mod.append(RectLine(start=[x-w,y3+1], end=[x+w,y2-0.5], layer='F.SilkS', width=configuration['silk_line_width'])) #add pin-1 designator px = 0 py = -1.5 m = 0.3 pin1 = [ {'x': px,'y': py}, {'x': px-m,'y': py-2*m}, {'x': px+m,'y': py-2*m}, {'x': px,'y': py}, ] kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.SilkS', width=configuration['silk_line_width'])) if fab_pin1_marker_type == 1: kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.Fab', width=configuration['fab_line_width'])) if fab_pin1_marker_type == 2: fab_marker_left = -fab_first_marker_w/2.0 fab_marker_bottom = y3 - fab_first_marker_h poly_fab_marker = [ {'x':fab_marker_left, 'y':y3}, {'x':0, 'y':fab_marker_bottom}, {'x':fab_marker_left + fab_first_marker_w, 'y':y3} ] kicad_mod.append(PolygoneLine(polygone=poly_fab_marker, layer='F.Fab', width=configuration['fab_line_width'])) ######################### Text Fields ############################### text_center_y = 'center' body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position=text_center_y) model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins, configuration): silk_pad_clearance = configuration[ 'silk_pad_clearance'] + configuration['silk_line_width'] / 2 mpn = part_base.format(n=pins) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format( man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad="", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription( "JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator" .format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format( series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate fp dimensions A = (pins - 1) * pitch B = A + 3.9 #coordinate locations # y1 x1 x3 x4 x2 # y2 | | | | # y3 | |1||2||3||4||5||6||7| | # y4 |_| |__| # | | # y5 |__________________| # y6 || || || || || || || #generate pads pad_size = [ pitch - pad_to_pad_clearance, drill + 2 * pad_copper_y_solder_length ] if pad_size[0] - drill < 2 * min_annular_ring: pad_size[0] = drill + 2 * min_annular_ring if pad_size[0] - drill > 2 * pad_copper_y_solder_length: pad_size[0] = drill + 2 * pad_copper_y_solder_length shape = Pad.SHAPE_OVAL if pad_size[0] == pad_size[1]: shape = Pad.SHAPE_CIRCLE optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append( PadArray(pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) #draw the component outline x1 = A / 2 - B / 2 x2 = x1 + B x3 = -0.9 x4 = pitch * (pins - 1) + 0.9 y6 = 13.4 y4 = y6 - 7.7 y1 = y4 - 7.7 y2 = y1 + 2 y3 = y1 + 4.5 y5 = y3 + 9.4 body_edge = {'left': x1, 'right': x2, 'top': y4, 'bottom': y5} #draw shroud outline on F.Fab layer kicad_mod.append( RectLine(start=[x3, y3], end=[x4, y5], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append( PolygoneLine(polygone=[{ 'x': x4 - 0.2, 'y': y3 }, { 'x': x4 - 0.2, 'y': y1 }, { 'x': x2, 'y': y1 }, { 'x': x2, 'y': y4 }, { 'x': x4, 'y': y4 }], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append( PolygoneLine(polygone=[{ 'x': x3, 'y': y4 }, { 'x': x1, 'y': y4 }, { 'x': x1, 'y': y1 }, { 'x': x3 + 0.2, 'y': y1 }, { 'x': x3 + 0.2, 'y': y3 }], layer='F.Fab', width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(x1 - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y1 - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2 + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y6 + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append( RectLine(start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #draw pin outlines and plastic between pins on F.Fab (pin width is 1.4mm, so 0.7mm is half the pin width) for pin in range(pins): kicad_mod.append( PolygoneLine(polygone=[{ 'x': pin * pitch - 0.7, 'y': y5 }, { 'x': pin * pitch - 0.7, 'y': y6 }, { 'x': pin * pitch + 0.7, 'y': y6 }, { 'x': pin * pitch + 0.7, 'y': y5 }], layer='F.Fab', width=configuration['fab_line_width'])) if pin < (pins - 1): kicad_mod.append( PolygoneLine(polygone=[{ 'x': pin * pitch + 1.38, 'y': y3 }, { 'x': pin * pitch + 1.38, 'y': y2 }, { 'x': pin * pitch + 2.58, 'y': y2 }, { 'x': pin * pitch + 2.58, 'y': y3 }], layer='F.Fab', width=configuration['fab_line_width'])) #draw pin1 mark on F.Fab kicad_mod.append( PolygoneLine(polygone=[{ 'x': -0.8, 'y': y3 }, { 'x': 0, 'y': y3 + 0.8 }, { 'x': 0.8, 'y': y3 }], layer='F.Fab', width=configuration['fab_line_width'])) #draw silk outlines off = configuration['silk_fab_offset'] x1 -= off y1 -= off x2 += off y2 -= off x3 -= off y3 -= off x4 += off y4 += off y5 += off y6 += off p1s_x = pad_size[0] / 2 + silk_pad_clearance p1s_y = pad_size[1] / 2 + silk_pad_clearance #silk around shroud; silk around stabilizers; silk long shroud between pin and shroud for first and last pins #note that half of pin width is 0.7mm, so adding 0.12mm silk offset gives 0.82mm about pin center; 0.44 is double silk offset in caeses where 'off' is in the wrong direction kicad_mod.append( PolygoneLine(polygone=[{ 'x': x3, 'y': y4 }, { 'x': x3, 'y': y5 }, { 'x': -0.82, 'y': y5 }], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=[{ 'x': x4 - 0.44, 'y': -1.6 }, { 'x': x4 - 0.44, 'y': y1 }, { 'x': x2, 'y': y1 }, { 'x': x2, 'y': y4 }, { 'x': x4, 'y': y4 }], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=[{ 'x': x4 - 0.44, 'y': y3 }, { 'x': x4 - 0.44, 'y': 1.6 }], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=[{ 'x': x3, 'y': y4 }, { 'x': x1, 'y': y4 }, { 'x': x1, 'y': y1 }, { 'x': x3 + 0.44, 'y': y1 }, { 'x': x3 + 0.44, 'y': -p1s_y }], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=[{ 'x': x3 + 0.44, 'y': 1.7 }, { 'x': x3 + 0.44, 'y': y3 }], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=[{ 'x': (pins - 1) * pitch + 0.82, 'y': y5 }, { 'x': x4, 'y': y5 }, { 'x': x4, 'y': y4 }], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=[{ 'x': -0.58, 'y': y3 }, { 'x': 1.26, 'y': y3 }], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=[{ 'x': pin * pitch - 1.26, 'y': y3 }, { 'x': pin * pitch + 0.58, 'y': y3 }], layer='F.SilkS', width=configuration['silk_line_width'])) #per-pin silk #pin silk for pin in range(pins): kicad_mod.append( PolygoneLine(polygone=[{ 'x': pin * pitch - 0.82, 'y': y5 }, { 'x': pin * pitch - 0.82, 'y': y6 }, { 'x': pin * pitch + 0.82, 'y': y6 }, { 'x': pin * pitch + 0.82, 'y': y5 }], layer='F.SilkS', width=configuration['silk_line_width'])) #silk around plastic between pins 1 and 2 (since pin 1 is rectangular, it seends to be handled a bit differently to meet ~0.2mm pin-silk clearance) if pin == 0: kicad_mod.append( PolygoneLine(polygone=[{ 'x': pin * pitch + 1.26, 'y': y3 }, { 'x': pin * pitch + 1.26, 'y': 1.7 }], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=[{ 'x': pin * pitch + pad_size[0] / 2 + silk_pad_clearance, 'y': y2 }, { 'x': (pin + 1) * pitch - pad_size[0] / 2 - silk_pad_clearance, 'y': y2 }], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=[{ 'x': pin * pitch + 2.7, 'y': 1 }, { 'x': pin * pitch + 2.7, 'y': y3 }], layer='F.SilkS', width=configuration['silk_line_width'])) #silk around plastic between other pins; silk along shroud between pin and shroud for other pins if (pin > 0) and (pin < (pins - 1)): kicad_mod.append( PolygoneLine(polygone=[{ 'x': pin * pitch + 1.26, 'y': y3 }, { 'x': pin * pitch + 1.26, 'y': 1 }], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=[{ 'x': pin * pitch + pad_size[0] / 2 + silk_pad_clearance, 'y': y2 }, { 'x': (pin + 1) * pitch - pad_size[0] / 2 - silk_pad_clearance, 'y': y2 }], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=[{ 'x': pin * pitch + 2.7, 'y': 1 }, { 'x': pin * pitch + 2.7, 'y': y3 }], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=[{ 'x': pin * pitch - 1.26, 'y': y3 }, { 'x': pin * pitch + 1.26, 'y': y3 }], layer='F.SilkS', width=configuration['silk_line_width'])) #silk between pins at locking end of shroud if (pin > 0) and (pin < pins): kicad_mod.append( PolygoneLine(polygone=[{ 'x': pin * pitch - 3.14, 'y': y5 }, { 'x': pin * pitch - 0.82, 'y': y5 }], layer='F.SilkS')) #add pin1 marker on F.FilkS (magic numbers intended to hit ~0.3mm copper-silk clearance) kicad_mod.append( PolygoneLine(polygone=[{ 'x': 0, 'y': -p1s_y }, { 'x': -p1s_x, 'y': -p1s_y }, { 'x': -p1s_x, 'y': 0 }], layer='F.SilkS', width=configuration['silk_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={ 'top': cy1, 'bottom': cy2 }, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pincount, configuration): mpn = "S{pincount}B-EH".format(pincount=pincount) #JST part number format string orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) if pincount == 2: drill = 1.0 else: drill = 0.95 pad_size = [pitch - pad_to_pad_clearance, drill + 2*pad_copper_y_solder_length] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring # create pads # kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, # at=[0, 0], size=pad_size, # drill=drill, layers=Pad.LAYERS_THT)) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(initial=1, start=[0, 0], x_spacing=pitch, pincount=pincount, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT, **optional_pad_params)) A = (pincount - 1) * pitch B = A + 5.0 x1 = -2.5 y1 = -6.7 x2 = x1 + B y21 = y1 + 6 y2 = 1.5 x11 = x1+1 x21 = x2-1 body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} #draw the main outline around the footprint # kicad_mod.append(RectLine(start={'x':x1,'y':y1}, end={'x':x2,'y':y2}, layer='F.Fab', width=configuration['fab_line_width'])) fab_outline=[ {'x': x11, 'y': y21}, {'x': x11, 'y': y2}, {'x': x1, 'y': y2}, {'x': x1, 'y': y1}, {'x': x2, 'y': y1}, {'x': x2, 'y': y2}, {'x': x21, 'y': y2}, {'x': x21, 'y': y21}, {'x': x11, 'y': y21} ] kicad_mod.append(PolygoneLine(polygone=fab_outline, layer='F.Fab', width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ########################### SilkS ################################# #line offset off = configuration['silk_fab_offset'] x1 -= off y1 -= off x2 += off y2 += off T = 1 + 2*configuration['silk_fab_offset'] y3 = y21 + off kicad_mod.append(PolygoneLine(polygone=[{'x':x1+T,'y':y3}, {'x':x1+T,'y':y2}, {'x':x1,'y':y2}, {'x':x1,'y':y1}, {'x':x2,'y':y1}, {'x':x2,'y':y2}, {'x':x2-T,'y':y2}, {'x':x2-T,'y':y3}], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=[{'x':x1,'y':y1+T}, {'x':x1+T,'y':y1+T}, {'x':x1+T,'y':y3}, {'x':x1,'y':y3}], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=[{'x':x2,'y':y1+T}, {'x':x2-T,'y':y1+T}, {'x':x2-T,'y':y3}, {'x':x2,'y':y3}], layer='F.SilkS', width=configuration['silk_line_width'])) #add pictures of pins #pin-width w #pin-length l w = 0.32 l = 3.5 py = y3-1 kicad_mod.append(Line(start={'x':x1+T,'y':py},end={'x':x2-T,'y':py}, layer='F.SilkS', width=configuration['silk_line_width'])) # kicad_mod.append(Line(start={'x':x1+T,'y':py+1},end={'x':x2-T,'y':py+1}, layer='F.SilkS', width=configuration['silk_line_width'])) pcs_x = pad_size[0]/2 + configuration['silk_pad_clearance'] + configuration['silk_line_width'] for p in range(pincount): px = p * pitch kicad_mod.append(PolygoneLine(polygone=[{'x': px,'y': py}, {'x': px-w,'y': py}, {'x': px-w,'y': py-l+0.25*w}, {'x': px,'y': py-l}, {'x': px+w,'y': py-l+0.25*w}, {'x': px+w,'y': py}, {'x': px,'y': py}], layer='F.SilkS', width=configuration['silk_line_width'])) if p < pincount-1: kicad_mod.append(Line(start=[px + pcs_x, y3], end=[px + pitch - pcs_x, y3], layer='F.SilkS', width=configuration['silk_line_width'])) ######################### Pin 1 marker ############################## xm = 0 ym = 1.5 m = 0.3 pin = [{'x':xm,'y':ym}, {'x':xm - m,'y':ym + 2 * m}, {'x':xm + m,'y':ym + 2 * m}, {'x':xm,'y':ym}] kicad_mod.append(PolygoneLine(polygone=pin, layer='F.SilkS', width=configuration['silk_line_width'])) sl = 1 pin = [ {'x':xm-sl/2,'y':y21}, {'x':xm,'y':y21-sl/sqrt(2)}, {'x':xm+sl/2,'y':y21} ] kicad_mod.append(PolygoneLine(polygone=pin,layer='F.Fab', width=configuration['fab_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generateFootprint(self, device_params): device_dimensions = LGA.deviceDimensions(device_params) size_x = device_dimensions['body_size_x'].nominal size_y = device_dimensions['body_size_y'].nominal with_thermal_vias = device_dimensions[ 'has_EP'] and 'thermal_vias' in device_params fab_line_width = self.configuration.get('fab_line_width', 0.1) silk_line_width = self.configuration.get('silk_line_width', 0.12) lib_name = self.configuration['lib_name_format_string'].format( category=category) pincount = device_params['num_pins_x'] * 2 + device_params[ 'num_pins_y'] * 2 ipc_reference = 'ipc_spec_flat_no_lead_pull_back' used_density = device_params.get('ipc_density', ipc_density) ipc_data_set = self.ipc_defintions[ipc_reference][used_density] ipc_round_base = self.ipc_defintions[ipc_reference]['round_base'] pad_details = self.calcPadDetails(device_dimensions, ipc_data_set, ipc_round_base) suffix = device_params.get('suffix', '').format( pad_x=pad_details['left']['size'][0], pad_y=pad_details['left']['size'][1]) suffix_3d = suffix if device_params.get('include_suffix_in_3dpath', 'True') == 'True' else "" model3d_path_prefix = self.configuration.get('3d_model_prefix', '${KISYS3DMOD}') name_format = self.configuration[ 'fp_name_lga_format_string_no_trailing_zero'] if device_dimensions['has_EP']: name_format = self.configuration[ 'fp_name_EP_format_string_no_trailing_zero'] EP_size = { 'x': device_dimensions['EP_size_x'].nominal, 'y': device_dimensions['EP_size_y'].nominal } EP_center = { 'x': device_dimensions['EP_center_x'].nominal, 'y': device_dimensions['EP_center_y'].nominal } if device_params['num_pins_x'] == 0 or device_params['num_pins_y'] == 0: layout = '' else: layout = self.configuration['lga_layout_border'].format( nx=device_params['num_pins_x'], ny=device_params['num_pins_y']) fp_name = name_format.format( man=device_params.get('manufacturer', ''), mpn=device_params.get('part_number', ''), pkg=device_params['device_type'], pincount=pincount, size_y=size_y, size_x=size_x, ep_size_x=EP_size['x'], ep_size_y=EP_size['y'], pitch=device_params['pitch'], layout=layout, suffix=suffix, suffix2="", vias=self.configuration.get('thermal_via_suffix', '_ThermalVias') if with_thermal_vias else '').replace('__', '_').lstrip('_') fp_name_2 = name_format.format( man=device_params.get('manufacturer', ''), mpn=device_params.get('part_number', ''), pkg=device_params['device_type'], pincount=pincount, size_y=size_y, size_x=size_x, ep_size_x=EP_size['x'], ep_size_y=EP_size['y'], pitch=device_params['pitch'], layout=layout, suffix=suffix_3d, suffix2="", vias='').replace('__', '_').lstrip('_') model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'\ .format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=fp_name_2) #print(fp_name) #print(pad_details) kicad_mod = Footprint(fp_name) # init kicad footprint kicad_mod.setDescription( "{manufacturer} {mpn} {package}, {pincount} Pin ({datasheet}), generated with kicad-footprint-generator {scriptname}"\ .format( manufacturer = device_params.get('manufacturer',''), package = device_params['device_type'], mpn = device_params.get('part_number',''), pincount = pincount, datasheet = device_params['size_source'], scriptname = os.path.basename(__file__).replace(" ", " ") ).lstrip()) kicad_mod.setTags(self.configuration['keyword_fp_string']\ .format( man=device_params.get('manufacturer',''), package=device_params['device_type'], category=category ).lstrip()) 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 device_dimensions['has_EP']: if with_thermal_vias: thermals = device_params['thermal_vias'] paste_coverage = thermals.get( 'EP_paste_coverage', device_params.get('EP_paste_coverage', DEFAULT_PASTE_COVERAGE)) kicad_mod.append( ExposedPad( number=pincount + 1, size=EP_size, at=EP_center, paste_layout=thermals.get( 'EP_num_paste_pads', device_params.get('EP_num_paste_pads', 1)), paste_coverage=paste_coverage, via_layout=thermals.get('count', 0), paste_between_vias=thermals.get('paste_between_vias'), paste_rings_outside=thermals.get( 'paste_rings_outside'), via_drill=thermals.get('drill', 0.3), via_grid=thermals.get('grid'), paste_avoid_via=thermals.get('paste_avoid_via', True), via_paste_clarance=thermals.get( 'paste_via_clearance', DEFAULT_VIA_PASTE_CLEARANCE), min_annular_ring=thermals.get( 'min_annular_ring', DEFAULT_MIN_ANNULAR_RING), bottom_pad_min_size=thermals.get('bottom_min_size', 0), kicad4_compatible=args.kicad4_compatible, **pad_shape_details)) else: kicad_mod.append( ExposedPad(number=pincount + 1, size=EP_size, at=EP_center, paste_layout=device_params.get( 'EP_num_paste_pads', 1), paste_coverage=device_params.get( 'EP_paste_coverage', DEFAULT_PASTE_COVERAGE), kicad4_compatible=args.kicad4_compatible, **pad_shape_details)) init = 1 if device_params['num_pins_x'] == 0: kicad_mod.append( PadArray(initial=init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_y'], x_spacing=0, y_spacing=device_params['pitch'], **pad_details['left'], **pad_shape_details)) init += device_params['num_pins_y'] kicad_mod.append( PadArray(initial=init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_y'], x_spacing=0, y_spacing=-device_params['pitch'], **pad_details['right'], **pad_shape_details)) elif device_params['num_pins_y'] == 0: #for devices with clockwise numbering kicad_mod.append( PadArray(initial=init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_x'], y_spacing=0, x_spacing=device_params['pitch'], **pad_details['top'], **pad_shape_details)) init += device_params['num_pins_x'] kicad_mod.append( PadArray(initial=init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_x'], y_spacing=0, x_spacing=-device_params['pitch'], **pad_details['bottom'], **pad_shape_details)) else: chamfer_size = device_params.get('chamfer_edge_pins') corner_first = [0, 1, 0, 0] corner_last = [0, 0, 1, 0] kicad_mod.append( PadArray(initial=init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_y'], x_spacing=0, y_spacing=device_params['pitch'], chamfer_size=chamfer_size, chamfer_corner_selection_first=corner_first, chamfer_corner_selection_last=corner_last, **pad_details['left'], **pad_shape_details)) init += device_params['num_pins_y'] corner_first = [1, 0, 0, 0] corner_last = [0, 1, 0, 0] kicad_mod.append( PadArray(initial=init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_x'], y_spacing=0, x_spacing=device_params['pitch'], chamfer_size=chamfer_size, chamfer_corner_selection_first=corner_first, chamfer_corner_selection_last=corner_last, **pad_details['bottom'], **pad_shape_details)) init += device_params['num_pins_x'] corner_first = [0, 0, 0, 1] corner_last = [1, 0, 0, 0] kicad_mod.append( PadArray(initial=init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_y'], x_spacing=0, y_spacing=-device_params['pitch'], chamfer_size=chamfer_size, chamfer_corner_selection_first=corner_first, chamfer_corner_selection_last=corner_last, **pad_details['right'], **pad_shape_details)) init += device_params['num_pins_y'] corner_first = [0, 0, 1, 0] corner_last = [0, 0, 0, 1] kicad_mod.append( PadArray(initial=init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_x'], y_spacing=0, x_spacing=-device_params['pitch'], chamfer_size=chamfer_size, chamfer_corner_selection_first=corner_first, chamfer_corner_selection_last=corner_last, **pad_details['top'], **pad_shape_details)) body_edge = { 'left': -size_x / 2, 'right': size_x / 2, 'top': -size_y / 2, 'bottom': size_y / 2 } bounding_box = body_edge pad_width = pad_details['top']['size'][0] # ############################ SilkS ################################## silk_pad_offset = configuration[ 'silk_pad_clearance'] + configuration['silk_line_width'] / 2 silk_offset = configuration['silk_fab_offset'] if device_params['num_pins_x'] == 0: kicad_mod.append( Line(start={ 'x': 0, 'y': body_edge['top'] - silk_offset }, end={ 'x': body_edge['right'], 'y': body_edge['top'] - silk_offset }, width=configuration['silk_line_width'], layer="F.SilkS", x_mirror=0)) kicad_mod.append( Line(start={ 'x': body_edge['left'], 'y': body_edge['bottom'] + silk_offset }, end={ 'x': body_edge['right'], 'y': body_edge['bottom'] + silk_offset }, width=configuration['silk_line_width'], layer="F.SilkS", x_mirror=0)) elif device_params['num_pins_y'] == 0: kicad_mod.append( Line(start={ 'y': 0, 'x': body_edge['left'] - silk_offset }, end={ 'y': body_edge['bottom'], 'x': body_edge['left'] - silk_offset }, width=configuration['silk_line_width'], layer="F.SilkS", x_mirror=0)) kicad_mod.append( Line(start={ 'y': body_edge['top'], 'x': body_edge['right'] + silk_offset }, end={ 'y': body_edge['bottom'], 'x': body_edge['right'] + silk_offset }, width=configuration['silk_line_width'], layer="F.SilkS", x_mirror=0)) else: sx1 = -(device_params['pitch'] * (device_params['num_pins_x'] - 1) / 2.0 + pad_width / 2.0 + silk_pad_offset) sy1 = -(device_params['pitch'] * (device_params['num_pins_y'] - 1) / 2.0 + pad_width / 2.0 + silk_pad_offset) poly_silk = [{ 'x': sx1, 'y': body_edge['top'] - silk_offset }, { 'x': body_edge['left'] - silk_offset, 'y': body_edge['top'] - silk_offset }, { 'x': body_edge['left'] - silk_offset, 'y': sy1 }] kicad_mod.append( PolygoneLine(polygone=poly_silk, width=configuration['silk_line_width'], layer="F.SilkS", x_mirror=0)) kicad_mod.append( PolygoneLine(polygone=poly_silk, width=configuration['silk_line_width'], layer="F.SilkS", y_mirror=0)) kicad_mod.append( PolygoneLine(polygone=poly_silk, width=configuration['silk_line_width'], layer="F.SilkS", x_mirror=0, y_mirror=0)) # # ######################## Fabrication Layer ########################### fab_bevel_size = min( configuration['fab_bevel_size_absolute'], configuration['fab_bevel_size_relative'] * min(size_x, size_y)) poly_fab = [ { 'x': body_edge['left'] + fab_bevel_size, 'y': body_edge['top'] }, { 'x': body_edge['right'], 'y': body_edge['top'] }, { 'x': body_edge['right'], 'y': body_edge['bottom'] }, { 'x': body_edge['left'], 'y': body_edge['bottom'] }, { 'x': body_edge['left'], 'y': body_edge['top'] + fab_bevel_size }, { 'x': body_edge['left'] + fab_bevel_size, 'y': body_edge['top'] }, ] kicad_mod.append( PolygoneLine(polygone=poly_fab, width=configuration['fab_line_width'], layer="F.Fab")) # # ############################ CrtYd ################################## off = ipc_data_set['courtyard'] grid = configuration['courtyard_grid'] cy1 = roundToBase(bounding_box['top'] - off, grid) kicad_mod.append( RectLine(start={ 'x': roundToBase(bounding_box['left'] - off, grid), 'y': cy1 }, end={ 'x': roundToBase(bounding_box['right'] + off, grid), 'y': roundToBase(bounding_box['bottom'] + off, grid) }, width=configuration['courtyard_line_width'], layer='F.CrtYd')) # ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={ 'top': cy1, 'bottom': -cy1 }, fp_name=fp_name, text_y_inside_position='center') ##################### Output and 3d model ############################ kicad_mod.append(Model(filename=model_name)) 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=fp_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(model, params, configuration): subseries, connector_style = params.series_name.split('-') pitch_mpn = '' if params.pin_pitch == 5.08: pitch_mpn = '-5,08' elif params.pin_pitch == 7.62: pitch_mpn = '-7,62' lib_series = 'GMSTB' if params.pin_pitch >= 7.5 else 'MSTB' lib_name = configuration['lib_name_format_str'].format(series=lib_series, style=series[1], pitch=params.pin_pitch, suffix='') mpn = configuration['mpn_format_string'].format(subseries=subseries, style = connector_style, rating=series[1], num_pins=params.num_pins, pitch=pitch_mpn) footprint_name = configuration['fp_name_format_string'].format(man = configuration['manufacturer'], series = series[0], mpn = mpn, num_rows = 1, num_pins = params.num_pins, mounting_pad = "", pitch = params.pin_pitch, orientation = configuration['orientation_str'][1] if params.angled else configuration['orientation_str'][0], flanged = configuration['flanged_str'][1] if params.flanged else configuration['flanged_str'][0], mount_hole = configuration['mount_hole_str'][1] if params.mount_hole else configuration['mount_hole_str'][0]) length, width, upper_to_pin, left_to_pin, mount_hole_left, mount_hole_right, inner_len = dimensions(params) body_top_left=[left_to_pin,upper_to_pin] body_bottom_right=v_add(body_top_left,[length,width]) body_edge={ 'left': body_top_left[0], 'top': body_top_left[1], 'right': body_bottom_right[0], 'bottom': body_bottom_right[1], } silk_top_left=v_offset(body_top_left, configuration['silk_fab_offset']) silk_bottom_right=v_offset(body_bottom_right, configuration['silk_fab_offset']) center_x = (params.num_pins-1)/2.0*params.pin_pitch kicad_mod = Footprint(footprint_name) mpn = configuration['mpn_format_string_description'].format(subseries=subseries, style = connector_style, rating=series[1], num_pins=params.num_pins, pitch=pitch_mpn) kicad_mod.setDescription(generate_description(params, mpn)) kicad_mod.setTags(configuration['keywords_format_string'].format(mpn=mpn, param_name=model, order_info = ', '.join(params.order_info))) ################################################# Pads ################################################# optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(initial=1, start=[0, 0], x_spacing=params.pin_pitch, pincount=params.num_pins, size=[params.pin_Sx, params.pin_Sy], drill=seriesParams.drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=configuration['pin_layers'], **optional_pad_params)) if params.mount_hole: kicad_mod.append(Pad(number='""', type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=mount_hole_left, size=[seriesParams.mount_drill, seriesParams.mount_drill], \ drill=seriesParams.mount_drill, layers=configuration['mount_hole_layers'])) kicad_mod.append(Pad(number='""', type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=mount_hole_right, size=[seriesParams.mount_drill, seriesParams.mount_drill], \ drill=seriesParams.mount_drill, layers=configuration['mount_hole_layers'])) #add an outline around the pins ################################################# Silk and Fab ################################################# kicad_mod.append(RectLine(start=silk_top_left, end=silk_bottom_right, layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['with_fab_layer']: kicad_mod.append(RectLine(start=body_top_left, end=body_bottom_right, layer='F.Fab', width=configuration['fab_line_width'])) if params.angled: lock_poly=[ {'x':-1, 'y':0}, {'x':1, 'y':0}, {'x':1.5/2, 'y':-1.5}, {'x':-1.5/2, 'y':-1.5}, {'x':-1, 'y':0} ] lock_poly_fab=[ {'x':-1, 'y':-configuration['silk_fab_offset']}, {'x':1, 'y':-configuration['silk_fab_offset']}, {'x':1.5/2, 'y':-1.5}, {'x':-1.5/2, 'y':-1.5}, {'x':-1, 'y':-configuration['silk_fab_offset']} ] kicad_mod.append(RectLine(start=[silk_top_left[0],silk_bottom_right[1]-1.5], end=[silk_bottom_right[0], silk_bottom_right[1]-1.5-1.8], layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: kicad_mod.append(RectLine(start=[body_top_left[0],silk_bottom_right[1]-1.5], end=[body_bottom_right[0], silk_bottom_right[1]-1.5-1.8], layer='F.Fab', width=configuration['fab_line_width'])) if params.flanged: lock_translation = Translation(mount_hole_left[0], silk_bottom_right[1]) lock_translation.append(PolygoneLine(polygone=lock_poly, layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: lock_translation.append(PolygoneLine(polygone=lock_poly_fab, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(lock_translation) lock_translation = Translation(mount_hole_right[0], silk_bottom_right[1]) lock_translation.append(PolygoneLine(polygone=lock_poly, layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: lock_translation.append(PolygoneLine(polygone=lock_poly_fab, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(lock_translation) for i in range(params.num_pins): lock_translation = Translation(i*params.pin_pitch, silk_bottom_right[1]) lock_translation.append(PolygoneLine(polygone=lock_poly, layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: lock_translation.append(PolygoneLine(polygone=lock_poly_fab, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(lock_translation) else: inner_width = 5.3 #measured pi1 = [body_top_left[0]+(length-inner_len)/2.0, body_top_left[1]+1.7] # 1.7mm measured top_thickness = pi1[1]-silk_top_left[1] pi2 = [body_bottom_right[0]-(length-inner_len)/2.0, pi1[1]+inner_width] #kicad_mod.append(RectLine(start=pi1, end=pi2, layer='F.SilkS')) first_center = params.pin_pitch/2.0 line_len = params.pin_pitch-2 outher_line_len = (-left_to_pin-1 + mount_hole_left[0]) if params.flanged else (-left_to_pin-1) kicad_mod.append(Line(start=[silk_top_left[0], pi1[1]-1], end=[silk_top_left[0]+outher_line_len, pi1[1]-1], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[silk_bottom_right[0], pi1[1]-1], end=[silk_bottom_right[0]-outher_line_len, pi1[1]-1], layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: kicad_mod.append(Line(start=[body_top_left[0], pi1[1]-1], end=[body_top_left[0]+outher_line_len, pi1[1]-1], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[body_bottom_right[0], pi1[1]-1], end=[body_bottom_right[0]-outher_line_len, pi1[1]-1], layer='F.Fab', width=configuration['fab_line_width'])) for i in range(params.num_pins -1): chamfer_edge = Translation(i*params.pin_pitch, pi1[1]-1) chamfer_edge.append(Line(start=[first_center-line_len/2.0, 0], end=[first_center+line_len/2.0, 0], layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: chamfer_edge.append(Line(start=[first_center-line_len/2.0, 0], end=[first_center+line_len/2.0, 0], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(chamfer_edge) flanged_line_left = (mount_hole_left[0]+1) lock_rect_silk={'start':[-1,0], 'end':[1,-top_thickness], 'layer':'F.SilkS', 'width':configuration['silk_line_width']} lock_rect_fab={'start':[-1,0], 'end':[1,-top_thickness+configuration['silk_fab_offset']], 'layer':'F.Fab', 'width':configuration['fab_line_width']} if params.flanged: lock_translation = Translation(mount_hole_left[0], pi1[1]) lock_translation.append(RectLine(**lock_rect_silk)) if configuration['inner_details_on_fab']: lock_translation.append(RectLine(**lock_rect_fab)) kicad_mod.append(lock_translation) lock_translation = Translation(mount_hole_right[0], pi1[1]) lock_translation.append(RectLine(**lock_rect_silk)) if configuration['inner_details_on_fab']: lock_translation.append(RectLine(**lock_rect_fab)) kicad_mod.append(lock_translation) chamfer_edge = Translation(0, pi1[1]-1) chamfer_edge.append(Line(start=[flanged_line_left, 0], end=[-1, 0], layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: chamfer_edge.append(Line(start=[flanged_line_left, 0], end=[-1, 0], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(chamfer_edge) chamfer_edge = Translation((params.num_pins-1)*params.pin_pitch+params.mount_hole_to_pin, pi1[1]-1) chamfer_edge.append(Line(start=[flanged_line_left, 0], end=[-1, 0], layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: chamfer_edge.append(Line(start=[flanged_line_left, 0], end=[-1, 0], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(chamfer_edge) for i in range(params.num_pins): lock_translation = Translation(i*params.pin_pitch, pi1[1]) lock_translation.append(RectLine(**lock_rect_silk)) if configuration['inner_details_on_fab']: lock_translation.append(RectLine(**lock_rect_fab)) kicad_mod.append(lock_translation) if params.flanged: kicad_mod.append(Circle(center=mount_hole_left, radius=1.9, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Circle(center=mount_hole_right, radius=1.9, layer='F.SilkS', width=configuration['silk_line_width'])) if not params.mount_hole: kicad_mod.append(Circle(center=mount_hole_left, radius=1, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Circle(center=mount_hole_right, radius=1, layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: kicad_mod.append(Circle(center=mount_hole_left, radius=1.9, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Circle(center=mount_hole_right, radius=1.9, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Circle(center=mount_hole_left, radius=1, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Circle(center=mount_hole_right, radius=1, layer='F.Fab', width=configuration['fab_line_width'])) angle = -100.5 arc_width = 4.0 for i in range(params.num_pins): plug_arc = Translation(i*params.pin_pitch,0) plug_arc.append(Arc(start=[-arc_width/2.0,pi2[1]], center=[0,0.55], angle=angle, layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: plug_arc.append(Arc(start=[-arc_width/2.0,pi2[1]], center=[0,0.55], angle=angle, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(plug_arc) for i in range(params.num_pins-1): lower_line = Translation(i*params.pin_pitch,pi2[1]) lower_line.append(Line(start=[arc_width/2.0, 0], end=[params.pin_pitch-arc_width/2.0, 0], layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: lower_line.append(Line(start=[arc_width/2.0, 0], end=[params.pin_pitch-arc_width/2.0, 0], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(lower_line) arc_to_side = pi1[0]+arc_width/2.0 poly=[ {'x':pi1[0]-arc_to_side, 'y':pi2[1]}, {'x':pi1[0], 'y':pi2[1]}, {'x':pi1[0], 'y':pi1[1]}, {'x':pi2[0], 'y':pi1[1]}, {'x':pi2[0], 'y':pi2[1]}, {'x':pi2[0]+arc_to_side, 'y':pi2[1]} ] kicad_mod.append(PolygoneLine(polygone=poly)) if configuration['inner_details_on_fab']: kicad_mod.append(PolygoneLine(polygone=poly, layer='F.Fab', width=configuration['fab_line_width'])) if params.mount_hole: kicad_mod.append(Circle(center=mount_hole_left, radius=seriesParams.mount_screw_head_r+configuration['silk_fab_offset'], layer='B.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Circle(center=mount_hole_right, radius=seriesParams.mount_screw_head_r+configuration['silk_fab_offset'], layer='B.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Circle(center=mount_hole_right, radius=seriesParams.mount_screw_head_r, layer='B.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Circle(center=mount_hole_left, radius=seriesParams.mount_screw_head_r, layer='B.Fab', width=configuration['fab_line_width'])) ################################################## Courtyard ################################################## #if params.angled: #p1=[p1[0],-seriesParams.pin_Sy/2] crtyd_top_left=v_offset(body_top_left, configuration['courtyard_offset']['connector']) crtyd_bottom_right=v_offset(body_bottom_right, configuration['courtyard_offset']['connector']) kicad_mod.append(RectLine(start=round_crty_point(crtyd_top_left, configuration['courtyard_grid']), end=round_crty_point(crtyd_bottom_right, configuration['courtyard_grid']), layer='F.CrtYd')) if params.mount_hole and configuration['courtyard_for_mountscrews']: kicad_mod.append(Circle(center=mount_hole_right, radius=seriesParams.mount_screw_head_r+configuration['courtyard_offset']['connector'], layer='B.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Circle(center=mount_hole_left, radius=seriesParams.mount_screw_head_r+configuration['courtyard_offset']['connector'], layer='B.CrtYd', width=configuration['courtyard_line_width'])) ################################################# Text Fields ################################################# addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':crtyd_top_left[1], 'bottom':crtyd_bottom_right[1]}, fp_name=footprint_name, text_y_inside_position='top') ################################################# Pin 1 Marker ################################################# if not params.angled: kicad_mod.append(PolygoneLine(polygone=create_pin1_marker_triangle(silk_top_left[1]-0.2), layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['with_fab_layer']: kicad_mod.append(PolygoneLine( polygone=create_pin1_marker_triangle(bottom_y = -params.pin_Sy/2- 0.75, dimensions = [1, 1], with_top_line = True), layer='F.Fab', width=configuration['fab_line_width'])) else: y_bottom_silk_marker = (silk_top_left[1] if silk_top_left[1] < -params.pin_Sy/2 else -params.pin_Sy/2) - 0.2 kicad_mod.append(PolygoneLine(polygone=create_pin1_marker_triangle(y_bottom_silk_marker), layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['with_fab_layer']: kicad_mod.append(PolygoneLine( polygone=create_pin1_marker_triangle(bottom_y = -0.5, dimensions = [1.9, -body_top_left[1]-0.5], with_top_line = False), layer='F.Fab', width=configuration['fab_line_width'])) #################################################### 3d file ################################################### p3dname = '{prefix:s}{lib_name:s}.3dshapes/{fp_name}.wrl'.format(prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/'), lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=p3dname, at=[0, 0, 0], scale=[1, 1, 1], rotate=[0, 0, 0])) file_handler = KicadFileHandler(kicad_mod) out_dir = '{:s}.pretty/'.format(lib_name) if not os.path.exists(out_dir): os.makedirs(out_dir) file_handler.writeFile('{:s}.pretty/{:s}.kicad_mod'.format(lib_name, footprint_name))
def generate_one_footprint(idx, pins, configuration): mpn = part_code.format(n=pins, param_1=mpn_param_1[idx]) pad_silk_off = configuration['silk_line_width'] / 2 + configuration[ 'silk_pad_clearance'] off = configuration['silk_fab_offset'] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format( man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad="-1MP", pitch=pitch, orientation=orientation_str) footprint_name = footprint_name.replace("__", '_') kicad_mod = Footprint(footprint_name) kicad_mod.setAttribute('smd') kicad_mod.setDescription( "{:s} {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator" .format(manufacturer, series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format( series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) A = (pins - 1) * pitch B = A + 2 * rel_body_edge_x pad_y = -rel_pad_y_outside_edge / 2 + pad_size[1] / 2 mpad_y = rel_pad_y_outside_edge / 2 - mp_size[1] / 2 mpad_x = A / 2 + center_pad_to_mounting_pad_edge + mp_size[0] / 2 kicad_mod.append( Pad(number=configuration['mounting_pad_number'], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[mpad_x, mpad_y], size=mp_size, layers=Pad.LAYERS_SMT)) kicad_mod.append( Pad(number=configuration['mounting_pad_number'], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[-mpad_x, mpad_y], size=mp_size, layers=Pad.LAYERS_SMT)) # create pads #createNumberedPadsTHT(kicad_mod, pincount, pitch, drill, {'x':x_dia, 'y':y_dia}) kicad_mod.append( PadArray(center=[0, pad_y], pincount=pins, x_spacing=pitch, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=pad_size, layers=Pad.LAYERS_SMT)) x1 = -B / 2 x2 = x1 + B y2 = mpad_y + mp_size[1] / 2 + rel_body_edge_y y1 = y2 - body_size_y body_edge = {'left': x1, 'right': x2, 'bottom': y2, 'top': y1} bounding_box = body_edge.copy() bounding_box['top'] = pad_y - pad_size[1] / 2 bb_x = mpad_x + mp_size[0] / 2 if bb_x > x2: bounding_box['left'] = -bb_x bounding_box['right'] = bb_x kicad_mod.append( RectLine(start={ 'x': x1, 'y': y1 }, end={ 'x': x2, 'y': y2 }, layer='F.Fab', width=configuration['fab_line_width'])) #line offset off = 0.1 x1 -= off y1 -= off x2 += off y2 += off #draw the main outline around the footprint silk_pad_x_left = -A / 2 - pad_size[0] / 2 - pad_silk_off silk_mp_top = mpad_y - mp_size[1] / 2 - pad_silk_off silk_mp_bottom = mpad_y + mp_size[1] / 2 + pad_silk_off kicad_mod.append( PolygoneLine(polygone=[{ 'x': silk_pad_x_left, 'y': y1 }, { 'x': x1, 'y': y1 }, { 'x': x1, 'y': silk_mp_top }], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=[{ 'x': -silk_pad_x_left, 'y': y1 }, { 'x': x2, 'y': y1 }, { 'x': x2, 'y': silk_mp_top }], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=[{ 'x': x1, 'y': silk_mp_bottom }, { 'x': x1, 'y': y2 }, { 'x': x2, 'y': y2 }, { 'x': x2, 'y': silk_mp_bottom }], layer='F.SilkS', width=configuration['silk_line_width'])) #add pin-1 marker kicad_mod.append( Line(start=[silk_pad_x_left, y1], end=[silk_pad_x_left, pad_y - pad_size[1] / 2], layer='F.SilkS', width=configuration['silk_line_width'])) sl = 1 pin = [{ 'y': body_edge['top'], 'x': -A / 2 - sl / 2 }, { 'y': body_edge['top'] + sl / sqrt(2), 'x': -A / 2 }, { 'y': body_edge['top'], 'x': -A / 2 + sl / 2 }] kicad_mod.append( PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### KEEPOUT ################################# k_top = pad_y + pad_size[1] / 2 + 0.1 k_size = [A + pad_size[0], 2.37] addRectangularKeepout(kicad_mod, [0, k_top + k_size[1] / 2], k_size) ########################### CrtYd ################################# cx1 = roundToBase( bounding_box['left'] - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase( bounding_box['top'] - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase( bounding_box['right'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase( bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append( RectLine(start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={ 'top': cy1, 'bottom': cy2 }, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pincount, configuration): silk_x_min = x_min - configuration['silk_fab_offset'] silk_y_min = y_min - configuration['silk_fab_offset'] silk_y_main_min = y_main_min - configuration['silk_fab_offset'] silk_y_max = y_max + configuration['silk_fab_offset'] x_mid = (pincount-1)*pitch/2.0 x_max = (pincount-1)*pitch + 1.95 silk_x_max = x_max + configuration['silk_fab_offset'] pad_size = [pitch - pad_to_pad_clearance, drill_size + 2*pad_copper_y_solder_length] if pad_size[0] - drill_size < 2*min_annular_ring: pad_size[0] = drill_size + 2*min_annular_ring # Through-hole type shrouded header, Side entry type mpn = "S{n}B-PH-K".format(n=pincount) #JST part number format string orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) # create Silkscreen tmp_x1=x_min+body_back_protrusion_width+configuration['silk_fab_offset'] tmp_x2=x_max-body_back_protrusion_width-configuration['silk_fab_offset'] pad_silk_offset = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 poly_silk_outline= [ {'x':-pad_size[0]/2.0-pad_silk_offset, 'y':silk_y_main_min}, {'x':tmp_x1, 'y':silk_y_main_min}, {'x':tmp_x1, 'y':silk_y_min}, {'x':silk_x_min, 'y':silk_y_min}, {'x':silk_x_min, 'y':silk_y_max}, {'x':silk_x_max, 'y':silk_y_max}, {'x':silk_x_max, 'y':silk_y_min}, {'x':tmp_x2, 'y':silk_y_min}, {'x':tmp_x2, 'y':silk_y_main_min}, {'x':(pincount-1)*pitch+pad_size[0]/2.0+pad_silk_offset, 'y':silk_y_main_min} ] kicad_mod.append(PolygoneLine(polygone=poly_silk_outline, layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['allow_silk_below_part'] == 'tht' or configuration['allow_silk_below_part'] == 'both': poly_big_cutout=[{'x':0.5, 'y':silk_y_max} ,{'x':0.5, 'y':2} ,{'x':x_max-2.45, 'y':2} ,{'x':x_max-2.45, 'y':silk_y_max}] kicad_mod.append(PolygoneLine(polygone=poly_big_cutout, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[silk_x_min, silk_y_main_min], end=[tmp_x1, silk_y_main_min], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[silk_x_max, silk_y_main_min], end=[tmp_x2, silk_y_main_min], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(RectLine(start=[-1.3, 2.5], end=[-0.3, 4.1], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(RectLine(start=[(pincount-1)*pitch+1.3, 2.5], end=[(pincount-1)*pitch+0.3, 4.1], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[-0.3, 4.1], end=[-0.3, silk_y_max], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[-0.8, 4.1], end=[-0.8, silk_y_max], layer='F.SilkS', width=configuration['silk_line_width'])) ########################### CrtYd ################################ part_x_min = x_min part_x_max = x_max part_y_min = y_min part_y_max = y_max cx1 = roundToBase(part_x_min-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(part_y_min-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(part_x_max+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(part_y_max+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ########################### Fab Outline ################################ tmp_x1=x_min+body_back_protrusion_width tmp_x2=x_max-body_back_protrusion_width poly_fab_outline= [ {'x':tmp_x1, 'y':y_main_min}, {'x':tmp_x1, 'y':y_min}, {'x':x_min, 'y':y_min}, {'x':x_min, 'y':y_max}, {'x':x_max, 'y':y_max}, {'x':x_max, 'y':y_min}, {'x':tmp_x2, 'y':y_min}, {'x':tmp_x2, 'y':y_main_min}, {'x':tmp_x1, 'y':y_main_min} ] kicad_mod.append(PolygoneLine(polygone=poly_fab_outline, layer='F.Fab', width=configuration['fab_line_width'])) ############################# Pads ################################## # kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, # at=[0, 0], size=pad_size, # drill=drill_size, layers=Pad.LAYERS_THT)) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(initial=1, start=[0, 0], x_spacing=pitch, pincount=pincount, size=pad_size, drill=drill_size, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT, **optional_pad_params)) ########################### Pin 1 marker ################################ poly_pin1_marker = [ {'x':0, 'y':-1.2}, {'x':-0.4, 'y':-1.6}, {'x':0.4, 'y':-1.6}, {'x':0, 'y':-1.2} ] if silk_pin1_marker_type == 1: kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.SilkS', width=configuration['silk_line_width'])) if silk_pin1_marker_type == 2: silk_pin1_marker_t2_x = -pad_size[0]/2.0-pad_silk_offset kicad_mod.append(Line(start=[silk_pin1_marker_t2_x, silk_y_main_min], end=[silk_pin1_marker_t2_x, -pad_size[1]/2.0-configuration['silk_pad_clearance']],layer='F.SilkS', width=configuration['silk_line_width'])) if fab_pin1_marker_type == 1: kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.Fab', width=configuration['fab_line_width'])) if fab_pin1_marker_type == 2: poly_pin1_marker_type2 = [ {'x':-0.75, 'y':y_main_min}, {'x':0, 'y':y_main_min+0.75}, {'x':0.75, 'y':y_main_min} ] kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker_type2, layer='F.Fab', width=configuration['fab_line_width'])) if fab_pin1_marker_type == 3: fab_pin1_marker_t3_y = pad_size[1]/2.0 poly_pin1_marker_type2 = [ {'x':0, 'y':fab_pin1_marker_t3_y}, {'x':-0.5, 'y':fab_pin1_marker_t3_y+0.5}, {'x':0.5, 'y':fab_pin1_marker_t3_y+0.5}, {'x':0, 'y':fab_pin1_marker_t3_y} ] kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker_type2, layer='F.Fab', width=configuration['fab_line_width'])) ######################### Text Fields ############################### text_center_y = 2.5 body_edge={'left':part_x_min, 'right':part_x_max, 'top':part_y_min, 'bottom':part_y_max} addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position=text_center_y) model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def __createFootprintVariant(self, device_params, header, dimensions, with_thermal_vias): fab_line_width = self.configuration.get('fab_line_width', 0.1) silk_line_width = self.configuration.get('silk_line_width', 0.12) lib_name = self.configuration['lib_name_format_string'].format( category=header['library_Suffix']) size_x = dimensions['body_size_x'].nominal size_y = dimensions['body_size_y'].nominal pincount = device_params['num_pins_x'] * 2 + device_params[ 'num_pins_y'] * 2 ipc_reference = 'ipc_spec_gw_large_pitch' if device_params[ 'pitch'] >= 0.625 else 'ipc_spec_gw_small_pitch' if device_params.get('force_small_pitch_ipc_definition', False): ipc_reference = 'ipc_spec_gw_small_pitch' used_density = device_params.get('ipc_density', ipc_density) ipc_data_set = self.ipc_defintions[ipc_reference][used_density] ipc_round_base = self.ipc_defintions[ipc_reference]['round_base'] pitch = device_params['pitch'] name_format = self.configuration[ 'fp_name_format_string_no_trailing_zero'] EP_size = {'x': 0, 'y': 0} EP_mask_size = {'x': 0, 'y': 0} if dimensions['has_EP']: name_format = self.configuration[ 'fp_name_EP_format_string_no_trailing_zero'] if 'EP_size_x_overwrite' in device_params: EP_size = { 'x': device_params['EP_size_x_overwrite'], 'y': device_params['EP_size_y_overwrite'] } else: EP_size = { 'x': device_dimensions['EP_size_x'].nominal, 'y': device_dimensions['EP_size_y'].nominal } if 'EP_mask_x' in dimensions: name_format = self.configuration[ 'fp_name_EP_custom_mask_format_string_no_trailing_zero'] EP_mask_size = { 'x': dimensions['EP_mask_x'].nominal, 'y': dimensions['EP_mask_y'].nominal } EP_size = Vector2D(EP_size) pad_details = self.calcPadDetails(dimensions, EP_size, ipc_data_set, ipc_round_base) if 'custom_name_format' in device_params: name_format = device_params['custom_name_format'] suffix = device_params.get('suffix', '').format( pad_x=pad_details['left']['size'][0], pad_y=pad_details['left']['size'][1]) suffix_3d = suffix if device_params.get('include_suffix_in_3dpath', 'True') == 'True' else "" model3d_path_prefix = self.configuration.get('3d_model_prefix', '${KISYS3DMOD}') fp_name = name_format.format( man=device_params.get('manufacturer', ''), mpn=device_params.get('part_number', ''), pkg=header['device_type'], pincount=pincount, size_y=size_y, size_x=size_x, pitch=device_params['pitch'], ep_size_x=EP_size['x'], ep_size_y=EP_size['y'], mask_size_x=EP_mask_size['x'], mask_size_y=EP_mask_size['y'], suffix=suffix, suffix2="", vias=self.configuration.get('thermal_via_suffix', '_ThermalVias') if with_thermal_vias else '').replace('__', '_').lstrip('_') fp_name_2 = name_format.format( man=device_params.get('manufacturer', ''), mpn=device_params.get('part_number', ''), pkg=header['device_type'], pincount=pincount, size_y=size_y, size_x=size_x, pitch=device_params['pitch'], ep_size_x=EP_size['x'], ep_size_y=EP_size['y'], mask_size_x=EP_mask_size['x'], mask_size_y=EP_mask_size['y'], suffix=suffix_3d, suffix2="", vias='').replace('__', '_').lstrip('_') model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'\ .format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=fp_name_2) #print(fp_name) #print(pad_details) kicad_mod = Footprint(fp_name) # init kicad footprint kicad_mod.setDescription( "{manufacturer} {mpn} {package}, {pincount} Pin ({datasheet}), generated with kicad-footprint-generator {scriptname}"\ .format( manufacturer = device_params.get('manufacturer',''), package = header['device_type'], mpn = device_params.get('part_number',''), pincount = pincount, datasheet = device_params['size_source'], scriptname = os.path.basename(__file__).replace(" ", " ") ).lstrip()) kicad_mod.setTags(self.configuration['keyword_fp_string']\ .format( man=device_params.get('manufacturer',''), package=header['device_type'], category=header['library_Suffix'] ).lstrip()) 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'] EP_round_radius = 0 if dimensions['has_EP']: EP_mask_size = EP_mask_size if EP_mask_size['x'] > 0 else None if with_thermal_vias: thermals = device_params['thermal_vias'] paste_coverage = thermals.get( 'EP_paste_coverage', device_params.get('EP_paste_coverage', DEFAULT_PASTE_COVERAGE)) EP = ExposedPad( number=pincount + 1, size=EP_size, mask_size=EP_mask_size, paste_layout=thermals.get('EP_num_paste_pads'), paste_coverage=paste_coverage, via_layout=thermals.get('count', 0), paste_between_vias=thermals.get('paste_between_vias'), paste_rings_outside=thermals.get('paste_rings_outside'), via_drill=thermals.get('drill', 0.3), via_grid=thermals.get('grid'), paste_avoid_via=thermals.get('paste_avoid_via', True), via_paste_clarance=thermals.get( 'paste_via_clearance', DEFAULT_VIA_PASTE_CLEARANCE), min_annular_ring=thermals.get('min_annular_ring', DEFAULT_MIN_ANNULAR_RING), bottom_pad_min_size=thermals.get('bottom_min_size', 0), **pad_shape_details) else: EP = ExposedPad( number=pincount + 1, size=EP_size, mask_size=EP_mask_size, paste_layout=device_params.get('EP_num_paste_pads', 1), paste_coverage=device_params.get('EP_paste_coverage', DEFAULT_PASTE_COVERAGE), **pad_shape_details) kicad_mod.append(EP) EP_round_radius = EP.getRoundRadius() pad_radius = add_dual_or_quad_pad_border(kicad_mod, configuration, pad_details, device_params) body_edge = { 'left': -dimensions['body_size_x'].nominal / 2, 'right': dimensions['body_size_x'].nominal / 2, 'top': -dimensions['body_size_y'].nominal / 2, 'bottom': dimensions['body_size_y'].nominal / 2 } bounding_box = { 'left': pad_details['left']['center'][0] - pad_details['left']['size'][0] / 2, 'right': pad_details['right']['center'][0] + pad_details['right']['size'][0] / 2, 'top': pad_details['top']['center'][1] - pad_details['top']['size'][1] / 2, 'bottom': pad_details['bottom']['center'][1] + pad_details['bottom']['size'][1] / 2 } if device_params['num_pins_x'] == 0: bounding_box['top'] = body_edge['top'] bounding_box['bottom'] = body_edge['bottom'] if EP_size['y'] > dimensions['body_size_y'].nominal: bounding_box['top'] = -EP_size['y'] / 2 bounding_box['bottom'] = EP_size['y'] / 2 if device_params['num_pins_y'] == 0: bounding_box['left'] = body_edge['left'] bounding_box['right'] = body_edge['right'] if EP_size['x'] > dimensions['body_size_x'].nominal: bounding_box['left'] = -EP_size['x'] / 2 bounding_box['right'] = EP_size['x'] / 2 pad_width = pad_details['top']['size'][0] # ############################ SilkS ################################## silk_pad_offset = configuration[ 'silk_pad_clearance'] + configuration['silk_line_width'] / 2 silk_offset = configuration['silk_fab_offset'] right_pads_silk_bottom = (device_params['num_pins_y']-1)*device_params['pitch']/2\ +pad_details['right']['size'][1]/2+silk_pad_offset silk_bottom = body_edge['bottom'] + silk_offset if EP_size['y'] / 2 <= body_edge[ 'bottom'] and right_pads_silk_bottom >= silk_bottom: silk_bottom = max(silk_bottom, EP_size['y'] / 2 + silk_pad_offset) silk_bottom = max(silk_bottom, right_pads_silk_bottom) silk_bottom = min(body_edge['bottom'] + silk_pad_offset, silk_bottom) bottom_pads_silk_right = (device_params['num_pins_x']-1)*device_params['pitch']/2\ +pad_details['bottom']['size'][0]/2+silk_pad_offset silk_right = body_edge['right'] + silk_offset if EP_size['x'] / 2 <= body_edge[ 'right'] and bottom_pads_silk_right >= silk_right: silk_right = max(silk_right, EP_size['x'] / 2 + silk_pad_offset) silk_right = max(silk_right, bottom_pads_silk_right) silk_right = min(body_edge['right'] + silk_pad_offset, silk_right) min_lenght = configuration.get('silk_line_lenght_min', 0) silk_corner_bottom_right = Vector2D(silk_right, silk_bottom) silk_point_bottom_inside = nearestSilkPointOnOrthogonalLine( pad_size=EP_size, pad_position=[0, 0], pad_radius=EP_round_radius, fixed_point=silk_corner_bottom_right, moving_point=Vector2D(0, silk_bottom), silk_pad_offset=silk_pad_offset, min_lenght=min_lenght) if silk_point_bottom_inside is not None and device_params[ 'num_pins_x'] > 0: silk_point_bottom_inside = nearestSilkPointOnOrthogonalLine( pad_size=pad_details['bottom']['size'], pad_position=[ pad_details['bottom']['center'][0] + (device_params['num_pins_x'] - 1) / 2 * pitch, pad_details['bottom']['center'][1] ], pad_radius=pad_radius, fixed_point=silk_corner_bottom_right, moving_point=silk_point_bottom_inside, silk_pad_offset=silk_pad_offset, min_lenght=min_lenght) silk_point_right_inside = nearestSilkPointOnOrthogonalLine( pad_size=EP_size, pad_position=[0, 0], pad_radius=EP_round_radius, fixed_point=silk_corner_bottom_right, moving_point=Vector2D(silk_right, 0), silk_pad_offset=silk_pad_offset, min_lenght=min_lenght) if silk_point_right_inside is not None and device_params[ 'num_pins_y'] > 0: silk_point_right_inside = nearestSilkPointOnOrthogonalLine( pad_size=pad_details['right']['size'], pad_position=[ pad_details['right']['center'][0], pad_details['right']['center'][1] + (device_params['num_pins_y'] - 1) / 2 * pitch ], pad_radius=pad_radius, fixed_point=silk_corner_bottom_right, moving_point=silk_point_right_inside, silk_pad_offset=silk_pad_offset, min_lenght=min_lenght) if silk_point_bottom_inside is None and silk_point_right_inside is not None: silk_corner_bottom_right['y'] = body_edge['bottom'] silk_corner_bottom_right = nearestSilkPointOnOrthogonalLine( pad_size=pad_details['bottom']['size'], pad_position=[ pad_details['bottom']['center'][0] + (device_params['num_pins_x'] - 1) / 2 * pitch, pad_details['bottom']['center'][1] ], pad_radius=pad_radius, fixed_point=silk_point_right_inside, moving_point=silk_corner_bottom_right, silk_pad_offset=silk_pad_offset, min_lenght=min_lenght) elif silk_point_right_inside is None and silk_point_bottom_inside is not None: silk_corner_bottom_right['x'] = body_edge['right'] silk_corner_bottom_right = nearestSilkPointOnOrthogonalLine( pad_size=pad_details['right']['size'], pad_position=[ pad_details['right']['center'][0], pad_details['right']['center'][1] + (device_params['num_pins_y'] - 1) / 2 * pitch ], pad_radius=pad_radius, fixed_point=silk_point_bottom_inside, moving_point=silk_corner_bottom_right, silk_pad_offset=silk_pad_offset, min_lenght=min_lenght) poly_bottom_right = [] if silk_point_bottom_inside is not None: poly_bottom_right.append(silk_point_bottom_inside) poly_bottom_right.append(silk_corner_bottom_right) if silk_point_right_inside is not None: poly_bottom_right.append(silk_point_right_inside) if len(poly_bottom_right) > 1 and silk_corner_bottom_right is not None: kicad_mod.append( PolygoneLine(polygone=poly_bottom_right, width=configuration['silk_line_width'], layer="F.SilkS")) kicad_mod.append( PolygoneLine(polygone=poly_bottom_right, width=configuration['silk_line_width'], layer="F.SilkS", x_mirror=0)) kicad_mod.append( PolygoneLine(polygone=poly_bottom_right, width=configuration['silk_line_width'], layer="F.SilkS", y_mirror=0)) if device_params['num_pins_y'] > 0: if silk_corner_bottom_right[ 'y'] - min_lenght >= right_pads_silk_bottom: poly_bottom_right[-1]['y'] = right_pads_silk_bottom kicad_mod.append( PolygoneLine(polygone=poly_bottom_right, width=configuration['silk_line_width'], layer="F.SilkS", y_mirror=0, x_mirror=0)) kicad_mod.append( Line(start={ 'x': -silk_corner_bottom_right['x'], 'y': -right_pads_silk_bottom }, end={ 'x': bounding_box['left'], 'y': -right_pads_silk_bottom }, width=configuration['silk_line_width'], layer="F.SilkS")) elif silk_corner_bottom_right[ 'y'] >= right_pads_silk_bottom and silk_point_bottom_inside is not None: kicad_mod.append( Line(start=-silk_point_bottom_inside, end={ 'x': bounding_box['left'], 'y': -silk_point_bottom_inside['y'] }, width=configuration['silk_line_width'], layer="F.SilkS")) else: if silk_corner_bottom_right[ 'x'] - min_lenght >= bottom_pads_silk_right: poly_bottom_right[0]['x'] = bottom_pads_silk_right kicad_mod.append( PolygoneLine(polygone=poly_bottom_right, width=configuration['silk_line_width'], layer="F.SilkS", y_mirror=0, x_mirror=0)) kicad_mod.append( Line(start={ 'x': -bottom_pads_silk_right, 'y': -silk_corner_bottom_right['y'] }, end={ 'x': -bottom_pads_silk_right, 'y': bounding_box['top'] }, width=configuration['silk_line_width'], layer="F.SilkS")) elif silk_corner_bottom_right[ 'x'] >= bottom_pads_silk_right and silk_point_right_inside is not None: kicad_mod.append( Line(start=-silk_point_right_inside, end={ 'x': -silk_point_right_inside['x'], 'y': bounding_box['top'] }, width=configuration['silk_line_width'], layer="F.SilkS")) # # ######################## Fabrication Layer ########################### fab_bevel_size = min( configuration['fab_bevel_size_absolute'], configuration['fab_bevel_size_relative'] * min(size_x, size_y)) poly_fab = [ { 'x': body_edge['left'] + fab_bevel_size, 'y': body_edge['top'] }, { 'x': body_edge['right'], 'y': body_edge['top'] }, { 'x': body_edge['right'], 'y': body_edge['bottom'] }, { 'x': body_edge['left'], 'y': body_edge['bottom'] }, { 'x': body_edge['left'], 'y': body_edge['top'] + fab_bevel_size }, { 'x': body_edge['left'] + fab_bevel_size, 'y': body_edge['top'] }, ] kicad_mod.append( PolygoneLine(polygone=poly_fab, width=configuration['fab_line_width'], layer="F.Fab")) # # ############################ CrtYd ################################## off = ipc_data_set['courtyard'] grid = configuration['courtyard_grid'] if device_params['num_pins_y'] == 0 or device_params['num_pins_x'] == 0: cy1 = roundToBase(bounding_box['top'] - off, grid) kicad_mod.append( RectLine(start={ 'x': roundToBase(bounding_box['left'] - off, grid), 'y': cy1 }, end={ 'x': roundToBase(bounding_box['right'] + off, grid), 'y': roundToBase(bounding_box['bottom'] + off, grid) }, width=configuration['courtyard_line_width'], layer='F.CrtYd')) else: cy1 = roundToBase(bounding_box['top'] - off, grid) cy2 = roundToBase(body_edge['top'] - off, grid) cy3 = -roundToBase( device_params['pitch'] * (device_params['num_pins_y'] - 1) / 2.0 + pad_width / 2.0 + off, grid) cx1 = -roundToBase( device_params['pitch'] * (device_params['num_pins_x'] - 1) / 2.0 + pad_width / 2.0 + off, grid) cx2 = roundToBase(body_edge['left'] - off, grid) cx3 = roundToBase(bounding_box['left'] - off, grid) crty_poly_tl = [{ 'x': 0, 'y': cy1 }, { 'x': cx1, 'y': cy1 }, { 'x': cx1, 'y': cy2 }, { 'x': cx2, 'y': cy2 }, { 'x': cx2, 'y': cy3 }, { 'x': cx3, 'y': cy3 }, { 'x': cx3, 'y': 0 }] kicad_mod.append( PolygoneLine(polygone=crty_poly_tl, layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append( PolygoneLine(polygone=crty_poly_tl, layer='F.CrtYd', width=configuration['courtyard_line_width'], x_mirror=0)) kicad_mod.append( PolygoneLine(polygone=crty_poly_tl, layer='F.CrtYd', width=configuration['courtyard_line_width'], y_mirror=0)) kicad_mod.append( PolygoneLine(polygone=crty_poly_tl, layer='F.CrtYd', width=configuration['courtyard_line_width'], x_mirror=0, y_mirror=0)) # ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={ 'top': cy1, 'bottom': -cy1 }, fp_name=fp_name, text_y_inside_position='center') ##################### Output and 3d model ############################ kicad_mod.append(Model(filename=model_name)) 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=fp_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_footprint(pins, configuration): mpn = pn.format(n=pins) pins_per_row = pins # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Harwin {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) kicad_mod.setAttribute('smd') ########################## Dimensions ############################## A = 2.54 * pins B = 2.54 * (pins-1) C = B - 2.54 body_edge={ 'left': -2.54, 'right': 2.54, 'top': -A/2, 'bottom': A/2 } ############################# Pads ################################## # # Mount Pegs # if pins == 2: kicad_mod.append(Pad(at=[0, 0], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=mount_drill, drill=mount_drill, layers=Pad.LAYERS_NPTH)) else: kicad_mod.append(Pad(at=[0, -C/2], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=mount_drill, drill=mount_drill, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(at=[0, C/2], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=mount_drill, drill=mount_drill, layers=Pad.LAYERS_NPTH)) # # THT Pegs # kicad_mod.append(PadArray(start=[-1.27, -B/2], initial="", pincount=pins, y_spacing=pitch, type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill_tht, drill=peg_drill_tht, layers=Pad.LAYERS_NPTH)) kicad_mod.append(PadArray(start=[1.27, -B/2], initial="", pincount=pins, y_spacing=pitch, type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill_tht, drill=peg_drill_tht, layers=Pad.LAYERS_NPTH)) # # Add pads # kicad_mod.append(PadArray(start=[-2.91, -B/2], initial=1, pincount=pins, increment=1, y_spacing=pitch, size=pad_size, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_SMT)) kicad_mod.append(PadArray(start=[2.91, -B/2], initial=pins+1, pincount=pins, increment=1, y_spacing=pitch, size=pad_size, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_SMT)) ######################## Fabrication Layer ########################### main_body_poly= [ {'x': body_edge['left'], 'y': body_edge['top']}, {'x': body_edge['right'], 'y': body_edge['top']}, {'x': body_edge['right'], 'y': body_edge['bottom']}, {'x': body_edge['left'], 'y': body_edge['bottom']}, {'x': body_edge['left'], 'y': body_edge['top']} ] kicad_mod.append(PolygoneLine(polygone=main_body_poly, width=configuration['fab_line_width'], layer="F.Fab")) main_arrow_poly= [ {'x': -2.54, 'y': body_edge['top'] + 1.27 - .4}, {'x': -1.9, 'y': body_edge['top'] + 1.27}, {'x': -2.54, 'y': body_edge['top'] + 1.27 + .4}, ] kicad_mod.append(PolygoneLine(polygone=main_arrow_poly, width=configuration['fab_line_width'], layer="F.Fab")) ######################## SilkS Layer ########################### poly_s_top= [ {'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': body_edge['top'] - configuration['silk_fab_offset'] + .7}, {'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': body_edge['top'] - configuration['silk_fab_offset']}, {'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': body_edge['top'] - configuration['silk_fab_offset']}, {'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': body_edge['top'] - configuration['silk_fab_offset'] + .7}, ] kicad_mod.append(PolygoneLine(polygone=poly_s_top, width=configuration['silk_line_width'], layer="F.SilkS")) poly_s_bot= [ {'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': body_edge['bottom'] + configuration['silk_fab_offset'] - .7}, {'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': body_edge['bottom'] + configuration['silk_fab_offset']}, {'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': body_edge['bottom'] + configuration['silk_fab_offset']}, {'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': body_edge['bottom'] + configuration['silk_fab_offset'] - .7}, ] kicad_mod.append(PolygoneLine(polygone=poly_s_bot, width=configuration['silk_line_width'], layer="F.SilkS")) ######################## CrtYd Layer ########################### CrtYd_offset = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] poly_yd = [ {'x': -3.8 - CrtYd_offset, 'y': body_edge['top'] - CrtYd_offset}, {'x': 3.8 + CrtYd_offset, 'y': body_edge['top'] - CrtYd_offset}, {'x': 3.8 + CrtYd_offset, 'y': body_edge['bottom'] + CrtYd_offset}, {'x': -3.8 - CrtYd_offset, 'y': body_edge['bottom'] + CrtYd_offset}, {'x': -3.8 - CrtYd_offset, 'y': body_edge['top'] - CrtYd_offset} ] kicad_mod.append(PolygoneLine(polygone=poly_yd, layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### cy1 = body_edge['top'] - configuration['courtyard_offset']['connector'] cy2 = body_edge['bottom'] + configuration['courtyard_offset']['connector'] + 0.2 addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Write to File and 3D ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins_per_row, variant, configuration): mpn = variant_params[variant]['part_code'].format(n=pins_per_row * number_of_rows) alt_mpn = [ code.format(n=pins_per_row * number_of_rows) for code in variant_params[variant]['alternative_codes'] ] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format( man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad="", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription( "Molex {:s}, {:s} (compatible alternatives: {:s}), {:d} Pins per row ({:s}), generated with kicad-footprint-generator" .format(series_long, mpn, ', '.join(alt_mpn), pins_per_row, variant_params[variant]['datasheet'])) kicad_mod.setTags(configuration['keyword_fp_string'].format( series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #kicad_mod.setAttribute('smd') ########################## Dimensions ############################## B = (pins_per_row - 1) * pitch A = B + 6.65 C = B + variant_params[variant]['C_minus_B'] pad_row_1_y = 0 pad1_x = 0 peg1_x = (B - C) / 2 peg2_x = (B + C) / 2 peg_y = pad_row_1_y + pitch + 0.94 tab_w = 1.4 tab_l = 1.4 body_edge = {'left': (B - A) / 2, 'right': (A + B) / 2, 'top': -2.47 + 0.5} body_edge['bottom'] = body_edge['top'] + (7.37 - 0.5) y_top_min = -2.47 chamfer = {'x': 1.2, 'y': 0.63} ############################# Pads ################################## # # Pegs # kicad_mod.append( Pad(at=[peg1_x, peg_y], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) kicad_mod.append( Pad(at=[peg2_x, peg_y], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) # # Add pads # optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for row_idx in range(2): kicad_mod.append( PadArray(start=[pad1_x, pad_row_1_y + pitch * row_idx], initial=row_idx * pins_per_row + 1, pincount=pins_per_row, increment=1, x_spacing=pitch, size=pad_size, type=Pad.TYPE_THT, shape=pad_shape, layers=Pad.LAYERS_THT, drill=drill, **optional_pad_params)) ######################## Fabrication Layer ########################### main_body_poly = [{ 'x': body_edge['left'] + chamfer['x'], 'y': body_edge['top'] }, { 'x': body_edge['left'] + chamfer['x'], 'y': y_top_min }, { 'x': body_edge['left'], 'y': y_top_min }, { 'x': body_edge['left'], 'y': body_edge['bottom'] }, { 'x': body_edge['right'], 'y': body_edge['bottom'] }, { 'x': body_edge['right'], 'y': y_top_min }, { 'x': body_edge['right'] - chamfer['x'], 'y': y_top_min }, { 'x': body_edge['right'] - chamfer['x'], 'y': body_edge['top'] }, { 'x': body_edge['left'] + chamfer['x'], 'y': body_edge['top'] }] kicad_mod.append( PolygoneLine(polygone=main_body_poly, width=configuration['fab_line_width'], layer="F.Fab")) kicad_mod.append( Line(start={ 'x': body_edge['left'], 'y': body_edge['top'] + chamfer['y'] }, end={ 'x': body_edge['left'] + chamfer['x'], 'y': body_edge['top'] }, width=configuration['fab_line_width'], layer="F.Fab")) kicad_mod.append( Line(start={ 'x': body_edge['right'], 'y': body_edge['top'] + chamfer['y'] }, end={ 'x': body_edge['right'] - chamfer['x'], 'y': body_edge['top'] }, width=configuration['fab_line_width'], layer="F.Fab")) tab_poly = [ { 'x': B / 2 - tab_l / 2, 'y': body_edge['bottom'] }, { 'x': B / 2 - tab_l / 2, 'y': body_edge['bottom'] + tab_w }, { 'x': B / 2 + tab_l / 2, 'y': body_edge['bottom'] + tab_w }, { 'x': B / 2 + tab_l / 2, 'y': body_edge['bottom'] }, ] kicad_mod.append( PolygoneLine(polygone=tab_poly, width=configuration['fab_line_width'], layer="F.Fab")) p1m_sl = 1 p1m_poly = tab_poly = [{ 'x': pad1_x - p1m_sl / 2, 'y': body_edge['top'] }, { 'x': pad1_x, 'y': body_edge['top'] + p1m_sl / sqrt(2) }, { 'x': pad1_x + p1m_sl / 2, 'y': body_edge['top'] }] kicad_mod.append( PolygoneLine(polygone=tab_poly, width=configuration['fab_line_width'], layer="F.Fab")) ############################ SilkS ################################## # Top left corner silk_pad_off = configuration[ 'silk_pad_clearance'] + configuration['silk_line_width'] / 2 ymp_top = peg_y - peg_drill / 2 - silk_pad_off ymp_bottom = peg_y + peg_drill / 2 + silk_pad_off off = configuration['silk_fab_offset'] poly_s_b = [ { 'x': body_edge['left'] - off, 'y': ymp_bottom }, { 'x': body_edge['left'] - off, 'y': body_edge['bottom'] + off }, { 'x': body_edge['right'] + off, 'y': body_edge['bottom'] + off }, { 'x': body_edge['right'] + off, 'y': ymp_bottom }, ] kicad_mod.append( PolygoneLine(polygone=poly_s_b, width=configuration['silk_line_width'], layer="F.SilkS")) poly_s_t = [ { 'x': body_edge['left'] - off, 'y': ymp_top }, { 'x': body_edge['left'] - off, 'y': y_top_min - off }, { 'x': body_edge['left'] + chamfer['x'] + off, 'y': y_top_min - off }, { 'x': body_edge['left'] + chamfer['x'] + off, 'y': body_edge['top'] - off }, { 'x': body_edge['right'] - chamfer['x'] - off, 'y': body_edge['top'] - off }, { 'x': body_edge['right'] - chamfer['x'] - off, 'y': y_top_min - off }, { 'x': body_edge['right'] + off, 'y': y_top_min - off }, { 'x': body_edge['right'] + off, 'y': ymp_top }, ] kicad_mod.append( PolygoneLine(polygone=poly_s_t, width=configuration['silk_line_width'], layer="F.SilkS")) ############################ CrtYd ################################## CrtYd_offset = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] cy_top = roundToBase(y_top_min - CrtYd_offset, CrtYd_grid) cy_bottom = roundToBase(body_edge['bottom'] + tab_w + CrtYd_offset, CrtYd_grid) cy_left = roundToBase(body_edge['left'] - CrtYd_offset, CrtYd_grid) cy_right = roundToBase(body_edge['right'] + CrtYd_offset, CrtYd_grid) poly_cy = [ { 'x': cy_left, 'y': cy_top }, { 'x': cy_right, 'y': cy_top }, { 'x': cy_right, 'y': cy_bottom }, { 'x': cy_left, 'y': cy_bottom }, { 'x': cy_left, 'y': cy_top }, ] kicad_mod.append( PolygoneLine(polygone=poly_cy, layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={ 'top': cy_top, 'bottom': cy_bottom }, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def make_module(pin_count, configuration): mpn = part_code.format(pin_count) datasheet='https://www.molex.com/pdm_docs/sd/2005280{:02d}0_sd.pdf'.format(pin_count) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format( man = manufacturer, series = series, mpn = mpn, num_rows = number_of_rows, pins = pin_count, pins_per_row = pin_count, mounting_pad = "-1MP", pitch = pitch, orientation = orientation_str) footprint_name = footprint_name.replace("__",'_') kicad_mod = Footprint(footprint_name) kicad_mod.setAttribute('smd') kicad_mod.setDescription( ("Molex {:s}, {:s}, {:d} Circuits ({:s}), " + "generated with kicad-footprint-generator").format( series_long, mpn, pin_count, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format( man=manufacturer, series=series, orientation=orientation_str, entry=configuration['entry_direction'][orientation])) A = pin_count + 5.2 B = pin_span = pin_count - 1 C = pin_count + 3.6 pin_y = -(0.4 - (lead_size[1] / 2)) - 0.71 lever_size = (C, 4) toe_ins_corner = ((A / 2) - toe_size[0], pin_y + (0.4 - (lead_size[1] / 2))) lever_out_corner = (C / 2, (toe_ins_corner[1] - toe_size[1]) + 5.25) pad_silk_off = (configuration['silk_pad_clearance'] + (configuration['silk_line_width'] / 2)) fab_silk_off = configuration['silk_fab_offset'] ## Mounting Pads ## mp_pos = ((pin_span / 2) + 1.8 + (mp_size[0] / 2), pin_y + (pad_size[1] / 2) + 1.55 + (mp_size[1] / 2)) def make_anchor_pad(x_direction): kicad_mod.append( Pad(number = configuration['mounting_pad_number'], type = Pad.TYPE_SMT, shape = Pad.SHAPE_RECT, at = [x_direction * mp_pos[0], mp_pos[1]], size = mp_size, layers = Pad.LAYERS_SMT)) make_anchor_pad(-1) make_anchor_pad(1) ## Pads ## kicad_mod.append( PadArray(center = [0, pin_y], pincount = pin_count, x_spacing = pitch, type = Pad.TYPE_SMT, shape = Pad.SHAPE_RECT, size = pad_size, layers = Pad.LAYERS_SMT)) ## Fab ## fab_body_outline = [ {'x': toe_ins_corner[0], 'y': toe_ins_corner[1] - toe_size[1]}, {'x': toe_ins_corner[0], 'y': toe_ins_corner[1]}, {'x': -toe_ins_corner[0], 'y': toe_ins_corner[1]}, {'x': -toe_ins_corner[0], 'y': toe_ins_corner[1] - toe_size[1]}, {'x': -(A / 2), 'y': toe_ins_corner[1] - toe_size[1]}, {'x': -(A / 2), 'y': (toe_ins_corner[1] - toe_size[1]) + foot_y}, {'x': (A / 2), 'y': (toe_ins_corner[1] - toe_size[1]) + foot_y}, {'x': (A / 2), 'y': toe_ins_corner[1] - toe_size[1]}, {'x': toe_ins_corner[0], 'y': toe_ins_corner[1] - toe_size[1]} ] kicad_mod.append(PolygoneLine( polygone = fab_body_outline, layer = 'F.Fab', width = configuration['fab_line_width'])) fab_pin1_mark = [ {'x': -(pin_span / 2) - 0.5, 'y': toe_ins_corner[1]}, {'x': -(pin_span / 2), 'y': toe_ins_corner[1] + 0.75}, {'x': -(pin_span / 2) + 0.5, 'y': toe_ins_corner[1]} ] kicad_mod.append(PolygoneLine( polygone = fab_pin1_mark, layer = 'F.Fab', width = configuration['fab_line_width'])) fab_lever_outline = [ {'x': lever_out_corner[0], 'y': lever_out_corner[1] - lever_size[1]}, {'x': -lever_out_corner[0], 'y': lever_out_corner[1] - lever_size[1]}, {'x': -lever_out_corner[0], 'y': lever_out_corner[1]}, {'x': lever_out_corner[0], 'y': lever_out_corner[1]}, {'x': lever_out_corner[0], 'y': lever_out_corner[1] - lever_size[1]} ] kicad_mod.append(PolygoneLine( polygone = fab_lever_outline, layer = 'F.Fab', width = configuration['fab_line_width'])) ## SilkS ## silk_outline1 = [ {'x': (-(pin_span / 2) - (pad_size[0] / 2)) - pad_silk_off, 'y': pin_y - (pad_size[1] / 2)}, {'x': (-(pin_span / 2) - (pad_size[0] / 2)) - pad_silk_off, 'y': toe_ins_corner[1] - fab_silk_off}, {'x': -toe_ins_corner[0] + fab_silk_off, 'y': toe_ins_corner[1] - fab_silk_off}, {'x': -toe_ins_corner[0] + fab_silk_off, 'y': (toe_ins_corner[1] - toe_size[1]) - fab_silk_off}, {'x': -(A / 2) - fab_silk_off, 'y': (toe_ins_corner[1] - toe_size[1]) - fab_silk_off}, {'x': -(A / 2) - fab_silk_off, 'y': (mp_pos[1] - (mp_size[1] / 2)) - pad_silk_off}, ] silk_outline2 = [ {'x': -(A / 2) - fab_silk_off, 'y': (mp_pos[1] + (mp_size[1] / 2)) + pad_silk_off}, {'x': -(A / 2) - fab_silk_off, 'y': ((toe_ins_corner[1] - toe_size[1]) + foot_y) + fab_silk_off}, {'x': -lever_out_corner[0] - fab_silk_off, 'y': ((toe_ins_corner[1] - toe_size[1]) + foot_y) + fab_silk_off}, {'x': -lever_out_corner[0] - fab_silk_off, 'y': lever_out_corner[1] + fab_silk_off}, {'x': lever_out_corner[0] + fab_silk_off, 'y': lever_out_corner[1] + fab_silk_off}, {'x': lever_out_corner[0] + fab_silk_off, 'y': ((toe_ins_corner[1] - toe_size[1]) + foot_y) + fab_silk_off}, {'x': (A / 2) + fab_silk_off, 'y': ((toe_ins_corner[1] - toe_size[1]) + foot_y) + fab_silk_off}, {'x': (A / 2) + fab_silk_off, 'y': (mp_pos[1] + (mp_size[1] / 2)) + pad_silk_off}, ] silk_outline3 = [ {'x': (A / 2) + fab_silk_off, 'y': (mp_pos[1] - (mp_size[1] / 2)) - pad_silk_off}, {'x': (A / 2) + fab_silk_off, 'y': (toe_ins_corner[1] - toe_size[1]) - fab_silk_off}, {'x': toe_ins_corner[0] - fab_silk_off, 'y': (toe_ins_corner[1] - toe_size[1]) - fab_silk_off}, {'x': toe_ins_corner[0] - fab_silk_off, 'y': toe_ins_corner[1] - fab_silk_off}, {'x': ((pin_span / 2) + (pad_size[0] / 2)) + pad_silk_off, 'y': toe_ins_corner[1] - fab_silk_off} ] kicad_mod.append(PolygoneLine( polygone = silk_outline1, layer = 'F.SilkS', width = configuration['silk_line_width'])) kicad_mod.append(PolygoneLine( polygone = silk_outline2, layer = 'F.SilkS', width = configuration['silk_line_width'])) kicad_mod.append(PolygoneLine( polygone = silk_outline3, layer = 'F.SilkS', width = configuration['silk_line_width'])) ## CrtYd ## bounding_box = { 'top': pin_y - (pad_size[1] / 2), 'left': (-mp_pos[0] - (mp_size[0] / 2)), 'bottom': lever_out_corner[1], 'right': (mp_pos[0] + (mp_size[0] / 2))} cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ## Text ## addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=bounding_box, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') if lib_by_conn_category: lib_name = configuration['lib_name_specific_function_format_string'].format(category=conn_category) else: lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins, params, configuration): pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 mpn = part_code.format(n=pins*number_of_rows) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) footprint_name += params['fp_name_suffix'] kicad_mod = Footprint(footprint_name) desc_format_str = "Molex {:s}, {:s}{:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription(desc_format_str.format(series_long, mpn, params['description'], pins, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate fp dimensions #ref: http://www.molex.com/pdm_docs/sd/439151404_sd.pdf #A = distance between mounting holes A = pins * pitch + 1.41 #B = distance between end pin centers B = (pins - 1) * pitch #E = length of part E = pins * pitch + 0.9 #connector width W = 19.16 #corner positions y1 = -(E-B)/2 y2 = y1 + E x1 = -1.15 x2 = x1 + W TL = 5 TW = 13 body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = { 'left': -pad_size[0]/2, 'right': pitch_row + offset_second_pad + pad_size[0]/2 } pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 #generate the pads for row_idx in range(2): for pad_idx in range(2): kicad_mod.append(PadArray( pincount=pins, start=[row_idx*pitch_row + pad_idx*offset_second_pad, 0], initial=row_idx*pins+1, y_spacing=pitch, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_THT, tht_pad1_shape=Pad.SHAPE_RECT)) #thermal vias d_small = 0.3 s_small = d_small + 2*min_annular_ring thermal_to_pad_edge = s_small/2 + 0.15 if params['thermals']: for yi in range(pins): for xi in range(number_of_rows): n = xi*pins + yi + 1 pad_center_x = xi*pitch_row + offset_second_pad/2 pad_center_y = yi*pitch pad_l = offset_second_pad + pad_size[0] dy = (pad_size[1] - 2*thermal_to_pad_edge)/2 dx = (pad_l - 2*thermal_to_pad_edge)/4 #draw rectangle on F.Fab layer # kicad_mod.append(RectLine( # start=[pad_center_x - pad_l/2, pad_center_y - pad_size[1]/2], # end=[pad_center_x + pad_l/2, pad_center_y + pad_size[1]/2], # layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PadArray(center=[pad_center_x, pad_center_y], pincount=3, x_spacing=dx*2, drill=d_small, size=s_small, initial=n, increment=0, shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_THT, layers=Pad.LAYERS_THT)) kicad_mod.append(PadArray(center=[pad_center_x, pad_center_y - dy], pincount=5, x_spacing=dx, drill=d_small, size=s_small, initial=n, increment=0, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_THT)) kicad_mod.append(PadArray(center=[pad_center_x, pad_center_y + dy], pincount=5, x_spacing=dx, drill=d_small, size=s_small, initial=n, increment=0, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_THT)) # locating pins kicad_mod.append(Pad(at=[x_loc, 5], type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=r_loc, drill=r_loc, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(at=[x_loc, B/2-A/2], type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, size=r_loc+0.5, drill=r_loc, layers=Pad.LAYERS_THT)) kicad_mod.append(Pad(at=[x_loc, B/2+A/2], type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, size=r_loc+0.5, drill=r_loc, layers=Pad.LAYERS_THT)) #mark pin-1 (bottom layer) kicad_mod.append(RectLine(start=[-pad_size[0]/2, -pad_size[1]/2], end=[offset_second_pad + pad_size[0]/2,pad_size[1]/2],offset=pad_silk_off, width=configuration['silk_line_width'], layer='B.SilkS')) #draw connector outline (basic) kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2], width=configuration['fab_line_width'], layer='F.Fab')) #connector outline on F.SilkScreen off = configuration['silk_line_width'] corner = [ {'y': -pad_size[1]/2 - pad_silk_off, 'x': x1-off}, {'y': y1 - off, 'x': x1-off}, {'y': y1 - off, 'x': x_loc-r_loc/2-0.5}, ] # kicad_mod.append(PolygoneLine(polygone=corner, # width=configuration['silk_line_width'], layer='F.SilkS')) kicad_mod.append(Line(start=[x_loc-r_loc/2-0.5, y1 - off], end=[x_loc-TW/2-off, y1 - off], width=configuration['silk_line_width'], layer='F.SilkS')) kicad_mod.append(PolygoneLine(polygone=corner,y_mirror=B/2, width=configuration['silk_line_width'], layer='F.SilkS')) kicad_mod.append(PolygoneLine(polygone=corner,x_mirror=x_loc, width=configuration['silk_line_width'], layer='F.SilkS')) kicad_mod.append(PolygoneLine(polygone=corner,y_mirror=B/2,x_mirror=x_loc, width=configuration['silk_line_width'], layer='F.SilkS')) #silk-screen between each pad for i in range(pins-1): ya = i * pitch + pad_size[1]/2 + pad_silk_off yb = (i+1) * pitch - pad_size[1]/2 - pad_silk_off kicad_mod.append(Line(start=[x1-off, ya],end=[x1-off, yb], width=configuration['silk_line_width'], layer='F.SilkS')) kicad_mod.append(Line(start=[x2+off, ya],end=[x2+off, yb], width=configuration['silk_line_width'], layer='F.SilkS')) #draw the tabs at each end def offsetPoly(poly_points, o , center_x, center_y): new_points = [] for point in poly_points: new_points.append( { 'y': point['y'] + (o if point['y'] > center_y else -o), 'x': point['x'] + (o if point['x'] > center_x else -o) } ) return new_points tab = [ {'y': y1,'x': x_loc-TW/2}, {'y': y1-TL,'x': x_loc-TW/2}, {'y': y1-TL,'x': x_loc+TW/2}, {'y': y1,'x': x_loc+TW/2}, ] kicad_mod.append(PolygoneLine(polygone=tab, width=configuration['fab_line_width'], layer='F.Fab')) kicad_mod.append(PolygoneLine(polygone=tab, y_mirror=B/2, width=configuration['fab_line_width'], layer='F.Fab')) tap_off = offsetPoly(tab, off, x_loc, B/2) kicad_mod.append(PolygoneLine(polygone=tap_off, width=configuration['silk_line_width'], layer='F.SilkS')) kicad_mod.append(PolygoneLine(polygone=tap_off, y_mirror=B/2, width=configuration['silk_line_width'], layer='F.SilkS')) bounding_box['top'] = y1 - TL bounding_box['bottom'] = y2 + TL #inner-tab T = 2 tab = [ {'y': y1-off,'x': x_loc-TW/2-off+T}, {'y': y1-off-TL+T,'x': x_loc-TW/2-off+T}, {'y': y1-off-TL+T,'x': x_loc+TW/2+off-T}, {'y': y1-off,'x': x_loc+TW/2+off-T}, ] kicad_mod.append(PolygoneLine(polygone=tab, width=configuration['silk_line_width'], layer='F.SilkS')) kicad_mod.append(PolygoneLine(polygone=tab,y_mirror=B/2, width=configuration['silk_line_width'], layer='F.SilkS')) #pin-1 marker x = x1 - 1.5 m = 0.4 pin = [ {'x': x,'y': 0}, {'x': x-2*m,'y': -m}, {'x': x-2*m,'y': +m}, {'x': x,'y': 0}, ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['silk_line_width'], layer='F.SilkS')) sl=3 pin = [ {'x': body_edge['left'], 'y': -sl/2}, {'x': body_edge['left'] + sl/sqrt(2), 'y': 0}, {'x': body_edge['left'], 'y': sl/2} ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(idx, pincount, series_definition, configuration, group_definition): if 'mpn_param_1' in series_definition: mpn_param_1 = series_definition['mpn_param_1'] mpn = series_definition['mpn_format_string'].format( pincount=pincount, param_1=mpn_param_1[idx]) else: mpn = series_definition['mpn_format_string'].format(pincount=pincount) pins_toward_bottom = series_definition['pad1_position'] == 'bottom-left' needs_additional_silk_pin1_marker = False pad_size = [ series_definition['pad_size_x'], series_definition['rel_pad_y_outside_edge'] - series_definition['rel_pad_y_inside_edge'] ] pad_pos_y = -series_definition['rel_pad_y_outside_edge'] / 2 + pad_size[ 1] / 2 mounting_pad_size = series_definition['mounting_pad_size'] mount_pad_y_pos = series_definition[ 'rel_pad_y_outside_edge'] / 2 - mounting_pad_size[1] / 2 if 'center_shift_y' in series_definition: mount_pad_y_pos -= series_definition['center_shift_y'] pad_pos_y -= series_definition['center_shift_y'] mount_pad_center_x_to_pin = series_definition[ 'center_pad_to_mounting_pad_edge'] + mounting_pad_size[0] / 2.0 # center pin 1 to center pin n dimension_A = (pincount - 1) * series_definition['pitch'] body_edge = {} if pins_toward_bottom: pad_pos_y *= -1 mount_pad_y_pos *= -1 mount_pad_edge_y_outside = mount_pad_y_pos - mounting_pad_size[1] / 2 body_edge['top'] = mount_pad_edge_y_outside - series_definition[ 'rel_body_edge_y'] body_edge[ 'bottom'] = body_edge['top'] + series_definition['body_size_y'] else: mount_pad_edge_y_outside = mount_pad_y_pos + mounting_pad_size[1] / 2 body_edge['bottom'] = mount_pad_edge_y_outside + series_definition[ 'rel_body_edge_y'] body_edge[ 'top'] = body_edge['bottom'] - series_definition['body_size_y'] body_edge['right'] = dimension_A / 2 + series_definition['rel_body_edge_x'] body_edge['left'] = -body_edge['right'] orientation = configuration['orientation_options'][ series_definition['orientation']] footprint_name = configuration['fp_name_format_string'].format( man=group_definition['manufacturer'], series=series_definition['series'], mpn=mpn, num_rows=1, pins_per_row=pincount, pitch=series_definition['pitch'], orientation=orientation) footprint_name = footprint_name.replace('__', '_') kicad_mod = Footprint(footprint_name) kicad_mod.setDescription( "{:s} {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator" .format(group_definition['manufacturer'], series_definition['series'], mpn, series_definition['datasheet'])) kicad_mod.setAttribute('smd') kicad_mod.setTags(configuration['keyword_fp_string'].format( series=series_definition['series'], orientation=orientation, man=group_definition['manufacturer'], entry=configuration['entry_direction'][ series_definition['orientation']])) ############################# Pads ################################## kicad_mod.append( PadArray(center=[0, pad_pos_y], x_spacing=series_definition['pitch'], pincount=pincount, size=pad_size, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_SMT)) mount_pad_left_x_pos = -dimension_A / 2 - mount_pad_center_x_to_pin kicad_mod.append( Pad(number='""', type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[mount_pad_left_x_pos, mount_pad_y_pos], size=mounting_pad_size, layers=Pad.LAYERS_SMT)) kicad_mod.append( Pad(number='""', type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[-mount_pad_left_x_pos, mount_pad_y_pos], size=mounting_pad_size, layers=Pad.LAYERS_SMT)) ######################### Body outline ############################### pad_edge_silk_center_offset = configuration[ 'silk_pad_clearance'] + configuration['silk_line_width'] / 2 pad_1_x_outside_edge = -dimension_A / 2 - pad_size[0] / 2 if pins_toward_bottom: #Man i wish there where a rotate footprint function available. body_edge_pin = body_edge['bottom'] body_edge_mount_pad = body_edge['top'] silk_y_mp_pin_side = mount_pad_y_pos + mounting_pad_size[ 1] / 2 + pad_edge_silk_center_offset mp_edge_outside = mount_pad_y_pos - mounting_pad_size[1] / 2 silk_y_mp_outside = mp_edge_outside - pad_edge_silk_center_offset pin_edge_outside = pad_pos_y + pad_size[1] / 2 silk_y_offset_pin_side = configuration['silk_fab_offset'] else: body_edge_pin = body_edge['top'] body_edge_mount_pad = body_edge['bottom'] silk_y_mp_pin_side = mount_pad_y_pos - mounting_pad_size[ 1] / 2 - pad_edge_silk_center_offset mp_edge_outside = mount_pad_y_pos + mounting_pad_size[1] / 2 silk_y_mp_outside = mp_edge_outside + pad_edge_silk_center_offset pin_edge_outside = pad_pos_y - pad_size[1] / 2 silk_y_offset_pin_side = -configuration['silk_fab_offset'] # Pin side bounding_box_y_pin_side = pad_pos_y + ( pad_size[1] / 2 if pins_toward_bottom else -pad_size[1] / 2) side_line_y_pin_side = body_edge_pin mp_inner_edge_x_left_silk = mount_pad_left_x_pos + mounting_pad_size[ 0] / 2 + pad_edge_silk_center_offset modified_pinside_x_inner = body_edge['left'] if 'edge_modifier_pin_side' in series_definition: modifier = series_definition['edge_modifier_pin_side'] modified_pinside_x_inner = body_edge['left'] + modifier['width'] if pins_toward_bottom: side_line_y_pin_side += modifier['length'] if side_line_y_pin_side > bounding_box_y_pin_side: bounding_box_y_pin_side = side_line_y_pin_side else: side_line_y_pin_side -= modifier['length'] if side_line_y_pin_side < bounding_box_y_pin_side: bounding_box_y_pin_side = side_line_y_pin_side poly_fab_pin_side = [{ 'x': body_edge['left'], 'y': side_line_y_pin_side }, { 'x': modified_pinside_x_inner, 'y': side_line_y_pin_side }, { 'x': modified_pinside_x_inner, 'y': body_edge_pin }, { 'x': -modified_pinside_x_inner, 'y': body_edge_pin }, { 'x': -modified_pinside_x_inner, 'y': side_line_y_pin_side }, { 'x': body_edge['right'], 'y': side_line_y_pin_side }] if modifier['length'] < 0: silk_x_offset = -configuration['silk_fab_offset'] else: silk_x_offset = configuration['silk_fab_offset'] if modified_pinside_x_inner + silk_x_offset > pad_1_x_outside_edge - pad_edge_silk_center_offset: poly_silk_edge_left = [{ 'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': silk_y_mp_pin_side }, { 'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': side_line_y_pin_side + silk_y_offset_pin_side }, { 'x': pad_1_x_outside_edge - pad_edge_silk_center_offset, 'y': side_line_y_pin_side + silk_y_offset_pin_side }, { 'x': pad_1_x_outside_edge - pad_edge_silk_center_offset, 'y': pin_edge_outside }] if abs(pin_edge_outside) - abs( side_line_y_pin_side + silk_y_offset_pin_side ) < configuration['silk_line_lenght_min']: needs_additional_silk_pin1_marker = True poly_silk_edge_right = [{ 'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': silk_y_mp_pin_side }, { 'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': side_line_y_pin_side + silk_y_offset_pin_side }, { 'x': -pad_1_x_outside_edge + pad_edge_silk_center_offset, 'y': side_line_y_pin_side + silk_y_offset_pin_side }] else: poly_silk_edge_left = [{ 'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': silk_y_mp_pin_side }, { 'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': side_line_y_pin_side + silk_y_offset_pin_side }, { 'x': modified_pinside_x_inner + silk_x_offset, 'y': side_line_y_pin_side + silk_y_offset_pin_side }, { 'x': modified_pinside_x_inner + silk_x_offset, 'y': body_edge_pin + silk_y_offset_pin_side }, { 'x': pad_1_x_outside_edge - pad_edge_silk_center_offset, 'y': body_edge_pin + silk_y_offset_pin_side }, { 'x': pad_1_x_outside_edge - pad_edge_silk_center_offset, 'y': pin_edge_outside }] if abs(pin_edge_outside) - abs( body_edge_pin + silk_y_offset_pin_side ) < configuration['silk_line_lenght_min']: needs_additional_silk_pin1_marker = True poly_silk_edge_right = [{ 'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': silk_y_mp_pin_side }, { 'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': side_line_y_pin_side + silk_y_offset_pin_side }, { 'x': -modified_pinside_x_inner - silk_x_offset, 'y': side_line_y_pin_side + silk_y_offset_pin_side }, { 'x': -modified_pinside_x_inner - silk_x_offset, 'y': body_edge_pin + silk_y_offset_pin_side }, { 'x': -pad_1_x_outside_edge + pad_edge_silk_center_offset, 'y': body_edge_pin + silk_y_offset_pin_side }] else: poly_fab_pin_side = [{ 'x': body_edge['left'], 'y': body_edge_pin }, { 'x': body_edge['right'], 'y': body_edge_pin }] poly_silk_edge_left = [{ 'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': silk_y_mp_pin_side }, { 'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': side_line_y_pin_side + silk_y_offset_pin_side }, { 'x': pad_1_x_outside_edge - pad_edge_silk_center_offset, 'y': body_edge_pin + silk_y_offset_pin_side }, { 'x': pad_1_x_outside_edge - pad_edge_silk_center_offset, 'y': pin_edge_outside }] if abs(pin_edge_outside) - abs(body_edge_pin + silk_y_offset_pin_side) < configuration[ 'silk_line_lenght_min']: needs_additional_silk_pin1_marker = True poly_silk_edge_right = [{ 'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': silk_y_mp_pin_side }, { 'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': side_line_y_pin_side + silk_y_offset_pin_side }, { 'x': -pad_1_x_outside_edge + pad_edge_silk_center_offset, 'y': body_edge_pin + silk_y_offset_pin_side }] kicad_mod.append( PolygoneLine(polygone=poly_fab_pin_side, layer='F.Fab', width=configuration['fab_line_width'])) if series_definition.get('no_automatic_silk_autline', 'False') != 'True': kicad_mod.append( PolygoneLine(polygone=poly_silk_edge_left, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=poly_silk_edge_right, layer='F.SilkS', width=configuration['silk_line_width'])) # Mount pad side bounding_box_y_mount_pad_side = mount_pad_y_pos + ( -mounting_pad_size[1] / 2 if pins_toward_bottom else mounting_pad_size[1] / 2) if abs(bounding_box_y_mount_pad_side) < abs(body_edge_mount_pad): bounding_box_y_mount_pad_side = body_edge_mount_pad mid_line_y_mount_pad_side = body_edge_mount_pad if 'edge_modifier_mount_pad_side' in series_definition: modifier = series_definition['edge_modifier_mount_pad_side'] if 'width_start' in modifier: modified_mp_start_x_inner = -modifier[ 'width_start'] / 2 # We assume centered body! if 'start_from_body_side' in modifier: modified_mp_start_x_inner = body_edge['left'] + modifier[ 'start_from_body_side'] modified_mp_end_x_inner = modified_mp_start_x_inner if 'width_end' in modifier: modified_mp_end_x_inner = -modifier[ 'width_end'] / 2 # We assume centered body! if 'end_from_body_side' in modifier: modified_mp_end_x_inner = body_edge['left'] + modifier[ 'end_from_body_side'] if pins_toward_bottom: mid_line_y_mount_pad_side += modifier['depth'] if mid_line_y_mount_pad_side < bounding_box_y_mount_pad_side: bounding_box_y_mount_pad_side = mid_line_y_mount_pad_side else: mid_line_y_mount_pad_side -= modifier['depth'] if mid_line_y_mount_pad_side > bounding_box_y_mount_pad_side: bounding_box_y_mount_pad_side = mid_line_y_mount_pad_side if modifier['depth'] < 0: silk_x_offset = -configuration['silk_fab_offset'] else: silk_x_offset = configuration['silk_fab_offset'] poly_fab_mp_side = [{ 'x': body_edge['left'], 'y': body_edge_mount_pad }, { 'x': modified_mp_start_x_inner, 'y': body_edge_mount_pad }, { 'x': modified_mp_end_x_inner, 'y': mid_line_y_mount_pad_side }, { 'x': -modified_mp_end_x_inner, 'y': mid_line_y_mount_pad_side }, { 'x': -modified_mp_start_x_inner, 'y': body_edge_mount_pad }, { 'x': body_edge['right'], 'y': body_edge_mount_pad }] poly_silk_mp_side = [{ 'x': mp_inner_edge_x_left_silk, 'y': body_edge_mount_pad - silk_y_offset_pin_side }, { 'x': modified_mp_start_x_inner + silk_x_offset, 'y': body_edge_mount_pad - silk_y_offset_pin_side }, { 'x': modified_mp_end_x_inner + silk_x_offset, 'y': mid_line_y_mount_pad_side - silk_y_offset_pin_side }, { 'x': -modified_mp_end_x_inner - silk_x_offset, 'y': mid_line_y_mount_pad_side - silk_y_offset_pin_side }, { 'x': -modified_mp_start_x_inner - silk_x_offset, 'y': body_edge_mount_pad - silk_y_offset_pin_side }, { 'x': -mp_inner_edge_x_left_silk, 'y': body_edge_mount_pad - silk_y_offset_pin_side }] if modified_mp_start_x_inner + configuration[ 'silk_fab_offset'] < mp_inner_edge_x_left_silk: poly_silk_mp_side = [{ 'x': mp_inner_edge_x_left_silk, 'y': mid_line_y_mount_pad_side - silk_y_offset_pin_side }, { 'x': -mp_inner_edge_x_left_silk, 'y': mid_line_y_mount_pad_side - silk_y_offset_pin_side }] else: poly_fab_mp_side = [{ 'x': body_edge['left'], 'y': body_edge_mount_pad }, { 'x': body_edge['right'], 'y': body_edge_mount_pad }] poly_silk_mp_side = [{ 'x': mp_inner_edge_x_left_silk, 'y': body_edge_mount_pad - silk_y_offset_pin_side }, { 'x': -mp_inner_edge_x_left_silk, 'y': body_edge_mount_pad - silk_y_offset_pin_side }] if series_definition['rel_body_edge_y'] > pad_edge_silk_center_offset: poly_silk_mp_side[0]['x'] = body_edge['left'] poly_silk_mp_side[len(poly_silk_mp_side) - 1]['x'] = body_edge['right'] if series_definition[ 'rel_body_edge_y'] > pad_edge_silk_center_offset + configuration[ 'silk_line_lenght_min']: poly_silk_mp_side[0][ 'x'] = body_edge['left'] - configuration['silk_fab_offset'] poly_silk_mp_side[ len(poly_silk_mp_side) - 1]['x'] = body_edge['right'] + configuration['silk_fab_offset'] poly_silk_mp_side.insert( 0, { 'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': silk_y_mp_outside }) poly_silk_mp_side.append({ 'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': silk_y_mp_outside }) if series_definition.get('no_automatic_silk_autline', 'False') != 'True': kicad_mod.append( PolygoneLine(polygone=poly_silk_mp_side, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=poly_fab_mp_side, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append( Line(start=[body_edge['left'], side_line_y_pin_side], end=[body_edge['left'], body_edge_mount_pad], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append( Line(start=[body_edge['right'], side_line_y_pin_side], end=[body_edge['right'], body_edge_mount_pad], layer='F.Fab', width=configuration['fab_line_width'])) ###################### Additional Drawing ########################### if 'additional_drawing' in series_definition: for drawing in series_definition['additional_drawing']: parseAdditionalDrawing(kicad_mod, drawing, configuration, series_definition, body_edge, pincount) ############################# CrtYd ################################## mp_left_edge = mount_pad_left_x_pos - mounting_pad_size[0] / 2 bounding_box_x1 = body_edge[ 'left'] if body_edge['left'] < mp_left_edge else mp_left_edge bounding_box_x2 = -bounding_box_x1 if pins_toward_bottom: bounding_box_y1 = bounding_box_y_mount_pad_side bounding_box_y2 = bounding_box_y_pin_side else: bounding_box_y1 = bounding_box_y_pin_side bounding_box_y2 = bounding_box_y_mount_pad_side cx1 = roundToBase( bounding_box_x1 - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase( bounding_box_x2 + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase( bounding_box_y1 - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase( bounding_box_y2 + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append( RectLine(start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Pin 1 marker ############################## if series_definition['pad1_position'] == 'bottom-left': poly_pin1_marker = [{ 'x': -dimension_A / 2 - configuration['fab_pin1_marker_length'] / 2, 'y': body_edge['bottom'] }, { 'x': -dimension_A / 2, 'y': body_edge['bottom'] - configuration['fab_pin1_marker_length'] / sqrt(2) }, { 'x': -dimension_A / 2 + configuration['fab_pin1_marker_length'] / 2, 'y': body_edge['bottom'] }] poly_pin1_marker_small = [{ 'x': -dimension_A / 2 - configuration['fab_pin1_marker_length'] / 4, 'y': cy2 + configuration['fab_pin1_marker_length'] / sqrt(8) }, { 'x': -dimension_A / 2, 'y': cy2 }, { 'x': -dimension_A / 2 + configuration['fab_pin1_marker_length'] / 4, 'y': cy2 + configuration['fab_pin1_marker_length'] / sqrt(8) }, { 'x': -dimension_A / 2 - configuration['fab_pin1_marker_length'] / 4, 'y': cy2 + configuration['fab_pin1_marker_length'] / sqrt(8) }] else: poly_pin1_marker = [{ 'x': -dimension_A / 2 - configuration['fab_pin1_marker_length'] / 2, 'y': body_edge['top'] }, { 'x': -dimension_A / 2, 'y': body_edge['top'] + configuration['fab_pin1_marker_length'] / sqrt(2) }, { 'x': -dimension_A / 2 + configuration['fab_pin1_marker_length'] / 2, 'y': body_edge['top'] }] poly_pin1_marker_small = [{ 'x': -dimension_A / 2 - configuration['fab_pin1_marker_length'] / 4, 'y': cy1 - configuration['fab_pin1_marker_length'] / sqrt(8) }, { 'x': -dimension_A / 2, 'y': cy1 }, { 'x': -dimension_A / 2 + configuration['fab_pin1_marker_length'] / 4, 'y': cy1 - configuration['fab_pin1_marker_length'] / sqrt(8) }, { 'x': -dimension_A / 2 - configuration['fab_pin1_marker_length'] / 4, 'y': cy1 - configuration['fab_pin1_marker_length'] / sqrt(8) }] if modified_pinside_x_inner < -dimension_A / 2 - configuration[ 'fab_pin1_marker_length'] / 2: kicad_mod.append( PolygoneLine(polygone=poly_pin1_marker, layer='F.Fab', width=configuration['fab_line_width'])) else: kicad_mod.append( PolygoneLine(polygone=poly_pin1_marker_small, layer='F.Fab', width=configuration['fab_line_width'])) if needs_additional_silk_pin1_marker: kicad_mod.append( PolygoneLine(polygone=poly_pin1_marker_small, layer='F.SilkS', width=configuration['silk_line_width'])) ######################### Text Fields ############################### text_center = series_definition.get('text_inside_pos', 'center') addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={ 'top': cy1, 'bottom': cy2 }, fp_name=footprint_name, text_y_inside_position=text_center) ########################### file names ############################### model3d_path_prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format( man=group_definition['manufacturer'], series=series_definition['series']) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pol, n, configuration): off = configuration['silk_fab_offset'] CrtYd_offset = configuration['courtyard_offset']['default'] fp_name = 'Samtec_MECF-' + n + '-0_-' if pol == False: fp_name = fp_name + 'NP-' fp_name += 'L-DV' fp_name += '_{:d}x{:02d}_P{:.2f}mm'.format(2,int(n),1.27) if pol: fp_name += '_Polarized' fp_name += '_Edge' kicad_mod = Footprint(fp_name) description = "Highspeed card edge connector for PCB's with " + n + " contacts " if pol == True: description = description + '(polarized)' else: description = description + '(not polarized)' kicad_mod.setAttribute('virtual') #set the FP description kicad_mod.setDescription(description) tags = "conn samtec card-edge high-speed" #set the FP tags kicad_mod.setTags(tags) # set general values top = -(5.0) bot = (5.0) left = -(K[n]/2.0) right = (K[n]/2.0) body_edge={ 'left': left, 'right': right, 'top': top, 'bottom': bot } top_left = [left, top] bot_right = [ right, bot] # create Fab Back(exact outline) kicad_mod.append(Line(start=[left + 1.27, bot], end=[right, bot], layer='F.Fab', width=configuration['fab_line_width'])) #bot line kicad_mod.append(Line(start=[left, top], end=[ right, top], layer='F.Fab', width=configuration['fab_line_width'])) #top line kicad_mod.append(Line(start=[left, bot - 1.27], end=[left, top], layer='F.Fab', width=configuration['fab_line_width'])) #left line kicad_mod.append(Line(start=[right, bot], end=[ right, top], layer='F.Fab', width=configuration['fab_line_width'])) #right line kicad_mod.append(Line(start=[left, bot - 1.27], end=[left + 1.27, bot], layer='F.Fab', width=configuration['fab_line_width'])) #corner # create Fab Front(exact outline) kicad_mod.append(Line(start=[left, bot], end=[right, bot], layer='B.Fab', width=configuration['fab_line_width'])) #bot line kicad_mod.append(Line(start=[left, top], end=[ right, top], layer='B.Fab', width=configuration['fab_line_width'])) #top line kicad_mod.append(Line(start=[left, bot ], end=[left, top], layer='B.Fab', width=configuration['fab_line_width'])) #left line kicad_mod.append(Line(start=[right, bot], end=[ right, top], layer='B.Fab', width=configuration['fab_line_width'])) #right line top = top - off #bot = bot + 0.11 left = left - off right = right + off # create silscreen Back(exact + 0.11) kicad_mod.append(Line(start=[round(left, 2) + 1.27, round(bot, 2)], end=[round(right, 2), round(bot, 2)], layer='F.SilkS', width=configuration['silk_line_width'])) #bot line kicad_mod.append(Line(start=[round(left, 2), round(top, 2)], end=[round(right, 2), round(top, 2)], layer='F.SilkS', width=configuration['silk_line_width'])) #top line kicad_mod.append(Line(start=[round(left, 2), round(bot, 2) - 1.27], end=[round(left, 2), round(top, 2)], layer='F.SilkS', width=configuration['silk_line_width'])) #left line kicad_mod.append(Line(start=[round(right, 2), round( bot, 2)], end=[round(right, 2), round(top, 2)], layer='F.SilkS', width=configuration['silk_line_width'])) #right line kicad_mod.append(Line(start=[round(left, 2) + 1.27, round(bot, 2) ], end=[round(left, 2), round(bot, 2) - 1.27], layer='F.SilkS', width=configuration['silk_line_width'])) #corner # create silscreen Front(exact + 0.11) kicad_mod.append(Line(start=[round(left, 2), round(bot, 2)], end=[round(right, 2), round(bot, 2)], layer='B.SilkS', width=configuration['silk_line_width'])) #bot line kicad_mod.append(Line(start=[round(left, 2), round(top, 2)], end=[round(right, 2), round(top, 2)], layer='B.SilkS', width=configuration['silk_line_width'])) #top line kicad_mod.append(Line(start=[round(left, 2), round(bot, 2)], end=[round(left, 2), round(top, 2)], layer='B.SilkS', width=configuration['silk_line_width'])) #left line kicad_mod.append(Line(start=[round(right, 2), round( bot, 2)], end=[round(right, 2), round(top, 2)], layer='B.SilkS', width=configuration['silk_line_width'])) #right line top = roundToBase(body_edge['top'] - CrtYd_offset, configuration['courtyard_grid']) bot = roundToBase(body_edge['bottom'], configuration['courtyard_grid']) left = roundToBase(body_edge['left'] - CrtYd_offset, configuration['courtyard_grid']) right = roundToBase(body_edge['right'] + CrtYd_offset, configuration['courtyard_grid']) cy1 = top cy2 = bot # create courtyard (exact + 0.25) kicad_mod.append(RectLine(start=[left, top], end=[right , bot], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(RectLine(start=[left, top], end=[right , bot], layer='B.CrtYd', width=configuration['courtyard_line_width'])) top = body_edge['top'] bot = body_edge['bottom'] slot_height = 7.0 ## create cutout kicad_mod.append(Line(start=[-K[n]/2.0, bot, 2], end=[-K[n]/2.0, top, 2], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #left line kicad_mod.append(Line(start=[K[n]/2.0, bot, 2], end=[K[n]/2.0, top], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #right line ## grid ends nextGrid = math.ceil((K[n]/2.0)/0.25 + 1.0) * 0.25 #nextGrid = roundToBase(K[n]/2, 0.25) kicad_mod.append(Line(start=[-nextGrid, top, 2], end=[-K[n]/2.0, top, 2], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #left line kicad_mod.append(Line(start=[+nextGrid, top, 2], end=[K[n]/2.0, top], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #right line if pol == True: # Cutouts kicad_mod.append(Line(start=[-K[n]/2.0, bot], end=[-K[n]/2.0+L[n]-1.24/2.0, bot], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #bot line kicad_mod.append(Line(start=[-K[n]/2.0+L[n]-1.24/2.0, bot], end=[-K[n]/2.0+L[n]-1.24/2.0, bot - slot_height], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #up kicad_mod.append(Line(start=[-K[n]/2.0+L[n]+1.24/2.0, bot], end=[-K[n]/2.0+L[n]+1.24/2.0, bot - slot_height], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #down kicad_mod.append(Line(start=[-K[n]/2.0+L[n]-1.24/2.0, bot - slot_height], end=[-K[n]/2.0+L[n]+1.24/2.0, bot - slot_height], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #cut if n in ['60','70']: kicad_mod.append(Line(start=[-K[n]/2.0+L[n]+1.24/2.0, bot], end=[-K[n]/2.0+M[n]-1.24/2.0, bot], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #bot line kicad_mod.append(Line(start=[-K[n]/2.0+M[n]-1.24/2.0, bot], end=[-K[n]/2.0+M[n]-1.24/2.0, bot - slot_height], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #up kicad_mod.append(Line(start=[-K[n]/2.0+M[n]+1.24/2.0, bot], end=[-K[n]/2.0+M[n]+1.24/2.0, bot - slot_height], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #down kicad_mod.append(Line(start=[-K[n]/2.0+M[n]-1.24/2.0, bot - slot_height], end=[-K[n]/2.0+M[n]+1.24/2.0, bot - slot_height], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #cut kicad_mod.append(Line(start=[-K[n]/2.0+M[n]+1.24/2.0, bot], end=[K[n]/2.0, bot], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #bot line else: kicad_mod.append(Line(start=[-K[n]/2.0+L[n]+1.24/2.0, bot], end=[K[n]/2.0, bot], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #bot line else: kicad_mod.append(Line(start=[-K[n]/2.0, bot], end=[K[n]/2.0, bot], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #bot line # create pads for i in range(0,int(n)): start = - K[n]/2.0 + 1.52 if pol == True: if (i*2+1) not in POL[n]: kicad_mod.append(Pad(number=i*2 + 1, type=pad_type, shape=Pad.SHAPE_RECT, at=[start + i*1.27, bot - 2.0 - 0.5], size=pad_size, layers=layers_top)) kicad_mod.append(Pad(number=i*2 + 2, type=pad_type, shape=Pad.SHAPE_RECT, at=[start + i*1.27, bot - 2.0 - 0.5], size=pad_size, layers=layers_bottom)) else: kicad_mod.append(Pad(number=i*2 + 1, type=pad_type, shape=Pad.SHAPE_RECT, at=[start + i*1.27, bot - 2.0 - 0.5], size=pad_size, layers=layers_top)) kicad_mod.append(Pad(number=i*2 + 2, type=pad_type, shape=Pad.SHAPE_RECT, at=[start + i*1.27, bot - 2.0 - 0.5], size=pad_size, layers=layers_bottom)) # output kicad model #print(kicad_mod # print render tree #print(kicad_mod.getRenderTree()) #print(kicad_mod.getCompleteRenderTree()) # kicad_mod.append(Text(type='reference', text='REF**', at=[0,-6.35], layer='F.SilkS')) # kicad_mod.append(Text(type='user', text='%R', at=[0,-2.54], layer='F.Fab')) # kicad_mod.append(Text(type='value', text=fp_name, at=[0,-3.81], layer='F.Fab')) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=fp_name, text_y_inside_position=-2.54) lib_name = configuration['lib_name_specific_function_format_string'].format(category=lib_name_category) 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=fp_name) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins_per_row, configuration): mpn = part_code.format(n=pins_per_row * number_of_rows) alt_mpn = [ code.format(n=pins_per_row * number_of_rows) for code in alternative_codes ] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format( man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad="", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription( "Molex {:s}, {:s} (compatible alternatives: {:s}), {:d} Pins per row ({:s}), generated with kicad-footprint-generator" .format(series_long, mpn, ', '.join(alt_mpn), pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format( series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate fp dimensions A = (pins_per_row - 1) * pitch B = A + 3.1 C = A + 4 #connector thickness T = 5.75 #corners x1 = -2 x2 = x1 + C T = 3.65 y1 = -1.5 y2 = y1 + T off = configuration['silk_fab_offset'] pad_silk_off = configuration[ 'silk_pad_clearance'] + configuration['silk_line_width'] / 2 body_edge = {'left': x1, 'right': x2, 'bottom': y2, 'top': y1} bounding_box = body_edge.copy() #add simple outline to F.Fab layer kicad_mod.append( RectLine(start=[x1, y1], end=[x2, y2], layer='F.Fab', width=configuration['fab_line_width'])) #wall-thickness W w = 0.4 #offset o = configuration['silk_fab_offset'] x1 -= o y1 -= o x2 += o y2 += o #generate the pads kicad_mod.append( PadArray(pincount=pins_per_row, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT)) #draw the courtyard #draw the connector outline out = RectLine(start=[x1, y1], end=[x2, y2], width=configuration['silk_line_width'], layer="F.SilkS") kicad_mod.append(out) #pin-1 marker y = -2 m = 0.3 O = 0.3 L = 2 pin = [ { 'x': x1 + L, 'y': y1 - O }, { 'x': x1 - O, 'y': y1 - O }, { 'x': x1 - O, 'y': y1 + L }, ] kicad_mod.append( PolygoneLine(polygone=pin, width=configuration['silk_line_width'], layer="F.SilkS")) p1m_sl = 1 pin = [{ 'x': -p1m_sl / 2, 'y': body_edge['top'] }, { 'x': 0, 'y': body_edge['top'] + p1m_sl / sqrt(2) }, { 'x': p1m_sl / 2, 'y': body_edge['top'] }] kicad_mod.append( PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) kicad_mod.append( Line(start=[x1, 2 * w], end=[x1 + w, 2 * w], width=configuration['silk_line_width'], layer="F.SilkS")) kicad_mod.append( Line(start=[x2, 2 * w], end=[x2 - w, 2 * w], width=configuration['silk_line_width'], layer="F.SilkS")) #add the 'wall' wall = [ { 'x': A / 2, 'y': y1 + w }, { 'x': x1 + w, 'y': y1 + w }, { 'x': x1 + w, 'y': 0 }, { 'x': x1 + 2 * w, 'y': 0 }, { 'x': x1 + 2 * w, 'y': w }, { 'x': x1 + w, 'y': w }, { 'x': x1 + w, 'y': y2 }, ] kicad_mod.append( PolygoneLine(polygone=wall, width=configuration['silk_line_width'], layer="F.SilkS")) kicad_mod.append( PolygoneLine(polygone=wall, x_mirror=A / 2, width=configuration['silk_line_width'], layer="F.SilkS")) ########################### CrtYd ################################# cx1 = roundToBase( bounding_box['left'] - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase( bounding_box['top'] - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase( bounding_box['right'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase( bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append( RectLine(start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={ 'top': cy1, 'bottom': cy2 }, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins_per_row, variant, configuration): mpn = variant_params[variant]['part_code'].format(n=pins_per_row*number_of_rows) alt_mpn = [code.format(n=pins_per_row*number_of_rows) for code in variant_params[variant]['alternative_codes']] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s} (compatible alternatives: {:s}), {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, ', '.join(alt_mpn), pins_per_row, variant_params[variant]['datasheet'])) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #kicad_mod.setAttribute('smd') ########################## Dimensions ############################## B = (pins_per_row-1)*pitch A = B + 6.65 C = B + variant_params[variant]['C_minus_B'] pad_y = 0 pad1_x = 0 peg1_x = (B-C)/2 peg2_x = (B+C)/2 peg_y = pad_y - 1.96 tab_w = 1.4 tab_l = 1.4 body_edge={ 'left': (B-A)/2, 'right': (A+B)/2, 'top': -2.47+0.5 } body_edge['bottom'] = body_edge['top'] + (4.37-0.5) y_top_min = -2.47 chamfer={'x': 1.2, 'y': 0.63} ############################# Pads ################################## # # Pegs # kicad_mod.append(Pad(at=[peg1_x, peg_y], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(at=[peg2_x, peg_y], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) # # Add pads # optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(start=[pad1_x, pad_y], initial=1, pincount=pins_per_row, increment=1, x_spacing=pitch, size=pad_size, type=Pad.TYPE_THT, shape=pad_shape, layers=Pad.LAYERS_THT, drill=drill, **optional_pad_params)) ######################## Fabrication Layer ########################### main_body_poly= [ {'x': body_edge['left'] + chamfer['x'], 'y': body_edge['top']}, {'x': body_edge['left'] + chamfer['x'], 'y': y_top_min}, {'x': body_edge['left'], 'y': y_top_min}, {'x': body_edge['left'], 'y': body_edge['bottom']}, {'x': body_edge['right'], 'y': body_edge['bottom']}, {'x': body_edge['right'], 'y': y_top_min}, {'x': body_edge['right'] - chamfer['x'], 'y': y_top_min}, {'x': body_edge['right'] - chamfer['x'], 'y': body_edge['top']}, {'x': body_edge['left'] + chamfer['x'], 'y': body_edge['top']} ] kicad_mod.append(PolygoneLine(polygone=main_body_poly, width=configuration['fab_line_width'], layer="F.Fab")) kicad_mod.append(Line( start={ 'x': body_edge['left'], 'y': body_edge['top'] + chamfer['y'] }, end={ 'x': body_edge['left'] + chamfer['x'], 'y': body_edge['top'] }, width=configuration['fab_line_width'], layer="F.Fab" )) kicad_mod.append(Line( start={ 'x': body_edge['right'], 'y': body_edge['top'] + chamfer['y'] }, end={ 'x': body_edge['right'] - chamfer['x'], 'y': body_edge['top'] }, width=configuration['fab_line_width'], layer="F.Fab" )) tab_poly = [ {'x': B/2-tab_l/2, 'y': body_edge['bottom']}, {'x': B/2-tab_l/2, 'y': body_edge['bottom'] + tab_w}, {'x': B/2+tab_l/2, 'y': body_edge['bottom'] + tab_w}, {'x': B/2+tab_l/2, 'y': body_edge['bottom']}, ] kicad_mod.append(PolygoneLine(polygone=tab_poly, width=configuration['fab_line_width'], layer="F.Fab")) p1m_sl = 1 p1m_poly = tab_poly = [ {'x': pad1_x - p1m_sl/2, 'y': body_edge['top']}, {'x': pad1_x, 'y': body_edge['top'] + p1m_sl/sqrt(2)}, {'x': pad1_x + p1m_sl/2, 'y': body_edge['top']} ] kicad_mod.append(PolygoneLine(polygone=tab_poly, width=configuration['fab_line_width'], layer="F.Fab")) ############################ SilkS ################################## # Top left corner silk_pad_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 xmp_top1 = peg1_x + peg_drill/2 + silk_pad_off xmp_top2 = peg2_x - peg_drill/2 - silk_pad_off ymp_bottom = peg_y + peg_drill/2 + silk_pad_off off = configuration['silk_fab_offset'] poly_s_b = [ {'x': body_edge['left'] - off, 'y': ymp_bottom}, {'x': body_edge['left'] - off, 'y': body_edge['bottom'] + off}, {'x': body_edge['right'] + off, 'y': body_edge['bottom'] + off}, {'x': body_edge['right'] + off, 'y': ymp_bottom}, ] kicad_mod.append(PolygoneLine(polygone=poly_s_b, width=configuration['silk_line_width'], layer="F.SilkS")) poly_s_t = [ {'x': xmp_top1 + off, 'y': y_top_min - off}, {'x': body_edge['left'] + chamfer['x'] + off, 'y': y_top_min - off}, {'x': body_edge['left'] + chamfer['x'] + off, 'y': body_edge['top'] - off}, {'x': body_edge['right'] - chamfer['x'] - off, 'y': body_edge['top'] - off}, {'x': body_edge['right'] - chamfer['x'] - off, 'y': y_top_min - off}, {'x': xmp_top2 - off, 'y': y_top_min - off}, ] kicad_mod.append(PolygoneLine(polygone=poly_s_t, width=configuration['silk_line_width'], layer="F.SilkS")) ############################ CrtYd ################################## CrtYd_offset = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] cy_top = roundToBase(y_top_min - CrtYd_offset, CrtYd_grid) cy_bottom = roundToBase(body_edge['bottom'] + tab_w + CrtYd_offset, CrtYd_grid) cy_left = roundToBase(body_edge['left'] - CrtYd_offset, CrtYd_grid) cy_right = roundToBase(body_edge['right'] + CrtYd_offset, CrtYd_grid) poly_cy = [ {'x': cy_left, 'y':cy_top}, {'x': cy_right, 'y':cy_top}, {'x': cy_right, 'y':cy_bottom}, {'x': cy_left, 'y':cy_bottom}, {'x': cy_left, 'y':cy_top}, ] kicad_mod.append(PolygoneLine(polygone=poly_cy, layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy_top, 'bottom':cy_bottom}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins, params, configuration): pad_silk_off = configuration[ 'silk_pad_clearance'] + configuration['silk_line_width'] / 2 mpn = params['mpn'].format(n=pins * params['number_of_rows']) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format( man=manufacturer, series=series, mpn=mpn, num_rows=params['number_of_rows'], pins_per_row=pins_per_row, pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) desc_format_str = "Molex {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription( desc_format_str.format(series_long, mpn, pins, params['datasheet'])) kicad_mod.setTags(configuration['keyword_fp_string'].format( series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) if params['number_of_rows'] == 2: pad_size = [ pitch_row - pad_to_pad_clearance, pitch - pad_to_pad_clearance ] else: pad_size = [drill + 2 * max_annular_ring, pitch - pad_to_pad_clearance] if pad_size[1] - drill < 2 * min_annular_ring: pad_size[1] = drill + 2 * min_annular_ring if pad_size[1] - drill > 2 * max_annular_ring: pad_size[1] = drill + 2 * max_annular_ring if pad_size[0] - drill < 2 * min_annular_ring: pad_size[0] = drill + 2 * min_annular_ring if pad_size[0] - drill > 2 * max_annular_ring: pad_size[0] = drill + 2 * max_annular_ring pad_shape = Pad.SHAPE_OVAL if pad_size[0] == pad_size[1]: pad_shape = Pad.SHAPE_CIRCLE #A = connector length A = pins * pitch + 0.94 #B = pin center distance B = (pins - 1) * pitch #W = thickness of plastic base W = 8.46 #locating pin position C = B #corner positions for plastic housing outline y1 = -(A - B) / 2 y2 = y1 + A x2 = (params['number_of_rows'] - 1) * pitch_row + 10.38 x1 = x2 - W off = configuration['silk_fab_offset'] pad_silk_off = configuration[ 'silk_pad_clearance'] + configuration['silk_line_width'] / 2 body_edge = {'left': x1, 'right': x2, 'bottom': y2, 'top': y1} bounding_box = body_edge.copy() bounding_box['left'] = -pad_size[0] / 2 pad_silk_off = configuration[ 'silk_pad_clearance'] + configuration['silk_line_width'] / 2 #generate the pads for r in range(params['number_of_rows']): kicad_mod.append( PadArray(pincount=pins, initial=r * pins + 1, start=[r * pitch_row, 0], y_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT)) #add the locating pins y_loc_a = B / 2 - C / 2 y_loc_b = B / 2 + C / 2 x_loc = (params['number_of_rows'] - 1) * pitch_row + 7.18 r_loc = 1.7 kicad_mod.append( Pad(at=[x_loc, y_loc_a], size=r_loc, drill=r_loc, type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_NPTH)) kicad_mod.append( Pad(at=[x_loc, y_loc_b], size=r_loc, drill=r_loc, type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_NPTH)) #add outline to F.Fab kicad_mod.append( RectLine(start=[x1, y1], end=[x2, y2], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append( RectLine(start=[x1, y1], end=[x2, y2], offset=off, width=configuration['silk_line_width'], layer="F.SilkS")) #draw the pins for i in range(pins): y = i * pitch x = (params['number_of_rows'] - 1) * pitch_row + pad_size[0] / 2 + pad_silk_off w = 0.15 kicad_mod.append( RectLine(start=[x1 - off, y + w], end=[x, y - w], width=configuration['silk_line_width'], layer="F.SilkS")) #pin-1 marker y = -pad_size[1] / 2 - pad_silk_off m = 0.3 pin = [ { 'x': 0, 'y': y }, { 'x': m, 'y': y - m * sqrt(2) }, { 'x': -m, 'y': y - m * sqrt(2) }, { 'x': 0, 'y': y }, ] kicad_mod.append( PolygoneLine(polygone=pin, width=configuration['silk_line_width'], layer="F.SilkS")) kicad_mod.append( PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# cx1 = roundToBase( bounding_box['left'] - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase( bounding_box['top'] - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase( bounding_box['right'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase( bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append( RectLine(start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={ 'top': cy1, 'bottom': cy2 }, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def __createFootprintVariant(self, device_params, header, dimensions, with_thermal_vias): fab_line_width = self.configuration.get('fab_line_width', 0.1) silk_line_width = self.configuration.get('silk_line_width', 0.12) lib_name = self.configuration['lib_name_format_string'].format(category=header['library_Suffix']) size_x = dimensions['body_size_x'].nominal size_y = dimensions['body_size_y'].nominal pincount = device_params['num_pins_x']*2 + device_params['num_pins_y']*2 ipc_reference = 'ipc_spec_gw_large_pitch' if device_params['pitch'] >= 0.625 else 'ipc_spec_gw_small_pitch' if device_params.get('force_small_pitch_ipc_definition', False): ipc_reference = 'ipc_spec_gw_small_pitch' used_density = device_params.get('ipc_density', ipc_density) ipc_data_set = self.ipc_defintions[ipc_reference][used_density] ipc_round_base = self.ipc_defintions[ipc_reference]['round_base'] pitch = device_params['pitch'] name_format = self.configuration['fp_name_format_string_no_trailing_zero'] EP_size = {'x':0, 'y':0} EP_mask_size = {'x':0, 'y':0} if dimensions['has_EP']: name_format = self.configuration['fp_name_EP_format_string_no_trailing_zero'] if 'EP_size_x_overwrite' in device_params: EP_size = { 'x':device_params['EP_size_x_overwrite'], 'y':device_params['EP_size_y_overwrite'] } else: EP_size = { 'x':dimensions['EP_size_x'].nominal, 'y':dimensions['EP_size_y'].nominal } if 'EP_mask_x' in dimensions: name_format = self.configuration['fp_name_EP_custom_mask_format_string_no_trailing_zero'] EP_mask_size = {'x':dimensions['EP_mask_x'].nominal, 'y':dimensions['EP_mask_y'].nominal} EP_size = Vector2D(EP_size) pad_details = self.calcPadDetails(dimensions, EP_size, ipc_data_set, ipc_round_base) if 'custom_name_format' in device_params: name_format = device_params['custom_name_format'] suffix = device_params.get('suffix', '').format(pad_x=pad_details['left']['size'][0], pad_y=pad_details['left']['size'][1]) suffix_3d = suffix if device_params.get('include_suffix_in_3dpath', 'True') == 'True' else "" model3d_path_prefix = self.configuration.get('3d_model_prefix','${KISYS3DMOD}') fp_name = name_format.format( man=device_params.get('manufacturer',''), mpn=device_params.get('part_number',''), pkg=header['device_type'], pincount=pincount, size_y=size_y, size_x=size_x, pitch=device_params['pitch'], ep_size_x = EP_size['x'], ep_size_y = EP_size['y'], mask_size_x = EP_mask_size['x'], mask_size_y = EP_mask_size['y'], suffix=suffix, suffix2="", vias=self.configuration.get('thermal_via_suffix', '_ThermalVias') if with_thermal_vias else '' ).replace('__','_').lstrip('_') fp_name_2 = name_format.format( man=device_params.get('manufacturer',''), mpn=device_params.get('part_number',''), pkg=header['device_type'], pincount=pincount, size_y=size_y, size_x=size_x, pitch=device_params['pitch'], ep_size_x = EP_size['x'], ep_size_y = EP_size['y'], mask_size_x = EP_mask_size['x'], mask_size_y = EP_mask_size['y'], suffix=suffix_3d, suffix2="", vias='' ).replace('__','_').lstrip('_') model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'\ .format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=fp_name_2) #print(fp_name) #print(pad_details) kicad_mod = Footprint(fp_name) # init kicad footprint kicad_mod.setDescription( "{manufacturer} {mpn} {package}, {pincount} Pin ({datasheet}), generated with kicad-footprint-generator {scriptname}"\ .format( manufacturer = device_params.get('manufacturer',''), package = header['device_type'], mpn = device_params.get('part_number',''), pincount = pincount, datasheet = device_params['size_source'], scriptname = os.path.basename(__file__).replace(" ", " ") ).lstrip()) kicad_mod.setTags(self.configuration['keyword_fp_string']\ .format( man=device_params.get('manufacturer',''), package=header['device_type'], category=header['library_Suffix'] ).lstrip()) 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'] EP_round_radius = 0 if dimensions['has_EP']: EP_mask_size = EP_mask_size if EP_mask_size['x'] > 0 else None if with_thermal_vias: thermals = device_params['thermal_vias'] paste_coverage = thermals.get('EP_paste_coverage', device_params.get('EP_paste_coverage', DEFAULT_PASTE_COVERAGE)) EP = ExposedPad( number=pincount+1, size=EP_size, mask_size=EP_mask_size, paste_layout=thermals.get('EP_num_paste_pads'), paste_coverage=paste_coverage, via_layout=thermals.get('count', 0), paste_between_vias=thermals.get('paste_between_vias'), paste_rings_outside=thermals.get('paste_rings_outside'), via_drill=thermals.get('drill', 0.3), via_grid=thermals.get('grid'), paste_avoid_via=thermals.get('paste_avoid_via', True), via_paste_clarance=thermals.get('paste_via_clearance', DEFAULT_VIA_PASTE_CLEARANCE), min_annular_ring=thermals.get('min_annular_ring', DEFAULT_MIN_ANNULAR_RING), bottom_pad_min_size=thermals.get('bottom_min_size', 0), **pad_shape_details ) else: EP = ExposedPad( number=pincount+1, size=EP_size, mask_size=EP_mask_size, paste_layout=device_params.get('EP_num_paste_pads', 1), paste_coverage=device_params.get('EP_paste_coverage', DEFAULT_PASTE_COVERAGE), **pad_shape_details ) kicad_mod.append(EP) EP_round_radius = EP.getRoundRadius() pad_radius = add_dual_or_quad_pad_border(kicad_mod, configuration, pad_details, device_params) body_edge = { 'left': -dimensions['body_size_x'].nominal/2, 'right': dimensions['body_size_x'].nominal/2, 'top': -dimensions['body_size_y'].nominal/2, 'bottom': dimensions['body_size_y'].nominal/2 } bounding_box = { 'left': pad_details['left']['center'][0] - pad_details['left']['size'][0]/2, 'right': pad_details['right']['center'][0] + pad_details['right']['size'][0]/2, 'top': pad_details['top']['center'][1] - pad_details['top']['size'][1]/2, 'bottom': pad_details['bottom']['center'][1] + pad_details['bottom']['size'][1]/2 } if device_params['num_pins_x'] == 0: bounding_box['top'] = body_edge['top'] bounding_box['bottom'] = body_edge['bottom'] if EP_size['y'] > dimensions['body_size_y'].nominal: bounding_box['top'] = -EP_size['y']/2 bounding_box['bottom'] = EP_size['y']/2 if device_params['num_pins_y'] == 0: bounding_box['left'] = body_edge['left'] bounding_box['right'] = body_edge['right'] if EP_size['x'] > dimensions['body_size_x'].nominal: bounding_box['left'] = -EP_size['x']/2 bounding_box['right'] = EP_size['x']/2 pad_width = pad_details['top']['size'][0] # ############################ SilkS ################################## silk_pad_offset = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 silk_offset = configuration['silk_fab_offset'] right_pads_silk_bottom = (device_params['num_pins_y']-1)*device_params['pitch']/2\ +pad_details['right']['size'][1]/2+silk_pad_offset silk_bottom = body_edge['bottom']+silk_offset if EP_size['y']/2 <= body_edge['bottom'] and right_pads_silk_bottom >= silk_bottom: silk_bottom = max(silk_bottom, EP_size['y']/2+silk_pad_offset) silk_bottom = max(silk_bottom, right_pads_silk_bottom) silk_bottom = min(body_edge['bottom']+silk_pad_offset, silk_bottom) bottom_pads_silk_right = (device_params['num_pins_x']-1)*device_params['pitch']/2\ +pad_details['bottom']['size'][0]/2+silk_pad_offset silk_right = body_edge['right']+silk_offset if EP_size['x']/2 <= body_edge['right'] and bottom_pads_silk_right >= silk_right: silk_right = max(silk_right, EP_size['x']/2+silk_pad_offset) silk_right = max(silk_right, bottom_pads_silk_right) silk_right = min(body_edge['right']+silk_pad_offset, silk_right) min_lenght = configuration.get('silk_line_lenght_min', 0) silk_corner_bottom_right = Vector2D(silk_right, silk_bottom) silk_point_bottom_inside = nearestSilkPointOnOrthogonalLine( pad_size=EP_size, pad_position=[0, 0], pad_radius=EP_round_radius, fixed_point=silk_corner_bottom_right, moving_point=Vector2D(0, silk_bottom), silk_pad_offset=silk_pad_offset, min_lenght=min_lenght) if silk_point_bottom_inside is not None and device_params['num_pins_x'] > 0: silk_point_bottom_inside = nearestSilkPointOnOrthogonalLine( pad_size=pad_details['bottom']['size'], pad_position=[ pad_details['bottom']['center'][0]+(device_params['num_pins_x']-1)/2*pitch, pad_details['bottom']['center'][1]], pad_radius=pad_radius, fixed_point=silk_corner_bottom_right, moving_point=silk_point_bottom_inside, silk_pad_offset=silk_pad_offset, min_lenght=min_lenght) silk_point_right_inside = nearestSilkPointOnOrthogonalLine( pad_size=EP_size, pad_position=[0, 0], pad_radius=EP_round_radius, fixed_point=silk_corner_bottom_right, moving_point=Vector2D(silk_right, 0), silk_pad_offset=silk_pad_offset, min_lenght=min_lenght) if silk_point_right_inside is not None and device_params['num_pins_y'] > 0: silk_point_right_inside = nearestSilkPointOnOrthogonalLine( pad_size=pad_details['right']['size'], pad_position=[ pad_details['right']['center'][0], pad_details['right']['center'][1]+(device_params['num_pins_y']-1)/2*pitch], pad_radius=pad_radius, fixed_point=silk_corner_bottom_right, moving_point=silk_point_right_inside, silk_pad_offset=silk_pad_offset, min_lenght=min_lenght) if silk_point_bottom_inside is None and silk_point_right_inside is not None: silk_corner_bottom_right['y'] = body_edge['bottom'] silk_corner_bottom_right = nearestSilkPointOnOrthogonalLine( pad_size=pad_details['bottom']['size'], pad_position=[ pad_details['bottom']['center'][0]+(device_params['num_pins_x']-1)/2*pitch, pad_details['bottom']['center'][1]], pad_radius=pad_radius, fixed_point=silk_point_right_inside, moving_point=silk_corner_bottom_right, silk_pad_offset=silk_pad_offset, min_lenght=min_lenght) elif silk_point_right_inside is None and silk_point_bottom_inside is not None: silk_corner_bottom_right['x'] = body_edge['right'] silk_corner_bottom_right = nearestSilkPointOnOrthogonalLine( pad_size=pad_details['right']['size'], pad_position=[ pad_details['right']['center'][0], pad_details['right']['center'][1]+(device_params['num_pins_y']-1)/2*pitch], pad_radius=pad_radius, fixed_point=silk_point_bottom_inside, moving_point=silk_corner_bottom_right, silk_pad_offset=silk_pad_offset, min_lenght=min_lenght) poly_bottom_right = [] if silk_point_bottom_inside is not None: poly_bottom_right.append(silk_point_bottom_inside) poly_bottom_right.append(silk_corner_bottom_right) if silk_point_right_inside is not None: poly_bottom_right.append(silk_point_right_inside) if len(poly_bottom_right) > 1 and silk_corner_bottom_right is not None: kicad_mod.append(PolygoneLine( polygone=poly_bottom_right, width=configuration['silk_line_width'], layer="F.SilkS")) kicad_mod.append(PolygoneLine( polygone=poly_bottom_right, width=configuration['silk_line_width'], layer="F.SilkS", x_mirror=0)) kicad_mod.append(PolygoneLine( polygone=poly_bottom_right, width=configuration['silk_line_width'], layer="F.SilkS", y_mirror=0)) if device_params['num_pins_y'] > 0: if len(poly_bottom_right)>2: kicad_mod.append(PolygoneLine( polygone=poly_bottom_right, width=configuration['silk_line_width'], layer="F.SilkS", y_mirror=0, x_mirror=0)) kicad_mod.append(Line( start={'x': -silk_right, 'y': -right_pads_silk_bottom}, end={'x': bounding_box['left'], 'y': -right_pads_silk_bottom}, width=configuration['silk_line_width'], layer="F.SilkS")) elif silk_corner_bottom_right['y'] >= right_pads_silk_bottom and silk_point_bottom_inside is not None: kicad_mod.append(Line( start=-silk_point_bottom_inside, end={'x': bounding_box['left'], 'y': -silk_point_bottom_inside['y']}, width=configuration['silk_line_width'], layer="F.SilkS")) else: if len(poly_bottom_right)>2: poly_bottom_right[0]['x']=bottom_pads_silk_right kicad_mod.append(PolygoneLine( polygone=poly_bottom_right, width=configuration['silk_line_width'], layer="F.SilkS", y_mirror=0, x_mirror=0)) kicad_mod.append(Line( start={'x': -bottom_pads_silk_right, 'y': -silk_corner_bottom_right['y']}, end={'x': -bottom_pads_silk_right, 'y': bounding_box['top']}, width=configuration['silk_line_width'], layer="F.SilkS")) elif silk_corner_bottom_right['x'] >= bottom_pads_silk_right and silk_point_right_inside is not None: kicad_mod.append(Line( start=-silk_point_right_inside, end={'x': -silk_point_right_inside['x'], 'y': bounding_box['top']}, width=configuration['silk_line_width'], layer="F.SilkS")) # # ######################## Fabrication Layer ########################### fab_bevel_size = min(configuration['fab_bevel_size_absolute'], configuration['fab_bevel_size_relative']*min(size_x, size_y)) poly_fab = [ {'x': body_edge['left']+fab_bevel_size, 'y': body_edge['top']}, {'x': body_edge['right'], 'y': body_edge['top']}, {'x': body_edge['right'], 'y': body_edge['bottom']}, {'x': body_edge['left'], 'y': body_edge['bottom']}, {'x': body_edge['left'], 'y': body_edge['top']+fab_bevel_size}, {'x': body_edge['left']+fab_bevel_size, 'y': body_edge['top']}, ] kicad_mod.append(PolygoneLine( polygone=poly_fab, width=configuration['fab_line_width'], layer="F.Fab")) # # ############################ CrtYd ################################## off = ipc_data_set['courtyard'] grid = configuration['courtyard_grid'] if device_params['num_pins_y'] == 0 or device_params['num_pins_x'] == 0: cy1=roundToBase(bounding_box['top']-off, grid) kicad_mod.append(RectLine( start={ 'x':roundToBase(bounding_box['left']-off, grid), 'y':cy1 }, end={ 'x':roundToBase(bounding_box['right']+off, grid), 'y':roundToBase(bounding_box['bottom']+off, grid) }, width=configuration['courtyard_line_width'], layer='F.CrtYd')) else: cy1=roundToBase(bounding_box['top']-off, grid) cy2=roundToBase(body_edge['top']-off, grid) cy3=-roundToBase( device_params['pitch']*(device_params['num_pins_y']-1)/2.0 + pad_width/2.0 + off, grid) cx1=-roundToBase( device_params['pitch']*(device_params['num_pins_x']-1)/2.0 + pad_width/2.0 + off, grid) cx2=roundToBase(body_edge['left']-off, grid) cx3=roundToBase(bounding_box['left']-off, grid) crty_poly_tl = [ {'x':0, 'y':cy1}, {'x':cx1, 'y':cy1}, {'x':cx1, 'y':cy2}, {'x':cx2, 'y':cy2}, {'x':cx2, 'y':cy3}, {'x':cx3, 'y':cy3}, {'x':cx3, 'y':0} ] kicad_mod.append(PolygoneLine(polygone=crty_poly_tl, layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(PolygoneLine(polygone=crty_poly_tl, layer='F.CrtYd', width=configuration['courtyard_line_width'], x_mirror=0)) kicad_mod.append(PolygoneLine(polygone=crty_poly_tl, layer='F.CrtYd', width=configuration['courtyard_line_width'], y_mirror=0)) kicad_mod.append(PolygoneLine(polygone=crty_poly_tl, layer='F.CrtYd', width=configuration['courtyard_line_width'], x_mirror=0, y_mirror=0)) # ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top': cy1, 'bottom': -cy1}, fp_name=fp_name, text_y_inside_position='center') ##################### Output and 3d model ############################ kicad_mod.append(Model(filename=model_name)) 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=fp_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins, variant, configuration): V = variant_params[variant]['V'] #calculate fp dimensions A = (pins - 1) * pitch B = A + 4.9 #Thickness of connector T = 11.5 #corners x1 = -2.45 x2 = x1 + B x_mid = (x1 + x2) / 2 y2 = V y1 = y2 - T #y at which the plastic tabs end y3 = y2 - 7 #generate the name mpn = part_base.format(n=pins, variant=variant) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format( man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount, pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription( "JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator" .format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format( series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) if pins == 2: drill = 1.0 else: drill = 0.95 pad_size = [ pitch - pad_to_pad_clearance, drill + 2 * pad_copper_y_solder_length ] if pad_size[0] - drill < 2 * min_annular_ring: pad_size[0] = drill + 2 * min_annular_ring #generate the pads ############################# Pads ################################## # kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, # at=[0, 0], size=pad_size, # drill=drill, layers=Pad.LAYERS_THT)) kicad_mod.append( PadArray(initial=1, start=[0, 0], x_spacing=pitch, pincount=pincount, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT)) #draw the courtyard cx1 = roundToBase(x1 - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y1 - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2 + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2 + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append( RectLine(start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #offset the outline around the connector off = configuration['silk_fab_offset'] xo1 = x1 - off yo1 = y1 - off xo2 = x2 + off yo2 = y2 + off #thickness of the notches notch = 1.5 #wall thickness of the outline wall = 1.2 #draw the outline of the connector outline = [ { 'x': x_mid, 'y': yo2 }, { 'x': xo1, 'y': yo2 }, { 'x': xo1, 'y': yo1 }, { 'x': xo1 + wall + 2 * off, 'y': yo1 }, { 'x': xo1 + wall + 2 * off, 'y': y3 - off }, { 'x': A / 2, 'y': y3 - off }, #{'x': -1.1,'y': y3 + off} ] if variant == 'A-1': outline = outline[:-1] kicad_mod.append( PolygoneLine(polygone=outline, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=outline, x_mirror=x_mid, layer='F.SilkS', width=configuration['silk_line_width'])) outline = [ { 'x': x_mid, 'y': y2 }, { 'x': x1, 'y': y2 }, { 'x': x1, 'y': y1 }, { 'x': x1 + wall, 'y': y1 }, { 'x': x1 + wall, 'y': y3 }, { 'x': A / 2, 'y': y3 }, #{'x': -1.1,'y': y3 + off} ] kicad_mod.append( PolygoneLine(polygone=outline, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append( PolygoneLine(polygone=outline, x_mirror=x_mid, layer='F.Fab', width=configuration['fab_line_width'])) #draw the pinsss for i in range(pins): x = i * pitch w = 0.25 kicad_mod.append( RectLine(start=[x - w, y3 + 1], end=[x + w, y2 - 0.5], layer='F.SilkS', width=configuration['silk_line_width'])) #add pin-1 designator px = 0 py = -1.5 m = 0.3 pin1 = [ { 'x': px, 'y': py }, { 'x': px - m, 'y': py - 2 * m }, { 'x': px + m, 'y': py - 2 * m }, { 'x': px, 'y': py }, ] kicad_mod.append( PolygoneLine(polygone=pin1, layer='F.SilkS', width=configuration['silk_line_width'])) if fab_pin1_marker_type == 1: kicad_mod.append( PolygoneLine(polygone=pin1, layer='F.Fab', width=configuration['fab_line_width'])) if fab_pin1_marker_type == 2: fab_marker_left = -fab_first_marker_w / 2.0 fab_marker_bottom = y3 - fab_first_marker_h poly_fab_marker = [{ 'x': fab_marker_left, 'y': y3 }, { 'x': 0, 'y': fab_marker_bottom }, { 'x': fab_marker_left + fab_first_marker_w, 'y': y3 }] kicad_mod.append( PolygoneLine(polygone=poly_fab_marker, layer='F.Fab', width=configuration['fab_line_width'])) ######################### Text Fields ############################### text_center_y = 'center' body_edge = {'left': x1, 'right': x2, 'top': y1, 'bottom': y2} addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={ 'top': cy1, 'bottom': cy2 }, fp_name=footprint_name, text_y_inside_position=text_center_y) model3d_path_prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def make_module(pin_count, configuration): pad_silk_off = configuration['silk_line_width']/2 + configuration['silk_pad_clearance'] off = configuration['silk_fab_offset'] mpn = part_code.format(pin_count) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_unequal_row_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins=pin_count, mounting_pad = "", pitch=cable_pitch*2, orientation=orientation_str) footprint_name = footprint_name.replace("__",'_') kicad_mod = Footprint(footprint_name) kicad_mod.setAttribute('smd') kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Circuits ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pin_count, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) pad_to_pad_inside = 2 pad_to_pad_outside = pad_to_pad_inside + odd_pad_size[0] + even_pad_size[0] row_spacing = pad_to_pad_outside - odd_pad_size[0]/2 - even_pad_size[0]/2 odd_pad_x = -pad_to_pad_outside/2 + odd_pad_size[0]/2 even_pad_x = odd_pad_x + row_spacing B = cable_pitch * (pin_count - 1) A = B + (7.05-4.8) bar_width_max = 2*3.8 bar_chamfer_y = 1 bar_from_side_min = 0.1 bar_width = A - 2*bar_from_side_min if bar_width > bar_width_max: bar_width = bar_width_max body_edge = { 'top': -A/2, 'bottom': A/2, 'left': odd_pad_x - odd_pad_size[0]/2 + 0.35 } body_edge['right'] = body_edge['left'] + 2.85 bar_down_edge = body_edge['left'] + 3.23 bounding_box = { 'top': body_edge['top'], 'bottom': body_edge['bottom'], 'left': odd_pad_x - odd_pad_size[0]/2, 'right': bar_down_edge } kicad_mod.append(RectLine( start=[body_edge['left'], body_edge['top']], end=[body_edge['right'], body_edge['bottom']], layer="F.Fab", width=configuration['fab_line_width'] )) kicad_mod.append(PolygoneLine( polygone=[ {'x': body_edge['right'], 'y': -bar_width/2}, {'x': bar_down_edge, 'y': -bar_width/2 + bar_chamfer_y}, {'x': bar_down_edge, 'y': bar_width/2 - bar_chamfer_y}, {'x': body_edge['right'], 'y': bar_width/2} ], layer="F.Fab", width=configuration['fab_line_width'] )) odd_pins_outside = B/2 + odd_pad_size[1]/2 + pad_silk_off silk_outline = [ {'x': body_edge['left']-off, 'y':odd_pins_outside}, {'x': body_edge['left']-off, 'y':body_edge['bottom']+off}, {'x': body_edge['right'] + off, 'y':body_edge['bottom']+off}, {'x': body_edge['right'] + off, 'y': bar_width/2 + off}, {'x': bar_down_edge + off, 'y': bar_width/2 - bar_chamfer_y + off}, {'x': bar_down_edge + off, 'y': 0} ] kicad_mod.append(PolygoneLine( polygone=silk_outline, layer="F.SilkS", width=configuration['silk_line_width'] )) kicad_mod.append(PolygoneLine( polygone=silk_outline, y_mirror=0, layer="F.SilkS", width=configuration['silk_line_width'] )) even_pins = pin_count//2 odd_pins = pin_count - even_pins kicad_mod.append(PadArray( center=[odd_pad_x,0], pincount=odd_pins, initial=1, increment=2, y_spacing=2*cable_pitch, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=odd_pad_size, layers=Pad.LAYERS_SMT)) kicad_mod.append(PadArray( center=[even_pad_x, 0], pincount=even_pins, initial=2, increment=2, y_spacing=2*cable_pitch, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=even_pad_size, layers=Pad.LAYERS_SMT)) pin1_y = -B/2 ps1_m = 0.3 p1s_x = bounding_box['left'] - pad_silk_off pin = [ {'x': p1s_x - ps1_m/sqrt(2), 'y': pin1_y-ps1_m/2}, {'x': p1s_x, 'y': pin1_y}, {'x': p1s_x - ps1_m/sqrt(2), 'y': pin1_y+ps1_m/2}, {'x': p1s_x - ps1_m/sqrt(2), 'y': pin1_y-ps1_m/2} ] kicad_mod.append(PolygoneLine(polygone=pin, layer="F.SilkS", width=configuration['silk_line_width'])) sl=0.6 pin = [ {'x': body_edge['left'], 'y': pin1_y-sl/2}, {'x': body_edge['left'] + sl/sqrt(2), 'y': pin1_y}, {'x': body_edge['left'], 'y': pin1_y+sl/2} ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='right') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') if lib_by_conn_category: lib_name = configuration['lib_name_specific_function_format_string'].format(category=conn_category) else: lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins, configuration): mpn = part_base.format(n=pins * number_of_rows) #JST part number format string orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format( man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad="", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription( "JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator" .format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format( series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate fp dimensions A = (pins - 1) * pitch B = A + 4 #generate the pads (row 1) size = [pitch - pad_to_pad_clearance, row_pitch - pad_to_pad_clearance] if size[0] - drill < 2 * min_annular_ring: size[0] = drill + 2 * min_annular_ring if size[0] - drill > 2 * pad_copper_y_solder_length: size[0] = drill + 2 * pad_copper_y_solder_length if size[1] - drill < 2 * min_annular_ring: size[1] = drill + 2 * min_annular_ring if size[1] - drill > 2 * pad_copper_y_solder_length: size[1] = drill + 2 * pad_copper_y_solder_length pa1 = PadArray(pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, increment=2, size=size, drill=drill, layers=Pad.LAYERS_THT) pa2 = PadArray(pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, start=[0, row_pitch], initial=2, increment=2, size=size, drill=drill, layers=Pad.LAYERS_THT) kicad_mod.append(pa1) kicad_mod.append(pa2) #draw the component outline x1 = A / 2 - B / 2 x2 = x1 + B y2 = row_pitch + 7.7 + 2.4 y1 = y2 - 12.7 body_edge = {'left': x1, 'right': x2, 'top': y1, 'bottom': y2} #draw simple outline on F.Fab layer kicad_mod.append( RectLine(start=[x1, y1], end=[x2, y2], layer='F.Fab', width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(x1 - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) if y1 < -size[1] / 2: cy1 = roundToBase(y1 - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) else: cy1 = roundToBase( -size[1] / 2 - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2 + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2 + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append( RectLine(start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #offset off off = configuration['silk_fab_offset'] x1 -= off y1 -= off x2 += off y2 += off #outline side = [ { 'x': -1, 'y': y1 }, { 'x': x1, 'y': y1 }, { 'x': x1, 'y': y2 }, { 'x': A / 2, 'y': y2 }, ] kicad_mod.append( PolygoneLine(polygone=side, width=configuration['silk_line_width'], layer='F.SilkS')) kicad_mod.append( PolygoneLine(polygone=side, x_mirror=A / 2, width=configuration['silk_line_width'], layer='F.SilkS')) #add mounting holes m1 = Pad(at=[-0.9, mh_y], layers=Pad.LAYERS_NPTH, shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_NPTH, size=mh_drill, drill=mh_drill) m2 = Pad(at=[A + 0.9, mh_y], layers=Pad.LAYERS_NPTH, shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_NPTH, size=mh_drill, drill=mh_drill) kicad_mod.append(m1) kicad_mod.append(m2) D = 0.3 L = 2.5 #add p1 marker marker = [{ 'x': pitch / 2, 'y': y1 - D + 0.25 }, { 'x': pitch / 2, 'y': y1 - D }, { 'x': x1 - D, 'y': y1 - D }, { 'x': x1 - D, 'y': y1 - D + L }] kicad_mod.append( PolygoneLine(polygone=marker, width=configuration['silk_line_width'], layer='F.SilkS')) sl = 1 marker = [{ 'x': sl / 2, 'y': body_edge['top'] }, { 'x': 0, 'y': body_edge['top'] + sl / sqrt(2) }, { 'x': -sl / 2, 'y': body_edge['top'] }] kicad_mod.append( PolygoneLine(polygone=marker, layer='F.Fab', width=configuration['fab_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={ 'top': cy1, 'bottom': cy2 }, fp_name=footprint_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins, configuration): mpn = part_base.format(n=pins) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate dimensions A = (pins - 1) * pitch B = A + 5 #draw the component outline x1 = A/2 - B/2 x2 = x1 + B y2 = 4.8 y1 = y2 - 8.5 body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} #draw the main outline on F.Fab layer kicad_mod.append(RectLine(start={'x':x1,'y':y1}, end={'x':x2,'y':y2}, layer='F.Fab', width=configuration['fab_line_width'])) #draw horizontal line for latch kicad_mod.append(PolygoneLine(polygone=[{'x':x1,'y':(y1+1.7)},{'x':x2,'y':(y1+1.7)}],layer='F.Fab',width=0.1)) #draw pin1 mark on F.Fab kicad_mod.append(PolygoneLine(polygone=[{'x':x1,'y':-1},{'x':(x1+1),'y':0}],layer='F.Fab',width=0.1)) kicad_mod.append(PolygoneLine(polygone=[{'x':x1,'y':1},{'x':(x1+1),'y':0}],layer='F.Fab',width=0.1)) ########################### CrtYd ################################# cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #draw silk outline off = configuration['silk_fab_offset'] x1 -= off y1 -= off x2 += off y2 += off kicad_mod.append(RectLine(start=[x1,y1], end=[x2,y2], layer='F.SilkS', width=configuration['silk_line_width'])) #add pin1 mark on silk px = x1 - 0.2 m = 0.3 marker = [{'x': px,'y': 0},{'x': px-2*m,'y': m},{'x': px-2*m,'y': -m},{'x': px,'y': 0}] kicad_mod.append(PolygoneLine(polygone=marker, layer='F.SilkS', width=configuration['silk_line_width'])) #generate tht pads (1.65mm drill with 2.35x3mm oval pads) pad_size = [pitch - pad_to_pad_clearance, drill + 2*pad_copper_y_solder_length] if pad_size[0] - drill > 2*pad_copper_y_solder_length: pad_size[0] = 2*pad_copper_y_solder_length + drill if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring shape=Pad.SHAPE_OVAL if pad_size[0] == pad_size[1]: shape=Pad.SHAPE_CIRCLE optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray( pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins, variant, configuration): #calculate fp dimensions boss = variant_params[variant]['boss'] A = (pins - 1) * pitch B = A + 4.9 #connector thickness T = 5.75 #corners x1 = -2.45 x2 = x1 + B x_mid = (x1 + x2) / 2 y1 = -2.35 y2 = y1 + T #generate the name mpn = part_base.format(n=pins, variant=variant) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s}{:s} ({:s}), generated with kicad-footprint-generator".format( series, mpn, ', with boss' if boss else '', datasheet)) tags = configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation]) if boss: tags += " boss" #set the FP tags kicad_mod.setTags(tags) #draw simple outline on F.Fab layer kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2],layer='F.Fab', width=configuration['fab_line_width'])) # set general values #kicad_mod.append(Text(type='reference', text='REF**', at=[x_mid,-3.5], layer='F.SilkS')) if pins == 2: drill = 1.0 else: drill = 0.95 pad_size = [pitch - pad_to_pad_clearance, drill + 2*pad_copper_y_solder_length] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring #generate the pads ############################# Pads ################################## # kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, # at=[0, 0], size=pad_size, # drill=drill, layers=Pad.LAYERS_THT)) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(initial=1, start=[0, 0], x_spacing=pitch, pincount=pins, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT, **optional_pad_params)) if boss: if pins == 1: boss_y = 4.35 boss_x = 0 boss_drill = 1.75 kicad_mod.append(Pad(type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=[boss_x, boss_y], size=boss_drill, drill=boss_drill, layers=Pad.LAYERS_NPTH)) else: boss_y = 2 boss_x = -1.6 boss_drill = 1.2 kicad_mod.append(Pad(type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=[boss_x, boss_y], size=boss_drill, drill=boss_drill, layers=Pad.LAYERS_NPTH)) if boss and pins == 1: boss_size_1pin = 1.5 off = configuration['silk_fab_offset'] x_boss_fab_off = boss_size_1pin/2 + off x_boss_pad_off = boss_drill/2 + configuration['silk_line_width']/2 + configuration['silk_pad_clearance'] x_boss = x_boss_fab_off if x_boss_pad_off > x_boss: x_boss=x_boss_pad_off out_silk = PolygoneLine(polygone=[ {'x': -x_boss, 'y':boss_y}, {'x': -x_boss, 'y':y2+off}, {'x': x1-off, 'y':y2+off}, {'x': x1-off, 'y':y1-off}, {'x': x2+off, 'y':y1-off}, {'x': x2+off, 'y':y2+off}, {'x': x_boss, 'y':y2+off}, {'x': x_boss, 'y':boss_y} ], layer='F.SilkS', width=configuration['silk_line_width']) kicad_mod.append(out_silk) kicad_mod.append(Arc(center=[0,boss_y], start=[-x_boss, boss_y], angle=-180, layer="F.SilkS", width=configuration['silk_line_width'])) out_fab = PolygoneLine(polygone=[ {'x': -boss_size_1pin/2, 'y':boss_y}, {'x': -boss_size_1pin/2, 'y':y2}, {'x': x1, 'y':y2}, {'x': x1, 'y':y1}, {'x': x2, 'y':y1}, {'x': x2, 'y':y2}, {'x': boss_size_1pin/2, 'y':y2}, {'x': boss_size_1pin/2, 'y':boss_y} ], layer='F.Fab', width=configuration['fab_line_width']) kicad_mod.append(out_fab) kicad_mod.append(Arc(center=[0,boss_y], start=[-boss_size_1pin/2, boss_y], angle=-180, layer="F.Fab", width=configuration['fab_line_width'])) else: out = RectLine(start=[x1,y1], end=[x2,y2], offset=configuration['silk_fab_offset'], layer='F.SilkS', width=configuration['silk_line_width']) kicad_mod.append(out) body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} #draw the courtyard cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) if boss and pins == 1: cy2 = roundToBase(boss_y+boss_drill/2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #draw the connector outline if fab_pin1_marker_type == 2: fab_marker_left = -fab_first_marker_w/2.0 fab_marker_bottom = y1 + fab_first_marker_h poly_fab_marker = [ {'x':fab_marker_left, 'y':y1}, {'x':0, 'y':fab_marker_bottom}, {'x':fab_marker_left + fab_first_marker_w, 'y':y1} ] kicad_mod.append(PolygoneLine(polygone=poly_fab_marker, layer='F.Fab', width=configuration['fab_line_width'])) #wall thickness w w = 0.75 #gap size g g = 1.5 off = 0.1 x1 -= off y1 -= off x2 += off y2 += off #draw the center tab kicad_mod.append(RectLine(start=[g/2,y1], end=[A-g/2,y1+w], layer='F.SilkS', width=configuration['silk_line_width'])) #add left tab kicad_mod.append(RectLine(start=[x1,y1], end=[-g/2,y1+w], layer='F.SilkS', width=configuration['silk_line_width'])) #right tab kicad_mod.append(RectLine(start=[A+g/2,y1], end=[x2,y1+w], layer='F.SilkS', width=configuration['silk_line_width'])) #add other line line = [ {'x': x1,'y': y1+w+g}, {'x': x1+w,'y': y1+w+g}, {'x': x1+w,'y': y2-w}, {'x': A/2,'y': y2-w} ] if boss and pins > 1: line2 = line[:2] line2.append({'x': x1+w,'y': boss_y - boss_drill/2 - configuration['silk_line_width']/2 - configuration['silk_pad_clearance']}) kicad_mod.append(PolygoneLine(polygone=line2, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[A/2, y2-w], end=[boss_x+boss_drill/2+ configuration['silk_line_width']/2 + configuration['silk_pad_clearance'], y2-w], layer='F.SilkS', width=configuration['silk_line_width'])) else: kicad_mod.append(PolygoneLine(polygone=line, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=line, x_mirror=A/2, layer='F.SilkS', width=configuration['silk_line_width'])) #pin-1 marker y = -2.75 m = 0.3 poly_pin1_marker = [ {'x':x1-pin1_marker_offset+pin1_marker_linelen, 'y':y1-pin1_marker_offset}, {'x':x1-pin1_marker_offset, 'y':y1-pin1_marker_offset}, {'x':x1-pin1_marker_offset, 'y':y1-pin1_marker_offset+pin1_marker_linelen} ] if fab_pin1_marker_type == 2: kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.SilkS', width=configuration['silk_line_width'])) if fab_pin1_marker_type == 3: kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.Fab', width=configuration['fab_line_width'])) pin = [ {'x': 0,'y': y}, {'x': -m,'y': y-2*m}, {'x': m,'y': y-2*m}, {'x': 0,'y': y}, ] if fab_pin1_marker_type == 1: kicad_mod.append(PolygoneLine(polygone=pin, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=pin, layer='F.Fab', width=configuration['fab_line_width'])) ######################### Text Fields ############################### text_center_y = 'bottom' addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position=text_center_y) model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins, configuration): pins_per_row = pins//2 mpn = part_code.format(n=pins) alt_mpn = [code.format(n=pins) for code in alternative_codes] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "-1MP", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s} (compatible alternatives: {:s}), {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, ', '.join(alt_mpn), pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) kicad_mod.setAttribute('smd') # Calculate dimensions if (pins < 4): B = 0 else: B = ((pins / 2) - 1) * pitch A = B + 6.65 C = B + 11.2 # D = pitch_y + PadSiseY pad_row_1_y = -pitch_y/2 pad_row_2_y = pad_row_1_y + pitch_y pad1_x = -B/2 mount_pad_x = ((C - mount_pad_size[0]) / 2) mount_pad_y = pad_row_1_y - (6.93 - pad_size[1]/2) body_edge={ 'left':-A/2, 'right':A/2, 'top': mount_pad_y - 4.6 } body_edge['bottom'] = body_edge['top'] + 9.91 # # Add solder nails # kicad_mod.append(Pad(at=[-mount_pad_x, mount_pad_y], number=configuration['mounting_pad_number'], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=mount_pad_size, layers=Pad.LAYERS_SMT)) kicad_mod.append(Pad(at=[mount_pad_x, mount_pad_y], number=configuration['mounting_pad_number'], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=mount_pad_size, layers=Pad.LAYERS_SMT)) # # Add pads # kicad_mod.append(PadArray(start=[pad1_x, pad_row_1_y], initial=1, pincount=pins_per_row, increment=1, x_spacing=pitch, size=pad_size, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_SMT)) kicad_mod.append(PadArray(start=[pad1_x, pad_row_2_y], initial=pins_per_row+1, pincount=pins_per_row, increment=1, x_spacing=pitch, size=pad_size, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_SMT)) # # Add F.Fab # LayerA = ['F.Fab', 'F.SilkS', 'F.CrtYd'] LineDXA = [ 0, configuration['silk_fab_offset'], configuration['courtyard_offset']['connector'] ] LindeDeltaA = [0, configuration['silk_pad_clearance'] + configuration['silk_line_width']/2, 0] LineWidthA = [ configuration['fab_line_width'], configuration['silk_line_width'], configuration['courtyard_line_width'] ] gridA = [0, 0, configuration['courtyard_grid']] for i in range(0,3): LineDX = LineDXA[i] Layer = LayerA[i] LineWidth = LineWidthA[i] LindeDelta = LindeDeltaA[i] points = [] grid = gridA[i] x1 = 0 y1 = body_edge['top'] - LineDX points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) # x1 = (A / 2) - 1 + LineDX y1 = y1 points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) # x1 = (A / 2) + LineDX y1 = y1 + 2 points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) # x1 = x1 y1 = mount_pad_y - ((mount_pad_size[1] / 2) + LineDX + LindeDelta) points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) # if (i == 1): # SilkS kicad_mod.append(PolygoneLine(polygone=points, layer=Layer, width=LineWidth)) # # Need to do something ugly here, becosue we will do points = [] # We need to reflect these points already here # points2 = [] for pp in points: points2.append([-pp[0], pp[1]]) kicad_mod.append(PolygoneLine(polygone=points2, layer=Layer, width=LineWidth)) # # points = [] x1 = x1 y1 =mount_pad_y + ((mount_pad_size[1] / 2) + LineDX + LindeDelta) points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) elif (i == 2): # CrtYd x1 = mount_pad_x + (mount_pad_size[0] / 2) + LineDX y1 = y1 points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) # x1 = x1 y1 =mount_pad_y + ((mount_pad_size[1] / 2) + LineDX) points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) # x1 = (A / 2) + LineDX y1 = y1 points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) # x1 = x1 y1 = body_edge['bottom'] + LineDX points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) # x1 = (B / 2) + (pad_size[0] / 2) + LineDX + LindeDelta y1 = y1 points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) # if (i == 0): x1 = 0 y1 = y1 points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) if (i == 1): ttx1 = x1 tty1 = y1 + (pad_size[1] / 2) if (i == 2): x1 = x1 y1 = ((pitch_y / 2) + (pad_size[1] / 2) + LineDX) ttx1 = x1 tty1 = y1 points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) # # x1 = 0 y1 = y1 points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) # # Reflect right part around the X-axis # points2 = [] for pp in points: points2.append([0 - pp[0], pp[1]]) # # if (i == 0): # Fab # Add pin 1 marker tt = len(points2) ps = points2[tt - 1] p1 = points2[tt - 2] p2 = [(0 - (B / 2)) - 1, p1[1]] p3 = [(0 - (B / 2)), p1[1] - 1] p4 = [(0 - (B / 2)) + 1, p1[1]] points2[tt - 2] = p2 points2[tt - 1] = p3 points2.append(p4) points2.append(ps) elif (i == 1): # silk points2.append([roundToBase(0 - ttx1, grid), roundToBase(tty1, grid)]) # # kicad_mod.append(PolygoneLine(polygone=points, layer=Layer, width=LineWidth)) # kicad_mod.append(PolygoneLine(polygone=points2, layer=Layer, width=LineWidth)) ######################### Text Fields ############################### cy1 = roundToBase(body_edge['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(pad_row_2_y + pad_size[1]/2 + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_footprint(params, mpn, configuration): fp_params = params['footprint'] mech_params = params['mechanical'] part_params = params['parts'][mpn] if 'id' in mech_params: size = str(mech_params['id']) elif 'ext_thread' in mech_params: size = str(mech_params['ext_thread']['od']) if 'M' not in size: size = "{}mm".format(size) td = "" size_prefix = "" hole_type = "inside through hole" if 'thread_depth' in part_params: hole_type = "inside blind hole" td = "_ThreadDepth{}mm".format(part_params['thread_depth']) elif 'ext_thread' in mech_params: hole_type = "external" size_prefix = 'External' h = part_params['h'] if 'h' in part_params else part_params['h1'] suffix = '' if 'suffix' in params: suffix = '_{}'.format(params['suffix']) fp_name = "Mounting_Wuerth_{series}-{size_prefix}{size}_H{h}mm{td}{suffix}_{mpn}".format( size=size, h=h, mpn=mpn, td=td, size_prefix=size_prefix, series=params['series_prefix'], suffix=suffix) kicad_mod = Footprint(fp_name) kicad_mod.setAttribute('smd') kicad_mod.setDescription("Mounting Hardware, {hole_type} {size}, height {h}, Wuerth electronics {mpn} ({ds:s}), generated with kicad-footprint-generator".format(size=size, h=h, mpn=mpn, ds=part_params['datasheet'], hole_type=hole_type)) kicad_mod.setTags('Mounting {} {}'.format(size, mpn)) paste_count = fp_params['ring']['paste'].get('paste_count', 4) kicad_mod.append( RingPad( number='1', at=(0, 0), size=fp_params['ring']['od'], inner_diameter=fp_params['ring']['id'], num_anchor=4, num_paste_zones=paste_count, paste_round_radius_radio=0.25, paste_max_round_radius=0.1, paste_to_paste_clearance=fp_params['ring']['paste']['clearance'], paste_inner_diameter=fp_params['ring']['paste']['id'], paste_outer_diameter=fp_params['ring']['paste']['od'] )) if 'npth' in fp_params: kicad_mod.append( Pad(at=[0, 0], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=fp_params['npth'], drill=fp_params['npth'], layers=Pad.LAYERS_NPTH)) kicad_mod.append( Circle( center=[0, 0], radius=mech_params['od']/2, layer='F.Fab', width=configuration['fab_line_width'] )) ########################### CrtYd ################################# rc = max(mech_params['od'], fp_params['ring']['od'])/2+configuration['courtyard_offset']['default'] rc = roundToBase(rc, configuration['courtyard_grid']) kicad_mod.append( Circle( center=[0, 0], radius=rc, layer='F.CrtYd', width=configuration['courtyard_line_width'] )) ########################### SilkS ################################# ######################### Text Fields ############################### rb = mech_params['od']/2 body_edge={'left':-rb, 'right':rb, 'top':-rb, 'bottom':rb} addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':-rc, 'bottom':rc}, fp_name=fp_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = "Mounting_Wuerth" model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=fp_name) kicad_mod.append(Model(filename=model_name)) 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=fp_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins_per_row, params, configuration): mpn = part_code.format(n=pins_per_row, shield=params['mpn_option']) CrtYd_off = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] off = configuration['silk_fab_offset'] pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 body_edge = {} bounding_box = {} # handle arguments orientation_str = configuration['orientation_options'][orientation] if params['shield_pad']: footprint_name = configuration['fp_name_format_string_shielded'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, pitch=pitch, orientation=orientation_str, shield_pins=1) else: footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) footprint_name = footprint_name.replace('__','_') kicad_mod = Footprint(footprint_name) kicad_mod.setAttribute('smd') kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) A = (pins_per_row-1)*pitch B = A + 2.5 C = A + 5.45 D = A + 6.75 E = A + 5.2 pad_to_pad_inside = 1.95+0.25 pad_y = (pad_to_pad_inside + pad_size[1])/2 boss_x = B/2 boss_y = -pad_y + pad_size[1]/2 + 0.25 shield_pad_x = C/2 shield_pad_y = boss_y + 2 body_chamfer = 0.3 body_edge['left'] = -D/2 if params['shield_pad'] else -E/2 body_edge['right'] = -body_edge['left'] body_edge['top'] = -4.98/2 body_edge['bottom'] = -body_edge['top'] bounding_box['left'] = (-shield_pad_x - shield_pad_size/2) if params['shield_pad'] else body_edge['left'] bounding_box['right'] = -bounding_box['left'] bounding_box['top'] = -pad_y - pad_size[1]/2 bounding_box['bottom'] = -bounding_box['top'] ################################ Pads ##################################### kicad_mod.append(PadArray(initial=1, increment=2, center=[0, -pad_y], x_spacing=pitch, pincount=pins_per_row, size=pad_size, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_SMT)) kicad_mod.append(PadArray(initial=2, increment=2, center=[0, pad_y], x_spacing=pitch, pincount=pins_per_row, size=pad_size, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_SMT)) kicad_mod.append(Pad(number ='""', type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=[boss_x, boss_y], size=boss_drill, drill=boss_drill, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(number ='""', type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=[-boss_x, boss_y], size=boss_drill, drill=boss_drill, layers=Pad.LAYERS_NPTH)) if params['shield_pad']: kicad_mod.append(Pad(number = pin_number_shield, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, at=[shield_pad_x, shield_pad_y], size=shield_pad_size, drill=shield_pad_drill, layers=Pad.LAYERS_THT)) kicad_mod.append(Pad(number = pin_number_shield, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, at=[-shield_pad_x, shield_pad_y], size=shield_pad_size, drill=shield_pad_drill, layers=Pad.LAYERS_THT)) ########################### Outline ################################ poly_fab = [ {'x': 0, 'y': body_edge['top']}, {'x': body_edge['left']+body_chamfer, 'y': body_edge['top']}, {'x': body_edge['left'], 'y': body_edge['top']+body_chamfer}, {'x': body_edge['left'], 'y': body_edge['bottom']-body_chamfer}, {'x': body_edge['left']+body_chamfer, 'y': body_edge['bottom']}, {'x': 0, 'y': body_edge['bottom']} ] kicad_mod.append(PolygoneLine(polygone=poly_fab, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly_fab, x_mirror=0, layer='F.Fab', width=configuration['fab_line_width'])) pad_x_outside_edge = A/2 + pad_size[0]/2 + pad_silk_off if not params['shield_pad']: poly_silk = [ {'x': -pad_x_outside_edge, 'y': body_edge['top']-off}, {'x': body_edge['left']+body_chamfer-off, 'y': body_edge['top']-off}, {'x': body_edge['left']-off, 'y': body_edge['top']+body_chamfer-off}, {'x': body_edge['left']-off, 'y': body_edge['bottom']-body_chamfer+off}, {'x': body_edge['left']+body_chamfer-off, 'y': body_edge['bottom']+off}, {'x': -pad_x_outside_edge, 'y': body_edge['bottom']+off} ] kicad_mod.append(PolygoneLine(polygone=poly_silk, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly_silk, x_mirror=0, layer='F.SilkS', width=configuration['silk_line_width'])) else: r = (shield_pad_size/2 + pad_silk_off) x = (D-C)/2 dy = sqrt(r**2 - x**2) poly_silk_top = [ {'x': -pad_x_outside_edge, 'y': body_edge['top']-off}, {'x': body_edge['left']+body_chamfer-off, 'y': body_edge['top']-off}, {'x': body_edge['left']-off, 'y': body_edge['top']+body_chamfer-off}, {'x': body_edge['left']-off, 'y': shield_pad_y-dy}, ] kicad_mod.append(PolygoneLine(polygone=poly_silk_top, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly_silk_top, x_mirror=0, layer='F.SilkS', width=configuration['silk_line_width'])) poly_silk_bottom = [ {'x': body_edge['left']-off, 'y': shield_pad_y+dy}, {'x': body_edge['left']-off, 'y': body_edge['bottom']-body_chamfer+off}, {'x': body_edge['left']+body_chamfer-off, 'y': body_edge['bottom']+off}, {'x': -pad_x_outside_edge, 'y': body_edge['bottom']+off} ] kicad_mod.append(PolygoneLine(polygone=poly_silk_bottom, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly_silk_bottom, x_mirror=0, layer='F.SilkS', width=configuration['silk_line_width'])) ########################### Pin 1 ################################# p1s_sl = 0.4 p1s_y = -pad_y - pad_size[1]/2 - pad_silk_off p1_x = -A/2 p1s_poly = [ {'x': p1_x, 'y':p1s_y}, {'x': p1_x-p1s_sl/2, 'y':p1s_y-p1s_sl/sqrt(2)}, {'x': p1_x+p1s_sl/2, 'y':p1s_y-p1s_sl/sqrt(2)}, {'x': p1_x, 'y':p1s_y} ] kicad_mod.append(PolygoneLine(polygone=p1s_poly, layer='F.SilkS', width=configuration['silk_line_width'])) p1f_sl = 2*pitch p1f_poly = [ {'x': p1_x-p1f_sl/2, 'y':body_edge['top']}, {'x': p1_x, 'y':body_edge['top']+p1f_sl/sqrt(2)}, {'x': p1_x+p1f_sl/2, 'y':body_edge['top']} ] kicad_mod.append(PolygoneLine(polygone=p1f_poly, layer='F.Fab', width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.load(config_stream)) except yaml.YAMLError as exc: print(exc) for variant in variant_params: for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, variant_params[variant], configuration)
def generate_one_footprint(pincount, configuration): mpn = "B{pincount}B-EH-A".format(pincount=pincount) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) A = (pincount - 1) * pitch B = A + 5.0 # set general values if pincount == 2: drill = 1.0 else: drill = 0.95 pad_size = [pitch - pad_to_pad_clearance, drill + 2*pad_copper_y_solder_length] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring # create pads # kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, # at=[0, 0], size=pad_size, # drill=drill, layers=Pad.LAYERS_THT)) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(initial=1, start=[0, 0], x_spacing=pitch, pincount=pincount, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT, **optional_pad_params)) x1 = -2.5 y1 = -1.6 x2 = x1 + B y2 = y1 + 3.8 body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} #draw the main outline on F.Fab layer kicad_mod.append(RectLine(start={'x':x1,'y':y1}, end={'x':x2,'y':y2}, layer='F.Fab', width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #line offset off = configuration['silk_fab_offset'] x1 -= off y1 -= off x2 += off y2 += off #draw the main outline around the footprint kicad_mod.append(RectLine(start={'x':x1,'y':y1},end={'x':x2,'y':y2}, layer='F.SilkS', width=configuration['silk_line_width'])) T = 0.5 #add top line kicad_mod.append(PolygoneLine(polygone=[{'x': x1,'y': 0}, {'x': x1 + T,'y': 0}, {'x': x1 + T,'y': y1 + T}, {'x': x2 - T,'y': y1 + T}, {'x': x2 - T,'y': 0}, {'x': x2,'y':0}], layer='F.SilkS', width=configuration['silk_line_width'])) #add bottom line (left) kicad_mod.append(PolygoneLine(polygone=[{'x':x1,'y':y2-3*T}, {'x':x1+2*T,'y':y2-3*T}, {'x':x1+2*T,'y':y2}], layer='F.SilkS', width=configuration['silk_line_width'])) #add bottom line (right) kicad_mod.append(PolygoneLine(polygone=[{'x':x2,'y':y2-3*T}, {'x':x2-2*T,'y':y2-3*T}, {'x':x2-2*T,'y':y2}], layer='F.SilkS', width=configuration['silk_line_width'])) #add pin-1 marker D = 0.3 L = 2.5 pin = [ {'x': x1-D,'y': y2+D-L}, {'x': x1-D,'y': y2+D}, {'x': x1-D+L,'y': y2+D}, ] kicad_mod.append(PolygoneLine(polygone=pin)) kicad_mod.append(PolygoneLine(polygone=pin, layer='F.Fab', width=configuration['fab_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins, configuration): pins_per_row = pins mpn = part_code.format(n=pins) alt_mpn = [code.format(n=pins) for code in alternative_codes] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s} (compatible alternatives: {:s}), {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, ', '.join(alt_mpn), pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) ########################## Dimensions ############################## B = (pins_per_row-1)*pitch A = B + 6.65 #Centra os pinos em metade do pitch pad_row_1_y = 0 pad_row_2_y = pad_row_1_y + pitch pad1_x = 0 C = 1.7 + pitch*(pins-3) #1º need be 4.7mm body_edge={ 'left':-3.325, 'right':A-3.325, 'top': -8.92 } body_edge['bottom'] = body_edge['top'] + 9.90 ############################# Pads ################################## # # Pegs # if pins_per_row == 2: kicad_mod.append(Pad(at=[pitch/2, pad_row_1_y - 4.32], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) elif pins_per_row == 3: kicad_mod.append(Pad(at=[pitch, pad_row_1_y - 4.32], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) else: kicad_mod.append(Pad(at=[pad1_x + 2.15, pad_row_1_y - 4.32], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(at=[pad1_x + 2.15 + C, pad_row_1_y - 4.32], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) # # Add pads # optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(start=[pad1_x, pad_row_1_y], initial=1, pincount=pins_per_row, increment=1, x_spacing=pitch, size=pad_size, type=Pad.TYPE_THT, shape=pad_shape, layers=Pad.LAYERS_THT, drill=drill, **optional_pad_params)) ######################## Fabrication Layer ########################### main_body_poly= [ {'x': body_edge['left'], 'y': body_edge['bottom']}, {'x': body_edge['left'], 'y': body_edge['top']+1}, {'x': body_edge['left']+1, 'y': body_edge['top']}, {'x': body_edge['right']-1, 'y': body_edge['top']}, {'x': body_edge['right'], 'y': body_edge['top']+1}, {'x': body_edge['right'], 'y': body_edge['bottom']}, {'x': body_edge['left'], 'y': body_edge['bottom']} ] kicad_mod.append(PolygoneLine(polygone=main_body_poly, width=configuration['fab_line_width'], layer="F.Fab")) main_arrow_poly= [ {'x': -.75, 'y': body_edge['bottom']}, {'x': 0, 'y': 0}, {'x': 0.75, 'y': body_edge['bottom']} ] kicad_mod.append(PolygoneLine(polygone=main_arrow_poly, width=configuration['fab_line_width'], layer="F.Fab")) ######################## SilkS Layer ########################### off = configuration['silk_fab_offset'] pad_silk_off = configuration['silk_line_width']/2 + configuration['silk_pad_clearance'] r_no_silk = max(pad_size)/2 + pad_silk_off # simplified to circle instead of oval dy = abs(body_edge['bottom']) + off pin_center_silk_x = 0 if dy >= r_no_silk else sqrt(r_no_silk**2-dy**2) pin1_center_silk_x = pad_size[0]/2 + pad_silk_off # simplified to rectangle instead of rounded rect poly_s_t= [ {'x': body_edge['left'] - off, 'y': body_edge['bottom'] + off}, {'x': body_edge['left'] - off, 'y': body_edge['top'] + 1 - off}, {'x': body_edge['left'] + 1 - off, 'y': body_edge['top'] - off}, {'x': body_edge['right'] - 1 + off, 'y': body_edge['top'] - off}, {'x': body_edge['right'] + off, 'y': body_edge['top'] + 1 - off}, {'x': body_edge['right'] + off, 'y': body_edge['bottom'] + off} ] kicad_mod.append(PolygoneLine(polygone=poly_s_t, width=configuration['silk_line_width'], layer="F.SilkS")) if pin_center_silk_x == 0: kicad_mod.append(Line( start=[body_edge['left']-off, body_edge['bottom']], end=[body_edge['right']-off, body_edge['bottom']], layer="F.SilkS", width=configuration['silk_line_width'] )) else: kicad_mod.append(Line( start=[body_edge['left']-off, body_edge['bottom']+off], end=[-pin1_center_silk_x, body_edge['bottom']+off], layer="F.SilkS", width=configuration['silk_line_width'] )) kicad_mod.append(Line( start=[body_edge['right']+off, body_edge['bottom']+off], end=[(pins_per_row-1)*pitch + pin_center_silk_x, body_edge['bottom']+off], layer="F.SilkS", width=configuration['silk_line_width'] )) kicad_mod.append(Line( start=[pin1_center_silk_x, body_edge['bottom']+off], end=[pitch - pin_center_silk_x, body_edge['bottom']+off], layer="F.SilkS", width=configuration['silk_line_width'] )) for i in range(1, pins_per_row-1): xl = i*pitch + pin_center_silk_x xr = (i+1)*pitch - pin_center_silk_x kicad_mod.append(Line( start=[xl, body_edge['bottom']+off], end=[xr, body_edge['bottom']+off], layer="F.SilkS", width=configuration['silk_line_width'] )) ######################## CrtYd Layer ########################### CrtYd_offset = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] poly_yd = [ {'x': roundToBase(body_edge['left'] - CrtYd_offset, CrtYd_grid), 'y': roundToBase(body_edge['bottom'] + CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(body_edge['left'] - CrtYd_offset, CrtYd_grid), 'y': roundToBase(body_edge['top'] - CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(body_edge['right'] + CrtYd_offset, CrtYd_grid), 'y': roundToBase(body_edge['top'] - CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(body_edge['right'] + CrtYd_offset, CrtYd_grid), 'y': roundToBase(body_edge['bottom'] + CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(body_edge['left'] - CrtYd_offset, CrtYd_grid), 'y': roundToBase(body_edge['bottom'] + CrtYd_offset, CrtYd_grid)} ] kicad_mod.append(PolygoneLine(polygone=poly_yd, layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### cy1 = roundToBase(body_edge['top'] - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(pad_size[1] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Write to File and 3D ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins, configuration): mpn = part_base.format(n=pins*number_of_rows) #JST part number format string orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate fp dimensions A = (pins - 1) * pitch B = A + 3.9 #draw the component outline x1 = A/2.0 - B/2.0 x2 = x1 + B y2 = 2 + 1.5 y1 = y2 - 5 body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} #wall thickness t_short = 0.75 #short side (fixed at 5mm) t_long = 0.4 #long side (A/B dimension) #draw simple outline on F.Fab layer kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2],layer='F.Fab',width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #draw silk polarity lines kicad_mod.append(RectLine(start=[x1+t_short,y1+t_long],end=[x2-t_short,y2-t_long],layer='F.SilkS',width=configuration['silk_line_width'])) #offset off off = configuration['silk_fab_offset'] #draw silk keying/polarity marks measured from 3D model on JST's site # from bottom (pin 2 row) of connector, notches are 1.6mm up and 0.8mm wide kicad_mod.append(Line(start=[x1-off,y2-2.4],end=[x1+t_short,y2-2.4],layer='F.SilkS',width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x2+off,y2-2.4],end=[x2-t_short,y2-2.4],layer='F.SilkS',width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x1-off,y2-1.6],end=[x1+t_short,y2-1.6],layer='F.SilkS',width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x2+off,y2-1.6],end=[x2-t_short,y2-1.6],layer='F.SilkS',width=configuration['silk_line_width'])) # from sides, inner edge of notches are 3.42mm inside and 0.94mm wide at the top (pin 1 row) and 1.50mm wide at the bottom (pin 2 row) kicad_mod.append(Line(start=[x1+3.42,y1-off],end=[x1+3.42,y1+t_long],layer='F.SilkS',width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x1+2.48,y1-off],end=[x1+2.48,y1+t_long],layer='F.SilkS',width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x2-3.42,y1-off],end=[x2-3.42,y1+t_long],layer='F.SilkS',width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x2-2.48,y1-off],end=[x2-2.48,y1+t_long],layer='F.SilkS',width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x1+3.42,y2+off],end=[x1+3.42,y2-t_long],layer='F.SilkS',width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x1+1.92,y2+off],end=[x1+1.92,y2-t_long],layer='F.SilkS',width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x2-3.42,y2+off],end=[x2-3.42,y2-t_long],layer='F.SilkS',width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x2-1.92,y2+off],end=[x2-1.92,y2-t_long],layer='F.SilkS',width=configuration['silk_line_width'])) x1 -= off y1 -= off x2 += off y2 += off #draw silk outline kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2],width=configuration['silk_line_width'],layer='F.SilkS')) #add p1 marker px = x1 - 0.2 m = 0.3 marker = [ {'x': px,'y': 0}, {'x': px-2*m,'y': m}, {'x': px-2*m,'y': -m}, {'x': px,'y': 0} ] kicad_mod.append(PolygoneLine(polygone=marker,width=configuration['silk_line_width'],layer='F.SilkS')) sl = 0.5 marker =[ {'x': body_edge['left'], 'y': sl}, {'x': body_edge['left'] + (2*sl)/sqrt(2) , 'y': 0}, {'x': body_edge['left'] , 'y': -sl} ] kicad_mod.append(PolygoneLine(polygone=marker,layer='F.Fab',width=configuration['fab_line_width'])) #generate the pads (row 1) size = [pitch - pad_to_pad_clearance, row_pitch - pad_to_pad_clearance] if size[0] - drill < 2*min_annular_ring: size[0] = drill + 2*min_annular_ring if size[0] - drill > 2*pad_copper_y_solder_length: size[0] = drill + 2*pad_copper_y_solder_length if size[1] - drill < 2*min_annular_ring: size[1] = drill + 2*min_annular_ring if size[1] - drill > 2*pad_copper_y_solder_length: size[1] = drill + 2*pad_copper_y_solder_length if size[0] == size[1]: pad_shape = Pad.SHAPE_CIRCLE else: pad_shape = Pad.SHAPE_OVAL optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT for row_idx in range(2): kicad_mod.append(PadArray( pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, start=[0, row_idx*row_pitch], initial=row_idx+1, increment=2, size=size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def gen_footprint(pinnum, manpart, configuration): orientation_str = configuration['orientation_options']['H'] footprint_name = configuration['fp_name_format_string'].format( man=manufacturer, series='', mpn=manpart, num_rows=1, pins_per_row=pinnum, pitch=pitch, orientation=orientation_str) footprint_name = footprint_name.replace('__','_') kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("{manufacturer} {series}, {mpn}{alt_mpn}, {pins_per_row} Pins per row ({datasheet}), generated with kicad-footprint-generator".format( manufacturer = manufacturer, series = series_long, mpn = manpart, alt_mpn = '', pins_per_row = pinnum, datasheet = datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry='horizontal')) kicad_mod.setAttribute('smd') # Pads kicad_mod.append(PadArray(start=[-6.775+padsize[0]/2, -(pitch*(pinnum-1))/2], initial=1, pincount=pinnum, increment=1, y_spacing=pitch, size=padsize, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_SMT, drill=None)) # Fab for y in range(0, pinnum): gen_fab_pins(-6.775+padsize[0]/2, -(pitch*(pinnum-1))/2+pitch+(y-1)*2.54, kicad_mod, configuration) poly_f_body = [ {'x': -6.775+padsize[0]/2+3.8, 'y': -(pitch*(pinnum-1))/2-pitch-2.54/2+0.4+2.54}, {'x': -6.775+padsize[0]/2+3.8+0.4, 'y': -(pitch*(pinnum-1))/2-pitch-2.54/2+2.54}, {'x': -6.775+padsize[0]/2+6.3, 'y': -(pitch*(pinnum-1))/2-pitch-2.54/2+2.54}, {'x': -6.775+padsize[0]/2+6.3, 'y': -(pitch*(pinnum-1))/2-pitch-2.54/2+2.54*pinnum+2.54}, {'x': -6.775+padsize[0]/2+3.8, 'y': -(pitch*(pinnum-1))/2-pitch-2.54/2+2.54*pinnum+2.54}, {'x': -6.775+padsize[0]/2+3.8, 'y': -(pitch*(pinnum-1))/2-pitch-2.54/2+0.4+2.54}, ] kicad_mod.append(PolygoneLine(polygone=poly_f_body, width=configuration['fab_line_width'], layer="F.Fab")) # SilkS silkslw = configuration['silk_line_width'] s_body = [ {'x': -6.775+padsize[0]/2+3.8-silkslw, 'y': -(pitch*(pinnum-1))/2-pitch-2.54/2-silkslw+2.54}, {'x': -6.775+padsize[0]/2+6.3+silkslw, 'y': -(pitch*(pinnum-1))/2-pitch-2.54/2-silkslw+2.54}, {'x': -6.775+padsize[0]/2+6.3+silkslw, 'y': -(pitch*(pinnum-1))/2-pitch-2.54/2+2.54*pinnum+silkslw+2.54}, {'x': -6.775+padsize[0]/2+3.8-silkslw, 'y': -(pitch*(pinnum-1))/2-pitch-2.54/2+2.54*pinnum+silkslw+2.54}, {'x': -6.775+padsize[0]/2+3.8-silkslw, 'y': -(pitch*(pinnum-1))/2-pitch-2.54/2-silkslw+2.54}, ] kicad_mod.append(PolygoneLine(polygone=s_body, width=configuration['silk_line_width'], layer="F.SilkS")) for y in range(0, pinnum): gen_silk_pins(-6.775+padsize[0]/2, -(pitch*(pinnum-1))/2+pitch+(y-1)*2.54, kicad_mod, configuration, y==0) s_pin1 = [ {'x': -6.775+padsize[0]/2-(2.5/2+configuration['silk_pad_clearance']+configuration['silk_line_width']), 'y': -(pitch*(pinnum-1))/2}, {'x': -6.775+padsize[0]/2-(2.5/2+configuration['silk_pad_clearance']+configuration['silk_line_width']), 'y': -(pitch*(pinnum-1))/2-1/2-configuration['silk_line_width']-configuration['silk_pad_clearance']}, {'x': -6.775+padsize[0]/2, 'y': -(pitch*(pinnum-1))/2-1/2-configuration['silk_line_width']-configuration['silk_pad_clearance']}, ] kicad_mod.append(PolygoneLine(polygone=s_pin1, width=configuration['silk_line_width'], layer="F.SilkS")) # CrtYd cy_offset = configuration['courtyard_offset']['connector'] cy_grid = configuration['courtyard_grid'] bounding_box={ 'left': -6.775+padsize[0]/2-2.5/2, 'right': -6.775+padsize[0]/2+12.3, 'top': -(pitch*(pinnum-1))/2-pitch-2.54/2+2.54, 'bottom': -(pitch*(pinnum-1))/2-pitch-2.54/2+2.54*pinnum+2.54, } cy_top = roundToBase(bounding_box['top'] - cy_offset, cy_grid) cy_bottom = roundToBase(bounding_box['bottom'] + cy_offset, cy_grid) cy_left = roundToBase(bounding_box['left'] - cy_offset, cy_grid) cy_right = roundToBase(bounding_box['right'] + cy_offset, cy_grid) poly_cy = [ {'x': cy_left, 'y': cy_top}, {'x': cy_right, 'y': cy_top}, {'x': cy_right, 'y': cy_bottom}, {'x': cy_left, 'y': cy_bottom}, {'x': cy_left, 'y': cy_top}, ] kicad_mod.append(PolygoneLine(polygone=poly_cy, layer='F.CrtYd', width=configuration['courtyard_line_width'])) # Text Fields body_edge={ 'left': -6.775+padsize[0]/2+3.8, 'right': -6.775+padsize[0]/2+6.3, 'top': -(pitch*(pinnum-1))/2-pitch-2.54/2-silkslw+2.54, 'bottom': -(pitch*(pinnum-1))/2-pitch-2.54/2+2.54*pinnum+silkslw+2.54, } addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy_top, 'bottom':cy_bottom}, fp_name=footprint_name, text_y_inside_position='center', allow_rotation=True) # 3D model model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) # Output 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pincount, configuration): mpn = part_code.format(n=pincount) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount//2, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Pins ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pincount, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) kicad_mod.setAttribute('smd') # calculate working values pad_x_spacing = 0.5 pad_y_spacing = 2.4 + 1.1 pad_width = 0.3 pad_height = 1.1 pad_x_span = (pad_x_spacing * ((pincount / 2) - 1)) h_body_width = 3.1 / 2.0 h_body_length = (pad_x_span / 2.0) + 1.4 + 0.37 fab_width = configuration['fab_line_width'] outline_x = h_body_length - (pad_x_span / 2.0) - pad_width/2 - (configuration['silk_pad_clearance'] + configuration['silk_line_width']/2) marker_y = 0.8 silk_width = configuration['silk_line_width'] nudge = configuration['silk_fab_offset'] courtyard_width = configuration['courtyard_line_width'] courtyard_precision = configuration['courtyard_grid'] courtyard_clearance = configuration['courtyard_offset']['connector'] courtyard_x = roundToBase(h_body_length + courtyard_clearance, courtyard_precision) courtyard_y = roundToBase((pad_y_spacing + pad_height) / 2.0 + courtyard_clearance, courtyard_precision) # create pads kicad_mod.append(PadArray(pincount=pincount//2, x_spacing=pad_x_spacing, y_spacing=0,\ center=[0,-pad_y_spacing/2.0], initial=1, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[pad_width, pad_height],\ layers=Pad.LAYERS_SMT)) kicad_mod.append(PadArray(pincount=pincount//2, x_spacing=pad_x_spacing, y_spacing=0,\ center=[0,pad_y_spacing/2.0], initial=2, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[pad_width, pad_height],\ layers=Pad.LAYERS_SMT)) # create fab outline and pin 1 marker kicad_mod.append(RectLine(start=[-h_body_length, -h_body_width], end=[h_body_length, h_body_width], layer='F.Fab', width=fab_width)) body_edge={ 'left':-h_body_length, 'top':-h_body_width } body_edge['right'] = -body_edge['left'] body_edge['bottom'] = -body_edge['top'] kicad_mod.append(Line(start=[-h_body_length+outline_x, -h_body_width-nudge], end=[-h_body_length+outline_x, -h_body_width-marker_y], layer='F.Fab', width=fab_width)) # create silkscreen outline and pin 1 marker left_outline = [[-h_body_length+outline_x, h_body_width+nudge], [-h_body_length-nudge, h_body_width+nudge], [-h_body_length-nudge, -h_body_width-nudge],\ [-h_body_length+outline_x, -h_body_width-nudge], [-h_body_length+outline_x, -h_body_width-marker_y]] right_outline = [[h_body_length-outline_x, h_body_width+nudge], [h_body_length+nudge, h_body_width+nudge], [h_body_length+nudge, -h_body_width-nudge],\ [h_body_length-outline_x, -h_body_width-nudge]] kicad_mod.append(PolygoneLine(polygone=left_outline, layer='F.SilkS', width=silk_width)) kicad_mod.append(PolygoneLine(polygone=right_outline, layer='F.SilkS', width=silk_width)) # create courtyard kicad_mod.append(RectLine(start=[-courtyard_x, -courtyard_y], end=[courtyard_x, courtyard_y], layer='F.CrtYd', width=courtyard_width)) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':-courtyard_y, 'bottom':+courtyard_y}, fp_name=footprint_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)
def generate_one_footprint(pins, params, configuration): pad_silk_off = configuration[ 'silk_pad_clearance'] + configuration['silk_line_width'] / 2 off = configuration['silk_fab_offset'] mpn = params['mpn'].format(n=pins * number_of_rows) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format( man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad="", pitch=pitch, orientation=orientation_str) footprint_name += params['fp_name_suffix'] kicad_mod = Footprint(footprint_name) desc_format_str = "Molex {:s}, {:s}{:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription( desc_format_str.format(series_long, mpn, params['description'], pins, params['datasheet'])) kicad_mod.setTags(configuration['keyword_fp_string'].format( series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) # Dimensions P = (pins - 1) * pitch B = P + 2 * 6.79 # connector length W = 14.76 # connector width body_edge = {} body_edge['left'] = (P - B) / 2 body_edge['right'] = body_edge['left'] + B body_edge['top'] = 0.925 body_edge['bottom'] = body_edge['top'] + 14.76 bounding_box = body_edge.copy() bounding_box['top'] = -offset_second_pad - pad_size[1] / 2 ################################## Pins ################################## kicad_mod.append( PadArray(pincount=pins, start=[0, 0], x_spacing=pitch, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_THT)) kicad_mod.append( PadArray(pincount=pins, start=[0, -offset_second_pad], x_spacing=pitch, size=pad_size, drill=drill, shape=Pad.SHAPE_RECT, type=Pad.TYPE_THT, layers=Pad.LAYERS_THT)) d_small = 0.3 s_small = d_small + 2 * min_annular_ring thermal_to_pad_edge = s_small / 2 + 0.15 if params['thermals']: for xi in range(pins): n = xi + 1 pad_center_y = -offset_second_pad / 2 pad_center_x = xi * pitch pad_h = offset_second_pad + pad_size[1] dx = (pad_size[0] - 2 * thermal_to_pad_edge) / 2 dy = (pad_h - 2 * thermal_to_pad_edge) / 4 #draw rectangle on F.Fab layer # kicad_mod.append(RectLine( # start=[pad_center_x - pad_l/2, pad_center_y - pad_size[1]/2], # end=[pad_center_x + pad_l/2, pad_center_y + pad_size[1]/2], # layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append( PadArray(center=[pad_center_x, pad_center_y], pincount=3, y_spacing=dy * 2, drill=d_small, size=s_small, initial=n, increment=0, shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_THT, layers=Pad.LAYERS_THT)) kicad_mod.append( PadArray(center=[pad_center_x - dx, pad_center_y], pincount=5, y_spacing=dy, drill=d_small, size=s_small, initial=n, increment=0, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_THT)) kicad_mod.append( PadArray(center=[pad_center_x + dx, pad_center_y], pincount=5, y_spacing=dy, drill=d_small, size=s_small, initial=n, increment=0, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_THT)) if params['lock']: kicad_mod.append( Pad(at=[-ret_dx, ret_dy], type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, size=ret_size, drill=ret_drill, layers=Pad.LAYERS_THT)) kicad_mod.append( Pad(at=[P + ret_dx, ret_dy], type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, size=ret_size, drill=ret_drill, layers=Pad.LAYERS_THT)) kicad_mod.append( RectLine( start=[-pad_size[0] / 2, -offset_second_pad - pad_size[1] / 2], end=[pad_size[0] / 2, pad_size[1] / 2], offset=pad_silk_off, width=configuration['silk_line_width'], layer='B.SilkS')) ############################ Outline ############################## #kicad_mod.append(RectLine(start=[xl1, yt1], end=[xr1, yb1], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append( RectLine(start=[body_edge['left'], body_edge['top']], end=[body_edge['right'], body_edge['bottom']], layer='F.Fab', width=configuration['fab_line_width'])) if params['lock']: silk1 = [ { 'x': -pad_size[0] / 2 - pad_silk_off, 'y': body_edge['top'] - off }, { 'x': body_edge['left'] - off, 'y': body_edge['top'] - off }, { 'x': body_edge['left'] - off, 'y': ret_dy - ret_size / 2 }, ] kicad_mod.append( PolygoneLine(polygone=silk1, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=silk1, layer='F.SilkS', width=configuration['silk_line_width'], x_mirror=P / 2)) silk2 = [ { 'x': body_edge['left'] - off, 'y': ret_dy + ret_size / 2 }, { 'x': body_edge['left'] - off, 'y': body_edge['bottom'] + off }, { 'x': P / 2, 'y': body_edge['bottom'] + off }, ] kicad_mod.append( PolygoneLine(polygone=silk2, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append( PolygoneLine(polygone=silk2, layer='F.SilkS', width=configuration['silk_line_width'], x_mirror=P / 2)) else: kicad_mod.append( RectLine(start=[body_edge['left'], body_edge['top']], end=[body_edge['right'], body_edge['bottom']], offset=off, layer='F.SilkS', width=configuration['silk_line_width'])) for i in range(pins - 1): kicad_mod.append( Line(start=[ i * pitch + pad_size[0] / 2 + pad_silk_off, body_edge['top'] - off ], end=[(i + 1) * pitch - pad_size[0] / 2 - pad_silk_off, body_edge['top'] - off], layer='F.SilkS', width=configuration['silk_line_width'])) for i in range(pins): w_pin = 1 kicad_mod.append( RectLine( start=[i * pitch - w_pin / 2, body_edge['top']], end=[i * pitch + w_pin / 2, -offset_second_pad - drill / 2], layer='F.Fab', width=configuration['fab_line_width'])) ############################ Pin 1 ################################ # Pin 1 designator pin1_sl = 2.4 pin1 = [{ 'x': -pin1_sl / 2, 'y': body_edge['top'] }, { 'x': 0, 'y': body_edge['top'] + pin1_sl / sqrt(2) }, { 'x': pin1_sl / 2, 'y': body_edge['top'] }] kicad_mod.append( PolygoneLine(polygone=pin1, layer='F.Fab', width=configuration['fab_line_width'])) pin1 = [{ 'x': -pad_size[0] / 2 - pad_silk_off, 'y': body_edge['top'] - off }, { 'x': -pad_size[0] / 2 - pad_silk_off, 'y': -offset_second_pad - pad_size[1] / 2 }] kicad_mod.append( PolygoneLine(polygone=pin1, layer='F.SilkS', width=configuration['silk_line_width'])) # pin1 = [ # {'x': 0, 'y': 8}, # {'x': 0.5, 'y': 9}, # {'x': -0.5, 'y': 9}, # {'x': 0, 'y': 8}, # ] # kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.SilkS', width=configuration['silk_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase( bounding_box['left'] - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase( bounding_box['top'] - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase( bounding_box['right'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase( bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append( RectLine(start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={ 'top': cy1, 'bottom': cy2 }, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) 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=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename)