add bt_player
This commit is contained in:
11
kicad_plugins/rf_tools_wizards/__init__.py
Normal file
11
kicad_plugins/rf_tools_wizards/__init__.py
Normal file
@@ -0,0 +1,11 @@
|
||||
# pcbnew loads this folder as a package using import
|
||||
# thus __init__.py (this file) is executed
|
||||
# We import the plugin class here and register it to pcbnew
|
||||
|
||||
from . import uwArcPrimitive_wizard
|
||||
from . import uwMitered_wizard
|
||||
from . import uwTaper_wizard
|
||||
|
||||
|
||||
|
||||
|
||||
193
kicad_plugins/rf_tools_wizards/uwArcPrimitive_wizard.py
Normal file
193
kicad_plugins/rf_tools_wizards/uwArcPrimitive_wizard.py
Normal file
@@ -0,0 +1,193 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
# This python script wizard creates an arc track for microwave applications
|
||||
# Author easyw
|
||||
# taskkill -im pcbnew.exe /f & C:\KiCad-v5-nightly\bin\pcbnew
|
||||
|
||||
from __future__ import division
|
||||
|
||||
import math, cmath
|
||||
|
||||
from pcbnew import *
|
||||
import pcbnew
|
||||
import FootprintWizardBase
|
||||
|
||||
|
||||
class uwArcPrimitive_wizard(FootprintWizardBase.FootprintWizard):
|
||||
|
||||
def GetName(self):
|
||||
return "uW Arc Pad"
|
||||
|
||||
def GetDescription(self):
|
||||
return "uW Arc Pad Footprint Wizard"
|
||||
|
||||
def GenerateParameterList(self):
|
||||
|
||||
self.AddParam("Corner", "width", self.uMM, 1.319)
|
||||
self.AddParam("Corner", "radius", self.uMM, 5.0, min_value=0, designator='r', hint="Arc radius")
|
||||
self.AddParam("Corner", "angle", self.uDegrees, 90, designator='a')
|
||||
self.AddParam("Corner", "square_end", self.uBool, False)
|
||||
self.AddParam("Corner", "solder_clearance", self.uMM, 0.0)
|
||||
self.AddParam("Corner", "linear", self.uBool, False)
|
||||
|
||||
def CheckParameters(self):
|
||||
|
||||
pads = self.parameters['Corner']
|
||||
|
||||
|
||||
def GetValue(self):
|
||||
name = "{0:.2f}_{1:0.2f}_{2:.0f}".format(pcbnew.ToMM(self.parameters["Corner"]["width"]),pcbnew.ToMM(self.parameters["Corner"]["radius"]),(self.parameters["Corner"]["angle"]))
|
||||
if not self.parameters["Corner"]["linear"]:
|
||||
pref = "uwArc"
|
||||
else:
|
||||
pref = "uwLine"
|
||||
if self.parameters["Corner"]["square_end"]:
|
||||
pref += "R"
|
||||
return pref + "%s" % name
|
||||
|
||||
def GetReferencePrefix(self):
|
||||
if not self.parameters["Corner"]["linear"]:
|
||||
pref = "uwA"
|
||||
else:
|
||||
pref = "uwL"
|
||||
#if self.parameters["Corner"]["rectangle"]:
|
||||
# pref += "R"
|
||||
return pref + "***"
|
||||
|
||||
# build a custom pad
|
||||
def smdCustomArcPad(self, module, size, pos, rad, name, angle_D, layer, ln, solder_clearance):
|
||||
if hasattr(pcbnew, 'D_PAD'):
|
||||
pad = D_PAD(module)
|
||||
else:
|
||||
pad = PAD(module)
|
||||
## NB pads must be the same size and have the same center
|
||||
pad.SetSize(size)
|
||||
#pad.SetSize(pcbnew.wxSize(size[0]/5,size[1]/5))
|
||||
pad.SetShape(PAD_SHAPE_CUSTOM) #PAD_RECT)
|
||||
pad.SetAttribute(PAD_ATTRIB_SMD) #PAD_SMD)
|
||||
#pad.SetDrillSize (0.)
|
||||
#Set only the copper layer without mask
|
||||
#since nothing is mounted on these pads
|
||||
pad.SetPos0(pos)
|
||||
pad.SetPosition(pos)
|
||||
pad.SetPadName(name)
|
||||
#pad.Rotate(pos, angle)
|
||||
pad.SetAnchorPadShape(PAD_SHAPE_CIRCLE) #PAD_SHAPE_RECT)
|
||||
if solder_clearance > 0:
|
||||
pad.SetLocalSolderMaskMargin(solder_clearance)
|
||||
pad.SetLayerSet(pad.ConnSMDMask())
|
||||
else:
|
||||
pad.SetLayerSet( LSET(layer) )
|
||||
|
||||
if not ln:
|
||||
pad.AddPrimitive(pcbnew.wxPoint(0,rad), pcbnew.wxPoint(0,0), int(angle_D*10), (size[0]))
|
||||
else:
|
||||
pad.AddPrimitive(pcbnew.wxPoint(0,0), pcbnew.wxPoint(rad,0), (size[0]))
|
||||
return pad
|
||||
|
||||
def smdPad(self,module,size,pos,name,ptype,angle_D,layer,solder_clearance,offs=None):
|
||||
if hasattr(pcbnew, 'D_PAD'):
|
||||
pad = D_PAD(module)
|
||||
else:
|
||||
pad = PAD(module)
|
||||
pad.SetSize(size)
|
||||
pad.SetShape(ptype) #PAD_SHAPE_RECT PAD_SHAPE_OVAL PAD_SHAPE_TRAPEZOID PAD_SHAPE_CIRCLE
|
||||
# PAD_ATTRIB_CONN PAD_ATTRIB_SMD
|
||||
pad.SetAttribute(PAD_ATTRIB_SMD)
|
||||
if solder_clearance > 0:
|
||||
pad.SetLocalSolderMaskMargin(solder_clearance)
|
||||
pad.SetLayerSet(pad.ConnSMDMask())
|
||||
else:
|
||||
pad.SetLayerSet( LSET(layer) )
|
||||
#pad.SetDrillSize (0.)
|
||||
#pad.SetLayerSet(pad.ConnSMDMask())
|
||||
pad.SetPos0(pos)
|
||||
pad.SetPosition(pos)
|
||||
#pad.SetOrientationDegrees(90-angle_D/10)
|
||||
pad.SetOrientationDegrees(angle_D)
|
||||
if offs is not None:
|
||||
pad.SetOffset(offs)
|
||||
pad.SetName(name)
|
||||
return pad
|
||||
|
||||
def BuildThisFootprint(self):
|
||||
|
||||
pads = self.parameters['Corner']
|
||||
|
||||
radius = pads['radius'] #outline['diameter'] / 2
|
||||
width = pads['width']
|
||||
sold_clear = pads['solder_clearance']
|
||||
line = pads['linear']
|
||||
|
||||
angle_deg = float(pads["angle"]) #*10)
|
||||
angle = math.radians(angle_deg) #/10) #To radians
|
||||
sign = 1.
|
||||
if angle < 0:
|
||||
sign = -1.
|
||||
|
||||
pos = pcbnew.wxPoint(0,0)
|
||||
offset1 = pcbnew.wxPoint(-sign*width/2,0)
|
||||
offset2 = pcbnew.wxPoint(0,0)
|
||||
module = self.module
|
||||
size_pad = pcbnew.wxSize(width, width)
|
||||
#size_pad = pcbnew.wxSize(width/5, width/5)
|
||||
module.Add(self.smdCustomArcPad(module, size_pad, pcbnew.wxPoint(0,0), radius, "1", (angle_deg), F_Cu, line, sold_clear))
|
||||
size_pad = pcbnew.wxSize(width, width)
|
||||
end_coord = (radius) * cmath.exp(math.radians(angle_deg-90)*1j)
|
||||
if pads['square_end'] or angle_deg == 0 or radius == 0:
|
||||
if not line:
|
||||
## NB pads must be the same size and have the same center
|
||||
module.Add(self.smdPad(module, size_pad, pcbnew.wxPoint(0,0), "1", PAD_SHAPE_RECT,0,F_Cu,sold_clear,offset1))
|
||||
else:
|
||||
module.Add(self.smdPad(module, size_pad, pcbnew.wxPoint(0,0), "1", PAD_SHAPE_RECT,0,F_Cu,sold_clear))
|
||||
if not line:
|
||||
#pos = pcbnew.wxPoint(end_coord.real+(sign*width/2)*math.cos(angle),end_coord.imag+(sign*width/2)*math.sin(angle)+radius)
|
||||
pos = pcbnew.wxPoint(end_coord.real,end_coord.imag+radius)
|
||||
module.Add(self.smdPad(module, size_pad, pos, "1", PAD_SHAPE_RECT,90-angle_deg,F_Cu,sold_clear,wxPoint(0,(sign*width/2))))
|
||||
#*math.sin(math.pi/2-angle),(sign*width/2)*math.cos(math.pi/2-angle))))
|
||||
else:
|
||||
pos = pcbnew.wxPoint(radius,0) #+width/2,0)
|
||||
module.Add(self.smdPad(module, size_pad, pos, "1", PAD_SHAPE_RECT,0,F_Cu,sold_clear))
|
||||
else:
|
||||
## NB pads must be the same size and have the same center
|
||||
#size_pad = pcbnew.wxSize(width/5, width/5)
|
||||
size_pad = pcbnew.wxSize(width, width)
|
||||
if not line:
|
||||
pos = pcbnew.wxPoint(end_coord.real,end_coord.imag+radius)
|
||||
else:
|
||||
pos = pcbnew.wxPoint(radius,0)
|
||||
module.Add(self.smdPad(module, size_pad, pos, "1", PAD_SHAPE_CIRCLE,0,F_Cu,sold_clear))
|
||||
|
||||
# Text size
|
||||
text_size = self.GetTextSize() # IPC nominal
|
||||
thickness = self.GetTextThickness()
|
||||
textposy = self.draw.GetLineThickness()/2 + self.GetTextSize()/2 + thickness #+ outline['margin']
|
||||
self.draw.Reference( 0, -textposy-width, text_size )
|
||||
if not line:
|
||||
self.draw.Value( 0, radius+textposy+width, text_size )
|
||||
else:
|
||||
self.draw.Value( 0, textposy+width, text_size )
|
||||
# set SMD attribute
|
||||
# set SMD attribute
|
||||
if hasattr(pcbnew, 'MOD_VIRTUAL'):
|
||||
module.SetAttributes(pcbnew.MOD_VIRTUAL)
|
||||
else:
|
||||
module.SetAttributes(pcbnew.FP_EXCLUDE_FROM_BOM | pcbnew.FP_EXCLUDE_FROM_POS_FILES)
|
||||
__version__ = 1.7
|
||||
self.buildmessages += ("version: {:.1f}".format(__version__))
|
||||
|
||||
uwArcPrimitive_wizard().register()
|
||||
352
kicad_plugins/rf_tools_wizards/uwMitered_wizard.py
Normal file
352
kicad_plugins/rf_tools_wizards/uwMitered_wizard.py
Normal file
@@ -0,0 +1,352 @@
|
||||
# This python script wizard creates a mitered bend for microwave applications
|
||||
# https://lists.launchpad.net/kicad-developers/msg17996.html
|
||||
# Author Henrik Forsten & easyw
|
||||
# improved pads using Primitive pads, single net node
|
||||
|
||||
from __future__ import division
|
||||
import FootprintWizardBase
|
||||
|
||||
import pcbnew
|
||||
from pcbnew import *
|
||||
import math
|
||||
|
||||
class UWMiterFootprintWizard(FootprintWizardBase.FootprintWizard):
|
||||
def GetName(self):
|
||||
return "uW Mitered Bend"
|
||||
|
||||
def GetDescription(self):
|
||||
return "Mitered Bend Footprint Wizard"
|
||||
|
||||
def GenerateParameterList(self):
|
||||
self.AddParam("Corner", "width", self.uMM, 1.31968)
|
||||
self.AddParam("Corner", "height", self.uMM, 1.57)
|
||||
self.AddParam("Corner", "*angle", self.uDegrees, 90)
|
||||
self.AddParam("Corner", "solder_clearance", self.uMM, 0.0)
|
||||
|
||||
# class UWMiterFootprintWizard(FootprintWizardBase.FootprintWizard):
|
||||
# def __init__(self):
|
||||
# FootprintWizardBase.FootprintWizard.__init__(self)
|
||||
# self.name = "uW Mitered Bend"
|
||||
# self.description = "Mitered Bend Footprint Wizard"
|
||||
# self.parameters = {
|
||||
# "Corner":{
|
||||
# "width": FromMM(0.34),
|
||||
# "height": FromMM(0.17),
|
||||
# "*angle": 90,
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# self.ClearErrors()
|
||||
|
||||
# build a rectangular pad
|
||||
def smdRectPad(self, module, size, pos, name, angle, layer, solder_clearance):
|
||||
if hasattr(pcbnew, 'D_PAD'):
|
||||
pad = D_PAD(module)
|
||||
else:
|
||||
pad = PAD(module)
|
||||
pad.SetSize(size)
|
||||
pad.SetShape(PAD_SHAPE_RECT) #PAD_RECT)
|
||||
pad.SetAttribute(PAD_ATTRIB_SMD) #PAD_SMD)
|
||||
#Set only the copper layer without mask
|
||||
#since nothing is mounted on these pads
|
||||
pad.SetLayerSet( LSET(F_Cu) )
|
||||
pad.SetPos0(pos)
|
||||
pad.SetPosition(pos)
|
||||
pad.SetPadName(name)
|
||||
pad.Rotate(pos, angle)
|
||||
if solder_clearance > 0:
|
||||
pad.SetLocalSolderMaskMargin(solder_clearance)
|
||||
pad.SetLayerSet(pad.ConnSMDMask())
|
||||
else:
|
||||
pad.SetLayerSet( LSET(layer) )
|
||||
#Set clearance to small value, because
|
||||
#pads can be very close together.
|
||||
#If distance is smaller than clearance
|
||||
#DRC doesn't allow routing the pads
|
||||
pad.SetLocalClearance(1)
|
||||
return pad
|
||||
|
||||
# build a custom pad
|
||||
def smdCustomPolyPad(self, module, size, pos, name, vpoints, layer, solder_clearance):
|
||||
if hasattr(pcbnew, 'D_PAD'):
|
||||
pad = D_PAD(module)
|
||||
else:
|
||||
pad = PAD(module)
|
||||
## NB pads must be the same size and have the same center
|
||||
pad.SetSize(size)
|
||||
#pad.SetSize(pcbnew.wxSize(size[0]/5,size[1]/5))
|
||||
pad.SetShape(PAD_SHAPE_CUSTOM) #PAD_RECT)
|
||||
pad.SetAttribute(PAD_ATTRIB_SMD) #PAD_SMD)
|
||||
#pad.SetDrillSize (0.)
|
||||
#Set only the copper layer without mask
|
||||
#since nothing is mounted on these pads
|
||||
#pad.SetPos0(wxPoint(0,0)) #pos)
|
||||
#pad.SetPosition(wxPoint(0,0)) #pos)
|
||||
pad.SetPos0(pos)
|
||||
pad.SetPosition(pos)
|
||||
#pad.SetOffset(pos)
|
||||
pad.SetPadName(name)
|
||||
#pad.Rotate(pos, angle)
|
||||
pad.SetAnchorPadShape(PAD_SHAPE_RECT) #PAD_SHAPE_CIRCLE) #PAD_SHAPE_RECT)
|
||||
if solder_clearance > 0:
|
||||
pad.SetLocalSolderMaskMargin(solder_clearance)
|
||||
pad.SetLayerSet(pad.ConnSMDMask())
|
||||
else:
|
||||
pad.SetLayerSet( LSET(layer) )
|
||||
|
||||
if hasattr(pcbnew, 'D_PAD'):
|
||||
pad.AddPrimitive(vpoints,0) # (size[0]))
|
||||
else:
|
||||
pad.AddPrimitivePoly(vpoints, 0, True) # (size[0]))
|
||||
|
||||
return pad
|
||||
|
||||
def Polygon(self, points, layer):
|
||||
"""
|
||||
Draw a polygon through specified points
|
||||
"""
|
||||
import pcbnew
|
||||
|
||||
polygon = pcbnew.EDGE_MODULE(self.module)
|
||||
polygon.SetWidth(0) #Disables outline
|
||||
|
||||
polygon.SetLayer(layer)
|
||||
polygon.SetShape(pcbnew.S_POLYGON)
|
||||
|
||||
polygon.SetPolyPoints(points)
|
||||
|
||||
self.module.Add(polygon)
|
||||
|
||||
|
||||
# This method checks the parameters provided to wizard and set errors
|
||||
def CheckParameters(self):
|
||||
p = self.parameters
|
||||
width = p["Corner"]["width"]
|
||||
height = p["Corner"]["height"]
|
||||
angle = p["Corner"]["*angle"]
|
||||
|
||||
errors = []
|
||||
if (width<0):
|
||||
errors.append("Width has invalid value")
|
||||
if width/height < 0.25:
|
||||
errors.append("Too small width to height ratio")
|
||||
if angle > 90:
|
||||
errors.append("Too large angle")
|
||||
if angle < 0:
|
||||
errors.append("Angle must be positive")
|
||||
errors = ', '.join(errors)
|
||||
print (errors)
|
||||
return errors == ""
|
||||
|
||||
def bilinear_interpolation(self, x, y, points):
|
||||
'''http://stackoverflow.com/questions/8661537/how-to-perform-bilinear-interpolation-in-python
|
||||
Interpolate (x,y) from values associated with four points.
|
||||
|
||||
The four points are a list of four triplets: (x, y, value).
|
||||
The four points can be in any order. They should form a rectangle.
|
||||
|
||||
>>> bilinear_interpolation(12, 5.5,
|
||||
... [(10, 4, 100),
|
||||
... (20, 4, 200),
|
||||
... (10, 6, 150),
|
||||
... (20, 6, 300)])
|
||||
165.0
|
||||
|
||||
'''
|
||||
# See formula at: http://en.wikipedia.org/wiki/Bilinear_interpolation
|
||||
|
||||
points = sorted(points) # order points by x, then by y
|
||||
(x1, y1, q11), (_x1, y2, q12), (x2, _y1, q21), (_x2, _y2, q22) = points
|
||||
|
||||
return (q11 * (x2 - x) * (y2 - y) +
|
||||
q21 * (x - x1) * (y2 - y) +
|
||||
q12 * (x2 - x) * (y - y1) +
|
||||
q22 * (x - x1) * (y - y1)
|
||||
) / ((x2 - x1) * (y2 - y1) + 0.0)
|
||||
|
||||
def OptimalMiter(self, w, h, angle):
|
||||
"""Calculate optimal miter by interpolating from table.
|
||||
https://awrcorp.com/download/faq/english/docs/Elements/MBENDA.htm
|
||||
"""
|
||||
wh = w/h
|
||||
whs = [0.5, 1.0, 2.0]
|
||||
angles = [0, 30, 60, 90, 120]
|
||||
table = [
|
||||
[0, 12, 45, 75, 98],
|
||||
[0, 19, 41, 63, 92],
|
||||
[0, 7, 31, 56, 79]
|
||||
]
|
||||
for i, x in enumerate(whs):
|
||||
if x > wh:
|
||||
break
|
||||
for j, y in enumerate(angles):
|
||||
if y > angle:
|
||||
break
|
||||
i = min(i-1,1)
|
||||
j = min(j-1,3)
|
||||
px = lambda ii,jj: (whs[ii],angles[jj],table[ii][jj])
|
||||
x1 = px(i,j)
|
||||
x2 = px(i+1,j)
|
||||
y1 = px(i,j+1)
|
||||
y2 = px(i+1,j+1)
|
||||
return self.bilinear_interpolation(wh, angle, [x1,x2,y1,y2])/100.0
|
||||
|
||||
# build the footprint from parameters
|
||||
#def BuildThisFootprint(self):
|
||||
def BuildFootprint(self):
|
||||
|
||||
if hasattr(pcbnew, 'MODULE'):
|
||||
module = MODULE(None) # create a new module
|
||||
else:
|
||||
module = FOOTPRINT(None) # create a new module
|
||||
#module = self.module
|
||||
self.module = module
|
||||
self.buildmessages = ""
|
||||
|
||||
if not self.CheckParameters():
|
||||
return
|
||||
|
||||
p = self.parameters
|
||||
width = p["Corner"]["width"]
|
||||
height = p["Corner"]["height"]
|
||||
angle_deg = float(p["Corner"]["*angle"])
|
||||
angle = angle_deg*0.0174532925 #To radians
|
||||
sold_clear = p["Corner"]['solder_clearance']
|
||||
#reference and value
|
||||
#text_size = self.GetTextSize() # IPC nominal
|
||||
|
||||
textposy = width + FromMM(1)
|
||||
size_text = wxSize( FromMM( 0.6), FromMM( 0.5) )
|
||||
|
||||
module.name = "'uwm_{0:.2f}_{1:0.2f}_{2:.0f}'".format(ToMM(width),ToMM(height),angle_deg)
|
||||
|
||||
#module.SetReference("uwm_{0:.2f}_{1:0.2f}_{2:.0f}".format(ToMM(width),ToMM(height),angle_deg))
|
||||
module.SetReference("uwM***") # give it a default value
|
||||
module.Reference().SetPos0(wxPoint(0, textposy))
|
||||
module.Reference().SetPosition(module.Reference().GetPos0())
|
||||
module.Reference().SetTextSize( size_text )
|
||||
if hasattr(module.Reference(), 'SetThickness'):
|
||||
module.Reference().SetThickness(FromMM(0.125))
|
||||
else:
|
||||
module.Reference().SetTextThickness(FromMM(0.125))
|
||||
module.Reference().SetVisible(True)
|
||||
|
||||
textposy = textposy + FromMM(1)
|
||||
#module.SetValue("Val***") # give it a default value
|
||||
module.SetValue("uwM_{0:.2f}_{1:0.2f}_{2:.0f}".format(ToMM(width),ToMM(height),angle_deg))
|
||||
module.Value().SetPos0( wxPoint(0, textposy) )
|
||||
module.Value().SetPosition(module.Value().GetPos0())
|
||||
module.Value().SetTextSize( size_text )
|
||||
module.Value().SetVisible(False) #0)
|
||||
|
||||
# fpid = FPID(self.module.GetReference()) #the name in library
|
||||
# module.SetFPID( fpid )
|
||||
|
||||
#Calculate the miter
|
||||
w = width
|
||||
|
||||
#Width of the corner from edge of the corner to inside corner
|
||||
corner_width = ToMM(w)/math.cos(angle/2)
|
||||
|
||||
#Get proportion of width to cut
|
||||
cut = self.OptimalMiter(width, height, angle_deg)
|
||||
cut_pc = cut
|
||||
print ("Cut: {0:.2f}%".format(cut*100))
|
||||
|
||||
#Distance from uncut outside corner point to point 7
|
||||
cut = FromMM(cut*corner_width/math.cos((math.pi-angle)/2))
|
||||
|
||||
#Distance between points 2 and 3 and points 3 and 4
|
||||
#Minimum of w/2 to satisfy DRC, otherwise pads are too close
|
||||
#and track connected to other pad overlaps the other one.
|
||||
#Rounded trace end can also stick out of the cut area
|
||||
#if a is too small.
|
||||
a = max(cut-width*math.tan(angle/2),w/2)
|
||||
|
||||
#Distance between points 3 and 4
|
||||
x34 = a*math.sin(angle)
|
||||
y34 = a*math.cos(angle)
|
||||
#Distance between points 4 and 5
|
||||
x45 = width*math.cos(angle)
|
||||
y45 = width*math.sin(angle)
|
||||
|
||||
# 1 2
|
||||
#8 +--+
|
||||
# | |3
|
||||
#7 \ --+ 4
|
||||
# \ |
|
||||
# \--+ 5
|
||||
# 6
|
||||
|
||||
# maui extension of polygon
|
||||
#points = [
|
||||
# (0,0-w/2),
|
||||
# (w,0-w/2),
|
||||
# (w,a),
|
||||
# (w+x34+w/2*math.sin(angle),a+y34+w/2*math.cos(angle)),
|
||||
# (w+x34-x45+w/2*math.sin(angle),a+y34+y45+w/2*math.cos(angle)),
|
||||
# (cut*math.sin(angle),a+width*math.tan(angle/2)+cut*math.cos(angle)),
|
||||
# (0,a+width*math.tan(angle/2)-cut),
|
||||
# (0,0-w/2)]
|
||||
points = [
|
||||
(0-w/2,0-w/2+w/2),
|
||||
(w-w/2,0-w/2+w/2),
|
||||
(w-w/2,a+w/2),
|
||||
(w+x34+w/2*math.sin(angle)-w/2,a+y34+w/2*math.cos(angle)+w/2),
|
||||
(w+x34-x45+w/2*math.sin(angle)-w/2,a+y34+y45+w/2*math.cos(angle)+w/2),
|
||||
(cut*math.sin(angle)-w/2,a+width*math.tan(angle/2)+cut*math.cos(angle)+w/2),
|
||||
(0-w/2,a+width*math.tan(angle/2)-cut+w/2),
|
||||
(0-w/2,0-w/2+w/2)]
|
||||
|
||||
#Last two points can be equal
|
||||
if points[-2] == points[-1]:
|
||||
points = points[:-1]
|
||||
|
||||
points = [wxPoint(*point) for point in points]
|
||||
vpoints = wxPoint_Vector(points)
|
||||
#self.Polygon(points, F_Cu)
|
||||
|
||||
#Create pads
|
||||
pad_l = width/2 #10 allowing big track to join the fp
|
||||
size_pad = wxSize(width,pad_l)
|
||||
|
||||
#module.Add(self.smdRectPad(module, size_pad, wxPoint(width/2,-pad_l/2), "1", 0))
|
||||
layer = F_Cu; # sold_clear = 0
|
||||
module.Add(self.smdCustomPolyPad(module, size_pad, wxPoint(width/2,-pad_l/2), "1", vpoints, layer,sold_clear))
|
||||
# smdCustomPolyPad(self, module, size, pos, name, points, layer, solder_clearance):
|
||||
size_pad = wxSize(pad_l,width)
|
||||
|
||||
#Halfway between points 4 and 5
|
||||
posx = ((w+x34) + (w+x34-x45))/2
|
||||
posy = ((a+y34) + (a+y34+y45))/2
|
||||
|
||||
#Position pad so that pad edge touches polygon edge
|
||||
posx += (pad_l/2)*math.sin(angle)
|
||||
posy += (pad_l/2)*math.cos(angle)+w/4
|
||||
size_pad = wxSize(pad_l, width)
|
||||
#solder clearance added only to polygon
|
||||
module.Add(self.smdRectPad(module, size_pad, wxPoint(posx,posy), "1", (angle_deg-90)*10,layer,0.0))
|
||||
# moving anchor to center of first pad
|
||||
module.MoveAnchorPosition(wxPoint(-width/2,pad_l/2))
|
||||
# set SMD attribute
|
||||
# set SMD attribute
|
||||
if hasattr(pcbnew, 'MOD_VIRTUAL'):
|
||||
module.SetAttributes(pcbnew.MOD_VIRTUAL)
|
||||
else:
|
||||
module.SetAttributes(pcbnew.FP_EXCLUDE_FROM_BOM | pcbnew.FP_EXCLUDE_FROM_POS_FILES)
|
||||
self.buildmessages = (
|
||||
"Building new {name} footprint with the following parameters:\n\n"
|
||||
.format(name=module.name))
|
||||
self.buildmessages += ("Track Width: {0:.4f}mm\n".format(ToMM(width)))
|
||||
self.buildmessages += ("PCB Height: {0:.4f}mm\n".format(ToMM(height)))
|
||||
self.buildmessages += ("Angle: {:.1f}deg\n\n".format(angle_deg))
|
||||
self.buildmessages += ("Cut: {0:.2f}%\n".format(cut_pc*100))
|
||||
__version__ = 1.6
|
||||
self.buildmessages += ("version: {:.1f}".format(__version__))
|
||||
|
||||
|
||||
# create our footprint wizard
|
||||
uwmiter_wizard = UWMiterFootprintWizard()
|
||||
|
||||
# register it into pcbnew
|
||||
uwmiter_wizard.register()
|
||||
210
kicad_plugins/rf_tools_wizards/uwTaper_wizard.py
Normal file
210
kicad_plugins/rf_tools_wizards/uwTaper_wizard.py
Normal file
@@ -0,0 +1,210 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
# This python script wizard creates an arc track for microwave applications
|
||||
# Author easyw
|
||||
# taskkill -im pcbnew.exe /f & C:\KiCad-v5-nightly\bin\pcbnew
|
||||
|
||||
from __future__ import division
|
||||
|
||||
import math, cmath
|
||||
|
||||
from pcbnew import *
|
||||
import pcbnew
|
||||
import FootprintWizardBase
|
||||
|
||||
|
||||
class uwTaper_wizard(FootprintWizardBase.FootprintWizard):
|
||||
|
||||
def GetName(self):
|
||||
return "uW Taper Pad"
|
||||
|
||||
def GetDescription(self):
|
||||
return "uW Taper Pad Footprint Wizard"
|
||||
|
||||
def GenerateParameterList(self):
|
||||
|
||||
self.AddParam("Taper", "P1 width", self.uMM, 0.5, min_value=0, hint="Pad 1 width")
|
||||
self.AddParam("Taper", "P1 height", self.uMM, 0.5, min_value=0, hint="Pad 1 height")
|
||||
self.AddParam("Taper", "P2 width", self.uMM, 1.0, min_value=0, hint="Pad 2 width")
|
||||
self.AddParam("Taper", "P2 height", self.uMM, 1.0, min_value=0, hint="Pad 2 height")
|
||||
self.AddParam("Taper", "P2 vert offset", self.uMM, 0.0, hint="Pad 2 vertical offset")
|
||||
self.AddParam("Taper", "length", self.uMM, 3.0, min_value=0, hint="length")
|
||||
self.AddParam("Taper", "solder_clearance", self.uMM, 0.0, min_value=0, hint="Solder Clearance")
|
||||
|
||||
def CheckParameters(self):
|
||||
|
||||
pads = self.parameters['Taper']
|
||||
|
||||
|
||||
def GetValue(self):
|
||||
name = "{0:.2f}_{1:0.2f}_{2:.2f}_{3:.2f}_{4:.2f}".format(pcbnew.ToMM(self.parameters["Taper"]["P1 width"]),\
|
||||
pcbnew.ToMM(self.parameters["Taper"]["P1 height"]),pcbnew.ToMM(self.parameters["Taper"]["P2 width"]),\
|
||||
pcbnew.ToMM(self.parameters["Taper"]["P2 height"]),pcbnew.ToMM(self.parameters["Taper"]["length"]))
|
||||
return "uwT" + "%s" % name
|
||||
|
||||
def GetReferencePrefix(self):
|
||||
return "uwT" + "***"
|
||||
|
||||
# build a custom pad
|
||||
def smdCustomPolyPad(self, module, size, pos, name, vpoints, layer, solder_clearance):
|
||||
if hasattr(pcbnew, 'D_PAD'):
|
||||
pad = D_PAD(module)
|
||||
else:
|
||||
pad = PAD(module)
|
||||
#pad = PAD(module)
|
||||
## NB pads must be the same size and have the same center
|
||||
pad.SetSize(size)
|
||||
#pad.SetSize(pcbnew.wxSize(size[0]/5,size[1]/5))
|
||||
pad.SetShape(PAD_SHAPE_CUSTOM) #PAD_RECT)
|
||||
pad.SetAttribute(PAD_ATTRIB_SMD) #PAD_SMD)
|
||||
#pad.SetDrillSize (0.)
|
||||
#Set only the copper layer without mask
|
||||
#since nothing is mounted on these pads
|
||||
#pad.SetPos0(wxPoint(0,0)) #pos)
|
||||
#pad.SetPosition(wxPoint(0,0)) #pos)
|
||||
pad.SetPos0(pos)
|
||||
pad.SetPosition(pos)
|
||||
#pad.SetOffset(pos)
|
||||
pad.SetPadName(name)
|
||||
#pad.Rotate(pos, angle)
|
||||
pad.SetAnchorPadShape(PAD_SHAPE_RECT) #PAD_SHAPE_CIRCLE) #PAD_SHAPE_RECT)
|
||||
if solder_clearance > 0:
|
||||
pad.SetLocalSolderMaskMargin(solder_clearance)
|
||||
pad.SetLayerSet(pad.ConnSMDMask())
|
||||
else:
|
||||
pad.SetLayerSet( LSET(layer) )
|
||||
|
||||
if hasattr(pcbnew, 'D_PAD'):
|
||||
pad.AddPrimitive(vpoints,0) # (size[0]))
|
||||
else:
|
||||
pad.AddPrimitivePoly(vpoints, 0, True) # (size[0]))
|
||||
return pad
|
||||
|
||||
def smdPad(self,module,size,pos,name,ptype,angle_D,layer,solder_clearance,offs=None):
|
||||
if hasattr(pcbnew, 'D_PAD'):
|
||||
pad = D_PAD(module)
|
||||
else:
|
||||
pad = PAD(module)
|
||||
pad.SetSize(size)
|
||||
pad.SetShape(ptype) #PAD_SHAPE_RECT PAD_SHAPE_OVAL PAD_SHAPE_TRAPEZOID PAD_SHAPE_CIRCLE
|
||||
# PAD_ATTRIB_CONN PAD_ATTRIB_SMD
|
||||
pad.SetAttribute(PAD_ATTRIB_SMD)
|
||||
if solder_clearance > 0:
|
||||
pad.SetLocalSolderMaskMargin(solder_clearance)
|
||||
pad.SetLayerSet(pad.ConnSMDMask())
|
||||
else:
|
||||
pad.SetLayerSet( LSET(layer) )
|
||||
#pad.SetDrillSize (0.)
|
||||
#pad.SetLayerSet(pad.ConnSMDMask())
|
||||
pad.SetPos0(pos)
|
||||
pad.SetPosition(pos)
|
||||
#pad.SetOrientationDegrees(90-angle_D/10)
|
||||
pad.SetOrientationDegrees(angle_D)
|
||||
if offs is not None:
|
||||
pad.SetOffset(offs)
|
||||
pad.SetName(name)
|
||||
return pad
|
||||
|
||||
def Polygon(self, points, layer):
|
||||
"""
|
||||
Draw a polygon through specified points
|
||||
"""
|
||||
import pcbnew
|
||||
|
||||
polygon = pcbnew.EDGE_MODULE(self.module)
|
||||
polygon.SetWidth(0) #Disables outline
|
||||
|
||||
polygon.SetLayer(layer)
|
||||
polygon.SetShape(pcbnew.S_POLYGON)
|
||||
|
||||
polygon.SetPolyPoints(points)
|
||||
|
||||
self.module.Add(polygon)
|
||||
|
||||
def BuildThisFootprint(self):
|
||||
|
||||
pads = self.parameters['Taper']
|
||||
|
||||
width1 = pads['P1 width']
|
||||
width2 = pads['P2 width']
|
||||
height1 = pads['P1 height']
|
||||
height2 = pads['P2 height']
|
||||
length = pads['length']
|
||||
p2vof = pads['P2 vert offset']
|
||||
sold_clear = pads['solder_clearance']
|
||||
w1=width1;w2=width2;
|
||||
h1=height1;h2=height2;
|
||||
|
||||
pos = pcbnew.wxPoint(0,0)
|
||||
offset1 = pcbnew.wxPoint(0,0)
|
||||
#offset2 = pcbnew.wxPoint(length+w1/2,0)
|
||||
offset2 = pcbnew.wxPoint(0,0)
|
||||
module = self.module
|
||||
# 1 2 3 4
|
||||
# +--+
|
||||
# / |
|
||||
# / |
|
||||
#9 +---+ |
|
||||
# | + + |
|
||||
#8 +---+ |
|
||||
# \ |
|
||||
# \ |
|
||||
# +--+
|
||||
# 7 6 5
|
||||
points = [
|
||||
(-w1/2,-h1/2),
|
||||
(w1/2,-h1/2),
|
||||
(w1/2+length-w2/2,-h2/2-p2vof),
|
||||
(w1/2+length+w2/2,-h2/2-p2vof),
|
||||
(w1/2+length+w2/2,h2/2-p2vof),
|
||||
(w1/2+length-w2/2,h2/2-p2vof),
|
||||
(w1/2,h1/2),
|
||||
(-w1/2,h1/2),
|
||||
]
|
||||
#Last two points can be equal
|
||||
if points[-2] == points[-1]:
|
||||
points = points[:-1]
|
||||
points = [wxPoint(*point) for point in points]
|
||||
vpoints = wxPoint_Vector(points)
|
||||
# self.Polygon(points, F_Cu)
|
||||
|
||||
size_pad = pcbnew.wxSize(width1, height1)
|
||||
#module.Add(self.smdPad(module, size_pad, pcbnew.wxPoint(0,0), "1", PAD_SHAPE_RECT,0,F_Cu,sold_clear,offset1))
|
||||
module.Add(self.smdCustomPolyPad(module, size_pad, wxPoint(0,0), "1", vpoints,F_Cu,sold_clear))
|
||||
|
||||
size_pad = pcbnew.wxSize(width2, height2)
|
||||
#solder clearance added only to polygon
|
||||
module.Add(self.smdPad(module, size_pad, pcbnew.wxPoint(length+w1/2,0-p2vof), "1", PAD_SHAPE_RECT,0,F_Cu,0.0,offset2))
|
||||
|
||||
# Text size
|
||||
text_size = self.GetTextSize() # IPC nominal
|
||||
thickness = self.GetTextThickness()
|
||||
textposy = self.draw.GetLineThickness()/2 + self.GetTextSize()/2 + thickness #+ outline['margin']
|
||||
height = max(height1,height2)
|
||||
self.draw.Reference( 0+length/2, -textposy-height/2, text_size )
|
||||
self.draw.Value( 0+length/2, textposy+height/2+text_size/2, text_size )
|
||||
# set SMD attribute
|
||||
if hasattr(pcbnew, 'MOD_VIRTUAL'):
|
||||
module.SetAttributes(pcbnew.MOD_VIRTUAL)
|
||||
else:
|
||||
module.SetAttributes(pcbnew.FP_EXCLUDE_FROM_BOM | pcbnew.FP_EXCLUDE_FROM_POS_FILES)
|
||||
# module.SetAttributes(pcbnew.MOD_VIRTUAL)
|
||||
# module.SetAttributes(pcbnew.FP_EXCLUDE_FROM_BOM | pcbnew.FP_EXCLUDE_FROM_POS_FILES)
|
||||
__version__ = 1.5
|
||||
self.buildmessages += ("version: {:.1f}".format(__version__))
|
||||
|
||||
uwTaper_wizard().register()
|
||||
Reference in New Issue
Block a user