#!/usr/bin/perl

###########################################################################
#
# gensmtpack
#
# Generate an Eagle Script file that will create a surface-mount
# package according to parameters entered on the command line.
#
# In order to use this, you'll need both the package dimensions,
# certainly provided by your part vendor, and a land pattern,
# which is sometimes available from your part vendor. If your part
# vendor doesn't provide a land pattern, you may be able to get one
# from the IPC, at http://www.ipc.org; you'll be wanting standard
# IPC-SM-782. Of particular note, if you register at their site,
# you'll be able to use their online Land Pattern calculator.
#
# Most of the command-line arguments for this program should be
# simple transcriptions from dimensions cited either in the part
# data sheet or on the land pattern.
#
# Released to Public Domain, March 2000
# Bob Drzyzgula, Federal Reserve Board, bob@frb.gov
#
# NO WARRANTY: The user of this program should not assume that it
# does anything even remotely resembling what it appears to do.
# IF YOU GENERATE A PART WITH THIS PROGRAM, CHECK IT OVER CAREFULLY!
# IF YOUR BOARD IS RUNIED BY USING THE OUTPUT OF THIS PROGRAM, IT IS
# NOT MY FAULT.
#
# NB: IN PARTICULAR, PLEASE DOUBLE-CHECK THAT NO MARKINGS ON LAYERS
# THAT WILL CARRY FORWARD TO THE SILKSCREEN (E.G. tPlace) WILL OBSCURE
# ANY SMDS. THE POSITIONING OF TEXT IS AUTOMATICALLY CALCULATED AND
# I AM NOT SURE THAT SUCH AN ERROR CANNOT OCCUR.
#
#
# Please report errors, bugs, comments, etc.
#
###########################################################################
#
# Version 0.0, March 27, 2000
# Version 0.1, March 27, 2000 (some dimensions improved)
# Version 0.2, March 28, 2000 (fixed some off-by-one errors)
# Version 0.3, March 30, 2000 (added concave pin type, changed labling)
# Version 0.4, April  1, 2000 (added j-lead pins, autoscaled text)
# Version 0.5, April  1, 2000 (extensively commented, cleaned up some dead
#                              and inconsistant code)
#
###########################################################################

use Getopt::Long;
use POSIX;


#
# Set default values.
#

$pincount = 24;
$endoffset = 0.35;
$des1 = "";
$des2 = "";
$des3 = "";
$smddx = 0.4;
$smddy = 1.1;
$pinwidth = 0.25;
$jwidth = 0.0;
$pinlength = 1.0;
$pinsetback = 0.0;
$pintype = "gullwing";
$bodywidth = 4.4;
$pitch = 0.65;
$pindent = 0.0;
$smdsep = 4.6;
$gridfinal = 0.005;
$gridfinalmult = 50;
$gridworking = 0.005;
$keepout = 0.3;
$help = 0;

#
# Set the following variable to 1 if you would like some diagnostic output.
#

# $debug = 1;
$debug = 0;

#
# Get options from command line. See Perl GetOptions package
# documentation for more information.
#

GetOptions
	(
		"pincount=i" => \$pincount, 
		"endoffset=f" => \$endoffset, 
		"des1:s" => \$des1, 
		"des2:s" => \$des2,
		"des3:s" => \$des3,
		"smddx=f" => \$smddx,
		"smddy=f" => \$smddy,
		"pinwidth=f" => \$pinwidth,
		"jwidth=f" => \$jwidth,
		"pinlength=f" => \$pinlength,
		"pinsetback=f" => \$pinsetback,
		"bodywidth=f" => \$bodywidth,
		"pitch=f" => \$pitch,
		"smdsep=f" => \$smdsep,
		"gridfinal=f" => \$gridfinal,
		"gridfinalmult=i" => \$gridfinalmult,
		"gridworking=f" => \$gridworking,
		"pintype=s" => \$pintype,
		"pindent=f" => \$pindent,
		"keepout=f" => \$keepout,
		"help" => \$help
	); 

#
# Print help message and exit if requested.
#

