Footprint generating scripts for the open source layout tool PCB

6 replies [Last post]
mcorne
Offline
Contributor
Joined: 17 Apr 2007
Posts:

These are a collection of scripts that we have used to create footprints for circuit boards we have designed here at Five Man. They have been tested, but I would still recommend always checking any new footprints manually before sending out your design. If you find any problems with the following scripts please let me know.

The scripts will generate PCB footprints using the 1/100th of a mil spec and therefore should be quite accurate even for fine pitch parts. The input to the scripts deal with fractions correctly where appropriate (ie. 5.35 mils).

The following scripts are included in the zip file:

make_header_fp : Makes header style through hole footprints.
make_headerx2_fp : Makes dual row through hole header footprints.
make_soic_fp : Makes any surface mount part with 2 rows of pins (ie TSOP, TSSOP, SSOP, SOIC, SM headers etc).
make_qfp_fp : Makes a QFP footprint (assumes pin 1 is in a corner, not in the center of the part).
make_pwrpad_fp : Basically the same script as the SOIC one, but adds support for a thermal pad on the bottom of the part.

Running a script with no arguments will show usage for that script.

Usage:

 ./make_?_fp arg1 arg2 ... arg? > FOOTPRINT

This will create a PCB readable footprint with the name of FOOTPRINT

Examples:

 ./make_header_fp 
 Ex: ./make_header_fp 5 

This will create a header footprint 5 pins long with 100 mil spacing.

 ./make_soic_fp      
 Ex: ./make_soic_fp 20 25 8.5 35 100 300

This will create a surface mount part with 10 pins on either side separated by 25 mil pitch. The pads will be 8.5 mils wide, 35 mils long, and will be separated by a 100 mil gap between pins 1-10 and 11-20. the last argument is only used for silkscreen placement.

The code can be downloaded in a zip here, or cut and pasted from below.
I plan on updating the scripts soon and possibly making a GUI interface to make them more user friendly.

**Note** See errata at the bottom of this page before using scripts

AttachmentSize
fp_gen_scripts.zip3.96 KB
mcorne
Offline
Contributor
Joined: 17 Apr 2007
Posts:
Header creation script


#!/usr/bin/perl
# Pass me: [pad count] [pad pitch] [pad width] [pad length] [package width] [package length]
#
# David Wolpoff
# Matt Corne
my $args = @ARGV;
die "Usage: $0 [pad count]\n or $0 [pad count] [pitch] [hole size] [thickness]\n" unless ($args == 1|$args == 4);

my $space = $ARGV[1];
my $count = $ARGV[0];
my $hole = $ARGV[2];
my $thickness = $ARGV[3];
my $solderm;

$space = $space*100;
$hole = $hole*100;
$thickness = $thickness*100*2+$hole;

print "Element[0x00000000 \"\" \"U0\" \"\" 557500 147600 -3100 -8200 0 100 0x00000000]\n(\n";
#First we locate our pins on the left.
$pinx1=0;
if($args == 1){
for ( $i = 0 ; $i < $count; $i++ )
{
$name = $i+1;
print "\tPin\[$pinx1 0 7000 3000 7500 3800 \"$name\" \"$name\" 0x4000001\]\n";
$pinx1=$pinx1+$space;
}
}
else{
$solderm = $thickness + 1500;
for ( $i = 0 ; $i < $count; $i++ )
{
$name = $i+1;
print "\tPin\[$pinx1 0 $thickness 3000 $solderm $hole \"$name\" \"$name\" 0x4000001\]\n";
$pinx1=$pinx1+$space;
}
}
$xmin=0-$space/2;
$xmax=$space*$count-$space/2;
$ymin=-5000;
$ymax=5000;
print "\tElementLine[$xmin $ymin $xmin $ymax 1500]\n";
print "\tElementLine[$xmin $ymax $xmax $ymax 1500]\n";
print "\tElementLine[$xmax $ymax $xmax $ymin 1500]\n";
print "\tElementLine[$xmax $ymin $xmin $ymin 1500]\n";
print ")\n";

mcorne
Offline
Contributor
Joined: 17 Apr 2007
Posts:
Double row header creation script (Only supports 100 mil pitch)


#!/usr/bin/perl
# Pass me: [pad count]
#
# David Wolpoff
my $args = @ARGV;
die "Usage: $0 [pad count] \n" unless $args == 1;
my $space = 10000;
my $count;

$count = $ARGV[0];

