Tôi ghét trả lời câu hỏi của riêng tôi, nhưng ở đây tôi đi. Tôi hy vọng tôi không nhận được điểm để trả lời, điều đó thật kỳ lạ, chỉ khi chấp nhận một câu trả lời? (BTW, tôi không nhận được bất kỳ phản hồi nào trên diễn đàn Element14.)
Giải pháp là sử dụng lệnh DRAW, không phải ROUTE. DRAW sẽ đặt một phân đoạn dây, chính xác là nơi bạn chỉ định (không giống như ROUTE, nơi cố gắng kết nối với một dây dẫn không có giới hạn. ROUTE về cơ bản là vô dụng trong một tập lệnh.). Vấn đề tiếp theo là thông qua: Tôi không thể (hoặc không muốn) phân biệt giữa hướng dẫn qua và tự động chạy qua, vì vậy tôi giữ tất cả thông qua kết nối hai (hoặc nhiều) đoạn dây thủ công. Thông qua khác được xóa.
Vì vậy, những gì kịch bản cuối cùng của tôi làm là:
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
Lưu ý rằng nó có thể sẽ không hoạt động nhiều hơn hai lớp, cũng như cho những thứ khác ngoài các đoạn dây ở lớp đồng.
IMHO toàn bộ khái niệm về đại bàng ULP và ngôn ngữ chỉ huy là rắc rối. Một ULP chạy trong môi trường chỉ đọc, cách duy nhất nó có thể ảnh hưởng đến mạch, bảng hoặc thư viện là bằng cách tạo một danh sách các lệnh. Điều này giúp loại bỏ một số kỹ thuật lập trình hữu ích, nhưng tệ hơn là các lệnh không được thiết kế để dễ dàng tạo ra từ một ULP. Bạn cần tất cả các loại biến đổi (trong trường hợp này: tọa độ, tên hình dạng) để dịch từ thế giới ULP sang thế giới CMD.
(chỉnh sửa) Trước khi bạn chạy ULP này, hãy đặt lựa chọn 'uốn cong dây' để cho phép các góc tùy ý, nếu không, đại bàng sẽ cố gắng điều chỉnh các dây được phục hồi thành các góc cho phép, điều này có thể dẫn đến tình trạng lộn xộn đẫm máu. IMHO đây là một ví dụ khác về vấn đề với ULP / SCR.
Đây là mã 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 );
}