Odio rispondere alla mia domanda, ma eccomi qui. Spero di non ottenere punti per la risposta, sarebbe strano, solo per aver accettato una risposta? (A proposito, non ho ricevuto alcuna risposta sul forum Element14.)
La soluzione è utilizzare il comando DRAW, non ROUTE. DRAW posizionerà un segmento di filo, esattamente dove si specifica (diversamente da ROUTE, che tenta di connettersi a un airwire non instradato. ROUTE è essenzialmente inutile in uno script.). Il prossimo problema è via: non riesco (o non voglio) distinguere tra un manuale via e un via automatica, quindi tengo tutti i via che collegano due (o più) segmenti di filo manuali. Altri via vengono eliminati.
Quindi quello che fa la mia sceneggiatura finale è:
prepare a ripup command
for all copper segments that are not 0.01 wide (the width I use for autorouting)
check both endpoints for a via at that location
prepare the via to be resurrected when it is visited the 2nd time
prepare a command that resurrects the copper segment
execute the prepared commands
Si noti che probabilmente non funzionerà per più di due strati, né per altre cose oltre ai segmenti di filo sullo strato di rame.
IMHO l'intero concetto dell'aquila ULP e dei linguaggi di comando è problematico. Un ULP funziona in un ambiente di sola lettura, l'unico modo in cui può influenzare il circuito, la scheda o la libreria è creando un elenco di comandi. Questo elimina alcune utili tecniche di programmazione, ma peggio ancora è che i comandi non sono stati progettati per essere facilmente creati da un ULP. Sono necessari tutti i tipi di trasformazioni (in questo caso: coordinate, nomi delle forme) per tradurre dal mondo ULP al mondo CMD.
(modifica) Prima di eseguire questo ULP, impostare la selezione 'piega filo' per consentire angoli arbitrari, altrimenti l'aquila proverà ad adattare i fili risorti agli angoli consentiti, il che può provocare un casino sanguinante. IMHO questo è un altro esempio del problema con ULP / SCR.
Questo è il codice ULP:
// gather the commands that must be run on exit
string RunOnExit = "";
void cmd( string s ) { RunOnExit += s + "\n"; }
// return an x or y position in the form that can be used in a command
real f( int x ){
board( B ) switch( B.grid.unit ) {
case 0: return u2mic(x);
case 1: return u2mm(x);
case 2: return u2mil(x);
case 3: return u2inch(x);
}
}
// return the string form of the a via's shape
string sn( int x ){
if( x == VIA_SHAPE_SQUARE ) return "square";
if( x == VIA_SHAPE_ROUND ) return "round";
if( x == VIA_SHAPE_OCTAGON ) return "octagon";
if( x == VIA_SHAPE_ANNULUS ) return "annulus";
if( x == VIA_SHAPE_THERMAL ) return "thermal";
return "unknown-via-shape";
}
// count the number of times x occurs in s
int n_ocurrences( string s, string x ){
int i, n = 0;
while( 1 ){
i = strstr( s, x );
if( i == -1 ) return n;
s = strsub( s, i + strlen( x ));
n++;
}
}
// add a via, but only when it is visited the second time
string via_list = "";
void add_via( int a, int b ){
// for all via's
board( B ) B.signals( S ) S.vias( V ){
// if the via is at the current location
if(( V.x == a ) && ( V.y == b )){
string s, coo;
// the coordinates of the via are used as its identification
sprintf( coo, "(%.6f %.6f)", f( V.x ), f( V.y ));
// if this is the second visit to this via
via_list += coo;
if( n_ocurrences( via_list, coo ) == 2 ){
// resurrect this via
sprintf( s, "VIA '%s' %f %s %s;",
S.name, f( V.drill ), sn( V.shape[ 1 ] ), coo );
cmd( s );
}
}
}
}
if( !board ){
dlgMessageBox("start this ULP in Board", "OK");
exit( 0 );
}
board( B ){
// first delete all coper segments,
// later we will resurrect what we want to keep
cmd( "RIPUP;" );
// for all wire segments in the top and bottom copper layers
B.signals(S) S.wires(W) {
if( ( W.layer == 1 ) || ( W.layer == 16 ) ){
// that are not 0.01 width (that is what the autorouter uses)
if( f( W.width ) != 0.01 ){
string s;
// resurrect via's adjacent to this wire segment
add_via( W.x1, W.y1 );
add_via( W.x2, W.y2 );
sprintf( s, "CHANGE LAYER %d;", W.layer );
cmd( s );
// resurrect this wire segment
sprintf(
s, "WIRE '%s' %f (%.6f %.6f) (%.6f %.6f);",
S.name, f( W.width),
f(W.x1), f(W.y1), f(W.x2), f(W.y2));
cmd( s );
}
}
}
// dlgMessageBox( RunOnExit, "OK");
exit( RunOnExit );
}