2015-09-30 16:42:28 +00:00
|
|
|
# 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.
|
2014-10-28 19:43:12 +00:00
|
|
|
#
|
2015-09-30 16:42:28 +00:00
|
|
|
# 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.
|
2014-10-28 19:43:12 +00:00
|
|
|
#
|
2015-09-30 16:42:28 +00:00
|
|
|
# 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.
|
2014-10-28 19:43:12 +00:00
|
|
|
#
|
|
|
|
|
2015-09-30 16:42:28 +00:00
|
|
|
from __future__ import division
|
|
|
|
import pcbnew
|
2015-10-31 11:54:48 +00:00
|
|
|
|
2017-01-03 15:01:47 +00:00
|
|
|
import FootprintWizardBase
|
2012-05-05 20:18:47 +00:00
|
|
|
|
2017-01-03 15:01:47 +00:00
|
|
|
class FPC_FootprintWizard(FootprintWizardBase.FootprintWizard):
|
2013-07-29 07:33:56 +00:00
|
|
|
|
2015-09-30 16:42:28 +00:00
|
|
|
def GetName(self):
|
|
|
|
return "FPC (SMT connector)"
|
2013-03-17 01:18:09 +00:00
|
|
|
|
2015-09-30 16:42:28 +00:00
|
|
|
def GetDescription(self):
|
|
|
|
return "FPC (SMT connector) Footprint Wizard"
|
2013-03-17 01:18:09 +00:00
|
|
|
|
2015-09-30 16:42:28 +00:00
|
|
|
def GetValue(self):
|
2017-01-03 15:01:47 +00:00
|
|
|
pins = self.parameters["Pads"]["n"]
|
2015-09-30 16:42:28 +00:00
|
|
|
return "FPC_%d" % pins
|
2013-03-17 01:18:09 +00:00
|
|
|
|
2015-09-30 16:42:28 +00:00
|
|
|
def GenerateParameterList(self):
|
2017-01-03 15:01:47 +00:00
|
|
|
self.AddParam( "Pads", "n", self.uInteger, 40 )
|
2015-09-30 16:42:28 +00:00
|
|
|
self.AddParam( "Pads", "pitch", self.uMM, 0.5 )
|
|
|
|
self.AddParam( "Pads", "width", self.uMM, 0.25 )
|
|
|
|
self.AddParam( "Pads", "height", self.uMM, 1.6)
|
|
|
|
self.AddParam( "Shield", "shield_to_pad", self.uMM, 1.6 )
|
|
|
|
self.AddParam( "Shield", "from_top", self.uMM, 1.3 )
|
|
|
|
self.AddParam( "Shield", "width", self.uMM, 1.5 )
|
|
|
|
self.AddParam( "Shield", "height", self.uMM, 2 )
|
2013-03-17 01:18:09 +00:00
|
|
|
|
|
|
|
|
2015-09-30 16:42:28 +00:00
|
|
|
# build a rectangular pad
|
|
|
|
def smdRectPad(self,module,size,pos,name):
|
2020-11-14 01:06:05 +00:00
|
|
|
pad = pcbnew.PAD(module)
|
2015-09-30 16:42:28 +00:00
|
|
|
pad.SetSize(size)
|
|
|
|
pad.SetShape(pcbnew.PAD_SHAPE_RECT)
|
|
|
|
pad.SetAttribute(pcbnew.PAD_ATTRIB_SMD)
|
|
|
|
pad.SetLayerSet( pad.SMDMask() )
|
|
|
|
pad.SetPos0(pos)
|
|
|
|
pad.SetPosition(pos)
|
2017-08-11 09:22:13 +00:00
|
|
|
pad.SetName(name)
|
2015-09-30 16:42:28 +00:00
|
|
|
return pad
|
2013-03-17 01:18:09 +00:00
|
|
|
|
2015-09-30 16:42:28 +00:00
|
|
|
def CheckParameters(self):
|
2017-01-03 15:01:47 +00:00
|
|
|
#TODO implement custom parameter checking
|
|
|
|
pass
|
2015-09-30 16:42:28 +00:00
|
|
|
|
|
|
|
def BuildThisFootprint(self):
|
2012-05-10 20:49:07 +00:00
|
|
|
p = self.parameters
|
2017-01-03 15:01:47 +00:00
|
|
|
pad_count = int(p["Pads"]["n"])
|
2012-05-10 20:49:07 +00:00
|
|
|
pad_width = p["Pads"]["width"]
|
|
|
|
pad_height = p["Pads"]["height"]
|
|
|
|
pad_pitch = p["Pads"]["pitch"]
|
|
|
|
shl_width = p["Shield"]["width"]
|
|
|
|
shl_height = p["Shield"]["height"]
|
|
|
|
shl_to_pad = p["Shield"]["shield_to_pad"]
|
|
|
|
shl_from_top = p["Shield"]["from_top"]
|
2013-03-17 01:18:09 +00:00
|
|
|
|
2015-09-05 12:10:54 +00:00
|
|
|
offsetX = pad_pitch * ( pad_count-1 ) / 2
|
2015-09-30 16:42:28 +00:00
|
|
|
size_pad = pcbnew.wxSize( pad_width, pad_height )
|
|
|
|
size_shld = pcbnew.wxSize(shl_width, shl_height)
|
2015-10-29 17:35:52 +00:00
|
|
|
size_text = self.GetTextSize() # IPC nominal
|
2013-07-29 07:33:56 +00:00
|
|
|
|
2015-10-29 17:35:52 +00:00
|
|
|
# Gives a position and size to ref and value texts:
|
|
|
|
textposy = pad_height/2 + pcbnew.FromMM(1) + self.GetTextThickness()
|
2017-01-26 19:19:20 +00:00
|
|
|
angle_degree = 0.0
|
|
|
|
self.draw.Reference( 0, textposy, size_text, angle_degree )
|
2013-03-17 01:18:09 +00:00
|
|
|
|
2015-10-29 17:35:52 +00:00
|
|
|
textposy = textposy + size_text + self.GetTextThickness()
|
|
|
|
self.draw.Value( 0, textposy, size_text )
|
|
|
|
|
2012-05-05 20:18:47 +00:00
|
|
|
# create a pad array and add it to the module
|
2015-09-05 12:10:54 +00:00
|
|
|
for n in range ( 0, pad_count ):
|
2013-07-29 07:33:56 +00:00
|
|
|
xpos = pad_pitch*n - offsetX
|
2015-09-30 16:42:28 +00:00
|
|
|
pad = self.smdRectPad(self.module,size_pad, pcbnew.wxPoint(xpos,0),str(n+1))
|
|
|
|
self.module.Add(pad)
|
2013-03-17 01:18:09 +00:00
|
|
|
|
2012-05-05 20:18:47 +00:00
|
|
|
|
2014-03-27 17:45:05 +00:00
|
|
|
# Mechanical shield pads: left pad and right pad
|
2013-07-29 07:33:56 +00:00
|
|
|
xpos = -shl_to_pad-offsetX
|
2015-09-30 16:42:28 +00:00
|
|
|
pad_s0_pos = pcbnew.wxPoint(xpos,shl_from_top)
|
|
|
|
pad_s0 = self.smdRectPad(self.module, size_shld, pad_s0_pos, "0")
|
2015-09-05 12:10:54 +00:00
|
|
|
xpos = (pad_count-1) * pad_pitch+shl_to_pad - offsetX
|
2015-09-30 16:42:28 +00:00
|
|
|
pad_s1_pos = pcbnew.wxPoint(xpos,shl_from_top)
|
|
|
|
pad_s1 = self.smdRectPad(self.module, size_shld, pad_s1_pos, "0")
|
2013-03-17 01:18:09 +00:00
|
|
|
|
2015-09-30 16:42:28 +00:00
|
|
|
self.module.Add(pad_s0)
|
|
|
|
self.module.Add(pad_s1)
|
2012-05-05 20:18:47 +00:00
|
|
|
|
2015-10-29 17:35:52 +00:00
|
|
|
# add footprint outline
|
2018-12-10 11:13:12 +00:00
|
|
|
self.draw.SetLineThickness( pcbnew.FromMM( 0.12 ) ) #Default per KLC F5.1 as of 12/2018
|
2016-02-11 15:02:37 +00:00
|
|
|
linewidth = self.draw.GetLineThickness()
|
2015-10-29 17:35:52 +00:00
|
|
|
margin = linewidth
|
2014-03-27 17:45:05 +00:00
|
|
|
|
|
|
|
# upper line
|
|
|
|
posy = -pad_height/2 - linewidth/2 - margin
|
|
|
|
xstart = - pad_pitch*0.5-offsetX
|
2015-09-05 12:10:54 +00:00
|
|
|
xend = pad_pitch * pad_count + xstart;
|
2018-12-10 13:22:53 +00:00
|
|
|
min_y = posy
|
|
|
|
max_y = posy
|
2015-10-29 17:35:52 +00:00
|
|
|
self.draw.Line( xstart, posy, xend, posy )
|
2013-07-29 07:33:56 +00:00
|
|
|
|
2014-03-27 17:45:05 +00:00
|
|
|
# lower line
|
|
|
|
posy = pad_height/2 + linewidth/2 + margin
|
2018-12-10 13:22:53 +00:00
|
|
|
max_y = max( max_y, posy )
|
2015-10-29 17:35:52 +00:00
|
|
|
self.draw.Line(xstart, posy, xend, posy)
|
2013-07-29 07:33:56 +00:00
|
|
|
|
2014-03-27 17:45:05 +00:00
|
|
|
# around left mechanical pad (the outline around right pad is mirrored/y axix)
|
|
|
|
yend = pad_s0_pos.y + shl_height/2 + margin
|
2018-12-10 13:22:53 +00:00
|
|
|
max_y = max( max_y, yend )
|
2015-10-29 17:35:52 +00:00
|
|
|
self.draw.Line(xstart, posy, xstart, yend)
|
|
|
|
self.draw.Line(-xstart, posy, -xstart, yend)
|
|
|
|
|
2014-03-27 17:45:05 +00:00
|
|
|
posy = yend
|
|
|
|
xend = pad_s0_pos.x - (shl_width/2 + linewidth + margin*2)
|
2018-12-10 13:22:53 +00:00
|
|
|
max_x = -xend
|
2015-10-29 17:35:52 +00:00
|
|
|
self.draw.Line(xstart, posy, xend, posy)
|
|
|
|
|
|
|
|
# right pad side
|
|
|
|
self.draw.Line(-xstart, posy, -xend, yend)
|
|
|
|
|
2016-02-18 14:29:30 +00:00
|
|
|
# set SMD attribute
|
2020-11-14 12:38:44 +00:00
|
|
|
self.module.SetAttributes(pcbnew.PAD_ATTRIB_SMD)
|
2017-01-03 17:04:35 +00:00
|
|
|
|
2015-10-29 17:35:52 +00:00
|
|
|
# vertical segment at left of the pad
|
2014-03-27 17:45:05 +00:00
|
|
|
xstart = xend
|
|
|
|
yend = posy - (shl_height + linewidth + margin*2)
|
2015-10-29 17:35:52 +00:00
|
|
|
self.draw.Line(xstart, posy, xend, yend)
|
2014-03-27 17:45:05 +00:00
|
|
|
|
2015-10-29 17:35:52 +00:00
|
|
|
# right pad side
|
|
|
|
self.draw.Line(-xstart, posy, -xend, yend)
|
2018-12-10 13:22:53 +00:00
|
|
|
max_y = max( max_y, posy )
|
|
|
|
min_y = min( min_y, yend )
|
2015-10-29 17:35:52 +00:00
|
|
|
|
|
|
|
# horizontal segment above the pad
|
2014-03-27 17:45:05 +00:00
|
|
|
xstart = xend
|
|
|
|
xend = - pad_pitch*0.5-offsetX
|
|
|
|
posy = yend
|
2015-10-29 17:35:52 +00:00
|
|
|
self.draw.Line(xstart, posy, xend, yend)
|
|
|
|
|
|
|
|
# right pad side
|
|
|
|
self.draw.Line(-xstart, posy,-xend, yend)
|
2014-03-27 17:45:05 +00:00
|
|
|
|
2015-10-29 17:35:52 +00:00
|
|
|
# vertical segment above the pad
|
2014-03-27 17:45:05 +00:00
|
|
|
xstart = xend
|
|
|
|
yend = -pad_height/2 - linewidth/2 - margin
|
2018-12-10 13:22:53 +00:00
|
|
|
min_y = min( min_y, yend )
|
2015-10-29 17:35:52 +00:00
|
|
|
self.draw.Line(xstart, posy, xend, yend)
|
|
|
|
|
|
|
|
# right pad side
|
|
|
|
self.draw.Line(-xstart, posy, -xend, yend)
|
2020-09-02 13:45:20 +00:00
|
|
|
|
2018-12-10 13:22:53 +00:00
|
|
|
# Courtyard
|
|
|
|
self.draw.SetLayer(pcbnew.F_CrtYd)
|
|
|
|
max_x = max_x + linewidth + margin
|
|
|
|
min_y = min_y - linewidth - margin
|
2020-09-02 13:45:20 +00:00
|
|
|
max_y = max_y + linewidth + margin
|
|
|
|
|
2018-12-10 13:22:53 +00:00
|
|
|
# round size to nearest 0.1mm, rectangle will thus land on a 0.05mm grid
|
|
|
|
max_x = pcbnew.PutOnGridMM(max_x, 0.05)
|
|
|
|
max_y = pcbnew.PutOnGridMM(max_y, 0.05)
|
|
|
|
min_y = pcbnew.PutOnGridMM(min_y, 0.05)
|
2020-09-02 13:45:20 +00:00
|
|
|
|
2018-12-10 13:22:53 +00:00
|
|
|
# set courtyard line thickness to the one defined in KLC
|
|
|
|
self.draw.SetLineThickness(pcbnew.FromMM(0.05))
|
|
|
|
self.draw.Line( -max_x, min_y, max_x, min_y )
|
|
|
|
self.draw.Line( max_x, min_y, max_x, max_y )
|
|
|
|
self.draw.Line( -max_x, max_y, max_x, max_y )
|
|
|
|
self.draw.Line( -max_x, min_y, -max_x, max_y )
|
2013-07-29 07:33:56 +00:00
|
|
|
|
2015-09-30 16:42:28 +00:00
|
|
|
FPC_FootprintWizard().register()
|