From: Dan White Date: Tue, 14 Feb 2012 19:28:10 +0000 (-0600) Subject: Add TI VQFN package generator X-Git-Tag: calibrations~242 X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=a7a089351fc0058b3ef849f2644db559d03e9cd3;p=430.git Add TI VQFN package generator --- diff --git a/sch-pcb/fp/Pcb-letter.pdf b/sch-pcb/fp/Pcb-letter.pdf new file mode 100644 index 0000000..f1ab9a2 Binary files /dev/null and b/sch-pcb/fp/Pcb-letter.pdf differ diff --git a/sch-pcb/fp/Pcb_9.pm b/sch-pcb/fp/Pcb_9.pm new file mode 100644 index 0000000..cfce576 --- /dev/null +++ b/sch-pcb/fp/Pcb_9.pm @@ -0,0 +1,1224 @@ +# Copyright (C) 2007 John C. Luciani Jr. + +# This program may be distributed or modified under the terms of +# version 0.2 of the No-Fee Software License published by +# John C. Luciani Jr. + +# A copy of the license is at the end of this file. + +package Pcb_9; +require Exporter; +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); +@ISA = qw(Exporter); +@EXPORT = qw(get_field_format scaled_value flag_value_element flags); +@EXPORT_OK = qw(element_get_field_names dim_field_p element_get_names element_str + ELEMENT_NAME_HIDDEN ELEMENT_SELECTED ELEMENT_SOLDER_SIDE + PIN_MASK PIN_ALWAYS_SET PIN_CONNECTED PIN_MOUNTING_HOLE PIN_DISPLAY_NAME + PIN_SELECTED PIN_SQUARE PIN_OCTAGONAL PIN_ROUND PIN_SHAPE_MASK + PAD_CONNECTED PAD_DISPLAY_NAME PAD_SELECTED PAD_SOLDER_SIDE PAD_SQUARE + PAD_ROUNDED TEXT_ON_SOLDER_SIDE); +%EXPORT_TAGS = (flags => [qw(ELEMENT_NAME_HIDDEN ELEMENT_SELECTED ELEMENT_SOLDER_SIDE + PIN_MASK PIN_ALWAYS_SET PIN_CONNECTED PIN_MOUNTING_HOLE PIN_DISPLAY_NAME + PIN_SELECTED PIN_SQUARE PIN_OCTAGONAL PIN_ROUND PIN_SHAPE_MASK + PAD_CONNECTED PAD_DISPLAY_NAME PAD_SELECTED PAD_SOLDER_SIDE PAD_SQUARE + PAD_ROUNDED TEXT_ON_SOLDER_SIDE)]); + +use strict; +use warnings; +use Carp; +use POSIX; +use Data::Dumper; + +### \title{Creating PCB Elements with Perl} +### \author{John C. Luciani Jr.} +### \date{\today} +### \maketitle + +### \section{Change Log} + +### \begin{tabular}{lccp{4in}} +### {\tt Pcb\_9} & ??? & {\tt jcl} &% +### 1. Fixed a dimension scaling bug in element\_add\_lines. +### The scaling routine now scales an array of points. +### This bug was reported by Ben Jackson.\\ +### &&& 2. The scaling routines now accept a dimension suffix which will +### override the default dimension.\\ +### {\tt Pcb\_8} & 19-Mar-2007 & {\tt jcl} &% +### 1. Removed the export of element\_add\_arc. Not necessary (OO).\\ +### &&& 2. Corrected the mask and clearance parameters in the pin, pad and pin\_oval procedures.\\ +### &&& 3. Removed the Mark command since the mark data is now in the Element header.\\ +### &&& 4. Exported element\_str and added a scale\_factor parameter (default value of 100)\\ +### &&& 5. the key to specify dimensional units (input\_dim) was changed to dim\\ +### &&& 6. Fixed the dimension scaling problem in {\tt add\_element\_lines}\\ +### &&& 7. Corrected the documentation for {\tt element\_add\_pin\_oval}\\ +### {\tt Pcb\_7} & 25 March 2005 & {\tt jcl} &% +### 1. changed the definition of the mask and clearance.\\ +### &&& 2. Fixed the mask and clearance parameters in the pin, pad and pin\_oval procedures.\\ +### {\tt Pcb\_6} & 22 March 2005 & {\tt jcl} &% +### 1. The {\tt element\_add\_rectangle} command now uses the {\tt x} and {\tt y} +### parameters. The center of the rectangle was always placed at (0,0)\\ +### &&& 2. The {\tt pin\_one\_square} key-value pair was not getting properly tested +### in the {\tt element\_add\_pin} procedure.\\ +### &&& 3. Added the {\tt clearance} and the {\tt mask} parameters to {\tt element\_add\_pad\_rectangle}.\\ +### {\tt Pcb\_5} & 6 March 2005 & {\tt jcl} &% +### 1. Added the {\tt element\_add\_lines} command.\\ +### &&& 2. added the {\tt element\_add\_pin\_oval} command.\\ +### &&& 3. Modified the debug print messages.\\ +### &&& 4. Fixed constant for octagonal pads.\\ +### &&& 5. Fixed errors in the EXPORT\_OK and EXPORT\_TAGS declarations.\\ +### &&& 6. Added {\tt element\_get\_names}.\\ +### {\tt Pcb\_4} & 27 February 2005 & {\tt jcl} &% +### 1. Modified the debug strings to output mm and mils.\\ + +### &&& 2. Fixed the {\tt scale\_factor} subroutine. {\tt +### scale\_factor} did not correctly convert from mils to mm. I did +### not test (or use) the conversion to mm until I modified the +### debug strings\\ + +### {\tt Pcb\_3} & 7 February 2005 & {\tt jcl } & Initial Release\\ +### \end{tabular} + +### \section{Pcb\_9} + +### This document describes a set of Perl routines that can be used to +### create component footprints for the circuit board layout program +### \href{http://bach.ece.jhu.edu/~haceaton/pcb}{PCB}. These routines +### reside in a file called |Pcb_|\|.pm| where \ is the current +### revision number of the package. Only the new format of PCB +### elements is output. The differences (that I am aware of) between +### the old and new formats are: + +### \begin{itemize} +### \item Dimensions are in hundreths of a mil. +### \item The argument delimiters are square brackets |[]| +### \item The element command adds the |mark_x| and |mark_y| parameters +### \item The pin and pad command add clearance and mask parameters. +### \end{itemize} +###\par + +### \subsection*{Requirements} + +### These routines should run with a standard Perl distribution. The +### only packages used are |POSIX| and |Carp|.\par + +### \subsection*{Usage} + +### These routines are object oriented. A PCB object is created using +### |new| and all subsequent method calls use this +### object. |element_begin| starts a new element. |element_output| +### outputs the element file. |element_add_mark| sets the component +### centroid. |element_set_text_xy| sets the text position for the +### reference designator. The names of the methods used to draw +### elements all start with the string |element_add|. Arguments for +### the method calls are key-value pairs. The keys are parameter +### strings defined in +### \href{http://pcb.sourceforge.net/pcb-20050127.html/index.html}{pcb.html}.\par + +### \medskip\noindent To use these routines in a Perl script to create a PCB element: + +### \begin{enumerate} +### \item Include the PCB routines |use Pcb_|\|;| +### \item Create a PCB object using |new| +### \item Begin an element using |element_begin| +### \item Add copper to the element using |element_add_pin| or |element_add_pad| +### \item Add silkcreen elements using |element_add_line|, |element_add_arc|, +### \item Mark the centroid using |element_add_mark|. The mark can +### also be set using parameters of the |element_begin| method. +### \item Add the text location for the reference designator using |element_set_text_xy| +### The text location can also be set using parameters of the |element_begin| method. +### \item Output the element to a file using |element_output| +### \end{enumerate} + +### The simple example in \autoref{lst:res example} creates a +### quarter~watt through-hole resistor. The example in +### \autoref{lst:smd example} creates a variety of two terminal SMD +### footprints ranging in size from |0402| to |2512|. The example in +### \autoref{lst:th example} creates Molex 8624 series header +### connector footprints. The example in \autoref{lst:tqfn example} +### creates TQFN footprints for a variety of Maxim parts. + +### These examples place files in the directory |./tmp|. This can be +### easily changed by changing the |element_begin| call. + +###\lstinputlisting[% +### label=lst:res example,% +### caption=1/4 Watt Resistor Example]{pcb-example-res} + +### \section{Examples} +### \label{sec:examples} + +###\lstinputlisting[% +### label=lst:to220 example,% +### caption=TO220 Pads]{pcb-example-TO220-pads} + +### \newpage +###\lstinputlisting[% +### label=lst:smd example,% +### caption=SMD Element Creation Example]{pcb-example-smd} + +###\newpage +###\lstinputlisting[% +### label=lst:th example,% +### caption=Header Connector Creation Example 1]{pcb-example-hdr1} + +###\newpage +###\lstinputlisting[% +### label=lst:th example,% +### caption=Header Connector Creation Example 2]{pcb-example-hdr2} + +###\newpage +###\lstinputlisting[% +### label=lst:tqfn example,% +### caption=TQFN Element Creation Example]{pcb-example-tqfn} + +### \section{Element Flags} + +### The element flag field determines the state of an element. The bit +### values are: + +### @key_value_table@ +use constant ELEMENT_NAME_HIDDEN => 0x10; ### bit 4: the element name is hidden +use constant ELEMENT_SELECTED => 0x40; ### bit 6: element has been selected +use constant ELEMENT_SOLDER_SIDE => 0x80; ### bit 7: element is located on the solder side +### @end_key_value_table@ Element Flags + +### \section{Text Flags} + +### @begin_key_value_table@ +use constant TEXT_DIRECTION_0 => 0; ### Horizontal +use constant TEXT_DIRECTION_90 => 1; ### 90 degrees counter-clockwise +use constant TEXT_DIRECTION_180 => 2; ### 180 degrees counter-clockwise +use constant TEXT_DIRECTION_270 => 3; ### 270 degrees counter-clockwise +### @end_key_value_table@ Text Direction Flags + +### @begin_key_value_table@ +use constant TEXT_SELECTED => 0x40; ### bit 6: the text has been selected +use constant TEXT_ON_SOLDER_SIDE => 0x80; ### bit 7: the text is on the solder (back) side of the board +use constant TEXT_ON_SILKSCREEN => 0x400; ### bit 10: the text is on the silkscreen layer +### @end_key_value_table@ Text Flags + +### \section{Pin Flags} + +### @key_value_table@ +use constant PIN_MASK => 0xFFFD; ### +use constant PIN_ALWAYS_SET => 0x0001; ### bit 0: always set + ### bit 1: always clear +use constant PIN_CONNECTED => 0x0004; ### bit 2: set if pin was found during a connection search +use constant PIN_MOUNTING_HOLE => 0x0008; ### bit 3: set if pin is only a mounting hole (no copper annulus) +use constant PIN_DISPLAY_NAME => 0x0020; ### bit 5: display the pins name +use constant PIN_SELECTED => 0x0040; ### bit 6: pin has been selected +use constant PIN_SQUARE => 0x0100; ### bit 8: pin is drawn as a square +use constant PIN_OCTAGONAL => 0x0800; ### bit 12: set if pin is drawn with an octagonal shape +use constant PIN_ROUND => 0x0000; ### +use constant PIN_SHAPE_MASK => 0xEEFF; ### +### @end_key_value_table@ Pin Flags + +### \section{Pad Flags} + +### @key_value_table@ +use constant PAD_CONNECTED => 0x0004; ### bit 2: set if pad was found during a connection search +use constant PAD_DISPLAY_NAME => 0x0020; ### bit 5: display the pads name +use constant PAD_SELECTED => 0x0040; ### bit 6: pad has been selected +use constant PAD_SOLDER_SIDE => 0x0080; ### bit 7: pad is located on the solder side +use constant PAD_SQUARE => 0x0100; ### +use constant PAD_ROUNDED => 0x0800; ### bit 11: pad has rounded corners +### @end_key_value_table@ Pad Flags + +### \Method new\\ + +### \Usage Pcb_9 -> new\\ + +### \Description + +### Creates an object that is used to make PCB element files. Default +### parameters for the various element drawing commands can be +### initialized using a key-value parameter list. + +### \medskip\noindent The valid keys and default values are in +### \autoref{tab:kv new} + +sub new { + my $class = shift; + my $self = { + ### @key_value_table@ + line_thickness => 10, ### thickness used in drawing silkscreen lines + arc_thickness => 10, ### thickness used in drawing silkscreen arcs + thickness => 10, ### thickness used in drawing any silkscreen line + pin_flags => 0, ### flags used in creating element pins (See \autoref{tab:kv pin flags}) + pad_flags => PAD_SQUARE, ### flags used in creating pads + font_size => 50, ### size in ??? of the silkscreen found + clearance => 10, ### \clearanceDEF + mask => 10, ### \maskDEF + debug => 0, ### debug messages. no messages (0). object methods (1). object methods + internal subroutines (2) + ### @end_key_value_table@ Keys for Method new | new + &_scale_dim(dim => 'mils', @_), + }; + bless $self, $class; # bless $self into the designated class + + printf("(new) Creating a new Pcb object\n") + if $self -> debug_p; + + # initialization + + return $self; +} + +### \Example + +### To create a new object that will display object method debugging +### messages:\par +### \medskip\noindent +### \begin{lstlisting}[numbers=none,frame=none] +### my $Pcb = Pcb_9 -> new(debug => 1); +### \end{lstlisting} + + + + +### \Method element_begin\\ + +### \Usage Pcb -> element_begin\\ + +### \Description + +### Initializes a new Pcb element. If an element was previously +### created but not output a call to |element_begin| will remove it. + +### \medskip\noindent The valid keys and default values are in +### \autoref{tab:kv element-begin} + +sub element_begin { + my $self = shift; + $self->{element} = + { + ### @key_value_table@ + flags => 0, ### \elementflagsDEF + description => '', ### \descriptionDEF + layout_name => '', ### \layoutnameDEF + value => '', ### \valueDEF + mark_x => 0, ### \markxDEF + mark_y => 0, ### \markyDEF + text_x => 0, ### \textxDEF + text_y => 0, ### \textyDEF + direction => 0, ### \directionDEF + scale => 100, ### \scaleDEF + text_flags => 0, ### \textflagsDEF + output_file => 'PCB_ELEMENT.TMP', ### Element filename + pin_one_square => 0, ### Sets a default value that is used when creating a pin. + dim => 'mils', ### units default to mils + ### @end_key_value_table@ Keys for Method element\_begin | element-begin + _elements => [], + $self -> scale_dim(@_) + }; + + printf("(element_begin) Creating element file %s\n", $self -> element_get('output_file')) + if $self -> debug_p; + +} + +### \Example + +### To begin a 1/4 Watt resistor element with dimension values in mils:\par +### \medskip\noindent +### \begin{lstlisting}[numbers=none,frame=none] +### $Pcb -> element_begin(description => 'resistor', +### output_file => '025W', +### dim => 'mils'); +### \end{lstlisting} + + +### \Method element_output\\ + +### \Usage Pcb -> element_output\\ + +### \Description + +### |element_output| outputs the element drawing commands to a +### file. At this time there are no parameters that are valid for the +### \. + +sub element_output ($) { + my ($self) = @_; + my $ref = $self->{element}; + if (defined $ref->{output_file}) { + my $output_file = $ref->{output_file}; + open(OUTFILE, ">$output_file") or + croak "(Pcb) (element_output) Could not open $output_file for output"; + printf(OUTFILE "Element[0x%x \"%s\" \"%s\" \"%s\" %i %i %i %i %i %i 0x%x]\n", + hex($ref->{flags}), + $ref->{description}, + $ref->{layout_name}, + $ref->{value}, + $ref->{mark_x} * 100, + $ref->{mark_y} * 100, + $ref->{text_x} * 100, + $ref->{text_y} * 100, + $ref->{direction}, + $ref->{scale}, + hex($ref->{text_flags})); + printf(OUTFILE "(\n"); + foreach (@ { $ref->{_elements} }) { + printf(OUTFILE " %s\n", &element_str(@$_)); + } + printf(OUTFILE ")\n"); + close(OUTFILE) or croak "(Pcb) (element_output) Could not close $output_file"; + } else { + carp "(Pcb) (element_output) Element filename was not defined"; + } +} + +### \Method element_add_line\\ + +### \Usage Pcb -> element_add_line\\ + +### \Description + +### Creates a silkscreen line of a specified thickness (|thickness|) +### between two \points. + +### \BeginKVTable +### x1 & & \xoneDEF \\ +### y1 & & \yoneDEF \\ +### x2 & & \xtwoDEF \\ +### y2 & & \ytwoDEF \\ +### thickness & & \thicknessDEF \\ +### \EndKVTable{Keys for Method element\_add\_line}{element-add-line} + +sub element_add_line ($%) { + my $self = shift; + my %v = (thickness => $self -> element_get('line_thickness'), + $self -> scale_dim(@_)); + printf(" (element_add_line) adding line from %s to %s with thickness %s\n", + &_debug_str_point($v{x1}, $v{y1}), + &_debug_str_point($v{x2}, $v{y2}), + &_debug_str_dim($v{thickness})) + if $self -> debug_p; + $self -> _element_add('ElementLine', %v); +} + +### \Example + +### To create a 200mil long silkscreen line that is centered at |(0,0)| that is +### 10 mils thick\par +### \medskip\noindent +### \begin{lstlisting}[numbers=none,frame=none] +### $Pcb -> element_add_line(x1 => -100, y1 => 0, +### x2 => 100, y2 => 0, +### thickness => 10); +### \end{lstlisting} + + +### \Method element_add_arc\\ + +### \Usage Pcb -> element_add_arc\\ + +### \Description + +### Creates a silkscreen arc with a specified |width| and |length| +### centered at a \point. + +### \BeginKVTable +### x & & \xDEF\\ +### y & & \yDEF\\ +### width & & horizontal width of the arc\\ +### height & & vertical length of the arc\\ +### start\_angle & & Starting angle of the arc (degrees) \\ +### delta\_angle & & Angle swept by the arc (degrees)\\ +### thickness & & line thickness\\ +### \EndKVTable{Keys for Method element\_add\_arc}{element-add-arc} + + +sub element_add_arc ($%) { + my $self = shift; + my %v = (thickness => $self -> get('arc_thickness'), + $self -> scale_dim(@_)); + printf(" (element_add_arc) center at %s, start angle=%.0f, delta angle=%.0f\n", + &_debug_str_point($v{x}, $v{y}), + map { $v{$_} } qw(start_angle delta_angle)) + if $self -> debug_p; + $self -> _element_add('ElementArc', %v); +} + +### \Example + +### To create a silkscreen circular arc centered at |(0,0)| with a +### line thickness of 10 mils, radius of 200 mils that starts at +### 45$\Deg$ and sweeps for 135$\Deg$:\par + +### \medskip\noindent +### \begin{lstlisting}[numbers=none,frame=none] +### $Pcb -> element_add_arc(start_angle => 45, +### delta_angle => 135, +### x => 0, +### y => 0, +### width => 200, +### height => 200, +### thickness => 10); +### \end{lstlisting} + +### For an ellipse set the width and height to unequal values. + + +### \Method element_add_pin\\ + +### \Usage Pcb -> element_add_pin\\ + +### \Description + +### Adds a pin to an element + +### \BeginKVTable +### x & & \xDEF\\ +### y & & \yDEF\\ +### thickness & & width of the copper pad\\ +### clearance & & \clearanceDEF\\ +### mask & & \maskDEF\\ +### drill\_hole & & diameter of the hole that is drilled at the center of the pad\\ +### name & & string\\ +### pin\_number & & \pinnumberDEF\\ +### flags & & See \autoref{tab:kv pin flags}\\ +### \EndKVTable{Keys for Method element\_add\_pin}{element-add-pin} + +sub element_add_pin { + my $self = shift; + my %v = ( clearance => $self -> get('clearance'), + mask => $self -> get('mask'), + name => '', + flags => $self -> get('pin_flags'), + $self -> scale_dim(@_)); + + if ($v{pin_number} == 1 && $self -> element_get('pin_one_square')) { + $v{flags} &= PIN_SHAPE_MASK; + $v{flags} |= PIN_SQUARE; + } + $v{flags} &= PIN_MASK; + $v{flags} |= PIN_ALWAYS_SET; + + # The mask parameter that was passed as an argument is the + # clearance between the edge of the copper and the edge of the + # masking material. The mask value that PCB wants is the total + # diameter of hole in the mask. + + $v{mask} = $v{mask} * 2 + $v{thickness}; + $v{clearance} *= 2; + + printf(" (element_add_pin) center at %s, diameter=%s, pin_number=%s, flags=0x%x\n", + &_debug_str_point($v{x}, $v{y}), + &_debug_str_dim($v{thickness}), + defined $v{pin_number} ? sprintf("%i", $v{pin_number}) : '?', + $v{flags}) + if $self -> debug_p; + + $self -> _element_add('Pin', %v); +} + +### \Example +### +### To place a pin with a round pad at |(-100,0)| with a pad diameter of 55 mils, a drill hole diameter +### of 35 mils, soldermask clearance of 10 mils, a copper clearance of 9 mils, and a pin number of one:\par +### \medskip\noindent +### \begin{lstlisting}[numbers=none,frame=none] +### $Pcb -> element_add_pin(x => -100, y => 0, +### thickness => 55, +### drill_hole => 35, +### mask => 10, +### clearance => 9, +### pin_number => 1); +### \end{lstlisting} + +### \Method element_add_pad\\ + +### \Usage Pcb -> element_add_pad\\ + +### \Description + +### Pads are created by drawing a line, with a specified thickness, +### between two points. The line is drawn with a square nib and +### extends beyond each end point by a distance of ${\tt +### thickess}\over 2$. + +### \BeginKVTable +### x1 & & \xoneDEF \\ +### y1 & & \yoneDEF \\ +### x2 & & \xtwoDEF \\ +### y2 & & \ytwoDEF \\ +### thickness & & \thicknessDEF \\ +### clearance & & \clearanceDEF\\ +### mask & & \maskDEF\\ +### name & & \padnameDEF\\ +### pad\_number & & \padnumberDEF\\ +### flags & & See \autoref{tab:kv pad flags}\\ +### \EndKVTable{Keys for Method element\_add\_line}{element-add-line} + +sub element_add_pad { + my $self = shift; + my %v = (flags => $self -> get('pad_flags'), + clearance => $self -> get('clearance'), + mask => $self -> get('mask'), + $self -> scale_dim(@_)); + printf(" (element_add_pad) from %s to %s with thickness %s\n", + &_debug_str_point($v{x1}, $v{y1}), + &_debug_str_point($v{x2}, $v{y2}), + &_debug_str_dim($v{thickness})) + if $self -> debug_p; + + $v{mask} = $v{mask} * 2 + $v{thickness}; + $v{clearance} *= 2; + + $self -> _element_add('Pad', %v); + +} + +### \Example + +### To create a pad that is centered at |(0,0)| that is 100 mils long and 50 mils thick\par +### has a soldermask clearance of 10 mils, a copper clearance of 9 mils and is numbered one:\par +### \medskip\noindent +### \begin{lstlisting}[numbers=none,frame=none] +### $Pcb -> element_add_pad(x1 => -25, y1 => 0, +### x2 => 25, y2 => 0, +### thickness => 50, +### mask => 10, +### clearance => 9, +### pad_number => 1); +### \end{lstlisting} + + + + +### \Method element_add_pad_rectangle\\ + +### \Usage Pcb -> element_add_pad_rectangle\\ + +### \Description + +### Create a pad with a specified width and length that is centered at +### a point |(x,y)|. The length is in x-direction and the width is in +### the y-direction. + +### \BeginKVTable +### x & & \xDEF\\ +### y & & \yDEF\\ +### width & & \widthDEF\\ +### length & & \lengthDEF\\ +### clearance & & \clearanceDEF\\ +### mask & & \maskDEF\\ +### name & & \padnameDEF\\ +### pin\_number & & \pinnumberDEF\\ +### \EndKVTable{Keys for Method element\_add\_pad\_rectangle}{element-add-pad-rectangle} + + +sub _print_missing_fields { + my ($sub_name, $ref, @fields) = @_; + my $missing_fields = 0; + foreach (@fields) { + next if defined $ref->{$_}; + printf("(%s) field %s is undefined\n", $sub_name, $_); + $missing_fields = 1; + } + return($missing_fields); +} + + +sub element_add_pad_rectangle { + my $self = shift; + my %v = (flags => $self -> get('pad_flags'), + clearance => $self -> get('clearance'), + mask => $self -> get('mask'), + $self -> scale_dim(@_)); + + die if &_print_missing_fields('element_add_pad_rectangle', + \%v, + qw(width length x y name pin_number clearance mask)); + + my ($x1, $x2, $y1, $y2); + my $thickness; + if ($v{width} < $v{length}) { + $thickness = $v{width}; + $y1 = $v{y}; $y2 = $v{y}; + $x1 = $v{x} - ($v{length} - $thickness) / 2; + $x2 = $v{x} + ($v{length} - $thickness) / 2; + } else { + $thickness = $v{length}; + $x1 = $v{x}; $x2 = $v{x}; + $y1 = $v{y} - ($v{width} - $thickness) / 2; + $y2 = $v{y} + ($v{width} - $thickness) / 2; + } + + printf(" (element_add_pad_rectangle) width = %s, length = %s, center at %s\n", + &_debug_str_dim($v{width}), + &_debug_str_dim($v{length}), + &_debug_str_point($v{x}, $v{y})) + if $self -> debug_p; + + $self -> element_add_pad(x1 => $x1, x2 => $x2, + y1 => $y1, y2 => $y2, + thickness => $thickness, + name => $v{name}, + pin_number => $v{pin_number}, + clearance => $v{clearance}, + mask => $v{mask}, + flags => $v{flags}, + dim => 'mils'); +} + + + +### \Method element_add_pin_oval\\ + +### \Usage Pcb -> element_add_pin_oval\\ + +### \Description + +### Create a pad with a specified width and length that is centered at +### a point |(x,y)|. The length is in x-direction and the width is in +### the y-direction. The corners of the pad are rounded.\par + +### \medskip\noindent This is actually a hybrid object consisting of a +### component side pad, a solder side pad and a pin placed at the same +### center point. + +### \BeginKVTable +### x & & \xDEF\\ +### y & & \yDEF\\ +### width & & \widthDEF\\ +### length & & \lengthDEF\\ +### drill\_hole & & diameter of the hole that is drilled at the center of the pad\\ +### name & & \padnameDEF\\ +### pin\_number & & \pinnumberDEF\\ +### \EndKVTable{Keys for Method element\_add\_pin\_oval}{element-add-pin-oval} + +sub element_add_pin_oval { + my $self = shift; + my %v = ( clearance => $self -> get('clearance'), + mask => $self -> get('mask'), + $self -> scale_dim(@_)); + my ($x1, $x2, $y1, $y2); + my $thickness; + if ($v{width} < $v{length}) { + $thickness = $v{width}; + $y1 = $v{y}; $y2 = $v{y}; + $x1 = $v{x} - ($v{length} - $thickness) / 2; + $x2 = $v{x} + ($v{length} - $thickness) / 2; + } else { + $thickness = $v{length}; + $x1 = $v{x}; $x2 = $v{x}; + $y1 = $v{y} - ($v{width} - $thickness) / 2; + $y2 = $v{y} + ($v{width} - $thickness) / 2; + } + + printf(" (element_add_pad_oval) width = %s, length = %s, center at %s\n", + &_debug_str_dim($v{width}), + &_debug_str_dim($v{length}), + &_debug_str_point($v{x}, $v{y})) + if $self -> debug_p; + + + $self -> element_add_pad(x1 => $x1, x2 => $x2, + y1 => $y1, y2 => $y2, + thickness => $thickness, + flags => PAD_ROUNDED, + dim => 'mils', + map { $_ => $v{$_} } qw(name pin_number clearance mask)); + + $self -> element_add_pad(x1 => $x1, x2 => $x2, + y1 => $y1, y2 => $y2, + thickness => $thickness, + flags => PAD_ROUNDED | PAD_SOLDER_SIDE, + dim => 'mils', + map { $_ => $v{$_} } qw(name pin_number clearance mask)); + + + $self -> element_add_pin(x => ($x1 + $x2) / 2, + y => ($y1 + $y2) / 2, + name => '', + pin_number => $v{pin_number}, + thickness => $thickness, + dim => 'mils', + drill_hole => $v{drill_hole}, + mask => $v{mask}, + flags => 0, + clearance => $v{clearance}); +} + +### \Example + +### To place a pin with an oval pad at |(-100,0)| with a pad diameter +### of 55 mils, a drill hole diameter of 35 mils, soldermask clearance +### of 10 mils, a copper clearance of 9 mils, and a pin number of +### one:\par + +### \medskip\noindent +### \begin{lstlisting}[numbers=none,frame=none] +### $Pcb -> element_add_pin_oval(x => -100, y => 0, +### thickness => 55, +### drill_hole => 35, +### mask => 10, +### clearance => 9, +### pin_number => 1); +### \end{lstlisting} + + +### \Method element_add_mark\\ + +### \Usage Pcb -> element_add_mark\\ + +### \Description + +### The mark is a positioning hint. |element_add_mark| places the mark at +### at a \point. + +### \BeginKVTable +### x & & \xDEF \\ +### y & & \yDEF \\ +### \EndKVTable{Keys for Method element\_add\_mark}{element-add-mark} + +sub element_add_mark ($%) { + my $self = shift; + my %v = $self -> scale_dim(@_); + printf(" (element_add_mark) mark at %s\n", + &_debug_str_point($v{x}, $v{y})) + if $self -> debug_p; + $self -> _element_add('Mark', %v); +} + +### \Method element_add_lines\\ + +### \Usage Pcb -> element_add_lines\\ + +### \Description + +### Draws silkscreen lines using the specified line end points. Lines +### are drawn from point to point until all the points are connected. + +### \BeginKVTable +### points & & reference to a list containing x,y coordinates for line end points.\\ +### thickness & & \thicknessDEF\\ +### \EndKVTable{Keys for Method element\_add\_lines}{element-add-lines} + +sub element_add_lines { + my $self = shift; + my %v = (thickness => $self -> element_get('line_thickness'), + $self -> scale_dim(@_)); + my @pts = @ { $v{points} }; + while (@pts) { + my ($x1, $y1) = splice @pts, 0, 2; + last if $#pts < 1; + $self -> element_add_line(x1 => $x1, y1 => $y1, + x2 => $pts[0], y2 => $pts[1], + thickness => $v{thickness}, + dim => 'mils'); + } +} + + +### \Method element_add_rectangle\\ + +### \Usage Pcb -> element_add_rectangle\\ + +### \Description + +### Draws a silkscreen rectangle with a specified |width| and |length| at a \point. + +### \BeginKVTable +### x & & \xDEF\\ +### y & & \yDEF\\ +### width & & rectangle width (y direction)\\ +### length & & rectangle length (x direction)\\ +### thickness & & \thicknessDEF\\ +### \EndKVTable{Keys for Method element\_add\_rectangle}{element-add-rectangle} + +sub element_add_rectangle { + my $self = shift; + my %v = (x => 0, + y => 0, + thickness => $self -> element_get('line_thickness'), + $self -> scale_dim(@_)); + + # x1,y1 lower left + # x2,y2 upper right + + my $x1 = $v{x} - $v{length} / 2; + my $x2 = $v{x} + $v{length} / 2; + my $y1 = $v{y} + $v{width} / 2; + my $y2 = $v{y} - $v{width} / 2; + $self -> element_add_lines(points => [$x1, $y1, $x1, $y2, $x2, $y2, $x2, $y1, $x1, $y1], + %v, + dim => 'mils'); +} + + +### \Method element_set_text_xy\\ + +### \Usage Pcb -> element_set_text_xy\\ + +### \Description + +### Sets the position of the reference designator text. + +### \BeginKVTable +### x & & \xDEF \\ +### y & & \yDEF \\ +### font\_size & & \\ +### \EndKVTable{Keys for Method element\_add\_mark}{element-add-mark} + +sub element_set_text_xy ($%) { + my $self = shift; + my %v = (font_size => $self -> element_get('font_size'), + $self -> scale_dim(@_)); + printf(" (element_set_text_xy) text at %s\n", + &_debug_str_point($v{x}, $v{y} - $v{font_size})) + if $self -> debug_p; + $self -> element_set(text_x => $v{x}, + text_y => $v{y} - $v{font_size}); +} + +### \Method element_set\\ + +### \Usage Pcb -> element_set\\ + +### \Description + +### Sets values in the element hash table. This should be the only +### method used to set values in the element hash. \ +### contains key-value pairs. + +sub element_set ($@) { + my ($self, @key_value_pairs) = @_; + while (@key_value_pairs) { + my ($k, $v) = splice @key_value_pairs, 0, 2; + next if $k =~ /^_/; # do not set private variables + $self->{element}{$k} = $v; + } +} + +### \Method element_get\\ + +### \Usage Pcb -> element_get\\ + +### \Description + +### Returns a value, from the element hash, for each key specified in +### \. If the value is undefined in the element hash +### then a value from the Pcb object hash is returned. A value of +### |undef| is returned if neither hash contains a defined value for +### the key.\par + +### \medskip\noindent This should be the only method used to retrieve +### values from the element hash. \ contains a list of +### keys.\par + +### \medskip\noindent + +sub element_get ($@) { + my ($self, @keys) = @_; + my @retvals; + foreach my $key (@keys) { + my $value = $self->{element}{$key}; + $value = $self -> get($key) unless defined $value; + push @retvals, $value; + } + return @retvals if wantarray(); + return $retvals[0] if defined wantarray(); + return; +} + + +### \Method get\\ + +### \Usage Pcb -> get\\ + +### \Description + +### Retrieves values from the PCB object hash. This should be the +### only method used to retrieve values from the PCB object hash. +### \ contains a list of keys. + +sub get ($@) { + my ($self, @keys) = @_; + my @retvals = map { $self->{$_} } @keys; + return @retvals if wantarray(); + return $retvals[0] if defined wantarray(); + return; +} + +sub debug_p { shift() -> get('debug') } + + +# Since these debug routines are only meant to be called from within +# the Pcb package distance is assumed to be mils. + +sub _debug_str_dim ($) { + my $dim = shift; + return 'undef' unless defined $dim; + sprintf("%.2f (%.2f)", $dim, &scaled_value($dim, 'mils', 'mm')); +} + +sub _debug_str_point ($$$) { + my ($x, $y) = @_; + return sprintf("x=%s, y=%s", (map { &_debug_str_dim($_) } $x, $y)); +} + + +### \Method element_dump\\ + +### \Usage Pcb -> element_dump\\ + +### \Description + +### A debugging procedure that Prints out the element command drawing +### commands to STDOUT. + +sub element_dump { + my ($self) = @_; + my $ref = $self->{element}; + my @fields = qw(flags description layout_name value text_x text_y direction scale text_flags); + foreach (@fields) { + printf("field %s = %s\n", $_, $ref->{$_}); + } + printf("Element(0x%x \"%s\" \"%s\" \"%s\" %i %i %i %i 0x%x)\n", map {$ref->{$_}} @fields); + printf("(\n"); + foreach (@ { $ref->{_elements} }) { + printf(" %s\n", &element_str(@$_)); + } + printf(")\n"); +} + + + +my %Element_fields; +my %Fields; + +BEGIN +{ + + %Element_fields = ( Element => [qw(flags description layout_name value mark_x mark_y + text_x text_y direction scale text_flags)], + ElementLine => [qw(x1 y1 x2 y2 thickness)], + ElementArc => [qw(x y width height start_angle delta_angle thickness)], + Pin => [qw(x y thickness clearance mask drill_hole name pin_number flags)], + Pad => [qw(x1 y1 x2 y2 thickness clearance mask name pin_number flags)]); + + %Fields = ((map { $_ => { dim => 0, format => '0x0%x'} } + qw(flags text_flags)), + (map { $_ => { dim => 1, format => '%i'} } + qw(text_x text_y + mark_x mark_y + clearance mask + line_thickness arc_thickness + x1 y1 x2 y2 + thickness width + height length x y drill_hole + xoffset yoffset + points + )), + (map { $_ => { dim => 0, format => '%i' } } + qw(start_angle delta_angle direction scale)), + (map { $_ => { dim => 0, format => '"%s"' } } + qw(description layout_name value name pin_number))); + +} + +sub dim_field_p ($) { + my $field_name = shift; + return $Fields{$field_name}{dim} if exists $Fields{$field_name}{dim}; + return 0; +} + +sub element_p { defined $Element_fields{ shift() } } + +sub get_field_format { + my $name = shift; + join(' ', + map { defined $Fields{$_}{format} ? $Fields{$_}{format} : "***$_***" } + &element_get_field_names($name)); +} + +sub element_get_names { + return keys %Element_fields; +} + +sub element_get_field_names ($) { + my ($name) = @_; + return () unless defined $Element_fields{$name}; + return @ { $Element_fields{$name} }; +} + +sub element_str { + my $element_name = shift; + my %v = (scale_factor => 100, + @_); + my $str; + croak "(Pcb) (element_str) Unknown element type '$element_name'", return('') + unless &element_p($element_name); + my @arg; + + foreach my $fn (&element_get_field_names($element_name)) { + croak "(Pcb) (element_str) Missing field value for field $fn, element $element_name" + unless defined $v{$fn}; + + $v{$fn} *= $v{scale_factor} if &dim_field_p($fn); + + push @arg, $v{$fn}; + } + $str = sprintf("%s[" . &get_field_format($element_name) . "]", $element_name, @arg); + return $str; +} + +# Scales dimension field values to mils. Field values that are not +# dimensions are left unchanged. Field names and values are returned +# as a list of key-value pairs. + +sub _scale_dim { + my %args = (dim => 'mils', @_); + my @retval; + foreach my $key (keys %args) { + push @retval, $key; + push(@retval, $args{$key}), next unless &dim_field_p($key); + if (ref($args{$key}) eq '') { + push(@retval, &scaled_value($args{$key}, $args{dim}, 'mils')); + } elsif (ref($args{$key}) eq 'ARRAY') { + push(@retval, [ map { &scaled_value($_, $args{dim}, 'mils') } @ { $args{$key} } ]); + } else { + printf("(Pcb_9) (_scale_dim) incorrect reference type %s for arg %s\n", + ref($args{$key}), + $key); + croak; + } + } + return (@retval); +} + +sub scale_dim ($@) { + my ($self, @args) = @_; + &_scale_dim(dim => $self -> element_get('dim'), + @args); +} + +sub _scale_factor ($) { + my ($dim) = @_; + return undef unless defined $dim; + return 1 if $dim =~ /^\s*mils?\s*$/; + return 0.01 if $dim =~ /^\s*mils?100\s*$/; + return 1000/25.4 if $dim =~ /^\s*mms?\s*$/; + return undef; +} + +sub scaled_value ($$$) { + my $value = shift; + my $from_units = shift || 'mils'; + my $to_units = shift || 'mils'; + + $from_units = $1 if $value =~ s/(\D+)$//; + + return undef unless defined $value; + return undef unless $value =~ /^[-+.0-9eE]+$/; + return $value * &_scale_factor($from_units) / &_scale_factor($to_units); +} + +# adds element definitions + +sub _element_add { + my $self = shift; + push @{ $self->{element}{_elements}}, [@_]; + return unless $self -> debug_p() > 1; + printf(" (_element_add) %s\n", shift); + while (@_) { + my ($k, $v) = splice @_, 0, 2; + printf(" %s = %s\n", map { defined $_ ? $_ : 'undef' } $k, $v); + } +} + +###\clearpage +###\ifpdfscreen% +###\phantomsection% +###\addcontentsline{toc}{section}{References}% +###\fi% +###\nocite{footprint} +###\nocite{Pcb} +#\bibliographystyle{apacite} +###\bibliography{/local/lan/texmf/bibdb/bibdb} +###\newpage + +1; + +# Style (adapted from the Perl Cookbook, First Edition, Recipe 12.4) + +# 1. Names of functions and local variables are all lowercase. +# 2. The module's persistent variables (either file lexicals +# or package globals) are capitalized. +# 3. Identifiers with multiple words have each of these +# separated by an underscore for readability. +# 4. Constants are all uppercase. +# 5. If the arrow operator (->) is followed by either a +# method name or a variable containing a method name then +# there is a space before and after the operator. +# 6. Function names, variable names, hash keys that are meant +# to be used only within the current package have an +# underscore prefix. + + +__END__ +[test program] +#!/usr/bin/perl + +# this is a test program for the various subroutines in the Pcb +# library. It is only meant to test individual routines not create a +# usable component. See the www.luciani.org for the working examples. + +use strict; +use warnings; + +use Pcb_9; + +my $Pcb = Pcb_9 -> new; + +$Pcb -> element_begin(description => 'SMD CAP 100 x 200mils'); + +$Pcb -> element_add_rectangle(width => 100, + length => 200); + +$Pcb -> element_dump; +$Pcb -> element_output; + + +$Pcb -> element_begin(description => 'SMD CAP 1mm x 2mils'); + +$Pcb -> element_add_rectangle(width => '1mm', + length => 2); + +$Pcb -> element_dump; +$Pcb -> element_output; + + +##### No-Fee Software License Version 0.2 + +#### Intent + +### The intent of this license is to allow for distribution of this +### software without fee. Usage of this software other than +### distribution, is unrestricted. + +#### License + +### Permission is granted to make and distribute verbatim copies of +### this software provided that (1) no fee is charged and (2) the +### copyright notice and license statement are preserved on all copies. + +### Permission is granted to make and distribute modified versions of +### this software provided that the entire resulting derived work is +### distributed (1) without fee and (2) with a license identical to +### this one. + +### This software is provided by the author "AS IS" and any express or +### implied warranties, including, but not limited to, the implied +### warranties of merchantability and fitness for a particular purpose +### are disclaimed. In no event shall the author be liable for any +### direct, indirect, incidental, special, exemplary, or consequential +### damages (including, but not limited to, procurement of substitute +### goods or services; loss of use, data, or profits; or business +### interruption) however caused and on any theory of liability, +### whether in contract, strict liability, or tort (including +### negligence or otherwise) arising in any way out of the use of this +### software, even if advised of the possibility of such damage. + diff --git a/sch-pcb/fp/VQFN-50P-400W-400L-24N-245WT-245LT__TI_RGE_Package.fp b/sch-pcb/fp/VQFN-50P-400W-400L-24N-245WT-245LT__TI_RGE_Package.fp new file mode 100644 index 0000000..2c29fa4 --- /dev/null +++ b/sch-pcb/fp/VQFN-50P-400W-400L-24N-245WT-245LT__TI_RGE_Package.fp @@ -0,0 +1,33 @@ +Element[0x0 "VQFN-TI-RGE-24" "" "" 0 0 -12106 -17106 0 100 0x0] +( + Pad[-8897 -4921 -6653 -4921 1102 2000 3102 "" "1" 0x0100] + Pad[-8897 -2952 -6653 -2952 1102 2000 3102 "" "2" 0x0100] + Pad[-8897 -984 -6653 -984 1102 2000 3102 "" "3" 0x0100] + Pad[-8897 984 -6653 984 1102 2000 3102 "" "4" 0x0100] + Pad[-8897 2952 -6653 2952 1102 2000 3102 "" "5" 0x0100] + Pad[-8897 4921 -6653 4921 1102 2000 3102 "" "6" 0x0100] + Pad[-4921 6653 -4921 8897 1102 2000 3102 "" "7" 0x0100] + Pad[-2952 6653 -2952 8897 1102 2000 3102 "" "8" 0x0100] + Pad[-984 6653 -984 8897 1102 2000 3102 "" "9" 0x0100] + Pad[984 6653 984 8897 1102 2000 3102 "" "10" 0x0100] + Pad[2952 6653 2952 8897 1102 2000 3102 "" "11" 0x0100] + Pad[4921 6653 4921 8897 1102 2000 3102 "" "12" 0x0100] + Pad[6653 4921 8897 4921 1102 2000 3102 "" "13" 0x0100] + Pad[6653 2952 8897 2952 1102 2000 3102 "" "14" 0x0100] + Pad[6653 984 8897 984 1102 2000 3102 "" "15" 0x0100] + Pad[6653 -984 8897 -984 1102 2000 3102 "" "16" 0x0100] + Pad[6653 -2952 8897 -2952 1102 2000 3102 "" "17" 0x0100] + Pad[6653 -4921 8897 -4921 1102 2000 3102 "" "18" 0x0100] + Pad[4921 -8897 4921 -6653 1102 2000 3102 "" "19" 0x0100] + Pad[2952 -8897 2952 -6653 1102 2000 3102 "" "20" 0x0100] + Pad[984 -8897 984 -6653 1102 2000 3102 "" "21" 0x0100] + Pad[-984 -8897 -984 -6653 1102 2000 3102 "" "22" 0x0100] + Pad[-2952 -8897 -2952 -6653 1102 2000 3102 "" "23" 0x0100] + Pad[-4921 -8897 -4921 -6653 1102 2000 3102 "" "24" 0x0100] + Pad[0 0 0 0 9645 2000 11645 "" "25" 0x0100] + ElementArc[-9169 -9169 551 551 0 360 1000] + ElementLine[-10137 10137 -10137 -10137 1000] + ElementLine[-10137 -10137 10137 -10137 1000] + ElementLine[10137 -10137 10137 10137 1000] + ElementLine[10137 10137 -10137 10137 1000] +) diff --git a/sch-pcb/fp/pcb-example-hdr1 b/sch-pcb/fp/pcb-example-hdr1 new file mode 100755 index 0000000..b7b9755 --- /dev/null +++ b/sch-pcb/fp/pcb-example-hdr1 @@ -0,0 +1,149 @@ +#!/usr/bin/perl + +# Copyright (C) 2005 John C. Luciani Jr. + +# This program may be distributed or modified under the terms of +# version 0.2 of the No-Fee Software License published by +# John C. Luciani Jr. + +# Creates the PCB elements for Molex 8624 header connectors + +use strict; +use warnings; + +use Pcb_8; + +my $Pcb = Pcb_8 -> new(debug => 1); + +my @Fields = qw(circuits body_length pin_row_length); + +my @Def; # definitions that are common to all components + +while () { + s/\#.*//; # Remove comments + s/^\s*//; # Remove leading spaces + s/\s*$//; # Revove trailing spaces + next unless length; # Skip empty lines + + # Lines that contain an '=' are global definitions. + + push(@Def, $1, $2), next if /(\S+)\s*=\s*(\S.*)/; + + my @values = split /\s*\|\s*/; + + # hash for each footprint + + my %f = ( @Def, + map { $_ => shift(@values) } @Fields); + + $Pcb -> element_begin(description => 'TH', + output_file => + "tmp/" . &package_name($f{circuits}, $f{pin_rows}), + dim => 'mils', + pin_one_square => 1); + + my $pin_num = 1; + my $pins_per_row = $f{circuits} / 2; + + # lower left corner is pin one + + my $x = -$f{pin_spacing} * ($pins_per_row - 1) / 2; + my $y = $f{row_spacing} / 2; + + # These header connectors consist of two rows of pins. With pin + # one in the lower left corner we will place pins from left to + # right until half the pins are placed. At the halfway point we + # will shift to the top row and place pins from right to left. + + while ($pin_num <= $f{circuits}) { + $Pcb -> element_add_pin(x => $x, y => $y, + thickness => 66, + drill_hole => 46, + mask => 10, + clearance => 10, + pin_number => $pin_num); + + # If this is the last pin in the row then + # update the y value otherwise update the x + # value. If we are past the halfway point move + # left (-) instead of right (+). + + $y *= -1; + $x += $f{pin_spacing} if $y > 0; + $pin_num++; + } + + $Pcb -> element_add_rectangle(width => $f{body_width}, + length=> $f{body_length}, + x => 0, + y => 0); + + + $Pcb -> element_set_text_xy(x => -$f{body_length}/2, + y => -$f{body_width}/2 - 20); + + + $Pcb -> element_output(); +} + +sub package_name ($$) { + my ($circuits, $rows) = @_; + sprintf("CON_HDR-254P-%iC-%iR-%iN__Molex_8624-Series", + $circuits/$rows, + $rows, + $circuits); +} + +__DATA__ + +body_width = 200 +pin_spacing = 100 +row_spacing = 100 +pin_diameter = 35 +pin_rows = 2 + +# circuits | body_length | pin_row_length + +4 | 190 | 100 +6 | 290 | 200 +8 | 390 | 300 +10 | 490 | 400 +12 | 590 | 500 +14 | 690 | 600 +16 | 790 | 700 +18 | 890 | 800 +20 | 990 | 900 +22 | 1090 | 1000 +24 | 1190| 1100 +26 | 1290| 1200 +28 | 1390| 1300 + +30 | 1490 | 1400 +32 | 1590 | 1500 +34 | 1690 | 1600 +36 | 1790 | 1700 +38 | 1890 | 1800 +40 | 1990 | 1900 +42 | 2090 | 2000 +44 | 2190 | 2100 +46 | 2290 | 2200 +48 | 2390 | 2300 +50 | 2490 | 2400 +52 | 2590 | 2500 +54 | 2690 | 2600 + +56 | 2790 | 2700 +58 | 2890 | 2800 +60 | 2990 | 2900 +62 | 3090 | 3000 +64 | 3190 | 3100 +66 | 3290 | 3200 +68 | 3390 | 3300 +70 | 3490 | 3400 +72 | 3590 | 3500 +74 | 3690 | 3600 +76 | 3790 | 3700 +78 | 3890 | 3800 +80 | 3990 | 3900 + + diff --git a/sch-pcb/fp/pcb-example-hdr2 b/sch-pcb/fp/pcb-example-hdr2 new file mode 100755 index 0000000..4b7ad20 --- /dev/null +++ b/sch-pcb/fp/pcb-example-hdr2 @@ -0,0 +1,185 @@ +#!/usr/bin/perl + +# Copyright (C) 2005 John C. Luciani Jr. + +# This program may be distributed or modified under the terms of +# version 0.2 of the No-Fee Software License published by +# John C. Luciani Jr. + +# Creates the PCB elements for Molex 8624 header connectors + +use strict; +use warnings; + +use Pcb_8; + +my $Pcb = Pcb_8 -> new(debug => 0); + +my @Fields = qw(circuits body_length pin_row_length); + +my @Def; # definitions that are common to all components + +while () { + s/\#.*//; # Remove comments + s/^\s*//; # Remove leading spaces + s/\s*$//; # Revove trailing spaces + next unless length; # Skip empty lines + + # Lines that contain an '=' are global definitions. + + push(@Def, $1, $2), next if /(\S+)\s*=\s*(\S.*)/; + + my @values = split /\s*\|\s*/; + + # hash for each footprint + + my %f = ( @Def, + map { $_ => shift(@values) } @Fields); + + $Pcb -> element_begin(description => 'TH', + output_file => + "tmp/" . &package_name($f{circuits}, $f{pin_rows}), + dim => 'mils', + pin_one_square => 1); + + my $pin_num = 1; + my $pins_per_row = $f{circuits} / 2; + + # lower left corner is pin one + + my $x0 = -$f{pin_spacing} * ($pins_per_row - 1) / 2; + my $y0 = $f{row_spacing} / 2; + + my $x = $x0; + my $y = $y0; + + # These header connectors consist of two rows of pins. With pin + # one in the lower left corner we will place pins from left to + # right until half the pins are placed. At the halfway point we + # will shift to the top row and place pins from right to left. + + while ($pin_num <= $f{circuits}) { + $Pcb -> element_add_pin(x => $x, y => $y, + thickness => $f{pad_thickness}, + drill_hole => $f{drill_hole}, + mask => 10, + clearance => 10, + pin_number => $pin_num); + + # Header connectors usually have pins numbered from left to + # right with odd numbers on the bottom and even numbers on the + # top. Since this example program could be used for connectors + # other than headers three pin-numbering options are provided. + + # header - two rows of pins. numbers increase from left to right. + # odd numbered pins on the bottom, even on the top. + + # dip - two rows of pins. starting in the lower left corner + # numbers increase left to right along the bottom row + # and right to left along the top row. + + # power - two rows of pins. numbers increase from left to right + # starting on the bottom row and then continue left to right + # along the top row. + + if ($f{pin_numbering_scheme} eq 'header') { + $y *= -1; + $x += $f{pin_spacing} if $y > 0; + } elsif ($f{pin_numbering_scheme} eq 'dip') { + if ($pin_num == $pins_per_row) { + $y -= $f{row_spacing}; + } else { + $x += $pin_num > $pins_per_row + ? -$f{pin_spacing} + : $f{pin_spacing}; + } + } elsif ($f{pin_numbering_scheme} eq 'power') { + if ($pin_num == $pins_per_row) { + $y -= $f{row_spacing}; + $x = $x0; + } else { + $x += $f{pin_spacing} + } + } else { + die "unknown pin numbering scheme |$f{pin_numbering_scheme}|"; + } + $pin_num++; + } + + $Pcb -> element_add_rectangle(width => $f{body_width}, + length=> $f{body_length}, + x => 0, + y => 0); + + + $Pcb -> element_set_text_xy(x => -$f{body_length}/2, + y => -$f{body_width}/2 - 20); + + + $Pcb -> element_output(); +} + +sub package_name ($$) { + my ($circuits, $rows) = @_; + sprintf("CON_HDR-254P-%iC-%iR-%iN__Molex_8624-Series", + $circuits/$rows, + $rows, + $circuits); +} + +__DATA__ + +pad_thickness = 66 +drill_hole = 46 +pin_numbering_scheme = header +body_width = 200 +pin_spacing = 100 +row_spacing = 100 +pin_diameter = 35 +pin_rows = 2 + +# circuits | body_length | pin_row_length + +4 | 190 | 100 +6 | 290 | 200 +8 | 390 | 300 +10 | 490 | 400 +12 | 590 | 500 +14 | 690 | 600 +16 | 790 | 700 +18 | 890 | 800 +20 | 990 | 900 +22 | 1090 | 1000 +24 | 1190| 1100 +26 | 1290| 1200 +28 | 1390| 1300 + +30 | 1490 | 1400 +32 | 1590 | 1500 +34 | 1690 | 1600 +36 | 1790 | 1700 +38 | 1890 | 1800 +40 | 1990 | 1900 +42 | 2090 | 2000 +44 | 2190 | 2100 +46 | 2290 | 2200 +48 | 2390 | 2300 +50 | 2490 | 2400 +52 | 2590 | 2500 +54 | 2690 | 2600 + +56 | 2790 | 2700 +58 | 2890 | 2800 +60 | 2990 | 2900 +62 | 3090 | 3000 +64 | 3190 | 3100 +66 | 3290 | 3200 +68 | 3390 | 3300 +70 | 3490 | 3400 +72 | 3590 | 3500 +74 | 3690 | 3600 +76 | 3790 | 3700 +78 | 3890 | 3800 +80 | 3990 | 3900 + + diff --git a/sch-pcb/fp/pcb-example-res b/sch-pcb/fp/pcb-example-res new file mode 100755 index 0000000..88f5faf --- /dev/null +++ b/sch-pcb/fp/pcb-example-res @@ -0,0 +1,60 @@ +#!/usr/bin/perl + +# Copyright (C) 2005 John C. Luciani Jr. + +# This program may be distributed or modified under the terms of +# version 0.2 of the No-Fee Software License published by +# John C. Luciani Jr. + +# Creates a 1/4 Watt resistor + +use strict; +use warnings; + +use Pcb_8; + +my $Pcb = Pcb_8 -> new(debug => 1); + +$Pcb -> element_begin(description => 'resistor', + output_file => '025W', + dim => 'mils'); + +# the resistor centroid is at (0,0) and the pins are placed 400 mils +# apart + +my $Body_width = 70; # y direction +my $Body_length = 240; # x direction +my @Pins = (-200, 0, 200, 0); # x,y pin centers +my $Pin_num = 1; + +while (@Pins) { + my ($x, $y) = splice @Pins, 0, 2; + $Pcb -> element_add_pin(x => $x, y => $y, + thickness => 55, + drill_hole => 35, + mask => 10, + clearance => 10, + pin_number => $Pin_num++); +} + +$Pcb -> element_add_rectangle(width => $Body_width, + length=> $Body_length, + thickness => 10, + x => 0, + y => 0); + +foreach my $sign (-1, 1) { + $Pcb -> element_add_line(x1 => $sign * $Body_length / 2, + y1 => 0, + x2 => $sign * ($Body_length / 2 + 30), + y2 => 0, + thickness => 10); +} + + +$Pcb -> element_set_text_xy(x => -$Body_length/2, + y => -$Body_width/2 - 20); + + +$Pcb -> element_output(); + diff --git a/sch-pcb/fp/pcb-example-smd b/sch-pcb/fp/pcb-example-smd new file mode 100755 index 0000000..ff3da13 --- /dev/null +++ b/sch-pcb/fp/pcb-example-smd @@ -0,0 +1,100 @@ +#!/usr/bin/perl + +# Copyright (C) 2005 John C. Luciani Jr. + +# This program may be distributed or modified under the terms of +# version 0.2 of the No-Fee Software License published by +# John C. Luciani Jr. + +# Creates the PCB elements specified in the DATA section. The +# footprints are for the SMD packages 0402, 0603, 0805, 1206, 1210, +# 2010, 2512, 0402, 0504, 0603, 0805, 1206, 1210, 1812, 1825 + +use strict; +use warnings; + +use Pcb_9; + +my $Pcb = Pcb_9 -> new(debug => 1); + +my @Fields = qw(land_pattern_length land_row_distance + land_width land_length + land_row_centers grid); + +while () { + s/\#.*//; # Remove comments + s/^\s*//; # Remove leading spaces + s/\s*$//; # Revove trailing spaces + next unless length; # Skip empty lines + my ($type, @values) = split /\s*\|\s*/; + + # hash for each footprint + + my %f = map { $_ => shift(@values) } @Fields; + + $Pcb -> element_begin(description => 'SMD', + output_file => "tmp/$type", + dim => 'mm'); + + my $x = -$f{land_row_centers} / 2; + foreach my $pin_num (1..2) { + $Pcb -> element_add_pad_rectangle(width => $f{land_width}, + length=> $f{land_length}, + x => $x, + y => 0, + name => 'input', + mask => 0.254, + clearance => 0.254, + pin_number => $pin_num); + $x += $f{land_row_centers}; + } + + # Draw a silkscreen rectangle around the component. A silkscreen + # specification that all PCB vendors should be able to meet is + # 10mil line width and 10mil spacing. The silkscreen line width + # defaults to 10mils. To achieve the proper spacing we add + # 30mils (0.762mm) to the maximum extents of the copper pads + # (10mils on either side of the copper and 2*5 mils for the + # silkscreen line). + + my $length = $f{land_pattern_length} + 0.762; + my $width = $f{land_width} + 0.762; + + $Pcb -> element_add_rectangle(width => $width, + length=> $length, + x => 0, + y => 0); + + # Place the refdes slightly (0.5mm) above the upper left corner of + # the outline rectangle. + + $Pcb -> element_set_text_xy(x => -$length/2, + y => -$width/2 - 0.5); + + $Pcb -> element_output(); + +} + + +__DATA__ + +# type package name +# Z overall length of land pattern +# G distance between land rows +# X land width +# Y land length +# C center-to-center spacing between land rows +# Grid number of 0.5mm by 0.5mm elements + +# type Z G X Y C Grid + + 0402 | 2.20 | 0.40 | 0.70 | 0.90 | 1.30 | 2x6 + 0504 | 2.40 | 0.40 | 1.30 | 1.00 | 1.40 | 4x6 + 0603 | 2.80 | 0.60 | 1.00 | 1.10 | 1.70 | 4x6 + 0805 | 3.20 | 0.60 | 1.50 | 1.30 | 1.90 | 4x8 + 1206 | 4.40 | 1.20 | 1.80 | 1.60 | 2.80 | 4x10 + 1210 | 4.40 | 1.20 | 2.70 | 1.60 | 2.80 | 6x10 + 1812 | 5.80 | 2.00 | 3.40 | 1.90 | 3.90 | 8x12 + 1825 | 5.80 | 2.00 | 6.80 | 1.90 | 3.90 | 14x12 + 2010 | 6.20 | 2.60 | 2.70 | 1.80 | 4.40 | 6x14 + 2512 | 7.40 | 3.80 | 3.20 | 1.80 | 5.60 | 8x16 diff --git a/sch-pcb/fp/pcb-example-tqfn b/sch-pcb/fp/pcb-example-tqfn new file mode 100755 index 0000000..33fd9b2 --- /dev/null +++ b/sch-pcb/fp/pcb-example-tqfn @@ -0,0 +1,260 @@ +#!/usr/bin/perl + +# Copyright (C) 2007 John C. Luciani Jr. + +# This program may be distributed or modified under the terms of +# version 0.2 of the No-Fee Software License published by +# John C. Luciani Jr. + +# Creates Maxim TQFN style packages. + +# Data is from the Maxim 21-0140 Rev G and Maxim 21-10159 Rev A +# specifications. + +# The TQFN (thin quad flat no-lead) packages have solder terminations +# on four sides and a thermal pad in the center. The two denser +# packages (T3255-2 and T4055-1) require smaller pads on the corner +# terminations. + +use strict; +use warnings; +use Carp; + +use Pcb_9; # routines to create PCB elements (packages) + +my $Pcb = Pcb_9 -> new(debug => 0); + +# The specifications to generate these symbols is in the __DATA__ +# section of this file. Each line can be either blank, contain a global +# definition or contain a package data record. + +# Global definitions are saved in @Def. +# The field names for the package data record are in @Fields. + +my @Def; # Global definitions saved as key-value pairs. +my @Fields = qw(package_code + pin_count + pad_spacing + pad_width + pad_length + corner_pad_length + thermal_pad_width + thermal_pad_length); + +# Read the __DATA__ section and output a PCB footprint everytime a +# package data record is read. + +while () { + last if /^__END__$/; + s/\#.*//; # Remove comments + s/^\s*//; # Remove leading spaces + s/\s*$//; # Revove trailing spaces + next unless length; # Skip empty lines + + # Lines that contain an '=' are global definitions. The key (lhs) + # and value (rhs) are pushed onto @Def. + + push(@Def, $1, $2), next if /(\S+)\s*=\s*(\S.*)/; + + # A line with non-zero length that is not a global definition is a + # package data record. We split the package record and create a + # hash %p that contains key-value pairs for all of the global + # definitions and the current record. + + my @values = split /\s*\|\s*/; + my %p = ( @Def, + map { $_ => shift(@values) } @Fields); + + # Create a simple id using the package name, package code and pin + # count and then start a new element. + + $p{id} = join('-', map { $p{$_} } qw(package_name package_code pin_count)); + $Pcb -> element_begin(description => $p{id}, + output_file => "tmp/$p{id}", + dim => 'mm'); + print "$p{id}\n"; + + # Create a few convenient specifications from data in the package + # data record hash. The convenetions for these packages is part + # centroid at (0,0) and pin one is in the lower left corner. + + # Corner pads on some of the parts are shorter. This condition is + # handled by creating a new pad length and some pad center + # offsets. + + $p{num_pads_per_side} = $p{pin_count} / 4; # leads on four sides + $p{corner_pad_length} = $p{pad_length} if $p{corner_pad_length} eq ''; + + my $row_center = ($p{body_width_max} - $p{pad_length}) / 2; + my $row_end = ($p{num_pads_per_side} - 1) * $p{pad_spacing} / 2; + my $corner_offset = ($p{pad_length} - $p{corner_pad_length}) / 2; + + # @xy contains the staring locations for a row of pads. + # @inc contains increment values for x and y and offsets for the + # the corner pads. for each row of pads either x or y is incremented. + + my @xy = (x => -$row_center, y => -$row_end, + x => -$row_end, y => $row_center, + x => $row_center, y => $row_end, + x => $row_end, y => -$row_center); + + my @inc= (yinc => $p{pad_spacing}, xoffset => -$corner_offset, + xinc => $p{pad_spacing}, yoffset => $corner_offset, + yinc => -$p{pad_spacing}, xoffset => $corner_offset, + xinc => -$p{pad_spacing}, yoffset => -$corner_offset); + + # create the rows of pads + + &set_pin_num(1); + + while (@xy) { + my %xy = (splice(@inc, 0, 4), + map { $_ => $p{$_} } qw(pad_spacing pad_width pad_length)); + + &draw_row_of_pads(splice(@xy, 0, 4), + %xy, + pad_length => $p{corner_pad_length}, + num_pads => 1); + + # no offsets for pads that aren't on the corners + + &draw_row_of_pads(%xy, + xoffset => 0, + yoffset => 0, + num_pads => $p{num_pads_per_side} - 2); + + &draw_row_of_pads(%xy, + pad_length => $p{corner_pad_length}, + num_pads => 1); + } + + # Add the thermal pad + + $Pcb -> element_add_pad_rectangle(x => 0, + y => 0, + length => $p{thermal_pad_length}, + width => $p{thermal_pad_width}, + name => '', + pin_number => $p{pin_count} + 1); + + # add the pin one dot + + my $dot_pos = $row_center + 0.254; #$p{pad_length} / 2; + + $Pcb -> element_add_arc(x => -$dot_pos, + y => -$dot_pos, + width => $p{pad_width} / 2, + height=> $p{pad_width} / 2, + start_angle => 0, + delta_angle => 360, + thickness => 0.254); # 10 mil lines + + # draw a silksreen rectangle around the package body. + + $Pcb -> element_add_rectangle(x => 0, + y => 0, + width => $p{body_width_max} + 1, + length=> $p{body_length_max} + 1); + + # Set the position of the reference designator to the upper left corner + + $Pcb -> element_set_text_xy(x => -$p{body_length_max} / 2 - 1, + y => -$p{body_width_max} / 2 - 1); + + # Set the centroid mark and output the element + + $Pcb -> element_output; + +} + +# $v{x} current x location +# $v{y} current y location +# $v{pin_num} current pin number + +my %v; # values for draw_row_of_pads + +sub set_pin_num ($) { + $v{pin_num} = shift; +} + +sub draw_row_of_pads { + my %p = (xoffset => 0, + yoffset => 0, + @_); + + foreach (qw(pin_num x y)) { + $v{$_} = $p{$_} if defined $p{$_}; + } + + # swap pad length and width for horizontal rows + + ($p{pad_width}, $p{pad_length}) = ($p{pad_length}, $p{pad_width}) + if defined $p{xinc}; + + foreach (1..$p{num_pads}) { + $Pcb -> element_add_pad_rectangle(x => $v{x} + $p{xoffset}, + y => $v{y} + $p{yoffset}, + width => $p{pad_width}, + length => $p{pad_length}, + name => '', + pin_number => $v{pin_num}++); + $v{x} += $p{xinc} if defined $p{xinc}; + $v{y} += $p{yinc} if defined $p{yinc}; + } +} + + + + +1; + + + +__DATA__ +body_width_min = 4.9 # E +body_width = 5.0 # E +body_width_max = 5.1 # E +body_length_min = 4.9 # D +body_length = 5.0 # D +body_length_max = 5.1 # D + +component_type = ic +package_name = TQFN-Maxim-5x5 + +# Final pad_length = pad_lenth + body_width_max - body_width_min + +# T1655-1 e (nom) b, L, E2, D2 (max) +# T2055-2 e (nom) b (max) L, E2, D2 (nom) +# T2055-5 e (nom) b (max) L (min) E2, D2 (nom) + +# T2855-1 e (nom) b (max) L (min) E2, D2 (nom) +# T2855-2 e (nom) b (max) L (min) E2, D2 (max) + +# T3255-2 e (nom) b (max) L (max) E2, D2 (max) +# T4055-1 e (nom) b (min) L (nom) E2, D2 (min) + + +# e b L L1 E2 D2 + T1655-1 | 16 | 0.8 | 0.35 | 0.5 | | 3.2 | 3.2 + T2055-2 | 20 | 0.65 | 0.35 | 0.55 | | 3.10 | 3.10 + T2055-5 | 20 | 0.65 | 0.35 | 0.45 | | 3.25 | 3.25 + + T2855-1 | 28 | 0.50 | 0.30 | 0.45 | | 3.25 | 3.25 + T2855-2 | 28 | 0.50 | 0.30 | 0.45 | | 2.8 | 2.8 + + + T3255-2 | 32 | 0.50 | 0.30 | 0.5 | 0.25 | 3.2 | 3.2 + T4055-1 | 40 | 0.40 | 0.2 | 0.5 | 0.25 | 3.2 | 3.2 + +# Style (adapted from the Perl Cookbook, First Edition, Recipe 12.4) + +# 1. Names of functions and local variables are all lowercase. +# 2. The program's persistent variables (either file lexicals +# or package globals) are capitalized. +# 3. Identifiers with multiple words have each of these +# separated by an underscore to make it easier to read. +# 4. Constants are all uppercase. +# 5. If the arrow operator (->) is followed by either a +# method name or a variable containing a method name then +# there is a space before and after the operator. + diff --git a/sch-pcb/fp/ti_rge.pl b/sch-pcb/fp/ti_rge.pl new file mode 100755 index 0000000..321d4db --- /dev/null +++ b/sch-pcb/fp/ti_rge.pl @@ -0,0 +1,262 @@ +#!/usr/bin/perl + +# Copyright (C) 2007 John C. Luciani Jr. + +# This program may be distributed or modified under the terms of +# version 0.2 of the No-Fee Software License published by +# John C. Luciani Jr. + +# Creates Maxim TQFN style packages. + +# Data is from the Maxim 21-0140 Rev G and Maxim 21-10159 Rev A +# specifications. + +# The TQFN (thin quad flat no-lead) packages have solder terminations +# on four sides and a thermal pad in the center. The two denser +# packages (T3255-2 and T4055-1) require smaller pads on the corner +# terminations. + +use strict; +use warnings; +use Carp; + +use Pcb_9; # routines to create PCB elements (packages) + +my $Pcb = Pcb_9 -> new(debug => 0); + +# The specifications to generate these symbols is in the __DATA__ +# section of this file. Each line can be either blank, contain a global +# definition or contain a package data record. + +# Global definitions are saved in @Def. +# The field names for the package data record are in @Fields. + +my @Def; # Global definitions saved as key-value pairs. +my @Fields = qw(package_code + pin_count + pad_spacing + pad_width + pad_length + corner_pad_length + thermal_pad_width + thermal_pad_length); + +# Read the __DATA__ section and output a PCB footprint everytime a +# package data record is read. + +while () { + last if /^__END__$/; + s/\#.*//; # Remove comments + s/^\s*//; # Remove leading spaces + s/\s*$//; # Revove trailing spaces + next unless length; # Skip empty lines + + # Lines that contain an '=' are global definitions. The key (lhs) + # and value (rhs) are pushed onto @Def. + + push(@Def, $1, $2), next if /(\S+)\s*=\s*(\S.*)/; + + # A line with non-zero length that is not a global definition is a + # package data record. We split the package record and create a + # hash %p that contains key-value pairs for all of the global + # definitions and the current record. + + my @values = split /\s*\|\s*/; + my %p = ( @Def, + map { $_ => shift(@values) } @Fields); + + # Create a simple id using the package name, package code and pin + # count and then start a new element. + + $p{id} = join('-', map { $p{$_} } qw(package_name package_code pin_count)); + $Pcb -> element_begin(description => $p{id}, + output_file => "tmp/$p{id}", + dim => 'mm'); + print "$p{id}\n"; + + # Create a few convenient specifications from data in the package + # data record hash. The convenetions for these packages is part + # centroid at (0,0) and pin one is in the lower left corner. + + # Corner pads on some of the parts are shorter. This condition is + # handled by creating a new pad length and some pad center + # offsets. + + $p{num_pads_per_side} = $p{pin_count} / 4; # leads on four sides + $p{corner_pad_length} = $p{pad_length} if $p{corner_pad_length} eq ''; + + #my $row_center = ($p{body_width_max} - $p{pad_length}) / 2; + my $row_center = ($p{pad_inner_width} + $p{pad_length}) / 2; + my $row_end = ($p{num_pads_per_side} - 1) * $p{pad_spacing} / 2; + my $corner_offset = ($p{pad_length} - $p{corner_pad_length}) / 2; + + # @xy contains the staring locations for a row of pads. + # @inc contains increment values for x and y and offsets for the + # the corner pads. for each row of pads either x or y is incremented. + + my @xy = (x => -$row_center, y => -$row_end, + x => -$row_end, y => $row_center, + x => $row_center, y => $row_end, + x => $row_end, y => -$row_center); + + my @inc= (yinc => $p{pad_spacing}, xoffset => -$corner_offset, + xinc => $p{pad_spacing}, yoffset => $corner_offset, + yinc => -$p{pad_spacing}, xoffset => $corner_offset, + xinc => -$p{pad_spacing}, yoffset => -$corner_offset); + + # create the rows of pads + + &set_pin_num(1); + + while (@xy) { + my %xy = (splice(@inc, 0, 4), + map { $_ => $p{$_} } qw(pad_spacing pad_width pad_length)); + + &draw_row_of_pads(splice(@xy, 0, 4), + %xy, + pad_length => $p{corner_pad_length}, + num_pads => 1); + + # no offsets for pads that aren't on the corners + + &draw_row_of_pads(%xy, + xoffset => 0, + yoffset => 0, + num_pads => $p{num_pads_per_side} - 2); + + &draw_row_of_pads(%xy, + pad_length => $p{corner_pad_length}, + num_pads => 1); + } + + # Add the thermal pad + + $Pcb -> element_add_pad_rectangle(x => 0, + y => 0, + length => $p{thermal_pad_length}, + width => $p{thermal_pad_width}, + name => '', + pin_number => $p{pin_count} + 1); + + # add the pin one dot + + #my $dot_pos = $row_center + 0.254; #$p{pad_length} / 2; + my $dot_pos = $p{body_width_max}/2 + 0.254; #$p{pad_length} / 2; + + $Pcb -> element_add_arc(x => -$dot_pos, + y => -$dot_pos, + width => $p{pad_width} / 2, + height=> $p{pad_width} / 2, + start_angle => 0, + delta_angle => 360, + thickness => 0.254); # 10 mil lines + + # draw a silksreen rectangle around the package body. + + $Pcb -> element_add_rectangle(x => 0, + y => 0, + width => $p{body_width_max} + 1, + length=> $p{body_length_max} + 1); + + # Set the position of the reference designator to the upper left corner + + $Pcb -> element_set_text_xy(x => -$p{body_length_max} / 2 - 1, + y => -$p{body_width_max} / 2 - 1); + + # Set the centroid mark and output the element + + $Pcb -> element_output; + +} + +# $v{x} current x location +# $v{y} current y location +# $v{pin_num} current pin number + +my %v; # values for draw_row_of_pads + +sub set_pin_num ($) { + $v{pin_num} = shift; +} + +sub draw_row_of_pads { + my %p = (xoffset => 0, + yoffset => 0, + @_); + + foreach (qw(pin_num x y)) { + $v{$_} = $p{$_} if defined $p{$_}; + } + + # swap pad length and width for horizontal rows + + ($p{pad_width}, $p{pad_length}) = ($p{pad_length}, $p{pad_width}) + if defined $p{xinc}; + + foreach (1..$p{num_pads}) { + $Pcb -> element_add_pad_rectangle(x => $v{x} + $p{xoffset}, + y => $v{y} + $p{yoffset}, + width => $p{pad_width}, + length => $p{pad_length}, + name => '', + pin_number => $v{pin_num}++); + $v{x} += $p{xinc} if defined $p{xinc}; + $v{y} += $p{yinc} if defined $p{yinc}; + } +} + + + + +1; + + + +__DATA__ +body_width_min = 3.85 # E +body_width = 4.0 # E +body_width_max = 4.15 # E +body_length_min = 3.85 # D +body_length = 4.0 # D +body_length_max = 4.15 # D + +pad_inner_width = 3.1 + +component_type = ic +package_name = VQFN-TI + +# Final pad_length = pad_lenth + body_width_max - body_width_min + +# T1655-1 e (nom) b, L, E2, D2 (max) +# T2055-2 e (nom) b (max) L, E2, D2 (nom) +# T2055-5 e (nom) b (max) L (min) E2, D2 (nom) + +# T2855-1 e (nom) b (max) L (min) E2, D2 (nom) +# T2855-2 e (nom) b (max) L (min) E2, D2 (max) + +# T3255-2 e (nom) b (max) L (max) E2, D2 (max) +# T4055-1 e (nom) b (min) L (nom) E2, D2 (min) + + +# e b L L1 E2 D2 + RGE | 24 | 0.50 | 0.28 | 0.85 | | 2.45 | 2.45 + +#T2855-1 | 28 | 0.50 | 0.30 | 0.45 | | 3.25 | 3.25 +#T2855-2 | 28 | 0.50 | 0.30 | 0.45 | | 2.8 | 2.8 + + +#T3255-2 | 32 | 0.50 | 0.30 | 0.5 | 0.25 | 3.2 | 3.2 +#T4055-1 | 40 | 0.40 | 0.2 | 0.5 | 0.25 | 3.2 | 3.2 + +# Style (adapted from the Perl Cookbook, First Edition, Recipe 12.4) + +# 1. Names of functions and local variables are all lowercase. +# 2. The program's persistent variables (either file lexicals +# or package globals) are capitalized. +# 3. Identifiers with multiple words have each of these +# separated by an underscore to make it easier to read. +# 4. Constants are all uppercase. +# 5. If the arrow operator (->) is followed by either a +# method name or a variable containing a method name then +# there is a space before and after the operator. +