print "Element[0x00000000 \"\" \"U0\" \"\" 557500 147600 -3100 -8200 0 100 0x00000000]\n(\n";
#First we locate our pins on the left.
$pinx1=0;
for ( $i = 0 ; $i < $count; $i=$i+2 )
{
$name = $i+1;
print "\tPin\[$pinx1 0 7000 3000 7500 3800 \"$name\" \"$name\" 0x4000001\]\n";
$name = $i+2;
print "\tPin\[$pinx1 -$space 7000 3000 7500 3800 \"$name\" \"$name\" 0x4000001\]\n";
$pinx1=$pinx1+$space;
}
$xmin=0-$space/2;
$xmax=$space*$count/2-$space/2;
$ymin=-$space-$space/2;
$ymax=$space-$space/2;
print "\tElementLine[$xmin $ymin $xmin $ymax 1500]\n";
print "\tElementLine[$xmin $ymax $xmax $ymax 1500]\n";
print "\tElementLine[$xmax $ymax $xmax $ymin 1500]\n";
print "\tElementLine[$xmax $ymin $xmin $ymin 1500]\n";
print ")\n";

mcorne
Offline
Contributor
Joined: 17 Apr 2007
Posts:
SOIC creation script


#!/usr/bin/perl
# Pass me: [pad count] [pad pitch] [pad width] [pad length] [package width] [package length]
#
# David Wolpoff
my $args = @ARGV;
die "Usage: $0 [pad count] [pitch] [pad width] [pad length] [package width] [package length]\n" unless $args == 6;

my $count;
my $pitch;
my $pwidth;
my $plength;
my $width;
my $length;

$count = $ARGV[0];
$pitch = $ARGV[1]*100;
$pwidth = $ARGV[2]*100;
$plength = $ARGV[3]*100;
$width = $ARGV[4]*100;
$length = $ARGV[5]*100;

$width = $width+$pwidth;
$plength = $plength-$pwidth;

if ($plength <= 0)
{
$plength = 1;
}

$namex = -$width/2;
print "Element[0x00000000 \"\" \"U0\" \"\" 0 0 0 $namex 0 100 0x00000000]\n(\n";
#First we locate our pins on the left.
$pinx1=0;
$piny1=0;
$piny2=$plength;
$clearance = 10*100;
$mask=$pwidth+$clearance;
$maxx=0;
for ($i = 1; $i <= $count/2; $i++)
{
$pinnum = $i;
print "\tPad\[$pinx1 $piny1 $pinx1 $piny2 $pwidth $clearance $mask \"\" \"$pinnum\" 0x00000100\]\n";
$pinx1=$pinx1+$pitch;
}
#The the pins on the left
$pinx1=$pinx1-$pitch;
$maxx=$pinx1;
$piny1=-($piny1+$width);
$piny2=-($piny2+$width);
for ($i = 1+$count/2; $i <= $count; $i++)
{
$pinnum=$i;
print "\tPad\[$pinx1 $piny1 $pinx1 $piny2 $pwidth $clearance $mask \"\" \"$pinnum\" 0x00000100\]\n";
$pinx1=$pinx1-$pitch;
}
$ymin=-2000;
$ymax=$piny1+2000;
$xmid=int($maxx/2);
$xmin=$xmid-int($length/2);
$xmax=$xmid+int($length/2);

print "\tElementLine[$xmin $ymin $xmin $ymax 1500]\n";
print "\tElementLine[$xmin $ymax $xmax $ymax 1500]\n";
print "\tElementLine[$xmax $ymax $xmax $ymin 1500]\n";
print "\tElementLine[$xmax $ymin $xmin $ymin 1500]\n";

$xmin=$xmin+1500;
$ymin=$ymin-1500;
print "\tElementArc[$xmin $ymin 1000 1000 0 9000 500]\n";
print "\tElementArc[$xmin $ymin 1000 1000 9000 9000 500]\n";
print "\tElementArc[$xmin $ymin 1000 1000 18000 9000 500]\n";
print "\tElementArc[$xmin $ymin 1000 1000 27000 9000 500]\n";

print ")\n";

mcorne
Offline
Contributor
Joined: 17 Apr 2007
Posts:
QFP creation script


#!/usr/bin/perl
# Pass me: [pad count x] [pad count y] [pad pitch] [pad width] [pad length] [package width] [package length]
#
# Original SOIC script by David Wolpoff
# Script adapted to create QFP by Matt Corne
my $args = @ARGV;
die "Usage: $0 [pad count x] [pad count y] [pitch] [pad width] [pad length] [package width] [package length]\n" unless $args == 7;

