X-Authentication-Warning: delorie.com: mail set sender to geda-user-bounces using -f X-Recipient: geda-user AT delorie DOT com X-Original-DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=sendgrid.net; h=subject:to:references:from:mime-version:in-reply-to:content-type:content-transfer-encoding; s=smtpapi; bh=1OIzZXuNsWzzVpxwzX4O+hymqqE=; b=p58tPrgOzgAFLnZv0c y5RfLYasTN/oQZNeEowkXJppnv5nOKDZhxsf5tuZvPNC5cRKI8n0Sh7mVkEhTxHU sgxZzxW8FNO70zuchX7a64pmhNcVfhegcmbasqQXna8eEgYktOfFb4FXSZfdzayq CXIFvBp6BERFXsc5TP1Er48IA= Subject: [geda-user] QFN packages script from Bdale Garbee with new features added To: geda-user AT delorie DOT com References: <2df480cc-5ef2-9ac6-b7ad-d17788a6b8b9 AT ecosensory DOT com> <59149c35-79a3-2bd7-4b04-6d0967fcfe0a AT ecosensory DOT com> <87d1fg1g13 DOT fsf AT rover DOT gag DOT com> <6ab4fd42-c0fa-f820-1b65-1b7ceb9dddb9 AT ecosensory DOT com> From: "John Griessen (john AT ecosensory DOT com) [via geda-user AT delorie DOT com]" Message-ID: <5f8ca416-a46b-631d-0e49-91b42c23d634@ecosensory.com> Date: Wed, 25 Jan 2017 15:12:34 -0600 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Icedove/45.4.0 MIME-Version: 1.0 In-Reply-To: <6ab4fd42-c0fa-f820-1b65-1b7ceb9dddb9@ecosensory.com> Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit X-SG-EID: V53lTA/kUP1+IqXnzXuv0M/cu/N8aMtf7nxyAyKnAkvIq0C7WSKpyZDbijX8tYxPMGHIYxNClUKDdy rk3CurHO87mC+wfS6TFuA4MbZuqMwgq/3bbcuUy7DeVkNoveqsYhBG9AGaozf2u/RmmBBTyyaag2vr yJ9uezLb7vY/Z//kKdZiqrWycG/D5qe8P+WAp7Nde25IXp5puzVjdWCU4yWkSjPVkJg3NNR+WwZn7o w= 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 Precedence: bulk On 01/23/2017 02:45 PM, John Griessen (john AT ecosensory DOT com) [via geda-user AT delorie DOT com] wrote: > On 01/21/2017 11:25 AM, Bdale Garbee wrote: >> All of the products shipped by Altus Metrum, LLC, to date have used a >> makefile-driven gschem -> pcb workflow, and all of our designs are in >> the hw/ tree on git.gag.com if anyone wants to learn more from studying >> what we've done. >> >> Bdale > Thanks Bdale, I'll be looking at it and most likely using it on a QFN 48 pads + center... I made a version of that with variables similar to found in datasheets such as These: http://www.ti.com/lit/an/sloa122/sloa122.pdf http://www.nxp.com/assets/documents/data/en/application-notes/AN1902.pdf Datasheet excerpt images: http://ecosensory.com/geda/qfn_guidelines.png Old image before doing this script: http://ecosensory.com/geda/qfn_solderpaste.png New image of gerbv viewing script output http://ecosensory.com/geda/qfn48_smallpaste.py.gerbv.png Here is my parameterized upgrade to Bdale's python QFN generator below. It's 7/8 done. Anyone want to tidy it up for me while I work on other things? Thanks, John Griessen ========================qfn48_smallpaste.py======================== #!/usr/bin/python # Copyright 2016 by Bdale Garbee, 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.5 # width of gap in soldermask or resist over pad EdgePadClearance = 0.5 # width of gap between copper and pad. EdgePadLength = 0.55 # Distance from end to end of pad. EdgePadHeelLength = 0.45 # 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 + EdgePadWidth/2 EdgePadEnd = EdgePadHeelSquare/2 + EdgePadLength - EdgePadWidth/2 PadRowStartCenter = (NumEdgePads/4 - 1) * PadSpacing/2 PadGridSize = (NumCoreGridDiv -1)/2 # Odd number cols, rows around zero. EdgePadHeelStart = EdgePadHeelSquare/2+EdgePadWidth 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 'Element[0x0 "QFN36" "" "" 0 0 0 0 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(EdgePadSoldermaskOpen), \ '"%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], hpd[6], 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], hpd[6], '"%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 running vertically vpd = mm2mils100(EdgePadHeelStart), \ mm2mils100(-PadRowStartCenter + (edgepadnum - 1) * PadSpacing), \ mm2mils100(EdgePadHeelEnd), \ mm2mils100(-PadRowStartCenter + (edgepadnum - 1) * PadSpacing), \ mm2mils100(EdgePadWidth), \ mm2mils100(EdgePadClearance), \ mm2mils100(EdgePadSoldermaskOpen), \ '"%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], vpd[6], vpd[7] , vpd[8], '"square,nopaste"]' #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 - 2) * PadSpacing), \ mm2mils100(-EdgePadEnd), \ mm2mils100(PadRowStartCenter - (edgepadnum - 1) * PadSpacing), \ vpd[4], vpd[5], vpd[6], \ '"%i"' % (NumEdgePads+1-edgepadnum), '"%i"' % (NumEdgePads+1-edgepadnum), '"square,nopaste"]' # silk layer mark for pin one: print ' ElementArc[',\ mm2mils100(-PadRowStartCenter - PadSpacing), \ mm2mils100(EdgePadHeelEnd), \ ' 400 400 0 360 ' , mm2mils100(SilkWidth), ' ]' print ")" ========================qfn48_smallpaste.py========================