#usage "KiCAD module exporting tool version 0.1a \n" "

" "This ULP can exports Eagle CAD Package contents into KiCAD module format." "

" "Load any library from the library directory and execute the ULP." "

" "Author: sdn@openhardware.ru" int rect_conv = 1; // many QFP-like packages use rectangles as a pin contour (too much segments in the ki-format) int poly_conv = 1; int holes_conv = 1; int RECT_WIDTH = 80; // it is very difficult for me to compare this two formats, so pLayers &2lease correct // this LUT if you find mistakes, and send your corrections to sdn@openhardware.ru. /* LAYER_CMP_N 15 CMP_N 15 NB_COPPER_LAYERS (CMP_N+1) FIRST_NO_COPPER_LAYER 16 ADHESIVE_N_CU 16 ADHESIVE_N_CMP 17 SOLDERPASTE_N_CU 18 SOLDERPASTE_N_CMP 19 SILKSCREEN_N_CU 20 SILKSCREEN_N_CMP 21 SOLDERMASK_N_CU 22 SOLDERMASK_N_CMP 23 DRAW_N 24 COMMENT_N 25 ECO1_N 26 ECO2_N 27 EDGE_N 28 */ int layer_lut[] = { 15, //LAYER_TOP 16, //LAYER_BOTTOM 15, //LAYER_PADS 15, //LAYER_VIAS 21, //LAYER_UNROUTED 21, //LAYER_DIMENSION 21, //LAYER_TPLACE 21, //LAYER_BPLACE 21, //LAYER_TORIGINS 21, //LAYER_BORIGINS 21, //LAYER_TNAMES 21, //LAYER_BNAMES 21, //LAYER_TVALUES 21, //LAYER_BVALUES 21, //LAYER_TSTOP 21, //LAYER_BSTOP 21, //LAYER_TCREAM 21, //LAYER_BCREAM 21, //LAYER_TFINISH 21, //LAYER_BFINISH 21, //LAYER_TGLUE 21, //LAYER_BGLUE 21, //LAYER_TTEST 21, //LAYER_BTEST 21, //LAYER_TKEEPOUT 21, //LAYER_BKEEPOUT 21, //LAYER_TRESTRICT 21, //LAYER_BRESTRICT 21, //LAYER_VRESTRICT 21, //LAYER_DRILLS 21, //LAYER_HOLES 21, //LAYER_MILLING 21, //LAYER_MEASURES 21, //LAYER_DOCUMENT 21, //LAYER_REFERENCE 21, //LAYER_TDOCU 20, //LAYER_BDOCU 21, //LAYER_NETS 21, //LAYER_BUSSES 21, //LAYER_PINS 21, //LAYER_SYMBOLS 21, //LAYER_NAMES 21 //LAYER_VALUES }; //------------------------------------------------------ // utils //------------------------------------------------------ int layer_lookup(int layer) { if(layer > 42) return 21; return layer_lut[layer+1]; } //Units conversion routine | 1.0 inch = 10000 Ki-units | int egl2ki(int units) { real inch = u2inch(units); return int(inch*10000); } // check for smd pads in package int issmd(UL_PACKAGE PAC) { int res = 0; PAC.contacts(C) { res |= C.smd?1:0; } return res; } //------------------------------------------------------ //write index of modules //------------------------------------------------------ void write_kikad_mod_idx(UL_LIBRARY LIB) { // write INDEX start tag printf("$INDEX\n"); // write index of modules LIB.packages(PAC) printf("%s\n", strupr(PAC.name)); // write INDEX end tag printf("$EndINDEX\n"); } //------------------------------------------------------ // pad conversion //------------------------------------------------------ void write_kikad_mod_pad(UL_PACKAGE PAC) { char shp = 'R'; string signal, type = "STD"; int dx, dy, drill, layset; PAC.contacts(CN) { // write PAD start tag printf("$PAD\n"); signal = CN.signal; if(CN.smd) { type = "SMD"; if(CN.smd.roundness > 40) if(CN.smd.dx == CN.smd.dy) shp = 'C'; else shp = 'O'; dx = CN.smd.dx; dy = CN.smd.dy; } if(CN.pad) { type = "STD"; if(CN.pad.shape[LAYER_TOP] == PAD_SHAPE_ROUND ) shp = 'C'; if(CN.pad.shape[LAYER_TOP] == PAD_SHAPE_OCTAGON) shp = 'C'; if(CN.pad.shape[LAYER_TOP] == PAD_SHAPE_LONG ) shp = 'O'; dx = CN.pad.diameter[LAYER_TOP]; dy = CN.pad.diameter[LAYER_TOP]; drill = CN.pad.drill; } // pad shape printf("Sh \"%s\" %c %d %d %d %d %d\n", CN.name, shp, egl2ki(dx), egl2ki(dy), 0, 0, 0); printf("Dr %d %d %d \n", egl2ki(drill), 0, 0); printf("At %s N %08X\n", type, layset); printf("Ne 0 \"%s\"\n", signal); printf("Po %d %d \n", egl2ki(CN.x), -egl2ki(CN.y)); // write PAD end tag printf("$EndPAD\n"); } } //------------------------------------------------------ // shape conversion //------------------------------------------------------ void write_kicad_mod_shapes(UL_PACKAGE PAC) { //write shapes //also we must convert inverted y-coordinates (take it with minus) // //segments (always from eagle's rectangles,wires and optional polygons) // rectangles converting ------------------------------------------------------------- int layer; if(rect_conv) PAC.rectangles(R) { layer = layer_lookup(R.layer); printf("DS %d %d %d %d %d %d\n", egl2ki(R.x1), -egl2ki(R.y1), egl2ki(R.x2), -egl2ki(R.y1), RECT_WIDTH, layer); printf("DS %d %d %d %d %d %d\n", egl2ki(R.x2), -egl2ki(R.y1), egl2ki(R.x2), -egl2ki(R.y2), RECT_WIDTH, layer); printf("DS %d %d %d %d %d %d\n", egl2ki(R.x1), -egl2ki(R.y2), egl2ki(R.x2), -egl2ki(R.y2), RECT_WIDTH, layer); printf("DS %d %d %d %d %d %d\n", egl2ki(R.x1), -egl2ki(R.y1), egl2ki(R.x1), -egl2ki(R.y2), RECT_WIDTH, layer); } // wires converting --------------------------------------------------------------------- PAC.wires(W) { layer = layer_lookup(W.layer); if(!W.arc) printf("DS %d %d %d %d %d %d\n", egl2ki(W.x1), -egl2ki(W.y1), egl2ki(W.x2), -egl2ki(W.y2), egl2ki(W.width), layer); } // polygons converting ------------------------------------------------------------------ if(poly_conv) PAC.polygons(P) { P.contours(CONT) { layer = layer_lookup(CONT.layer); printf("DS %d %d %d %d %d %d\n", egl2ki(CONT.x1), -egl2ki(CONT.y1), egl2ki(CONT.x2), -egl2ki(CONT.y2), egl2ki(CONT.width), layer); } P.wires(W) { printf("DS %d %d %d %d %d %d\n", egl2ki(W.x1), egl2ki(W.y1), egl2ki(W.x2), egl2ki(W.y2), egl2ki(W.width), layer);} } //circles (always from eagle's circles and optional from holes) // circles converting -------------------------------------------------------------------- PAC.circles(C) { layer = layer_lookup(C.layer); printf("DC %d %d %d %d %d %d\n", egl2ki(C.x) , -egl2ki(C.y) , egl2ki(C.x) + ((egl2ki(C.x)>0)?1:(-1)) * egl2ki(C.radius/2), -egl2ki(C.y) - ((egl2ki(C.y)>0)?1:(-1)) * egl2ki(C.radius/2), egl2ki(C.width), layer); } if(holes_conv) PAC.holes(H) { layer = 21; printf("DC %d %d %d %d %d %d\n", egl2ki(H.x), -egl2ki(H.y), egl2ki(H.x) + ((egl2ki(H.x)>0)?1:(-1)) * egl2ki(H.drill/4), -egl2ki(H.y) - ((egl2ki(H.y)>0)?1:(-1)) * egl2ki(H.drill/4), 50, layer); printf("DS %d %d %d %d %d %d\n", egl2ki(H.x - (H.drill/2)), -egl2ki(H.y), egl2ki(H.x + (H.drill/2)), -egl2ki(H.y), 50, layer); printf("DS %d %d %d %d %d %d\n", egl2ki(H.x), -egl2ki(H.y - (H.drill/2)), egl2ki(H.x), -egl2ki(H.y + (H.drill/2)), 50, layer); } //arcs converting (always from wires) ---------------------------------------------------- PAC.wires(W) { if(W.arc) { layer = layer_lookup(W.layer); printf("DA %d %d %d %d %d %d %d \n", egl2ki(W.arc.xc ), -egl2ki(W.arc.yc), egl2ki(W.arc.x2), -egl2ki(W.arc.y2), int((360 + abs(W.curve))*10) , egl2ki(W.arc.width), layer); } } } //------------------------------------------------------ // Text conversion //------------------------------------------------------ void write_kicad_mod_text(UL_PACKAGE PAC) { int textnum = 0; PAC.texts(T) { printf("T%d %d %d %d %d %d %d %d \"%s\"\n", textnum, egl2ki(T.x), -egl2ki(T.y), egl2ki(T.size), egl2ki(T.size), int((360 + abs(T.angle))*10), 50, 21, T.value); textnum++; } } //------------------------------------------------------ // Mod body conversion //------------------------------------------------------ void write_kikad_mod_body(UL_LIBRARY LIB) { //for all packages in library LIB.packages(PAC) { // write MODULE start tag printf("$MODULE %s\n", strupr(PAC.name)); //write module position printf("Po %d %d %d %d 00200000 00000000 ~~\n", 0, // what's it? 0, // and here? 0, // orient 15 // layer ); //write name & description printf("Li %s\n", strupr(PAC.name)); printf("Cd %s\n", strupr(PAC.headline)); printf("Kw %s\n", strupr(PAC.headline)); //write timestamp printf("Sc 00000000\n"); //write orientation printf("Op 0 0 0\n"); //write attributes printf("At %s\n", issmd(PAC) ? "SMD" : "VIRTUAL"); write_kicad_mod_shapes(PAC); write_kicad_mod_text(PAC); // write module pads write_kikad_mod_pad(PAC); // write MODULE end tag printf("$EndMODULE %s\n", strupr(PAC.name)); } } //------------------------------------------------------ //ki-format high-level write functions //------------------------------------------------------ void write_kicad_mod(string name) { output(name, "wt") { if (library) library(L) { int t = time(); printf("PCBNEW-LibModule-V1 %02d/%02d/%04d-%02d:%02d:%02d\n", t2day(t), t2month(t)+1, t2year(t), t2hour(t), t2minute(t), t2second(t)); write_kikad_mod_idx(L); write_kikad_mod_body(L); } } } //------------------------------------------------------ // main program //------------------------------------------------------ string mod_name ; int result; string ref; if (library) library(L) mod_name = strsub(L.name, 0, strlen(L.name) - 3) + "mod"; else { dlgMessageBox("Please run from library editor." ); exit(EXIT_FAILURE); } result = dlgDialog("Export KiCAD mod") { dlgTabWidget { //=====================TAB1============================================================= dlgTabPage("Output") { dlgHBoxLayout dlgSpacing(400); dlgStretch(0); dlgLabel("Export to file:"); dlgStretch(0); dlgStringEdit(mod_name); dlgVBoxLayout { dlgStretch(0); dlgHBoxLayout { dlgStretch(1); dlgPushButton("+OK") dlgAccept(); dlgStretch(0); } dlgHBoxLayout { dlgStretch(1); dlgPushButton("-Cancel") dlgReject(); dlgStretch(0); } dlgStretch(10); }; dlgStretch(1); } //======================TAB2============================================================ // dlgTabPage("Layers") // { // dlgTextView("Click here: options", ref) dlgDialog(ref){dlgLabel(ref);}; // } } }; //dlgMessageBox(" \n" ); if(result) write_kicad_mod(mod_name); else dlgMessageBox("Canceled!" ); exit(EXIT_SUCCESS);