#usage "Export DIF 4.0 format
"
"This format is used for production and test purposes. It has been defined by Digitaltest GmbH.
"
"Run the ULP from the board editor and get the file boardname.dif.
"
"Please have a look at the \"user definable parameters\" section of the program."
"
"
"Author: support@cadsoft.de"
// THIS PROGRAM IS PROVIDED AS IS AND WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED
// 2005-02-28: Corrected output for mirrored components
// Added "File Save" dialog
// by support@cadsoft.de
// 2005-11-09: Corrected Y Coordinate, was always minus
// 2008-05-27: Corrected relativ coordinates if package rotate in 0.1 degree
// by alf@cadsoft.de
string REVISION = "2.00";
////////////////// user definable parameters ////////////////////////////////////////////////
int pad_layer = 1; // change to 16 if pad parameters should be taken from bottom layer
int nr_of_layers = 2;
int fill_polygons = 1; // set to 0 if polygons are not to be filled
// if set to 1, please make sure the width parameter of the polygons
// is >> 0
// make also sure the polygon filling is visible in EAGLE
/////////////////////////////////////////////////////////////////////////////////////////////
string difversion = "4.0";
string jobname, pcbname,
shapename[], // package names
t[]; // padtypes
real ang2, x, y;
int nr_of_nets = 0, nr_of_comps = 0, i, new, sx, dummy_pad_code;
//-----------------------------------------------------
string validname (string s) {
int i;
for (i = 0; s[i]; i++) {
if (s[i] == ',') s[i] = '_';
if (s[i] == ';') s[i] = '_';
if (s[i] == ')') s[i] = '_';
// add further substitutions here
}
return s;
}
//-----------------------------------------------------
int u2u(int x) { // resolution 1/10000 mm
// return u2mil(x); // mil
return x;
}
//-----------------------------------------------------
int u2x(int x) {
return u2u(x);
}
//-----------------------------------------------------
int u2y(int x) {
return u2u(x); // correct sign, was always minus 2005.11.09 alf@cadsoft.de
}
//-----------------------------------------------------
real deg2arc(int x) { // degree to arc
return x*PI/180;
}
//-----------------------------------------------------
int u2ang(real x) {
if (x > 360)
x = x -360;
return x;
}
//----------------------------------------------------
void relco (UL_ELEMENT E, int xt, int yt) { // change if finer rotation possible
xt = xt - E.x; yt = yt - E.y; // move part origin to 0,0
if (E.mirror) { // flip back if mirrored
x = -x;
}
if (E.angle == 0) { // rotate to zero position
x = xt; y = yt;
}
if (E.angle == 90) {
x = yt; y = -xt;
}
if (E.angle == 180) {
x = -xt; y = -yt;
}
if (E.angle == 270) {
x = -yt; y = xt;
}
}
//-----------------------------------------------------
string padtype(UL_PACKAGE P, UL_CONTACT C) {
string s;
int pdi;
if (C.pad) {
pdi = u2u(C.pad.diameter[pad_layer]);
sprintf(s, "pad_%d_%d_%d", C.pad.shape[pad_layer], u2u(C.pad.diameter[pad_layer]), u2u(C.pad.drill));
}
if (C.smd) {
sprintf(s, "smd_%d_%d", u2x(C.smd.dx), u2y(C.smd.dy));
}
return s;
}
//-----------------------------------------------------
int padindex(UL_PACKAGE P,UL_CONTACT C) {
int i = 0;
for (i = 0; t[i]; i++) {
if (t[i] == padtype(P,C))
return i+1;
}
return i; // should not be possible
}
//-----------------------------------------------------
string viatype(UL_VIA V) {
string s;
int pdi;
pdi = u2u(V.diameter[pad_layer]);
sprintf(s, "pad_%d_%d_%d", V.shape[pad_layer], u2u(V.diameter[pad_layer]), u2u(V.drill));
return s;
}
//-----------------------------------------------------
int viaindex(UL_VIA V) {
int i = 0;
for (i = 0; t[i]; i++) {
if (t[i] == viatype(V))
return i+1;
}
return i; // should not be possible
}
//-----------------------------------------------------
int realnet(UL_SIGNAL S) {
S.contactrefs(S)
return 1;
return 0;
}
//////////////////////////////////////////////////////
void create_environment () {
int t = time();
printf(" { ENVIRONMENT\n");
printf(" { SOURCE \"EAGLE %d.%02d %s Revision %s\" }\n", EAGLE_VERSION, EAGLE_RELEASE, filename(argv[0]),REVISION);
printf(" { VERSION %s }\n", difversion);
printf(" { DATE %d/%d/%d }\n", t2day(t),t2month(t)+1,t2year(t));
printf(" { TIME %d:%d:%d }\n", t2hour(t),t2minute(t),t2second(t));
printf(" { UNITS 1/10000 mm }\n");
printf(" { LAYER %d }\n", nr_of_layers);
printf(" { TOP_LAYER 1 }\n");
printf(" { BOTTOM_LAYER 16 }\n");
printf(" { NO_NET %d }\n", nr_of_nets);
printf(" { NO_COMP %d }\n", nr_of_comps);
printf(" }\n");
}
//////////////////////////////////////////////////////
void board_data(UL_BOARD B) {
int i = 0;
printf (" { BOARD\n");
printf (" { F\n");
B.wires(W) { // if board outline as wires in board
i++;
if (W.layer == LAYER_DIMENSION) {
printf(" { L (%d,%d) (%d,%d) }\n", u2x(W.x1), u2y(W.y1), u2x(W.x2), u2y(W.y2));
}
}
if (i == 0) { // board contains no dim wires, try packages
B.elements(E) {
E.package.wires(W) {
if (W.layer == LAYER_DIMENSION) {
printf(" { L (%d,%d) (%d,%d) }\n", u2x(W.x1), u2y(W.y1), u2x(W.x2), u2y(W.y2));
}
}
}
}
printf (" }\n");
printf (" }\n");
}
//////////////////////////////////////////////////////
void components(UL_BOARD B) {
int i, pic_nr;
string devname = "";
printf (" { COMPONENTS\n");
B.elements(E) {
if (E.package) {
printf(" { COMP\n");
printf(" { COMP_DEF\n");
printf(" { NAME %s }\n", E.name);
printf(" { PART_NR %s }\n", validname(E.package.name)+"_"+validname(E.package.library));
printf(" }\n");
printf(" { PIN_DEF\n");
int issmd = 0;
E.package.contacts(C) {
printf(" { PIN %s { NET %s } }\n", C.name, C.signal);
if (C.smd) issmd = 1;
}
// find picture code
for (i=0; shapename[i] != validname(E.package.name)+"_"+validname(E.package.library); i++) {
}
pic_nr = i;
printf(" }\n");
printf(" { PICTURE\n");
printf(" { ORIGIN (%d,%d) }\n", u2x(E.x), u2y(E.y));
printf(" { PIC %d }\n", pic_nr);
printf(" { ROTATION %d }\n", u2ang(E.angle));
int mside = 1;
if (E.mirror) {
mside = 2;
}
printf(" { M_SIDE %d }\n", mside);
if (issmd) {
printf(" { KIND SMD }\n");
}
/* implement later if necessary
E.texts(T) {
printf(" { TEXT\n");
printf(" }\n");
}
*/
printf(" }\n");
printf(" }\n");
}
}
printf(" }\n");
}
//////////////////////////////////////////////////////
void pad_symbols(UL_BOARD B) {
int i, j = 0, new; // j+1 = pad index; t[] contains padtypes
printf (" { PAD_DEF\n");
B.elements(E) {
E.package.contacts(C) {
if (1 /* C.pad */) {
new = 1; // padtype not generated yet
for (i = 0; t[i]; i++) {
if (t[i] == padtype(E.package, C))
new = 0; // padtype exists
}
if (new) {
t[j] = padtype(E.package, C);
j++;
if (C.pad)
printf(" { PAD %d\n { SIZE %d }\n { DRILL %d }\n }\n",
j,abs(u2u(C.pad.diameter[pad_layer])),abs(u2u(C.pad.drill)));
if (C.smd)
printf(" { PAD %d\n { SIZE %d }\n { DRILL 0 }\n }\n",
j, min(abs(u2x(C.smd.dx)), abs(u2y(C.smd.dy))));
}
}
}
}
B.signals(S) {
S.vias(V) {
new = 1;
for (i = 0; t[i]; i++) {
if (t[i] == viatype(V))
new = 0; // padtype exists
}
if (new) {
t[j] = viatype(V);
j++;
dummy_pad_code = j; // find pad code for dummy pad
printf(" { PAD %d\n { SIZE %d }\n { DRILL %d }\n }\n",
j,u2u(V.diameter[pad_layer]),u2u(V.drill));
}
}
}
printf (" }\n");
}
//////////////////////////////////////////////////////
// 2008-05-27: Corrected relativ coordinates if package rotate in 0.1 degree alf@cadsoft.de
void picturePackage(UL_PACKAGE P, int ox, int oy) {
real angle, delta = 15;
P.wires(W) {
if (W.layer == LAYER_TPLACE || W.layer == LAYER_TDOCU || W.layer == LAYER_BPLACE || W.layer == LAYER_BDOCU) {
if (W.arc) {
// process arcs (done with wire segments)
printf(" { L (%d,%d)\n", u2x(W.arc.x1-ox), u2y(W.arc.y1-oy));
angle = W.arc.angle1 + delta;
while (angle < W.arc.angle2) {
printf(" (%d,%d)\n",
u2x((W.arc.xc-ox+W.arc.radius) * cos(deg2arc(angle))),
u2y((W.arc.yc-oy+W.arc.radius) * sin(deg2arc(angle))));
angle += delta;
}
printf(" (%d,%d)\n }\n", u2x(W.arc.x2-ox), u2y(W.arc.y2-oy));
}
else {
printf(" { Linie (%d,%d) ", u2x(W.x1-ox), u2y(W.y1-oy));
printf("(%d,%d) }\n", u2x(W.x2-ox), u2y(W.y2-oy));
}
}
}
P.circles(W) {
if (W.layer == LAYER_TPLACE || W.layer == LAYER_TDOCU || W.layer == LAYER_BPLACE || W.layer == LAYER_BDOCU) {
printf(" { L (%d,%d)\n", u2x(W.x-ox+W.radius), u2y(W.y-oy));
angle = 0;
while (angle < 360) {
printf(" (%d,%d)\n", u2x((W.x-ox+W.radius) * cos(deg2arc(angle))), u2y((W.y-oy+W.radius) * sin(deg2arc(angle))));
angle += delta;
}
printf(" (%d,%d)\n }\n", u2x(W.x-ox+W.radius), u2y(W.y-oy));
}
}
P.rectangles(W) {
if (W.layer == LAYER_TPLACE || W.layer == LAYER_TDOCU || W.layer == LAYER_BPLACE || W.layer == LAYER_BDOCU) {
printf(" { L (%d,%d)\n", u2x(W.x1-ox), u2y(W.y1-oy));
printf(" (%d,%d)\n", u2x(W.x2-ox), u2y(W.y1-oy));
printf(" (%d,%d)\n", u2x(W.x2-ox), u2y(W.y2-oy));
printf(" (%d,%d)\n", u2x(W.x1-ox), u2y(W.y2-oy));
printf(" (%d,%d)\n }\n", u2x(W.x1-ox), u2y(W.y1-oy));
}
}
int nr_of_pins = 0;
P.contacts(C) { nr_of_pins++;}
if (nr_of_pins) {
printf(" { PINS %d\n", nr_of_pins);
}
P.contacts(C) {
printf(" (%d,%d) %d\n", u2x(C.x-ox), u2y(C.y-oy), padindex(P, C)); // Pin IDs
}
if (nr_of_pins) {
printf(" }\n");
}
printf(" { SPECIFIC \"%s\" }\n", validname(P.name)+"_"+validname(P.library)); // PACK.NAME
printf(" }\n"); // end pic n
return;
}
//////////////////////////////////////////////////////
void pictures(UL_BOARD B) {
printf ("{ PIC_LIB\n");
sx=0;
B.elements(E) {
if (E.package) {
new = 1; // padtype not generated yet
for (i = 0; shapename[i]; i++) {
if (shapename[i] == validname(E.package.name)+"_"+validname(E.package.library))
new = 0; // ident. package exists
}
if (new) {
shapename[sx] = validname(E.package.name)+"_"+validname(E.package.library);
printf(" { PIC %d\n",sx++); // PACKAGE NR
picturePackage(E.package, E.x, E.y);
}
}
}
printf(" { PIC 999\n");
printf(" { R (0, 0) }\n");
printf(" { PINS 1 (0, 0) %d }\n", dummy_pad_code);
printf(" }\n");
printf("}\n");
}
//////////////////////////////////////////////////////
void nets(UL_BOARD B) {
printf(" { NET_DEF\n");
B.signals(S) {
if (realnet(S)) {
printf(" { NET %s\n", S.name);
S.wires(W) {
printf(" { W (%d, %d) %d %d (%d %d) %d %d }\n", u2x(W.x1), u2y(W.y1), W.layer, u2u(W.width), u2x(W.x2), u2y(W.y2), W.layer, u2u(W.width));
}
S.polygons(P) {
P.contours(W) {
printf(" { W (%d, %d) %d %d (%d %d) %d %d }\n", u2x(W.x1), u2y(W.y1), W.layer, u2u(W.width), u2x(W.x2), u2y(W.y2), W.layer, u2u(W.width));
}
if (fill_polygons) {
P.fillings(W) {
printf(" { W (%d, %d) %d %d (%d %d) %d %d }\n", u2x(W.x1), u2y(W.y1), W.layer, u2u(W.width), u2x(W.x2), u2y(W.y2), W.layer, u2u(W.width));
}
}
}
S.vias(V) {
printf(" { V (%d, %d) %d 1, 15 }\n", u2x(V.x), u2y(V.y), viaindex(V));
}
printf(" }\n");
}
}
printf(" }\n");
}
//////////////////////////////////////////////////////
void net_comp_count(UL_BOARD B) {
nr_of_nets = 0;
nr_of_comps = 0;
B.signals(S) {
if (realnet(S)) {
nr_of_nets++;
}
}
B.elements(E) {
if (E.package) {
nr_of_comps++;
}
}
}
//////////////////////////////////////////////////////
if (board) board(B) {
jobname = filename(filesetext(B.name, ""));
pcbname = filename(filesetext(B.name, ""));
string fileName = dlgFileSave("Save DIF 4.0 File", filesetext(B.name, ".dif"), "*.dif");
if (fileName == "") exit(0);
output(fileName) {
printf("{ JOB %s\n", jobname);
printf(" { PCB %s\n", pcbname);
net_comp_count(B);
create_environment();
board_data(B);
pad_symbols(B);
pictures(B);
nets(B);
components(B);
printf(" }\n");
printf("}\n");
}
}
else {
dlgMessageBox("\n Start this ULP in a Board \n");
exit (0);
}