if ($help == 1)
	{
		print STDERR  "\nGENSMTPACK\n----------\n\nThis program will generate an Eagle Script file that can\n";
		print STDERR  "in turn be run within Eagle to generate a package design\n";
		print STDERR  "for a two-sided, surface mount part. Pin options are gullwing,\n";
		print STDERR  "jlead and concave (dimpled parts like panasonic resistor networks)\n\n";
		print STDERR  "Run this program and redirect the output to a file called\n";
		print STDERR  "\"partname.scr\" in a directory in Eagle's script file\n";
		print STDERR  "search path. Then, within eagle, open a library, create a \n";
		print STDERR  "new, empty package, and then run the script partname.scr.\n";
		print STDERR	"\nMost of the command-line arguments for this program should be\n";
		print STDERR	"simple transcriptions from dimensions cited either in the part\n";
		print STDERR	"data sheet or on the land pattern.\n";
		print STDERR	"\nReleased to Public Domain, March 2000\n";
		print STDERR	"Bob Drzyzgula, Federal Reserve Board, bob\@frb.gov\n";
		print STDERR	"\nNO WARRANTY: The user of this program should not assume that it\n";
		print STDERR	"does anything even remotely resembling what it appears to do.\n";
		print STDERR	"IF YOU GENERATE A PART WITH THIS PROGRAM, CHECK IT OVER CAREFULLY!\n";
		print STDERR	"IF YOUR BOARD IS RUNIED BY USING THE OUTPUT OF THIS PROGRAM, IT IS\n";
		print STDERR	"NOT MY FAULT.\n";
		print STDERR	"\nNB: IN PARTICULAR, PLEASE DOUBLE-CHECK THAT NO MARKINGS ON LAYERS\n";
		print STDERR	"THAT WILL CARRY FORWARD TO THE SILKSCREEN (E.G. tPlace) WILL OBSCURE\n";
		print STDERR	"ANY SMDS. THE POSITIONING OF TEXT IS AUTOMATICALLY CALCULATED AND\n";
		print STDERR	"I AM NOT SURE THAT SUCH AN ERROR CANNOT OCCUR.\n";
		print STDERR  "\n";
		print STDERR  "Usage:\n";
		print STDERR  "   gensmtpack [options] >partname.scr \n";
		print STDERR  "   \nInformational options:\n";
		print STDERR  "   --help print this message\n";
		print STDERR  "   \nPin-specific options:\n";
		print STDERR  "   --pincount=<integer> Number of pins on part (default 24) \n";
		print STDERR  "   --pindent=<float> mm diameter of concave dent in pins (default 0.0)\n";
		print STDERR  "   --pinlength=<float> mm length of physical pins (default 1.0)\n";
		print STDERR  "   --pinsetback=<float> mm how far back from the edge of the package (default 0.0)\n";
		print STDERR  "   --pintype=<string> [gullwing|concave|jlead] (default gullwing) \n";
		print STDERR  "   --pinwidth=<float> mm width of physical pins (default 0.25)\n";
		print STDERR  "   --jwidth=<float> mm width of lower contact portion of J-lead pins (default 0.0)\n";
		print STDERR  "   --pitch=<float> mm center-to-center distance between pins (default 0.65)\n";
		print STDERR  "   \nPackage Dimensioning options:\n";
		print STDERR  "   --endoffset=<float> mm from end of package body to center of first pin\n";
		print STDERR  "       (default 0.35)\n";
		print STDERR  "   --keepout=<float> mm margain around part for tKeepOut layer (default 0.3)\n";
		print STDERR  "   --bodywidth=<float> mm width (from pin side to pin side) of package body (default 4.4)\n";
		print STDERR  "   \nSMD options:\n";
		print STDERR  "   --smddx=<float>  mm x width of SMDs (default 0.4)\n";
		print STDERR  "   --smddy=<float>  mm y height of SMDs (default 1.1)\n";
		print STDERR  "   --smdsep=<float> mm distance between the SMDs on one side of package to\n";
		print STDERR  "       SMDs on other side of package. Probably a tiny bit more than --bodywidth (default 4.6)\n";
		print STDERR  "   \nDocumentation & scaling options:\n";
		print STDERR  "   --gridfinal=<float> mm grid spacing upon return (default 0.005 mm)\n";
		print STDERR  "   --gridfinalmult=<int> grid spacing multiple for drawing gridlines (default 50)\n";
		print STDERR  "   --gridworking=<float> mm grid spacing to use while parts are being deposited (default 0.005)\n";
		print STDERR  "   --des1=<string>, --des2=<string>, --des3=<string>\n";
		print STDERR  "       three lines of description will be put on layer 250\n";
		print STDERR  "       (default \"\" [null string]). Use them in order starting from des1 -- e.g. if des2 is \n";
		print STDERR  "       specified but des1 is not, des2 will not be recognized\n";
		print STDERR  "   \n";
		print STDERR  "By default, the script should generate a poorly-labeled TSSOP 24,\n";
		print STDERR  "because that\'s what I needed when I wrote the script.\n";
		print STDERR  "   \n";
		print STDERR  "I mean, the TSSOP 24, not the poorly-labled part :-)\n";
		print STDERR  "   \n";
		print STDERR  "Please report errors, bugs, comments, etc to bob\@frb.gov\n";
		print STDERR  "See the script file text for more information on the workings of this program\n";
		exit (0);
	}

