delorie.com/archives/browse.cgi   search  
Mail Archives: geda-user/2017/08/13/21:17:18

X-Authentication-Warning: delorie.com: mail set sender to geda-user-bounces using -f
X-Recipient: geda-user AT delorie DOT com
Subject: Re: [geda-user] QFN24_EP (0.65 pitch) footprint?
To: geda-user AT delorie DOT com
References: <3b07341c-041d-1e0a-4cfe-f96698c4285c AT neurotica DOT com>
From: "John Griessen (john AT ecosensory DOT com) [via geda-user AT delorie DOT com]" <geda-user AT delorie DOT com>
Message-ID: <622b5b46-4656-b963-72c6-303e6c90e842@ecosensory.com>
Date: Sun, 13 Aug 2017 20:14:59 -0500
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101
Thunderbird/52.2.1
MIME-Version: 1.0
In-Reply-To: <3b07341c-041d-1e0a-4cfe-f96698c4285c@neurotica.com>
Reply-To: geda-user AT delorie DOT com
Errors-To: nobody AT delorie DOT com
X-Mailing-List: geda-user AT delorie DOT com
X-Unsubscribes-To: listserv AT delorie DOT com

No,

but here's a script to generate a qfn49 with 0.5mm pitch that you could adapt...

I put some features for pcb-rnd which handles cutouts as easily as positive mask areas,
so it might have some features not in line with mainline PCB.

run it like this:

./qfn48_smallpaste.py > qfn48_smallpaste.fp


-- 
John Griessen -- building field gear for biologists
Ecosensory  Austin TX  ecosensory.com


===================================qfn48_smallpaste.py===================================
#!/usr/bin/python
# Copyright 2016 by Bdale Garbee, 2017 by John Griessen.  GPLv2
#
# Program to emit PCB footprint for UFQPN48  package used by STM32F401CE
# Pad[x y x y 1000 3 ...] x, y footprint coords are relative to footprint center.
# PCB y coordinate is going *DOWN* the page...it can fool you if expecting Y up.
EdgePadHeelSquare = 6.20	# inside edge of pads to opposite inside edge distance.
EdgePadWidth = 0.28			# Pad metal width.
NumEdgePads = 48		# Integer number of pads around edge of QFN.
EdgePadSoldermaskOpen = 0.58		# width of gap in soldermask or resist over pad
EdgePadHeelSoldermaskOpen = 0.32		# width of gap in soldermask or resist over pad
EdgePadClearance = 0.57		# width of gap between copper and pad.
EdgePadLength = 0.55		# Distance from end to end of pad.
EdgePadHeelLength = 0.4 	# Length end to end of pad heel (rounded inner part).
PadSpacing = 0.50
NumCoreGridDiv = 5			# Symmetry needs an odd number grid around zero.
ViaSize = .635			# Via 25 mils diameter (.635mm dia.)
ViaDrillSize = .381		# Via drill hole 15 mils diameter (.381mm dia.)
CoreGridSize = 5.4		# Grid zone of soldermask openings and paste dots.
CenterPadSquare = 5.60		# Pad lines start EdgePadWidth/2 outside this box.
CenterPadClearance = 0.9	# width of gap between copper and pad.
SilkWidth = 0.26
CoreGridSquare = CoreGridSize/NumCoreGridDiv  	# Size of squares with vias, paste dots..
CenterPasteShrink = 0.16	# Paste is smaller than Pad by CenterPasteShrink * 2.
CenterPasteWidth = CoreGridSquare - (2 * CenterPasteShrink) # Paste is smaller.
EdgePasteShrink = 0.06		# Paste is smaller than Pad by EdgePasteShrink * 2.
EdgePasteWidth = EdgePadWidth - (2 * EdgePasteShrink)
EdgePadHeelStart = (EdgePadHeelSquare/2) + (EdgePadWidth/2)
EdgePadHeelEnd = (EdgePadHeelSquare/2)  + EdgePadHeelLength
EdgePadStart =  (EdgePadHeelSquare/2) + EdgePadHeelLength
EdgePadEnd =  EdgePadHeelSquare/2 + EdgePadLength - EdgePadWidth/2
PadRowStartCenter = (NumEdgePads/4 - 1) * PadSpacing/2
PadGridSize = (NumCoreGridDiv -1)/2	# Odd number cols, rows around zero.



