#usage "FastPlacer"
"
"
"FastPlacer assists you in good placing of the components before routing or autorouting. "
"It is especially useful when you are designing multilayer boards where GND and supply nets are typically "
"laid out in internal layers. But designs using double sided board with one side covered with groundplane "
"are equally good candidates for FastPlacer. "
"FastPlacer runs in board editor mode, not in schematic. It is a pure graphic design tool. "
"
"
"How you use FastPlacer:"
"
"
"You use FastPlacer after having set up your schematic, and before beginning to design the board. "
"Call it by typing 'RUN FastPlacer' at the command line; the ULP "
"will then make the following 3 function key assignments for you because they are necessary for speedy working."
"
"
" ASSIGN F12 'RATSNEST; RUN FastPlacer; MOVE'"
"
"
" ASSIGN S+F12 'RUN FastPlacer end'"
"
"
" ASSIGN C+F12 'RUN FastPlacer toggle'"
"
"
"It's recommended to issue the RATSNEST command before each run of FastPlacer; the 1st of the above assignments "
"does this automatically. Equally, after FastPlacer, a MOVE command is appended automatically, to allow you "
"to immediately go ahead moving more components after updating the display with F12. The version with the argument "
"\"end\" is for terminating the placement session and cleaning up; the version with \"toggle\" is for having "
"a look at the original situation in the layer 19 'unrouted'."
"
"
"In your schematic, leave all important signal nets in the class 0 (\"default\"), all others (like "
"power supply and GND nets) you place in other classes (define a class 1 (\"Power nets\"), e.g. for this). "
"Then go to the Board mode (or create the board). Usually it displays a distracting huge mess "
"of yellow air wires running all over the place. Run FastPlacer and you'll be amazed to see the "
"picture cleared up, leaving only the essential signal nets you have allowed to remain in the class 0 before."
"
"
"Placing the components goes as usual, with the exception that the air wires don't follow the "
"components immediately. Instead you run FastPlacer (hit F12) whenever you feel having made a progress "
"in placing components. While placing, just disregard all the GND and supply nets "
"although it makes good sense to keep them in mind. For example it is wise to line up all OpAmps in rows "
"with all in the same orientation; This radically eases power supply routing later on. "
"
"
"After placing, run FastPlacer once again but this time with the argument \"end\" (hit SHIFT+F12). This cleans up "
"and prepares everything for subsequent routing (manual or auto). "
"
"
"If, during a placement session, you like to see all of the original air wires, just hit CONTROL+F12. "
"This toggles back and forth between a display with the original layer 19 'unrouted' and with the new "
"layer '__SignalWires'. "
"
"
"What FastPlacer does:"
"
"
"It simply hides the layer 19 'unrouted' and presents instead a newly created layer where it "
"copies only the air wires belonging to the class 0 'default' signal nets. "
"The new layer, once created, will be reused on further runs of this ULP. "
"This layer can be emptied and deleted from the layer stack at any time without further consequences, "
"either by hand, or simply by hitting SHIFT+F12. "
"This ULP does not affect your schematic in any way nor does it interfere with EAGLE's "
"routing or autorouting functionality. "
"
"
"What FastPlacer cannot do:"
"
"
"FastPlacer is a rather crude substitute for a quite simple thing: one should be able to select whether "
"air wires belonging to nets of certain classes should be displayed or not. Excluding GND and supply nets "
"from the air wire display greatly helps the designer focus on his main task of laying out his signal "
"paths in an orderly and straightforward manner. FastPlacer lets you make these exclusions, but it cannot "
"give you the feel of rubberbands always following the components like in the original air wire display. "
"
"
"THIS PROGRAM IS PROVIDED AS IS AND WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED"
"
"
"Author: Luc Eberhard eol.eberhard@bluewin.ch / October 2006"
// THIS PROGRAM IS PROVIDED AS IS AND WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED
// Declarations
int x1[], y1[], x2[], y2[]; // arrays for buffering positions of all signal wire segments
int i,j; // counting variables
int iBoxResult;
int iFast;
int iLNSignalWires;
int iLastNumber;
string sCommand;
string sInstruction;
string sMessage;
// main
if (board) board(B) {
// Set grid units to mm
sprintf(sInstruction, "GRID MM;\nSET WIRE_BEND 2;\n");
sCommand = sInstruction;
// Look for a preexisting special layer named "__SignalWires"
// If the layer is found, determine whether it is currently visible or not.
iFast = 2;
iLNSignalWires = 0;
B.layers(L)
{ if (L.name == "__SignalWires")
{ iLNSignalWires = L.number;
iFast = L.visible;
}
}
// If the version with 'toggle' is called and the special layer exists, then toggle its visibility
// with the one of the layer 19 'unrouted'.
if ((argc == 2) && (argv[1] == "toggle"))
{ if (iFast == 1) sprintf(sInstruction,"DISPLAY UNROUTED -__SignalWires;\n");
if (iFast == 0) sprintf(sInstruction,"DISPLAY -UNROUTED __SignalWires;\n");
if (iFast < 2) sCommand += sInstruction;
sprintf(sInstruction, "GRID LAST;\n");
sCommand += sInstruction;
exit (sCommand);
}
// If no special layer is found, we are running the first time and look for a free layer position
// (something above LAYER_USER (100)) and create the layer from scratch. Color is to be light magenta
// line style solid.
// If the layer already exists, we clean it up (delete all wire segments) to prepare it for copying
if (!iLNSignalWires)
{ if ((argc == 2) && (argv[1] == "end"))
{ sprintf(sInstruction, "GRID LAST;\n");
sCommand += sInstruction;
exit ("");
}
iLastNumber = LAYER_USER;
B.layers(L)
{ if (L.number > (iLastNumber+1))
{ if (!iLNSignalWires) iLNSignalWires = iLastNumber+1;
iLastNumber=L.number;
}
}
sprintf (sMessage,"You started the FastPlacer ULP the first time:\n\
A new layer called \"__SignalWires\" with the number %d will be created now. OK?\n\
If you say NO here, the ULP terminates without further action.\0",iLNSignalWires);
if (dlgMessageBox(sMessage, "&Yes", "&No") == 1)
{ sprintf(sInstruction, "GRID LAST;\n");
sCommand += sInstruction;
exit ("");
}
sprintf (sInstruction, "LAYER %d __SignalWires;\n",iLNSignalWires);
sCommand += sInstruction;
sprintf (sInstruction, "SET COLOR_LAYER %d 13;\n",iLNSignalWires);
sCommand += sInstruction;
sprintf (sInstruction, "SET FILL_LAYER %d 1;\n",iLNSignalWires);
sCommand += sInstruction;
sprintf (sInstruction, "ASSIGN F12 'RATSNEST; RUN FastPlacer; MOVE';\n");
sCommand += sInstruction;
sprintf (sInstruction, "ASSIGN S+F12 'RUN FastPlacer end';\n");
sCommand += sInstruction;
sprintf (sInstruction, "ASSIGN C+F12 'RUN FastPlacer toggle';\n");
sCommand += sInstruction;
} else
{ sprintf(sInstruction, "DISPLAY NONE __SignalWires;\n");
sCommand += sInstruction;
B.wires(W)
{ if (W.layer == iLNSignalWires)
{ sprintf(sInstruction, "DELETE (%.4f %.4f);\n",u2mm(W.x1+W.x2)/2, u2mm(W.y1+W.y2)/2);
sCommand += sInstruction;
}
}
}
// At this point we have our special layer named "__SignalWires" cleaned up.
// If the ULP was called with the argument "end" this signifies the user wants to get rid
// of this layer so we remove it and terminate the ULP. The remaining layers are shown so as to
// prepare for routing by hand or by auto router.
if ((argc == 2) && (argv[1] == "end"))
{ sprintf(sInstruction,"LAYER -%d;\n",iLNSignalWires);
sCommand += sInstruction;
sprintf(sInstruction, "DISPLAY TOP BOTTOM PADS VIAS TPLACE BPLACE TNAMES BNAMES DIMENSION -TVALUES -BVALUES UNROUTED;\n");
sCommand += sInstruction;
sprintf(sInstruction, "GRID LAST;\n");
sCommand += sInstruction;
exit(sCommand);
}
// The user has chosen to go ahead: so we copy all class 0 (default) air wires from the currently invisible
// layer 19 (unrouted) to the layer "__SignalWires". This will reproduce the subset of those air wires the
// user wants to see for effective placement of components. All other cluttering stuff is left aside.
j=1;
B.signals(S)
{ if (S.class.name == "default")
{ S.wires(W)
{ if (W.layer == 19)
{ x1[j] = W.x1; // get endpoint coordinates of all wire segments out there
y1[j] = W.y1; // but only of those which belong to class 0
x2[j] = W.x2;
y2[j] = W.y2;
++j;
}
}
}
} // we come up here with a subset of j wire segments; now start drawing
sprintf(sInstruction, "CHANGE LAYER %d;\n",iLNSignalWires);
sCommand += sInstruction;
for (i = 1; i < j; ++i)
{ sprintf(sInstruction, "WIRE %.4f (%.4f %.4f) (%.4f %.4f);\n", u2mm(20),
u2mm(x1[i]), u2mm(y1[i]), u2mm(x2[i]), u2mm(y2[i]) );
sCommand += sInstruction;
}
// Set the right selection of layers to visible for further placement of components
sprintf(sInstruction, "DISPLAY TOP BOTTOM PADS VIAS TPLACE BPLACE DIMENSION TNAMES BNAMES -TVALUES -BVALUES -UNROUTED -TDOCU -BDOCU __SignalWires;\n");
sCommand += sInstruction;
// Reset the grid to the units it had before
sprintf(sInstruction, "GRID LAST;\n");
sCommand += sInstruction;
// Tranfer control back to EAGLE with the string of instructions built up so far
exit(sCommand);
}
else dlgMessageBox("start this ULP in a Board", "OK");