/* Copyright (c) 2008, Sven Pauli All rights reserved. */ /* Scale factor */ int pac_scale = 10; int sym_scale = 1; /* Modes: 1 -- Symbol 2 -- Package */ int mode; string script_file; real scu(int x) { switch (mode) { case 0: return 0; /* Symbol */ case 1: return u2mic(x / sym_scale); /* Package */ case 2: return u2mic(x / pac_scale); } } string str_replace(string s, char c, string r) { int pos; int start = 0; string result = ""; pos = strchr(s, c); if (pos == -1) { return s; } while (pos >= 0) { result += strsub(s, start, pos - start); result += r; start = pos + 1; pos = strchr(s, c, start); } result += strsub(s, start); return result; } string make_description(string s) { string result; sprintf(result, "%s (pac 1:%u, sym 1:%u)", s, pac_scale, sym_scale); result = str_replace(result, '\'', "''"); result = str_replace(result, '\n', "\\n"); return result; } string strip_at(string s) { int pos = strstr(s, "@"); if (pos > 0) { return strsub(s, 0, pos); } return s; } string check_gate_name(string name) { if (name == "") { return "_"; } return str_replace(name, ' ', "-"); } string separate_technologies(string t) { string technologies[]; int n = strsplit(technologies, t, ' '); string result = ""; for (int i = 0; i < n; i++) { if (technologies[i] == "''") { result += "'' "; } else { result += "'" + technologies[i] + "' "; } } return result; } void change_layer(int layer) { int trash = 0; switch (mode) { case 0: break; /* Symbol */ case 1: if ( (layer <= 90) || ((layer >= 97) && (layer<=99)) ) { trash = 1; } break; /* Package */ case 2: if ( (layer >= 91) && (layer <= 99) ) { trash = 1; } break; } if (trash) { printf("LAYER 250;\n"); } else { printf("LAYER %d;\n", layer); } } void copy_circle(UL_CIRCLE X) { change_layer(X.layer); printf("CIRCLE %f (%f %f) (%f %f);\n", scu(X.width), scu(X.x), scu(X.y), scu(X.x + X.radius), scu(X.y) ); } void copy_rectangle(UL_RECTANGLE X) { change_layer(X.layer); printf("RECT R%.1f (%f %f) (%f %f);\n", X.angle, scu(X.x1), scu(X.y1), scu(X.x2), scu(X.y2) ); } void copy_text(UL_TEXT X) { change_layer(X.layer); /* Font */ switch (X.font) { case FONT_VECTOR: printf("CHANGE FONT VECTOR;\n"); break; case FONT_PROPORTIONAL: printf("CHANGE FONT PROPORTIONAL;\n"); break; case FONT_FIXED: printf("CHANGE FONT FIXED;\n"); break; } /* Size and ratio */ printf("CHANGE SIZE %f;\n", scu(X.size)); printf("CHANGE RATIO %d;\n", X.ratio); /* Angle, spin and mirror */ string angle = ""; if (X.spin) { angle += "S"; } if (X.mirror) { angle += "M"; } /* TODO Apostrophes? */ printf("TEXT %sR%.1f '%s' (%f %f);\n", angle, X.angle, X.value, scu(X.x), scu(X.y) ); } void copy_hole(UL_HOLE X) { /* TODO Diameter? */ printf("CHANGE DRILL %f;\n", scu(X.drill)); printf("HOLE (%f %f);\n", scu(X.x), scu(X.y) ); } void copy_wire(UL_WIRE X) { change_layer(X.layer); if (X.arc) { printf("ARC CCW %f (%f %f) (%f %f) (%f %f);\n", scu(X.width), scu(X.arc.x1), scu(X.arc.y1), scu(X.arc.xc + X.arc.xc - X.arc.x1), scu(X.arc.yc + X.arc.yc - X.arc.y1), scu(X.arc.x2), scu(X.arc.y2) ); } else { printf("WIRE %f (%f %f) (%f %f);\n", scu(X.width), scu(X.x1), scu(X.y1), scu(X.x2), scu(X.y2) ); } } void copy_contact(UL_CONTACT X) { string shape; string flags = ""; if (X.pad) { /* Drill */ printf("CHANGE DRILL %f;\n", scu(X.pad.drill)); /* Shape */ switch(X.pad.shape[17]) { case PAD_SHAPE_SQUARE: shape = "SQUARE"; break; case PAD_SHAPE_ROUND: shape = "ROUND"; break; case PAD_SHAPE_OCTAGON: shape = "OCTAGON"; break; case PAD_SHAPE_LONG: shape = "LONG"; break; case PAD_SHAPE_OFFSET: shape = "OFFSET"; break; } /* Flags */ if ( !(X.pad.flags & PAD_FLAG_STOP) ) { flags += "NOSTOP"; } if ( !(X.pad.flags & PAD_FLAG_THERMALS) ) { flags += "NOTHERMALS"; } if (X.pad.flags & PAD_FLAG_FIRST) { flags += "FIRST"; } printf("PAD %f %s R%.1f %s '%s' (%f %f);\n", scu(X.pad.diameter[17]), shape, X.pad.angle, flags, str_replace(X.pad.name, '\'', "''"), scu(X.pad.x), scu(X.pad.y) ); } else if (X.smd) { change_layer(X.smd.layer); /* Roundness */ printf("CHANGE ROUNDNESS %d;\n", X.smd.roundness); /* Flags */ if ( !(X.smd.flags & SMD_FLAG_STOP) ) { flags += "NOSTOP"; } if ( !(X.smd.flags & SMD_FLAG_THERMALS) ) { flags += "NOTHERMALS"; } if ( !(X.smd.flags & SMD_FLAG_CREAM) ) { flags += "NOCREAM"; } printf("SMD %f %f -%d R%.1f %s '%s' (%f %f);\n", scu(X.smd.dx), scu(X.smd.dy), X.smd.roundness, X.smd.angle, flags, str_replace(X.smd.name, '\'', "''"), scu(X.smd.x), scu(X.smd.y) ); } } void copy_polygon(UL_POLYGON X) { change_layer(X.layer); /* Isolate and spacing */ printf("CHANGE ISOLATE %f;\n", scu(X.isolate)); printf("CHANGE SPACING %f;\n", scu(X.spacing)); /* Orphans */ if (X.orphans) { printf("CHANGE ORPHANS ON;\n"); } else { printf("CHANGE ORPHANS OFF;\n"); } /* Thermals */ if (X.thermals) { printf("CHANGE THERMALS ON;\n"); } else { printf("CHANGE THERMALS OFF;\n"); } /* Pour */ switch (X.pour) { case POLYGON_POUR_SOLID: printf("CHANGE POUR SOLID;\n"); break; case POLYGON_POUR_HATCH: printf("CHANGE POUR HATCH;\n"); break; } /* Start polygon */ printf("POLYGON %f ", scu(X.width)); /* Append first coordinate */ X.wires(W) { printf("(%f %f) ", scu(W.x1), scu(W.y1)); break; } /* Append remaining coordinates */ X.wires(W) { printf(" %+f (%f %f) ", W.curve, scu(W.x2), scu(W.y2) ); } /* Finalize polygon */ printf(";\n"); } void copy_pin(UL_PIN X) { string angle; string function; string visibility; string direction; string length; /* Angle */ sprintf(angle, "R%f", X.angle); /* Function */ switch (X.function) { case PIN_FUNCTION_FLAG_NONE: function = "NONE"; break; case PIN_FUNCTION_FLAG_DOT: function = "DOT"; break; case PIN_FUNCTION_FLAG_CLK: function = "CLK"; break; case (PIN_FUNCTION_FLAG_DOT | PIN_FUNCTION_FLAG_CLK): function = "DOTCLK"; break; } /* Visibility */ switch (X.visible) { case PIN_VISIBLE_FLAG_OFF: visibility = "OFF"; break; case PIN_VISIBLE_FLAG_PIN: visibility = "PIN"; break; case PIN_VISIBLE_FLAG_PAD: visibility = "PAD"; break; case (PIN_VISIBLE_FLAG_PIN | PIN_VISIBLE_FLAG_PAD): visibility = "BOTH"; break; } /* Direction */ switch(X.direction) { case PIN_DIRECTION_NC: direction = "NC"; break; case PIN_DIRECTION_IN: direction = "IN"; break; case PIN_DIRECTION_OUT: direction = "OUT"; break; case PIN_DIRECTION_IO: direction = "I/O"; break; case PIN_DIRECTION_OC: direction = "OC"; break; case PIN_DIRECTION_PWR: direction = "PWR"; break; case PIN_DIRECTION_PAS: direction = "PAS"; break; case PIN_DIRECTION_HIZ: direction = "HIZ"; break; case PIN_DIRECTION_SUP: direction = "SUP"; break; } /* Length */ switch (X.length) { case PIN_LENGTH_POINT: length = "POINT"; break; case PIN_LENGTH_SHORT: length = "SHORT"; break; case PIN_LENGTH_MIDDLE: length = "MIDDLE"; break; case PIN_LENGTH_LONG: length = "LONG"; break; } printf("PIN '%s' %s %s %s %s %s %d (%f %f);\n", str_replace(X.name, '\'', "''"), direction, function, length, angle, visibility, X.swaplevel, scu(X.x), scu(X.y)); } void clone_layers(UL_LIBRARY X) { X.layers(L) { } } void clone_symbol(UL_SYMBOL X) { mode = 1; printf("EDIT %s.SYM;\n", X.name); X.circles(C) { copy_circle(C); } X.rectangles(R) { copy_rectangle(R); } X.wires(W) { copy_wire(W); } X.pins(P) { copy_pin(P); } X.texts(T) { copy_text(T); } X.polygons(PO) { copy_polygon(PO); } } void clone_package(UL_PACKAGE X) { mode = 2; printf("EDIT %s.PAC;\n", X.name); printf("DESCRIPTION '%s';\n", make_description(X.description)); X.circles(C) { copy_circle(C); } X.rectangles(R) { copy_rectangle(R); } X.wires(W) { copy_wire(W); } X.contacts(C) { copy_contact(C); } X.texts(T) { copy_text(T); } X.holes(H) { copy_hole(H); } X.polygons(PO) { copy_polygon(PO); } } void clone_deviceset(UL_DEVICESET X) { printf("EDIT %s.DEV;\n", X.name); /* Device properties */ printf("DESCRIPTION '%s';\n", make_description(X.description)); printf("PREFIX %s;\n", X.prefix); printf("VALUE %s;\n", X.value); /* Gates */ X.gates(G) { /* Addlevel */ switch (G.addlevel) { case GATE_ADDLEVEL_NEXT: printf("CHANGE ADDLEVEL NEXT;\n"); break; case GATE_ADDLEVEL_MUST: printf("CHANGE ADDLEVEL MUST;\n"); break; case GATE_ADDLEVEL_CAN: printf("CHANGE ADDLEVEL CAN;\n"); break; case GATE_ADDLEVEL_REQUEST: printf("CHANGE ADDLEVEL REQUEST;\n"); break; case GATE_ADDLEVEL_ALWAYS: printf("CHANGE ADDLEVEL ALWAYS;\n"); break; } /* Swaplevel */ printf("CHANGE SWAPLEVEL %d;\n", G.swaplevel); printf("ADD %s '%s' (%f %f);\n", strip_at(G.symbol.name), check_gate_name(G.name), scu(G.x), scu(G.y) ); } /* Devices */ X.devices(DV) { if (DV.package) { printf("PACKAGE '%s' %s;\n", strip_at(DV.package.name), strip_at(DV.name) ); printf("TECHNOLOGY %s;\n", separate_technologies(DV.technologies) ); } DV.gates(G) { G.symbol.pins(P) { if (!DV.package) { continue; } if (!P.contact) { continue; } printf("CONNECT '%s.%s' '%s';\n", check_gate_name(G.name), str_replace(P.name, '\'', "''"), str_replace(P.contact.name, '\'', "''") ); } } /* DV.gates */ } /* X.devices */ } void clone_library() { /* Generate trash layer on 250 */ printf("LAYER 250 trash;\n"); /* Setup some things */ printf("GRID MIC 1;\n"); printf("DISPLAY ALL;\n"); printf("SET UNDO_LOG OFF;\n"); library(L) { printf("DESCRIPTION '%s';\n", make_description(L.description)); L.packages(P) { status("Cloning package " + P.name + "..."); clone_package(P); } L.symbols(S) { status("Cloning symbol " + S.name + "..."); clone_symbol(S); } L.devicesets(DS) { status("Cloning device " + DS.name + "..."); clone_deviceset(DS); } /* TODO Grid? */ } printf("SET UNDO_LOG ON;\n"); } if (!library) { dlgMessageBox("Please open a source library."); exit(EXIT_FAILURE); } /* Select and open script file */ script_file = dlgFileSave("Select script file", "", "*.scr"); if (script_file == "") { exit(EXIT_FAILURE); } /* Clone the library */ output(script_file, "w") { clone_library(); } exit(EXIT_SUCCESS);