Add John Beard's patch: new and useful footprint wizards (SIP/SIP, SOIC/SSOP/TSSOP/MSOP and BGA).
Add Python utility tools to make wizard scripts more easy to write.
This commit is contained in:
parent
61fe97e666
commit
38f36ae45c
|
@ -0,0 +1,134 @@
|
|||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
import pcbnew
|
||||
|
||||
class FootprintWizardDrawingAids:
|
||||
"""
|
||||
Collection of handy functions to simplify drawing shapes from within
|
||||
footprint wizards
|
||||
|
||||
A "drawing context" is provided which can be used to set and retain
|
||||
settings such as line width and layer
|
||||
"""
|
||||
def __init__(self, module):
|
||||
self.module = module
|
||||
#drawing context defaults
|
||||
self.dc = {
|
||||
'layer': pcbnew.SILKSCREEN_N_FRONT,
|
||||
'width': pcbnew.FromMM(0.2)
|
||||
}
|
||||
|
||||
def SetWidth(self, width):
|
||||
self.dc['width'] = width
|
||||
|
||||
def SetLayer(self, layer):
|
||||
self.dc['layer'] = layer
|
||||
|
||||
def Line(self, x1, y1, x2, y2):
|
||||
|
||||
outline = pcbnew.EDGE_MODULE(self.module)
|
||||
outline.SetWidth(self.dc['width'])
|
||||
outline.SetLayer(self.dc['layer'])
|
||||
outline.SetShape(pcbnew.S_SEGMENT)
|
||||
start = pcbnew.wxPoint(x1, y1)
|
||||
end = pcbnew.wxPoint(x2, y2)
|
||||
outline.SetStartEnd(start, end)
|
||||
self.module.Add(outline)
|
||||
|
||||
# extends from (x1,y1) right
|
||||
def HLine(self, x, y, l):
|
||||
"""
|
||||
Draw a horizontal line from (x,y), rightwards
|
||||
"""
|
||||
self.Line(x, y, x + l, y)
|
||||
|
||||
def VLine(self, x, y, l):
|
||||
"""
|
||||
Draw a vertical line from (x1,y1), downwards
|
||||
"""
|
||||
self.Line(x, y, x, y + l)
|
||||
|
||||
def Polyline(self, pts):
|
||||
|
||||
if len(pts) < 2:
|
||||
return
|
||||
|
||||
for i in range(0, len(pts) - 1):
|
||||
self.Line(pts[i][0], pts[i][1], pts[i+1][0], pts[i+1][1])
|
||||
|
||||
def Reference(self, x, y, size):
|
||||
"""
|
||||
Draw the module's reference as the given point.
|
||||
|
||||
The actual setting of the reference is not done in this drawing
|
||||
aid - that is up to the wizard
|
||||
"""
|
||||
|
||||
text_size = pcbnew.wxSize(size, size)
|
||||
|
||||
self.module.Reference().SetPos0(pcbnew.wxPoint(x, y))
|
||||
self.module.Reference().SetTextPosition(self.module.Reference().GetPos0())
|
||||
self.module.Reference().SetSize(text_size)
|
||||
|
||||
def Value(self, x, y, size):
|
||||
"""
|
||||
As for references, draw the module's value
|
||||
"""
|
||||
text_size = pcbnew.wxSize(size, size)
|
||||
|
||||
self.module.Value().SetPos0(pcbnew.wxPoint(x, y))
|
||||
self.module.Value().SetTextPosition(self.module.Value().GetPos0())
|
||||
self.module.Value().SetSize(text_size)
|
||||
|
||||
def Box(self, x, y, w, h):
|
||||
"""
|
||||
Draw a rectangular box, centred at (x,y), with given width and
|
||||
height
|
||||
"""
|
||||
self.VLine(x - w/2, y - h/2, h) # left
|
||||
self.VLine(x + w/2, y - h/2, h) # right
|
||||
self.HLine(x - w/2, y + h/2, w) # bottom
|
||||
self.HLine(x - w/2, y - h/2, w) # top
|
||||
|
||||
def NotchedBox(self, x, y, w, h, notchW, notchH):
|
||||
"""
|
||||
Draw a box with a notch in the top edge
|
||||
"""
|
||||
#limit to half the overall width
|
||||
notchW = min(x + w/2, notchW)
|
||||
|
||||
# draw notch
|
||||
self.Polyline([ #three sides of box
|
||||
(x - w/2, y - h/2),
|
||||
(x - w/2, y + h/2),
|
||||
(x + w/2, y + h/2),
|
||||
(x + w/2, y - h/2),
|
||||
#the notch
|
||||
(notchW/2, y - h/2),
|
||||
(notchW/2, y - h/2 + notchH),
|
||||
(-notchW/2, y - h/2 + notchH),
|
||||
(-notchW/2, y - h/2),
|
||||
(x - w/2, y - h/2)
|
||||
])
|
||||
|
||||
def BoxWithDiagonalAtCorner(self, x, y, w, h, diagSetback):
|
||||
|
||||
self.Box(x, y, w, h)
|
||||
|
||||
#diagonal corner
|
||||
self.Line(x - w/2 + diagSetback, x - h/2, x - w/2,
|
||||
x - h/2 + diagSetback)
|
|
@ -0,0 +1,250 @@
|
|||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
import pcbnew
|
||||
import FootprintWizardDrawingAids
|
||||
|
||||
class FootprintWizardParameterManager:
|
||||
"""
|
||||
Functions for helpfully managing parameters to a KiCAD Footprint
|
||||
Wizard.
|
||||
|
||||
Abstracts away from whatever structure is used by pcbnew's footprint
|
||||
wizard class
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.parameters = {}
|
||||
self.GenerateParameterList()
|
||||
|
||||
def GenerateParameterList(self):
|
||||
"""
|
||||
Construct parameters here, or leave out to have no parameters
|
||||
"""
|
||||
pass
|
||||
|
||||
def CheckParameters(self):
|
||||
"""
|
||||
Implement this to make checks on parameter values, filling
|
||||
parameter_errors (or using the checker routines)
|
||||
|
||||
Subclasses can implment their own and override the parent
|
||||
defaults and add new ones
|
||||
"""
|
||||
pass
|
||||
|
||||
uMM = 1
|
||||
uMils = 2
|
||||
uNatural = 3
|
||||
uBool = 4
|
||||
|
||||
def AddParam(self, section, param, unit, default, hint = ''):
|
||||
"""
|
||||
Add a parameter with some properties.
|
||||
|
||||
TODO: Hints are not supported, as there is as yet nowhere to
|
||||
put them in the KiCAD interface
|
||||
"""
|
||||
|
||||
val = None
|
||||
if unit == self.uMM:
|
||||
val = pcbnew.FromMM(default)
|
||||
elif unit == self.uMils:
|
||||
val = pcbnew.FromMils(default)
|
||||
elif unit == self.uNatural:
|
||||
val = default
|
||||
elif unit == self.uBool:
|
||||
val = "True" if default else "False" #ugly stringing
|
||||
else:
|
||||
print "Warning: Unknown unit type: %s" % unit
|
||||
return
|
||||
|
||||
if unit in [self.uNatural, self.uBool]:
|
||||
param = "*%s" % param #star prefix for natural
|
||||
|
||||
if section not in self.parameters:
|
||||
self.parameters[section] = {}
|
||||
|
||||
self.parameters[section][param] = val
|
||||
|
||||
def _PrintParameterTable(self):
|
||||
"""
|
||||
Pretty-print the parameters we have
|
||||
"""
|
||||
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 _ParametersHaveErrors(self):
|
||||
"""
|
||||
Return true if we discovered errors suring parameter processing
|
||||
"""
|
||||
|
||||
for name, section in self.parameter_errors.iteritems():
|
||||
for k, v in section.iteritems():
|
||||
if v:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _PrintParameterErrors(self):
|
||||
"""
|
||||
Pretty-print parameters with errors
|
||||
"""
|
||||
|
||||
for name, section in self.parameter_errors.iteritems():
|
||||
printed_section = False
|
||||
|
||||
for key, value in section.iteritems():
|
||||
if value:
|
||||
if not printed_section:
|
||||
print " %s:" % name
|
||||
|
||||
print " %s: %s (have %s)" % (key, value,
|
||||
self.parameters[name][key])
|
||||
|
||||
def ProcessParameters(self):
|
||||
"""
|
||||
Make sure the parameters we have meet whatever expectations the
|
||||
footprint wizard has of them
|
||||
"""
|
||||
|
||||
self.ClearErrors()
|
||||
self.CheckParameters();
|
||||
|
||||
if self._ParametersHaveErrors():
|
||||
print "Cannot build footprint: Parameters have errors:"
|
||||
self._PrintParameterErrors()
|
||||
return False
|
||||
|
||||
print "Building new %s footprint with the following parameters:" % self.name
|
||||
|
||||
self._PrintParameterTable()
|
||||
return True
|
||||
|
||||
#################################################################
|
||||
# PARAMETER CHECKERS
|
||||
#################################################################
|
||||
|
||||
def CheckParamPositiveInt(self, section, param, min_value = 1,
|
||||
max_value = None, is_multiple_of = 1):
|
||||
"""
|
||||
Make sure a parameter can be made into an int, and enforce
|
||||
limits if required
|
||||
"""
|
||||
|
||||
try:
|
||||
self.parameters[section][param] = int(self.parameters[section][param])
|
||||
except ValueError:
|
||||
self.parameter_errors[section][param] = "Must be a valid integer"
|
||||
return
|
||||
|
||||
if min_value is not None and (self.parameters[section][param] < min_value):
|
||||
self.parameter_errors[section][param] = "Must be greater than or equal to %d" % (min_value)
|
||||
return
|
||||
|
||||
if max_value is not None and (self.parameters[section][param] > min_value):
|
||||
self.parameter_errors[section][param] = "Must be less than or equal to %d" % (max_value)
|
||||
return
|
||||
|
||||
if is_multiple_of > 1 and (self.parameters[section][param] % is_multiple_of) > 0:
|
||||
self.parameter_errors[section][param] = "Must be a multiple of %d" % is_multiple_of
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
def CheckParamBool(self, section, param):
|
||||
"""
|
||||
Make sure a parameter looks like a boolean, convert to native
|
||||
boolean type if so
|
||||
"""
|
||||
if str(self.parameters[section][param]).lower() in ["true", "t", "y", "yes", "on", "1", "1.0"]:
|
||||
self.parameters[section][param] = True;
|
||||
return
|
||||
elif str(self.parameters[section][param]).lower() in ["false", "f", "n", "no", "off", "0", "0.0"]:
|
||||
self.parameters[section][param] = False;
|
||||
return
|
||||
|
||||
self.parameter_errors[section][param] = "Must be boolean (true/false)"
|
||||
return
|
||||
|
||||
|
||||
class HelpfulFootprintWizardPlugin(pcbnew.FootprintWizardPlugin,
|
||||
FootprintWizardParameterManager):
|
||||
"""
|
||||
A class to simplify many aspects of footprint creation, leaving only
|
||||
the foot-print specific routines to the wizards themselves
|
||||
|
||||
Generally, you need to implement:
|
||||
GetReference()
|
||||
GetValue()
|
||||
GenerateParameterList()
|
||||
CheckParameters()
|
||||
BuildThisFootprint()
|
||||
GetName()
|
||||
GetDescription()
|
||||
"""
|
||||
def __init__(self):
|
||||
pcbnew.FootprintWizardPlugin.__init__(self)
|
||||
FootprintWizardParameterManager.__init__(self)
|
||||
|
||||
self.name = self.GetName()
|
||||
self.decription = self.GetDescription()
|
||||
self.image = self.GetImage()
|
||||
|
||||
def GetReference(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def GetValuePrefix(self):
|
||||
return "U" # footprints needing wizards of often ICs
|
||||
|
||||
def GetImage(self):
|
||||
return ""
|
||||
|
||||
def BuildThisFootprint(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def BuildFootprint(self):
|
||||
"""
|
||||
Actually make the footprint. We defer all but the setup to
|
||||
the implmenting class
|
||||
"""
|
||||
|
||||
if not self.ProcessParameters():
|
||||
return
|
||||
|
||||
self.module = pcbnew.MODULE(None) # create a new module
|
||||
|
||||
self.draw = FootprintWizardDrawingAids.FootprintWizardDrawingAids(self.module)
|
||||
|
||||
self.module.SetReference(self.GetReference())
|
||||
self.module.SetValue("%s**" % self.GetValuePrefix())
|
||||
|
||||
fpid = pcbnew.FPID(self.module.GetReference()) #the name in library
|
||||
self.module.SetFPID( fpid )
|
||||
|
||||
self.BuildThisFootprint() # implementer's build function
|
|
@ -0,0 +1,148 @@
|
|||
|
||||
import pcbnew
|
||||
|
||||
class PadMaker:
|
||||
"""
|
||||
Useful construction functions for common types of pads
|
||||
"""
|
||||
|
||||
def __init__(self, module):
|
||||
self.module = module
|
||||
|
||||
def THPad(self, w, l, drill, shape = pcbnew.PAD_OVAL):
|
||||
pad = pcbnew.D_PAD(self.module)
|
||||
|
||||
pad.SetSize(pcbnew.wxSize(l, w))
|
||||
|
||||
pad.SetShape(shape)
|
||||
|
||||
pad.SetAttribute(pcbnew.PAD_STANDARD)
|
||||
pad.SetLayerMask(pcbnew.PAD_STANDARD_DEFAULT_LAYERS)
|
||||
pad.SetDrillSize(pcbnew.wxSize(drill, drill))
|
||||
|
||||
return pad
|
||||
|
||||
def SMDPad(self, w, l, shape = pcbnew.PAD_RECT):
|
||||
pad = pcbnew.D_PAD(self.module)
|
||||
pad.SetSize(pcbnew.wxSize(l, w))
|
||||
|
||||
pad.SetShape(shape)
|
||||
|
||||
pad.SetAttribute(pcbnew.PAD_SMD)
|
||||
pad.SetLayerMask(pcbnew.PAD_SMD_DEFAULT_LAYERS)
|
||||
|
||||
return pad
|
||||
|
||||
def SMTRoundPad(self, size):
|
||||
pad = self.SMDPad(size, size, shape = pcbnew.PAD_CIRCLE)
|
||||
return pad
|
||||
|
||||
class PadArray:
|
||||
|
||||
def __init__(self):
|
||||
self.firstPad = 1;
|
||||
|
||||
def SetFirstPadInArray(self, fpNum):
|
||||
self.firstPad = fpNum
|
||||
|
||||
# HACK! pad should one day have its own clone method
|
||||
def ClonePad(self):
|
||||
|
||||
pad = pcbnew.D_PAD(self.pad.GetParent())
|
||||
|
||||
pad.SetSize(self.pad.GetSize())
|
||||
pad.SetShape(self.pad.GetShape())
|
||||
pad.SetAttribute(self.pad.GetAttribute())
|
||||
pad.SetLayerMask(self.pad.GetLayerMask())
|
||||
pad.SetDrillSize(self.pad.GetDrillSize())
|
||||
|
||||
return pad
|
||||
|
||||
def AddPad(self, pad):
|
||||
self.pad.GetParent().Add(pad)
|
||||
|
||||
class PadGridArray(PadArray):
|
||||
|
||||
def __init__(self, pad, nx, ny, px, py, pin1Pos):
|
||||
# this pad is more of a "context", we will use it as a source of
|
||||
# pad data, but not actually add it
|
||||
self.pad = pad
|
||||
self.nx = int(nx)
|
||||
self.ny = int(ny)
|
||||
self.px = px
|
||||
self.py = py
|
||||
self.pin1Pos = pin1Pos
|
||||
|
||||
# handy utility function 1 - A, 2 - B, 26 - AA, etc
|
||||
# aIndex = 0 for 0 - A
|
||||
def AlphaNameFromNumber(self, n, aIndex = 1):
|
||||
|
||||
div, mod = divmod(n - aIndex, 26)
|
||||
alpha = chr(65 + mod)
|
||||
|
||||
if div > 0:
|
||||
return self.AlphaNameFromNumber(div) + alpha;
|
||||
|
||||
return alpha;
|
||||
|
||||
# right to left, top to bottom
|
||||
def NamingFunction(self, x, y):
|
||||
return self.firstPad + (self.nx * y + x)
|
||||
|
||||
#relocate the pad and add it as many times as we need
|
||||
def AddPadsToModule(self):
|
||||
|
||||
for x in range(0, self.nx):
|
||||
for y in range(self.ny):
|
||||
posX = self.pin1Pos.x + (self.px * x)
|
||||
posY = self.pin1Pos.y + (self.py * y)
|
||||
|
||||
pos = pcbnew.wxPoint(posX, posY)
|
||||
|
||||
# THIS DOESN'T WORK yet!
|
||||
#pad = self.pad.Clone()
|
||||
pad = self.ClonePad()
|
||||
|
||||
pad.SetPos0(pos)
|
||||
pad.SetPosition(pos)
|
||||
|
||||
pad.SetPadName(str(self.NamingFunction(x,y)))
|
||||
|
||||
self.AddPad(pad)
|
||||
|
||||
class PadLineArray(PadGridArray):
|
||||
|
||||
def __init__(self, pad, n, pitch, isVertical, pin1Pos):
|
||||
|
||||
if isVertical:
|
||||
PadGridArray.__init__(self, pad, 1, n, 0, pitch, pin1Pos)
|
||||
else:
|
||||
PadGridArray.__init__(self, pad, n, 1, pitch, 0, pin1Pos)
|
||||
|
||||
class RectPadArray(PadArray):
|
||||
|
||||
def __init__(self, nx, ny, pitch, xpitch, ypitch, pin1Pos):
|
||||
|
||||
#left row
|
||||
pin1Pos = pcbnew.wxPoint(-h_pitch / 2, -row_len / 2)
|
||||
array = PadLineArray(h_pad, pads_per_row, pad_pitch, True, pin1Pos)
|
||||
array.SetFirstPadInArray(1)
|
||||
array.AddPadsToModule()
|
||||
|
||||
#bottom row
|
||||
pin1Pos = pcbnew.wxPoint(-row_len / 2, v_pitch / 2)
|
||||
array = PA.PadLineArray(v_pad, pads_per_row, pad_pitch, False, pin1Pos)
|
||||
array.SetFirstPadInArray(pads_per_row + 1)
|
||||
array.AddPadsToModule()
|
||||
|
||||
#right row
|
||||
pin1Pos = pcbnew.wxPoint(h_pitch / 2, row_len / 2)
|
||||
array = PadLineArray(h_pad, pads_per_row, -pad_pitch, True, pin1Pos)
|
||||
array.SetFirstPadInArray(2*pads_per_row + 1)
|
||||
array.AddPadsToModule()
|
||||
|
||||
#top row
|
||||
pin1Pos = pcbnew.wxPoint(row_len / 2, -v_pitch / 2)
|
||||
array = PadLineArray(v_pad, pads_per_row, -pad_pitch, False, pin1Pos)
|
||||
array.SetFirstPadInArray(3*pads_per_row + 1)
|
||||
array.AddPadsToModule()
|
|
@ -0,0 +1,98 @@
|
|||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
from __future__ import division
|
||||
import pcbnew
|
||||
|
||||
import HelpfulFootprintWizardPlugin as HFPW
|
||||
import PadArray as PA
|
||||
|
||||
|
||||
class BGAPadGridArray(PA.PadGridArray):
|
||||
|
||||
def NamingFunction(self, x, y):
|
||||
return "%s%d" % (self.AlphaNameFromNumber(y + 1), x + 1)
|
||||
|
||||
|
||||
class BGAWizard(HFPW.HelpfulFootprintWizardPlugin):
|
||||
|
||||
def GetName(self):
|
||||
return "BGA"
|
||||
|
||||
def GetDescription(self):
|
||||
return "Ball Grid Array Footprint Wizard"
|
||||
|
||||
def GenerateParameterList(self):
|
||||
|
||||
self.AddParam("Pads", "pad pitch", self.uMM, 1)
|
||||
self.AddParam("Pads", "pad size", self.uMM, 0.5)
|
||||
self.AddParam("Pads", "row count", self.uNatural, 5)
|
||||
self.AddParam("Pads", "column count", self.uNatural, 5)
|
||||
self.AddParam("Pads", "outline x margin", self.uMM, 1)
|
||||
self.AddParam("Pads", "outline y margin", self.uMM, 1)
|
||||
|
||||
def CheckParameters(self):
|
||||
|
||||
self.CheckParamPositiveInt("Pads", "*row count")
|
||||
self.CheckParamPositiveInt("Pads", "*column count")
|
||||
|
||||
|
||||
def GetReference(self):
|
||||
|
||||
pins = self.parameters["Pads"]["*row count"] * self.parameters["Pads"]["*column count"]
|
||||
|
||||
return "BGA %d" % pins
|
||||
|
||||
|
||||
def GetValuePrefix(self):
|
||||
return "U"
|
||||
|
||||
|
||||
def BuildThisFootprint(self):
|
||||
|
||||
pads = self.parameters["Pads"]
|
||||
|
||||
rows = pads["*row count"]
|
||||
cols = pads["*column count"]
|
||||
pad_size = pads["pad size"]
|
||||
|
||||
pad_size = pcbnew.wxSize(pad_size, pad_size)
|
||||
|
||||
pad_pitch = pads["pad pitch"]
|
||||
|
||||
# add in the pads
|
||||
pad = PA.PadMaker(self.module).SMTRoundPad(pads["pad size"])
|
||||
|
||||
pin1Pos = pcbnew.wxPoint(-((rows - 1) * pad_pitch) / 2,
|
||||
-((cols - 1) * pad_pitch) / 2)
|
||||
|
||||
array = BGAPadGridArray(pad, rows, cols, pad_pitch, pad_pitch, pin1Pos)
|
||||
array.AddPadsToModule()
|
||||
|
||||
#box
|
||||
ssX = -pin1Pos.x + pads["outline x margin"]
|
||||
ssY = -pin1Pos.y + pads["outline y margin"]
|
||||
|
||||
self.draw.BoxWithDiagonalAtCorner(0, 0, ssX*2, ssY*2, pads["outline x margin"])
|
||||
|
||||
#reference and value
|
||||
textSize = pcbnew.FromMM(0.8)
|
||||
|
||||
self.draw.Value(0, - ssY - textSize, textSize)
|
||||
self.draw.Reference(0, ssY + textSize, textSize)
|
||||
|
||||
|
||||
BGAWizard().register()
|
|
@ -1,235 +1,89 @@
|
|||
from __future__ import division
|
||||
import pcbnew
|
||||
|
||||
def abs(x):
|
||||
if x < 0:
|
||||
return -x
|
||||
import HelpfulFootprintWizardPlugin
|
||||
import PadArray as PA
|
||||
|
||||
return x
|
||||
class QFPWizard(HelpfulFootprintWizardPlugin.HelpfulFootprintWizardPlugin):
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
def GetName(self):
|
||||
return "QFP"
|
||||
|
||||
self.ClearErrors()
|
||||
def GetDescription(self):
|
||||
return "QFP Footprint Wizard"
|
||||
|
||||
def smd_rect_pad(self, module, size, pos, name):
|
||||
pad = pcbnew.D_PAD(module)
|
||||
def GenerateParameterList(self):
|
||||
self.AddParam("Pads", "n", self.uNatural, 100)
|
||||
self.AddParam("Pads", "pad pitch", self.uMM, 0.5)
|
||||
self.AddParam("Pads", "pad width", self.uMM, 0.25)
|
||||
self.AddParam("Pads", "pad length", self.uMM, 1.5)
|
||||
self.AddParam("Pads", "vertical pitch", self.uMM, 15)
|
||||
self.AddParam("Pads", "horizontal pitch", self.uMM, 15)
|
||||
self.AddParam("Pads", "oval", self.uBool, True)
|
||||
|
||||
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
|
||||
self.AddParam("Pads", "package width", self.uMM, 14)
|
||||
self.AddParam("Pads", "package height", self.uMM, 14)
|
||||
|
||||
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
|
||||
self.CheckParamPositiveInt("Pads", "*n", is_multiple_of = 4)
|
||||
|
||||
return errors
|
||||
def GetReference(self):
|
||||
return "QFP %d" % self.parameters["Pads"]["*n"]
|
||||
|
||||
def BuildFootprint(self):
|
||||
if self.has_errors():
|
||||
print "Cannot build footprint: Parameters have errors:"
|
||||
print self.parameter_errors
|
||||
return
|
||||
def BuildThisFootprint(self):
|
||||
|
||||
print "Building new QFP footprint with the following parameters:"
|
||||
self.print_parameter_table()
|
||||
pads = self.parameters["Pads"]
|
||||
|
||||
self.module = pcbnew.MODULE(None) # create a new module
|
||||
pad_pitch = pads["pad pitch"]
|
||||
pad_length = self.parameters["Pads"]["pad length"]
|
||||
pad_width = self.parameters["Pads"]["pad width"]
|
||||
|
||||
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"]
|
||||
v_pitch = pads["vertical pitch"]
|
||||
h_pitch = pads["horizontal pitch"]
|
||||
|
||||
package_width = pads["Package"]["width"]
|
||||
package_height = pads["Package"]["height"]
|
||||
pads_per_row = pads["*n"] // 4
|
||||
|
||||
side_length = pad_pitch * ((num_pads / 4) - 1)
|
||||
row_len = (pads_per_row - 1) * pad_pitch
|
||||
|
||||
offsetX = pad_pitch * ((num_pads / 4) - 1) / 2
|
||||
text_size = pcbnew.wxSize(pcbnew.FromMM(0.8), pcbnew.FromMM(0.8))
|
||||
h_pad = PA.PadMaker(self.module).SMDPad(pad_width, pad_length, shape = pcbnew.PAD_OVAL)
|
||||
v_pad = PA.PadMaker(self.module).SMDPad(pad_length, pad_width, shape = pcbnew.PAD_OVAL)
|
||||
|
||||
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)
|
||||
#left row
|
||||
pin1Pos = pcbnew.wxPoint(-h_pitch / 2, -row_len / 2)
|
||||
array = PA.PadLineArray(h_pad, pads_per_row, pad_pitch, True, pin1Pos)
|
||||
array.SetFirstPadInArray(1)
|
||||
array.AddPadsToModule()
|
||||
|
||||
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)
|
||||
#bottom row
|
||||
pin1Pos = pcbnew.wxPoint(-row_len / 2, v_pitch / 2)
|
||||
array = PA.PadLineArray(v_pad, pads_per_row, pad_pitch, False, pin1Pos)
|
||||
array.SetFirstPadInArray(pads_per_row + 1)
|
||||
array.AddPadsToModule()
|
||||
|
||||
fpid = pcbnew.FPID(self.module.GetReference()) #the name in library
|
||||
self.module.SetFPID( fpid )
|
||||
#right row
|
||||
pin1Pos = pcbnew.wxPoint(h_pitch / 2, row_len / 2)
|
||||
array = PA.PadLineArray(h_pad, pads_per_row, -pad_pitch, True, pin1Pos)
|
||||
array.SetFirstPadInArray(2*pads_per_row + 1)
|
||||
array.AddPadsToModule()
|
||||
|
||||
pad_size_left_right = pcbnew.wxSize(pad_length, pad_width)
|
||||
pad_size_bottom_top = pcbnew.wxSize(pad_width, pad_length)
|
||||
#top row
|
||||
pin1Pos = pcbnew.wxPoint(row_len / 2, -v_pitch / 2)
|
||||
array = PA.PadLineArray(v_pad, pads_per_row, -pad_pitch, False, pin1Pos)
|
||||
array.SetFirstPadInArray(3*pads_per_row + 1)
|
||||
array.AddPadsToModule()
|
||||
|
||||
for cur_pad in range(0, num_pads):
|
||||
side = int(cur_pad / (num_pads / 4)) # 0 -> left, 1 -> bottom, 2 -> right, 3 -> top
|
||||
limX = pads["package width"] / 2
|
||||
limY = pads["package height"] / 2
|
||||
inner = (row_len / 2) + pad_pitch
|
||||
|
||||
if side == 0 or side == 2:
|
||||
pad_size = pad_size_left_right
|
||||
|
||||
pad_pos_x = -(pad_horizontal_pitch / 2)
|
||||
pad_pos_y = (cur_pad % (num_pads / 4)) * pad_pitch - (side_length / 2)
|
||||
|
||||
if side == 2:
|
||||
pad_pos_x = -pad_pos_x
|
||||
pad_pos_y = -pad_pos_y
|
||||
|
||||
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
|
||||
else:
|
||||
pad_pos_x = -pad_pos_x
|
||||
|
||||
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
|
||||
#top left - diagonal
|
||||
self.draw.Line(-limX, -inner, -inner, -limY)
|
||||
# top right
|
||||
self.draw.Polyline([(inner, -limY), (limX, -limY), (limX, -inner)])
|
||||
# bottom left
|
||||
self.draw.Polyline([(-inner, limY), (-limX, limY), (-limX, inner)])
|
||||
# bottom right
|
||||
self.draw.Polyline([(inner, limY), (limX, limY), (limX, inner)])
|
||||
|
||||
QFPWizard().register()
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
from __future__ import division
|
||||
import pcbnew
|
||||
|
||||
import HelpfulFootprintWizardPlugin as HFPW
|
||||
import PadArray as PA
|
||||
|
||||
|
||||
class RowedGridArray(PA.PadGridArray):
|
||||
|
||||
def NamingFunction(self, x, y):
|
||||
if (x % 2) == 0: # even row, count up
|
||||
return (x * self.ny) + y + 1;
|
||||
else: # odd row, count down
|
||||
return (self.ny * (x + 1)) - y;
|
||||
|
||||
class RowedFootprint(HFPW.HelpfulFootprintWizardPlugin):
|
||||
|
||||
def GenerateParameterList(self):
|
||||
|
||||
# defaults for a DIP package
|
||||
self.AddParam("Pads", "n", self.uNatural, 24)
|
||||
self.AddParam("Pads", "silk screen inside", self.uBool, False)
|
||||
self.AddParam("Pads", "row count", self.uNatural, 2)
|
||||
|
||||
def CheckParameters(self):
|
||||
self.CheckParamPositiveInt("Pads", "*row count")
|
||||
self.CheckParamPositiveInt("Pads", "*n", is_multiple_of = self.parameters["Pads"]["*row count"])
|
||||
self.CheckParamBool("Pads", "*silk screen inside") #can do this internally to parameter manager?
|
||||
|
||||
def BuildThisFootprint(self):
|
||||
|
||||
pads = self.parameters["Pads"]
|
||||
|
||||
num_pads = pads["*n"]
|
||||
|
||||
pad_length = pads["pad length"]
|
||||
pad_width = pads["pad width"]
|
||||
row_pitch = pads["row spacing"]
|
||||
pad_pitch = pads["pad pitch"]
|
||||
num_rows = pads["*row count"]
|
||||
|
||||
pads_per_row = num_pads // num_rows
|
||||
|
||||
row_length = pad_pitch * (pads_per_row - 1) #fenceposts
|
||||
|
||||
# add in the pads
|
||||
pad = self.GetPad()
|
||||
|
||||
pin1Pos = pcbnew.wxPoint(-((num_rows - 1) * row_pitch) / 2, -row_length / 2)
|
||||
|
||||
array = RowedGridArray(pad, num_rows, pads_per_row, row_pitch, pad_pitch, pin1Pos)
|
||||
array.AddPadsToModule()
|
||||
|
||||
# draw the Silk Screen
|
||||
|
||||
pad_length = pads["pad length"]
|
||||
pad_width = pads["pad width"]
|
||||
|
||||
ssXOffset = -pad_length / 2 - pads["outline x margin"]
|
||||
ssYOffset = -pad_width / 2 - pads["outline y margin"]
|
||||
|
||||
|
||||
if pads["*silk screen inside"]:
|
||||
ssXOffset *= -1
|
||||
|
||||
ssX = -pin1Pos.x - ssXOffset
|
||||
ssY = -pin1Pos.y - ssYOffset
|
||||
|
||||
|
||||
self.DrawBox(ssX, ssY)
|
||||
|
||||
#reference and value
|
||||
textSize = pcbnew.FromMM(0.8)
|
||||
|
||||
self.draw.Value(0, - ssY - textSize, textSize)
|
||||
self.draw.Reference(0, ssY + textSize, textSize)
|
||||
|
||||
|
||||
class SDIPWizard(RowedFootprint):
|
||||
|
||||
def GetName(self):
|
||||
return "S/DIP"
|
||||
|
||||
def GetDescription(self):
|
||||
return "Single/Dual Inline Package Footprint Wizard"
|
||||
|
||||
def GenerateParameterList(self):
|
||||
RowedFootprint.GenerateParameterList(self)
|
||||
|
||||
self.AddParam("Pads", "pad pitch", self.uMils, 100)
|
||||
self.AddParam("Pads", "pad width", self.uMils, 60)
|
||||
self.AddParam("Pads", "pad length", self.uMils, 150)
|
||||
self.AddParam("Pads", "row spacing", self.uMils, 300)
|
||||
self.AddParam("Pads", "drill size", self.uMM, 1)
|
||||
self.AddParam("Pads", "outline x margin", self.uMM, 0.5)
|
||||
self.AddParam("Pads", "outline y margin", self.uMM, 1)
|
||||
|
||||
def GetReference(self):
|
||||
|
||||
rows = self.parameters["Pads"]["*row count"]
|
||||
|
||||
if rows == 1:
|
||||
name = "SIP"
|
||||
elif rows == 2:
|
||||
name = "DIP"
|
||||
else: # triple and up aren't really a thing, but call it something!
|
||||
name = "xIP"
|
||||
|
||||
return "%s %d" % (name, self.parameters["Pads"]["*n"])
|
||||
|
||||
def GetPad(self):
|
||||
pad_length = self.parameters["Pads"]["pad length"]
|
||||
pad_width = self.parameters["Pads"]["pad width"]
|
||||
drill = self.parameters["Pads"]["drill size"]
|
||||
return PA.PadMaker(self.module).THPad(pad_width, pad_length, drill, shape = pcbnew.PAD_OVAL)
|
||||
|
||||
def DrawBox(self, ssX, ssY):
|
||||
|
||||
if self.parameters["Pads"]["*row count"] == 2:
|
||||
|
||||
# ----------
|
||||
# |8 7 6 5 |
|
||||
# > |
|
||||
# |1 2 3 4 |
|
||||
# ----------
|
||||
|
||||
# draw the notch
|
||||
notchWidth = pcbnew.FromMM(3)
|
||||
notchHeight = pcbnew.FromMM(1)
|
||||
|
||||
self.draw.NotchedBox(0, 0, ssX*2, ssY*2, notchWidth, notchHeight)
|
||||
else:
|
||||
# -----------------
|
||||
# |1|2 3 4 5 6 7 8|
|
||||
# -----------------
|
||||
self.draw.Box(ssX*2, ssY*2)
|
||||
|
||||
#line between pin1 and pin2
|
||||
pad_pitch = self.parameters["Pads"]["pad pitch"];
|
||||
self.draw.HLine(-ssX, pin1Pos.y + pad_pitch/2, ssX * 2)
|
||||
|
||||
return ssX, ssY
|
||||
|
||||
SDIPWizard().register()
|
||||
|
||||
|
||||
class SOICWizard(RowedFootprint):
|
||||
|
||||
def GetName(self):
|
||||
return "SOIC"
|
||||
|
||||
def GetDescription(self):
|
||||
return "SOIC, MSOP, SSOP, TSSOP, etc, footprint wizard"
|
||||
|
||||
def GetReference(self):
|
||||
return "%s %d" % ("SOIC", self.parameters["Pads"]["*n"])
|
||||
|
||||
def GenerateParameterList(self):
|
||||
RowedFootprint.GenerateParameterList(self)
|
||||
|
||||
#and override some of them
|
||||
self.AddParam("Pads", "pad pitch", self.uMM, 1.27)
|
||||
self.AddParam("Pads", "pad width", self.uMM, 0.6)
|
||||
self.AddParam("Pads", "pad length", self.uMM, 2.2)
|
||||
self.AddParam("Pads", "row spacing", self.uMM, 5.2)
|
||||
|
||||
self.AddParam("Pads", "outline x margin", self.uMM, 0.5)
|
||||
self.AddParam("Pads", "outline y margin", self.uMM, 0.5)
|
||||
|
||||
def GetPad(self):
|
||||
pad_length = self.parameters["Pads"]["pad length"]
|
||||
pad_width = self.parameters["Pads"]["pad width"]
|
||||
return PA.PadMaker(self.module).SMDPad(pad_width, pad_length, shape = pcbnew.PAD_RECT)
|
||||
|
||||
def DrawBox(self, ssX, ssY):
|
||||
|
||||
# ----------
|
||||
# |8 7 6 5 |
|
||||
# |1 2 3 4 |
|
||||
# \---------
|
||||
|
||||
self.draw.BoxWithDiagonalAtCorner(0, 0, ssX*2, ssY*2, pcbnew.FromMM(1))
|
||||
|
||||
SOICWizard().register()
|
Loading…
Reference in New Issue