|
|
#usage "<b>Generate EAGLE Output in Fabmaster Format FATF REV 11.1</b><p>\n"
|
|
|
"See program text for more information<p>"
|
|
|
"ULP Rev. 1.42<br>"
|
|
|
"<author>Author: support@cadsoft.de</author>"
|
|
|
|
|
|
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<39> */
|
|
|
WinkelNeu = (Xalt - Xorigin + 90) + UserWinkel;
|
|
|
real rad = PI / 180 * WinkelNeu;
|
|
|
return (RADIUS * cos(rad));
|
|
|
}
|
|
|
if ((Xalt == Xorigin) && (Yalt < Yorigin)) { /* 270<37> */
|
|
|
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<39> */
|
|
|
WinkelNeu = (Xalt - Xorigin + 90) + UserWinkel;
|
|
|
real rad = PI / 180 * WinkelNeu;
|
|
|
return (RADIUS * sin(rad));
|
|
|
}
|
|
|
if ((Xalt == Xorigin) && (Yalt < Yorigin)) { /* 270<37> */
|
|
|
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));
|
|
|
*/
|
|
|
}
|
|
|
}
|