my $countx;
my $county;
my $pitch;
my $pwidth;
my $plength;
my $width;
my $length;

$countx = $ARGV[0];
$county = $ARGV[1];
$pitch = $ARGV[2]*100;
$pwidth = $ARGV[3]*100;
$plength = $ARGV[4]*100;
$width = $ARGV[5]*100;
$length = $ARGV[6]*100;

$width = $width+$pwidth;
$plength = $plength-$pwidth;

if ($plength <= 0)
{
$plength = 1;
}

$namex = $width/2+$plength/2;
$namey = -($length/2+$plength/2+2000);
print "Element[0x00000000 \"\" \"U0\" \"\" 0 0 $namex $namey 0 100 0x00000000]\n(\n";

#Some clearance variables
$clearance = 10*100;
$mask=$pwidth+$clearance;
#Locate pin number one starting position (origin is in center)
#Pin 1 starts in top left corner and counts counterclockwise
#around part
$pinx1=0;
$piny1=0;
$pinx1=$pinx1-($plength+$width/2);
$piny1=$piny1-($county/2-0.5)*$pitch;

#remembering some data
$xmin=$pinx1+$plength+2000;
$dotx=$pinx1;
$doty=$piny1-$pwidth-1000;
#Draw pins on left side of part
$pinx2=$pinx1+$plength;
for ($i = 1; $i <= $county; $i++)
{
$pinnum = $i;
print "\tPad\[$pinx1 $piny1 $pinx2 $piny1 $pwidth $clearance $mask \"\" \"$pinnum\" 0x00000100\]\n";
$piny1=$piny1+$pitch;
}
#Locating bottom-left pin starting position
$pinx1=0;
$piny1=0;
$pinx1=$pinx1-($countx/2-0.5)*$pitch;
$piny1=$piny1+($plength+$width/2);
#remembering more crap
$ymax=$piny1-$plength-2000;
#draw pins on bottom side of part
$piny2=$piny1-$plength;
for ($i = $county+1; $i <= $county+$countx; $i++)
{
$pinnum = $i;
print "\tPad\[$pinx1 $piny1 $pinx1 $piny2 $pwidth $clearance $mask \"\" \"$pinnum\" 0x00000100\]\n";
$pinx1=$pinx1+$pitch;
}
#Locating bottom-right pin starting location
$pinx1=0;
$piny1=0;
$pinx1=$pinx1+($plength+$width/2);
$piny1=$piny1+($county/2-0.5)*$pitch;
#Remember some more crap
$xmax=$pinx1-$plength-2000;
#Draw pins on right side of part
$pinx2=$pinx1-$plength;
for ($i = $county+$countx+1; $i <= 2*$county+$countx; $i++)
{
$pinnum = $i;
print "\tPad\[$pinx1 $piny1 $pinx2 $piny1 $pwidth $clearance $mask \"\" \"$pinnum\" 0x00000100\]\n";
$piny1=$piny1-$pitch;
}
#Locate the top-right pin starting location
$pinx1=0;
$piny1=0;
$pinx1=$pinx1+($countx/2-0.5)*$pitch;
$piny1=$piny1-($plength+$width/2);
#remembering some data
$ymin=$piny1+$plength+2000;
#Draw pins on top side of part
$piny2=$piny1+$plength;
for ($i = 2*$county+$countx+1; $i <= 2*$county+2*$countx; $i++)
{
$pinnum = $i;
print "\tPad\[$pinx1 $piny1 $pinx1 $piny2 $pwidth $clearance $mask \"\" \"$pinnum\" 0x00000100\]\n";
$pinx1=$pinx1-$pitch;
}

#$ymin=-2000;
#$ymax=$piny1+2000;
#$xmid=int($maxx/2);
#$xmin=$xmid-int($length/2);
#$xmax=$xmid+int($length/2);

print "\tElementLine[$xmin $ymax $xmin $ymin 1500]\n";
print "\tElementLine[$xmin $ymin $xmax $ymin 1500]\n";
print "\tElementLine[$xmax $ymin $xmax $ymax 1500]\n";
print "\tElementLine[$xmax $ymax $xmin $ymax 1500]\n";

print "\tElementArc[$dotx $doty 1000 1000 0 9000 500]\n";
print "\tElementArc[$dotx $doty 1000 1000 9000 9000 500]\n";
print "\tElementArc[$dotx $doty 1000 1000 18000 9000 500]\n";
print "\tElementArc[$dotx $doty 1000 1000 27000 9000 500]\n";

print ")\n";

