#usage "Export IPC-D-356 data format\n"
"
"
"Generates a netlist in IPC-D-356 format from the current board."
"
"
"Please take care of net names. IPC-D-356 does not allow more than 14 characters! "
"Written for EAGLE 4.1. "
"
"
"IPC-D-356 syntax generated according to the specifications of
"
"
"
"IPC-D-356 Simplified "
"Written by Rich Nedbal "
"DownStream Technologies, LLC "
" |
"
""
"Author: support@cadsoft.de"
#require 4.1602
// THIS PROGRAM IS PROVIDED AS IS AND WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED
//
// Release 1.0 -- November 2003
// Release 1.0.1 -- May 2006, Added source of specification (ric)
// Release 2.0.0 -- 2012-02-29, values calculated with u2inch (alf)
// Release 2.0.1 -- 2012-03-13, corrected calulation of diameter (alf)
// now generate the same data as the original ulp up to V5.
// Release 2.0.2 -- corrected line 82, multiplicator 1000 -> 10000
// Release 2.1.0 -- Added support for blind and buried vias (JG)
// Release 2.2.0 -- Added support for long net names(JG)
// Release 2.3.0 -- Added length checks for Reference Designators(JG)
/* TODO LIST
*
* Add length checks to every parameter, the file format is very sensitive to long names
*/
string Version = "2.3.0";
string fileName, RefDes, Access, Xpolarity, Ypolarity, RestOfLine, NoDiameter, EmptySignal, Alias[], temp[], SigName;
int i = 0, n, Alias_counter = 0, TypeNumber, Diameter, Xcoord, Ycoord, RectDataX, RectDataY, Angle;
void Header(UL_BOARD B) {
printf("C IPC-D-356 generated by %s\n", EAGLE_SIGNATURE);
printf("C Database %s -- Exported at %s\n", B.name, t2string(time()));
//printf("C ULP-Version %s : Values = Inch/1000\n", Version); // 2012-03-13
printf("C \n");
printf("P JOB EAGLE %d.%d NETLIST, DATE: %s\n", EAGLE_VERSION, EAGLE_RELEASE , t2string(time()));
printf("P UNITS CUST 0\n");
printf("P DIM N\n");
printf("P IMAGE PRIMARY\n");
B.signals(S) {
//Check if signal name exceeds 14 character limit
if (strlen(S.name) >= 14) {
sprintf(Alias[i],"%s;WZ%03d", S.name, Alias_counter); //1000 Long netnames allowed
strsplit(temp,Alias[i],';');
printf("P NNAME%s %-58s\n",temp[1],temp[0]);
i++;
Alias_counter++;
}
if (Alias_counter > 999) {
dlgMessageBox("You have more than 1000 net names longer than 14 characters, please use shorter names in order to generate the netlist");
exit (0);
}
}
}
void TestRecord(UL_BOARD B) {
B.signals(S) {
S.vias(V) {
Access = "A00"; //This value is irrelevant for blind/buried vias but is necessary, to conform to the format
if (V.start == 1 && V.end == 16) {
TypeNumber = 317 ;
}
else {
TypeNumber = 307 ; //Blind or buried vias
}
RefDes = "VIA";
Diameter = round(u2inch(V.drill)*1000);
Xcoord = round(u2inch(V.x)*10000);
Ycoord = round(u2inch(V.y)*10000);
if (Xcoord >= 0) Xpolarity = "X ";
if (Xcoord < 0) Xpolarity = "X-";
if (Ycoord >= 0) Ypolarity = "Y ";
if (Ycoord < 0) Ypolarity = "Y-";
//Check for long net name, if it is long use alias otherwise use name
if (strlen(S.name) >= 14) {
SigName = lookup(Alias, S.name, 1, ';');
}
else {
SigName = S.name;
}
if (V.start == 1 && V.end == 16) {
RectDataX = RectDataY = round(u2inch(V.diameter[V.start])*10000);
RestOfLine = " " ; // 13 blanks to fill up 80 characters
printf("%3d%-14s %-12sD%4dP%-3s%2s%6d%2s%6dX%4dY%4d%-13s\n",
TypeNumber, SigName, RefDes, Diameter, Access, Xpolarity, abs(Xcoord), Ypolarity, abs(Ycoord),
RectDataX, RectDataY, RestOfLine);
}
else if (V.start == 1 && V.end != 16) {
//Blind Vias with access from the top
RectDataX = RectDataY = round(u2inch(V.diameter[V.start])*10000);
RestOfLine = " " ; // 13 blanks to fill up 80 characters
EmptySignal = " "; // Blank name for the 027 record
printf("%3d%-14s %-12sD%4dP%-3s%2s%6d%2s%6d L%02dL%02d\n",
TypeNumber, SigName, RefDes, Diameter, Access, Xpolarity, abs(Xcoord), Ypolarity, abs(Ycoord),
V.start, V.end);
printf("%03d%-14s %-12s %-3s%2s%6d%2s%6dX%4dY%4d%-13s\n",
027, EmptySignal, RefDes, Access, Xpolarity, abs(Xcoord), Ypolarity, abs(Ycoord),
RectDataX, RectDataY, RestOfLine);
}
else if (V.start != 1 && V.end == 16) {
//Blind Vias with access from the bottom
RectDataX = RectDataY = round(u2inch(V.diameter[V.end])*10000);
RestOfLine = " " ; // 13 blanks to fill up 80 characters
EmptySignal = " "; // Blank name for the 027 record
printf("%3d%-14s %-12sD%4dP%-3s%2s%6d%2s%6d L%02dL%02d\n",
TypeNumber, SigName, RefDes, Diameter, Access, Xpolarity, abs(Xcoord), Ypolarity, abs(Ycoord),
V.start, V.end);
printf("%03d%-14s %-12s %-3s%2s%6d%2s%6dX%4dY%4d%-13s\n",
027, EmptySignal, RefDes, Access, Xpolarity, abs(Xcoord), Ypolarity, abs(Ycoord),
RectDataX, RectDataY, RestOfLine);
}
else {
//Buried Vias
printf("%3d%-14s %-12sD%4dP%-3s%2s%6d%2s%6d L%02dL%02d\n",
TypeNumber, SigName, RefDes, Diameter, Access, Xpolarity, abs(Xcoord), Ypolarity, abs(Ycoord),
V.start, V.end);
}
}
}
B.elements(E) {
E.package.contacts(C) {
if (C.pad) {
TypeNumber = 317 ;
RefDes = E.name;
//Check for long reference designator
if (strlen(RefDes) > 6) {
int result;
string toolong_mesg = RefDes+"is too long a reference designator. Would you like to truncate it to 6 characters? No will exit the ULP";
if(dlgMessageBox(toolong_mesg,"&Yes","&No") == 0) {
RefDes = strsub(RefDes, 0, 5);
}
else {
exit(0);
}
}
Diameter = round(u2inch(C.pad.drill)*1000);
Access = "A00";
Xcoord = round(u2inch(C.pad.x)*10000);
Ycoord = round(u2inch(C.pad.y)*10000);
if (Xcoord >= 0) Xpolarity = "X ";
if (Xcoord < 0) Xpolarity = "X-";
if (Ycoord >= 0) Ypolarity = "Y ";
if (Ycoord < 0) Ypolarity = "Y-";
if (C.pad.elongation == 0)
RectDataX = RectDataY = round(u2inch(C.pad.diameter[LAYER_TOP])*10000);
else { // if (C.pad.elongation != 0)
RectDataX = round(u2inch(C.pad.diameter[LAYER_TOP])*10000);
RectDataY = round((u2inch(C.pad.diameter[LAYER_TOP])*10000) * (C.pad.elongation / 100) + u2inch(C.pad.diameter[LAYER_TOP])*10000);
}
Angle = round(C.pad.angle);
RestOfLine = " ";
//Check for long net name, if it is long use alias otherwise use name
if (strlen(C.pad.signal) >= 14) {
SigName = lookup(Alias, C.pad.signal, 1, ';');
}
else {
SigName = C.pad.signal;
}
printf("%3d%-14s %-6s-%-4s D%4dP%-3s%2s%6d%2s%6dX%4dY%4dR%3d%-9s\n",
TypeNumber, SigName, RefDes, C.pad.name, Diameter, Access,
Xpolarity, abs(Xcoord), Ypolarity, abs(Ycoord), RectDataX, RectDataY, Angle, RestOfLine);
}
if (C.smd) {
TypeNumber = 327 ;
RefDes = E.name;
NoDiameter = " "; // No drill ==> coloum 33-38 empty
if (C.smd.layer == 1) Access = "A01";
if (C.smd.layer == 16) Access = "A16";
Xcoord = round(u2inch(C.smd.x)*10000);
Ycoord = round(u2inch(C.smd.y)*10000);
if (Xcoord >= 0) Xpolarity = "X ";
if (Xcoord < 0) Xpolarity = "X-";
if (Ycoord >= 0) Ypolarity = "Y ";
if (Ycoord < 0) Ypolarity = "Y-";
RectDataX = round(u2inch(C.smd.dx) * 10000) ;
RectDataY = round(u2inch(C.smd.dy) * 10000) ;
Angle = round(C.smd.angle);
RestOfLine = " ";
//Check for long net name, if it is long use alias otherwise use name
if (strlen(C.smd.signal) >= 14) {
SigName = lookup(Alias, C.smd.signal, 1, ';');
}
else {
SigName = C.smd.signal;
}
printf("%3d%-14s %-6s-%-4s %-6s%-3s%2s%6d%2s%6dX%4dY%4dR%3d%-9s\n",
TypeNumber, SigName, RefDes, C.smd.name, NoDiameter, Access,
Xpolarity, abs(Xcoord), Ypolarity, abs(Ycoord), RectDataX, RectDataY, Angle, RestOfLine);
}
}
// B.holes(H) TypeNumber = 347 ; printf("%d", TypeNumber);
// E.package.holes(H) TypeNumber = 347 ; printf("%d", TypeNumber);
}
}
void EndOfFile(void) {
printf("999\n");
}
//==========main===========
if (board) {
board(B) {
fileName = dlgFileSave("Save IPC-D-356 File", filesetext(B.name, ".ipc"), "*.ipc");
if (fileName == "") exit(0);
output(fileName) {
Header(B);
TestRecord(B);
EndOfFile();
}
}
}
else {
dlgMessageBox("!Start this ULP in a Board.");
exit (0);
}