#
# The following section will set up some tables for use in autoscaling
# the text fields in the package. I've selected ten standard text
# sizes from among the list offered on the change..text menu. I've
# fixed the description fields (small text) to be four sizes smaller
# than the name/value fields.
#
# Stdtxtsm and stdtxtlg are tables of the allowed text sizes
#

@stdtxtsm = (0.24,0.254,0.3048,0.4064,0.6096,0.8128,1.016,1.27,1.4224,1.6764);
@stdtxtlg = (0.6096,0.8128,1.016,1.27,1.4224,1.6764,1.778,1.9304,2.1844,2.54);

#
# Linesep is the distance between the bottom of one line and the top
# of the one below. It is the same for small text and large text,
# and is set to one twenty-fifth of the package width, rounded up
# to the nearest tenth of a mm.
#

$linesep = POSIX::ceil(($bodywidth/25)*10) / 10;
printf STDERR "linesep $linesep\n" if ($debug > 0);

#
# stdfit is a table that tells how much total text height, including
# line separation, is requried for various combinations of lines.
# Having this table set up greatly simplifies some of the code below.
#

for ($i = 0; $i < 10; $i++)
	{
		$stdfit[0][$i] =                            $stdtxtlg[$i]  + 2 * $linesep;
		$stdfit[1][$i] =                       (2 * $stdtxtlg[$i]) + 3 * $linesep;
		$stdfit[2][$i] =                       (3 * $stdtxtlg[$i]) + 4 * $linesep;
		$stdfit[3][$i] =      $stdtxtsm[$i]  + (2 * $stdtxtlg[$i]) + 4 * $linesep;
		$stdfit[4][$i] =      $stdtxtsm[$i]  + (3 * $stdtxtlg[$i]) + 5 * $linesep;
		$stdfit[5][$i] = (2 * $stdtxtsm[$i]) + (2 * $stdtxtlg[$i]) + 5 * $linesep;
		$stdfit[6][$i] = (2 * $stdtxtsm[$i]) + (3 * $stdtxtlg[$i]) + 6 * $linesep;
		$stdfit[7][$i] = (3 * $stdtxtsm[$i]) + (2 * $stdtxtlg[$i]) + 6 * $linesep;
		$stdfit[8][$i] = (3 * $stdtxtsm[$i]) + (3 * $stdtxtlg[$i]) + 7 * $linesep;
	}

#
# Diagnostic dumps of the contents of the just-computed arrays:
#

printf STDERR "stdtxtsm @stdtxtsm\n" if ($debug > 0);
printf STDERR "stdtxtlg @stdtxtlg\n" if ($debug > 0);

if ($debug > 0)
	{
		for ($i = 0; $i < 10; $i++)
			{
				printf STDERR "stdfit[$i]";
				for ($j = 0; $j < 10; $j++)
					{
						printf STDERR " $stdfit[$i][$j]";
					}
				printf STDERR "\n";
			}
	}