import sys

# we're going to use the 1/100 of a mil fundamental unit form
def mm2mils100( mm ):
	return int( mm / 25.4 * 1000.0 * 100.0 + 0.5 )

print '# author: Bdale Garbee, John Griessen'
print '# email: john AT cibolo DOT com'
print '# dist-license: GPL 2'
print '# use-license: unlimited'
print '# mm2mils100(CenterPasteWidth) =  ' , mm2mils100(CenterPasteWidth), CenterPasteWidth
print '# EdgePadHeelStart =  ' , mm2mils100(EdgePadHeelStart), EdgePadHeelStart
print '# EdgePadHeelEnd =  ' , mm2mils100(EdgePadHeelEnd), EdgePadHeelEnd
print '# EdgePadStart =  ' , mm2mils100(EdgePadStart), EdgePadStart
print '# EdgePadEnd =  ' , mm2mils100(EdgePadEnd), EdgePadEnd

print 'Element[0x0 "UFQFPN48" "U?" "" 0 0 17000 -17000 0 100 0x0]'
print "("

# center pad under the chip -- usually needs thermal or current vias
print '   Pad[',\
  	mm2mils100(0), \
	mm2mils100(0), \
  	mm2mils100(0), \
	mm2mils100(0), \
	mm2mils100(CenterPadSquare), \
	mm2mils100(CenterPadClearance), \
  	0, \
	'"%i"' % (NumEdgePads+1),  '"%i"' %  (NumEdgePads+1),  '"square,nopaste"]'

# vias in the center pad -- center is zero, (python range doesn't include final integer)
for viarow in range (-PadGridSize/2,(PadGridSize/2)+1):
   for viacol in range (-PadGridSize/2,(PadGridSize/2)+1):
     print '   Pin[',\
	mm2mils100(2 * viacol * CoreGridSquare), \
  	mm2mils100(2 * viarow * CoreGridSquare), \
	mm2mils100(ViaSize), \
	2500, \
   	0, \
   	mm2mils100(ViaDrillSize), \
	'"%i"' % (NumEdgePads+1),  '"%i"' %  (NumEdgePads+1), ' 0x0002]'

# break pad under chip into a grid to control the resist and paste masks
for viarow in range (-2, 3):
   for viacol in range (-2, 3):
     if (viarow in (-2, 0, 2)) and (viacol in (-2, 0, 2)):
       # copper sub-square with resist over vias
       print '   Pad[',\
	mm2mils100(viacol * CoreGridSquare), \
  	mm2mils100(viarow * CoreGridSquare), \
	mm2mils100(viacol * CoreGridSquare), \
  	mm2mils100(viarow * CoreGridSquare), \
	mm2mils100(CoreGridSquare), \
	0, \
  	0, \
	'"%i"' % (NumEdgePads+1),  '"%i"' %  (NumEdgePads+1),  ' "square,nopaste"]'
     else:
       # copper sub-square without resist
       print '   Pad[',\
	mm2mils100(viacol * CoreGridSquare), \
  	mm2mils100(viarow * CoreGridSquare), \
	mm2mils100(viacol * CoreGridSquare), \
  	mm2mils100(viarow * CoreGridSquare), \
	mm2mils100(CoreGridSquare), \
	0, \
	mm2mils100(CoreGridSquare+0.02), \
	'"%i"' % (NumEdgePads+1),  '"%i"' %  (NumEdgePads+1), ' "square,nopaste"]'
       # copper dot to control paste mask generation
       print '   Pad[',\
	mm2mils100(viacol * CoreGridSquare), \
  	mm2mils100(viarow * CoreGridSquare), \
	mm2mils100(viacol * CoreGridSquare), \
  	mm2mils100(viarow * CoreGridSquare), \
   	mm2mils100(CenterPasteWidth), \
	0, \
	mm2mils100(CoreGridSquare+0.02), \
	'"%i"' % (NumEdgePads+1),  '"%i"' %  (NumEdgePads+1), ' "square"]'

