#usage "Generate EAGLE Output in Fabmaster Format FATF REV 11.1

\n" "See program text for more information

" "ULP Rev. 1.42
" "Author: support@cadsoft.de" string ULPversion = "V1.42"; /////////////////////////////////////////////////////////////////////////////////////////// // ASCII Transfer Format (FATF) FABmaster software V8.E - 11 August 2000 // // FABMASTER FATF REV 11.1 // // // // // // Rev. 1.42: quick find pin-name part-name // // 2009-12-04 by support@cadsoft.de // // // // Rev. 1.41: Corrected LAYER_NAMES definition for BPLACE // // March 2007 by support@cadsoft.de // // // // Revision 1.4: Export Layer 51/52 (Layer table expanded) // // Febr. 2007 support@cadsoft.de // // // // Revision 1.3: Export Wires with Arc, rotated Pads, Pad Shape Long & Offset // // rotated Packages in 0.1 degree // // export rectangle and circle on layer 1, 16, 21, 22 // // export polygon filling on klayer 1, 16 // // export text on layer 1,16,21,22 as wire (**vector font**) // // Mai 2004 by support@cadsoft.de // /////////////////////////////////////////////////////////////////////////////////////////// // Revision 1.2: Slightly changed in the output statement, so that the Fabmaster file // // will be written in the same directory as the brd file is. // // November 2001 by support@cadsoft.de // /////////////////////////////////////////////////////////////////////////////////////////// // Revision 1.1: Runs with EAGLE version >= 4; top pad shape assumed for all layers; // fixed bug in EAGLE version output /////////////////////////////////////////////////////////////////////////////////////////// // Rudi Hofer, CadSoft, rudi.hofer@cadsoft.de, 9/99 // // THIS PROGRAM IS PROVIDED AS IS AND WITHOUT WARRANTY OF ANY KIND, // EXPRESSED OR IMPLIED. // // This ULP generates output for FABMASTER software which is able to convert the // data for automatic mounting and test equipment. The resolution is fixed to 1 mil. // // To generate the output, load the board and run this ULP from the board window. // // Restrictions and prerequisites: // - Board outline must be defined as wires in dimension layer (directly in // board or in a package). // - All coordinates must be positive!!! Please move the board accordingly!!! // - Do not use different packages with the same name (avoid REPLACE command). // - Padtypes octagon, xlongoct, ylongoct are realized with round shapes. // - For polygons no output is generated. // - Inner layer Route2..5 may contain tracks. // - Inner layer Route6 may contain a power plain (no output generated yet!). // - For all other inner layers no output is generated. // - On the top and bottom layers only wires and smd pads are output. // Exception: Circles defined in a package are output as filled circles // but do not belong to a signal. // /////////////////////////////////////////////////////////////////////////////////////////// if (EAGLE_VERSION * 100 + EAGLE_RELEASE < 411) { string h; sprintf(h, "Eagleversion %d %d ", EAGLE_VERSION, EAGLE_RELEASE); dlgMessageBox(h + "This ULP does not run in Eagle Versions older than 4.11", "OK"); exit(0); } string jobname, layer_name[], padshape[] = {"P_ROUND","P_ROUND","P_ROUND","P_ROUND","P_ROUND"},// if long/offset subst. by round viashape[] = {"P_BLOCK","P_ROUND","P_ROUND","P_ROUND","P_ROUND"},// if long/offset subst. by round padname, shapename[], // package names t[], // padtypes pst[]; // padstacktypes real cx, cy, rx, ry, x, y, x1, x2, y1, y2, r, a1, a2;; real delta = 5; int i, new, sx, padcount, pad_is_numeric, // eagle to fabmaster layer conversion // eagle 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52 ** Feb. 2007 ** flayer[] = {0, 2, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 1, 0,16,16,17, 0, 0,18,19,20,21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,16,17}; string partnumname[]; // 2009-12-03 quick find pin-name part-name int cntnumname = 0; numeric string areaEname[]; int indexareaEname[]; int cntindex = 1; // create pad number index list numeric string areaEpadname[]; int areaPadNumber[]; // the number of pad in FATF format int cntEpad = 1; int sizes[], ratio[]; // Text fonts int cntt = 0; int boardroundness = 100; // global roundness (design rules) int xmin = 32000, xmax = 0, ymin = 32000, ymax = 0; int ht = time(); //----------------------------------------------------- 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 fablayer(int l) { return flayer[l]; } //----------------------------------------------------- int u2u(int x) { // resolution 1/1000 inch return u2mil(x); // mil } //----------------------------------------------------- real deg2arc(int x) { // degree to arc return x*PI/180; } //----------------------------------------------------- int u2ang(real x, int mirror) { if (mirror) { real m = 360 - x; if (m > 180) m -= 180; else m += 180; x = round((360 - m) * 10); // clockwise in FABMASTER!!! } else { x = round((360 - x) * 10); // clockwise in FABMASTER!!! } return x; } //---------------------------------------------------- real Xneu(real Xalt, real Yalt, real Xorigin, real Yorigin, real UserWinkel) { real RADIUS = sqrt(((Xalt - Xorigin) * (Xalt - Xorigin)) + ((Yalt - Yorigin) * (Yalt - Yorigin))); real WinkelNeu; /* alter Cosinus Winkel = (Xalt - Xorigin) / RADIUS; */ if ((Xalt > Xorigin) && (Yalt >= Yorigin)) { /* Quadrant 1 */ WinkelNeu = acos((Xalt - Xorigin) / RADIUS) * 57.29578 + UserWinkel; real rad = PI / 180 * WinkelNeu; return (RADIUS * cos(rad)); } if ((Xalt < Xorigin) && (Yalt >= Yorigin)) { /* Quadrant 2 */ WinkelNeu = acos((Xalt - Xorigin) / RADIUS) * 57.29578 + UserWinkel; real rad = PI / 180 * WinkelNeu; return (RADIUS * cos(rad)); } if ((Xalt < Xorigin) && (Yalt < Yorigin)) { /* Quadrant 3 */ WinkelNeu = 360 - acos((Xalt - Xorigin) / RADIUS) * 57.29578 + UserWinkel; real rad = PI / 180 * WinkelNeu; return (RADIUS * cos(rad)); } if ((Xalt > Xorigin) && (Yalt < Yorigin)) { /* Quadrant 4 */ WinkelNeu = 360 - acos((Xalt - Xorigin) / RADIUS) * 57.29578 + UserWinkel; real rad = PI / 180 * WinkelNeu; return (RADIUS * cos(rad)); } if ((Xalt == Xorigin) && (Yalt == Yorigin)) { /* Ursprung */ WinkelNeu = (Xalt - Xorigin) + UserWinkel; real rad = PI / 180 * WinkelNeu; return (RADIUS * cos(rad)); } if ((Xalt == Xorigin) && (Yalt > Yorigin)) { /* 90° */ WinkelNeu = (Xalt - Xorigin + 90) + UserWinkel; real rad = PI / 180 * WinkelNeu; return (RADIUS * cos(rad)); } if ((Xalt == Xorigin) && (Yalt < Yorigin)) { /* 270° */ WinkelNeu = (Xalt - Xorigin + 270)+ UserWinkel; real rad = PI / 180 * WinkelNeu; return (RADIUS * cos(rad)); } } real Yneu(real Xalt, real Yalt, real Xorigin, real Yorigin, real UserWinkel) { real RADIUS = sqrt(((Xalt - Xorigin) * (Xalt - Xorigin)) + ((Yalt - Yorigin) * (Yalt - Yorigin))); real WinkelNeu; /* alter Cosinus Winkel = (Xalt - Xorigin) / RADIUS; */ if ((Xalt > Xorigin) && (Yalt >= Yorigin)) { /* Quadrant 1 */ WinkelNeu = acos((Xalt - Xorigin) / RADIUS) * 57.29578 + UserWinkel; real rad = PI / 180 * WinkelNeu; return (RADIUS * sin(rad)); } if ((Xalt < Xorigin) && (Yalt >= Yorigin)) { /* Quadrant 2 */ WinkelNeu = acos((Xalt - Xorigin) / RADIUS) * 57.29578 + UserWinkel; real rad = PI / 180 * WinkelNeu; return (RADIUS * sin(rad)); } if ((Xalt < Xorigin) && (Yalt < Yorigin)) { /* Quadrant 3 */ WinkelNeu = 360 - acos((Xalt - Xorigin) / RADIUS) * 57.29578 + UserWinkel; real rad = PI / 180 * WinkelNeu; return (RADIUS * sin(rad)); } if ((Xalt > Xorigin) && (Yalt < Yorigin)) { /* Quadrant 4 */ WinkelNeu = 360 - acos((Xalt - Xorigin) / RADIUS) * 57.29578 + UserWinkel; real rad = PI / 180 * WinkelNeu; return (RADIUS * sin(rad)); } if ((Xalt == Xorigin) && (Yalt == Yorigin)) { /* Ursprung */ WinkelNeu = (Xalt - Xorigin) + UserWinkel; real rad = PI / 180 * WinkelNeu; return (RADIUS * sin(rad)); } if ((Xalt == Xorigin) && (Yalt > Yorigin)) { /* 90° */ WinkelNeu = (Xalt - Xorigin + 90) + UserWinkel; real rad = PI / 180 * WinkelNeu; return (RADIUS * sin(rad)); } if ((Xalt == Xorigin) && (Yalt < Yorigin)) { /* 270° */ WinkelNeu = (Xalt - Xorigin + 270)+ UserWinkel; real rad = PI / 180 * WinkelNeu; return (RADIUS * sin(rad)); } } //----------------------------------------------------- string padtype(UL_ELEMENT E, UL_CONTACT C) { string s; int pdi, x1, y1, x2, y2, r, d; if (C.pad) { pdi = u2u(C.pad.diameter[16]); if (C.pad.shape[16] == PAD_SHAPE_ROUND || C.pad.shape[16] == PAD_SHAPE_OCTAGON || C.pad.shape[16] == PAD_SHAPE_SQUARE) { sprintf(s, "%s (%d);", padshape[C.pad.shape[16]], pdi); } // if long subst. by round use this code else if (C.pad.shape[16] == PAD_SHAPE_LONG) { // substitute y/xlongoct by round pdi = pdi/2; sprintf(s, "%s (%d);", padshape[C.pad.shape[16]], pdi); } // if offset subst. by round use this code else if (C.pad.shape[16] == PAD_SHAPE_OFFSET) { // substitute offset by round pdi = pdi/2; sprintf(s, "%s (%d);", padshape[C.pad.shape[16]], pdi); } } return s; } void get_roundness(UL_ELEMENT E) { E.package.contacts(C) { if (C.smd) { if (C.smd.roundness < boardroundness) boardroundness = C.smd.roundness; } } return; } //----------------------------------------------------- int padindex(UL_ELEMENT E,UL_CONTACT C) { int i = 0; for (i = 0; t[i]; i++) { if (t[i] == padtype(E,C)) return i+1; } return i; // should not be possible } //----------------------------------------------------- string padstacktype(UL_ELEMENT E, UL_CONTACT C) { int px, d; string s; px = padindex(E,C); d = u2u(C.pad.drill); sprintf(s, "P_%d_%d", d, px); return s; } //----------------------------------------------------- string PAC_padtype(UL_PACKAGE P, UL_CONTACT C) { string s; int pdi, x1, y1, x2, y2, r, d; if (C.pad) { pdi = u2u(C.pad.diameter[16]); if (C.pad.shape[16] == PAD_SHAPE_ROUND || C.pad.shape[16] == PAD_SHAPE_OCTAGON || C.pad.shape[16] == PAD_SHAPE_SQUARE) { sprintf(s, "%s (%d);", padshape[C.pad.shape[16]], pdi); } // if long subst. by round use this code else if (C.pad.shape[16] == PAD_SHAPE_LONG) { // substitute y/xlongoct by round pdi = pdi/2; sprintf(s, "%s (%d);", padshape[C.pad.shape[16]], pdi); } // if offset subst. by round use this code else if (C.pad.shape[16] == PAD_SHAPE_OFFSET) { // substitute offset by round pdi = pdi/2; sprintf(s, "%s (%d);", padshape[C.pad.shape[16]], pdi); } } return s; } //----------------------------------------------------- int PAC_padindex(UL_PACKAGE P,UL_CONTACT C) { int i = 0; for (i = 0; t[i]; i++) { if (t[i] == PAC_padtype(P,C)) return i+1; } return i; // should not be possible } //----------------------------------------------------- string PAC_padstacktype(UL_PACKAGE P, UL_CONTACT C) { int px, d; string s; px = PAC_padindex(P,C); d = u2u(C.pad.drill); sprintf(s, "P_%d_%d", d, px); return s; } //----------------------------------------------------- int padstackindex(UL_PACKAGE P, UL_CONTACT C) { int i = 0; for (i = 0; pst[i]; i++) { if (pst[i] == PAC_padstacktype(P,C)) return i+1; } return i; // should not be possible } //----------------------------------------------------- string viatype(UL_VIA V) { string s; int pdi, x1, y1, x2, y2; pdi = u2u(V.diameter[16]); if (V.shape[16] == VIA_SHAPE_ROUND || V.shape[16] == VIA_SHAPE_OCTAGON) { sprintf(s, "%s (%d);", viashape[V.shape[16]], pdi); } if (V.shape[16] == VIA_SHAPE_SQUARE) { x1 = round(-pdi/2); y1 = round(-pdi/2); x2 = round(pdi/2); y2 = round(pdi/2); sprintf(s, "%s (%d,%d,%d,%d);", viashape[V.shape[16]], x1,y1,x2,y2); } 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 } //----------------------------------------------------- string viastacktype(UL_VIA V) { int px, d; string s; px = viaindex(V); d = u2u(V.drill); sprintf(s, "P_%d_%d", d, px); return s; } //----------------------------------------------------- int viastackindex(UL_VIA V) { int i = 0; for (i = 0; pst[i]; i++) { if (pst[i] == viastacktype(V)) return i+1; } return i; // should not be possible } //----------------------------------------------------- string drawpadpoly(int dx, int dy, int xo, int yo, real angle, int roundness, real elong, int padtype) { string s; real a = angle; if(roundness) { real r1; int l, r; real rad, rad1, x1, x2, y1, y2; real x_1, y_1, x_2, y_2; if (dx <= dy) { r = dx; l = dy; } else { r = dy; l = dx; } r1 = r / 200 * roundness; if (roundness == 100) { // rounded pad if (padtype == PAD_SHAPE_OFFSET) { rad = PI / 180 * a; rad1 = PI / 180 * (a + 180); x1 = 0; y1 = 0; x2 = u2u(cos(rad) * (r*elong/100) ); y2 = u2u(sin(rad) * (r*elong/100) ); } else if (padtype == PAD_SHAPE_LONG) { rad = PI / 180 * a; rad1 = PI / 180 * (a + 180); x1 = u2u(cos(rad) * ((r*elong/100) /2) ); y1 = u2u(sin(rad) * ((r*elong/100) /2) ); x2 = u2u(cos(rad1) * ((r*elong/100) /2) ); y2 = u2u(sin(rad1) * ((r*elong/100) /2) ); } else { // SMD rad = PI / 180 * a; rad1 = PI / 180 * (a + 180); x1 = u2u(cos(rad) * ((l-r) /2) ); y1 = u2u(sin(rad) * ((l-r) /2) ); x2 = u2u(cos(rad1) * ((l-r) /2) ); y2 = u2u(sin(rad1) * ((l-r) /2) ); } sprintf(s, "TRACK (%d(%.0f,%.0f)(%.0f,%.0f))", u2u(r), u2u(xo) + x1, u2u(yo) + y1, u2u(xo) + x2, u2u(yo) + y2 ); } else { // octagon r1 = r * 0.56; sprintf(s, "POLYGON ((%.0f,%.0f)(%.0f,%.0f)\n (%.0f,%.0f)(%.0f,%.0f)\n (%.0f,%.0f)(%.0f,%.0f)\n (%.0f,%.0f)(%.0f,%.0f)\n (%.0f,%.0f))", u2u(xo) + Xneu( u2u(0+ dx /2 ), u2u(0+ (dy-r1) /2 ), 0, 0, a), u2u(yo) + Yneu( u2u(0+ dx /2 ), u2u(0+ (dy-r1) /2 ), 0, 0, a), u2u(xo) + Xneu( u2u(0+ (dx-r1) /2 ), u2u(0+ dy /2 ), 0, 0, a), u2u(yo) + Yneu( u2u(0+ (dx-r1) /2 ), u2u(0+ dy /2 ), 0, 0, a), u2u(xo) + Xneu( u2u(0- (dx-r1) /2 ), u2u(0+ dy /2 ), 0, 0, a), u2u(yo) + Yneu( u2u(0- (dx-r1) /2 ), u2u(0+ dy /2 ), 0, 0, a), u2u(xo) + Xneu( u2u(0- dx /2 ), u2u(0+ (dy-r1) /2 ), 0, 0, a), u2u(yo) + Yneu( u2u(0- dx /2 ), u2u(0+ (dy-r1) /2 ), 0, 0, a), u2u(xo) + Xneu( u2u(0- dx /2 ), u2u(0- (dy-r1) /2 ), 0, 0, a), u2u(yo) + Yneu( u2u(0- dx /2 ), u2u(0- (dy-r1) /2 ), 0, 0, a), u2u(xo) + Xneu( u2u(0- (dx-r1) /2 ), u2u(0- dy /2 ), 0, 0, a), u2u(yo) + Yneu( u2u(0- (dx-r1) /2 ), u2u(0- dy /2 ), 0, 0, a), u2u(xo) + Xneu( u2u(0+ (dx-r1) /2 ), u2u(0- dy /2 ), 0, 0, a), u2u(yo) + Yneu( u2u(0+ (dx-r1) /2 ), u2u(0- dy /2 ), 0, 0, a), u2u(xo) + Xneu( u2u(0+ dx /2 ), u2u(0- (dy-r1) /2 ), 0, 0, a), u2u(yo) + Yneu( u2u(0+ dx /2 ), u2u(0- (dy-r1) /2 ), 0, 0, a), u2u(xo) + Xneu( u2u(0+ dx /2 ), u2u(0+ (dy-r1) /2 ), 0, 0, a), u2u(yo) + Yneu( u2u(0+ dx /2 ), u2u(0+ (dy-r1) /2 ), 0, 0, a) ); } } else { // rectangle sprintf(s, "POLYGON ((%.0f,%.0f)(%.0f,%.0f)(%.0f,%.0f)(%.0f,%.0f)(%.0f,%.0f))", u2u(xo) + Xneu( u2u(0 + dx /2), u2u(0 + dy / 2), 0, 0, a), u2u(yo) + Yneu( u2u(0 + dx /2), u2u(0 + dy / 2), 0, 0, a), u2u(xo) + Xneu( u2u(0 + dx /2), u2u(0 - dy / 2), 0, 0, a), u2u(yo) + Yneu( u2u(0 + dx /2), u2u(0 - dy / 2), 0, 0, a), u2u(xo) + Xneu( u2u(0 - dx /2), u2u(0 - dy / 2), 0, 0, a), u2u(yo) + Yneu( u2u(0 - dx /2), u2u(0 - dy / 2), 0, 0, a), u2u(xo) + Xneu( u2u(0 - dx /2), u2u(0 + dy / 2), 0, 0, a), u2u(yo) + Yneu( u2u(0 - dx /2), u2u(0 + dy / 2), 0, 0, a), u2u(xo) + Xneu( u2u(0 + dx /2), u2u(0 + dy / 2), 0, 0, a), u2u(yo) + Yneu( u2u(0 + dx /2), u2u(0 + dy / 2), 0, 0, a) ); } return s; } //----------------------------------------------------- string drawpad(UL_PACKAGE P, UL_CONTACT C, int l) { string s = "no pad!"; int dx, dy, r, d; if (C.pad) { if (C.pad.shape[l] == PAD_SHAPE_ROUND) { sprintf(s, "ROUND (%d,%d,%d)", u2u(C.pad.diameter[l]), u2u(C.pad.x), u2u(C.pad.y) ); } else if (C.pad.shape[l] == PAD_SHAPE_SQUARE) { s = drawpadpoly(C.pad.diameter[l], C.pad.diameter[l], C.pad.x, C.pad.y, C.pad.angle, 0, 0, 0); } else if (C.pad.shape[l] == PAD_SHAPE_OCTAGON) { d = round(d); s = drawpadpoly(C.pad.diameter[l], C.pad.diameter[l], C.pad.x, C.pad.y, C.pad.angle, 50, C.pad.elongation, PAD_SHAPE_OCTAGON); } else if (C.pad.shape[l] == PAD_SHAPE_LONG) { r = round(d/2); s = drawpadpoly(C.pad.diameter[l]*2, C.pad.diameter[l], C.pad.x, C.pad.y, C.pad.angle, 100, C.pad.elongation, PAD_SHAPE_LONG); } else if (C.pad.shape[l] == PAD_SHAPE_OFFSET) { r = round(d); s = drawpadpoly(C.pad.diameter[l]*2, C.pad.diameter[l], C.pad.x, C.pad.y, C.pad.angle, 100, C.pad.elongation, PAD_SHAPE_OFFSET); } // PAD_SHAPE_ANNULUS // PAD_SHAPE_THERMAL } else { // smd int smd_roundnes = C.smd.roundness; if (smd_roundnes < boardroundness) smd_roundnes = boardroundness; s = drawpadpoly(C.smd.dx, C.smd.dy, C.smd.x, C.smd.y, C.smd.angle, smd_roundnes, 0, 0); } return s; } //--------------------------------------------------- string pin_number(UL_ELEMENT E, string pinname) { int j, pad_is_numeric = 1, padcount; string s = ""; E.package.contacts(CT) { s = CT.name; for (j = 0; s[j]; ++j) { if (!isdigit(s[j])) { pad_is_numeric = 0; } } } if (pad_is_numeric) { return pinname; } else { padcount = 0; E.package.contacts(CT) { padcount++; if (CT.name == pinname) { sprintf(s, "%d", padcount); return s; } } } return s; } //------------------------------------------------------- string PAC_pin_number(UL_PACKAGE P, string pinname) { int j, pad_is_numeric = 1, padcount; string s = ""; P.contacts(CT) { s = CT.name; for (j = 0; s[j]; ++j) { if (!isdigit(s[j])) { pad_is_numeric = 0; } } } if (pad_is_numeric) { return pinname; } else { padcount = 0; P.contacts(CT) { padcount++; if (CT.name == pinname) { sprintf(s, "%d", padcount); return s; } } } return s; } //--------------------------------------------------- int realnet(UL_SIGNAL S) { S.contactrefs(S) return 1; return 0; } //--------------------------------------------------- int net_on_layer(UL_SIGNAL S, int layer) { // 1 if a wire of this net is on the given layer S.wires(W) if (W.layer == layer) return 1; S.polygons(P) if(P.layer == layer) return 1; return 0; } ////////////////////////////////////////////////////// void create_header () { printf (";EAGLE %d.%02d %s %s FATF OUTPUT FILE FABmaster(R) ", EAGLE_VERSION, EAGLE_RELEASE, filename(argv[0]), ULPversion); printf ("%02d.%02d.%02d %02d:%02d:%02d\n\n", t2day(ht),t2month(ht)+1,t2year(ht),t2hour(ht),t2minute(ht),t2second(ht)); printf (":FABMASTER FATF REV11.1;\n\n"); printf (":UNITS = 1/1000 INCH\n"); printf (":NOAUTOROTATE\n"); return; } ////////////////////////////////////////////////////// void board_data(UL_BOARD B) { int t = time(); printf ("\n:BOARD_DATA\n"); printf ("1,JOB(\"%s\",,%02d-%02d-%02d,);\n", jobname,t2day(t),t2month(t),t2year(t)); B.wires(W) { // if board outline as wires in board if (W.layer == LAYER_DIMENSION) { xmin = min(u2u(W.x1), xmin); xmin = min(u2u(W.x2), xmin); ymin = min(u2u(W.y1), ymin); ymin = min(u2u(W.y2), ymin); xmax = max(u2u(W.x1), xmax); xmax = max(u2u(W.x2), xmax); ymax = max(u2u(W.y1), ymax); ymax = max(u2u(W.y2), ymax); if (W.curve) { // process arcs (done with wire segments) x = W.arc.x1; y = W.arc.y1; printf ("2,CONTOUR ("); printf("(%d,%d,0)", u2u(x), u2u(y)); real angle = W.arc.angle1 + delta; while (angle < W.arc.angle2) { i++; if (i==1) { printf(","); } else if (i==2){ printf(");\n2,CONTOUR ("); i = 0; } x = W.arc.xc + W.arc.radius * cos(deg2arc(angle)); y = W.arc.yc + W.arc.radius * sin(deg2arc(angle)); printf("(%d,%d)", u2u(x), u2u(y)); xmin = min(u2u(x), xmin); xmin = min(u2u(x), xmin); ymin = min(u2u(y), ymin); ymin = min(u2u(y), ymin); xmax = max(u2u(x), xmax); xmax = max(u2u(x), xmax); ymax = max(u2u(y), ymax); ymax = max(u2u(y), ymax); angle += delta; } if (!i) { printf("(%d,%d,0));\n", u2u(W.arc.x2), u2u(W.arc.y2)); } else { printf(");\n2,CONTOUR ((%d,%d,0)", u2u(x), u2u(y)); printf(",(%d,%d,0));\n", u2u(W.arc.x2), u2u(W.arc.y2)); } i=0; } else { printf ("2,CONTOUR ("); printf("(%d,%d,0),(%d,%d,0)", u2u(W.x1), u2u(W.y1), u2u(W.x2), u2u(W.y2)); printf(");\n"); } } } B.elements(E) { E.package.wires(W) { if (W.layer == LAYER_DIMENSION) { xmin = min(u2u(W.x1), xmin); xmin = min(u2u(W.x2), xmin); ymin = min(u2u(W.y1), ymin); ymin = min(u2u(W.y2), ymin); xmax = max(u2u(W.x1), xmax); xmax = max(u2u(W.x2), xmax); ymax = max(u2u(W.y1), ymax); ymax = max(u2u(W.y2), ymax); if (W.curve) { // process arcs (done with wire segments) x = W.arc.x1; y = W.arc.y1; printf ("2,CONTOUR ("); printf("(%d,%d,0)", u2u(x), u2u(y)); real angle = W.arc.angle1 + delta; while (angle < W.arc.angle2) { i++; if (i==1) { printf(","); } else if (i==2){ printf(");\n2,CONTOUR ("); i = 0; } x = W.arc.xc + W.arc.radius * cos(deg2arc(angle)); y = W.arc.yc + W.arc.radius * sin(deg2arc(angle)); printf("(%d,%d)", u2u(x), u2u(y)); xmin = min(u2u(x), xmin); xmin = min(u2u(x), xmin); ymin = min(u2u(y), ymin); ymin = min(u2u(y), ymin); xmax = max(u2u(x), xmax); xmax = max(u2u(x), xmax); ymax = max(u2u(y), ymax); ymax = max(u2u(y), ymax); angle += delta; } if (!i) { printf("(%d,%d,0));\n", u2u(W.arc.x2), u2u(W.arc.y2)); } else { printf(");\n2,CONTOUR ((%d,%d,0)", u2u(x), u2u(y)); printf(",(%d,%d,0));\n", u2u(W.arc.x2), u2u(W.arc.y2)); } i=0; } else { printf ("2,CONTOUR ("); printf("(%d,%d,0),(%d,%d,0)", u2u(W.x1), u2u(W.y1), u2u(W.x2), u2u(W.y2)); printf(");\n"); } } } } printf("3,WORK_SPACE (%d,%d,%d,%d);\n", xmin, xmax, ymin, ymax); printf (":EOD\n"); printf ("\n:NOTRACE\n"); return; } ////////////////////////////////////////////////////// void parts(UL_BOARD B) { int i = 1; printf ("\n:PARTS\n"); B.elements(E) { partnumname[i] = E.name; // 2009-12-03 printf("%d,",i++); // PART ID printf("%s,",E.name); // PART NAME (not as in definition!) printf("\"%s\",",E.value); // DEVICE NAME = Value printf("%s,",validname(E.package.name + "__" + E.package.library)); // PACKAGE NAME printf("%d,%d,",u2u(E.x), u2u(E.y)); // X,Y printf("%d,",u2ang(E.angle, E.mirror)); // ROTATION if (E.mirror) // ASSEMBLY SIDE printf("B;"); else printf("T;"); printf("\n"); } cntnumname = i; // 2009-12-03 printf(":EOD\n"); return; } ////////////////////////////////////////////////////// void pad_symbols(UL_BOARD B) { int i, j = 0, new; // j+1 = pad index; t[] contains padtypes printf ("\n:PAD_SYMBOLS\n\n"); B.elements(E) { E.package.contacts(C) { if (C.pad) { new = 1; // padtype not generated yet for (i = 0; t[i]; i++) { if (t[i] == padtype(E,C)) new = 0; // padtype exists } if (new) { t[j] = padtype(E,C); printf("%d,%s\n", j+1, padtype(E,C)); j++; } } } } 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); printf("%d,%s\n", j+1, viatype(V)); j++; } } } printf(":EOD\n"); return; } ////////////////////////////////////////////////////// void layer_names(UL_BOARD B) { int i; string layers[] = { "\"DRILL PAD\",COMMON,0,ELECTRICAL;" // layer 1 ,"\"TOP\",TOP,3,ELECTRICAL;" ,"\"BOTTOM\",BOTTOM,2,ELECTRICAL;" ,"\"ROUTE2\",TRANSPARENT,0,ELECTRICAL;" ,"\"ROUTE3\",TRANSPARENT,0,ELECTRICAL;" ,"\"ROUTE4\",TRANSPARENT,0,ELECTRICAL;" ,"\"ROUTE5\",TRANSPARENT,0,ELECTRICAL;" ,"\"POWER1\",TRANSPARENT,0,ELECTRICAL;" ,"\"DRILLH\",TRANSPARENT,0,DOCUMENTATION;" //layer 9 ,"\"POWER2\",TRANSPARENT,0,DOCUMENTATION;" ,"\"DRILL\",TRANSPARENT,0,DOCUMENTATION;" ,"\"THERMAL_2\",TRANSPARENT,0,DOCUMENTATION;" ,"\"FORMAT\",TRANSPARENT,0,BOARD_CUTOUT;" ,"\"THERMAL_1\",TRANSPARENT,0,DOCUMENTATION;" ,"\"THERMAL\",TRANSPARENT,0,DOCUMENTATION;" ,"\"TPLACE\",TOP,17,ASSEMBLY;" // 16 ,"\"BPLACE\",BOTTOM,16,ASSEMBLY;" ,"\"TNAMES\",TOP,19,DOCUMENTATION;" ,"\"BNAMES\",BOTTOM,18,DOCUMENTATION;" ,"\"TVALUES\",TOP,21,DOCUMENTATION;" ,"\"BVALUES\",BOTTOM,20,DOCUMENTATION;" }; printf("\n:LAYER_NAMES\n"); for (i=0; layers[i]; i++) { printf("%d,%s\n", i+1, layers[i]); } printf(":EOD\n"); printf("\n:LAYER_SETS\n"); //layer sets printf("1,\"ALL\",(1"); for (i=1; layers[i]; i++) { printf(",%d", i+1); } printf(");\n"); printf(":EOD\n"); return; } ////////////////////////////////////////////////////// void pad_stacks(UL_BOARD B) { int new, i, j; printf ("\n:PAD_STACKS\n"); B.elements(E) { E.package.contacts(C) { if (C.pad) { new = 1; // padstacktype not generated yet for (i = 0; pst[i]; i++) { if (pst[i] == padstacktype(E, C)) new = 0; // padstacktype exists } if (new) { pst[j] = padstacktype(E, C); printf("%d,\"%s\",%d,P,((1,%d));\n", j+1, padstacktype(E,C), u2u(C.pad.drill), padindex(E,C) ); j++; } } } } B.signals(S) { S.vias(V) { new = 1; for (i = 0; pst[i]; i++) { if (pst[i] == viastacktype(V)) new = 0; // viastacktype exists } if (new) { pst[j] = viastacktype(V); printf("%d,\"%s\",%d,P,((1,%d));\n", j+1, viastacktype(V), u2u(V.drill), viaindex(V) ); j++; } } } printf(":EOD\n"); return; } ////////////////////////////////////////////////////// void pads(UL_BOARD B) { int i = 0; printf ("\n:PADS\n"); B.signals(S) { if (realnet(S)) { // vias belonging to real net i++; S.vias(V) { printf("%d,%d,((%d,%d));\n", i, viastackindex(V), u2u(V.x), u2u(V.y)); } } else { // other vias S.vias(V) { printf("0,%d,((%d,%d));\n", viastackindex(V), u2u(V.x), u2u(V.y)); } } } printf(":EOD\n"); return; } int searchfont(int tsize, int tratio) { int found = -1; for (int n = 0; n < cntt; n++) { if (sizes[n] == tsize && ratio[n] == tratio) { found = n; break; } } return found; } ////////////////////////////////////////////////////// void fonts(UL_BOARD B) { int n; printf ("\n:FONTS\n"); printf ("1,\"STANDARD\",96,60,72,0;\n"); B.texts(T) { if (searchfont(T.size, T.ratio) < 0) { sizes[cntt] = T.size; ratio[cntt] = T.ratio; cntt++; } } B.elements(E) { E.package.texts(T) { if (searchfont(T.size, T.ratio) < 0) { sizes[cntt] = T.size; ratio[cntt] = T.ratio; cntt++; } } } for (n = 0; n < cntt; n++) { printf("%d,\"FONT_%d\",%d,%.0f,%.0f,%.d;\n", n+2, n+2, u2u(sizes[n]), u2u(sizes[n])*.6, u2u(sizes[n])*.72, u2u(sizes[n]*ratio[n])/100); } printf(":EOD\n"); return; } ////////////////////////////////////////////////////// void packages(UL_BOARD B) { int i = 1, j, k, l, xll,yll, textlayer; real tangle, angle; string dp, jst; printf ("\n:PACKAGES\n"); B.libraries(LBR) { LBR.packages(P) { new = 1; // padstacktype not generated yet for (i = 0; shapename[i]; i++) { if (shapename[i] == validname(P.name + "__" + P.library)) new = 0; // package name exists } if (new) { shapename[sx] = validname(P.name + "__" + P.library); sx++; printf("%d,",i++); // PACKAGE ID printf("\"%s\",",validname(P.name + "__" + P.library)); // PACK.NAME printf(",,,\n"); // xmin etc. left blank j = 0; k = 0; P.contacts(C) { if (k == 0) printf(" (PINS "); // only if contacts present k++; printf("(%s,,%d,%d,", PAC_pin_number(P, C.name), u2u(C.x), u2u(C.y)); // Pin IDs if (C.pad) printf("D)"); // ASSEMBLY SIDE else printf("T)"); j++; if (j > 2) { // max. 3 pins in one line printf("\n "); j = 0; } } if (k != 0) printf(")\n"); // only if contacts present close PINS section j = 0; printf(" ("); // corresponds to ); before next package P.contacts(C) { if (C.pad) { if (j > 0) { printf(" "); } printf("%s,PAD (%d ((%d,%d)))\n", // PAD PAC_pin_number(P, C.name), padstackindex(P,C), u2u(C.x), u2u(C.y)); j++; } } // close PIN-ID,PAD section j = 0; P.contacts(C) { if (C.pad) { dp = drawpad(P, C, 1); printf(" %s,LAYER (%d (\n", PAC_pin_number(P, C.name), fablayer(1)); // top side printf(" %s))\n", dp); dp = drawpad(P, C, 16); printf(" %s,LAYER (%d (\n", PAC_pin_number(P, C.name), fablayer(16)); // bottom side printf(" %s))\n", dp); } else { // smd, always on top layer if (j > 0) printf(" "); if (C.smd.layer == 1) { printf("%s,LAYER (%d (\n", PAC_pin_number(P, C.name), fablayer(1)); printf(" %s))\n", drawpad(P, C, 1)); } else { printf("%s,LAYER (%d (\n", PAC_pin_number(P, C.name), fablayer(16)); printf(" %s))\n", drawpad(P, C, 16)); } } j++; } // close PIN-ID,LAYER section // process circles etc. on top and bottom side P.circles(C) { if (C.layer == 1 || C.layer == 16) { printf("\n 0,LAYER (%d (\n", fablayer(C.layer)); int RminRmax = C.radius - C.width; if (!C.width || RminRmax < 0) { RminRmax = C.width/2; printf(" ROUND (%d,%d,%d)", u2u((C.radius + RminRmax)*2), u2u(C.x), u2u(C.y)); } else { printf(" CIRCLE (%d,%d,%d,%d)", u2u(C.radius) + u2u(C.width)/2, u2u(C.radius) - u2u(C.width)/2, u2u(C.x), u2u(C.y)); } printf("))\n"); } } P.rectangles(W) { if (W.layer == 1 || W.layer == 16) { printf("\n 0,LAYER (%d (\n", fablayer(W.layer)); xll = W.x1; yll = W.y1; int rectcenterx = (W.x1 + W.x2) /2; int rectcentery = (W.y1 + W.y2) /2; int rectx = W.x2 - W.x1; int recty = W.y2 - W.y1; printf(" %s", drawpadpoly(rectx, recty, rectcenterx, rectcentery, W.angle, 0, 0, 0)); printf("))\n"); } } P.texts(T) { if (T.layer == 1 || T.layer == 16) { printf(" 0,LAYER (%d (\n", fablayer(T.layer)); T.wires(W) { printf(" TRACK (%d,(%d,%d),(%d,%d))\n", u2u(W.width), u2u(W.x1), u2u(W.y1), u2u(W.x2), u2u(W.y2)); } /* printf(" TEXT (%d,%d,%d,%s,%.1f,%s,%s)))\n", searchfont(T.size, T.ratio)+2, u2u(T.x), u2u(T.y), jst, T.angle, Mirror, T.value); */ printf("))\n"); } } // end circles etc. on top and bottom P.wires(W) { if (W.layer == 1 || W.layer == 16 || W.layer == 21 || W.layer == 22 || W.layer == 51 || W.layer == 52) { printf(" 0,LAYER (%d (\n", fablayer(W.layer)); // tplace layer if (W.curve) { // process arcs (done with wire segments) printf(" TRACK (%d,(%d,%d),", u2u(W.width), u2u(W.arc.x1), u2u(W.arc.y1)); angle = W.arc.angle1 + delta; while (angle < W.arc.angle2) { printf("\n (%d,%d),", u2u(W.arc.xc + W.arc.radius * cos(deg2arc(angle))), u2u(W.arc.yc + W.arc.radius * sin(deg2arc(angle))) ); angle += delta; } printf("(%d,%d))", u2u(W.arc.x2), u2u(W.arc.y2) ); } else { printf(" TRACK (%d,(%d,%d),", u2u(W.width), u2u(W.x1), u2u(W.y1)); printf("(%d,%d))", u2u(W.x2), u2u(W.y2)); } printf("))\n"); } } P.rectangles(W) { if (W.layer == 21 || W.layer == 22 || W.layer == 51 || W.layer == 52) { printf(" 0,LAYER (%d (\n", fablayer(W.layer)); // tplace layer xll = W.x1; yll = W.y1; int rectcenterx = (W.x1 + W.x2) /2; int rectcentery = (W.y1 + W.y2) /2; int rectx = W.x2 - W.x1; int recty = W.y2 - W.y1; printf("%s", drawpadpoly(rectx, recty, rectcenterx, rectcentery, W.angle, 0, 0, 0)); printf("))\n"); } } P.circles(C) { if (C.layer == 21 || C.layer == 22 || C.layer == 51 || C.layer == 52) { printf(" 0,LAYER (%d (\n", fablayer(C.layer)); // tplace layer int RminRmax = C.radius - C.width; if (!C.width || RminRmax < 0) { RminRmax = C.width/2; printf(" ROUND (%d,%d,%d)\n", u2u((C.radius + RminRmax)*2), u2u(C.x), u2u(C.y)); } else { printf(" CIRCLE (%d,%d,%d,%d)\n", u2u(C.radius) + u2u(C.width)/2, u2u(C.radius) - u2u(C.width)/2, u2u(C.x), u2u(C.y)); } printf("))\n"); } } P.texts(T) { if (T.layer == 1 || T.layer == 16 || T.layer == 21 || T.layer == 22 || T.layer == 51 || T.layer == 52) { printf(" 0,LAYER (%d (\n", fablayer(T.layer)); T.wires(W) { printf(" TRACK (%d,(%d,%d),(%d,%d))\n", u2u(W.width), u2u(W.x1), u2u(W.y1), u2u(W.x2), u2u(W.y2)); } printf("))\n"); } /* if (T.layer == 51 || T.layer == 52) { printf(" 0,LAYER (%d (\n", fablayer(T.layer - 30)); // tplace layer if (!T.mirror) { jst = "BOTTOM_LEFT"; } else { jst = "TOP_RIGHT"; } printf(" TEXT (1,%d,%d,%s,%3.0f, ,%s)\n", u2u(x), u2u(y), jst, T.angle, T.value); } */ } printf(");\n"); } } } printf(":EOD\n"); return; } ////////////////////////////////////////////////////// void layer(UL_BOARD B) { int textlayer; string jst, mir; real tangle, angle; printf ("\n:LAYERS\n"); int i = 0, lay; B.signals(S) { if (realnet(S)) { ++i; for (lay = 1; lay <= 16; lay++) { if (net_on_layer(S, lay) && fablayer(lay) > 0) { printf("%d,LAYER (%d, (\n", i, fablayer(lay)); S.wires(W) { if (lay == W.layer) { if (W.curve) { // process arcs (done with wire segments) x = W.arc.x1; y = W.arc.y1; printf(" TRACK (%d,(%d,%d)", u2u(W.width), u2u(x), u2u(y)); angle = W.arc.angle1 + delta; while (angle < W.arc.angle2) { x = W.arc.xc + W.arc.radius * cos(deg2arc(angle)); y = W.arc.yc + W.arc.radius * sin(deg2arc(angle)); printf(",\n (%d,%d)", u2u(x), u2u(y)); angle += delta; } printf("\n (%d,%d))", u2u(W.arc.x2), u2u(W.arc.y2)); } else { printf(" TRACK (%d,(%d,%d),(%d,%d))\n", u2u(W.width), u2u(W.x1), u2u(W.y1), u2u(W.x2), u2u(W.y2)); } } } S.polygons(P) { // 13.05.2004 polygon if (lay == P.layer) { P.contours(W) { printf(" TRACK (%d,(%d,%d),(%d,%d))\n", u2u(W.width), u2u(W.x1), u2u(W.y1), u2u(W.x2), u2u(W.y2)); } P.fillings(W) { printf(" TRACK (%d,(%d,%d),(%d,%d))\n", u2u(W.width), u2u(W.x1), u2u(W.y1), u2u(W.x2), u2u(W.y2)); } } } printf(" ));\n"); } } } } // process name texts B.elements(E) { if (E.package) { tangle = 0; if (!E.mirror) { textlayer = 25; mir = ""; } else { textlayer = 26; mir = "M"; } jst = "CENTER"; x = E.x; y = E.y; printf("0,LAYER (%d (\n", fablayer(textlayer)); // tnames layer printf(" TEXT (1,%d,%d,%s,0,%s,%s)));\n", u2u(x), u2u(y), jst, mir, E.name); } } B.texts(T) { if (T.layer == 1 || T.layer == 16 || T.layer == 21) { printf(" 0,LAYER (%d (\n", fablayer(T.layer)); T.wires(W) { printf(" TRACK (%d,(%d,%d),(%d,%d))\n", u2u(W.width), u2u(W.x1), u2u(W.y1), u2u(W.x2), u2u(W.y2)); } printf("))\n"); } } printf(":EOD\n"); } // //////////// 2009-12-03 ///////////////// void creat_pad_number_index(UL_BOARD B) { B.elements(E) { int iscontact = 0; E.package.contacts(C) { iscontact = 1; break; } if (!iscontact) { sprintf(areaEname[cntindex], "%s", E.name); // index of element without contacts indexareaEname[cntindex] = 0; cntindex++; } else { int j = 0; E.package.contacts(C) { if (!j) { j++; sprintf(areaEname[cntindex], "%s", E.name); // index to start of pad names in package-pad-list indexareaEname[cntindex] = cntEpad; cntindex++; } // create pad number index list 2009-12-03 sprintf(areaEpadname[cntEpad], "%s~%s", E.name, C.name); areaPadNumber[cntEpad] = strtol(pin_number(E, C.name)); // *** the number of pad in FATF format cntEpad++; j++; } } } return; } //------------------------------------- int getpadnbr(int i, string epname) { for (int n = i; n < cntEpad; n++) { if (areaEpadname[n] == epname) return areaPadNumber[n]; } return 0; } int getpinr(string ename, string pname) { string ep = ename + "~" + pname; for (int i = 1; i < cntindex; i++) { if (areaEname[i] == ename) return getpadnbr(indexareaEname[i], ep); } return 0; } int getelnr(string ename) { for (int i = 1; i < cntindex; i++) { if (areaEname[i] == ename) return i; } return 0; } ////////////////////////////////////////////////////// void nets(UL_BOARD B) { int i = 0, itemcnt, elnr, j; string pin; printf("\n:NETS\n"); B.signals(S) { if (realnet(S)) { printf("%d,\"%s\",S,\n (", ++i, S.name); // NET NR, NET NAME, STYPE itemcnt = 0; S.contactrefs(C) { elnr = getelnr(C.element.name); // Part ID 2009-12-03 sprintf(pin, "%d", getpinr(C.element.name, C.contact.name)); // Pin ID 2009-12-03 //} /* //S.contactrefs(C) { j = 0; B.elements(E) { j++; if (E.name == C.element.name) { elnr = j; // find Part ID pin = pin_number(E, C.contact.name); // find Pin ID if (dlgMessageBox(h + " <~> " + pin, "ok", "esc") != 0) exit(-999); } } */ if (itemcnt) { printf(","); } if (itemcnt > 5) { printf("\n "); itemcnt = 0; } itemcnt++; printf("(%d,%s)", elnr, pin); // PART ID, PIN ID } printf(");\n"); } } printf(":EOD\n"); return; } ////////////////////////////////////////////////////// void create_pcboard_section(UL_BOARD B) { B.elements(E) get_roundness(E); board_data(B); parts(B); nets(B); pad_symbols(B); layer_names(B); pad_stacks(B); pads(B); fonts(B); packages(B); layer(B); return; } ////////////////////////////////////////////////////// if (board) board(B) { jobname = filename(B.name); jobname = strsub(jobname, 0, strlen(jobname) - 4); output(filesetext(B.name, ".fab")) { create_header(); creat_pad_number_index(B); create_pcboard_section(B); /* option to count run time printf (";start %02d.%02d.%02d %02d:%02d:%02d : ", t2day(ht),t2month(ht)+1,t2year(ht),t2hour(ht),t2minute(ht),t2second(ht)); int t = time(); printf (";end %02d.%02d.%02d %02d:%02d:%02d\n", t2day(t),t2month(t)+1,t2year(t),t2hour(t),t2minute(t),t2second(t)); */ } }