#
# Prepare some useful quantities for later use:
#
# Generally, variables ending in "f" are formatted text versions of values
# in such cases, values are written to 1 micron (0.001 mm) precision
#

# $smdsizef is text for use printing out the Smd commands later
$smdsizef = sprintf("%.3f",$smddx) . " " . sprintf("%.3f",$smddy);

# $hpc is half the pincount -- half the pins go on each side of the package (duh).
$hpc = $pincount/2;

# $hpw is half the pinwidth.
$hpw = $pinwidth/2;

# $hbodlen is half the length of the package body
$hbodlen = (($endoffset * 2) + (($hpc -1) * $pitch))/2;
$hbodlenf = sprintf("%.3f",$hbodlen);

# $halfbod is half the body width
$halfbod = $bodywidth/2;
$halfbodf = sprintf("%.3f",$halfbod);

# $pinminy is the minimum vertical dimension of the package pins
$pinminy = $halfbod - $pinsetback;
$pinminyf = sprintf("%.3f",$pinminy);

# $pinendf is the maximum veritcal dimension of the package pins
$pinendf = sprintf("%.3f",($pinlength + $pinminy));

#
# Beginning of Eagle script output
#
print "Grid mm $gridworking off;\n";
print "Set Wire_Style 0;\n";

#
# Package outline and pin drawings go on tDocu layer
#
print "Layer tDocu;\n";
#
# a line around the perimeter of the package
#
print "Wire (-$hbodlenf $halfbodf) ($hbodlenf $halfbodf) ($hbodlenf -$halfbodf) (-$hbodlenf -$halfbodf) (-$hbodlenf $halfbodf);\n";

# pinstart is initialized to the left edge of the far-left-side pin. 
$pinstart = $endoffset - $hbodlen - $hpw;

#
# The following section draws the pins. There are currently three supported
# types of pins: "gullwing", "jlead" and "concave".
#
# * Gullwing pins have a single width and extend from the package edge
#   out $pinlength in length.
#
# * J-lead pins are one width outside the package perimeter, but
#   have a thinner ($jwidth) cupped portion of the pin that extends
#   beneath the package body. I draw these as two rectangles, one inside
#   and one outside the perimiter.
#
# * Concave pins are the dimpled things that the put on the sides of
#   some surface-mount resistor packs, such as those from Panasonic.
#   I draw these as a wire outline because I couldn't find any way
#   to make a filled, curved area.
#

if ($pintype eq "concave")
	{
	   # $arcoffset is the distance between the side of the pin and
		# the beginning of the dimple arc.
		$arcoffset = ($pinwidth - $pindent)/2;

		#
		# Loop through all the pin positions, left to right.
		# the top and bottom pins at each position are drawn
		# as mirror imagages of each other.
		#
		for ( $i = 0 ; $i < $hpc ; $i++)
			{
				# $pinstop is the right side of the pin.
				$pinstop = $pinstart + $pinwidth;

				# $po1 is the location of the right side of the arc
				$po1 = $pinstart + $arcoffset;

				# $po2 is the location of the left side of the arc
				$po2 = $pinstop - $arcoffset;

				# make formatted versions...

				$pinstartf = sprintf("%.3f",$pinstart);
				$po1f = sprintf("%.3f",$po1);
				$po2f = sprintf("%.3f",$po2);
				$pinstopf = sprintf("%.3f",$pinstop);

				# spit out the wire paths...

				print "Wire 0.05 ($po1f $pinendf) ($pinstartf $pinendf) ($pinstartf $pinminyf) ($pinstopf $pinminyf) ($pinstopf $pinendf) ($po2f $pinendf);\n";
				print "Wire 0.05 ($po1f -$pinendf) ($pinstartf -$pinendf) ($pinstartf -$pinminyf) ($pinstopf -$pinminyf) ($pinstopf -$pinendf) ($po2f -$pinendf);\n";
				print "Arc 0.05 CCW ($po1f $pinendf) ($po2f $pinendf) ($po2f $pinendf);\n";
				print "Arc 0.05 CW ($po1f -$pinendf) ($po2f -$pinendf) ($po2f -$pinendf);\n";

				# increment to the next pin postion...
				$pinstart += $pitch;
			}
	}
