neingeist
/
arduinisten
Archived
1
0
Fork 0
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

1601 lines
70 KiB
Plaintext

#usage "<qt>nobr><b>Exports the board to HyperLynx Signal-Integrity Transfer Format (.HYP)</b><p>"
"* HyprLynx.ULP Written by Frank Hoffman of LLOYD I/O INC<br>"
"* Copyright (c) 1997, All Rights Reserved by LLOYD I/O INC<br>"
"* 503/222-0702 frankh@lloydio.com www.lloydio.com"
"<p>"
"* 1 sided boards use layer 16<br>"
"* 2 sided boards use layers 1 and 16<br>"
"* 4 layer boards use layers 1,2 and 15, 16<br>"
"* 6 layer boards use layers 1,2,3 and 14,15,16<br>"
"* 8 layer boards use layers 1,2,3,4 and 13,14,15,16<br>"
"* 10 layer boards use layers 1,2,3,4,5 and 12,13,14,15,16<br>"
"* 12 layer boards use layers 1,2,3,4,5,6 and 11,12,13,14,15,16<br>"
"* 14 layer boards use layers 1,2,3,4,5,6,7 and 10,11,12,13,14,15,16<br>"
"* 16 layer boards use layers 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16<br>"
"* <br>"
"* Adapted for Eagle-Version 4.1 <br>"
"* - Unrouted layer not exported<br>"
"* - Export also Wire-Arcs<br>"
"* - SMD shape Roundnes is included<br>"
"* - PAD shape LONG OFFSET (Oblong) is included<br>"
"* - PAD accept Top, Bottom and Inner (MDEF) layer<br>"
"* - VIA generate only used layer in stack<br>"
"* 02.04.2004 alf@cadsoft.de<br>"
"* - W.curve correction in C.element.package.wires(W)<br>"
"* 21.04.2005 alf@cadsoft.de<br>"
"* - {PADSTACK=...%03d correct number while count from 1<br>"
"* 17.08.2005 alf@cadsoft.de<br>"
"* <br>";
// Version 4.11 : W.curve correction in C.element.package.wires(W) 21.04.2005
// Version 4.12 : Correct Padstack number while list from 0 (zerro) 03.05.2005
// The original ULP counts the PADSTACK-List from 1 (+1),
// the used Pads counts from 0 ! *** 03.05.2005
// Version 4.13 : Correct Padstack counter in for { loop } *** 11.08.2005
// Check if a SMD-Pad dx=0 or dy=0 then aborted this ULP RUN.
// Version 4.14 : Correct Padstack counter in all function, count now from 1 to total_pad
// eliminate correction of 4.12 from 03.05.2005
string Version = "Version 2.00 9/11/97 -- 4.14 17/08/2005";
string headerline = "* Exports the board to HyperLynx Signal-Integrity Transfer Format (.HYP)";
//***********************************************
// Definitions of yes and no! Do not modify!
char yes = 1; // yes must be different from no.
char no = 0; // no must be zero (0)
//********************************************************************************************
//********************************************************************************************
//********************************************************************************************
// USER MODIFYABLE DATA
// Generate Files Options:
char GenerateReferenceFile = yes; // Generate the Reference File ('yes'/'no')
char GenerateHyperlynxFile = yes; // Generate the Hyperlynx File ('yes'/'no')
// Generate Component Types Options:
char UseComponentTypes = yes; // Devices Q, T, U, IC, C, D, L, R, BD, etc. ('yes'/'no')
// Generate Component Pin Direction Options:
char GeneratePinDirection = no; // If 'yes', slows down many many times.
// Component Value Change Options:
char TruncateComponentValues = no; // Truncate ".1uf 50v" to ".1uf" ('yes'/'no')
char ConvertCapValues = yes; // Convert Capacitor Values. i.e. change ".1" to ".1u" ('yes'/'no')
string ConvertLT1to = "uF"; // values less than 1 are labeled as this unit
string ConvertGE1to = "uF"; // convert greater than or equal to 1 are labeled as this unit
// Board Thickness AND Stack Up Options:
char UseBoardStackUp = yes; // Use board thickness data ('yes'/'no')
real board_thickness = 0.0625; // Board Thickness, if 0: use fixed layer sizes else calc layer thicknesses
// Copper Value Options:
real zerooz = 0.0000; // zero copper thickness
real halfoz = 0.0007; // 0.5 oz copper thickness
real oneoz = 0.0014; // 1.0 oz copper thickness
real twooz = 0.0028; // 2.0 oz copper thickness
// Copper Layer Thickness for Each Layer of Copper
real copper_thickness[] = {0.0, halfoz,halfoz,halfoz,halfoz,halfoz,halfoz,
halfoz,halfoz,halfoz,halfoz,halfoz,halfoz,
halfoz,halfoz,halfoz,halfoz}; // 1st number is not used (no layer 0)
// Copper Layer Plating Thickness for Each Layer of Copper.
// Top and Bottom are used most often.
real copper_plating[] = {0.0, halfoz,zerooz,zerooz,zerooz,zerooz,zerooz,
zerooz,zerooz,zerooz,zerooz,zerooz,zerooz,
zerooz,zerooz,zerooz,halfoz}; // 1st number is not used (no layer 0)
// Dielectric Value Options:
real dicons = 4.8; // default dielectric constant
real dit1ly = 0.0611; // dielectric thickness for 1 sided board
real dit2ly = 0.0597; // dielectric thickness for 2 sided board
real ditmly = 0.0200; // dielectric thickness for multilayered boards
real dielectric_constant[] = { dicons,dicons,dicons,dicons,dicons,dicons,dicons,dicons,dicons};
real dielectric_thickness[] = { dit1ly,dit2ly,ditmly,ditmly,ditmly,ditmly,ditmly,ditmly,ditmly};
// Special Wire Width Options:
real RectOutlineWireWidth = 0.001; // Rectangle outline wire width in inches
real HoleOutlineWireWidth = 0.001; // Holes outline wire width in inches
// Precision of board components to accurately draw and locate.
// (After the decimal '.' point.)
int precision_of_perimeter = 4; // board perimeter dimension precision
int precision_of_layers = 5; // layer thickness precision
int precision_of_pads = 3; // pad/smd size precision
int precision_of_nets = 4; // pin/via/segment/width precision
//********************************************************************************************
//********************************************************************************************
//********************************************************************************************
// DO NOT MODIFY ANYTHING BELOW THIS LINE //
int index[]; // sorting index array (indirect)
// pad info
int ISAPAD = 0; // through hole pad
int ISASMD = 1; // surface mount device pad
int ISAVIA = 18; //
// *** HyperLynx pad shapes ***
int OVALROUND = 0; // '0' means oval or round (pad_sx=pad_sy if round)
int RECTSQUARE = 1; // '1' means rectangular or square (pad_sx=pad_sy if square)
int OBLONG = 2; // '2' means oblong (oblong shape is a rectangular with rounded corners)
string PadShapes[]; // list of hyp's pad shapes
string HypPadShapes[]; // list of hyp's pad shapes
string EaglePadShapes[]; // list of eagle pad shapes
int Total_Pads = 0; // total pads
int pad_type[]; // pad types (ISAPAD,ISASMD)
int pad_layer[]; // 0 = Pad, 1 or 16 = SMD, 18 = Via
int pad_shape_Top_rnds[]; // hyperlynx type OVALROUND, RECTSQUARE, OBLONG
int pad_shape_Inner[]; // hyperlynx type OVALROUND, RECTSQUARE, OBLONG
int pad_shape_Bott[]; // hyperlynx type OVALROUND, RECTSQUARE, OBLONG
real pad_angle_end[]; // Pad rotation or Via End layer (Vias can not rotate!)
int pad_diameter_Top_or_dx[];
int pad_diameter_Inner[];
int pad_diameter_Bott[];
int pad_dy_elong_start[]; // SMD-dy, Pad-Elongation, Via Stack-Start
int pad_drill[];
string padStackList = "#\ttype\tlayer\tTop_rnd\tInner\tBott\tang_end\tdx_T\tdx_I\tdx_B\tdy_el\tdril\n";
// copper layer info
string LayerNames[]; // layer names
int copp_lookup[] = {0, 1,16, 2,15, 3,14, 4,13, 5,12, 6,11, 7,10, 8,9 };
int copp_used_layer[];
int Total_Layers; // total number of used layers
int layer_counter; // layer counter
real Total_Board_Thickness; // calculated total board thickness
/* ----- Eagle HELP --------------------------------
PAD_SHAPE_SQUARE square
PAD_SHAPE_ROUND round
PAD_SHAPE_OCTAGON octagon
PAD_SHAPE_LONG long
PAD_SHAPE_OFFSET offset
PAD_SHAPE_ANNULUS annulus (only in Supply-Layer)
PAD_SHAPE_THERMAL thermal (only in Supply-Layer)
-------------------------------------------------- */
// define the HyperLynx Pad Shapes
PadShapes[ PAD_SHAPE_SQUARE ] = "1"; // hyp's square and rectangle shape
HypPadShapes[ PAD_SHAPE_SQUARE ] = "Square"; // HyperLynx's square and rectangle shape
EaglePadShapes[ PAD_SHAPE_SQUARE ] = "Square"; // Eagle's square and rectangle shape
PadShapes[ PAD_SHAPE_ROUND ] = "0"; // hyp's round and oval shape
HypPadShapes[ PAD_SHAPE_ROUND ] = "Round"; // HyperLynx's round and oval shape
EaglePadShapes[ PAD_SHAPE_ROUND ] = "Round"; // Eagle's round and oval shape
PadShapes[ PAD_SHAPE_OCTAGON ] = "0"; // hyp's octagon is a round shape
HypPadShapes[ PAD_SHAPE_OCTAGON ] = "Round"; // HyperLynx's octagon is a round shape
EaglePadShapes[ PAD_SHAPE_OCTAGON ] = "Octagon"; // Eagle's octagon is a round shape
PadShapes[ PAD_SHAPE_LONG ] = "2"; // hyp's oblong, rectangle with rounded corners
HypPadShapes[ PAD_SHAPE_LONG ] = "Oblong"; // HyperLynx's oblong, rectangle with rounded corners
EaglePadShapes[ PAD_SHAPE_LONG ] = "Long"; // Eagle's oblong, rectangle with rounded corners
PadShapes[ PAD_SHAPE_OFFSET ] = "0"; // hyp's round and oval shape
HypPadShapes[ PAD_SHAPE_OFFSET ] = "Round"; // HyperLynx's oblong, rectangle with rounded corners
EaglePadShapes[ PAD_SHAPE_OFFSET ] = "Offset"; // Eagle's (Long) Offset, rectangle with rounded corners
// ***************************************************************************
// layers
// This routine counts visible layers and stores the name in an internal table
// Layer names beginning with '$' have the leading '$' striped.
// This routine is called from a loop
void CountLayers(UL_LAYER L) {
if ( ( L.number >= 1 ) && ( L.number <= 16 ) ) {
if ( strchr( L.name, '$' ) == 0 ) {
LayerNames[L.number] = strsub( L.name, 1 );
}
else {
LayerNames[L.number] = L.name;
}
if (L.visible) {
layer_counter++;
if (L.used) copp_used_layer[L.number] = 1;
}
}
}
// This routine writes out the layer names as signal layers or power planes
// It also writes out the dielectric layer info when needed
// This routine is called from a loop
string layernam; // layer name buffer
void PrintLayer(UL_LAYER L) {
real diele_thickness; // calculated dielectric thickness
real copp_thickness; // calculated total copper thickness
int i; // loop counter
if (L.visible) {
if ( L.number >= 1 && L.number <= 16 ) {
if ( strchr( L.name, '$' ) == 0 ) { // ** is it a Power plane?
layernam = strsub( L.name, 1 );
printf("(PLANE T=%6.*f L=%s)\n",
precision_of_layers, copper_thickness[L.number], layernam);
}
else {
printf("(SIGNAL T=%6.*f P=%6.*f L=%s)\n",
precision_of_layers, copper_thickness[L.number],
precision_of_layers, copper_plating[L.number],
L.name);
}
layer_counter++;
if (board_thickness) {
Total_Board_Thickness = board_thickness;
copp_thickness = 0.0;
for (int i = 1; i <= Total_Layers; i++ ) {
copp_thickness += copper_thickness[copp_lookup[i]] + copper_plating[copp_lookup[i]];
}
if (Total_Layers <= 2 ) diele_thickness = ( board_thickness - copp_thickness );
else diele_thickness = ( board_thickness - copp_thickness ) / ( real(Total_Layers) - 1.00 );
}
else {
diele_thickness = dielectric_thickness[Total_Layers/2];
copp_thickness = 0.0;
for (int i = 1; i <= Total_Layers; i++ ) {
copp_thickness += copper_thickness[copp_lookup[i]] + copper_plating[copp_lookup[i]];
}
if (Total_Layers <= 2 ) Total_Board_Thickness = copp_thickness + diele_thickness;
else Total_Board_Thickness = copp_thickness + (diele_thickness * ( real(Total_Layers) - 1.00 ));
}
if (layer_counter < Total_Layers) {
printf("(DIELECTRIC T=%6.*f C=%4.*f ",
precision_of_layers,diele_thickness,
precision_of_layers,dielectric_constant[Total_Layers/2]);
printf("L=DL%02d)\n",layer_counter);
}
if (Total_Layers == 1) {
printf("(DIELECTRIC T=%6.*f C=%4.*f ",
precision_of_layers,diele_thickness,
precision_of_layers,dielectric_constant[Total_Layers/2]);
printf("L=DL%02d)\n",layer_counter);
}
}
}
}
// ***************************************************************************
// pads
int search_A_Pad( int apad_type, int apad_layer,
int apad_shape_Top_rnds, int apad_shape_Inner, int apad_shape_Bott,
real apad_angle_end,
int apad_dx_Top, int apad_dx_Inner, int apad_dx_Bott,
int apad_dy_elong_start,
int apad_dril ) {
int found = 0;
for ( int i = 1; i <= Total_Pads; i++ ) {
if ( pad_type[i] == apad_type &&
pad_layer[i] == apad_layer &&
pad_shape_Top_rnds[i] == apad_shape_Top_rnds &&
pad_shape_Inner[i] == apad_shape_Inner &&
pad_shape_Bott[i] == apad_shape_Bott &&
pad_angle_end[i] == apad_angle_end &&
pad_diameter_Top_or_dx[i] == apad_dx_Top &&
pad_diameter_Inner[i] == apad_dx_Inner &&
pad_diameter_Bott[i] == apad_dx_Bott &&
pad_dy_elong_start[i] == apad_dy_elong_start&&
pad_drill[i] == apad_dril )
{
found = i;
break;
}
}
return( found);
}
// This routine inserts a pad of known type and size into the pad table
// The returned value reflects the current number of pads in the table
// If the pad size already exists, the pad is not inserted
void Insert_A_Pad( int apad_type, int apad_layer,
int apad_shape_Top_rnds, int apad_shape_Inner, int apad_shape_Bott,
real apad_angle_end,
int apad_dx_Top, int apad_dx_Inner, int apad_dx_Bott,
int apad_dy_elong_start,
int apad_dril ) {
int fnd = search_A_Pad( apad_type, apad_layer, apad_shape_Top_rnds, apad_shape_Inner, apad_shape_Bott, apad_angle_end, apad_dx_Top, apad_dx_Inner, apad_dx_Bott, apad_dy_elong_start, apad_dril);
if (fnd == 0) {
Total_Pads++;
pad_type[Total_Pads] = apad_type;
pad_layer[Total_Pads] = apad_layer;
pad_shape_Top_rnds[Total_Pads] = apad_shape_Top_rnds;
pad_shape_Inner[Total_Pads] = apad_shape_Inner;
pad_shape_Bott[Total_Pads] = apad_shape_Bott;
pad_angle_end[Total_Pads] = apad_angle_end;
pad_diameter_Top_or_dx[Total_Pads] = apad_dx_Top;
pad_diameter_Inner[Total_Pads] = apad_dx_Inner;
pad_diameter_Bott[Total_Pads] = apad_dx_Bott;
pad_dy_elong_start[Total_Pads] = apad_dy_elong_start;
pad_drill[Total_Pads] = apad_dril;
}
return;
}
// This routine finds a pad of a known type and size and returns the ID
// of the pad (internal number) that is used to identify the pad.
int Find_A_Pad( int apad_type, int apad_layer,
int apad_shape_Top_rnds, int apad_shape_Inner, int apad_shape_Bott,
real apad_angle_end,
int apad_dx_Top, int apad_dx_Inner, int apad_dx_Bott,
int apad_dy_elong_start,
int apad_dril ) {
int fnd = search_A_Pad( apad_type, apad_layer, apad_shape_Top_rnds, apad_shape_Inner, apad_shape_Bott, apad_angle_end, apad_dx_Top, apad_dx_Inner, apad_dx_Bott, apad_dy_elong_start, apad_dril);
return( fnd );
}
// This routine finds the HyperLynx shape form of eagle shape
int SmdRoundness(int r) {
if (r == 100) return 0; // oval or round
if (r == 0) return 1; // rect or square
return 2; // oblong
}
// Insert a pin on in a list of associated connected contacts
int AssPinCount = 0; // Number of associated Contacts
string AssTabEname[]; // Element Name
string AssTabCname[]; // Contact Name
int AssTabLenEname[]; // Element Name Length
int AssTabLenCname[]; // Contact Name Length
int InsertAssocatedPin( string ename, string cname ) {
int lenofename,lenofcname;
lenofename = strlen(ename);
lenofcname = strlen(cname);
if ( AssPinCount > 0 ) {
for ( int i = 0; i < AssPinCount; i++ ) {
if ( lenofename == AssTabLenEname[i] )
if ( lenofcname == AssTabLenCname[i] )
if ( strstr( AssTabEname[i], ename ) != -1 )
if ( strstr( AssTabCname[i], cname ) != -1 ) return( AssPinCount );
}
}
AssTabEname[AssPinCount] = ename;
AssTabCname[AssPinCount] = cname;
AssTabLenEname[AssPinCount] = lenofename;
AssTabLenCname[AssPinCount] = lenofcname;
AssPinCount++;
return( AssPinCount );
}
int FindAssocatedPin( string ename, string cname ) {
int lenofename,lenofcname;
lenofename = strlen(ename);
lenofcname = strlen(cname);
if ( AssPinCount > 0 ) {
for ( int i = 0; i < AssPinCount; i++ ) {
if ( lenofename == AssTabLenEname[i] )
if ( lenofcname == AssTabLenCname[i] )
if ( strstr( AssTabEname[i], ename ) != -1 )
if ( strstr( AssTabCname[i], cname ) != -1 ) return( AssPinCount );
}
}
return( 0 );
}
// write a divider
void printdivider( void ) {
printf("**********************************************************************\n");
return;
}
// write a section header with dividers
void printheader(string hs) {
printdivider();
printf("* %s\n*\n",hs);
return;
}
// write translated package types from Eagle to Hyperlynx
int saypackagetype(string pn) {
if ( strstr( pn,"TSSOP" ) != -1 ) {
printf(" PKG=TSSOP");
}
else if ( strstr( pn,"TQFP" ) != -1 ) {
printf(" PKG=TQFP");
}
else if ( strstr( pn,"SSOP" ) != -1 ) {
printf(" PKG=SSOP");
}
else if ( strstr( pn,"PLCC" ) != -1 ) {
printf(" PKG=PLCC");
}
else if ( strstr( pn,"LCC" ) != -1 ) {
printf(" PKG=LCC");
}
else if ( strstr( pn,"DIP" ) != -1 ) {
printf(" PKG=DIP");
}
else if ( strstr( pn,"QFP" ) != -1 ) {
printf(" PKG=QFP");
}
else if ( strstr( pn,"BGA" ) != -1 ) {
printf(" PKG=BGA");
}
else if ( strstr( pn,"PGA" ) != -1 ) {
printf(" PKG=PGA");
}
else if ( strstr( pn,"DIL" ) != -1 ) {
printf(" PKG=DIP");
}
else if ( strstr( pn,"DIP" ) != -1 ) {
printf(" PKG=DIP");
}
else if ( strstr( pn,"SO" ) != -1 ) {
printf(" PKG=SO");
}
else return( no ); // no package type recognized
return( yes ); // yes, package recognized
}
// truncate trailing zeros and print value
void TruncateTrailingZeros( real value, int prec ) {
string num;
int nlen;
sprintf( num, "%1.*f", prec, value );
nlen = strlen( num );
if ( nlen > 0 ) {
while ( num[ nlen-1 ] == '0' ) {
// truncate with a null
num[ nlen-1 ] = 0;
// recalc string length
nlen = strlen( num );
if ( nlen == 0 ) break;
}
}
printf("%s",num);
return;
}
// Convert Capacitor Values. i.e. change ".1" to ".1u"
// char ConvertCapValues = yes;
// Cap value conversion rules for values without suffix multipliers
// string ConvertLT1to = "u"; // values less than 1 are "u" or "something else"
// string ConvertGE1to = "u"; // convert greater than or equal to 1 as "u" or "p"
//
void ConvertCapValue( string capvalue ) {
char cstate; // state machine
char clabel; // unit label
real cvalue; // the value of the capacitor
int lenofcapvalue; // length of the string for parsing
if ( ConvertCapValues == yes ) {
cvalue = strtod( capvalue );
if ( cvalue != 0.0 ) {
lenofcapvalue = strlen( capvalue );
cstate = 1; // set state for searching digits
for ( int i=0; i<lenofcapvalue; i++ ) {
clabel = capvalue[ i ];
if ( isdigit( clabel ) || ( clabel == '.' ) ) {
cstate = 2; // digits found
}
else {
clabel = toupper( clabel );
if ( strchr( "FMUPN", clabel ) != -1 ) cstate = 3; // multiplier found
break;
}
}
// If the value NOT labeled with a multiplier, then label it
if ( cstate == 1 ) {
// report error for debugging purposes
printf("***no digits found***");
}
if ( cstate == 2 ) {
if ( cvalue < 1.0 ) {
TruncateTrailingZeros( cvalue, 6 );
printf("%s",ConvertLT1to);
} else {
TruncateTrailingZeros( cvalue, 6 );
printf("%s",ConvertGE1to);
}
return;
}
if ( cstate == 3 ) {
if ( clabel == 'M' ) {
TruncateTrailingZeros( cvalue, 6 );
printf("uF");
return;
}
}
}
}
printf( "%s", capvalue );
return;
}
// Search and Translate pin direction information if available and enabled
void SayUPinFunction( string Ptname, string Paname ) {
int lofs1, lofs2;
string ipadname;
// check if search allowed
if ( GeneratePinDirection == no ) return;
// part name must begin with either IC or U
if ( ( strstr( Ptname, "IC" ) == 0 ) || ( strstr( Ptname, "U" ) == 0 ) ) {
if ( project.schematic ) {
project.schematic(SCH) {
SCH.parts(PT) {
lofs1 = strlen( Ptname );
lofs2 = strlen( PT.name );
if ( lofs1 == 0 ) return;
if ( lofs1 == lofs2 ) {
if ( strstr( PT.name, Ptname ) == 0 ) {
PT.instances(I) {
I.gate.symbol.pins(PIN) {
if ( PIN.contact.pad ) ipadname = PIN.contact.pad.name;
if ( PIN.contact.smd ) ipadname = PIN.contact.smd.name;
lofs1 = strlen( ipadname );
lofs2 = strlen( Paname );
if ( lofs1 == 0 ) return;
if ( lofs1 == lofs2 ) {
if ( strstr( ipadname, Paname ) == 0 ) {
switch ( PIN.direction ) {
case PIN_DIRECTION_OUT:
case PIN_DIRECTION_OC:
case PIN_DIRECTION_HIZ:
printf(" F=SIM_OUT");
break;
case PIN_DIRECTION_IO:
printf(" F=SIM_BOTH");
break;
}
}
}
}
}
}
}
}
}
}
}
return;
}
// ***************************************************************************
// board
//
// This is the MAIN() function of this ULP
if (board) board(B) {
if ( GenerateReferenceFile == yes ) {
output( filesetext( B.name, ".REF" ) ) {
printdivider();
printf("%s\n", headerline); // 03.05.2005 alf@cadsoft.de
printf("* %s\n*\n", Version);
printf("* %s\n*\n", EAGLE_SIGNATURE);
printf("* HyperLynx Board exported from:\n");
printf("* %s\n", B.name);
printf("* At %s\n*\n", t2string(time()));
if (project.schematic) {
printf("* Schematic is loaded.\n");
}
else {
printf("* Schematic NOT is loaded.\n");
}
printf("*\n*\n");
// Generate the cross references
printheader("Auto Mapped Reference File for ICs and Us");
int unknownIC, ICstate, ICvaluelen, ICccnt;
string ICname, ICvalue, ICpn, ICreflib;
B.elements(E) {
unknownIC = yes; // set component as unknown
ICname = E.name; // remember component reference designator
ICvalue = E.value; // remember component value name (IC number)
// parse reference designators ?
if ( strstr( ICname, "IC" ) == 0 ) {
if ( isdigit( ICname[2] ) ) unknownIC = no;
}
else if ( isdigit( ICname[1] ) ) {
if ( strchr( ICname, 'U' ) == 0 ) unknownIC = no;
}
if ( unknownIC == no ) {
unknownIC = yes; // reset component as unknown
if ( strstr( ICvalue, "74" ) == 0 ) {
ICstate = 0;
ICvaluelen = strlen( ICvalue );
ICccnt = 0;
for ( int i=2; i<ICvaluelen; i++ ) {
if ( isalpha( ICvalue[i] ) ) {
ICccnt++;
}
}
unknownIC = no;
if ( ICccnt > 0 ) {
ICreflib = "74" + strsub( ICvalue, 2, ICccnt ) + ".PML";
}
else {
ICreflib = "74TTL.PML";
}
} else
if ( strstr( ICvalue, "40" ) == 0 ) {
unknownIC = no;
ICreflib = "74HC.PML";
ICvalue = "74HC" + ICvalue;
}
if ( unknownIC == no ) {
printf("%s, %s, %s",ICname,ICreflib,ICvalue);
ICpn =E.package.name;
if ( strstr( ICpn,"TSSOP" ) != -1 ) {
printf("_TSSOP");
}
else if ( strstr( ICpn,"TQFP" ) != -1 ) {
printf("_TQFP");
}
else if ( strstr( ICpn,"SSOP" ) != -1 ) {
printf("_SSOP");
}
else if ( strstr( ICpn,"PLCC" ) != -1 ) {
printf("_PLCC");
}
else if ( strstr( ICpn,"LCC" ) != -1 ) {
printf("_LCC");
}
else if ( strstr( ICpn,"DIP" ) != -1 ) {
printf("_DIP");
}
else if ( strstr( ICpn,"QFP" ) != -1 ) {
printf("_QFP");
}
else if ( strstr( ICpn,"BGA" ) != -1 ) {
printf("_BGA");
}
else if ( strstr( ICpn,"PGA" ) != -1 ) {
printf("_PGA");
}
else if ( strstr( ICpn,"DIL" ) != -1 ) {
printf("_DIP");
}
else if ( strstr( ICpn,"DIP" ) != -1 ) {
printf("_DIP");
}
else if ( strstr( ICpn,"SO" ) != -1 ) {
printf("_SSOP");
}
printf("\n");
}
}
}
}
}
if ( GenerateHyperlynxFile == no ) {
exit( EXIT_SUCCESS );
}
output( filesetext( B.name, ".HYP" ) ) {
printdivider();
printf("%s\n", headerline); // 03.05.2005 alf@cadsoft.de
printf("* %s\n*\n", Version);
printf("* %s\n*\n", EAGLE_SIGNATURE);
printf("* HyperLynx Board exported from:\n");
printf("* %s\n", B.name);
printf("* At %s\n*\n", t2string(time()));
if (project.schematic) {
printf("* Schematic is loaded.\n");
}
else {
printf("* Schematic NOT is loaded.\n");
}
printf("*\n\n");
printf("{VERSION=2.10} Compatible with Hyperlynx version 2.10.\n");
printf("{UNITS=ENGLISH WEIGHT}\n\n");
// BOARD OVERALL AREA DIMENSIONS
// Writes the board dimensions found on layer 20
printheader("Board Dimensions");
printf("{BOARD\n");
// wires on the dimension layer
B.wires(W) {
if (W.layer == 20 ) {
if (W.curve) {
// arcs in the dimension layer
printf("(PERIMETER_ARC X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f XC=%5.*f YC=%5.*f R=%5.*f) Arcs: Board Outline Arc is CCW\n",
precision_of_nets,u2inch(W.arc.x1),precision_of_nets,u2inch(W.arc.y1),
precision_of_nets,u2inch(W.arc.x2),precision_of_nets,u2inch(W.arc.y2),
precision_of_nets,u2inch(W.arc.xc),precision_of_nets,u2inch(W.arc.yc),
precision_of_nets,u2inch(W.arc.radius) );
}
else {
printf("(PERIMETER_SEGMENT X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f) Wires: From Board\n",
precision_of_perimeter,u2inch(W.x1),precision_of_perimeter,u2inch(W.y1),
precision_of_perimeter,u2inch(W.x2),precision_of_perimeter,u2inch(W.y2));
}
}
}
// rectangles on the dimension layer
B.rectangles(R) {
if (R.layer == 20 ) {
printf("(PERIMETER_SEGMENT X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f) Rectangles: From Board : Bottom\n",
precision_of_perimeter,u2inch(R.x1),precision_of_perimeter,u2inch(R.y1),
precision_of_perimeter,u2inch(R.x2),precision_of_perimeter,u2inch(R.y1) );
printf("(PERIMETER_SEGMENT X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f) Rectangles: From Board : Right\n",
precision_of_perimeter,u2inch(R.x2),precision_of_perimeter,u2inch(R.y1),
precision_of_perimeter,u2inch(R.x2),precision_of_perimeter,u2inch(R.y2) );
printf("(PERIMETER_SEGMENT X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f) Rectangles: From Board : Top\n",
precision_of_perimeter,u2inch(R.x2),precision_of_perimeter,u2inch(R.y2),
precision_of_perimeter,u2inch(R.x1),precision_of_perimeter,u2inch(R.y2) );
printf("(PERIMETER_SEGMENT X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f) Rectangles: From Board : Left\n",
precision_of_perimeter,u2inch(R.x1),precision_of_perimeter,u2inch(R.y2),
precision_of_perimeter,u2inch(R.x1),precision_of_perimeter,u2inch(R.y1) );
}
}
// polygons on the dimension layer
B.polygons(P) {
if (P.layer == 20 ) {
P.wires(W) {
if (W.layer == 20 ) {
printf("(PERIMETER_SEGMENT X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f) Polygon Wires: From Board\n",
precision_of_perimeter,u2inch(W.x1),precision_of_perimeter,u2inch(W.y1),
precision_of_perimeter,u2inch(W.x2),precision_of_perimeter,u2inch(W.y2));
}
}
}
}
// circles in the dimension layer
B.circles(C) {
if (C.layer == 20 ) {
printf("(PERIMETER_ARC X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f XC=%5.*f YC=%5.*f R=%5.*f) Circles: Board Outline Arc is CCW\n",
precision_of_nets,u2inch(C.x),precision_of_nets,u2inch(C.y+C.radius),
precision_of_nets,u2inch(C.x),precision_of_nets,u2inch(C.y+C.radius),
precision_of_nets,u2inch(C.x),precision_of_nets,u2inch(C.y),
precision_of_nets,u2inch(C.radius) );
}
}
// holes in the board
int halfdrilldiameter;
B.holes(H) {
halfdrilldiameter = H.drill / 2;
printf("(PERIMETER_ARC X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f XC=%5.*f YC=%5.*f R=%5.*f) Holes: Board Outline Arc is CCW\n",
precision_of_nets,u2inch(H.x),precision_of_nets,u2inch(H.y+halfdrilldiameter),
precision_of_nets,u2inch(H.x),precision_of_nets,u2inch(H.y+halfdrilldiameter),
precision_of_nets,u2inch(H.x),precision_of_nets,u2inch(H.y),
precision_of_nets,u2inch(halfdrilldiameter) );
}
// package wires on the dimension layer
B.elements(E) {
E.package.wires(W) {
if (W.layer == 20 ) {
if (W.curve) {
// package arcs in the dimension layer
printf("(PERIMETER_ARC X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f XC=%5.*f YC=%5.*f R=%5.*f) Arcs: Board Outline Arc is CCW Package %s in %s.LBR\n",
precision_of_nets,u2inch(W.arc.x1),precision_of_nets,u2inch(W.arc.y1),
precision_of_nets,u2inch(W.arc.x2),precision_of_nets,u2inch(W.arc.y2),
precision_of_nets,u2inch(W.arc.xc),precision_of_nets,u2inch(W.arc.yc),
precision_of_nets,u2inch(W.arc.radius),
E.package.name,E.package.library );
}
else {
printf("(PERIMETER_SEGMENT X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f) Wires: From Package %s in %s.LBR\n",
precision_of_perimeter,u2inch(W.x1),precision_of_perimeter,u2inch(W.y1),
precision_of_perimeter,u2inch(W.x2),precision_of_perimeter,u2inch(W.y2),
E.package.name,E.package.library);
}
}
}
// package rectangles on the dimension layer
E.package.rectangles(R) {
if (R.layer == 20 ) {
printf("(PERIMETER_SEGMENT X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f) Rectangles: From Package %s in %s.LBR : Bottom\n",
precision_of_perimeter,u2inch(R.x1),precision_of_perimeter,u2inch(R.y1),
precision_of_perimeter,u2inch(R.x2),precision_of_perimeter,u2inch(R.y1),
E.package.name,E.package.library );
printf("(PERIMETER_SEGMENT X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f) Rectangles: From Package %s in %s.LBR : Right\n",
precision_of_perimeter,u2inch(R.x2),precision_of_perimeter,u2inch(R.y1),
precision_of_perimeter,u2inch(R.x2),precision_of_perimeter,u2inch(R.y2),
E.package.name,E.package.library );
printf("(PERIMETER_SEGMENT X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f) Rectangles: From Package %s in %s.LBR : Top\n",
precision_of_perimeter,u2inch(R.x2),precision_of_perimeter,u2inch(R.y2),
precision_of_perimeter,u2inch(R.x1),precision_of_perimeter,u2inch(R.y2),
E.package.name,E.package.library );
printf("(PERIMETER_SEGMENT X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f) Rectangles: From Package %s in %s.LBR : Left\n",
precision_of_perimeter,u2inch(R.x1),precision_of_perimeter,u2inch(R.y2),
precision_of_perimeter,u2inch(R.x1),precision_of_perimeter,u2inch(R.y1),
E.package.name,E.package.library );
}
}
// package polygons on the dimension layer
E.package.polygons(P) {
if (P.layer == 20 ) {
P.wires(W) {
if (W.layer == 20 ) {
printf("(PERIMETER_SEGMENT X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f) Polygon Wires: From Package %s in %s.LBR\n",
precision_of_perimeter,u2inch(W.x1),precision_of_perimeter,u2inch(W.y1),
precision_of_perimeter,u2inch(W.x2),precision_of_perimeter,u2inch(W.y2),
E.package.name,E.package.library);
}
}
}
}
// package circles in the dimension layer
E.package.circles(C) {
if (C.layer == 20 ) {
printf("(PERIMETER_ARC X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f XC=%5.*f YC=%5.*f R=%5.*f) Circles: Board Outline Arc is CCW Package %s in %s.LBR\n",
precision_of_nets,u2inch(C.x),precision_of_nets,u2inch(C.y+C.radius),
precision_of_nets,u2inch(C.x),precision_of_nets,u2inch(C.y+C.radius),
precision_of_nets,u2inch(C.x),precision_of_nets,u2inch(C.y),
precision_of_nets,u2inch(C.radius),
E.package.name,E.package.library );
}
}
// package holes
int halfdrilldiameter;
E.package.holes(H) {
halfdrilldiameter = H.drill / 2;
printf("(PERIMETER_ARC X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f XC=%5.*f YC=%5.*f R=%5.*f) Holes: Board Outline Arc is CCW Package %s in %s.LBR\n",
precision_of_nets,u2inch(H.x),precision_of_nets,u2inch(H.y+halfdrilldiameter),
precision_of_nets,u2inch(H.x),precision_of_nets,u2inch(H.y+halfdrilldiameter),
precision_of_nets,u2inch(H.x),precision_of_nets,u2inch(H.y),
precision_of_nets,u2inch(halfdrilldiameter),
E.package.name,E.package.library );
}
}
printf("}\n\n");
// LAYER INFORMATION
printheader("Thickness of Copper and Dielectric Layer Data");
if ( UseBoardStackUp == yes ) {
printf("{STACKUP\n");
layer_counter = 0;
B.layers(L) CountLayers(L);
Total_Layers = layer_counter; // remember active layers
layer_counter = 0;
B.layers(L) PrintLayer(L);
printf("}\n");
// TOTAL BOARD THICKNESS
printf("* Total Board Thickness %6.4f inch\n\n",Total_Board_Thickness);
}
else {
printf("* No PCB Thickness Data Generated !!! \n*\n\n");
}
// PACKAGES ON THE BOARD
printheader("Components");
printf("{DEVICES\n");
int unknowncomponenttype, pincount, componentspace;
string componentname;
string componentvalue;
B.elements(E) {
// get the number of pins
pincount = 0;
E.package.contacts(C) {
pincount++;
}
// set component as unknown
unknowncomponenttype = yes;
// remember component reference designator
componentname = E.name;
// truncate component values at the first space
// ? ASK HYPERLYNX : what about something like .1u 50v
componentvalue = E.value;
if ( TruncateComponentValues == yes )
if ( ( componentspace = strchr( componentvalue, ' ' ) ) != -1 )
componentvalue = strsub( componentvalue, 0, componentspace );
// parse reference designators ?
if ( UseComponentTypes == yes ) {
if ( strstr( componentname, "IC" ) == 0 ) {
if ( isdigit( componentname[2] ) ) {
printf("(IC REF=%s NAME=%s L=%s",componentname,componentvalue,
E.mirror ? LayerNames[16] : LayerNames[1] );
saypackagetype(E.package.name);
unknowncomponenttype = no;
}
}
else if ( strstr( componentname, "BD" ) == 0 ) {
if ( isdigit( componentname[2] ) ) {
printf("(BD REF=%s NAME=%s L=%s",componentname,componentvalue,
E.mirror ? LayerNames[16] : LayerNames[1] );
unknowncomponenttype = no;
}
}
else if ( strstr( componentname, "BEAD" ) == 0 ) {
if ( isdigit( componentname[4] ) ) {
printf("(BD REF=%s NAME=%s L=%s",componentname, componentvalue,
E.mirror ? LayerNames[16] : LayerNames[1] );
unknowncomponenttype = no;
}
}
else if ( isdigit( componentname[1] ) ) {
if ( strchr( componentname, 'U' ) == 0 ) {
printf("(IC REF=%s NAME=%s L=%s",componentname, componentvalue,
E.mirror ? LayerNames[16] : LayerNames[1] );
saypackagetype(E.package.name);
unknowncomponenttype = no;
}
else if ( strchr( componentname, 'C' ) == 0 ) {
printf("(C REF=%s VAL=",componentname);
ConvertCapValue(componentvalue);
printf(" L=%s",E.mirror ? LayerNames[16] : LayerNames[1] );
unknowncomponenttype = no;
}
else if ( strchr( componentname, 'R' ) == 0 ) {
printf("(R REF=%s VAL=%s L=%s",componentname, componentvalue,
E.mirror ? LayerNames[16] : LayerNames[1] );
unknowncomponenttype = no;
}
else if ( strchr( componentname, 'L' ) == 0 ) {
printf("(L REF=%s VAL=%s L=%s",componentname, componentvalue,
E.mirror ? LayerNames[16] : LayerNames[1] );
unknowncomponenttype = no;
}
else if ( strchr( componentname, 'D' ) == 0 ) {
printf("(CR REF=%s NAME=%s L=%s",componentname, componentvalue,
E.mirror ? LayerNames[16] : LayerNames[1] );
unknowncomponenttype = no;
}
else if ( strchr( componentname, 'J' ) == 0 ) {
printf("(J REF=%s NAME=%s L=%s",componentname, componentvalue,
E.mirror ? LayerNames[16] : LayerNames[1] );
unknowncomponenttype = no;
}
else if ( strchr( componentname, 'Q' ) == 0 ) {
printf("(J REF=%s NAME=%s L=%s",componentname, componentvalue,
E.mirror ? LayerNames[16] : LayerNames[1] );
unknowncomponenttype = no;
}
else if ( strchr( componentname, 'T' ) == 0 ) {
printf("(J REF=%s NAME=%s L=%s",componentname, componentvalue,
E.mirror ? LayerNames[16] : LayerNames[1] );
unknowncomponenttype = no;
}
}
}
// handle unknown component types
if ( ( unknowncomponenttype == yes ) || ( UseComponentTypes == no ) ) {
printf("(? REF=%s NAME=%s L=%s",componentname,componentvalue,
E.mirror ? LayerNames[16] : LayerNames[1] );
saypackagetype(E.package.name);
}
// append comment field
printf(") R%03.0f X=%5.*f Y=%5.*f : ",E.angle,precision_of_nets,u2inch(E.x),
precision_of_nets,u2inch(E.y) );
printf(" Lib: %s : %s : ", E.package.library, E.package.name);
printf("Pins %d", pincount);
printf("\n");
}
printf("}\n\n");
// PADSTACK CREATION OF PADS, SMDS, AND VIAS
// create list of all the different pads and smds (vias are pads)
printheader("Pads, Smds, and Via Library");
// handle all net contacts and vias
B.signals(S) {
S.vias(V) {
Insert_A_Pad( ISAPAD, ISAVIA,
V.shape[1], V.shape[2], V.shape[16],
V.end,
V.diameter[1], V.diameter[2], V.diameter[16],
V.start,
V.drill );
}
}
// handle all package pins
B.elements(E) {
E.package.contacts(C) {
if (C.pad) {
Insert_A_Pad( ISAPAD, ISAPAD,
C.pad.shape[1], C.pad.shape[2], C.pad.shape[16],
C.pad.angle,
C.pad.diameter[1], C.pad.diameter[2], C.pad.diameter[16],
C.pad.elongation,
C.pad.drill );
}
else if (C.smd) {
if ( !C.smd.dx || !C.smd.dy) {
string h;
sprintf(h, "!<qt><nobr>Found a SMD-Pad with <b>dx</b> or <b>dy</b> = 0 (Zerro)<br>Pad <b>%s</b>'<br>Layer <b>%d</b><br>Coordinate <b>(%.4f %.4f)</b> mil<br>Package <b>%s.PAC</b><br>Element <b>%s</b><br>Library <b>%s.lbr</b><p><b>ULP aborted.</b></nobr></qt>",
C.name,
C.smd.layer,
u2mil(C.x), u2mil(C.y),
E.package.name,
E.name,
E.package.library
);
dlgMessageBox( h, "OK");
exit(0);
}
else {
Insert_A_Pad( ISASMD, C.smd.layer,
SmdRoundness(C.smd.roundness), 0, 0,
C.smd.angle,
C.smd.dx, 0, 0,
C.smd.dy,
0 );
}
}
}
}
// write out sorted list of the pads and smds
if (Total_Pads) {
/* *** Hyperlynx documentation *************************************
{PADSTACK=padstack_name, // ** maximum of 32 characters an cannot contain white space
[drill_size]
(layer_name,
pad_shape, // '0' means oval or round (pad_sx=pad_sy if round)
// '1' means rectangular or square (pad_sx=pad_sy if square)
// '2' means oblong (oblong shape is a rectangular with rounded corners)
pad_sx,
pad_sy,
pad_angle, // is the counter-clockwise rotation angle of the pad in degree;
// rotation angle can range from 0.0 to +/-359.999;
// valid angular resolution is 0.001 degree;
// 0 (without a decimal point) is th recommended way of specifying 'no rotation'
[thermal_clear_shape],
[thermal_clear_sx],
[thermal_clear_sy],
[thermal_clear_angle],
[pad_type])
***************************************************************** */
string s;
for (int i = 1; i <= Total_Pads; i++) { // *** 17.08.2005 count from 1 ***
if (pad_layer[i] == 0) s = "ISAPAD";
if (pad_layer[i] == 1 || pad_layer[i] == 16) s = "ISASMD";
if (pad_layer[i] == 18) s = "ISAVIA";
if (pad_type[i] == ISASMD) {
printf("{PADSTACK=SMD%03d\n",i); // **** 17.08.2005 alf@cadsoft.de ***
// smds are square, round or oblong
// * if you wish layer name for layer number remark *
// * this next 2 lines und mark the second 2 lines *
// printf("(%s,%d,%5.*f,%5.*f,%.1f) Shape was Smd and is now Smd\n",
// LayerNames[pad_layer[i]], // Layer name
printf("(%d,%d,%5.*f,%5.*f,%.1f) %s Shape was Smd and is now Smd\n",
pad_layer[i], // Layer number
pad_shape_Top_rnds[i],
precision_of_pads, u2inch(pad_diameter_Top_or_dx[i]),
precision_of_pads, u2inch(pad_dy_elong_start[i]),
pad_angle_end[i],
s );
}
else if (pad_type[i] == ISAPAD) {
/* *** HyperLynx Signal-Integrity Transfer Format ******
{PADSTACK=padstack_name, [drill_size]
(layer_name, pad_shape, pad_sx, pad_sy, pad_angle,
[thermal_clear_shape],
[thermal_clear_sx],
[thermal_clear_sy],
[thermal_clear_angel],
[pad_type]) [comment]
** [pad_type]!M=metal-pad A=anti-pad **
******* HyperLynx Signal-Integrity Transfer Format *** */
printf("{PADSTACK=THR%03d,%5.3f\n", i, u2inch(pad_drill[i])); // *** 17.08.2005 count from 1 ***
// pads are on all layers, and have various shapes
if (pad_layer[i] == ISAPAD) {
// Pad layer Top
if (pad_shape_Top_rnds[i] == OBLONG) {
printf("(1,%s,%5.*f,%5.*f,%.1f) %s Shape was %s and is now %s\n",
PadShapes[pad_shape_Top_rnds[i]],
precision_of_pads,u2inch(pad_diameter_Top_or_dx[i] * pad_dy_elong_start[i]),
precision_of_pads,u2inch(pad_diameter_Top_or_dx[i]),
pad_angle_end[i],
s,
EaglePadShapes[pad_shape_Top_rnds[i]],
HypPadShapes[pad_shape_Top_rnds[i]] );
}
else { // OVALROUND or RECTSQUARE
printf("(1,%s,%5.*f,%5.*f,%.1f) %s Shape was %s and is now %s\n",
PadShapes[pad_shape_Top_rnds[i]],
precision_of_pads,u2inch(pad_diameter_Top_or_dx[i]),
precision_of_pads,u2inch(pad_diameter_Top_or_dx[i]),
pad_angle_end[i],
s,
EaglePadShapes[pad_shape_Top_rnds[i]],
HypPadShapes[pad_shape_Top_rnds[i]] );
}
// Pad layer Inner
printf("(MDEF,%s,%5.*f,%5.*f,0) %s\n",
PadShapes[pad_shape_Inner[i]],
precision_of_pads,u2inch(pad_diameter_Inner[i]),
precision_of_pads,u2inch(pad_diameter_Inner[i]),
s);
// Pad layer Bottom
if (pad_shape_Bott[i] == OBLONG) {
printf("(16,%s,%5.*f,%5.*f,%.1f) %s Shape was %s and is now %s\n",
PadShapes[pad_shape_Bott[i]],
precision_of_pads,u2inch(pad_diameter_Bott[i] * pad_dy_elong_start[i]),
precision_of_pads,u2inch(pad_diameter_Bott[i]),
pad_angle_end[i],
s,
EaglePadShapes[pad_shape_Bott[i]],
HypPadShapes[pad_shape_Bott[i]]);
}
else { // OVALROUND or RECTSQUARE
printf("(16,%s,%5.*f,%5.*f,%.1f) %s Shape was %s and is now %s\n",
PadShapes[pad_shape_Bott[i]],
precision_of_pads,u2inch(pad_diameter_Bott[i]),
precision_of_pads,u2inch(pad_diameter_Bott[i]),
pad_angle_end[i],
s,
EaglePadShapes[pad_shape_Bott[i]],
HypPadShapes[pad_shape_Bott[i]]);
}
}
else if (pad_layer[i] == ISAVIA) {
// Top - Inner(schleife) - Bottom
for (int vlay = pad_dy_elong_start[i]; vlay <= pad_angle_end[i]; vlay++) {
// layer used and allowed?
if (copp_used_layer[vlay]) { // layer used for copper an visible
if (vlay == 1)
printf("(1,%s,%5.*f,%5.*f,0) %s Shape was %s and is now %s\n",
PadShapes[pad_shape_Top_rnds[i]],
precision_of_pads,u2inch(pad_diameter_Top_or_dx[i] * pad_dy_elong_start[i]),
precision_of_pads,u2inch(pad_diameter_Top_or_dx[i]),
s,
EaglePadShapes[pad_shape_Top_rnds[i]],
HypPadShapes[pad_shape_Top_rnds[i]] );
else if (vlay == 16)
printf("(16,%s,%5.*f,%5.*f,0f) %s Shape was %s and is now %s\n",
PadShapes[pad_shape_Bott[i]],
precision_of_pads,u2inch(pad_diameter_Bott[i] * pad_dy_elong_start[i]),
precision_of_pads,u2inch(pad_diameter_Bott[i]),
s,
EaglePadShapes[pad_shape_Top_rnds[i]],
HypPadShapes[pad_shape_Top_rnds[i]] );
else printf("(%d,0,%5.*f,%5.*f,0) %s always round in inner layer\n",
vlay,
precision_of_pads,u2inch(pad_diameter_Inner[i]),
precision_of_pads,u2inch(pad_diameter_Inner[i]),
s );
}
}
}
}
printf("}\n\n");
}
}
// SIGNALS
printheader("Nets");
int Pad_ID, Xpad, Ypad, EpadX, EpadY, TLaylimit, Blaylimit;
B.signals(S) {
printf("{NET=%s\n",S.name);
S.contactrefs(C) {
if (C.contact.pad) {
Pad_ID = Find_A_Pad( ISAPAD, 0,
C.contact.pad.shape[1], C.contact.pad.shape[2], C.contact.pad.shape[16],
C.contact.pad.angle,
C.contact.pad.diameter[1], C.contact.pad.diameter[2], C.contact.pad.diameter[16],
C.contact.pad.elongation,
C.contact.pad.drill );
if ( Pad_ID ) { // *** 17.08.2005 Pad count from 1 to total_pad ***
Xpad = C.contact.pad.x;
EpadX = Xpad;
Ypad = C.contact.pad.y;
EpadY = Ypad;
TLaylimit = 1;
Blaylimit = 16;
printf("(PIN X=%5.*f Y=%5.*f R=%s.%s P=THR%03d",
precision_of_nets,u2inch(Xpad), precision_of_nets,u2inch(Ypad),
C.element.name, C.contact.pad.name, Pad_ID); // ** correct number while listing count from 1
// ** 17.08.2005 alf@cadsoft.de ***
SayUPinFunction( C.element.name, C.contact.pad.name );
printf(") %s, Pad Diameter: %5.*f Drill: %5.*f\n",
S.name, precision_of_nets, u2inch(C.contact.pad.diameter[16]),
precision_of_nets, u2inch(C.contact.pad.drill) );
}
else {
printf("Unregistered Pin Size!\n");
}
}
if (C.contact.smd) {
Pad_ID = Find_A_Pad( ISASMD, C.contact.smd.layer,
SmdRoundness(C.contact.smd.roundness), 0, 0,
C.contact.smd.angle,
C.contact.smd.dx, 0, 0,
C.contact.smd.dy,
0 );
if ( Pad_ID ) { // *** 17.08.2005 count from 1 ***
Xpad = C.contact.smd.x;
EpadX = Xpad;
Ypad = C.contact.smd.y;
EpadY = Ypad;
TLaylimit = C.contact.smd.layer;
Blaylimit = C.contact.smd.layer;
printf("(PIN X=%5.*f Y=%5.*f R=%s.%s P=SMD%03d",
precision_of_nets,u2inch(Xpad), precision_of_nets,u2inch(Ypad),
C.element.name, C.contact.smd.name, Pad_ID); // ** correct number while listing count from 1
// ** 17.08.2005 alf@cadsoft.de *** SayUPinFunction( C.element.name, C.contact.smd.name );
printf(") %s, Smd Dx: %5.*f Dy: %5.*f\n",
S.name, precision_of_nets, u2inch(C.contact.smd.dx),
precision_of_nets, u2inch(C.contact.smd.dy) );
}
else {
printf("Unregistered Smd Size!\n");
}
}
// if a pad/smd was located for this contact
// and a copper segment starts at this contact's x,y location,
// then the copper segment is included on this net.
if ( Pad_ID ) { // *** 17.08.2005 count from 1 ***
// Package element copper information
// circles
C.element.package.circles(A) {
if ( ( A.layer >= 1 ) && ( A.layer <= 16 ) ) {
printf("* %s has metal circles or isolation circles\n",C.element.name);
}
}
// polygons
C.element.package.polygons(P) {
if ( ( P.layer >= 1 ) && ( P.layer <= 16 ) ) {
printf("* %s has metal polygons\n",C.element.name);
}
}
// rectangles
C.element.package.rectangles(R) {
if ( ( R.layer >= 1 ) && ( R.layer <= 16 ) ) {
printf("* %s has metal rectangles\n",C.element.name);
}
}
// Find any wires that connect to this pin/pad that are internal to the package
// 1. build a table of all wires on the accepted layer
int AnyPackageWiresCount = 0;
int Wx1[], Wy1[], Wx2[], Wy2[], Wwid[], Wusedflag[],
Wcurve[], Warcx1[], Warcx2[], Warcxc[], Warcy1[], Warcy2[], Warcyc[], Warcradius[],
Wlayer ;
C.element.package.wires(W) {
// find all wires on the correct layer.
if ( ( W.layer >= TLaylimit ) && ( W.layer <= Blaylimit ) ) {
Wx1[AnyPackageWiresCount] = W.x1;
Wy1[AnyPackageWiresCount] = W.y1;
Wx2[AnyPackageWiresCount] = W.x2;
Wy2[AnyPackageWiresCount] = W.y2;
Wwid[AnyPackageWiresCount] = W.width;
Wcurve[AnyPackageWiresCount] = W.curve;
if (W.curve) { // 21.04.2005 alf@cadsoft.de
Warcx1[AnyPackageWiresCount] = W.arc.x1;
Warcx2[AnyPackageWiresCount] = W.arc.x2;
Warcxc[AnyPackageWiresCount] = W.arc.xc;
Warcy1[AnyPackageWiresCount] = W.arc.y1;
Warcy2[AnyPackageWiresCount] = W.arc.y2;
Warcyc[AnyPackageWiresCount] = W.arc.yc;
Warcradius[AnyPackageWiresCount] = W.arc.radius;
}
Wusedflag[AnyPackageWiresCount] = no;
TLaylimit = W.layer; // fix layer to first found layer on an accepted first layer
Blaylimit = W.layer; // fix layer to first found layer on an accepted first layer
Wlayer = W.layer; // fix the layer
AnyPackageWiresCount++; // count one segment
}
}
// 2. search for physically connected copper segments, even if out of order
if ( AnyPackageWiresCount != 0 ) {
for ( int woi = 0; woi < AnyPackageWiresCount; woi++ ) {
if ( Wusedflag[woi] == no ) {
// check either end of the segment
if ( ( Wx1[woi] == Xpad ) && ( Wy1[woi] == Ypad ) ) {
Xpad = Wx2[woi]; // remember the end of this segment
Ypad = Wy2[woi]; // which must be the start of the next segment
Wusedflag[woi] = yes;
woi = 0; // start searching list from the beginning again
}
else if ( ( Wx2[woi] == Xpad ) && ( Wy2[woi] == Ypad ) ) {
Xpad = Wx1[woi]; // remember the end of this segment
Ypad = Wy1[woi]; // which must be the start of the next segment
Wusedflag[woi] = yes;
woi = 0; // start searching list from the beginning again
}
}
}
}
// 3. write out all segments attached to the contact
if ( AnyPackageWiresCount != 0 ) {
for ( int woi = 0; woi < AnyPackageWiresCount; woi++ ) {
if ( Wusedflag[woi] == yes ) {
// write the segment
if ( Wlayer >= 1 && Wlayer <= 16 ) {
if (Wcurve[woi]) {
printf("(PERIMETER_ARC X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f XC=%5.*f YC=%5.*f R=%5.*f W=%5.*f L=%s) Arcs: Board Outline Arc is CCW\n",
precision_of_nets,u2inch(Warcx1[woi]), precision_of_nets,u2inch(Warcy1[woi]),
precision_of_nets,u2inch(Warcx2[woi]), precision_of_nets,u2inch(Warcy2[woi]),
precision_of_nets,u2inch(Warcxc[woi]), precision_of_nets,u2inch(Warcyc[woi]),
precision_of_nets,u2inch(Warcradius[woi]),
precision_of_nets,u2inch(Wwid[woi]),
LayerNames[Wlayer] );
}
else {
printf("(SEG X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f W=%5.*f L=%s) %s Internal Package Wire\n",
precision_of_nets,u2inch(Wx1[woi]),
precision_of_nets,u2inch(Wy1[woi]),
precision_of_nets,u2inch(Wx2[woi]),
precision_of_nets,u2inch(Wy2[woi]),
precision_of_nets,u2inch(Wwid[woi]),
LayerNames[Wlayer],
S.name);
}
}
// write any contact pins or smds
int OtherPad_ID;
C.element.package.contacts(Q) {
// don't write out contacts at the original element contact location
if ( ( Q.x != EpadX ) || ( Q.y != EpadY ) ) {
// check if this element contact is at either end of the wire segment
if ( ( ( Q.x == Wx1[woi] ) && ( Q.y == Wy1[woi] ) ) ||
( ( Q.x == Wx2[woi] ) && ( Q.y == Wy2[woi] ) ) ) {
// if a through hole pad
if (Q.pad) {
// find a pad on any layer
OtherPad_ID = Find_A_Pad( ISAPAD, 0,
Q.pad.shape[1], Q.pad.shape[2], Q.pad.shape[16],
Q.pad.angle,
Q.pad.diameter[1], Q.pad.diameter[2], Q.pad.diameter[16],
Q.pad.elongation,
Q.pad.drill );
if ( OtherPad_ID ) { // *** 17.08.2005 count from 1 ***
printf("(PIN X=%5.*f Y=%5.*f R=%s.%s P=THR%03d",
precision_of_nets, u2inch(Q.pad.x), precision_of_nets, u2inch(Q.pad.y),
C.element.name, Q.pad.name, OtherPad_ID);
SayUPinFunction( C.element.name, Q.pad.name );
printf(") %s, Internal Package Pad Diameter: %5.*f Drill: %5.*f\n",
S.name, precision_of_nets,u2inch(Q.pad.diameter[16]),
precision_of_nets, u2inch(Q.pad.drill) );
InsertAssocatedPin( C.element.name, Q.pad.name );
}
else {
printf("Unregistered Internal Package Pin Size!\n");
}
}
// if a smd pad
if (Q.smd) {
// smd pad must be on this layer
if ( Q.smd.layer == Wlayer ) {
// find a smd that matches
OtherPad_ID = Find_A_Pad( ISASMD, Q.smd.layer,
SmdRoundness(Q.smd.roundness), 0, 0,
Q.smd.angle,
Q.smd.dx, 0, 0,
Q.smd.dy,
0 );
if ( OtherPad_ID ) { // *** 17.08.2005 count from 1 ***
printf("(PIN X=%5.*f Y=%5.*f R=%s.%s P=SMD%03d",
precision_of_nets,u2inch(Q.smd.x), precision_of_nets,u2inch(Q.smd.y),
C.element.name, Q.smd.name, OtherPad_ID);
SayUPinFunction( C.element.name, Q.smd.name );
printf(") %s, Smd Dx: %5.*f Dy: %5.*f\n",
S.name,precision_of_nets,u2inch(Q.smd.dx),
precision_of_nets,u2inch(Q.smd.dy) );
InsertAssocatedPin( C.element.name, Q.smd.name );
}
else {
printf("Unregistered Smd Size!\n");
}
}
}
}
}
}
}
}
}
}
}
S.vias(V) {
Pad_ID = Find_A_Pad( ISAPAD, 18,
V.shape[1], V.shape[2], V.shape[16],
V.end,
V.diameter[1], V.diameter[2], V.diameter[16],
V.start,
V.drill );
if ( Pad_ID ) { // 17.08.2005 count from 1 ***
printf("(VIA X=%5.*f Y=%5.*f P=THR%03d) %s\n",
precision_of_nets,u2inch(V.x), precision_of_nets, u2inch(V.y),
Pad_ID, S.name); // ** correct number while listing count from 1
// ** 17.08.2005 alf@cadsoft.de ***
}
else {
printf("Unregistered Via Size!\n");
}
}
S.wires(W) {
if (W.layer >= 1 && W.layer <= 16 ) {
if (W.curve) {
printf("(ARC X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f XC=%5.*f YC=%5.*f R=%5.*f W=%5.*f L=%s)\n",
precision_of_nets,u2inch(W.arc.x1), precision_of_nets,u2inch(W.arc.y1),
precision_of_nets,u2inch(W.arc.x2), precision_of_nets,u2inch(W.arc.y2),
precision_of_nets,u2inch(W.arc.xc), precision_of_nets,u2inch(W.arc.yc),
precision_of_nets,u2inch(W.arc.radius),
precision_of_nets,u2inch(W.width),
LayerNames[W.layer] );
}
else {
printf("(SEG X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f W=%5.*f L=%s) %s\n",
precision_of_nets,u2inch(W.x1), precision_of_nets,u2inch(W.y1),
precision_of_nets,u2inch(W.x2), precision_of_nets,u2inch(W.y2),
precision_of_nets,u2inch(W.width), LayerNames[W.layer], S.name);
}
}
}
S.polygons(P) {
printf("* POLYGONS NOT Allowed in HYP as of BoardSimm 2.2 Build 70. ");
printf("Hopefully someday they will!\n");
printf("* I=Isolate S=Spacing W=Width O=Orphins_On/Off P=Pour_SOLID/HATCH T=Thermals_On/Off L=Layer) Polygon Format\n");
printf("*(PLG I=%5.*f S=%5.*f W=%5.*f O=%s P=%s T=%s L=%s) Polygon %s Data\n",
precision_of_nets,u2inch(P.isolate),precision_of_nets,u2inch(P.spacing),
precision_of_nets,u2inch(P.width),P.orphans ? "On" : "Off",
P.pour == POLYGON_POUR_SOLID ? "SOLID" : "HATCH",
P.thermals ? "On" : "Off",LayerNames[P.layer],S.name);
P.wires(W) {
printf("(SEG X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f W=%5.*f L=%s) Polygon %s\n",
precision_of_nets,u2inch(W.x1),precision_of_nets,u2inch(W.y1),
precision_of_nets,u2inch(W.x2),precision_of_nets,u2inch(W.y2),
precision_of_nets,u2inch(W.width),LayerNames[W.layer],S.name);
}
}
printf("}\n\n");
}
// Unconnected Component Pins are on their own special net "HYP$xPy"
// where x=element name and y=pin name
// handle all unconnected package pins
B.elements(E) {
E.package.contacts(C) {
if ( strlen(C.signal) == 0 ) {
if (C.pad) {
Pad_ID = Find_A_Pad( ISAPAD, 0,
C.pad.shape[1], C.pad.shape[2], C.pad.shape[16],
C.pad.angle,
C.pad.diameter[1], C.pad.diameter[2], C.pad.diameter[16],
C.pad.elongation,
C.pad.drill );
if ( Pad_ID ) { // *** 17.08.2005 count from 1 ***
if ( FindAssocatedPin( E.name, C.pad.name ) == 0 ) {
Xpad = C.pad.x;
Ypad = C.pad.y;
printf("{NET=HYP$%s.%s\n",E.name,C.pad.name);
printf("(PIN X=%5.*f Y=%5.*f R=%s.%s P=THR%03d",
precision_of_nets,u2inch(Xpad), precision_of_nets,u2inch(Ypad),
E.name, C.pad.name, Pad_ID);
printf(") Pad Diameter: %5.*f Drill: %5.*f\n",
precision_of_nets, u2inch(C.pad.diameter[16]),
precision_of_nets, u2inch(C.pad.drill) );
printf("}\n\n");
}
else {
printf("* PIN %s.%s is part of an internal package net.\n",E.name,C.pad.name);
}
}
else {
printf("* Unregistered Pin Size!\n");
}
}
if (C.smd) {
Pad_ID = Find_A_Pad( ISASMD, C.smd.layer,
SmdRoundness(C.smd.roundness), 0, 0,
C.smd.angle,
C.smd.dx, 0, 0,
C.smd.dy,
0 );
if ( Pad_ID ) { // *** 17.08.2005 count from 1 ***
if ( FindAssocatedPin( E.name, C.smd.name ) == 0 ) {
Xpad = C.smd.x;
Ypad = C.smd.y;
printf("{NET=HYP$%s.%s\n",E.name,C.smd.name);
printf("(PIN X=%5.*f Y=%5.*f R=%s.%s P=SMD%03d",
precision_of_nets,u2inch(Xpad), precision_of_nets,u2inch(Ypad),
E.name, C.smd.name, Pad_ID);
printf(") Smd Dx: %5.*f Dy: %5.*f\n",
precision_of_nets, u2inch(C.smd.dx),
precision_of_nets, u2inch(C.smd.dy) );
printf("}\n\n");
}
else {
printf("* PIN %s.%s is part of an internal package net.\n",E.name,C.smd.name);
}
}
else {
printf("* Unregistered Smd Size!\n");
}
}
}
}
}
// NETS that aren't signals but are copper are exported as a net named "N$ComNet"
// Search for any common nets
int AnyNets = no;
// B.arcs(A) if ( ( A.layer >= 1 ) && ( A.layer <= 16 ) ) AnyNets = yes;
B.circles(C) if ( ( C.layer >= 1 ) && ( C.layer <= 16 ) ) AnyNets = yes;
B.rectangles(R) if ( ( R.layer >= 1 ) && ( R.layer <= 16 ) ) AnyNets = yes;
B.wires(W) if ( ( W.layer >= 1 ) && ( W.layer <= 16 ) ) AnyNets = yes;
if ( AnyNets == yes ) {
printf("{NET=N$ComNet\n");
// CIRCLES
B.circles(C) {
if ( ( C.layer >= 1 ) && ( C.layer <= 16 ) ) {
printf("(ARC X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f XC=%5.*f YC=%5.*f R=%5.*f W=%5.*f L=%s) Circle\n",
precision_of_nets,u2inch(C.x),precision_of_nets,u2inch(C.y+C.radius),
precision_of_nets,u2inch(C.x),precision_of_nets,u2inch(C.y+C.radius),
precision_of_nets,u2inch(C.x),precision_of_nets,u2inch(C.y),
precision_of_nets,u2inch(C.radius),precision_of_nets,u2inch(C.width),
LayerNames[C.layer]);
}
}
// RECTANGLES
B.rectangles(R) {
if ( ( R.layer >= 1 ) && ( R.layer <= 16 ) ) {
printf("(SEG X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f W=%5.*f L=%s) Rectangle Segment Bottom\n",
precision_of_nets,u2inch(R.x1),precision_of_nets,u2inch(R.y1),
precision_of_nets,u2inch(R.x2), precision_of_nets,u2inch(R.y1),
precision_of_nets,RectOutlineWireWidth,LayerNames[R.layer]);
printf("(SEG X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f W=%5.*f L=%s) Rectangle Segment Right\n",
precision_of_nets,u2inch(R.x2),precision_of_nets,u2inch(R.y1),
precision_of_nets,u2inch(R.x2),precision_of_nets,u2inch(R.y2),
precision_of_nets,RectOutlineWireWidth,LayerNames[R.layer]);
printf("(SEG X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f W=%5.*f L=%s) Rectangle Segment Top\n",
precision_of_nets,u2inch(R.x2),precision_of_nets,u2inch(R.y2),
precision_of_nets,u2inch(R.x1),precision_of_nets,u2inch(R.y2),
precision_of_nets,RectOutlineWireWidth,LayerNames[R.layer]);
printf("(SEG X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f W=%5.*f L=%s) Rectangle Segment Left\n",
precision_of_nets,u2inch(R.x1),precision_of_nets,u2inch(R.y2),
precision_of_nets,u2inch(R.x1),precision_of_nets,u2inch(R.y1),
precision_of_nets,RectOutlineWireWidth,LayerNames[R.layer]);
}
}
// WIRES
B.wires(W) {
if ( ( W.layer >= 1 ) && ( W.layer <= 16 ) ) {
if (W.curve) {
// ARCS
printf("(ARC X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f XC=%5.*f YC=%5.*f R=%5.*f W=%5.*f L=%s) Arc is CCW\n",
precision_of_nets,u2inch(W.arc.x2),precision_of_nets,u2inch(W.arc.y2),
precision_of_nets,u2inch(W.arc.x1),precision_of_nets,u2inch(W.arc.y1),
precision_of_nets,u2inch(W.arc.xc),precision_of_nets,u2inch(W.arc.yc),
precision_of_nets,u2inch(W.arc.radius),precision_of_nets,u2inch(W.width),
LayerNames[W.layer]);
}
else {
printf("(SEG X1=%5.*f Y1=%5.*f X2=%5.*f Y2=%5.*f W=%5.*f L=%s) Wire Segment\n",
precision_of_nets,u2inch(W.x1),precision_of_nets,u2inch(W.y1),
precision_of_nets,u2inch(W.x2),precision_of_nets,u2inch(W.y2),
precision_of_nets,u2inch(W.width),LayerNames[W.layer]);
}
}
}
printf("}\n\n");
} // end of copper as common net
// END OF RUN
printheader("End of data");
printf("{END}\n\n");
printf("{KEY=028-015E-4E5D}\n\n");
} // end of output() {}
} // end of board() {}