#usage "Renumber the parts of a schematic

" "This version renumbers only devices with packages (no supply) " "sorted by sheets and coordinates (vertical/descending, horizontal/ascending" "and various percent combined vertical+horizontal).
" "Optional: The starting point for the numeration of parts on the first sheet " "defines an offset value for the following pages.
" "Example:
" " - 0 = R1 ... Rn
" " - 100 sheet 1: R101..R199 sheet 2: R201..R299 ...
" " - 500 sheet 1: R501..R999 sheet 2: R1001..R1499 ...
" " - 1000 sheet 1: R1001..R1999 sheet 2: R2001..R2999 ...
" "

" "Author: support@cadsoft.de" // THIS PROGRAM IS PROVIDED AS IS AND WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED string Version = "ULP Version 4.5.0"; // 2006.08.23 alf@cadsoft.de // correct counter if crossing page by same prefix // 2008.01.30 alf@cadsoft.de // renumber only the current sheet by start sheet-number * numerical_order // added X+Y combined emphasis 6.5.2014 Ing. Miroslav Kovar @ soft string Info = "ATTENTION

" + "Please verify that the corresponding layout file (if already existing) " + "has been loaded with the schematic file.

" + "Otherwise back-/forward-annotation will not work afterwards."; string Infoplus = " You can change the following sorting parameters:

