#usage "Create library or libraries from schematic/board
\n" "Can be used to make individual changes to components in a project. " "Just load the board or the schematic and the board, use this ULP to " "generate a library or several libraries " "containing the used components, make your changes in the library, and use the " "UPDATE command to introduce the changes to the schematic or board.
" "Version 1.2: Put objects in forbidden layers into trash layer (edit variable trash_layer). " "Replace @ in library and device names with $, and spaces with _.
"
"10.02.2004 Accept spaces in path and file name.
"
"09.06.2004 Replace @ in package, device and symbol names with $, and spaces with _.
"
"22.11.2004 check pin.contact (old eagle versions allow in device pins without contact)
"
" - replace # with _ in Layernames
"
" - correct first flag in package
"
"21.12.2004 strip @x from Device or Library name
"
"21.03.2005 export correct layer [17] of PAD Shape
"
"28.04.2005 browse path corrected
"
" - Change spaces in library and device names to '_'
"
" - Clear data and log if working path changed
"
" - Option: Generate with or without Library-Name if creat 'one' library
"
"03.08.2005 Technologies separated with ' ' if start a Technology with '-'
"
"08.01.2007 Correct Apostroph in Pin/Padnames
"
"See Help for further details
"
"
\n" "This program collects the parts from a schematic or board and stores them back " "into one or several libraries.
\n"
"Attention: Before using this program please make sure no library is open and all layers containing objects "
"are used. If in doubt, execute the command
\n"
" SET USED_LAYERS ALL
\n" "If you use this ULP from a schematic, the respective board MUST be opened, too!
\n" "Creation Mode
\n" "If 'Multiple libraries' is checked, the program generates libraries with their original name. " "Thus you can edit symbols and/or packages in the generated libraries and " "use the UPDATE command to change all of the respective parts in the schematic or board.
\n" "If 'One library' is checked, a single project library with the name of the schematic or board is generated. " "Package/symbol/device names are then prefixed with the names of the original libraries [optional].
\n" "Show scripts and file dialogs
" "If checked, you can edit the scripts and select path/filename for the library " "script and the log file before execution of the library generation script file.
\n" "Save log file
" "If checked, the logfile is saved before execution of the library generation script file.
\n" "Working path
" "Enter the path where the libraries and the log file go to, or use 'Browse' to select the directory.
\n" "Collect data, Create library
"
"Use these buttons in this order to create the project library or libraries. \\n\\\nby %s';\n", filename(project_name), filename(argv[0]));
cmd += h;
return;
}
void CreateHeader(UL_LIBRARY LBR) {
if (project.board) {
project.board(B) {
B.layers(L) {
sprintf(h, "Layer %d %s;\n", L.number, strip_at_num(L.name));
if (L.number > 1 && L.number < 16) cmd += "# "+h;
else cmd += h;
}
}
}
if (project.schematic) {
project.schematic(SCH) {
SCH.layers(L) {
sprintf(h, "Layer %d %s;\n", L.number, strip_at_num(L.name));
cmd += h;
}
}
}
sprintf(h, "Set Wire_bend 2;\nSet Select_factor 0;\nSet Undo_log off;\n"); cmd += h;
sprintf(h, "Grid mic 1;\n"); cmd += h;
sprintf(h, "Display All;\n"); cmd += h;
cmd += "DESCRIPTION "+replacenewline(LBR.description)+";\n";
return;
}
void CreateTrailer(void) {
sprintf(h, "Set Undo_log On;\nSet Select_factor 0.02;\nGrid last;\n"); cmd += h;
return;
}
void PrintValidLayer(int LNr) {
// put anything not allowed in trash_layer
if (mode==in_symbol && (LNr<91 || (LNr>96 && LNr<100))) {
sprintf(h, "Layer trash %d;\n", trash_layer); cmd += h;
LNr = trash_layer;
}
if (mode==in_package && (LNr>90 && LNr<100)) {
LNr = trash_layer;
sprintf(h, "Layer trash %d;\n", trash_layer); cmd += h;
}
sprintf(h, "Layer %d;\n", LNr); cmd += h;
return;
}
void DrawCircle(UL_CIRCLE C) {
PrintValidLayer(C.layer);
sprintf(h, "Circle %f (%f %f) (%f %f);\n",
u2mic(C.width),
u2mic(C.x), u2mic(C.y),
u2mic(C.x + C.radius), u2mic(C.y));
cmd += h;
return;
}
void DrawWire(UL_WIRE W) {
PrintValidLayer(W.layer);
if (W.arc) { // 2008-09-11
sprintf(h, "WIRE %f (%f %f) %+f (%.f %.f);\n",
u2mic(W.width),
u2mic(W.x1), u2mic(W.y1),
W.curve,
u2mic(W.x2), u2mic(W.y2));
cmd += h;
}
else {
sprintf(h, "Wire %f (%f %f) (%f %f);\n",
u2mic(W.width), u2mic(W.x1), u2mic(W.y1), u2mic(W.x2), u2mic(W.y2));
cmd += h;
}
return;
}
void DrawRectangle(UL_RECTANGLE R) {
PrintValidLayer(R.layer);
sprintf(h, "Rect R%.1f (%f %f) (%f %f);\n",
R.angle,
u2mic(R.x1), u2mic(R.y1),
u2mic(R.x2), u2mic(R.y2));
cmd += h;
return;
}
void DrawContact(UL_CONTACT C) {
string ShapeString;
string ShapeFlag;
if (C.pad) {
switch(C.pad.shape[17]) {
case PAD_SHAPE_SQUARE : ShapeString = "Square"; break;
case PAD_SHAPE_ROUND : ShapeString = "Round"; break;
case PAD_SHAPE_OCTAGON : ShapeString = "Octagon"; break;
case PAD_SHAPE_LONG : ShapeString = "Long"; break;
case PAD_SHAPE_OFFSET : ShapeString = "Offset"; break;
}
if (!(C.pad.flags & PAD_FLAG_STOP) ) ShapeFlag = "NOSTOP ";
if (!(C.pad.flags & PAD_FLAG_THERMALS) ) ShapeFlag += "NOTHERMALS ";
if ((C.pad.flags & PAD_FLAG_FIRST) ) ShapeFlag += "FIRST "; // 22.11.2004 support@cadsoft
//
// PAD [diameter] [shape] [orientation] [flags] ['name'] *..
//
sprintf(h, "Change Drill %f;\n", u2mic(C.pad.drill)); cmd += h;
sprintf(h, "Pad %f %s R%.1f %s '%s' (%f %f);\n",
u2mic(C.pad.diameter[17]),
ShapeString,
C.pad.angle,
ShapeFlag,
addApostroph(C.pad.name),
u2mic(C.pad.x), u2mic(C.pad.y));
cmd += h;
}
else if (C.smd) {
if (!(C.smd.flags & PAD_FLAG_STOP) ) ShapeFlag = "NOSTOP ";
if (!(C.smd.flags & SMD_FLAG_THERMALS) ) ShapeFlag += "NOTHERMALS ";
if (!(C.smd.flags & SMD_FLAG_CREAM) ) ShapeFlag += "NOCREAM ";
PrintValidLayer(C.smd.layer);
sprintf(h, "CHANGE Roundness %d;\n", C.smd.roundness); cmd += h;
//
// SMD [x_width y_width] [-roundness] [orientation] [flags] ['name'] *..
//
sprintf(h, "SMD %f %f -%d R%.1f %s '%s' (%f %f);\n",
u2mic(C.smd.dx), u2mic(C.smd.dy),
C.smd.roundness,
C.smd.angle,
ShapeFlag,
addApostroph(C.smd.name),
u2mic(C.smd.x), u2mic(C.smd.y));
cmd += h;
}
return;
}
void DrawText(UL_TEXT T) {
PrintValidLayer(T.layer);
switch(T.font) {
case FONT_VECTOR : sprintf(h, "CHANGE FONT VECTOR;\n");
cmd += h;
break;
case FONT_PROPORTIONAL : sprintf(h, "CHANGE FONT PROPORTIONAL;\n");
cmd += h;
break;
case FONT_FIXED : sprintf(h, "CHANGE FONT FIXED;\n");
cmd += h;
break;
}
string Spin = "";
string Mirror = "";
if (T.spin) Spin = "S";
if (T.mirror) Mirror = "M";
sprintf(h, "Change Size %f;\n", u2mic(T.size));
cmd += h;
sprintf(h, "Change Ratio %d;\n", T.ratio);
cmd += h;
sprintf(h, "Text %s%sR%.1f '%s' (%f %f);\n",
Spin, Mirror, T.angle, T.value, u2mic(T.x), u2mic(T.y)
);
cmd += h;
return;
}
void DrawHole(UL_HOLE H) {
sprintf(h, "Change Drill %f;\n", u2mic(H.drill)); cmd += h;
sprintf(h, "Hole (%f %f);\n", u2mic(H.x), u2mic(H.y)); cmd += h;
return;
}
void DrawPolygon(UL_POLYGON PL) {
PrintValidLayer(PL.layer);
sprintf(h, "Change Isolate %f;\n", u2mic(PL.isolate)); cmd += h;
sprintf(h, "Change Spacing %f;\n", u2mic(PL.spacing)); cmd += h;
if (PL.orphans) {
sprintf(h, "Change Orphans On;\n");
cmd += h;
}
else {
sprintf(h, "Change Orphans Off;\n"); cmd += h;
}
if (PL.thermals) {
sprintf(h, "Change Thermals On;\n"); cmd += h;
}
else {
sprintf(h, "Change Thermals Off;\n"); cmd += h;
}
if (PL.pour == POLYGON_POUR_SOLID) {
sprintf(h, "Change Pour Solid;\n"); cmd += h;
}
else {
sprintf(h, "Change Pour Hatch;\n"); cmd += h;
}
sprintf(h, "Polygon %f ", u2mic(PL.width)); cmd += h;
PL.wires(W) {
sprintf(h, "(%f %f) ", u2mic(W.x1), u2mic(W.y1)); cmd += h; /*start coord.*/
break;
}
PL.wires(W) {
sprintf(h, " %+f (%f %f) ", W.curve, u2mic(W.x2), u2mic(W.y2)); cmd += h;
}
sprintf(h, ";\n"); cmd += h;
return;
}
void DrawPin(UL_PIN P) {
string DIR = "", FUNC = "", LEN = "", VIS = "", ANGLE = "R0";
if (P.angle == 90) (ANGLE = "R90");
if (P.angle == 180) (ANGLE = "R180");
if (P.angle == 270) (ANGLE = "R270");
if (P.function == PIN_FUNCTION_FLAG_NONE) (FUNC = "None");
if (P.function == PIN_FUNCTION_FLAG_DOT) (FUNC = "Dot");
if (P.function == PIN_FUNCTION_FLAG_CLK) (FUNC = "Clk");
if (P.function == (PIN_FUNCTION_FLAG_DOT | PIN_FUNCTION_FLAG_CLK))
(FUNC = "DotClk");
if (P.visible == PIN_VISIBLE_FLAG_OFF) (VIS = "Off");
if (P.visible == PIN_VISIBLE_FLAG_PIN) (VIS = "Pin");
if (P.visible == PIN_VISIBLE_FLAG_PAD) (VIS = "Pad");
if (P.visible == (PIN_VISIBLE_FLAG_PIN | PIN_VISIBLE_FLAG_PAD))
(VIS = "Both");
switch(P.direction) {
case PIN_DIRECTION_NC : DIR = "NC"; break;
case PIN_DIRECTION_IN : DIR = "In"; break;
case PIN_DIRECTION_OUT : DIR = "Out"; break;
case PIN_DIRECTION_IO : DIR = "I/O"; break;
case PIN_DIRECTION_OC : DIR = "OC"; break;
case PIN_DIRECTION_PWR : DIR = "Pwr"; break;
case PIN_DIRECTION_PAS : DIR = "Pas"; break;
case PIN_DIRECTION_HIZ : DIR = "Hiz"; break;
case PIN_DIRECTION_SUP : DIR = "Sup";
}
switch(P.length) {
case PIN_LENGTH_POINT : LEN = "Point"; break;
case PIN_LENGTH_SHORT : LEN = "Short"; break;
case PIN_LENGTH_MIDDLE : LEN = "Middle"; break;
case PIN_LENGTH_LONG : LEN = "Long";
}
sprintf(h, "Pin '%s' %s %s %s %s %s %d (%f %f);\n",
addApostroph(P.name),
DIR, FUNC, LEN, ANGLE, VIS, P.swaplevel, u2mic(P.x), u2mic(P.y));
cmd += h;
return;
}
void DrawSymbol(UL_SYMBOL S) {
mode = in_symbol;
IsPackage = 0;
S.circles(C) DrawCircle(C);
S.rectangles(R) DrawRectangle(R);
S.wires(W) DrawWire(W);
S.pins(P) DrawPin(P);
S.texts(T) DrawText(T);
S.polygons(PL) DrawPolygon(PL);
mode = no_mode;
return;
}
void DrawPackage(UL_PACKAGE P) {
mode = in_package;
IsPackage = 1;
P.circles(C) DrawCircle(C);
P.wires(W) DrawWire(W);
P.rectangles(R) DrawRectangle(R);
P.contacts(C) DrawContact(C);
P.texts(T) DrawText(T);
P.holes(H) DrawHole(H);
P.polygons(PL) DrawPolygon(PL);
mode = no_mode;
return;
}
void checktechno(string tec, string dev, string lib) {
string t[];
int n = strsplit(t, tec, ' ');
if (n > 254) {
string s;
sprintf(s, "
"
"If one of the library files to be created already exists, you will be prompted if "
"the existing file may be deleted."
;
void DisplayHelp(void) {
dlgDialog("Export Project Library - Help") {
dlgHBoxLayout dlgSpacing(400);
dlgHBoxLayout {
dlgVBoxLayout dlgSpacing(300);
dlgTextView(HelpText);
}
dlgHBoxLayout {
dlgStretch(1);
dlgPushButton("-Close") dlgReject();
}
};
return;
}
void testview(void) {
dlgDialog("Test") {
int sel;
dlgListView("Lines", x, sel);
dlgPushButton("+Ok") dlgAccept();
dlgPushButton("-Esc") { dlgReject(); exit(-9); }
};
return;
}
string get_project_path() {
if (board) board(B) return(filedir(B.name));
if (schematic) schematic(B) return(filedir(B.name));
if (library) library(B) return(filedir(B.name));
}
string replacenewline(string nl) {
string a[];
int n = strsplit(a, nl, '\n');
if (n > 0) {
nl = "";
for (int x = 0; x < n - 1; x++) {
nl += a[x] + "\\n";
}
nl += a[x];
}
return "'" + nl + "'";
}
string addApostroph(string s) {
int len = strlen(s);
int pos = strrchr(s, '\'');
string l;
if (pos >= 0) {
l = strsub(s, 0, pos) + "'" + strsub(s, pos, len-pos);
s = l;
}
return s;
}
// *** characters '#@ ' not allowed in LBR, DEV, SYM or PAC-Name ***
string change_at(string s) { // replace '@' -> '$' | 'space' -> '_' | '#' -> '_'
int i;
for (i=0; i
This program can only work in the schematic or board editor.");
exit(1);
}
else {
if (board) board(B) EditName = filename(B.name); // name of loaded board/schematic w/o path
if (schematic) schematic(S) EditName = filename(S.name);
}
PureScriptName = filesetext(EditName, ".scr"); // name of generated script w/o path
PureLogName = filesetext(EditName, ".log"); // name of generated log msgs w/o path
WorkPath = get_project_path();
Status = "Version " + Version;
int Result = dlgDialog("Create Project Library") {
string globList[];
int globListIndex = -1;
int globCnt = 0;
dlgHBoxLayout {
dlgStretch(1);
dlgSpacing(500);
dlgStretch(1);
}
dlgHBoxLayout {
dlgVBoxLayout {
dlgGroup("Creation Mode") {
dlgRadioButton("&Multiple libraries", onelib);
dlgRadioButton("&One library", onelib);
dlgHBoxLayout {
dlgSpacing(16);
dlgCheckBox("&Generate LBR-Name_/PAC/SYM/DEV", generate_lbrname);
}
dlgHBoxLayout {
dlgSpacing(34);
dlgLabel("if One library selected");
}
}
dlgGroup("User Interface") {
dlgCheckBox("Show scripts and file dialogs", show_script);
dlgCheckBox("Save log file", save_log);
}
dlgStretch(1);
}
dlgVBoxLayout {
dlgLabel("Log file");
dlgTextView(logf);
}
}
dlgHBoxLayout {
dlgSpacing(60);
dlgLabel("&Working path:");
dlgStringEdit(WorkPath);
dlgPushButton("Bro&wse") {
if (cmd) {
cmd = "";
logf = "";
}
h = WorkPath;
WorkPath = dlgDirectory("Select a directory", WorkPath);
if (WorkPath == "") WorkPath = h;
else WorkPath += "/"; // 29.03.2005 support@cadsoft.de
}
}
dlgSpacing(10);
dlgHBoxLayout {
dlgLabel(Status, 1);
dlgStretch(1);
dlgPushButton("+&Collect data") { logf = "Project Library Creation Log File "+t2string(time())+"\n"
+EAGLE_SIGNATURE+"\nCreated from: "+EditName+"\n\n";
if (onelib) { cmd = ""; make_one_lbr(); }
else { cmd = ""; make_lbr(); }
show_save_script_file(cmd);
Status = "Collect finish";
dlgRedisplay();
if (save_log) show_save_log_file(logf);
}
dlgPushButton("Create &library") { if (cmd == "") dlgMessageBox("Use 'Collect data' first!","&OK");
else exit("SCRIPT '"+ScriptName+"';\n");
}
dlgPushButton("-&Quit") dlgReject();
dlgSpacing(23);
dlgPushButton("&Help") DisplayHelp();
}
};