WIP: footprint generation based off of text on 'User.Drawings' layer
This commit is contained in:
182
.scripts/foot_gen.py
Normal file
182
.scripts/foot_gen.py
Normal file
@@ -0,0 +1,182 @@
|
||||
import sys
|
||||
import os
|
||||
|
||||
from pcbnew import *
|
||||
|
||||
filename = sys.argv[1]
|
||||
|
||||
pcb = LoadBoard(filename)
|
||||
|
||||
ToUnits = ToMM
|
||||
FromUnits = FromMM
|
||||
|
||||
print("")
|
||||
print("List drawings:")
|
||||
|
||||
|
||||
# layers = pcb.GetEnabledLayers()
|
||||
top_layer_id = pcb.GetLayerID("F.Cu")
|
||||
|
||||
|
||||
new_foots = {}
|
||||
foot_name = ""
|
||||
foot_path = ""
|
||||
for item in pcb.GetDrawings():
|
||||
if type(item) is PCB_TEXT and "User.Drawings" in item.GetLayerName():
|
||||
lines = str(item.GetText()).splitlines()
|
||||
# Must have the correct header
|
||||
if "Foot Pinout" not in lines[0]:
|
||||
continue
|
||||
if not lines[1].startswith("Name:"):
|
||||
continue
|
||||
foot_name = lines[1].split(":")[-1].strip()
|
||||
if not lines[2].startswith("Path:"):
|
||||
continue
|
||||
foot_path = lines[2].split(":")[-1].strip()
|
||||
for line in lines[3:]:
|
||||
sp = line.split(':', 1)
|
||||
if len(sp) != 2:
|
||||
continue
|
||||
# Path to substitue footprint
|
||||
ref = sp[0]
|
||||
foot_sp = sp[1].split(',')
|
||||
foot = foot_sp[0].strip()
|
||||
offset = (0,0)
|
||||
# Optional offset tuple
|
||||
if len(foot_sp) == 2:
|
||||
offset = tuple(foot_sp[1])
|
||||
|
||||
new_foots[ref] = [foot, offset]
|
||||
# pins = sp[1]
|
||||
# pin_refs = []
|
||||
# for pin in pins.split(','):
|
||||
# pin_refs.push(int(pin))
|
||||
|
||||
break
|
||||
elif type(item) is PCB_TEXT:
|
||||
print("Text: ", item.GetText())
|
||||
print("Layer: ", item.GetLayerName())
|
||||
|
||||
print("")
|
||||
print("New Footprint List: ", new_foots)
|
||||
|
||||
# Clear tracks
|
||||
pcb.Tracks().clear()
|
||||
# Clear zones
|
||||
pcb.Zones().clear()
|
||||
# Clear Drawings
|
||||
pcb.Drawings().clear()
|
||||
|
||||
# Keep only required foots
|
||||
saved = []
|
||||
while len(pcb.Footprints()) > 1:
|
||||
foot = pcb.Footprints().pop()
|
||||
if foot.GetReference() in new_foots.keys():
|
||||
saved.append(foot)
|
||||
# just in case
|
||||
pcb.DeleteAllFootprints()
|
||||
# Add them back
|
||||
sorted_pads = []
|
||||
for foot in saved:
|
||||
vals = new_foots[foot.GetReference()]
|
||||
# Change the footprint
|
||||
foot.SetFPIDAsString(vals[0])
|
||||
# Save the original postion of footprint + pads
|
||||
orig_cent = foot.GetBoundingBox(False,False).Centre()
|
||||
pads = []
|
||||
for pad in foot.Pads():
|
||||
pads.append([pad.GetCenter(), pad.GetNet()])
|
||||
|
||||
# Flip to other side
|
||||
foot.SetLayerAndFlip(top_layer_id)
|
||||
# Put back in original position with an offset
|
||||
box = foot.GetBoundingBox(False,False)
|
||||
new_cent = foot.GetBoundingBox(False,False).Centre()
|
||||
cent_diff = orig_cent - new_cent
|
||||
foot.SetX(foot.GetX() + cent_diff.x + vals[1][0])
|
||||
foot.SetY(foot.GetY() + cent_diff.y + vals[1][1])
|
||||
# Flip the net assignments of the pads
|
||||
for pad in foot.Pads():
|
||||
sorted_pads.append(pad)
|
||||
# Check position diff from old
|
||||
# to new
|
||||
new_cent = pad.GetCenter()
|
||||
diffs = []
|
||||
for [old_cent,_] in pads:
|
||||
diffs.append(new_cent - old_cent)
|
||||
min_diff = min(diffs)
|
||||
# If pad is within 0.05mm it's a match
|
||||
if (min_diff.x**2 + min_diff.y**2)**0.5 < 50000:
|
||||
# Set the net to what the old pad was
|
||||
i = diffs.index(min_diff)
|
||||
match_pad = pads[i][1:]
|
||||
pad.SetNet(match_pad[0])
|
||||
|
||||
pcb.Add(foot)
|
||||
|
||||
|
||||
# Sort by Y
|
||||
sorted_pads.sort(key=lambda p: p.GetY())
|
||||
|
||||
box = pcb.GetBoundingBox()
|
||||
brd_width = ToUnits(box.GetWidth())
|
||||
brd_height = ToUnits(box.GetHeight())
|
||||
|
||||
print("Box: ", box)
|
||||
print("W: ", brd_width, "H: ", brd_height)
|
||||
|
||||
|
||||
sys.path.append(os.path.join(sys.path[0],"../../../../../dev/kicad-footprint-generator"))
|
||||
|
||||
|
||||
from KicadModTree import *
|
||||
from KicadModTree.nodes.specialized.PadArray import PadArray
|
||||
|
||||
footprint_name = ""
|
||||
|
||||
# init kicad footprint
|
||||
kicad_mod = Footprint(footprint_name, FootprintType.SMD)
|
||||
kicad_mod.setDescription("A example footprint")
|
||||
kicad_mod.setTags("example")
|
||||
|
||||
# set general values
|
||||
kicad_mod.append(Text(type='reference', text='REF**', at=[0,-3], layer='F.SilkS'))
|
||||
kicad_mod.append(Text(type='value', text=footprint_name, at=[1.5,3], layer='F.Fab'))
|
||||
|
||||
# create silscreen
|
||||
kicad_mod.append(RectLine(start=[-brd_width/2,-brd_height/2], end=[brd_width/2,brd_height/2], layer='F.SilkS', width=0.15))
|
||||
|
||||
# create courtyard
|
||||
kicad_mod.append(RectLine(start=[-brd_width/2 - 0.1,-brd_height/2 - 0.1], end=[brd_width/2 + 0.1,brd_height/2 + 0.1], layer='F.CrtYd', width=0.05, offset=2))
|
||||
|
||||
# create pads
|
||||
|
||||
for x, pad in enumerate(sorted_pads):
|
||||
cent = ToUnits(pad.GetCenter())
|
||||
pad_size = ToUnits(pad.GetSize())
|
||||
drill_size = ToUnits(pad.GetDrillSize())
|
||||
kicad_mod.append(Pad(number=x, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, at=list(cent), size=list(pad_size), drill=list(drill_size), layers=['*.Cu', '*.Mask', 'F.SilkS']))
|
||||
# kicad_mod.append(Pad(number=22, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, at=[3,0], size=[2,2], drill=1.2, layers=['*.Cu', '*.Mask', 'F.SilkS']))
|
||||
#
|
||||
# kicad_mod.append(Pad(number=12, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[3,0], size=[2,2], drill=1.2, layers=['*.Cu', '*.Mask', 'F.SilkS']))
|
||||
|
||||
# add model
|
||||
# kicad_mod.append(Model(filename="example.3dshapes/example_footprint.wrl"
|
||||
# ,at=[0,0,0]
|
||||
# ,scale=[1,1,1]
|
||||
# ,rotate=[0,0,0]))
|
||||
|
||||
# kicad_mod.append(PadArray(pincount=10,spacing=[1,-1],center=[0,0], initial=5, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[1,2], layers=["*.Cu"]))
|
||||
|
||||
# output kicad model
|
||||
#print(kicad_mod)
|
||||
|
||||
# print render tree
|
||||
#print(kicad_mod.getRenderTree())
|
||||
#print(kicad_mod.getCompleteRenderTree())
|
||||
|
||||
# write file
|
||||
file_handler = KicadFileHandler(kicad_mod)
|
||||
file_handler.writeFile('example_footprint.kicad_mod')
|
||||
|
||||
SaveBoard("test/test.kicad_pcb", pcb)
|
||||
Reference in New Issue
Block a user