for edgepadnum in range (1, (NumEdgePads/4)+1):
     # edgepads stepping horizontally
     hpd = mm2mils100(-PadRowStartCenter + (edgepadnum - 1) * PadSpacing), \
	mm2mils100(-EdgePadHeelStart), \
  	mm2mils100(-PadRowStartCenter + (edgepadnum - 1) * PadSpacing), \
	mm2mils100(-EdgePadHeelEnd), \
	mm2mils100(EdgePadWidth), \
	mm2mils100(EdgePadClearance), \
	mm2mils100(EdgePadHeelSoldermaskOpen), \
	'"%i"' % ((NumEdgePads*3/4)+1-edgepadnum), '"%i"' % ((NumEdgePads*3/4)+1-edgepadnum)

     #full metal pad heels define the < NumEdgePads*3/4 row:
     print '   Pad[', hpd[0], hpd[1], hpd[2], hpd[3], hpd[4], hpd[5], \
     hpd[6], hpd[7] , hpd[8], '"nopaste"]'

     #full metal pad toes define the < NumEdgePads*3/4 row:
     print '   Pad[', hpd[0], mm2mils100(-EdgePadStart),  hpd[2], \
	mm2mils100(-EdgePadEnd),  hpd[4], hpd[5], mm2mils100(EdgePadSoldermaskOpen), hpd[7] , hpd[8], '"square,nopaste"]'

     #solderpaste pad heels define the < NumEdgePads*3/4 row:
     print '   Pad[', hpd[0], hpd[1], hpd[2], hpd[3], \
     mm2mils100(EdgePasteWidth), hpd[5], hpd[6], hpd[7] , hpd[8], '""]'

     #solderpaste pad toes define the < NumEdgePads*3/4 row:
     print '   Pad[', hpd[0], mm2mils100(-EdgePadStart),  hpd[2], \
	mm2mils100(-EdgePadEnd), mm2mils100(EdgePasteWidth),  hpd[5], \
         hpd[6], hpd[7] , hpd[8], '"square"]'

     #full metal pad heels define the first side row:
     print '   Pad[',  hpd[0], mm2mils100(EdgePadHeelStart), hpd[2], \
     mm2mils100(EdgePadHeelEnd), hpd[4], hpd[5], hpd[6],  \
	'"%i"' % edgepadnum, '"%i"' % edgepadnum, '"nopaste"]'

     #full metal pad toes define the first side row:
     print '   Pad[',  hpd[0], mm2mils100(EdgePadStart), hpd[2], \
	mm2mils100(EdgePadEnd), \
	hpd[4], hpd[5], mm2mils100(EdgePadSoldermaskOpen), '"%i"' % edgepadnum, '"%i"' % edgepadnum, '"square,nopaste"]'

     #solderpaste pad heels define the first side row:
     print '   Pad[',  hpd[0], mm2mils100(EdgePadHeelStart), hpd[2], \
     mm2mils100(EdgePadHeelEnd), mm2mils100(EdgePasteWidth), hpd[5], hpd[6], \
	'"%i"' % edgepadnum, '"%i"' % edgepadnum, '""]'

     #solderpaste pad toes define the first side row:
     print '   Pad[',  hpd[0], mm2mils100(EdgePadStart), hpd[2], \
	mm2mils100(EdgePadEnd), mm2mils100(EdgePasteWidth), \
	hpd[5], hpd[6], '"%i"' % edgepadnum, '"%i"' % edgepadnum, '"square"]'

     # edgepads stepping vertically
     vpd = mm2mils100(EdgePadHeelStart), \
  	mm2mils100(-PadRowStartCenter + (edgepadnum - 1) * PadSpacing), \
	mm2mils100(EdgePadHeelEnd), \
  	mm2mils100(-PadRowStartCenter + (edgepadnum - 1) * PadSpacing), \
	mm2mils100(EdgePadWidth), \
	mm2mils100(EdgePadClearance), \
	mm2mils100(EdgePadHeelSoldermaskOpen), \
	'"%i"' % (NumEdgePads/2+1-edgepadnum), '"%i"' % (NumEdgePads/2+1-edgepadnum)


     #full metal pad heels define the < NumEdgePads/2  side column:
     print '   Pad[', vpd[0], vpd[1], vpd[2], vpd[3], vpd[4], vpd[5], \
     vpd[6] , vpd[7] , vpd[8], '"nopaste"]'

     #full metal pad toes define the < NumEdgePads/2  side column:
     print '   Pad[', mm2mils100(EdgePadStart),  vpd[1], mm2mils100(EdgePadEnd), \
         vpd[3], vpd[4], vpd[5],  mm2mils100(EdgePadSoldermaskOpen), vpd[7] , vpd[8], '"square,nopaste"]'

    #solderpaste pad heels define the < NumEdgePads/2  side column:
     print '   Pad[', vpd[0], vpd[1], vpd[2], vpd[3], mm2mils100(EdgePasteWidth), \
     vpd[5], vpd[6] , vpd[7] , vpd[8], '""]'

     #solderpaste  pad toes define the < NumEdgePads/2  side column:
     print '   Pad[', mm2mils100(EdgePadStart),  vpd[1], mm2mils100(EdgePadEnd), \
     vpd[3], mm2mils100(EdgePasteWidth),  vpd[5],  \
     mm2mils100(EdgePadSoldermaskOpen), vpd[7] , vpd[8], '"square"]'


     #full metal pad heels define the highest numbered side column:
     print '   Pad[',\
	mm2mils100(-EdgePadHeelStart), \
  	mm2mils100(PadRowStartCenter - (edgepadnum - 1) * PadSpacing), \
	mm2mils100(-EdgePadHeelEnd), \
  	mm2mils100(PadRowStartCenter - (edgepadnum - 1) * PadSpacing), \
         vpd[4], vpd[5], vpd[6] ,  \
	'"%i"' % (NumEdgePads+1-edgepadnum), '"%i"' % (NumEdgePads+1-edgepadnum), '"nopaste"]'

     #full metal pad toes define the highest numbered side column:
     print '   Pad[',\
	mm2mils100(-EdgePadStart), \
  	mm2mils100(PadRowStartCenter - (edgepadnum - 1) * PadSpacing), \
	mm2mils100(-EdgePadEnd), \
  	mm2mils100(PadRowStartCenter - (edgepadnum - 1) * PadSpacing), \
         vpd[4], vpd[5],  mm2mils100(EdgePadSoldermaskOpen), \
	'"%i"' % (NumEdgePads+1-edgepadnum), '"%i"' % (NumEdgePads+1-edgepadnum), '"square,nopaste"]'

     #solderpaste pad heels define the highest numbered side column:
     print '   Pad[',\
	mm2mils100(-EdgePadHeelStart), \
  	mm2mils100(PadRowStartCenter - (edgepadnum - 1) * PadSpacing), \
	mm2mils100(-EdgePadHeelEnd), \
  	mm2mils100(PadRowStartCenter - (edgepadnum - 1) * PadSpacing), \
         mm2mils100(EdgePasteWidth),  vpd[5], vpd[6] ,  \
	'"%i"' % (NumEdgePads+1-edgepadnum), '"%i"' % (NumEdgePads+1-edgepadnum), '""]'

     #solderpaste pad toes define the highest numbered side column:
     print '   Pad[',\
	mm2mils100(-EdgePadStart), \
  	mm2mils100(PadRowStartCenter - (edgepadnum - 1) * PadSpacing), \
	mm2mils100(-EdgePadEnd), \
  	mm2mils100(PadRowStartCenter - (edgepadnum - 1) * PadSpacing), \
          mm2mils100(EdgePasteWidth),  vpd[5],  mm2mils100(EdgePadSoldermaskOpen), \
	'"%i"' % (NumEdgePads+1-edgepadnum), '"%i"' % (NumEdgePads+1-edgepadnum), '"square"]'


# silk layer mark for pin one:
print '   ElementArc[',\
	mm2mils100(-PadRowStartCenter - PadSpacing), \
	mm2mils100(EdgePadEnd), \
	' 400 400 0 360 ' , mm2mils100(SilkWidth), ' ]'
print ")"
===================================qfn48_smallpaste.py===================================

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019