kicad/pcbnew/scripting/plugins/qfp_wizard.py

230 lines
8.5 KiB
Python

import pcbnew
def abs(x):
if x < 0:
return -x
return x
class QFPWizard(pcbnew.FootprintWizardPlugin):
def __init__(self):
pcbnew.FootprintWizardPlugin.__init__(self)
self.name = "QFP"
self.description = "QFP Footprint Wizard"
self.parameters = {
"Pads": {
"*n": 100,
"pitch": pcbnew.FromMM(0.5),
"width": pcbnew.FromMM(0.25),
"length": pcbnew.FromMM(1.5),
"horizontal pitch": pcbnew.FromMM(15),
"vertical pitch": pcbnew.FromMM(15),
"*oval": "True"
},
"Package": {
"width": pcbnew.FromMM(14),
"height": pcbnew.FromMM(14)
}
}
self.ClearErrors()
def smd_rect_pad(self, module, size, pos, name):
pad = pcbnew.D_PAD(module)
pad.SetSize(size)
if self.parameters['Pads'].get('*oval', "true").lower() == "true":
pad.SetShape(pcbnew.PAD_OVAL)
else:
pad.SetShape(pcbnew.PAD_RECT)
pad.SetAttribute(pcbnew.PAD_SMD)
pad.SetLayerMask(pcbnew.PAD_SMD_DEFAULT_LAYERS)
pad.SetPos0(pos)
pad.SetPosition(pos)
pad.SetPadName(name)
return pad
def CheckParameters(self):
errors = ""
pads = self.parameters
num_pads = pads["Pads"]["*n"]
if (num_pads < 1):
self.parameter_errors["Pads"]["*n"] = "Must be positive"
errors +="Pads/n has wrong value, "
pads["Pads"]["*n"] = int(num_pads) # Reset to int instead of float
return errors
def BuildFootprint(self):
if self.has_errors():
print "Cannot build footprint: Parameters have errors:"
print self.parameter_errors
return
print "Building new QFP footprint with the following parameters:"
self.print_parameter_table()
self.module = pcbnew.MODULE(None) # create a new module
pads = self.parameters
num_pads = int(pads["Pads"]["*n"])
pad_width = pads["Pads"]["width"]
pad_length = pads["Pads"]["length"]
pad_pitch = pads["Pads"]["pitch"]
pad_horizontal_pitch = pads["Pads"]["horizontal pitch"]
pad_vertical_pitch = pads["Pads"]["vertical pitch"]
package_width = pads["Package"]["width"]
package_height = pads["Package"]["height"]
side_length = pad_pitch * ((num_pads / 4) - 1)
offsetX = pad_pitch * ((num_pads / 4) - 1) / 2
text_size = pcbnew.wxSize(pcbnew.FromMM(0.8), pcbnew.FromMM(0.8))
self.module.SetReference("QFP %d" % int(num_pads))
self.module.Reference().SetPos0(pcbnew.wxPoint(0, pcbnew.FromMM(-0.8)))
self.module.Reference().SetTextPosition(self.module.Reference().GetPos0())
self.module.Reference().SetSize(text_size)
self.module.SetValue("U**")
self.module.Value().SetPos0(pcbnew.wxPoint(0, pcbnew.FromMM(+0.8)))
self.module.Value().SetTextPosition(self.module.Value().GetPos0())
self.module.Value().SetSize(text_size)
self.module.SetLibRef("QFP-%d" % int(num_pads))
pad_size_left_right = pcbnew.wxSize(pad_length, pad_width)
pad_size_bottom_top = pcbnew.wxSize(pad_width, pad_length)
for cur_pad in range(0, num_pads):
side = int(cur_pad / (num_pads / 4)) # 0 -> left, 1 -> bottom, 2 -> right, 3 -> top
if side == 0 or side == 2:
pad_size = pad_size_left_right
pad_pos_x = -(pad_horizontal_pitch / 2)
if side == 2:
pad_pos_x = -pad_pos_x
pad_pos_y = (cur_pad % (num_pads / 4)) * pad_pitch - (side_length / 2)
else:
pad_size = pad_size_bottom_top
pad_pos_x = (cur_pad % (num_pads / 4)) * pad_pitch - (side_length / 2)
pad_pos_y = -(pad_vertical_pitch / 2)
if side == 1:
pad_pos_y = -pad_pos_y
pad_pos = pcbnew.wxPoint(pad_pos_x, pad_pos_y)
pad = self.smd_rect_pad(self.module, pad_size, pad_pos, str(cur_pad + 1))
self.module.Add(pad)
half_package_width = package_width / 2
half_package_height = package_height / 2
package_pad_height_offset = abs(package_height - side_length) / 2 - pad_pitch
package_pad_width_offset = abs(package_width - side_length) / 2 - pad_pitch
# Bottom Left Edge, vertical line
outline = pcbnew.EDGE_MODULE(self.module)
outline.SetWidth(pcbnew.FromMM(0.2))
outline.SetLayer(pcbnew.SILKSCREEN_N_FRONT)
outline.SetShape(pcbnew.S_SEGMENT)
start = pcbnew.wxPoint(-half_package_width, half_package_height - package_pad_height_offset)
end = pcbnew.wxPoint(-half_package_width, half_package_height)
outline.SetStartEnd(start, end)
self.module.Add(outline)
# Bottom Left Edge, horizontal line
outline = pcbnew.EDGE_MODULE(self.module)
outline.SetWidth(pcbnew.FromMM(0.2))
outline.SetLayer(pcbnew.SILKSCREEN_N_FRONT)
outline.SetShape(pcbnew.S_SEGMENT)
start = pcbnew.wxPoint(-half_package_width, half_package_height)
end = pcbnew.wxPoint(-half_package_width + package_pad_width_offset, half_package_height)
outline.SetStartEnd(start, end)
self.module.Add(outline)
# Bottom Right Edge, vertical line
outline = pcbnew.EDGE_MODULE(self.module)
outline.SetWidth(pcbnew.FromMM(0.2))
outline.SetLayer(pcbnew.SILKSCREEN_N_FRONT)
outline.SetShape(pcbnew.S_SEGMENT)
start = pcbnew.wxPoint(half_package_width, half_package_height - package_pad_height_offset)
end = pcbnew.wxPoint(half_package_width, half_package_height)
outline.SetStartEnd(start, end)
self.module.Add(outline)
# Bottom Right Edge, horizontal line
outline = pcbnew.EDGE_MODULE(self.module)
outline.SetWidth(pcbnew.FromMM(0.2))
outline.SetLayer(pcbnew.SILKSCREEN_N_FRONT)
outline.SetShape(pcbnew.S_SEGMENT)
start = pcbnew.wxPoint(half_package_width, half_package_height)
end = pcbnew.wxPoint(half_package_width - package_pad_width_offset, half_package_height)
outline.SetStartEnd(start, end)
self.module.Add(outline)
# Top Right Edge, vertical line
outline = pcbnew.EDGE_MODULE(self.module)
outline.SetWidth(pcbnew.FromMM(0.2))
outline.SetLayer(pcbnew.SILKSCREEN_N_FRONT)
outline.SetShape(pcbnew.S_SEGMENT)
start = pcbnew.wxPoint(half_package_width, -half_package_height + package_pad_height_offset)
end = pcbnew.wxPoint(half_package_width, -half_package_height)
outline.SetStartEnd(start, end)
self.module.Add(outline)
# Top Right Edge, horizontal line
outline = pcbnew.EDGE_MODULE(self.module)
outline.SetWidth(pcbnew.FromMM(0.2))
outline.SetLayer(pcbnew.SILKSCREEN_N_FRONT)
outline.SetShape(pcbnew.S_SEGMENT)
start = pcbnew.wxPoint(half_package_width, -half_package_height)
end = pcbnew.wxPoint(half_package_width - package_pad_width_offset, -half_package_height)
outline.SetStartEnd(start, end)
self.module.Add(outline)
# Top Left Edge, straight line
outline = pcbnew.EDGE_MODULE(self.module)
outline.SetWidth(pcbnew.FromMM(0.2))
outline.SetLayer(pcbnew.SILKSCREEN_N_FRONT)
outline.SetShape(pcbnew.S_SEGMENT)
start = pcbnew.wxPoint(-half_package_width, -half_package_height + package_pad_height_offset)
end = pcbnew.wxPoint(-half_package_width + package_pad_width_offset, -half_package_height)
outline.SetStartEnd(start, end)
self.module.Add(outline)
def print_parameter_table(self):
for name, section in self.parameters.iteritems():
print " %s:" % name
for key, value in section.iteritems():
unit = ""
if (type(value) is int or type(value) is float) and not "*" in key:
unit = "mm"
if "*" in key:
key = key[1:]
else:
value = pcbnew.ToMM(value)
print " %s: %s%s" % (key, value, unit)
def has_errors(self):
for name, section in self.parameter_errors.iteritems():
for k, v in section.iteritems():
if v:
return True
return False
QFPWizard().register()