elsif ($pintype eq "gullwing" )
	{
		for ( $i = 0 ; $i < $hpc ; $i++)
			{
				# pinstop is the right side of the pin
				$pinstop = $pinstart + $pinwidth;

				# make formatted versions
				$pinstartf = sprintf("%.3f",$pinstart);
				$pinstopf = sprintf("%.3f",$pinstop);

				# spit out eagle commands to make pins...
				print "Rect ($pinstartf $pinminyf) ($pinstopf $pinendf);\n";
				print "Rect ($pinstartf -$pinminyf) ($pinstopf -$pinendf);\n";

				# increment to next pin position
				$pinstart += $pitch;
			}
	}
elsif ($pintype eq "jlead")
	{
		for ( $i = 0 ; $i < $hpc ; $i++)
			{
				# pinstop is the right side of the pin
				$pinstop = $pinstart + $pinwidth;

				# make formatted versions
				$pinstartf = sprintf("%.3f",$pinstart);
				$pinstopf = sprintf("%.3f",$pinstop);

				# jdiff is the difference in width between
				# the outer pin portion and the inner, j portion
				$jdif = $pinwidth - $jwidth;
				# ...half of that
				$hjdif = $jdif/2;
				# ...formatted start and stop positions...
				$jpstartf = sprintf("%.3f",($pinstart + $hjdif));
				$jpstopf = sprintf("%.3f",($pinstop - $hjdif));

				# Spit out those commands...
				print "Rect ($pinstartf $halfbod) ($pinstopf $pinendf);\n";
				print "Rect ($jpstartf $pinminyf) ($jpstopf $halfbod);\n";
				print "Rect ($pinstartf -$halfbod) ($pinstopf -$pinendf);\n";
				print "Rect ($jpstartf -$pinminyf) ($jpstopf -$halfbod);\n";

				# increment to next pin postion...
				$pinstart += $pitch;
			}
	}
else
	{
		# Say what?
		printf STDERR "unknown pin type $pintype\n";
		exit (2);
	}


#
# Make the keepout rectangle. This goes all around the part and
# is placed on the tKeepout layer. The maximum reach of the
# package itself and the SMDs is rounded up to the nearest
# 0.1 mm, and then an additional offset of $keepout is added.
#

$kolx = $keepout + POSIX::ceil($hbodlen*10)/10;
$kolxf = sprintf("%.3f",$kolx);
$koly = $keepout + POSIX::ceil(10*($smdsep/2 + $smddy))/10;
$kolyf = sprintf("%.3f",$koly);

#
# Make the wire...
#

print "Layer tKeepout;\n";
print "Wire (-$kolxf $kolyf) ($kolxf $kolyf) ($kolxf -$kolyf) (-$kolxf -$kolyf) (-$kolxf $kolyf) ;\n";

#
# Figure out where to put the text
# All text lables are placed 0.5 mm from the left edge of the part
# except for the pin 1 indicator, which is placed 0.1mm from the
# bottom left corner of the part outline.
#

$textstart = $hbodlen - 0.5;
$textstartf = sprintf("%.3f",$textstart);
$onexf = sprintf("%.3f",(0.1 - $hbodlen));
$oneyf = sprintf("%.3f",(0.1 - $halfbod));


#
# Now figure out how much vertical space is available for lines of text.
# The text needs to fit in otherwise unoccupied space on the part body.
# This could wind up being constrained either by the body outline, the
# Pin outline, or the SMD outline. the following construct figures out
# which applies here and sets the amount of space appropriately.
#

if ($pinminy < $halfbod)
	{
		if (($smdsep/2) < $pinminy)
			{
				$vspace = $smdsep;
				$halfv = $smdsep/2;
			}
		else
			{
				$vspace = 2 * $pinminy;
				$halfv = $pinminy;
			}
	}
else
	{
		if (($smdsep/2) < $halfbod)
			{
				$vspace = $smdsep;
				$halfv = $smdsep/2;
			}
		else
			{
				$vspace = $bodywidth;
				$halfv = $halfbod;
			}
	}