" + " descx = 0 (X ascending [left >> right])
" + " descx = 1 (X descending [right >> left])
" + " descy = 0 (Y ascending [bottom >> top])
" + " descy = 1 (Y descending [top >> bottom])
"; int descy = 1; // set to 0 sorting ascending int descx = 0; // set to 1 sorting descending int numerical_order = 0; // sort from sheet 1, or sort by start counter for sheet int emphases = 0; // weighting of emphases first X second Y or first Y second X int actual_sheet = 0; // 2008.01.30 int only_actual_sheet = 0; // 2008.01.30 string sheet_info = ""; numeric string OldNames[], NewNames[], Prefix[]; int x[], y[], i[], sh[]; int nrNames = 0; numeric string SymNames[]; // Device-Name of Symbol int symsh[]; int sx[], sy[]; int Snr = 0; int Dnr = 0; string error = ""; string SymPrefix[]; string DevPrefix[]; string DevName[]; string SymDevName[]; string NoPrefixRenumber = "TP"; // Prefix do not renumber Testpoints int ckx[], cky[], cksh[]; string ckname[]; string cmd; string c; real Grid = 100; // in 100 Mil string lbr[], dev[], sym[]; int GetNumberIndex(string Name) { // Returns the index of the first digit of the numeric part of Name // -1 indicates there is no numeric part in Name int l = strlen(Name) - 1; for (int i = l; i >= 0; --i) { if (!isdigit(Name[i])) return i < l ? i + 1 : -1; } return 0; } string prefix(string name) // Prefix of Device { int num = GetNumberIndex(name); if (num < 1) return name; else { string pfx = name; pfx[num] = 0; return pfx; } } void DescendingY(void) { for (int ny = 0; ny < nrNames ; ny++) { y[ny] = 0 - y[ny]; } } void DescendingX(void) { for (int nx = 0; nx < nrNames ; nx++) { x[nx] = 0 - x[nx]; } } void SortElements(void) { // Sorts the elements according to their location, first by ascending // x coordinates, then by ascending y coordinates. // If you prefer a different kind of sorting, you can implement this here. // As a result, the integer array i[] must contain the new sequence // in which to renumber the elements. // 2008-07-24 alf, weighting of emphases first X second Y or first Y second X // begin - combined emphasis 6.5.2014 Ing. Miroslav Kovar @ soft int smx[], smy[], s[]; schematic(S) { S.sheets(SH) { smx[SH.number] = SH.area.x2 - SH.area.x1; smy[SH.number] = SH.area.y2 - SH.area.y1; } } for (int n = 0; n < nrNames; n++) { int xx, yy, ss; xx = x[n]; if (descx) xx = - xx; yy = y[n]; if (descy) yy = - yy; switch (emphases) { case 0 : ss = xx * smy[sh[n]] + yy; break; case 1 : ss = yy * smx[sh[n]] + xx; break; case 2 : ss = (xx << 4) + yy; break; case 3 : ss = (yy << 4) + xx; break; case 4 : ss = (xx << 3) + yy; break; case 5 : ss = (yy << 3) + xx; break; case 6 : ss = (xx << 2) + yy; break; case 7 : ss = (yy << 2) + xx; break; case 8 : ss = (xx << 1) + yy; break; case 9 : ss = (yy << 1) + xx; break; case 10 : ss = (xx << 2) + 3 * yy; break; case 11 : ss = (yy << 2) + 3 * xx; break; case 12 : ss = xx + yy; break; } s[n] = ss; } if(!numerical_order) sort(nrNames, i, NewNames, sh, s); else sort(nrNames, i, sh, NewNames, s); // end - combined emphasis 6.5.2014 Ing. Miroslav Kovar @ soft /* if (descy) DescendingY(); if (descx) DescendingX(); if(!numerical_order) { if (!emphases) sort(nrNames, i, NewNames, sh, x, y); else sort(nrNames, i, NewNames, sh, y, x); } else { if (!emphases) sort(nrNames, i, sh, NewNames, x, y); if (!emphases) sort(nrNames, i, sh, NewNames, y, x); } if (descy) DescendingY(); if (descx) DescendingX(); */ return; } void CheckSameOrigin(int chk) { // eagle can not rename an element // if another element is on the same coordinate int index[]; string checklist, h; sort(chk, index, cksh, ckx, cky); for (int n = 0; n < nrNames; n++) { if(ckx[index[n]] == ckx[index[n+1]] && cky[index[n]] == cky[index[n+1]] && cksh[index[n]] == cksh[index[n+1]]) { sprintf(h, "%s & %s on same coordinate (%d %d) mil in sheet %d\n", ckname[index[n]], ckname[index[n+1]], ckx[index[n]], cky[index[n]], cksh[index[n]]); checklist += h; } } if (checklist) { dlgDialog("Check coordinates") { dlgLabel("Eagle can not rename elements that are placed at the same position!"); dlgHBoxLayout { dlgSpacing(300); } dlgTextView(checklist); dlgHBoxLayout { dlgPushButton("Break") dlgAccept(); dlgStretch(1); } }; exit(0); } return; } void GenerateNames(void) { string memprefix = ""; int mem_sh = 0; if(!numerical_order) { // Generates new numeric parts to the element names in NewNames int k; for (int n = 0; n <= nrNames - 1; ++n) { if (memprefix != NewNames[i[n]]) { memprefix = NewNames[i[n]]; k = 0; } sprintf(NewNames[i[n]], "%s%d", NewNames[i[n]], ++k); } } else { // renumber sheets by 100.. 200.. 300.. string h; int newdevnr; for(int n = 0; n < nrNames ; ++n) { if (memprefix != NewNames[i[n]]) { memprefix = NewNames[i[n]]; newdevnr = numerical_order * sh[i[n]] +1; } if (mem_sh != sh[i[n]]) { // a new Sheet is starting by old prefix *** 2006.08.23 alf@cadsoft.de mem_sh = sh[i[n]]; newdevnr = numerical_order * sh[i[n]] +1; } sprintf(NewNames[i[n]], "%s%d", NewNames[i[n]], newdevnr); newdevnr++; if (newdevnr-(sh[i[n]]*numerical_order) >= numerical_order) { sprintf(h, "More parts with prefix '%s' than starting point %d on sheet %d
Start the ulp with numerical order >= %d
", memprefix, numerical_order, sh[i[n]], numerical_order*10); dlgMessageBox(h, "Break"); exit(0); } } } return; } void Rename(int x, int y, string New) { // Generates the EAGLE command necessary to change element name Old to New sprintf(c, "Name '%s' (%d %d);\n", New, x, y); cmd += c; return; } void GenerateScript(void) { // Generates an EAGLE script file that does the whole renumbering. // The tricky part here is that we cannot rename an element to a name // that already exists in the schematic (which, e.g. might be necessary if // we had to swap the names of two elements). Therefore we have to // use a ScratchName wherever this is necessary. // If there is nothing to do, the resulting script file will be empty. string ScratchName; int sch = 0; int n; for ( n = 0; n < nrNames; ++n) { if (sh[i[n]] != sch) { sch = sh[i[n]]; // *** change sheet sprintf(c, "Edit .s%d;\n", sch); cmd += c; } sprintf( ScratchName, "$%d_%d_$", sch, n); Rename(x[i[n]],y[i[n]], ScratchName); } for ( n = 0; n < nrNames; ++n) { if (sh[i[n]] != sch) { sch = sh[i[n]]; // *** change sheet sprintf(c, "Edit .s%d;\n", sch); cmd += c; } Rename(x[i[n]],y[i[n]], NewNames[i[n]]); } return; } // *** check collision before rename *** string CheckNames(void) { string new_name = ";"; string h; for (int Dn = 0; Dn < Dnr; Dn++ ) { for (int Sn = 0; Sn < Snr; Sn++) { if (DevPrefix[Dn] == SymPrefix[Sn]) { sprintf(h, "# Do not use Prefix %s on Device with Package (%s) and Device without Package (%s)\n", SymPrefix[Sn], DevName[Dn], SymDevName[Sn]); error += h; break; } } } for (int n = 0; n < nrNames - 1; ++n) { // make a long string new_name += NewNames[n] + ";"; } for (int xx = 0; xx < Snr - 1; xx++) { string sd = SymNames[xx]; if(sd[0] == '$') { // if first character is a $ on Symbolname error += "# Do not use $ character at first position in device names\n"; sprintf(h, "# RENAME %s at (%.2f %.2f) - sheet %d before running this ULP again' (%.2f %.2f)\n", SymNames[xx], sx[xx] / 1000.0, sy[xx] / 1000.0, symsh[xx], sx[xx] / 1000.0, sy[xx] / 1000.0); error += h; } int s; int pos = strrstr(new_name, ";" + SymNames[xx] + ";"); if (pos > 0 ) { for (s = 0; s < nrNames - 1; s++) { if(NewNames[s] == SymNames[xx]) { break; } } error += "# Collision of symbol name and device name (eg. Frames, Supply ...)\n"; sprintf(h, "# Rename PREFIX of Device %s at (%.2f %.2f) - sheet %d before renaming %s at (%.2f %.2f) - sheet %d';\n", SymNames[xx], sx[xx] / 1000.0, sy[xx] / 1000.0, symsh[xx], OldNames[s], x[s] / 1000.0, y[s] / 1000.0, sh[s] ); error += h; } } return error; } void setgridmil (void) { sprintf(c, "GRID MIL 100 OFF;\n"); cmd += c; // ## only display layer 94 (symbol) if placed a text // ## at symbol origin. 15.06.2004 alf@cadsoft.de sprintf(c, "DISPLAY NONE 94 -95 -96;\n"); cmd += c; return; } void visible(UL_SCHEMATIC S) { sprintf(c, "DISP NONE "); cmd += c; S.layers(L) { if (L.visible) { sprintf(c, "%d ", L.number); cmd += c; } } cmd += ";\n"; return; } void menue(void) { int Result = dlgDialog("Renumber Schematic") { dlgLabel("" + Info + ""); dlgHBoxLayout { dlgGroup("Sort X") { dlgRadioButton("&Ascending", descx); dlgRadioButton("&Descending", descx); } dlgGroup("Sort Y") { dlgRadioButton("A&scending", descy); dlgRadioButton("D&escending", descy); } dlgGroup("Weighting of emphases") { dlgRadioButton("X-direction", emphases); dlgRadioButton("Y-direction", emphases); dlgRadioButton("X + 6% Y-direction", emphases); dlgRadioButton("Y + 6% X-direction", emphases); dlgRadioButton("X + 12% Y-direction", emphases); dlgRadioButton("Y + 12% X-direction", emphases); dlgRadioButton("X + 25% Y-direction", emphases); dlgRadioButton("Y + 25% X-direction", emphases); dlgRadioButton("X + 50% Y-direction", emphases); dlgRadioButton("Y + 50% X-direction", emphases); dlgRadioButton("X + 75% Y-direction", emphases); dlgRadioButton("Y + 75% X-direction", emphases); dlgRadioButton("X + Y-direction", emphases); } dlgStretch(1); } dlgHBoxLayout { dlgLabel("Do not renumber parts with &Prefix "); dlgStringEdit(NoPrefixRenumber); dlgStretch(1); } dlgHBoxLayout { dlgVBoxLayout dlgSpacing(180); dlgGroup("Sheet") { dlgLabel("Start numbering for sheet at:"); dlgLabel(" - 0 numeration R1...Rn"); dlgLabel(" - 100 sheet 1: R101..R199, sheet 2: R201..R299, ..."); dlgLabel(" - 1000 sheet 1: R1001..R1999, sheet 2: R2001..R2999, ..."); dlgSpacing(10); dlgHBoxLayout { dlgLabel("&Numerical order "); dlgIntEdit(numerical_order, 0, 10000); dlgStretch(1); } dlgVBoxLayout dlgSpacing(10); dlgCheckBox("Sort in numerical order on the ¤t sheet only", only_actual_sheet) { if (only_actual_sheet) { if (numerical_order) { sprintf(sheet_info, "The starting number of current sheet is %d", actual_sheet * numerical_order); } else { sprintf(sheet_info, "Please check the numerical order!"); } } else { if (!numerical_order) sprintf(sheet_info, "The starting number is 1"); else sprintf(sheet_info, "The starting number on sheet is X * %d", numerical_order); } } dlgVBoxLayout dlgSpacing(10); dlgLabel(sheet_info, 1); dlgStretch(1); } } dlgHBoxLayout { dlgPushButton("+&OK") { if (only_actual_sheet && !numerical_order) { sprintf(sheet_info, "Please check the numerical order!"); dlgMessageBox(sheet_info, "OK"); } else dlgAccept(); } dlgSpacing(15); dlgPushButton("-Cancel") dlgReject(); dlgSpacing(15); dlgLabel(Version); dlgStretch(1); } }; if (!Result) exit (0); return ; } if (schematic) { if (sheet) { sheet(S) actual_sheet = S.number; sprintf(sheet_info, "The current sheet is %d", actual_sheet); } schematic(S) { menue(); int l = 1; int chk; S.sheets(SH) { if (only_actual_sheet) { ; // do not change the actual sheet number } else { actual_sheet = SH.number; // set the numer to actuel sheet number } if (actual_sheet == SH.number) { // 2008.01.30 SH.parts(P) { int n = GetNumberIndex(P.name); if (n > 0) { if (P.device.package) { // **** only Devices with Packages // **** without Supply symbol Frames ect... // **** DO NOT RENUMBER Elements with this PREFIX if (prefix(P.name) == NoPrefixRenumber); else { DevPrefix[Dnr] = prefix(P.name); DevName[Dnr] = P.name; ++Dnr; P.instances(I) { int found = -1; for (int fn = 0; fn < nrNames; fn++) { if (OldNames[fn] == P.name) { found = fn; break; } } if (found < 0) { x[nrNames] = u2mil(I.x); // cannot use E.x/y directly because of y[nrNames] = u2mil(I.y); // sort() problem with integers > 32767 OldNames[nrNames] = P.name; // in version 3.50 NewNames[nrNames] = strsub(P.name, 0, n); sh[nrNames] = I.sheet; Prefix[nrNames] = prefix(P.name); ++nrNames; } else { if (sh[fn] == I.sheet) { if ( u2mil(I.x) < x[fn] || u2mil(I.y) > y[fn] ) { // tausche wenn x kleiner oder y groesser x[fn] > u2mil(I.x); y[fn] > u2mil(I.y); } } } } } } // Only Symbol (Supply, Port, Frame...) else { // *** check PartName on Symbols Supply, Port, Frame ... *** SymPrefix[Snr] = prefix(P.name); SymDevName[Snr] = P.name; P.instances(I) { SymNames[Snr] = P.name; // Device-Name of Symbol sx[Snr] = u2mil(I.x); // cannot use E.x/y directly because of sy[Snr] = u2mil(I.y); // sort() problem with integers > 32767 symsh[Snr] = I.sheet; ++Snr; break; } } } P.instances(I) { ckx[chk] = u2mil(I.x); // cannot use E.x/y directly because of cky[chk] = u2mil(I.y); // sort() problem with integers > 32767 ckname[chk] = I.name; cksh[chk] = I.sheet; chk++; } } } // 2008.01.30 } CheckSameOrigin(chk); SortElements(); GenerateNames(); setgridmil (); GenerateScript(); if (CheckNames()) { int select; dlgDialog("Symbol ref Device Names") { dlgVBoxLayout { dlgLabel("Warnings for renumber!"); dlgTextView(error); } dlgHBoxLayout { dlgSpacing(450); } dlgHBoxLayout { dlgPushButton("+&OK") dlgAccept(); dlgStretch(1); } }; exit (-1); } sprintf(c, "GRID INCH 0.1;\n"); cmd += c; sprintf(c, "EDIT .S%d;\n", actual_sheet); cmd += c; visible(S); string fname = filesetext(S.name, "~renumsch.scr"); output(fname, "wtD") printf("%s", cmd); exit ("SCRIPT '" + fname + "';"); } } else { dlgMessageBox("\n Start this ULP in a Schematic \n"); exit (0); }