You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
470 lines
14 KiB
Plaintext
470 lines
14 KiB
Plaintext
15 years ago
|
#usage "<b>Renumber the parts of a schematic</b><p>"
|
||
|
"This version renumbers only devices with packages (no supply) "
|
||
|
"sorted by sheets and coordinates (vertical/descending, horizontal/ascending).<br>"
|
||
|
"Optional: The starting point for the numeration of parts on the first sheet "
|
||
|
"defines an offset value for the following pages.<br>"
|
||
|
"Example:<br>"
|
||
|
" - 0 = R1 ... Rn<br>"
|
||
|
" - 100 sheet 1: R101..R199 sheet 2: R201..R299 ...<br>"
|
||
|
" - 1000 sheet 1: R1001..R1999 sheet 2: R2001..R2999 ...<br>"
|
||
|
"<p>"
|
||
|
"<author>Author: support@cadsoft.de</author>"
|
||
|
|
||
|
// THIS PROGRAM IS PROVIDED AS IS AND WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED
|
||
|
|
||
|
string Version = "ULP Version 4.3.0"; // 2006.08.23 alf@cadsoft.de
|
||
|
// correct counter if crossing page by same prefix
|
||
|
|
||
|
string Info = "<b>ATTENTION<p>\n" +
|
||
|
"Please verify that the corresponding layout file (if already existing) " +
|
||
|
"has been loaded with the schematic file.<p>" +
|
||
|
"Otherwise back-/forward-annotation will not work afterwards.</b>";
|
||
|
|
||
|
string Infoplus =
|
||
|
" You can change the following sorting parameters:<p>" +
|
||
|
" descx = 0 (X ascending [left >> right])<br>" +
|
||
|
" descx = 1 (X descending [right >> left])<br>" +
|
||
|
" descy = 0 (Y ascending [bottom >> top])<br>" +
|
||
|
" descy = 1 (Y descending [top >> bottom])<br>";
|
||
|
|
||
|
|
||
|
int descy = 1; // set to 0 sorting ascending
|
||
|
int descx = 0; // set to 1 sorting descending
|
||
|
int numerical_order = 0;
|
||
|
|
||
|
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 NoRenumber = "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.
|
||
|
if (descy) DescendingY();
|
||
|
if (descx) DescendingX();
|
||
|
|
||
|
if(!numerical_order) {
|
||
|
sort(nrNames, i, NewNames, sh, y, x);
|
||
|
}
|
||
|
else {
|
||
|
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, "<qt><nobr>More parts with prefix '%s' than starting point %d on sheet %d<br>Start the ulp with <b>numerical order</b> >= %d</nobr>",
|
||
|
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("<font color=red>" + Info + "</font>");
|
||
|
dlgHBoxLayout {
|
||
|
dlgGroup("Sort X") {
|
||
|
dlgRadioButton("&Ascending", descx);
|
||
|
dlgRadioButton("&Descending", descx);
|
||
|
}
|
||
|
dlgGroup("Sort Y") {
|
||
|
dlgRadioButton("A&scending", descy);
|
||
|
dlgRadioButton("D&escending", descy);
|
||
|
}
|
||
|
dlgSpacing(8);
|
||
|
dlgGroup("Do not renumber parts with") {
|
||
|
dlgHBoxLayout {
|
||
|
dlgLabel("&Prefix ");
|
||
|
dlgStringEdit(NoRenumber);
|
||
|
dlgStretch(1);
|
||
|
}
|
||
|
}
|
||
|
dlgStretch(1);
|
||
|
}
|
||
|
dlgHBoxLayout {
|
||
|
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);
|
||
|
}
|
||
|
}
|
||
|
dlgStretch(1);
|
||
|
}
|
||
|
dlgHBoxLayout {
|
||
|
dlgPushButton("+&OK") dlgAccept();
|
||
|
dlgSpacing(15);
|
||
|
dlgPushButton("-&Cancel") dlgReject();
|
||
|
dlgSpacing(15);
|
||
|
dlgLabel(Version);
|
||
|
dlgStretch(1);
|
||
|
}
|
||
|
};
|
||
|
if (!Result) exit (0);
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
if (schematic) {
|
||
|
schematic(S) {
|
||
|
menue();
|
||
|
int l = 1;
|
||
|
int chk;
|
||
|
S.sheets(SH) {
|
||
|
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) == NoRenumber);
|
||
|
|
||
|
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++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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 .S1;\n");
|
||
|
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);
|
||
|
}
|