mcorne
Offline
Contributor
Joined: 17 Apr 2007
Posts:
Power Pad or Thermal Pad footprint creation script


#!/usr/bin/perl
# Pass me: [pad count] [pad pitch] [pad width] [pad length] [package width] [package length] [thermal width] [thermal length]
#
# David Wolpoff
# Matt Corne
my $args = @ARGV;
die "Usage: $0 [pad count] [pitch] [pad width] [pad length] [package width] [package length] [thermal width] [thermal length]\n" unless $args == 8;

my $count;
my $pitch;
my $pwidth;
my $plength;
my $width;
my $length;
my $thrmw;
my $thrml;

$count = $ARGV[0];
$pitch = $ARGV[1]*100;
$pwidth = $ARGV[2]*100;
$plength = $ARGV[3]*100;
$width = $ARGV[4]*100;
$length = $ARGV[5]*100;
$thrmw = $ARGV[6]*100;
$thrml = $ARGV[7]*100;

$width = $width+$pwidth;
$plength = $plength-$pwidth;

if ($plength <= 0)
{
$plength = 1;
}

$namex = -$width/2;
print "Element[0x00000000 \"\" \"U0\" \"\" 0 0 0 $namex 0 100 0x00000000]\n(\n";
#First we locate our pins on the left.
$pinx1=0;
$piny1=0;
$piny2=$plength;
$clearance = 10*100;
$mask=$pwidth+$clearance;
$maxx=0;
for ($i = 1; $i <= $count/2; $i++)
{
$pinnum = $i;
print "\tPad\[$pinx1 $piny1 $pinx1 $piny2 $pwidth $clearance $mask \"\" \"$pinnum\" 0x00000100\]\n";
$pinx1=$pinx1+$pitch;
}
#The the pins on the left
$pinx1=$pinx1-$pitch;
$maxx=$pinx1;
$piny1=-($piny1+$width);
$piny2=-($piny2+$width);
for ($i = 1+$count/2; $i <= $count; $i++)
{
$pinnum=$i;
print "\tPad\[$pinx1 $piny1 $pinx1 $piny2 $pwidth $clearance $mask \"\" \"$pinnum\" 0x00000100\]\n";
$pinx1=$pinx1-$pitch;
}
$ymin=-2000;
$ymax=$piny1+2000;
$ymid=int(($ymax-2000)/2);
$xmid=int($maxx/2);
$xmin=$xmid-int($length/2);
$xmax=$xmid+int($length/2);

#Add Thermal Pad
$pwidth=$thrmw;
$thrmy=$ymid;
$thrmx1=$xmid+int($thrml/2)-int($pwidth/2);
$thrmx2=$xmid-int($thrml/2)+int($pwidth/2);
$clearance = 10*100;
$mask=$pwidth+$clearance;
$maxx=0;
$pinnum = $count+1;
print "\tPad\[$thrmx1 $thrmy $thrmx2 $thrmy $pwidth $clearance $mask \"\" \"$pinnum\" 0x00000100\]\n";
#print "XMIN: $xmin\n";
#print "XMAX: $xmax\n";
#print "YMIN: $ymin\n";
#print "YMAX: $ymax\n";

#Print outline
print "\tElementLine[$xmin $ymin $xmin $ymax 1500]\n";
print "\tElementLine[$xmin $ymax $xmax $ymax 1500]\n";
print "\tElementLine[$xmax $ymax $xmax $ymin 1500]\n";
print "\tElementLine[$xmax $ymin $xmin $ymin 1500]\n";

$xmin=$xmin+1500;
$ymin=$ymin-1500;
print "\tElementArc[$xmin $ymin 1000 1000 0 9000 500]\n";
print "\tElementArc[$xmin $ymin 1000 1000 9000 9000 500]\n";
print "\tElementArc[$xmin $ymin 1000 1000 18000 9000 500]\n";
print "\tElementArc[$xmin $ymin 1000 1000 27000 9000 500]\n";

print ")\n";

mcorne
Offline
Contributor
Joined: 17 Apr 2007
Posts:
**Bug Notice**

The SOIC generating script can only make SMD parts that have 4 or more pins. If you try to make a 2 pin part by either making the pitch 0 mils or making the the pitch the distance between the 2 pads and rotating the pads length and width you will get the wrong size pads!

I will fix this in an update soon. For the time being I have created 2 pad devices (such as a 2512 package) by creating a 4 pin SOIC part with the right pad dimensions, then deleting the 2 bottom pins and silkscreen, and finally adjusting the pin numbers to be correct (in a text editor).

-Matt