Footprint Wizards Update
This commit is contained in:
committed by
jean-pierre charras
parent
d1278a48b6
commit
66ee44cb1f
+7
-9
@@ -17,10 +17,9 @@
|
||||
from __future__ import division
|
||||
import pcbnew
|
||||
|
||||
import HelpfulFootprintWizardPlugin as HFPW
|
||||
import FootprintWizardBase
|
||||
|
||||
|
||||
class FPC_FootprintWizard(HFPW.HelpfulFootprintWizardPlugin):
|
||||
class FPC_FootprintWizard(FootprintWizardBase.FootprintWizard):
|
||||
|
||||
def GetName(self):
|
||||
return "FPC (SMT connector)"
|
||||
@@ -29,11 +28,11 @@ class FPC_FootprintWizard(HFPW.HelpfulFootprintWizardPlugin):
|
||||
return "FPC (SMT connector) Footprint Wizard"
|
||||
|
||||
def GetValue(self):
|
||||
pins = self.parameters["Pads"]["*n"]
|
||||
pins = self.parameters["Pads"]["n"]
|
||||
return "FPC_%d" % pins
|
||||
|
||||
def GenerateParameterList(self):
|
||||
self.AddParam( "Pads", "n", self.uNatural, 40 )
|
||||
self.AddParam( "Pads", "n", self.uInteger, 40 )
|
||||
self.AddParam( "Pads", "pitch", self.uMM, 0.5 )
|
||||
self.AddParam( "Pads", "width", self.uMM, 0.25 )
|
||||
self.AddParam( "Pads", "height", self.uMM, 1.6)
|
||||
@@ -56,13 +55,12 @@ class FPC_FootprintWizard(HFPW.HelpfulFootprintWizardPlugin):
|
||||
return pad
|
||||
|
||||
def CheckParameters(self):
|
||||
p = self.parameters
|
||||
self.CheckParamInt( "Pads", "*n" ) # not internal units preceded by "*"
|
||||
|
||||
#TODO implement custom parameter checking
|
||||
pass
|
||||
|
||||
def BuildThisFootprint(self):
|
||||
p = self.parameters
|
||||
pad_count = int(p["Pads"]["*n"])
|
||||
pad_count = int(p["Pads"]["n"])
|
||||
pad_width = p["Pads"]["width"]
|
||||
pad_height = p["Pads"]["height"]
|
||||
pad_pitch = p["Pads"]["pitch"]
|
||||
+154
-12
@@ -15,10 +15,150 @@
|
||||
#
|
||||
|
||||
from __future__ import division
|
||||
|
||||
import pcbnew
|
||||
import math
|
||||
|
||||
# Base class for creating footprint wizards
|
||||
# Inherit this class to make a new wizard
|
||||
class FootprintWizard(pcbnew.FootprintWizardPlugin):
|
||||
|
||||
# Copy units from pcbnew
|
||||
uMM = pcbnew.uMM
|
||||
uMils = pcbnew.uMils
|
||||
uFloat = pcbnew.uFloat
|
||||
uInteger = pcbnew.uInteger
|
||||
uBool = pcbnew.uBool
|
||||
uRadians = pcbnew.uRadians
|
||||
uDegrees = pcbnew.uDegrees
|
||||
uPercent = pcbnew.uPercent
|
||||
uString = pcbnew.uString
|
||||
|
||||
"""
|
||||
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:
|
||||
GetValue()
|
||||
GenerateParameterList()
|
||||
CheckParameters()
|
||||
BuildThisFootprint()
|
||||
GetName()
|
||||
GetDescription()
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
pcbnew.FootprintWizardPlugin.__init__(self)
|
||||
self.GenerateParameterList()
|
||||
|
||||
def GetName(self):
|
||||
"""
|
||||
Retun the name of the footprint wizard
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def GetDescription(self):
|
||||
"""
|
||||
Return the footprint wizard description
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def GetValue(self):
|
||||
"""
|
||||
Return the value (name) of the generated footprint
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def GenerateParameterList(self):
|
||||
"""
|
||||
Footprint parameter specification is done here
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def CheckParameters(self):
|
||||
"""
|
||||
Any custom parameter checking should be performed here
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def BuildThisFootprint(self):
|
||||
"""
|
||||
Draw the footprint.
|
||||
|
||||
This is specific to each footprint class, you need to implment
|
||||
this to draw what you want
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
# Do not override this method!
|
||||
def BuildFootprint( self ):
|
||||
"""
|
||||
Actually make the footprint. We defer all but the setup to
|
||||
the implementing class
|
||||
"""
|
||||
|
||||
self.buildmessages = ""
|
||||
self.module = pcbnew.MODULE(None) # create a new module
|
||||
|
||||
# Perform default checks on all params
|
||||
for p in self.params:
|
||||
p.ClearErrors()
|
||||
p.Check() # use defaults
|
||||
|
||||
self.CheckParameters() # User error checks
|
||||
|
||||
|
||||
if self.AnyErrors(): # Errors were detected!
|
||||
|
||||
self.buildmessages = "Cannot build footprint: Parameters have errors:\n"
|
||||
|
||||
for p in self.params:
|
||||
if len(p.error_list) > 0:
|
||||
self.buildmessages +="['{page}']['{name}']:\n".format(page=p.page,name=p.name)
|
||||
|
||||
for error in p.error_list:
|
||||
self.buildmessages += "\t" + error + "\n"
|
||||
|
||||
return
|
||||
|
||||
self.buildmessages = ("Building new {name} footprint with the following parameters:\n".format(name=self.name))
|
||||
|
||||
self.buildmessages += self.Show()
|
||||
|
||||
self.draw = FootprintWizardDrawingAids(
|
||||
self.module)
|
||||
|
||||
self.module.SetValue(self.GetValue())
|
||||
self.module.SetReference("%s**" % self.GetReferencePrefix())
|
||||
|
||||
fpid = pcbnew.LIB_ID(self.module.GetValue()) # the name in library
|
||||
self.module.SetFPID(fpid)
|
||||
|
||||
self.SetModule3DModel() # add a 3d module if specified
|
||||
|
||||
thick = self.GetTextThickness()
|
||||
|
||||
self.module.Reference().SetThickness(thick)
|
||||
self.module.Value().SetThickness(thick)
|
||||
|
||||
self.BuildThisFootprint() # implementer's build function
|
||||
|
||||
return
|
||||
|
||||
def SetModule3DModel(self):
|
||||
pass
|
||||
|
||||
def GetTextSize(self):
|
||||
"""
|
||||
IPC nominal
|
||||
"""
|
||||
return pcbnew.FromMM(1.0)
|
||||
|
||||
def GetTextThickness(self):
|
||||
"""
|
||||
Thicker than IPC guidelines (10% of text height = 0.12mm)
|
||||
as 5 wires/mm is a common silk screen limitation
|
||||
"""
|
||||
return pcbnew.FromMM(0.15)
|
||||
|
||||
class FootprintWizardDrawingAids:
|
||||
"""
|
||||
@@ -294,6 +434,7 @@ class FootprintWizardDrawingAids:
|
||||
If filled is true, the thickness and radius of the line will be set
|
||||
such that the circle appears filled
|
||||
"""
|
||||
|
||||
circle = pcbnew.EDGE_MODULE(self.module)
|
||||
start = self.TransformPoint(x, y)
|
||||
|
||||
@@ -362,21 +503,22 @@ class FootprintWizardDrawingAids:
|
||||
|
||||
_PolyLineInternal(pts) # original
|
||||
|
||||
if mirrorX is not None:
|
||||
self.TransformFlip(mirrorX, 0, self.flipX)
|
||||
_PolyLineInternal(pts)
|
||||
self.PopTransform()
|
||||
|
||||
if mirrorY is not None:
|
||||
self.TransformFlipOrigin(0, mirrorY, self.flipY)
|
||||
_PolyLineInternal(pts)
|
||||
self.PopTransform()
|
||||
|
||||
if mirrorX is not None and mirrorY is not None:
|
||||
self.TransformFlip(mirrorX, mirrorY, self.flipBoth) # both
|
||||
_PolyLineInternal(pts)
|
||||
self.PopTransform()
|
||||
|
||||
elif mirrorX is not None:
|
||||
self.TransformFlip(mirrorX, 0, self.flipX)
|
||||
_PolyLineInternal(pts)
|
||||
self.PopTransform()
|
||||
|
||||
elif mirrorY is not None:
|
||||
self.TransformFlip(0, mirrorY, self.flipY)
|
||||
_PolyLineInternal(pts)
|
||||
self.PopTransform()
|
||||
|
||||
|
||||
def Reference(self, x, y, size, orientation_degree = 0):
|
||||
"""
|
||||
Draw the module's reference as the given point.
|
||||
@@ -529,4 +671,4 @@ class FootprintWizardDrawingAids:
|
||||
[0, 0]]
|
||||
|
||||
self.Polyline(pts)
|
||||
self.PopTransform(2)
|
||||
self.PopTransform(2)
|
||||
@@ -1,348 +0,0 @@
|
||||
# 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 math
|
||||
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
|
||||
uString = 5
|
||||
|
||||
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
|
||||
"""
|
||||
error = ""
|
||||
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.uString:
|
||||
val = str(default)
|
||||
elif unit == self.uBool:
|
||||
val = "True" if default else "False" # ugly stringing
|
||||
else:
|
||||
error = "Warning: Unknown unit type: %s" % unit
|
||||
return error
|
||||
|
||||
if unit in [self.uNatural, self.uBool, self.uString]:
|
||||
param = "*%s" % param # star prefix for natural
|
||||
|
||||
if section not in self.parameters:
|
||||
if not hasattr(self, 'page_order'):
|
||||
self.page_order = []
|
||||
self.page_order.append(section)
|
||||
self.parameters[section] = {}
|
||||
if not hasattr(self, 'parameter_order'):
|
||||
self.parameter_order = {}
|
||||
self.parameter_order[section] = []
|
||||
|
||||
self.parameters[section][param] = val
|
||||
self.parameter_order[section].append(param)
|
||||
|
||||
return error
|
||||
|
||||
|
||||
def _PrintParameterTable(self):
|
||||
"""
|
||||
Pretty-print the parameters we have
|
||||
"""
|
||||
message = ""
|
||||
|
||||
for name, section in self.parameters.iteritems():
|
||||
message += " %s:\n" % 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)
|
||||
|
||||
message += " %s: %s%s\n" % (key, value, unit)
|
||||
|
||||
return message
|
||||
|
||||
|
||||
def _ParametersHaveErrors(self):
|
||||
"""
|
||||
Return true if we discovered errors during 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
|
||||
"""
|
||||
errors = ""
|
||||
|
||||
for name, section in self.parameter_errors.iteritems():
|
||||
printed_section = False
|
||||
|
||||
for key, value in section.iteritems():
|
||||
if value:
|
||||
if not printed_section:
|
||||
errors += " %s:" % name
|
||||
|
||||
errors += " %s: %s (have %s)\n" % (
|
||||
key, value, self.parameters[name][key])
|
||||
|
||||
return errors
|
||||
|
||||
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():
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
#################################################################
|
||||
# PARAMETER CHECKERS
|
||||
#################################################################
|
||||
|
||||
def CheckParamInt(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] > max_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 GetValue(self):
|
||||
raise NotImplementedError
|
||||
|
||||
# this value come from our KiCad Library Convention 1.0
|
||||
def GetReferencePrefix(self):
|
||||
return "REF"
|
||||
|
||||
def GetImage(self):
|
||||
return ""
|
||||
|
||||
def GetTextSize(self):
|
||||
"""
|
||||
IPC nominal
|
||||
"""
|
||||
return pcbnew.FromMM(1.0)
|
||||
|
||||
def GetTextThickness(self):
|
||||
"""
|
||||
Thicker than IPC guidelines (10% of text height = 0.12mm)
|
||||
as 5 wires/mm is a common silk screen limitation
|
||||
"""
|
||||
return pcbnew.FromMM(0.15)
|
||||
|
||||
def SetModule3DModel(self):
|
||||
"""
|
||||
Set a 3D model for the module
|
||||
|
||||
Default is to do nothing, you need to implement this if you have
|
||||
a model to set
|
||||
|
||||
FIXME: This doesn't seem to be enabled yet?
|
||||
"""
|
||||
pass
|
||||
|
||||
def PutOnGridMM(self, value, gridSizeMM=0.05):
|
||||
"""
|
||||
Round the value (in KiCAD internal units 1nm) according to the
|
||||
provided gridSize in mm.
|
||||
"""
|
||||
thresh = pcbnew.FromMM(gridSizeMM)
|
||||
res = round(value/thresh)*thresh
|
||||
return res
|
||||
|
||||
def PutOnGridMils(self, value, gridSizeMil=2):
|
||||
"""
|
||||
Round the value (in KiCAD internal units 1nm) according to the
|
||||
provided gridSize in mil.
|
||||
"""
|
||||
thresh = pcbnew.FromMils(gridSizeMil)
|
||||
res = round(value/thresh)*thresh
|
||||
return res
|
||||
|
||||
def BuildThisFootprint(self):
|
||||
"""
|
||||
Draw the footprint.
|
||||
|
||||
This is specific to each footprint class, you need to implment
|
||||
this to draw what you want
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def BuildFootprint( self ):
|
||||
"""
|
||||
Actually make the footprint. We defer all but the setup to
|
||||
the implementing class
|
||||
"""
|
||||
|
||||
self.buildmessages = ""
|
||||
|
||||
self.module = pcbnew.MODULE(None) # create a new module
|
||||
# do it first, so if we return early, we don't segfault KiCad
|
||||
|
||||
if not self.ProcessParameters():
|
||||
self.buildmessages = "Cannot build footprint: Parameters have errors:\n"
|
||||
self.buildmessages += self._PrintParameterErrors()
|
||||
return
|
||||
|
||||
self.buildmessages = ("Building new %s footprint with the following parameters:\n"
|
||||
% self.name)
|
||||
|
||||
self.buildmessages += self._PrintParameterTable()
|
||||
|
||||
self.draw = FootprintWizardDrawingAids.FootprintWizardDrawingAids(
|
||||
self.module)
|
||||
|
||||
self.module.SetValue(self.GetValue())
|
||||
self.module.SetReference("%s**" % self.GetReferencePrefix())
|
||||
|
||||
fpid = pcbnew.LIB_ID(self.module.GetValue()) # the name in library
|
||||
self.module.SetFPID(fpid)
|
||||
|
||||
self.SetModule3DModel() # add a 3d module if specified
|
||||
|
||||
thick = self.GetTextThickness()
|
||||
|
||||
self.module.Reference().SetThickness(thick)
|
||||
self.module.Value().SetThickness(thick)
|
||||
|
||||
self.BuildThisFootprint() # implementer's build function
|
||||
|
||||
return
|
||||
@@ -17,7 +17,7 @@
|
||||
from __future__ import division
|
||||
import pcbnew
|
||||
|
||||
import HelpfulFootprintWizardPlugin as HFPW
|
||||
import FootprintWizardBase
|
||||
import PadArray as PA
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ class BGAPadGridArray(PA.PadGridArray):
|
||||
n_x + 1)
|
||||
|
||||
|
||||
class BGAWizard(HFPW.HelpfulFootprintWizardPlugin):
|
||||
class BGAWizard(FootprintWizardBase.FootprintWizard):
|
||||
|
||||
def GetName(self):
|
||||
return "BGA"
|
||||
@@ -38,35 +38,48 @@ class BGAWizard(HFPW.HelpfulFootprintWizardPlugin):
|
||||
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)
|
||||
self.AddParam("Pads", "pitch", self.uMM, 1, designator='p')
|
||||
self.AddParam("Pads", "size", self.uMM, 0.5)
|
||||
self.AddParam("Pads", "columns", self.uInteger, 5, designator="nx")
|
||||
self.AddParam("Pads", "rows", self.uInteger, 5, designator="ny")
|
||||
|
||||
self.AddParam("Package", "width", self.uMM, 6, designator='X')
|
||||
self.AddParam("Package", "length", self.uMM, 6, designator='Y')
|
||||
self.AddParam("Package", "margin", self.uMM, 0.25, min_value=0.2, hint="Courtyard margin")
|
||||
|
||||
def CheckParameters(self):
|
||||
self.CheckParamInt("Pads", "*row count")
|
||||
self.CheckParamInt("Pads", "*column count")
|
||||
|
||||
# check that the package is large enough
|
||||
width = pcbnew.ToMM(self.parameters['Pads']['pitch'] * self.parameters['Pads']['columns'])
|
||||
|
||||
length = pcbnew.ToMM(self.parameters['Pads']['pitch'] * self.parameters['Pads']['rows'])
|
||||
|
||||
self.CheckParam('Package','width',min_value=width,info="Package width is too small (< {w}mm)".format(w=width))
|
||||
self.CheckParam('Package','length',min_value=length,info="Package length is too small (< {l}mm".format(l=length))
|
||||
|
||||
def GetValue(self):
|
||||
pins = (self.parameters["Pads"]["*row count"]
|
||||
* self.parameters["Pads"]["*column count"])
|
||||
pins = (self.parameters["Pads"]["rows"] * self.parameters["Pads"]["columns"])
|
||||
|
||||
return "BGA_%d" % pins
|
||||
return "BGA-{n}_{a}x{b}_{x}x{y}mm".format(
|
||||
n = pins,
|
||||
a = self.parameters['Pads']['columns'],
|
||||
b = self.parameters['Pads']['rows'],
|
||||
x = pcbnew.ToMM(self.parameters['Package']['width']),
|
||||
y = pcbnew.ToMM(self.parameters['Package']['length'])
|
||||
)
|
||||
|
||||
def BuildThisFootprint(self):
|
||||
|
||||
pads = self.parameters["Pads"]
|
||||
|
||||
rows = pads["*row count"]
|
||||
cols = pads["*column count"]
|
||||
pad_size = pads["pad size"]
|
||||
rows = pads["rows"]
|
||||
cols = pads["columns"]
|
||||
pad_size = pads["size"]
|
||||
pad_size = pcbnew.wxSize(pad_size, pad_size)
|
||||
pad_pitch = pads["pad pitch"]
|
||||
pad_pitch = pads["pitch"]
|
||||
|
||||
# add in the pads
|
||||
pad = PA.PadMaker(self.module).SMTRoundPad(pads["pad size"])
|
||||
pad = PA.PadMaker(self.module).SMTRoundPad(pads["size"])
|
||||
|
||||
pin1_pos = pcbnew.wxPoint(-((cols - 1) * pad_pitch) / 2,
|
||||
-((rows - 1) * pad_pitch) / 2)
|
||||
@@ -74,21 +87,68 @@ class BGAWizard(HFPW.HelpfulFootprintWizardPlugin):
|
||||
array = BGAPadGridArray(pad, cols, rows, pad_pitch, pad_pitch)
|
||||
array.AddPadsToModule(self.draw)
|
||||
|
||||
#box
|
||||
ssx = -pin1_pos.x + pads["outline x margin"]
|
||||
ssy = -pin1_pos.y + pads["outline y margin"]
|
||||
# Draw box outline on F.Fab layer
|
||||
self.draw.SetLayer(pcbnew.F_Fab)
|
||||
ssx = self.parameters['Package']['width'] / 2
|
||||
ssy = self.parameters['Package']['length'] / 2
|
||||
|
||||
self.draw.BoxWithDiagonalAtCorner(0, 0, ssx*2, ssy*2,
|
||||
pads["outline x margin"])
|
||||
# Bevel should be 1mm nominal but we'll allow smaller values
|
||||
if pcbnew.ToMM(ssx) < 1:
|
||||
bevel = ssx
|
||||
else:
|
||||
bevel = pcbnew.FromMM(1)
|
||||
|
||||
# Box with 1mm bevel as per IPC7351C
|
||||
self.draw.BoxWithDiagonalAtCorner(0, 0, ssx*2, ssy*2, bevel)
|
||||
|
||||
# Add IPC markings to F_Silk layer
|
||||
self.draw.SetLayer(pcbnew.F_SilkS)
|
||||
offset = pcbnew.FromMM(0.15)
|
||||
len_x = 0.5 * ssx
|
||||
len_y = 0.5 * ssy
|
||||
|
||||
edge = [
|
||||
[ ssx + offset - len_x, -ssy - offset],
|
||||
[ ssx + offset, -ssy - offset],
|
||||
[ ssx + offset, -ssy - offset + len_y],
|
||||
]
|
||||
|
||||
# Draw three square edges
|
||||
self.draw.Polyline(edge)
|
||||
self.draw.Polyline(edge, mirrorY=0)
|
||||
self.draw.Polyline(edge, mirrorX=0, mirrorY=0)
|
||||
|
||||
# Draw pin-1 marker
|
||||
bevel += offset
|
||||
pin1 = [
|
||||
[ -ssx - offset + len_x, -ssy - offset],
|
||||
[ -ssx - offset + bevel, -ssy - offset],
|
||||
[ -ssx - offset, -ssy - offset + bevel],
|
||||
[ -ssx - offset, -ssy - offset + len_y],
|
||||
]
|
||||
|
||||
# Remove lines if the package is too small
|
||||
if bevel > len_x:
|
||||
pin1 = pin1[1:]
|
||||
|
||||
if bevel > len_y:
|
||||
pin1 = pin1[:-1]
|
||||
|
||||
self.draw.Polyline(pin1)
|
||||
|
||||
# Draw a circle in the bevel void
|
||||
self.draw.Circle( -ssx, -ssy, pcbnew.FromMM(0.2), filled=True)
|
||||
|
||||
# Courtyard
|
||||
cmargin = self.draw.GetLineThickness()
|
||||
cmargin = self.parameters['Package']['margin']
|
||||
self.draw.SetLayer(pcbnew.F_CrtYd)
|
||||
sizex = (ssx + cmargin) * 2
|
||||
sizey = (ssy + cmargin) * 2
|
||||
|
||||
# round size to nearest 0.1mm, rectangle will thus land on a 0.05mm grid
|
||||
sizex = self.PutOnGridMM(sizex, 0.1)
|
||||
sizey = self.PutOnGridMM(sizey, 0.1)
|
||||
sizex = pcbnew.PutOnGridMM(sizex, 0.1)
|
||||
sizey = pcbnew.PutOnGridMM(sizey, 0.1)
|
||||
|
||||
# set courtyard line thickness to the one defined in KLC
|
||||
self.draw.SetLineThickness(pcbnew.FromMM(0.05))
|
||||
self.draw.Box(0, 0, sizex, sizey)
|
||||
|
||||
@@ -18,11 +18,11 @@ from __future__ import division
|
||||
import math
|
||||
|
||||
import pcbnew
|
||||
import HelpfulFootprintWizardPlugin as HFPW
|
||||
import FootprintWizardBase
|
||||
import PadArray as PA
|
||||
|
||||
|
||||
class circular_pad_array_wizard(HFPW.HelpfulFootprintWizardPlugin):
|
||||
class circular_pad_array_wizard(FootprintWizardBase.FootprintWizard):
|
||||
|
||||
def GetName(self):
|
||||
return "Circular Pad Array"
|
||||
@@ -32,52 +32,84 @@ class circular_pad_array_wizard(HFPW.HelpfulFootprintWizardPlugin):
|
||||
|
||||
def GenerateParameterList(self):
|
||||
|
||||
self.AddParam("Pads", "n", self.uNatural, 6)
|
||||
self.AddParam("Pads", "pad width", self.uMM, 1.5)
|
||||
self.AddParam("Pads", "drill", self.uMM, 1)
|
||||
self.AddParam("Pads", "circle diameter", self.uMM, 5)
|
||||
self.AddParam("Pads", "first pad angle", self.uNatural, 0)
|
||||
self.AddParam("Pads", "number clockwise", self.uBool, True)
|
||||
self.AddParam("Pads", "first pad number", self.uNatural, 1)
|
||||
self.AddParam("Pads", "count", self.uInteger, 6, min_value=1, designator='n')
|
||||
self.AddParam("Pads", "center diameter", self.uMM, 5, min_value=0, designator='r', hint="Centre distance between pads")
|
||||
self.AddParam("Pads", "diameter", self.uMM, 1.5)
|
||||
self.AddParam("Pads", "drill", self.uMM, 0.8)
|
||||
self.AddParam("Pads", "angle", self.uDegrees, 0, designator='a')
|
||||
|
||||
self.AddParam("Numbering", "initial", self.uInteger, 1, min_value=1)
|
||||
#self.AddParam("Numbering", "increment", self.uInteger, 1, min_value=1)
|
||||
self.AddParam("Numbering", "clockwise", self.uBool, True)
|
||||
|
||||
self.AddParam("Outline", "diameter", self.uMM, 7, designator='D')
|
||||
self.AddParam("Outline", "margin", self.uMM, 0.25, min_value=0.2)
|
||||
|
||||
def CheckParameters(self):
|
||||
|
||||
self.CheckParamInt("Pads", "*n")
|
||||
self.CheckParamInt("Pads", "*first pad number")
|
||||
self.CheckParamBool("Pads", "*number clockwise")
|
||||
pads = self.parameters['Pads']
|
||||
numbering = self.parameters['Numbering']
|
||||
outline = self.parameters['Outline']
|
||||
|
||||
# Check that pads do not overlap
|
||||
pad_dia = pcbnew.ToMM(pads['diameter'])
|
||||
centres = pcbnew.ToMM(pads['center diameter'])
|
||||
n_pads = pads['count']
|
||||
|
||||
self.CheckParam('Pads','diameter',max_value=centres*math.pi/n_pads,info="Pads overlap")
|
||||
|
||||
# Check that the pads fit inside the outline
|
||||
d_min = pad_dia + centres
|
||||
|
||||
self.CheckParam("Outline","diameter",min_value=d_min, info="Outline diameter is too small")
|
||||
|
||||
|
||||
def GetValue(self):
|
||||
pins = self.parameters["Pads"]["*n"]
|
||||
pins = self.parameters["Pads"]["count"]
|
||||
return "CPA_%d" % pins
|
||||
|
||||
def BuildThisFootprint(self):
|
||||
|
||||
prm = self.parameters['Pads']
|
||||
pads = self.parameters['Pads']
|
||||
numbering = self.parameters['Numbering']
|
||||
outline = self.parameters['Outline']
|
||||
|
||||
pad_size = prm['pad width']
|
||||
pad_size = pads['diameter']
|
||||
|
||||
pad = PA.PadMaker(self.module).THPad(
|
||||
prm['pad width'], prm['pad width'], prm['drill'])
|
||||
pad = PA.PadMaker(self.module).THPad(pads['diameter'], pads['diameter'], pads['drill'])
|
||||
|
||||
array = PA.PadCircleArray(
|
||||
pad, prm['*n'], prm['circle diameter'] / 2,
|
||||
angle_offset=prm["*first pad angle"],
|
||||
pad, pads['count'], pads['center diameter'] / 2,
|
||||
angle_offset=pads["angle"],
|
||||
centre=pcbnew.wxPoint(0, 0),
|
||||
clockwise=prm["*number clockwise"])
|
||||
clockwise=numbering["clockwise"])
|
||||
|
||||
array.SetFirstPadInArray(prm["*first pad number"])
|
||||
array.SetFirstPadInArray(numbering["initial"])
|
||||
|
||||
array.AddPadsToModule(self.draw)
|
||||
|
||||
body_radius = (prm['circle diameter'] + prm['pad width'])/2 + self.draw.GetLineThickness()
|
||||
# Draw the outline
|
||||
body_radius = outline['diameter'] / 2
|
||||
self.draw.SetLayer(pcbnew.F_Fab)
|
||||
self.draw.GetLineThickness()
|
||||
self.draw.Circle(0, 0, body_radius)
|
||||
|
||||
#silkscreen
|
||||
body_radius += pcbnew.FromMM(0.15)
|
||||
self.draw.SetLayer(pcbnew.F_SilkS)
|
||||
self.draw.Circle(0, 0, body_radius)
|
||||
|
||||
# courtyard
|
||||
self.draw.SetLayer(pcbnew.F_CrtYd)
|
||||
self.draw.SetLineThickness(pcbnew.FromMM(0.05))
|
||||
self.draw.Circle(0, 0, body_radius + outline['margin'])
|
||||
|
||||
# Text size
|
||||
|
||||
text_size = self.GetTextSize() # IPC nominal
|
||||
thickness = self.GetTextThickness()
|
||||
textposy = body_radius + self.draw.GetLineThickness()/2 + self.GetTextSize()/2 + thickness
|
||||
textposy = body_radius + self.draw.GetLineThickness()/2 + self.GetTextSize()/2 + thickness + + outline['margin']
|
||||
self.draw.Value( 0, textposy, text_size )
|
||||
self.draw.Reference( 0, -textposy, text_size )
|
||||
|
||||
|
||||
|
||||
circular_pad_array_wizard().register()
|
||||
|
||||
@@ -17,55 +17,80 @@
|
||||
from __future__ import division
|
||||
import pcbnew
|
||||
|
||||
import HelpfulFootprintWizardPlugin as HFPW
|
||||
import pcbnew
|
||||
import FootprintWizardBase
|
||||
import PadArray as PA
|
||||
|
||||
class QFNWizard(HFPW.HelpfulFootprintWizardPlugin):
|
||||
class QFNWizard(FootprintWizardBase.FootprintWizard):
|
||||
|
||||
def GetName(self):
|
||||
return "QFN"
|
||||
|
||||
def GetDescription(self):
|
||||
return "Quad Flat No-lead with Exposed Pad footprint wizard"
|
||||
return "Quad Flat No-lead (QFN) footprint wizard"
|
||||
|
||||
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", "oval", self.uBool, True)
|
||||
self.AddParam("Pads", "thermal vias", self.uBool, True)
|
||||
self.AddParam("Pads", "thermal vias drill", self.uMM, 0.3)
|
||||
self.AddParam("Pads", "epad subdiv x", self.uNatural, 2)
|
||||
self.AddParam("Pads", "epad subdiv y", self.uNatural, 2)
|
||||
|
||||
self.AddParam("Package", "package width", self.uMM, 14)
|
||||
self.AddParam("Package", "package height", self.uMM, 14)
|
||||
self.AddParam("Package", "courtyard margin", self.uMM, 1)
|
||||
#TODO - Allow different number of pads in x and y directions
|
||||
|
||||
self.AddParam("Pads", "n", self.uInteger, 100, multiple=4, min_value=4)
|
||||
self.AddParam("Pads", "pitch", self.uMM, 0.5, designator='e')
|
||||
self.AddParam("Pads", "width", self.uMM, 0.25, designator='X1')
|
||||
self.AddParam("Pads", "length", self.uMM, 1.5, designator='Y1')
|
||||
self.AddParam("Pads", "oval", self.uBool, True)
|
||||
|
||||
self.AddParam("EPad", "epad", self.uBool, True)
|
||||
self.AddParam("EPad", "width", self.uMM, 10, designator="E2")
|
||||
self.AddParam("EPad", "length", self.uMM, 10, designator="D2")
|
||||
self.AddParam("EPad", "thermal vias", self.uBool, False)
|
||||
self.AddParam("EPad", "thermal vias drill", self.uMM, 1, min_value=0.1)
|
||||
self.AddParam("EPad", "x divisions", self.uInteger, 2, min_value=1)
|
||||
self.AddParam("EPad", "y divisions", self.uInteger, 2, min_value=1)
|
||||
self.AddParam("EPad", "paste margin", self.uMM, 0.1)
|
||||
|
||||
self.AddParam("Package", "width", self.uMM, 14, designator='E')
|
||||
self.AddParam("Package", "height", self.uMM, 14, designator='D')
|
||||
self.AddParam("Package", "margin", self.uMM, 0.25, minValue=0.2)
|
||||
|
||||
@property
|
||||
def pads(self):
|
||||
return self.parameters['Pads']
|
||||
|
||||
@property
|
||||
def epad(self):
|
||||
return self.parameters['EPad']
|
||||
|
||||
@property
|
||||
def package(self):
|
||||
return self.parameters['Package']
|
||||
|
||||
def CheckParameters(self):
|
||||
self.CheckParamInt("Pads", "*n", is_multiple_of=4)
|
||||
self.CheckParamBool("Pads", "*oval")
|
||||
self.CheckParamBool("Pads", "*thermal vias")
|
||||
pass
|
||||
|
||||
def GetValue(self):
|
||||
return "QFN_%d" % self.parameters["Pads"]["*n"]
|
||||
|
||||
return "QFN-{n}_{ep}{x:g}x{y:g}_Pitch{p:g}mm".format(
|
||||
n = self.pads['n'],
|
||||
ep = "EP_" if self.epad['epad'] else '',
|
||||
x = pcbnew.ToMM(self.package['width']),
|
||||
y = pcbnew.ToMM(self.package['height']),
|
||||
p = pcbnew.ToMM(self.pads['pitch'])
|
||||
)
|
||||
|
||||
def BuildThisFootprint(self):
|
||||
pads = self.parameters["Pads"]
|
||||
|
||||
pad_pitch = pads["pad pitch"]
|
||||
pad_length = pads["pad length"]
|
||||
pad_width = pads["pad width"]
|
||||
pad_pitch = self.pads["pitch"]
|
||||
pad_length = self.pads["length"]
|
||||
pad_width = self.pads["width"]
|
||||
|
||||
v_pitch = self.parameters["Package"]["package height"]
|
||||
h_pitch = self.parameters["Package"]["package width"]
|
||||
v_pitch = self.package["height"]
|
||||
h_pitch = self.package["width"]
|
||||
|
||||
pads_per_row = pads["*n"] // 4
|
||||
pads_per_row = int(self.pads["n"] // 4)
|
||||
|
||||
row_len = (pads_per_row - 1) * pad_pitch
|
||||
|
||||
pad_shape = pcbnew.PAD_SHAPE_OVAL if pads["*oval"] else pcbnew.PAD_SHAPE_RECT
|
||||
pad_shape = pcbnew.PAD_SHAPE_OVAL if self.pads["oval"] else pcbnew.PAD_SHAPE_RECT
|
||||
|
||||
h_pad = PA.PadMaker(self.module).SMDPad( pad_length, pad_width,
|
||||
shape=pad_shape, rot_degree=90.0)
|
||||
@@ -97,79 +122,88 @@ class QFNWizard(HFPW.HelpfulFootprintWizardPlugin):
|
||||
array.SetFirstPadInArray(3*pads_per_row + 1)
|
||||
array.AddPadsToModule(self.draw)
|
||||
|
||||
lim_x = self.parameters["Package"]["package width"] / 2
|
||||
lim_y = self.parameters["Package"]["package height"] / 2
|
||||
lim_x = self.package["width"] / 2
|
||||
lim_y = self.package["height"] / 2
|
||||
inner = (row_len / 2) + pad_pitch
|
||||
|
||||
# epad
|
||||
epad_width = self.parameters["Package"]["package height"] - (2*pad_length)
|
||||
epad_length = self.parameters["Package"]["package width"] - (2*pad_length)
|
||||
epad_subdv_x = pads["*epad subdiv x"]
|
||||
epad_subdv_y = pads["*epad subdiv y"]
|
||||
epad_via_drill = pads["thermal vias drill"]
|
||||
epad_width = self.epad["width"]
|
||||
epad_length = self.epad["length"]
|
||||
|
||||
if (epad_subdv_y != 0 and epad_subdv_x != 0) and (epad_subdv_y != 1 or epad_subdv_x != 1):
|
||||
# Create the master pad (one area) on front solder mask, and perhaps of front copper layer
|
||||
# at location 0,0
|
||||
emasterpad = PA.PadMaker(self.module).SMDPad( epad_length, epad_width,
|
||||
shape=pcbnew.PAD_SHAPE_RECT, rot_degree=0.0)
|
||||
emasterpad.SetLayerSet(pcbnew.LSET(pcbnew.F_Mask)) # currently, only on solder mask
|
||||
emasterpad.SetPadName(pads["*n"]+1)
|
||||
self.module.Add(emasterpad)
|
||||
epad_ny = self.epad["x divisions"]
|
||||
epad_nx = self.epad["y divisions"]
|
||||
|
||||
px = pcbnew.FromMM(0.1); py = pcbnew.FromMM(0.1)
|
||||
esubpad_size_x = epad_length / epad_subdv_x - px
|
||||
esubpad_size_y = epad_width / epad_subdv_y - py
|
||||
epad1_pos = pcbnew.wxPoint(-(esubpad_size_x*(epad_subdv_x-1)/2), -esubpad_size_y*(epad_subdv_y-1)/2)
|
||||
epad = PA.PadMaker(self.module).SMDPad( esubpad_size_y, esubpad_size_x,
|
||||
shape=pcbnew.PAD_SHAPE_RECT, rot_degree=0.0)
|
||||
array = PA.EPADGridArray(epad, epad_subdv_x, epad_subdv_y, esubpad_size_x + px, esubpad_size_y + py, pcbnew.wxPoint(0,0))
|
||||
array.SetFirstPadInArray(pads["*n"]+1)
|
||||
array.AddPadsToModule(self.draw)
|
||||
if pads["*thermal vias"]:
|
||||
via_diam = min(esubpad_size_y, esubpad_size_x)/3.
|
||||
thpad = PA.PadMaker(self.module).THRoundPad(via_diam, min(via_diam/2, epad_via_drill))
|
||||
layerset = pcbnew.LSET.AllCuMask()
|
||||
layerset.AddLayer(pcbnew.B_Mask)
|
||||
layerset.AddLayer(pcbnew.F_Mask)
|
||||
thpad.SetLayerSet(layerset)
|
||||
array2 = PA.EPADGridArray(thpad, epad_subdv_x, epad_subdv_y, esubpad_size_x + px, esubpad_size_y + py, pcbnew.wxPoint(0,0))
|
||||
array2.SetFirstPadInArray(pads["*n"]+1)
|
||||
array2.AddPadsToModule(self.draw)
|
||||
else:
|
||||
epad = PA.PadMaker(self.module).SMDPad(epad_length, epad_width)
|
||||
epad_pos = pcbnew.wxPoint(0,0)
|
||||
array = PA.PadLineArray(epad, 1, 1, False, epad_pos)
|
||||
array.SetFirstPadInArray(pads["*n"]+1)
|
||||
array.AddPadsToModule(self.draw)
|
||||
if pads["*thermal vias"]:
|
||||
via_diam = min(epad_length, epad_width)/3.
|
||||
thpad = PA.PadMaker(self.module).THRoundPad( via_diam, min(via_diam/2, epad_via_drill))
|
||||
layerset = pcbnew.LSET.AllCuMask()
|
||||
layerset.AddLayer(pcbnew.B_Mask)
|
||||
layerset.AddLayer(pcbnew.F_Mask)
|
||||
thpad.SetLayerSet(layerset)
|
||||
array2 = PA.PadLineArray(thpad, 1, 1, False, epad_pos)
|
||||
array2.SetFirstPadInArray(pads["*n"]+1)
|
||||
array2.AddPadsToModule(self.draw)
|
||||
epad_via_drill = self.epad["thermal vias drill"]
|
||||
|
||||
#top left - diagonal
|
||||
self.draw.Line(-lim_x, -inner, -inner, -lim_y)
|
||||
# top right
|
||||
self.draw.Polyline([(inner, -lim_y), (lim_x, -lim_y), (lim_x, -inner)])
|
||||
# bottom left
|
||||
self.draw.Polyline([(-inner, lim_y), (-lim_x, lim_y), (-lim_x, inner)])
|
||||
# bottom right
|
||||
self.draw.Polyline([(inner, lim_y), (lim_x, lim_y), (lim_x, inner)])
|
||||
# Create a central exposed pad?
|
||||
if self.epad['epad'] == True:
|
||||
|
||||
epad_num = self.pads['n'] + 1
|
||||
|
||||
epad_w = epad_length / epad_nx
|
||||
epad_l = epad_width / epad_ny
|
||||
|
||||
# Create the epad
|
||||
epad = PA.PadMaker(self.module).SMDPad( epad_w, epad_l, shape=pcbnew.PAD_SHAPE_RECT )
|
||||
epad.SetLocalSolderPasteMargin( -1 * self.epad['paste margin'] )
|
||||
# set pad layers
|
||||
layers = pcbnew.LSET(pcbnew.F_Mask)
|
||||
layers.AddLayer(pcbnew.F_Cu)
|
||||
layers.AddLayer(pcbnew.F_Paste)
|
||||
epad.SetPadName(epad_num)
|
||||
|
||||
array = PA.EPADGridArray( epad, epad_ny, epad_nx, epad_l, epad_w, pcbnew.wxPoint(0,0) )
|
||||
array.SetFirstPadInArray(epad_num)
|
||||
array.AddPadsToModule(self.draw)
|
||||
|
||||
if self.epad['thermal vias']:
|
||||
|
||||
# create the thermal via
|
||||
via_diam = min(epad_w, epad_l) / 2
|
||||
via_drill = min(via_diam / 2, epad_via_drill)
|
||||
via = PA.PadMaker(self.module).THRoundPad(via_diam, via_drill)
|
||||
layers = pcbnew.LSET.AllCuMask()
|
||||
layers.AddLayer(pcbnew.B_Mask)
|
||||
layers.AddLayer(pcbnew.F_Mask)
|
||||
via.SetLayerSet(layers)
|
||||
|
||||
via_array = PA.EPADGridArray(via, epad_ny, epad_nx, epad_l, epad_w, pcbnew.wxPoint(0,0) )
|
||||
via_array.SetFirstPadInArray(epad_num)
|
||||
via_array.AddPadsToModule(self.draw)
|
||||
|
||||
# Draw the package outline on the F.Fab layer
|
||||
bevel = min( pcbnew.FromMM(1.0), self.package['width']/2, self.package['height']/2 )
|
||||
|
||||
self.draw.SetLayer(pcbnew.F_Fab)
|
||||
|
||||
w = self.package['width']
|
||||
h = self.package['height']
|
||||
|
||||
self.draw.BoxWithDiagonalAtCorner(0, 0, w, h, bevel)
|
||||
|
||||
# Silkscreen
|
||||
self.draw.SetLayer(pcbnew.F_SilkS)
|
||||
|
||||
offset = self.draw.GetLineThickness()
|
||||
clip = row_len / 2 + self.pads['pitch']
|
||||
|
||||
self.draw.Polyline( [ [ clip, -h/2-offset], [ w/2+offset,-h/2-offset], [ w/2+offset, -clip] ] ) # top right
|
||||
self.draw.Polyline( [ [ clip, h/2+offset], [ w/2+offset, h/2+offset], [ w/2+offset, clip] ] ) # bottom right
|
||||
self.draw.Polyline( [ [-clip, h/2+offset], [-w/2-offset, h/2+offset], [-w/2-offset, clip] ] ) # bottom left
|
||||
|
||||
# Add pin-1 indication as per IPC-7351C
|
||||
self.draw.Line(-clip, -h/2-offset, -w/2-pad_length/2, -h/2-offset)
|
||||
|
||||
# Courtyard
|
||||
cmargin = self.parameters["Package"]["courtyard margin"]
|
||||
cmargin = self.package["margin"]
|
||||
self.draw.SetLayer(pcbnew.F_CrtYd)
|
||||
sizex = (lim_x + cmargin) * 2 + pad_length/2.
|
||||
sizey = (lim_y + cmargin) * 2 + pad_length/2.
|
||||
|
||||
sizex = (lim_x + cmargin) * 2 + pad_length
|
||||
sizey = (lim_y + cmargin) * 2 + pad_length
|
||||
|
||||
# round size to nearest 0.1mm, rectangle will thus land on a 0.05mm grid
|
||||
sizex = self.PutOnGridMM(sizex, 0.1)
|
||||
sizey = self.PutOnGridMM(sizey, 0.1)
|
||||
sizex = pcbnew.PutOnGridMM(sizex, 0.1)
|
||||
sizey = pcbnew.PutOnGridMM(sizey, 0.1)
|
||||
# set courtyard line thickness to the one defined in KLC
|
||||
thick = self.draw.GetLineThickness()
|
||||
self.draw.SetLineThickness(pcbnew.FromMM(0.05))
|
||||
|
||||
@@ -17,53 +17,64 @@
|
||||
from __future__ import division
|
||||
import pcbnew
|
||||
|
||||
import HelpfulFootprintWizardPlugin
|
||||
import FootprintWizardBase
|
||||
import PadArray as PA
|
||||
|
||||
|
||||
class QFPWizard(HelpfulFootprintWizardPlugin.HelpfulFootprintWizardPlugin):
|
||||
class QFPWizard(FootprintWizardBase.FootprintWizard):
|
||||
|
||||
def GetName(self):
|
||||
return "QFP"
|
||||
|
||||
def GetDescription(self):
|
||||
return "Quad Flat Package footprint wizard"
|
||||
return "Quad Flat Package (QFP) footprint wizard"
|
||||
|
||||
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", "n", self.uInteger, 100, multiple=4, min_value=4)
|
||||
self.AddParam("Pads", "pitch", self.uMM, 0.5, designator='e')
|
||||
self.AddParam("Pads", "width", self.uMM, 0.25, designator='X1')
|
||||
self.AddParam("Pads", "length", self.uMM, 1.5, designator='Y1')
|
||||
self.AddParam("Pads", "horizontal spacing", self.uMM, 15, designator='C1')
|
||||
self.AddParam("Pads", "vertical spacing", self.uMM, 15, designator='C2')
|
||||
self.AddParam("Pads", "oval", self.uBool, True)
|
||||
|
||||
self.AddParam("Package", "package width", self.uMM, 14)
|
||||
self.AddParam("Package", "package height", self.uMM, 14)
|
||||
self.AddParam("Package", "courtyard margin", self.uMM, 1)
|
||||
self.AddParam("Package", "width", self.uMM, 14, designator='D1')
|
||||
self.AddParam("Package", "height", self.uMM, 14, designator='E1')
|
||||
self.AddParam("Package", "courtyard margin", self.uMM, 0.25, min_value=0.2)
|
||||
|
||||
@property
|
||||
def pads(self):
|
||||
return self.parameters['Pads']
|
||||
|
||||
@property
|
||||
def package(self):
|
||||
return self.parameters['Package']
|
||||
|
||||
def CheckParameters(self):
|
||||
self.CheckParamInt("Pads", "*n", is_multiple_of=4)
|
||||
self.CheckParamBool("Pads", "*oval")
|
||||
# todo - custom checking
|
||||
pass
|
||||
|
||||
def GetValue(self):
|
||||
return "QFP_%d" % self.parameters["Pads"]["*n"]
|
||||
return "QFP-{n}_{x:g}x{y:g}_Pitch{p:g}mm".format(
|
||||
n = self.pads['n'],
|
||||
x = pcbnew.ToMM(self.package['width']),
|
||||
y = pcbnew.ToMM(self.package['height']),
|
||||
p = pcbnew.ToMM(self.pads['pitch'])
|
||||
)
|
||||
|
||||
def BuildThisFootprint(self):
|
||||
pads = self.parameters["Pads"]
|
||||
|
||||
pad_pitch = pads["pad pitch"]
|
||||
pad_length = self.parameters["Pads"]["pad length"]
|
||||
pad_width = self.parameters["Pads"]["pad width"]
|
||||
pad_pitch = self.pads["pitch"]
|
||||
pad_length = self.pads["length"]
|
||||
pad_width = self.pads["width"]
|
||||
|
||||
v_pitch = pads["vertical pitch"]
|
||||
h_pitch = pads["horizontal pitch"]
|
||||
v_pitch = self.pads["vertical spacing"]
|
||||
h_pitch = self.pads["horizontal spacing"]
|
||||
|
||||
pads_per_row = pads["*n"] // 4
|
||||
pads_per_row = int(self.pads["n"] // 4)
|
||||
|
||||
row_len = (pads_per_row - 1) * pad_pitch
|
||||
|
||||
pad_shape = pcbnew.PAD_SHAPE_OVAL if pads["*oval"] else pcbnew.PAD_SHAPE_RECT
|
||||
pad_shape = pcbnew.PAD_SHAPE_OVAL if self.pads["oval"] else pcbnew.PAD_SHAPE_RECT
|
||||
|
||||
h_pad = PA.PadMaker(self.module).SMDPad( pad_length, pad_width,
|
||||
shape=pad_shape, rot_degree=90.0)
|
||||
@@ -95,27 +106,49 @@ class QFPWizard(HelpfulFootprintWizardPlugin.HelpfulFootprintWizardPlugin):
|
||||
array.SetFirstPadInArray(3*pads_per_row + 1)
|
||||
array.AddPadsToModule(self.draw)
|
||||
|
||||
lim_x = self.parameters["Package"]["package width"] / 2
|
||||
lim_y = self.parameters["Package"]["package height"] / 2
|
||||
offset = pcbnew.FromMM(0.15)
|
||||
|
||||
x = self.parameters["Package"]["width"] / 2 + offset
|
||||
y = self.parameters["Package"]["height"] / 2 + offset
|
||||
inner = (row_len / 2) + pad_pitch
|
||||
|
||||
#top left - diagonal
|
||||
self.draw.Line(-lim_x, -inner, -inner, -lim_y)
|
||||
# Add outline to F_Fab layer
|
||||
self.draw.SetLayer(pcbnew.F_Fab)
|
||||
|
||||
bevel = min( pcbnew.FromMM(1.0), self.package['width']/2, self.package['height']/2 )
|
||||
|
||||
w = self.package['width']
|
||||
h = self.package['height']
|
||||
|
||||
# outermost limits of pins
|
||||
right_edge = (h_pitch + pad_length) / 2
|
||||
left_edge = -right_edge
|
||||
|
||||
bottom_edge = (v_pitch + pad_length) / 2
|
||||
top_edge = -bottom_edge
|
||||
|
||||
self.draw.BoxWithDiagonalAtCorner(0, 0, w, h, bevel)
|
||||
|
||||
# Draw silkscreen
|
||||
self.draw.SetLayer(pcbnew.F_SilkS)
|
||||
|
||||
#top left - as per IPC-7351C
|
||||
self.draw.Polyline([(-inner, -y), (-x, -y), (-x, -inner), (left_edge, -inner)])
|
||||
# top right
|
||||
self.draw.Polyline([(inner, -lim_y), (lim_x, -lim_y), (lim_x, -inner)])
|
||||
self.draw.Polyline([(inner, -y), (x, -y), (x, -inner)])
|
||||
# bottom left
|
||||
self.draw.Polyline([(-inner, lim_y), (-lim_x, lim_y), (-lim_x, inner)])
|
||||
self.draw.Polyline([(-inner, y), (-x, y), (-x, inner)])
|
||||
# bottom right
|
||||
self.draw.Polyline([(inner, lim_y), (lim_x, lim_y), (lim_x, inner)])
|
||||
self.draw.Polyline([(inner, y), (x, y), (x, inner)])
|
||||
|
||||
# Courtyard
|
||||
cmargin = self.parameters["Package"]["courtyard margin"]
|
||||
self.draw.SetLayer(pcbnew.F_CrtYd)
|
||||
sizex = (lim_x + cmargin) * 2 + pad_length
|
||||
sizey = (lim_y + cmargin) * 2 + pad_length
|
||||
sizex = (right_edge + cmargin) * 2
|
||||
sizey = (bottom_edge + cmargin) * 2
|
||||
# round size to nearest 0.1mm, rectangle will thus land on a 0.05mm grid
|
||||
sizex = self.PutOnGridMM(sizex, 0.1)
|
||||
sizey = self.PutOnGridMM(sizey, 0.1)
|
||||
sizex = pcbnew.PutOnGridMM(sizex, 0.1)
|
||||
sizey = pcbnew.PutOnGridMM(sizey, 0.1)
|
||||
# set courtyard line thickness to the one defined in KLC
|
||||
thick = self.draw.GetLineThickness()
|
||||
self.draw.SetLineThickness(pcbnew.FromMM(0.05))
|
||||
|
||||
@@ -0,0 +1,827 @@
|
||||
#
|
||||
# QR Code Generator for Python
|
||||
#
|
||||
# Copyright (c) 2012 Kazuhiko Arase
|
||||
#
|
||||
# URL: http://www.d-project.com/
|
||||
#
|
||||
# Licensed under the MIT license:
|
||||
# http://www.opensource.org/licenses/mit-license.php
|
||||
#
|
||||
# The word 'QR Code' is registered trademark of
|
||||
# DENSO WAVE INCORPORATED
|
||||
# http://www.denso-wave.com/qrcode/faqpatent-e.html
|
||||
#
|
||||
|
||||
"""QR Code Generator for Python
|
||||
|
||||
from qrcode import QRCode, ErrorCorrectLevel
|
||||
|
||||
# generate with explicit type number
|
||||
qr = QRCode()
|
||||
qr.setTypeNumber(4)
|
||||
qr.setErrorCorrectLevel(ErrorCorrectLevel.M)
|
||||
qr.addData('here comes qr!')
|
||||
qr.make()
|
||||
|
||||
# generate with auto type number
|
||||
# qr = QRCode.getMinimumQRCode('here comes qr!', ErrorCorrectLevel.M)
|
||||
|
||||
# create an image
|
||||
for r in range(qr.getModuleCount() ):
|
||||
for c in range(qr.getModuleCount() ):
|
||||
color = black if qr.isDark(r, c) else white
|
||||
# set pixel ...
|
||||
|
||||
"""
|
||||
|
||||
class QRCode:
|
||||
|
||||
PAD0 = 0xEC
|
||||
PAD1 = 0x11
|
||||
|
||||
def __init__(self):
|
||||
self.typeNumber = 1
|
||||
self.errorCorrectLevel = ErrorCorrectLevel.H
|
||||
self.qrDataList = []
|
||||
self.modules = []
|
||||
self.moduleCount = 0
|
||||
|
||||
def getTypeNumber(self):
|
||||
return self.typeNumber
|
||||
|
||||
def setTypeNumber(self, typeNumber):
|
||||
self.typeNumber = typeNumber
|
||||
|
||||
def getErrorCorrectLevel(self):
|
||||
return self.errorCorrectLevel
|
||||
|
||||
def setErrorCorrectLevel(self, errorCorrectLevel):
|
||||
self.errorCorrectLevel = errorCorrectLevel
|
||||
|
||||
def clearData(self):
|
||||
self.qrDataList = []
|
||||
|
||||
def addData(self, data):
|
||||
self.qrDataList.append(QR8BitByte(data) )
|
||||
|
||||
def getDataCount(self):
|
||||
return len(self.qrDataList)
|
||||
|
||||
def getData(self, index):
|
||||
return self.qrDataList[index]
|
||||
|
||||
def isDark(self, row, col):
|
||||
return (self.modules[row][col] if self.modules[row][col] != None
|
||||
else False)
|
||||
|
||||
def getModuleCount(self):
|
||||
return self.moduleCount
|
||||
|
||||
def make(self):
|
||||
self._make(False, self._getBestMaskPattern() )
|
||||
|
||||
def _getBestMaskPattern(self):
|
||||
minLostPoint = 0
|
||||
pattern = 0
|
||||
for i in range(8):
|
||||
self._make(True, i)
|
||||
lostPoint = QRUtil.getLostPoint(self)
|
||||
if i == 0 or minLostPoint > lostPoint:
|
||||
minLostPoint = lostPoint
|
||||
pattern = i
|
||||
return pattern
|
||||
|
||||
def _make(self, test, maskPattern):
|
||||
|
||||
self.moduleCount = self.typeNumber * 4 + 17
|
||||
self.modules = [[None] * self.moduleCount
|
||||
for i in range(self.moduleCount)]
|
||||
|
||||
self._setupPositionProbePattern(0, 0)
|
||||
self._setupPositionProbePattern(self.moduleCount - 7, 0)
|
||||
self._setupPositionProbePattern(0, self.moduleCount - 7)
|
||||
|
||||
self._setupPositionAdjustPattern()
|
||||
self._setupTimingPattern()
|
||||
|
||||
self._setupTypeInfo(test, maskPattern)
|
||||
|
||||
if self.typeNumber >= 7:
|
||||
self._setupTypeNumber(test)
|
||||
|
||||
data = QRCode._createData(
|
||||
self.typeNumber,
|
||||
self.errorCorrectLevel,
|
||||
self.qrDataList)
|
||||
|
||||
self._mapData(data, maskPattern)
|
||||
|
||||
def _mapData(self, data, maskPattern):
|
||||
|
||||
rows = list(range(self.moduleCount) )
|
||||
cols = [col - 1 if col <= 6 else col
|
||||
for col in range(self.moduleCount - 1, 0, -2)]
|
||||
maskFunc = QRUtil.getMaskFunction(maskPattern)
|
||||
|
||||
byteIndex = 0
|
||||
bitIndex = 7
|
||||
|
||||
for col in cols:
|
||||
rows.reverse()
|
||||
for row in rows:
|
||||
for c in range(2):
|
||||
if self.modules[row][col - c] == None:
|
||||
|
||||
dark = False
|
||||
if byteIndex < len(data):
|
||||
dark = ( (data[byteIndex] >> bitIndex) & 1) == 1
|
||||
if maskFunc(row, col - c):
|
||||
dark = not dark
|
||||
self.modules[row][col - c] = dark
|
||||
|
||||
bitIndex -= 1
|
||||
if bitIndex == -1:
|
||||
byteIndex += 1
|
||||
bitIndex = 7
|
||||
|
||||
def _setupPositionAdjustPattern(self):
|
||||
pos = QRUtil.getPatternPosition(self.typeNumber)
|
||||
for row in pos:
|
||||
for col in pos:
|
||||
if self.modules[row][col] != None:
|
||||
continue
|
||||
for r in range(-2, 3):
|
||||
for c in range(-2, 3):
|
||||
self.modules[row + r][col + c] = (
|
||||
r == -2 or r == 2 or c == -2 or c == 2
|
||||
or (r == 0 and c == 0) )
|
||||
|
||||
def _setupPositionProbePattern(self, row, col):
|
||||
for r in range(-1, 8):
|
||||
for c in range(-1, 8):
|
||||
if (row + r <= -1 or self.moduleCount <= row + r
|
||||
or col + c <= -1 or self.moduleCount <= col + c):
|
||||
continue
|
||||
self.modules[row + r][col + c] = (
|
||||
(0 <= r and r <= 6 and (c == 0 or c == 6) )
|
||||
or (0 <= c and c <= 6 and (r == 0 or r == 6) )
|
||||
or (2 <= r and r <= 4 and 2 <= c and c <= 4) )
|
||||
|
||||
def _setupTimingPattern(self):
|
||||
for r in range(8, self.moduleCount - 8):
|
||||
if self.modules[r][6] != None:
|
||||
continue
|
||||
self.modules[r][6] = r % 2 == 0
|
||||
for c in range(8, self.moduleCount - 8):
|
||||
if self.modules[6][c] != None:
|
||||
continue
|
||||
self.modules[6][c] = c % 2 == 0
|
||||
|
||||
def _setupTypeNumber(self, test):
|
||||
bits = QRUtil.getBCHTypeNumber(self.typeNumber)
|
||||
for i in range(18):
|
||||
self.modules[i // 3][i % 3 + self.moduleCount - 8 - 3] = (
|
||||
not test and ( (bits >> i) & 1) == 1)
|
||||
for i in range(18):
|
||||
self.modules[i % 3 + self.moduleCount - 8 - 3][i // 3] = (
|
||||
not test and ( (bits >> i) & 1) == 1)
|
||||
|
||||
def _setupTypeInfo(self, test, maskPattern):
|
||||
|
||||
data = (self.errorCorrectLevel << 3) | maskPattern
|
||||
bits = QRUtil.getBCHTypeInfo(data)
|
||||
|
||||
# vertical
|
||||
for i in range(15):
|
||||
mod = not test and ( (bits >> i) & 1) == 1
|
||||
if i < 6:
|
||||
self.modules[i][8] = mod
|
||||
elif i < 8:
|
||||
self.modules[i + 1][8] = mod
|
||||
else:
|
||||
self.modules[self.moduleCount - 15 + i][8] = mod
|
||||
|
||||
# horizontal
|
||||
for i in range(15):
|
||||
mod = not test and ( (bits >> i) & 1) == 1
|
||||
if i < 8:
|
||||
self.modules[8][self.moduleCount - i - 1] = mod
|
||||
elif i < 9:
|
||||
self.modules[8][15 - i - 1 + 1] = mod
|
||||
else:
|
||||
self.modules[8][15 - i - 1] = mod
|
||||
|
||||
# fixed
|
||||
self.modules[self.moduleCount - 8][8] = not test
|
||||
|
||||
@staticmethod
|
||||
def _createData(typeNumber, errorCorrectLevel, dataArray):
|
||||
|
||||
rsBlocks = RSBlock.getRSBlocks(typeNumber, errorCorrectLevel)
|
||||
|
||||
buffer = BitBuffer()
|
||||
|
||||
for data in dataArray:
|
||||
buffer.put(data.getMode(), 4)
|
||||
buffer.put(data.getLength(), data.getLengthInBits(typeNumber) )
|
||||
data.write(buffer)
|
||||
|
||||
totalDataCount = sum(rsBlock.getDataCount()
|
||||
for rsBlock in rsBlocks)
|
||||
|
||||
if buffer.getLengthInBits() > totalDataCount * 8:
|
||||
raise Exception('code length overflow. (%s > %s)' %
|
||||
(buffer.getLengthInBits(), totalDataCount * 8) )
|
||||
|
||||
# end code
|
||||
if buffer.getLengthInBits() + 4 <= totalDataCount * 8:
|
||||
buffer.put(0, 4)
|
||||
|
||||
# padding
|
||||
while buffer.getLengthInBits() % 8 != 0:
|
||||
buffer.put(False)
|
||||
|
||||
# padding
|
||||
while True:
|
||||
if buffer.getLengthInBits() >= totalDataCount * 8:
|
||||
break
|
||||
buffer.put(QRCode.PAD0, 8)
|
||||
if buffer.getLengthInBits() >= totalDataCount * 8:
|
||||
break
|
||||
buffer.put(QRCode.PAD1, 8)
|
||||
|
||||
return QRCode._createBytes(buffer, rsBlocks)
|
||||
|
||||
@staticmethod
|
||||
def _createBytes(buffer, rsBlocks):
|
||||
|
||||
offset = 0
|
||||
|
||||
maxDcCount = 0
|
||||
maxEcCount = 0
|
||||
|
||||
dcdata = [None] * len(rsBlocks)
|
||||
ecdata = [None] * len(rsBlocks)
|
||||
|
||||
for r in range(len(rsBlocks) ):
|
||||
|
||||
dcCount = rsBlocks[r].getDataCount()
|
||||
ecCount = rsBlocks[r].getTotalCount() - dcCount
|
||||
|
||||
maxDcCount = max(maxDcCount, dcCount)
|
||||
maxEcCount = max(maxEcCount, ecCount)
|
||||
|
||||
dcdata[r] = [0] * dcCount
|
||||
for i in range(len(dcdata[r] ) ):
|
||||
dcdata[r][i] = 0xff & buffer.getBuffer()[i + offset]
|
||||
offset += dcCount
|
||||
|
||||
rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount)
|
||||
rawPoly = Polynomial(dcdata[r], rsPoly.getLength() - 1)
|
||||
|
||||
modPoly = rawPoly.mod(rsPoly)
|
||||
ecdata[r] = [0] * (rsPoly.getLength() - 1)
|
||||
for i in range(len(ecdata[r]) ):
|
||||
modIndex = i + modPoly.getLength() - len(ecdata[r])
|
||||
ecdata[r][i] = modPoly.get(modIndex) if modIndex >= 0 else 0
|
||||
|
||||
totalCodeCount = sum(rsBlock.getTotalCount()
|
||||
for rsBlock in rsBlocks)
|
||||
|
||||
data = [0] * totalCodeCount
|
||||
|
||||
index = 0
|
||||
|
||||
for i in range(maxDcCount):
|
||||
for r in range(len(rsBlocks) ):
|
||||
if i < len(dcdata[r] ):
|
||||
data[index] = dcdata[r][i]
|
||||
index += 1
|
||||
|
||||
for i in range(maxEcCount):
|
||||
for r in range(len(rsBlocks) ):
|
||||
if i < len(ecdata[r] ):
|
||||
data[index] = ecdata[r][i]
|
||||
index += 1
|
||||
|
||||
return data
|
||||
|
||||
@staticmethod
|
||||
def getMinimumQRCode(data, errorCorrectLevel):
|
||||
mode = Mode.MODE_8BIT_BYTE # fixed to 8bit byte
|
||||
qr = QRCode()
|
||||
qr.setErrorCorrectLevel(errorCorrectLevel)
|
||||
qr.addData(data)
|
||||
length = qr.getData(0).getLength()
|
||||
for typeNumber in range(1, 11):
|
||||
if length <= QRUtil.getMaxLength(
|
||||
typeNumber, mode, errorCorrectLevel):
|
||||
qr.setTypeNumber(typeNumber)
|
||||
break
|
||||
qr.make()
|
||||
return qr
|
||||
|
||||
class Mode:
|
||||
MODE_NUMBER = 1 << 0
|
||||
MODE_ALPHA_NUM = 1 << 1
|
||||
MODE_8BIT_BYTE = 1 << 2
|
||||
MODE_KANJI = 1 << 3
|
||||
|
||||
class ErrorCorrectLevel:
|
||||
L = 1 # 7%
|
||||
M = 0 # 15%
|
||||
Q = 3 # 25%
|
||||
H = 2 # 30%
|
||||
|
||||
class MaskPattern:
|
||||
PATTERN000 = 0
|
||||
PATTERN001 = 1
|
||||
PATTERN010 = 2
|
||||
PATTERN011 = 3
|
||||
PATTERN100 = 4
|
||||
PATTERN101 = 5
|
||||
PATTERN110 = 6
|
||||
PATTERN111 = 7
|
||||
|
||||
class QRUtil:
|
||||
|
||||
@staticmethod
|
||||
def getPatternPosition(typeNumber):
|
||||
return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1]
|
||||
|
||||
PATTERN_POSITION_TABLE = [
|
||||
[],
|
||||
[6, 18],
|
||||
[6, 22],
|
||||
[6, 26],
|
||||
[6, 30],
|
||||
[6, 34],
|
||||
[6, 22, 38],
|
||||
[6, 24, 42],
|
||||
[6, 26, 46],
|
||||
[6, 28, 50],
|
||||
[6, 30, 54],
|
||||
[6, 32, 58],
|
||||
[6, 34, 62],
|
||||
[6, 26, 46, 66],
|
||||
[6, 26, 48, 70],
|
||||
[6, 26, 50, 74],
|
||||
[6, 30, 54, 78],
|
||||
[6, 30, 56, 82],
|
||||
[6, 30, 58, 86],
|
||||
[6, 34, 62, 90],
|
||||
[6, 28, 50, 72, 94],
|
||||
[6, 26, 50, 74, 98],
|
||||
[6, 30, 54, 78, 102],
|
||||
[6, 28, 54, 80, 106],
|
||||
[6, 32, 58, 84, 110],
|
||||
[6, 30, 58, 86, 114],
|
||||
[6, 34, 62, 90, 118],
|
||||
[6, 26, 50, 74, 98, 122],
|
||||
[6, 30, 54, 78, 102, 126],
|
||||
[6, 26, 52, 78, 104, 130],
|
||||
[6, 30, 56, 82, 108, 134],
|
||||
[6, 34, 60, 86, 112, 138],
|
||||
[6, 30, 58, 86, 114, 142],
|
||||
[6, 34, 62, 90, 118, 146],
|
||||
[6, 30, 54, 78, 102, 126, 150],
|
||||
[6, 24, 50, 76, 102, 128, 154],
|
||||
[6, 28, 54, 80, 106, 132, 158],
|
||||
[6, 32, 58, 84, 110, 136, 162],
|
||||
[6, 26, 54, 82, 110, 138, 166],
|
||||
[6, 30, 58, 86, 114, 142, 170]
|
||||
]
|
||||
|
||||
MAX_LENGTH = [
|
||||
[ [41, 25, 17, 10], [34, 20, 14, 8], [27, 16, 11, 7], [17, 10, 7, 4] ],
|
||||
[ [77, 47, 32, 20], [63, 38, 26, 16], [48, 29, 20, 12], [34, 20, 14, 8] ],
|
||||
[ [127, 77, 53, 32], [101, 61, 42, 26], [77, 47, 32, 20], [58, 35, 24, 15] ],
|
||||
[ [187, 114, 78, 48], [149, 90, 62, 38], [111, 67, 46, 28], [82, 50, 34, 21] ],
|
||||
[ [255, 154, 106, 65], [202, 122, 84, 52], [144, 87, 60, 37], [106, 64, 44, 27] ],
|
||||
[ [322, 195, 134, 82], [255, 154, 106, 65], [178, 108, 74, 45], [139, 84, 58, 36] ],
|
||||
[ [370, 224, 154, 95], [293, 178, 122, 75], [207, 125, 86, 53], [154, 93, 64, 39] ],
|
||||
[ [461, 279, 192, 118], [365, 221, 152, 93], [259, 157, 108, 66], [202, 122, 84, 52] ],
|
||||
[ [552, 335, 230, 141], [432, 262, 180, 111], [312, 189, 130, 80], [235, 143, 98, 60] ],
|
||||
[ [652, 395, 271, 167], [513, 311, 213, 131], [364, 221, 151, 93], [288, 174, 119, 74] ]
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def getMaxLength(typeNumber, mode, errorCorrectLevel):
|
||||
t = typeNumber - 1
|
||||
e = {
|
||||
ErrorCorrectLevel.L: 0,
|
||||
ErrorCorrectLevel.M: 1,
|
||||
ErrorCorrectLevel.Q: 2,
|
||||
ErrorCorrectLevel.H: 3
|
||||
}[errorCorrectLevel]
|
||||
m = {
|
||||
Mode.MODE_NUMBER: 0,
|
||||
Mode.MODE_ALPHA_NUM: 1,
|
||||
Mode.MODE_8BIT_BYTE: 2,
|
||||
Mode.MODE_KANJI: 3
|
||||
}[mode]
|
||||
return QRUtil.MAX_LENGTH[t][e][m]
|
||||
|
||||
@staticmethod
|
||||
def getErrorCorrectPolynomial(errorCorrectLength):
|
||||
a = Polynomial([1])
|
||||
for i in range(errorCorrectLength):
|
||||
a = a.multiply(Polynomial([1, QRMath.gexp(i)]) )
|
||||
return a
|
||||
|
||||
@staticmethod
|
||||
def getMaskFunction(maskPattern):
|
||||
return {
|
||||
MaskPattern.PATTERN000:
|
||||
lambda i, j: (i + j) % 2 == 0,
|
||||
MaskPattern.PATTERN001:
|
||||
lambda i, j: i % 2 == 0,
|
||||
MaskPattern.PATTERN010:
|
||||
lambda i, j: j % 3 == 0,
|
||||
MaskPattern.PATTERN011:
|
||||
lambda i, j: (i + j) % 3 == 0,
|
||||
MaskPattern.PATTERN100:
|
||||
lambda i, j: (i // 2 + j // 3) % 2 == 0,
|
||||
MaskPattern.PATTERN101:
|
||||
lambda i, j: (i * j) % 2 + (i * j) % 3 == 0,
|
||||
MaskPattern.PATTERN110:
|
||||
lambda i, j: ( (i * j) % 2 + (i * j) % 3) % 2 == 0,
|
||||
MaskPattern.PATTERN111:
|
||||
lambda i, j: ( (i * j) % 3 + (i + j) % 2) % 2 == 0
|
||||
}[maskPattern]
|
||||
|
||||
@staticmethod
|
||||
def getLostPoint(qrcode):
|
||||
|
||||
moduleCount = qrcode.getModuleCount()
|
||||
lostPoint = 0
|
||||
|
||||
# LEVEL1
|
||||
for row in range(moduleCount):
|
||||
for col in range(moduleCount):
|
||||
sameCount = 0
|
||||
dark = qrcode.isDark(row, col)
|
||||
for r in range(-1, 2):
|
||||
if row + r < 0 or moduleCount <= row + r:
|
||||
continue
|
||||
for c in range(-1, 2):
|
||||
if col + c < 0 or moduleCount <= col + c:
|
||||
continue
|
||||
if r == 0 and c == 0:
|
||||
continue
|
||||
if dark == qrcode.isDark(row + r, col + c):
|
||||
sameCount += 1
|
||||
if sameCount > 5:
|
||||
lostPoint += (3 + sameCount - 5)
|
||||
|
||||
# LEVEL2
|
||||
for row in range(moduleCount - 1):
|
||||
for col in range(moduleCount - 1):
|
||||
count = 0
|
||||
if qrcode.isDark(row, col):
|
||||
count += 1
|
||||
if qrcode.isDark(row + 1, col):
|
||||
count += 1
|
||||
if qrcode.isDark(row, col + 1):
|
||||
count += 1
|
||||
if qrcode.isDark(row + 1, col + 1):
|
||||
count += 1
|
||||
if count == 0 or count == 4:
|
||||
lostPoint += 3
|
||||
|
||||
# LEVEL3
|
||||
for row in range(moduleCount):
|
||||
for col in range(moduleCount - 6):
|
||||
if (qrcode.isDark(row, col)
|
||||
and not qrcode.isDark(row, col + 1)
|
||||
and qrcode.isDark(row, col + 2)
|
||||
and qrcode.isDark(row, col + 3)
|
||||
and qrcode.isDark(row, col + 4)
|
||||
and not qrcode.isDark(row, col + 5)
|
||||
and qrcode.isDark(row, col + 6) ):
|
||||
lostPoint += 40
|
||||
|
||||
for col in range(moduleCount):
|
||||
for row in range(moduleCount - 6):
|
||||
if (qrcode.isDark(row, col)
|
||||
and not qrcode.isDark(row + 1, col)
|
||||
and qrcode.isDark(row + 2, col)
|
||||
and qrcode.isDark(row + 3, col)
|
||||
and qrcode.isDark(row + 4, col)
|
||||
and not qrcode.isDark(row + 5, col)
|
||||
and qrcode.isDark(row + 6, col) ):
|
||||
lostPoint += 40
|
||||
|
||||
# LEVEL4
|
||||
darkCount = 0
|
||||
for col in range(moduleCount):
|
||||
for row in range(moduleCount):
|
||||
if qrcode.isDark(row, col):
|
||||
darkCount += 1
|
||||
|
||||
ratio = abs(100 * darkCount // moduleCount // moduleCount - 50) // 5
|
||||
lostPoint += ratio * 10
|
||||
|
||||
return lostPoint
|
||||
|
||||
G15 = ( (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) |
|
||||
(1 << 2) | (1 << 1) | (1 << 0) )
|
||||
G18 = ( (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) |
|
||||
(1 << 8) | (1 << 5) | (1 << 2) | (1 << 0) )
|
||||
G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1)
|
||||
|
||||
@staticmethod
|
||||
def getBCHTypeInfo(data):
|
||||
d = data << 10
|
||||
while QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0:
|
||||
d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) -
|
||||
QRUtil.getBCHDigit(QRUtil.G15) ) )
|
||||
return ( (data << 10) | d) ^ QRUtil.G15_MASK
|
||||
|
||||
@staticmethod
|
||||
def getBCHTypeNumber(data):
|
||||
d = data << 12
|
||||
while QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0:
|
||||
d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) -
|
||||
QRUtil.getBCHDigit(QRUtil.G18) ) )
|
||||
return (data << 12) | d
|
||||
|
||||
@staticmethod
|
||||
def getBCHDigit(data):
|
||||
digit = 0
|
||||
while data != 0:
|
||||
digit += 1
|
||||
data >>= 1
|
||||
return digit
|
||||
|
||||
@staticmethod
|
||||
def stringToBytes(s):
|
||||
return [ord(c) & 0xff for c in s]
|
||||
|
||||
class QR8BitByte:
|
||||
|
||||
def __init__(self, data):
|
||||
self.mode = Mode.MODE_8BIT_BYTE
|
||||
self.data = data
|
||||
|
||||
def getMode(self):
|
||||
return self.mode
|
||||
|
||||
def getData(self):
|
||||
return self.data
|
||||
|
||||
'''
|
||||
def write(self, buffer): raise Exception('not implemented.')
|
||||
def getLength(self): raise Exception('not implemented.')
|
||||
'''
|
||||
|
||||
def write(self, buffer):
|
||||
data = QRUtil.stringToBytes(self.getData() )
|
||||
for d in data:
|
||||
buffer.put(d, 8)
|
||||
|
||||
def getLength(self):
|
||||
return len(QRUtil.stringToBytes(self.getData() ) )
|
||||
|
||||
def getLengthInBits(self, type):
|
||||
if 1 <= type and type < 10: # 1 - 9
|
||||
return {
|
||||
Mode.MODE_NUMBER: 10,
|
||||
Mode.MODE_ALPHA_NUM: 9,
|
||||
Mode.MODE_8BIT_BYTE: 8,
|
||||
Mode.MODE_KANJI: 8
|
||||
}[self.mode]
|
||||
|
||||
elif type < 27: # 10 - 26
|
||||
return {
|
||||
Mode.MODE_NUMBER: 12,
|
||||
Mode.MODE_ALPHA_NUM: 11,
|
||||
Mode.MODE_8BIT_BYTE: 16,
|
||||
Mode.MODE_KANJI: 10
|
||||
}[self.mode]
|
||||
|
||||
elif type < 41: # 27 - 40
|
||||
return {
|
||||
Mode.MODE_NUMBER: 14,
|
||||
Mode.MODE_ALPHA_NUM: 13,
|
||||
Mode.MODE_8BIT_BYTE: 16,
|
||||
Mode.MODE_KANJI: 12
|
||||
}[self.mode]
|
||||
|
||||
else:
|
||||
raise Exception('type:%s' % type)
|
||||
|
||||
class QRMath:
|
||||
|
||||
EXP_TABLE = None
|
||||
LOG_TABLE = None
|
||||
|
||||
@staticmethod
|
||||
def _init():
|
||||
|
||||
QRMath.EXP_TABLE = [0] * 256
|
||||
for i in range(256):
|
||||
QRMath.EXP_TABLE[i] = (1 << i if i < 8 else
|
||||
QRMath.EXP_TABLE[i - 4] ^ QRMath.EXP_TABLE[i - 5] ^
|
||||
QRMath.EXP_TABLE[i - 6] ^ QRMath.EXP_TABLE[i - 8])
|
||||
|
||||
QRMath.LOG_TABLE = [0] * 256
|
||||
for i in range(255):
|
||||
QRMath.LOG_TABLE[QRMath.EXP_TABLE[i] ] = i
|
||||
|
||||
@staticmethod
|
||||
def glog(n):
|
||||
if n < 1:
|
||||
raise Exception('log(%s)' % n)
|
||||
return QRMath.LOG_TABLE[n]
|
||||
|
||||
@staticmethod
|
||||
def gexp(n):
|
||||
while n < 0:
|
||||
n += 255
|
||||
while n >= 256:
|
||||
n -= 255
|
||||
return QRMath.EXP_TABLE[n]
|
||||
|
||||
# initialize statics
|
||||
QRMath._init()
|
||||
|
||||
class Polynomial:
|
||||
|
||||
def __init__(self, num, shift=0):
|
||||
offset = 0
|
||||
length = len(num)
|
||||
while offset < length and num[offset] == 0:
|
||||
offset += 1
|
||||
self.num = num[offset:] + [0] * shift
|
||||
|
||||
def get(self, index):
|
||||
return self.num[index]
|
||||
|
||||
def getLength(self):
|
||||
return len(self.num)
|
||||
|
||||
def __repr__(self):
|
||||
return ','.join( [str(self.get(i) )
|
||||
for i in range(self.getLength() ) ] )
|
||||
|
||||
def toLogString(self):
|
||||
return ','.join( [str(QRMath.glog(self.get(i) ) )
|
||||
for i in range(self.getLength() ) ] )
|
||||
|
||||
def multiply(self, e):
|
||||
num = [0] * (self.getLength() + e.getLength() - 1)
|
||||
for i in range(self.getLength() ):
|
||||
for j in range(e.getLength() ):
|
||||
num[i + j] ^= QRMath.gexp(QRMath.glog(self.get(i) ) +
|
||||
QRMath.glog(e.get(j) ) )
|
||||
return Polynomial(num)
|
||||
|
||||
def mod(self, e):
|
||||
if self.getLength() - e.getLength() < 0:
|
||||
return self
|
||||
ratio = QRMath.glog(self.get(0) ) - QRMath.glog(e.get(0) )
|
||||
num = self.num[:]
|
||||
for i in range(e.getLength() ):
|
||||
num[i] ^= QRMath.gexp(QRMath.glog(e.get(i) ) + ratio)
|
||||
return Polynomial(num).mod(e)
|
||||
|
||||
class RSBlock:
|
||||
|
||||
RS_BLOCK_TABLE = [
|
||||
|
||||
# L
|
||||
# M
|
||||
# Q
|
||||
# H
|
||||
|
||||
# 1
|
||||
[1, 26, 19],
|
||||
[1, 26, 16],
|
||||
[1, 26, 13],
|
||||
[1, 26, 9],
|
||||
|
||||
# 2
|
||||
[1, 44, 34],
|
||||
[1, 44, 28],
|
||||
[1, 44, 22],
|
||||
[1, 44, 16],
|
||||
|
||||
# 3
|
||||
[1, 70, 55],
|
||||
[1, 70, 44],
|
||||
[2, 35, 17],
|
||||
[2, 35, 13],
|
||||
|
||||
# 4
|
||||
[1, 100, 80],
|
||||
[2, 50, 32],
|
||||
[2, 50, 24],
|
||||
[4, 25, 9],
|
||||
|
||||
# 5
|
||||
[1, 134, 108],
|
||||
[2, 67, 43],
|
||||
[2, 33, 15, 2, 34, 16],
|
||||
[2, 33, 11, 2, 34, 12],
|
||||
|
||||
# 6
|
||||
[2, 86, 68],
|
||||
[4, 43, 27],
|
||||
[4, 43, 19],
|
||||
[4, 43, 15],
|
||||
|
||||
# 7
|
||||
[2, 98, 78],
|
||||
[4, 49, 31],
|
||||
[2, 32, 14, 4, 33, 15],
|
||||
[4, 39, 13, 1, 40, 14],
|
||||
|
||||
# 8
|
||||
[2, 121, 97],
|
||||
[2, 60, 38, 2, 61, 39],
|
||||
[4, 40, 18, 2, 41, 19],
|
||||
[4, 40, 14, 2, 41, 15],
|
||||
|
||||
# 9
|
||||
[2, 146, 116],
|
||||
[3, 58, 36, 2, 59, 37],
|
||||
[4, 36, 16, 4, 37, 17],
|
||||
[4, 36, 12, 4, 37, 13],
|
||||
|
||||
# 10
|
||||
[2, 86, 68, 2, 87, 69],
|
||||
[4, 69, 43, 1, 70, 44],
|
||||
[6, 43, 19, 2, 44, 20],
|
||||
[6, 43, 15, 2, 44, 16]
|
||||
]
|
||||
|
||||
def __init__(self, totalCount, dataCount):
|
||||
self.totalCount = totalCount
|
||||
self.dataCount = dataCount
|
||||
|
||||
def getDataCount(self):
|
||||
return self.dataCount
|
||||
|
||||
def getTotalCount(self):
|
||||
return self.totalCount
|
||||
|
||||
def __repr__(self):
|
||||
return ('(total=%s,data=%s)' % (self.totalCount, self.dataCount) )
|
||||
|
||||
@staticmethod
|
||||
def getRSBlocks(typeNumber, errorCorrectLevel):
|
||||
rsBlock = RSBlock.getRsBlockTable(typeNumber, errorCorrectLevel)
|
||||
length = len(rsBlock) // 3
|
||||
list = []
|
||||
for i in range(length):
|
||||
count = rsBlock[i * 3 + 0]
|
||||
totalCount = rsBlock[i * 3 + 1]
|
||||
dataCount = rsBlock[i * 3 + 2]
|
||||
list += [RSBlock(totalCount, dataCount)] * count
|
||||
return list
|
||||
|
||||
@staticmethod
|
||||
def getRsBlockTable(typeNumber, errorCorrectLevel):
|
||||
return {
|
||||
ErrorCorrectLevel.L:
|
||||
RSBlock.RS_BLOCK_TABLE[ (typeNumber - 1) * 4 + 0],
|
||||
ErrorCorrectLevel.M:
|
||||
RSBlock.RS_BLOCK_TABLE[ (typeNumber - 1) * 4 + 1],
|
||||
ErrorCorrectLevel.Q:
|
||||
RSBlock.RS_BLOCK_TABLE[ (typeNumber - 1) * 4 + 2],
|
||||
ErrorCorrectLevel.H:
|
||||
RSBlock.RS_BLOCK_TABLE[ (typeNumber - 1) * 4 + 3]
|
||||
}[errorCorrectLevel]
|
||||
|
||||
class BitBuffer:
|
||||
|
||||
def __init__(self, inclements=32):
|
||||
self.inclements = inclements
|
||||
self.buffer = [0] * self.inclements
|
||||
self.length = 0
|
||||
|
||||
def getBuffer(self):
|
||||
return self.buffer
|
||||
|
||||
def getLengthInBits(self):
|
||||
return self.length
|
||||
|
||||
def get(self, index):
|
||||
return ( (self.buffer[index // 8] >> (7 - index % 8) ) & 1) == 1
|
||||
|
||||
def putBit(self, bit):
|
||||
if self.length == len(self.buffer) * 8:
|
||||
self.buffer += [0] * self.inclements
|
||||
if bit:
|
||||
self.buffer[self.length // 8] |= (0x80 >> (self.length % 8) )
|
||||
self.length += 1
|
||||
|
||||
def put(self, num, length):
|
||||
for i in range(length):
|
||||
self.putBit( ( (num >> (length - i - 1) ) & 1) == 1)
|
||||
|
||||
def __repr__(self):
|
||||
return ''.join('1' if self.get(i) else '0'
|
||||
for i in range(self.getLengthInBits() ) )
|
||||
@@ -0,0 +1,120 @@
|
||||
# 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 FootprintWizardBase
|
||||
|
||||
# Additional import for QRCode
|
||||
# see https://github.com/kazuhikoarase/qrcode-generator/blob/master/python/qrcode.py
|
||||
import qrcode
|
||||
|
||||
class QRCodeWizard(FootprintWizardBase.FootprintWizard):
|
||||
GetName = lambda self: '2D Barcode QRCode'
|
||||
GetDescription = lambda self: 'QR Code'
|
||||
GetReferencePrefix = lambda self: 'QR***'
|
||||
GetValue = lambda self: self.module.Value().GetText()
|
||||
|
||||
def GenerateParameterList(self):
|
||||
self.AddParam("Barcode", "Pixel Width", self.uMM, 0.5, min_value=0.4)
|
||||
self.AddParam("Barcode", "Border", self.uInteger, 0)
|
||||
self.AddParam("Barcode", "Contents", self.uString, 'Example')
|
||||
self.AddParam("Barcode", "Negative", self.uBool, False)
|
||||
self.AddParam("Barcode", "Use SilkS layer", self.uBool, False)
|
||||
self.AddParam("Barcode", "Use Cu layer", self.uBool, True)
|
||||
self.AddParam("Caption", "Enabled", self.uBool, True)
|
||||
self.AddParam("Caption", "Height", self.uMM, 1.2)
|
||||
self.AddParam("Caption", "Thickness", self.uMM, 0.12)
|
||||
|
||||
|
||||
def CheckParameters(self):
|
||||
self.Barcode = str(self.parameters['Barcode']['Contents'])
|
||||
self.X = self.parameters['Barcode']['Pixel Width']
|
||||
self.negative = self.parameters['Barcode']['Negative']
|
||||
self.UseSilkS = self.parameters['Barcode']['Use SilkS layer']
|
||||
self.UseCu = self.parameters['Barcode']['Use Cu layer']
|
||||
self.border = int(self.parameters['Barcode']['Border'])
|
||||
self.textHeight = int(self.parameters['Caption']['Height'])
|
||||
self.module.Value().SetText(str(self.Barcode) )
|
||||
|
||||
# Build Qrcode
|
||||
self.qr = qrcode.QRCode()
|
||||
self.qr.setTypeNumber(4)
|
||||
# ErrorCorrectLevel: L = 7%, M = 15% Q = 25% H = 30%
|
||||
self.qr.setErrorCorrectLevel(qrcode.ErrorCorrectLevel.M)
|
||||
self.qr.addData(str(self.Barcode))
|
||||
self.qr.make()
|
||||
|
||||
def _drawPixel(self, xposition, yposition):
|
||||
# build a rectangular pad: as a dot
|
||||
pad = pcbnew.D_PAD(self.module)
|
||||
pad.SetSize(pcbnew.wxSize(self.X, self.X))
|
||||
pad.SetShape(pcbnew.PAD_SHAPE_RECT)
|
||||
pad.SetAttribute(pcbnew.PAD_ATTRIB_SMD)
|
||||
layerset = pcbnew.LSET()
|
||||
if self.UseCu:
|
||||
layerset.AddLayer(pcbnew.F_Cu)
|
||||
layerset.AddLayer(pcbnew.F_Mask)
|
||||
if self.UseSilkS:
|
||||
layerset.AddLayer(pcbnew.F_SilkS)
|
||||
pad.SetLayerSet( layerset )
|
||||
pad.SetPosition(pcbnew.wxPoint(xposition,yposition))
|
||||
pad.SetPadName("1")
|
||||
self.module.Add(pad)
|
||||
|
||||
|
||||
def BuildThisFootprint(self):
|
||||
if self.border >= 0:
|
||||
# Adding border: Create a new array larger than the self.qr.modules
|
||||
sz = self.qr.modules.__len__() + (self.border * 2)
|
||||
arrayToDraw = [ [ 0 for a in range(sz) ] for b in range(sz) ]
|
||||
lineposition = self.border
|
||||
for i in self.qr.modules:
|
||||
columnposition = self.border
|
||||
for j in i:
|
||||
arrayToDraw[lineposition][columnposition] = j
|
||||
columnposition += 1
|
||||
lineposition += 1
|
||||
else:
|
||||
# No border: using array as is
|
||||
arrayToDraw = self.qr.modules
|
||||
|
||||
# used many times...
|
||||
half_number_of_elements = arrayToDraw.__len__() / 2
|
||||
|
||||
# Center position of QrCode
|
||||
yposition = - int(half_number_of_elements * self.X)
|
||||
for line in arrayToDraw:
|
||||
xposition = - int(half_number_of_elements * self.X)
|
||||
for pixel in line:
|
||||
# Trust table for drawing a pixel
|
||||
# Negative is a boolean;
|
||||
# each pixel is a boolean (need to draw of not)
|
||||
# Negative | Pixel | Result
|
||||
# 0 | 0 | 0
|
||||
# 0 | 1 | 1
|
||||
# 1 | 0 | 1
|
||||
# 1 | 1 | 0
|
||||
# => Draw as Xor
|
||||
if self.negative != pixel: # Xor...
|
||||
self._drawPixel(xposition, yposition)
|
||||
xposition += self.X
|
||||
yposition += self.X
|
||||
#int((5 + half_number_of_elements) * self.X))
|
||||
textPosition = int((self.textHeight) + ((1 + half_number_of_elements) * self.X))
|
||||
self.module.Value().SetPosition(pcbnew.wxPoint(0, - textPosition))
|
||||
self.module.Reference().SetPosition(pcbnew.wxPoint(0, textPosition))
|
||||
self.module.Value().SetLayer(pcbnew.F_SilkS)
|
||||
|
||||
QRCodeWizard().register()
|
||||
@@ -17,7 +17,7 @@
|
||||
from __future__ import division
|
||||
import pcbnew
|
||||
|
||||
import HelpfulFootprintWizardPlugin as HFPW
|
||||
import FootprintWizardBase
|
||||
import PadArray as PA
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ class RowedGridArray(PA.PadGridArray):
|
||||
return x+1
|
||||
|
||||
|
||||
class RowedFootprint(HFPW.HelpfulFootprintWizardPlugin):
|
||||
class RowedFootprint(FootprintWizardBase.FootprintWizard):
|
||||
|
||||
pad_count_key = 'pad count'
|
||||
row_count_key = 'row count'
|
||||
@@ -50,31 +50,25 @@ class RowedFootprint(HFPW.HelpfulFootprintWizardPlugin):
|
||||
|
||||
def GenerateParameterList(self):
|
||||
# defaults for a DIP package
|
||||
self.AddParam("Pads", self.pad_count_key, self.uNatural, 24)
|
||||
self.AddParam("Pads", self.row_count_key, self.uNatural, 2)
|
||||
self.AddParam("Pads", self.pad_count_key, self.uInteger, 24)
|
||||
self.AddParam("Pads", self.row_count_key, self.uInteger, 2, min_value=1, max_value=2)
|
||||
|
||||
self.AddParam("Body", self.silkscreen_inside_key, self.uBool, False)
|
||||
self.AddParam("Body", self.outline_x_margin_key, self.uMM, 0.5)
|
||||
self.AddParam("Body", self.outline_y_margin_key, self.uMM, 0.5)
|
||||
|
||||
def CheckParameters(self):
|
||||
self.CheckParamInt("Pads", '*' + self.row_count_key, min_value=1, max_value=2)
|
||||
self.CheckParamInt(
|
||||
"Pads", '*' + self.pad_count_key,
|
||||
is_multiple_of=self.parameters["Pads"]['*' + self.row_count_key])
|
||||
|
||||
# can do this internally to parameter manager?
|
||||
self.CheckParamBool("Body", '*' + self.silkscreen_inside_key)
|
||||
self.CheckParam("Pads", self.pad_count_key, multiple=self.parameters['Pads'][self.row_count_key], info='Pads must be multiple of row count')
|
||||
|
||||
def BuildThisFootprint(self):
|
||||
pads = self.parameters["Pads"]
|
||||
body = self.parameters["Body"]
|
||||
num_pads = pads['*' + self.pad_count_key]
|
||||
num_pads = pads[self.pad_count_key]
|
||||
pad_length = pads[self.pad_length_key]
|
||||
pad_width = pads[self.pad_width_key]
|
||||
row_pitch = pads[self.row_spacing_key]
|
||||
pad_pitch = pads[self.pad_pitch_key]
|
||||
num_rows = pads['*' + self.row_count_key]
|
||||
num_rows = pads[self.row_count_key]
|
||||
|
||||
pads_per_row = num_pads // num_rows
|
||||
|
||||
@@ -96,7 +90,7 @@ class RowedFootprint(HFPW.HelpfulFootprintWizardPlugin):
|
||||
ssx_offset = -pad_width / 2 - body[self.outline_x_margin_key]
|
||||
ssy_offset = -pad_length / 2 - body[self.outline_y_margin_key]
|
||||
|
||||
if body['*' + self.silkscreen_inside_key]:
|
||||
if body[self.silkscreen_inside_key]:
|
||||
ssy_offset *= -1
|
||||
|
||||
ssx = -pin1_posX - ssx_offset
|
||||
@@ -110,8 +104,8 @@ class RowedFootprint(HFPW.HelpfulFootprintWizardPlugin):
|
||||
sizex = (ssx + cmargin) * 2
|
||||
sizey = (ssy + cmargin) * 2
|
||||
# round size to nearest 0.1mm, rectangle will thus land on a 0.05mm grid
|
||||
sizex = self.PutOnGridMM(sizex, 0.1)
|
||||
sizey = self.PutOnGridMM(sizey, 0.1)
|
||||
sizex = pcbnew.PutOnGridMM(sizex, 0.1)
|
||||
sizey = pcbnew.PutOnGridMM(sizey, 0.1)
|
||||
# set courtyard line thickness to the one defined in KLC
|
||||
self.draw.SetLineThickness(pcbnew.FromMM(0.05))
|
||||
self.draw.Box(0, 0, sizex, sizey)
|
||||
@@ -156,8 +150,8 @@ class SDIPWizard(RowedFootprint):
|
||||
|
||||
def GetValue(self):
|
||||
pads = self.parameters["Pads"]
|
||||
rows = pads['*' + self.row_count_key]
|
||||
pad_count = pads['*' + self.pad_count_key]
|
||||
rows = pads[self.row_count_key]
|
||||
pad_count = pads[self.pad_count_key]
|
||||
row_dist_mil = pcbnew.Iu2Mils(int(self.parameters["Pads"][self.row_spacing_key])) #int(self.parameters["Pads"][self.row_spacing_key] / 2.54 * 100)
|
||||
pad_shape = ""
|
||||
|
||||
@@ -185,7 +179,7 @@ class SDIPWizard(RowedFootprint):
|
||||
|
||||
def DrawBox(self, ssx, ssy):
|
||||
|
||||
if self.parameters["Pads"]['*' + self.row_count_key] == 2:
|
||||
if self.parameters["Pads"][self.row_count_key] == 2:
|
||||
|
||||
# ----------
|
||||
# |8 7 6 5 |
|
||||
@@ -208,7 +202,7 @@ class SDIPWizard(RowedFootprint):
|
||||
|
||||
#line between pin1 and pin2
|
||||
pad_pitch = self.parameters["Pads"][self.pad_pitch_key]
|
||||
pad_cnt = self.parameters["Pads"]['*' + self.pad_count_key]
|
||||
pad_cnt = self.parameters["Pads"][self.pad_count_key]
|
||||
line_x = ( pad_cnt/2 - 1) * pad_pitch
|
||||
self.draw.VLine(-line_x, -ssy, ssy * 2)
|
||||
|
||||
@@ -226,7 +220,7 @@ class SOICWizard(RowedFootprint):
|
||||
return "SOIC, MSOP, SSOP, TSSOP, etc, footprint wizard"
|
||||
|
||||
def GetValue(self):
|
||||
pad_count = self.parameters["Pads"]['*' + self.pad_count_key]
|
||||
pad_count = self.parameters["Pads"][self.pad_count_key]
|
||||
return "%s-%d" % ("SOIC", pad_count)
|
||||
|
||||
def GenerateParameterList(self):
|
||||
|
||||
@@ -24,10 +24,10 @@
|
||||
#
|
||||
|
||||
from pcbnew import *
|
||||
import HelpfulFootprintWizardPlugin as HFPW
|
||||
import FootprintWizardBase
|
||||
import pcbnew
|
||||
|
||||
|
||||
class TouchSliderWizard(HFPW.HelpfulFootprintWizardPlugin):
|
||||
class TouchSliderWizard(FootprintWizardBase.FootprintWizard):
|
||||
|
||||
def GetName(self):
|
||||
"""
|
||||
@@ -44,16 +44,23 @@ class TouchSliderWizard(HFPW.HelpfulFootprintWizardPlugin):
|
||||
return 'Capacitive Touch Slider wizard'
|
||||
|
||||
def GetValue(self):
|
||||
steps = int(self.parameters["Pads"]["*steps"])
|
||||
return "TS"+str(steps)
|
||||
return "TouchSlider-{s}_{x:g}x{y:g}mm".format(
|
||||
s = self.pads['steps'],
|
||||
x = pcbnew.ToMM(self.pads['length']),
|
||||
y = pcbnew.ToMM(self.pads['width'])
|
||||
)
|
||||
|
||||
def GenerateParameterList(self):
|
||||
self.AddParam("Pads", "steps", self.uNatural, 4)
|
||||
self.AddParam("Pads", "bands", self.uNatural, 2)
|
||||
self.AddParam("Pads", "steps", self.uInteger, 4, min_value=2)
|
||||
self.AddParam("Pads", "bands", self.uInteger, 2, min_value=1)
|
||||
self.AddParam("Pads", "width", self.uMM, 10)
|
||||
self.AddParam("Pads", "length", self.uMM, 50)
|
||||
self.AddParam("Pads", "clearance", self.uMM, 1)
|
||||
|
||||
@property
|
||||
def pads(self):
|
||||
return self.parameters['Pads']
|
||||
|
||||
# build a rectangular pad
|
||||
def smdRectPad(self,module,size,pos,name):
|
||||
pad = D_PAD(module)
|
||||
@@ -82,18 +89,8 @@ class TouchSliderWizard(HFPW.HelpfulFootprintWizardPlugin):
|
||||
|
||||
# This method checks the parameters provided to wizard and set errors
|
||||
def CheckParameters(self):
|
||||
prms = self.parameters["Pads"]
|
||||
steps = prms["*steps"]
|
||||
bands = prms["*bands"]
|
||||
|
||||
if steps < 1:
|
||||
self.parameter_errors["Pads"]["*steps"]="steps must be positive"
|
||||
if bands < 1:
|
||||
self.parameter_errors["Pads"]["*bands"]="bands must be positive"
|
||||
|
||||
touch_width = prms["width"]
|
||||
touch_length = prms["length"]
|
||||
touch_clearance = prms["clearance"]
|
||||
#TODO - implement custom checks
|
||||
pass
|
||||
|
||||
# The start pad is made of a rectangular pad plus a couple of
|
||||
# triangular pads facing tips on the middle/right of the first
|
||||
@@ -177,18 +174,18 @@ class TouchSliderWizard(HFPW.HelpfulFootprintWizardPlugin):
|
||||
# build the footprint from parameters
|
||||
# FIX ME: the X and Y position of the footprint can be better.
|
||||
def BuildThisFootprint(self):
|
||||
prm = self.parameters["Pads"]
|
||||
steps = int(prm["*steps"])
|
||||
bands = int(prm["*bands"])
|
||||
touch_width = prm["width"]
|
||||
touch_length = prm["length"]
|
||||
touch_clearance = prm["clearance"]
|
||||
|
||||
steps = self.pads["steps"]
|
||||
bands = self.pads["bands"]
|
||||
touch_width = self.pads["width"]
|
||||
touch_length = self.pads["length"]
|
||||
touch_clearance = self.pads["clearance"]
|
||||
|
||||
step_length = float(touch_length) / float(steps)
|
||||
|
||||
t_size = self.GetTextSize()
|
||||
w_text = self.draw.GetLineThickness()
|
||||
ypos = touch_width/(bands*2) + t_size/2 + w_text
|
||||
ypos = touch_width/2 + t_size/2 + w_text
|
||||
self.draw.Value(0, -ypos, t_size)
|
||||
ypos += t_size + w_text*2
|
||||
self.draw.Reference(0, -ypos, t_size)
|
||||
@@ -197,9 +194,13 @@ class TouchSliderWizard(HFPW.HelpfulFootprintWizardPlugin):
|
||||
self.module.SetAttributes(MOD_CMS)
|
||||
|
||||
# starting pad
|
||||
pos = wxPointMM(0,0)
|
||||
band_width = touch_width/bands
|
||||
|
||||
xpos = -0.5 * (steps - 1) * step_length
|
||||
ypos = -0.5 * (bands - 1) * band_width
|
||||
|
||||
pos = wxPointMM(pcbnew.ToMM(xpos), pcbnew.ToMM(ypos))
|
||||
|
||||
for b in range(bands):
|
||||
self.AddStrip(pos,steps,band_width,step_length,touch_clearance)
|
||||
pos += wxPoint(0,band_width)
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
|
||||
from __future__ import division
|
||||
import pcbnew as B
|
||||
|
||||
import HelpfulFootprintWizardPlugin
|
||||
import FootprintWizardBase
|
||||
|
||||
'''
|
||||
Created on Jan 16, 2015
|
||||
@@ -49,7 +48,7 @@ class Uss39:
|
||||
# Reformated text with start and end characters
|
||||
return reduce(lambda a1, a2: a1 + [0] + a2, [map(int, ptd[c]) for c in ("*%s*" % self.makePrintable(text))])
|
||||
|
||||
class Uss39Wizard(HelpfulFootprintWizardPlugin.HelpfulFootprintWizardPlugin):
|
||||
class Uss39Wizard(FootprintWizardBase.FootprintWizard):
|
||||
GetName = lambda self: 'BARCODE USS-39'
|
||||
GetDescription = lambda self: 'USS-39 Barcode'
|
||||
GetReferencePrefix = lambda self: 'BARCODE'
|
||||
@@ -61,18 +60,20 @@ class Uss39Wizard(HelpfulFootprintWizardPlugin.HelpfulFootprintWizardPlugin):
|
||||
self.AddParam("Barcode", "Height", self.uMM, 3.0)
|
||||
self.AddParam("Barcode", "Margin", self.uMM, 2.0)
|
||||
self.AddParam("Barcode", "Contents", self.uString, 'BARCODE')
|
||||
|
||||
self.AddParam("Caption", "Enabled", self.uBool, True)
|
||||
self.AddParam("Caption", "Height", self.uMM, 1.2)
|
||||
self.AddParam("Caption", "Thickness", self.uMM, 0.12)
|
||||
|
||||
def CheckParameters(self):
|
||||
|
||||
# Reset constants
|
||||
self.CourtyardLineWidth = B.FromMM(0.05)
|
||||
# Set bar height to the greater of 6.35mm or 0.15*L
|
||||
# Set quiet width to 10*X
|
||||
# User-defined parameters
|
||||
# Create barcode object
|
||||
self.Barcode = Uss39('=' + str(self.parameters['Barcode']['*Contents']))
|
||||
self.Barcode = Uss39('=' + str(self.parameters['Barcode']['Contents']))
|
||||
self.X = int(self.parameters['Barcode']['Pixel Width'])
|
||||
self.module.Value().SetText( str(self.Barcode) )
|
||||
self.C = len(str(self.Barcode))
|
||||
@@ -146,4 +147,4 @@ class Uss39Wizard(HelpfulFootprintWizardPlugin.HelpfulFootprintWizardPlugin):
|
||||
self.draw.Circle(0, 0, B.FromMM(0.25))
|
||||
self.module.Value().SetLayer(B.F_Fab)
|
||||
|
||||
Uss39Wizard().register()
|
||||
Uss39Wizard().register()
|
||||
@@ -17,52 +17,41 @@
|
||||
from __future__ import division
|
||||
import pcbnew
|
||||
|
||||
import HelpfulFootprintWizardPlugin as HFPW
|
||||
import FootprintWizardBase
|
||||
import PadArray as PA
|
||||
|
||||
|
||||
class RowedFootprint(HFPW.HelpfulFootprintWizardPlugin):
|
||||
|
||||
pad_count_key = '#pad count'
|
||||
line_count_key = '#line count'
|
||||
pad_vertical_size_key = 'pad vertical size'
|
||||
pad_horizontal_size_key = 'pad horizontal size'
|
||||
line_spacing_key = 'line spacing'
|
||||
pad_pitch_key = 'pad pitch'
|
||||
drill_size_key = 'drill size'
|
||||
|
||||
courtyard_x_margin_key = 'courtyard x margin'
|
||||
courtyard_y_margin_key = 'courtyard y margin'
|
||||
outline_x_margin_key = 'outline x margin'
|
||||
outline_y_margin_key = 'outline y margin'
|
||||
silkscreen_inside_key = 'silk screen inside'
|
||||
class RowedFootprint(FootprintWizardBase.FootprintWizard):
|
||||
|
||||
def GenerateParameterList(self):
|
||||
|
||||
# defaults for a ZIP package
|
||||
self.AddParam("Pads", self.pad_count_key, self.uNatural, 24)
|
||||
self.AddParam("Pads", self.line_count_key, self.uNatural, 2)
|
||||
self.AddParam("Body", self.silkscreen_inside_key, self.uBool, False)
|
||||
self.AddParam("Body", self.courtyard_x_margin_key, self.uMM, 1)
|
||||
self.AddParam("Body", self.courtyard_y_margin_key, self.uMM, 1)
|
||||
self.AddParam("Pads", "pad count", self.uInteger, 24)
|
||||
self.AddParam("Pads", "line count", self.uInteger, 2)
|
||||
|
||||
self.AddParam("Body", "silkscreen inside", self.uBool, False)
|
||||
self.AddParam("Body", "courtyard margin", self.uMM, 0.5, min_value=0.2)
|
||||
|
||||
@property
|
||||
def pads(self):
|
||||
return self.parameters['Pads']
|
||||
|
||||
@property
|
||||
def body(self):
|
||||
return self.parameters['Body']
|
||||
|
||||
def CheckParameters(self):
|
||||
self.CheckParamInt("Pads", '*' + self.pad_count_key)
|
||||
self.CheckParamInt("Pads", '*' + self.line_count_key)
|
||||
|
||||
# can do this internally to parameter manager?
|
||||
self.CheckParamBool("Body", '*' + self.silkscreen_inside_key)
|
||||
# TODO - implement custom checks
|
||||
pass
|
||||
|
||||
def BuildThisFootprint(self):
|
||||
pads = self.parameters["Pads"]
|
||||
body = self.parameters["Body"]
|
||||
|
||||
pad_count = pads['*' + self.pad_count_key]
|
||||
pad_Vsize = pads[self.pad_vertical_size_key]
|
||||
pad_Hsize = pads[self.pad_horizontal_size_key]
|
||||
line_pitch = pads[self.line_spacing_key]
|
||||
pad_pitch = pads[self.pad_pitch_key]
|
||||
line_count = pads['*' + self.line_count_key]
|
||||
pad_count = self.pads['pad count']
|
||||
pad_Vsize = self.pads['pad height']
|
||||
pad_Hsize = self.pads['pad width']
|
||||
line_pitch = self.pads['line spacing']
|
||||
pad_pitch = self.pads['pitch']
|
||||
line_count = self.pads['line count']
|
||||
|
||||
if line_count == 1:
|
||||
singleline = True
|
||||
@@ -74,12 +63,12 @@ class RowedFootprint(HFPW.HelpfulFootprintWizardPlugin):
|
||||
|
||||
array = PA.PadZGridArray(pad, pad_count, line_count, line_pitch, pad_pitch)
|
||||
array.AddPadsToModule(self.draw)
|
||||
|
||||
|
||||
# draw the Silk Screen
|
||||
pads_per_line = pad_count // line_count
|
||||
row_length = pad_pitch * (pads_per_line - 1) # fenceposts
|
||||
ssx_offset = pad_Hsize / 2 + body[self.outline_x_margin_key]
|
||||
ssy_offset = pad_Vsize / 2 + body[self.outline_y_margin_key]
|
||||
ssx_offset = pad_Hsize / 2 + self.body['outline x margin']
|
||||
ssy_offset = pad_Vsize / 2 + self.body['outline y margin']
|
||||
|
||||
pin1posX = pad_pitch * (pad_count - 1) / 2
|
||||
pin1posY = line_pitch * (line_count - 1) / 2
|
||||
@@ -91,7 +80,7 @@ class RowedFootprint(HFPW.HelpfulFootprintWizardPlugin):
|
||||
# body inside pads is possible only for 2 rows.
|
||||
# for other values, there is no room
|
||||
linew = self.draw.GetLineThickness()
|
||||
if body['*'+self.silkscreen_inside_key] and line_count == 2:
|
||||
if self.body['silkscreen inside'] and line_count == 2:
|
||||
cornery = pin1posY - ssy_offset
|
||||
if cornery < linew:
|
||||
cornery = linew
|
||||
@@ -99,15 +88,15 @@ class RowedFootprint(HFPW.HelpfulFootprintWizardPlugin):
|
||||
self.DrawBox(leftx*2, cornery*2)
|
||||
|
||||
# Courtyard
|
||||
cmarginx = body[self.courtyard_x_margin_key]
|
||||
cmarginy = body[self.courtyard_y_margin_key]
|
||||
cmarginx = self.body['courtyard margin']
|
||||
cmarginy = cmarginx
|
||||
self.draw.SetLayer(pcbnew.F_CrtYd)
|
||||
thick = self.draw.GetLineThickness()
|
||||
sizex = (pin1posX + cmarginx) * 2 + pad_Hsize + thick
|
||||
sizey = (pin1posY + cmarginy) * 2 + pad_Vsize + thick
|
||||
# round size to nearest 0.1mm, rectangle will thus land on a 0.05mm grid
|
||||
sizex = self.PutOnGridMM(sizex, 0.1)
|
||||
sizey = self.PutOnGridMM(sizey, 0.1)
|
||||
sizex = pcbnew.PutOnGridMM(sizex, 0.1)
|
||||
sizey = pcbnew.PutOnGridMM(sizey, 0.1)
|
||||
# set courtyard line thickness to the one defined in KLC
|
||||
self.draw.SetLineThickness(pcbnew.FromMM(0.05))
|
||||
self.draw.Box(0, 0, sizex, sizey)
|
||||
@@ -152,17 +141,17 @@ class ZIPWizard(RowedFootprint):
|
||||
def GenerateParameterList(self):
|
||||
RowedFootprint.GenerateParameterList(self)
|
||||
|
||||
self.AddParam("Pads", self.pad_pitch_key, self.uMM, 1.27)
|
||||
self.AddParam("Pads", self.pad_horizontal_size_key, self.uMM, 1.2)
|
||||
self.AddParam("Pads", self.pad_vertical_size_key, self.uMM, 2)
|
||||
self.AddParam("Pads", self.line_spacing_key, self.uMM, 2.54)
|
||||
self.AddParam("Pads", self.drill_size_key, self.uMM, 0.8)
|
||||
self.AddParam("Body", self.outline_x_margin_key, self.uMM, 1)
|
||||
self.AddParam("Body", self.outline_y_margin_key, self.uMM, 0.5)
|
||||
self.AddParam("Pads", "pitch", self.uMM, 1.27)
|
||||
self.AddParam("Pads", "pad width", self.uMM, 1.2)
|
||||
self.AddParam("Pads", "pad height", self.uMM, 2)
|
||||
self.AddParam("Pads", "line spacing", self.uMM, 2.54)
|
||||
self.AddParam("Pads", "drill size", self.uMM, 0.8)
|
||||
self.AddParam("Body", 'outline x margin', self.uMM, 1)
|
||||
self.AddParam("Body", 'outline y margin', self.uMM, 0.5)
|
||||
|
||||
def GetValue(self):
|
||||
rows = self.parameters["Pads"]['*' + self.line_count_key]
|
||||
pad_cnt = self.parameters["Pads"]['*' + self.pad_count_key]
|
||||
rows = self.pads['line count']
|
||||
pad_cnt = self.pads['pad count']
|
||||
|
||||
if rows == 1:
|
||||
name = "SIP"
|
||||
@@ -174,9 +163,9 @@ class ZIPWizard(RowedFootprint):
|
||||
return "%s-%d" % (name, pad_cnt)
|
||||
|
||||
def GetPad(self):
|
||||
pad_Vsize = self.parameters["Pads"][self.pad_vertical_size_key]
|
||||
pad_Hsize = self.parameters["Pads"][self.pad_horizontal_size_key]
|
||||
drill = self.parameters["Pads"][self.drill_size_key]
|
||||
pad_Vsize = self.pads['pad height']
|
||||
pad_Hsize = self.pads['pad width']
|
||||
drill = self.pads['drill size']
|
||||
return PA.PadMaker(self.module).THPad(
|
||||
pad_Vsize, pad_Hsize, drill, shape=pcbnew.PAD_SHAPE_OVAL)
|
||||
|
||||
@@ -192,23 +181,23 @@ class ZOICWizard(RowedFootprint):
|
||||
return "ZOIC, etc, Footprint Wizard"
|
||||
|
||||
def GetValue(self):
|
||||
return "%s-%d" % ("ZOIC", self.parameters["Pads"]['*' + self.pad_count_key])
|
||||
return "%s-%d" % ("ZOIC-", self.pads['pad count'])
|
||||
|
||||
def GenerateParameterList(self):
|
||||
RowedFootprint.GenerateParameterList(self)
|
||||
|
||||
#and override some of them
|
||||
self.AddParam("Pads", self.pad_pitch_key, self.uMM, 0.6)
|
||||
self.AddParam("Pads", self.pad_horizontal_size_key, self.uMM, 0.6)
|
||||
self.AddParam("Pads", self.pad_vertical_size_key, self.uMM, 1.8)
|
||||
self.AddParam("Pads", self.line_spacing_key, self.uMM, 5.2)
|
||||
self.AddParam("Pads", "pitch", self.uMM, 0.6)
|
||||
self.AddParam("Pads", "pad width", self.uMM, 0.6)
|
||||
self.AddParam("Pads", "pad height", self.uMM, 1.8)
|
||||
self.AddParam("Pads", "line spacing", self.uMM, 5.2)
|
||||
|
||||
self.AddParam("Body", self.outline_x_margin_key, self.uMM, 0.5)
|
||||
self.AddParam("Body", self.outline_y_margin_key, self.uMM, 1)
|
||||
self.AddParam("Body", "outline x margin", self.uMM, 0.5)
|
||||
self.AddParam("Body", "outline y margin", self.uMM, 1)
|
||||
|
||||
def GetPad(self):
|
||||
pad_Vsize = self.parameters["Pads"][self.pad_vertical_size_key]
|
||||
pad_Hsize = self.parameters["Pads"][self.pad_horizontal_size_key]
|
||||
pad_Vsize = self.pads['pad height']
|
||||
pad_Hsize = self.pads['pad width']
|
||||
return PA.PadMaker(self.module).SMDPad(
|
||||
pad_Vsize, pad_Hsize, shape=pcbnew.PAD_SHAPE_RECT)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user