# In a *very* thin package, there may not be room to print the value, but
# by default we do.

$printval = 1;

#
# Figure out how many description lines are specified on the command line.
# One should start from the beginning; if des1 is blank but des3 isn't,
# des3 still won't print.
#

$ndes = 0;
$ndes++ if ($des1 ne "");
$ndes++ if ($des2 ne "");
$ndes++ if ($des3 ne "");

#
# If the text space is constrained only by the body width
# (e.g. no SMDs or pins are placed within the package
# outline), then we want to raise the >VALUE line up a bit
# so as to not crowd the numeral "1" in the pin-one corner.
#

if ($halfv ==  $halfbod)
	{
		$offsetval = 1;
	}
else
	{
		$offsetval = 0;
	}

#
# Now figure out which size text to use. Set the $usetxtsz to -1
# as a marker to indicate it hasn't yet been set.
#

$usetxtsz = -1;


#
# The rows in @stdfit are organized such that the row number is
# one plus twice the number of description lines, plus one if the
# valule line must be raised. Row zero of @stdfit is for when
# there is no room even to print a valule line.
#

#
# Optimally, we'll print the value and name lines, all the requested
# description lines, and offset the value line if necessary, so
# first set a row index ($k) to according to these specs and then
# look for the largest text size that will fit in the available space.
#

$k = 1 + (2 * $ndes) + $offsetval;

try: for ($i = 9; $i >= 0; $i--)
	{
		if ($stdfit[$k][$i] < $vspace)
			{
				$usetxtsz = $i;
				$fitslice = $k;
				last try;
			}
	}

#
# if $usetxtsize hasn't been set, then it must be that all our
# requested text just won't fit. As a first strategy, we start
# dropping off description lines, assuming that we'll need to
# use the smallest text size in any event...
#

if ($usetxtsz < 0)
	{
		tryagain: for ($ndes--; $ndes >= 0; $ndes--)
			{
				$k = 1 + (2 * $ndes) + $offsetval;
				if ($stdfit[$k][0] < $vspace)
					{
						$usetxtsz = 0;
						$fitslice = $k;
						last tryagain;
					}
			}
	}

#
# If $usetxtsz *still* isn't set, then we're going to
# to have to drop the value line (the name line is
# essential.
#

if ($usetxtsz < 0)
	{
		# since all we have to place is the name line in this
		# case, it's pretty simple.
		$usetxtsz = 0;
		$printval = 0;
		$fitslice = 0;
		$valladd = 0;
		$namey =  -1 * $stdtxtlg[0]/2;
		$nameyf = sprintf("%.3f",$namey);
	}
else
	{
		#
		# if we've gotten here, then we've got a text
		# size to use, and we will print at a minimum
		# both the text and value lines.
		#
		# First, figure how much to raise up the value line,
		# if at all:
		#
		if ($offsetval > 0)
			{	
				$valadd = $linesep + $stdtxtlg[$usetxtsz];
			}
		else
			{
				$valadd = 0;
			}

		# $namey is the hieght (y coordinate) of the bottom of the name line.
		$namey = $halfv - ($linesep + $stdtxtlg[$usetxtsz]);
		$nameyf = sprintf("%.3f",$namey);

		# $valuey is the hieght of the bottom of the valule line.
		$valuey = $valadd + $linesep - $halfv;
		$valueyf = sprintf("%.3f",$valuey);

		# $desspace is how much space is left between the value
		# and name lines to put the description lines.
		$desspace = $namey - ($valuey + $stdtxtlg[$usetxtsz]);

		# $halfdes is, well duh...
		$halfdes = $desspace/2;

		#
		# $desymmiddle is the y position of the bottom of a description
		# line that would be placed in the middle of the $desspace zone.
		# so that the middle of the space between the value and name
		# lines will be at exactly half the text height.
		#

		$desymiddle = $namey - ($halfdes + $stdtxtsm[$usetxtsz]/2);
	}

printf STDERR "nameyf $nameyf valueyf $valueyf desspace $desspace halfdes $halfdes desymiddle $desymiddle\n" if ($debug > 0);


#
# figure out where to put the description lines
#

if ($ndes == 1)
	{
		#
		# one description line: put it in the middle
		#
		$des1yf = sprintf("%.3f",$desymiddle);
	}
elsif ($ndes == 2)
	{
		#
		# Two description lines: one above and one below the middle, by $linesep/2
		#
		$des1yf = sprintf("%.3f",($desymiddle + ($linesep + $stdtxtsm[$usetxtsz])/2));
		$des2yf = sprintf("%.3f",($desymiddle - ($linesep + $stdtxtsm[$usetxtsz])/2));
	}
elsif ($ndes == 3)
	{
		#
		# three description lines: one in the middle, the other two
		# above and below by the text height and a line separator.
		#
		$des1yf = sprintf("%.3f",($desymiddle + ($linesep + $stdtxtsm[$usetxtsz])));
		$des2yf = sprintf("%.3f",$desymiddle);
		$des3yf = sprintf("%.3f",($desymiddle - ($linesep + $stdtxtsm[$usetxtsz])));
	}

printf STDERR "des1yf $des1yf des2yf $des2yf des3yf $des3yf\n" if ($debug > 0);

#
# Spit out the rest of the text...
#

#
# Name, value and "1" line are large-size text
#

print "Change size $stdtxtlg[$usetxtsz];\n";

#
# The name line goes on the tNames layer...
#

print "Layer tNames;\n";
print "Text \'>NAME\' R0 (-$textstartf $nameyf) ;\n";

#
# Only print out the valule line if $printval > 0
# The value line goes on the tValues layer...
#

print "Layer tValues;\n" if ($printval > 0);
print "Text \'>VALUE\' R0 (-$textstartf $valueyf) ;\n" if ($printval > 0);

#
# The "1" needs to go on the tPlace layer
# XXXXXXX: This needs some more thought; the tPlace will usually go on the silkscreen,
# and we don't want any silkscreen going on the SMDs. I haven't carefully thought this
# through yet, although in all of my examples it hasn't been a problem. I had been
# using the large text size for this, but I've changed it to small to minimize the
# chance of it being a problem until I think it through some more.
#

print "Change size $stdtxtsm[$usetxtsz];\n";
print "Layer tPlace;\n";
print "Text \'1\' R0 ($onexf $oneyf) ;\n";

#
# The description lines use small text. 
#

print "Change size $stdtxtsm[$usetxtsz];\n";

#
# Layer 250, "Descript", is a non-standard layer, but this is what Cadsoft
# did in their IPC packages. I've simply followed suit here. Since it is
# non-standard, we have to create it and set the color and fill style...
#

print "Layer 250 Descript;\n";
print "SET COLOR_LAYER Descript Cyan;\n";
print "SET FILL_LAYER Descript WideDot;\n";

#
# Finally, place the descriptive text
#

print "Text \'$des1\' R0 (-$textstartf $des1yf) ;\n" if ($ndes > 0);
print "Text \'$des2\' R0 (-$textstartf $des2yf) ;\n" if ($ndes > 1);
print "Text \'$des3\' R0 (-$textstartf $des3yf) ;\n" if ($ndes > 2);

#
# Now we have to place the SMDs, which go on the layer Top.
#

print "Layer Top;\n";

#
# Initialize $smdcenterx and $smdcenteryf to the center of the
# first SMD to be placed. SMDs will be given sequential numbers
# going around the package, as is traditional in SO parts.
#

$smdcenterx=(1 - $hpc)*$pitch/2;
$k = $pincount + 1;
$smdcenteryf = sprintf("%.3f",(($smdsep + $smddy) / 2));

for ($i = 1; $i <= $hpc; $i++)
	{
		$k--;
		$smdcenterxf = sprintf("%.3f",$smdcenterx);
		print "SMD $smdsizef \'$k\' ($smdcenterxf $smdcenteryf);\n";
		print "SMD $smdsizef \'$i\' ($smdcenterxf -$smdcenteryf);\n";
		$smdcenterx += $pitch;
	}

#
# Finally, reset the grid and zoom to fit...
#
print "Grid mm $gridfinal $gridfinalmult on;\n";
print "Window Fit;\n";
