Created
November 14, 2012 09:01
-
-
Save yoneken/4071092 to your computer and use it in GitHub Desktop.
This script converts a library of Eagle to one of KiCad.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#usage "<b>KiCAD module exporting tool version 0.8 </b>\n" | |
"<p>" | |
"This ULP can exports Eagle CAD Package and Symbol contents into KiCAD lib and module format." | |
"<p>" | |
"Load any library from the library directory and execute the ULP." | |
"<p>" | |
"<author>Author: Dmitri N. Sytov sdn (at) openhardware.ru</author>" | |
"<author>Author: juergen.messerer (at) freesurf.ch</author>" | |
/* | |
* CHANGELOG=(dd.mm.yyyy)=============================================== | |
* | |
* 09.11.2012: Fix a bug for drawing a circle. | |
* | |
* 06.09.2012: Respond to FPLIST. (Changed by taki4416) | |
* | |
* 01.12.2006: Little changes on the script with DEV.package. Always check if | |
* DEV.package exist otherwise an error will occure. | |
* | |
* 22.08.2006: - Changes made by Sergiusz Urbaniak (mieszkoman (at) gmx.de) | |
* - Selection of export of Pin Names and Pin Numbers | |
* - Prefixing each module with the Eagle library name (easier to navigate in the netlist) | |
* - Support of multiple units | |
* | |
* 17.07.2006: The positions of the name and the prefix are fixed for multi part devices | |
* | |
* 17.07.2006: Now the script creates also devices without packages. | |
* When a device has more then one part then it use symbol name | |
* for the alias "F0, F1, .." | |
* When it has more then one package then it use the device name | |
* | |
* 19.06.2006: Bugfix, devices with more then one packages will now generate | |
* a device for each package | |
* | |
* 14.06.2006: Add the translation feature for multipart devices | |
* | |
* 12.06.2006: Fixed the arc problem. There is still a text position problem | |
* | |
* 08.06.2006: Now it converts also the symbol from eagle | |
* | |
* 14.11.2005: Fixed BUGS: | |
* - Invalid layers in $PAD section | |
* - Text fields has right coords but bad align | |
* - Polygonal areas draws twice | |
* Thanks to: | |
* Biglacko <biglacko (at) startolj.hu> | |
*/ | |
/* ========================================================================== | |
* License: This file is released under the license of the GNU Public license | |
* Version 2. | |
* ==========================================================================*/ | |
real VERSION = 0.9; | |
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; | |
string g_lib_prefix ; | |
int writePins = 0; | |
int drawPinnumber = 0; | |
int drawPinname = 0; | |
int RECT_WIDTH = 26; | |
// please edit this LUT if you found mistakes, | |
// and send your corrections to sdn (at) 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 | |
*/ | |
// Lookup table for shape layers | |
int layer_lut[] = | |
{0, | |
15, //LAYER_TOP | |
0,0,0,0,0,0,0,0,0,0,0,0,0,0, //inner layers | |
16, //LAYER_BOTTOM | |
16, //LAYER_PADS | |
16, //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 | |
}; | |
// Lookup table for pad layers | |
//CUIVRE_LAYER 0x00000001 | |
//CMP_LAYER 0x00008000 | |
//ADHESIVE_LAYER_CU 0x00010000 | |
//ADHESIVE_LAYER_CMP 0x00020000 | |
//SOLDERPASTE_LAYER_CU 0x00040000 | |
//SOLDERPASTE_LAYER_CMP 0x00080000 | |
//SILKSCREEN_LAYER_CU 0x00100000 | |
//SILKSCREEN_LAYER_CMP 0x00200000 | |
//SOLDERMASK_LAYER_CU 0x00400000 | |
//SOLDERMASK_LAYER_CMP 0x00800000 | |
//DRAW_LAYER 0x01000000 | |
//COMMENT_LAYER 0x02000000 | |
//ECO1_LAYER 0x04000000 | |
//ECO2_LAYER 0x08000000 | |
//EDGE_LAYER 0x10000000 | |
//intS_LAYER 0xE0000000 | |
//ALL_LAYERS 0x1FFFFFFF | |
//ALL_NO_CU_LAYERS 0x1FFF0000 | |
//ALL_CU_LAYERS 0x0000FFFF | |
//INTERNAL_LAYERS 0x00007FFE | |
//EXTERNAL_LAYERS 0x00008001 | |
int pad_lut[] = | |
{0, | |
0x00008000 | 0x00800000 | 0x00080000, //LAYER_TOP | |
0,0,0,0,0,0,0,0,0,0,0,0,0,0, //inner layers | |
0x00000001 | 0x00400000, //LAYER_BOTTOM | |
0x00008001 | 0x00A00000 | 0x00080000, //LAYER_PADS | |
0x00008001 | 0x00800000 | 0x00400000, //LAYER_VIAS | |
0, //LAYER_UNROUTED | |
0, //LAYER_DIMENSION | |
0, //LAYER_TPLACE | |
0, //LAYER_BPLACE | |
0, //LAYER_TORIGINS | |
0, //LAYER_BORIGINS | |
0, //LAYER_TNAMES | |
0, //LAYER_BNAMES | |
0, //LAYER_TVALUES | |
0, //LAYER_BVALUES | |
0, //LAYER_TSTOP | |
0, //LAYER_BSTOP | |
0, //LAYER_TCREAM | |
0, //LAYER_BCREAM | |
0, //LAYER_TFINISH | |
0, //LAYER_BFINISH | |
0, //LAYER_TGLUE | |
0, //LAYER_BGLUE | |
0, //LAYER_TTEST | |
0, //LAYER_BTEST | |
0, //LAYER_TKEEPOUT | |
0, //LAYER_BKEEPOUT | |
0, //LAYER_TRESTRICT | |
0, //LAYER_BRESTRICT | |
0, //LAYER_VRESTRICT | |
0x01000000 , //LAYER_DRILLS | |
0x01000000 , //LAYER_HOLES | |
0x01000000 , //LAYER_MILLING | |
0, //LAYER_MEASURES | |
0, //LAYER_DOCUMENT | |
0, //LAYER_REFERENCE | |
0, //LAYER_TDOCU | |
0, //LAYER_BDOCU | |
0, //LAYER_NETS | |
0, //LAYER_BUSSES | |
0x00008001 | 0x00A00000 | 0x00080000, //LAYER_PINS | |
0, //LAYER_SYMBOLS | |
0, //LAYER_NAMES | |
0 //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-%s\n", g_lib_prefix, 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; | |
layset = CN.smd.layer; | |
} | |
if(CN.pad) | |
{ | |
type = "STD"; | |
if(CN.pad.shape[LAYER_TOP] == PAD_SHAPE_ROUND ) | |
{ | |
shp = 'C'; | |
dy = CN.pad.diameter[LAYER_TOP]; | |
} | |
if(CN.pad.shape[LAYER_TOP] == PAD_SHAPE_OCTAGON) | |
{ | |
shp = 'C'; | |
dy = CN.pad.diameter[LAYER_TOP] * 2; | |
} | |
if(CN.pad.shape[LAYER_TOP] == PAD_SHAPE_LONG ) | |
{ | |
shp = 'O'; | |
dy = CN.pad.diameter[LAYER_TOP] * 2; | |
} | |
dx = CN.pad.diameter[LAYER_TOP]; | |
drill = CN.pad.drill; | |
layset = LAYER_PADS ; | |
} | |
// 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, pad_lut[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) | |
{ | |
//writing shapes | |
//also we must convert inverted y-coordinates (take it with minus) | |
// | |
//segments (always from eagle's rectangles,wires and optional polygons) | |
// converting rectangles ------------------------------------------------------------- | |
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); | |
} | |
// converting wires--------------------------------------------------------------------- | |
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); | |
} | |
// draws twice, fixed. | |
// 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) | |
//converting circles -------------------------------------------------------------------- | |
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/10*7), | |
-egl2ki(C.y) - ((egl2ki(C.y)>0)?1:(-1)) * egl2ki(C.radius/10*7), 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); | |
} | |
//converting (always from wires)arcs ---------------------------------------------------- | |
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); | |
} | |
} | |
} | |
//------------------------------------------------------ | |
// field conversion | |
//------------------------------------------------------ | |
void write_kicad_mod_text(UL_PACKAGE PAC) | |
{ | |
int textnum = 0; | |
int xoffs, yoffs,size; | |
string text; | |
PAC.texts(T){ | |
size = egl2ki(T.size ); | |
switch(int(T.angle)){ | |
case 0: | |
xoffs = (T.size * strlen(T.value))/2; | |
yoffs = T.size/2; | |
break; | |
case 90: | |
xoffs = -T.size/2; | |
yoffs = (T.size * strlen(T.value))/2; | |
break; | |
case 180: | |
xoffs = -(T.size * strlen(T.value))/2; | |
yoffs = -T.size/2; | |
break; | |
case 270: | |
xoffs = (T.size/2); | |
yoffs = -(T.size * strlen(T.value))/2; | |
break; | |
} | |
printf("T%d %d %d %d %d %d %d N V \"%s\"\n", | |
textnum, egl2ki(T.x + xoffs), -egl2ki(T.y + yoffs), | |
size, size, | |
int((abs(T.angle))*10), 35, 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-%s\n", g_lib_prefix, 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-%s\n", g_lib_prefix, 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 writing functions | |
//------------------------------------------------------ | |
void write_kikad_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); | |
} | |
} | |
} | |
//============================================================================================================== | |
// Eagle Symbol conversion to kicad lib file 08.06.2006 | |
//============================================================================================================= | |
//------------------------------------------------------ | |
// Global variables | |
//------------------------------------------------------ | |
string g_mod_name ; | |
string g_lib_name ; | |
real g_Fact = 254; // global uMeter to uInch conversion factor | |
int g_missingPrefix = 0; // global Indicator if an eagle devices hasn't got an prefix | |
//------------------------------------------------------ | |
//write kicad multipoint polygone entries | |
//------------------------------------------------------ | |
void write_kikad_polygon( UL_GATE G, int transX, int transY, int gatePos ) | |
{ | |
G.symbol.polygons(POLY) | |
{ | |
string polyCoord = ""; | |
int countPolyCoord = 0; | |
char fillPattern; | |
switch( POLY.pour ) | |
{ | |
case POLYGON_POUR_SOLID: | |
fillPattern = 'F'; | |
break; | |
case POLYGON_POUR_HATCH: | |
fillPattern = 'f'; | |
break; | |
default: | |
fillPattern = 'F'; | |
break; | |
} | |
POLY.wires(W) | |
{ | |
int x1 = (W.x1/g_Fact) - transX; | |
int y1 = (W.y1/g_Fact) - transY; | |
int x2 = (W.x2/g_Fact) - transX; | |
int y2 = (W.y2/g_Fact) - transY; | |
sprintf( polyCoord, " %s %d %d %d %d", polyCoord, x1, y1, x2, y2 ); | |
countPolyCoord += 2; | |
} | |
printf("P %d %d %d %d %s %c\n", countPolyCoord, gatePos, 1, 0, polyCoord, fillPattern); | |
} | |
} | |
//------------------------------------------------------ | |
//write kicad arc and polygone (line) entries | |
//------------------------------------------------------ | |
void write_kikad_arc_line( UL_GATE G, int transX, int transY, int gatePos ) | |
{ | |
G.symbol.wires(WIRE) | |
{ | |
if( WIRE.arc) | |
{ | |
int x1 = WIRE.arc.x1 / g_Fact - transX; | |
int y1 = WIRE.arc.y1 / g_Fact - transY; | |
int x2 = WIRE.arc.x2 / g_Fact - transX; | |
int y2 = WIRE.arc.y2 / g_Fact - transY; | |
int xc = WIRE.arc.xc / g_Fact - transX; | |
int yc = WIRE.arc.yc / g_Fact - transY; | |
int radius = WIRE.arc.radius / g_Fact; | |
int angle1 = (WIRE.arc.angle1 * 10)-3599; | |
int angle2 = (WIRE.arc.angle2 * 10)-3601; | |
printf( "A %d %d %d %d %d %d %d %d N %d %d %d %d\n", xc, yc, radius, angle1, angle2, | |
gatePos, 1, 0, x1, y1, x2, y2 ); | |
} | |
else | |
{ | |
int x1 = WIRE.x1 / g_Fact - transX; | |
int y1 = WIRE.y1 / g_Fact - transY; | |
int x2 = WIRE.x2 / g_Fact - transX; | |
int y2 = WIRE.y2 / g_Fact - transY; | |
printf( "P 2 %d %d %d %d %d %d %d\n", gatePos, 0, 0, x1, y1, x2, y2 ); | |
} | |
} | |
} | |
//------------------------------------------------------ | |
//write kicad rectangle entries | |
//------------------------------------------------------ | |
void write_kikad_rectangle( UL_GATE G, int transX, int transY, int gatePos ) | |
{ | |
G.symbol.rectangles(RECT) | |
{ | |
int x1 = (RECT.x1/g_Fact) - transX; | |
int y1 = (RECT.y1/g_Fact) - transY; | |
int x2 = (RECT.x2/g_Fact) - transX; | |
int y2 = (RECT.y2/g_Fact) - transY; | |
printf( "S %d %d %d %d %d %d %d F\n", x1, y1, x2, y2, gatePos, 1, 0 ); | |
} | |
} | |
//------------------------------------------------------ | |
//write kicad circle entries | |
//------------------------------------------------------ | |
void write_kikad_circle( UL_GATE G, int transX, int transY, int gatePos ) | |
{ | |
G.symbol.circles(C) | |
{ | |
int x = (C.x/g_Fact) - transX; | |
int y = (C.y/g_Fact) - transY; | |
int radius = C.radius/g_Fact; | |
if( radius > 0 && radius < 10 ) | |
{ | |
printf("C %d %d %d %d %d %d F\n", x, y, radius, gatePos, 1, 0); | |
} | |
else | |
{ | |
printf("C %d %d %d %d %d %d N\n", x, y, radius, gatePos, 1, 0); | |
} | |
} | |
} | |
//------------------------------------------------------ | |
//write kicad text entries | |
//------------------------------------------------------ | |
void write_kikad_text( UL_GATE G, int transX, int transY, int gatePos ) | |
{ | |
char orient = 0; | |
char hAlign = 'C'; | |
char vAlign = 'C'; | |
G.symbol.texts(T) | |
{ | |
int textAngle = T.angle; | |
string textString = T.value; | |
real fontSize = T.size/g_Fact; | |
int posX = (T.x/g_Fact) - transX; | |
int posY = (T.y/g_Fact) - transY; | |
int offset = ((T.size * strlen(T.value))/2)/g_Fact; | |
// Replace all spaces with '~' | |
for (int idx = 0; textString[idx]; ++idx) | |
{ | |
if( textString[idx] == ' ' ) | |
textString[idx] = '~'; | |
} | |
switch( textAngle ) | |
{ | |
case 0: | |
orient = 0; | |
hAlign = 'L'; | |
vAlign = 'B'; | |
posX = posX + offset; | |
posY = posY + fontSize/2; | |
break; | |
case 90: | |
orient = 1; | |
hAlign = 'L'; | |
vAlign = 'B'; | |
posX = posX - fontSize/2; | |
posY = posY + offset; | |
break; | |
case 180: | |
orient = 0; | |
hAlign = 'R'; | |
vAlign = 'T'; | |
posX = posX - offset; | |
posY = posY - fontSize/2; | |
break; | |
case 270: | |
orient = 1; | |
hAlign = 'L'; | |
vAlign = 'B'; | |
posX = posX + fontSize/2; | |
posY = posY - offset; | |
break; | |
} | |
if(T.value != ">NAME" && T.value != ">VALUE" ) | |
printf("T %d %d %d %.0f %d %d %d %s\n", orient, posX, posY, | |
fontSize, 0, gatePos, 0, textString ); | |
} | |
} | |
//------------------------------------------------------ | |
//write kicad pin entries | |
//------------------------------------------------------ | |
void write_kikad_pins( UL_GATE G, int transX, int transY, int gatePos ) | |
{ | |
int pinCount = 1; | |
G.symbol.pins(P) | |
{ | |
int pinAngle = 0; | |
char orient = 'L'; | |
int pinLength = 0; | |
char pinType = 'U'; | |
string pinShape = ""; | |
string pinContact = ""; | |
int posX = P.x/g_Fact - transX; | |
int posY = P.y/g_Fact - transY; | |
if(pinCount >= 9999 ) | |
{ | |
dlgMessageBox("Canceled! To many pin numbers. (>9999)" ); | |
exit(EXIT_FAILURE); | |
} | |
pinAngle = P.angle; | |
switch( pinAngle ) | |
{ | |
case 0: | |
orient = 'R'; | |
break; | |
case 90: | |
orient = 'U'; | |
break; | |
case 180: | |
orient = 'L'; | |
break; | |
case 270: | |
orient = 'D'; | |
break; | |
default: | |
orient = 'R'; | |
break; | |
} | |
switch(P.length) | |
{ | |
case PIN_LENGTH_POINT: | |
pinLength = 0; | |
break; | |
case PIN_LENGTH_SHORT: | |
pinLength = 100; | |
break; | |
case PIN_LENGTH_MIDDLE: | |
pinLength = 200; | |
break; | |
case PIN_LENGTH_LONG: | |
pinLength = 300; | |
break; | |
default: | |
pinLength = 200; | |
break; | |
} | |
switch(P.direction) | |
{ | |
case PIN_DIRECTION_NC: | |
pinType = 'U'; | |
break; | |
case PIN_DIRECTION_IN: | |
pinType = 'I'; | |
break; | |
case PIN_DIRECTION_OUT: | |
pinType = 'O'; | |
break; | |
case PIN_DIRECTION_IO: | |
pinType = 'B'; | |
break; | |
case PIN_DIRECTION_OC: | |
pinType = 'C'; | |
break; | |
case PIN_DIRECTION_PWR: | |
pinType = 'W'; | |
break; | |
case PIN_DIRECTION_PAS: | |
pinType = 'P'; | |
break; | |
case PIN_DIRECTION_HIZ: | |
pinType = 'T'; | |
break; | |
case PIN_DIRECTION_SUP: | |
pinType = 'w'; | |
break; | |
default: | |
pinType = 'U'; | |
break; | |
} | |
switch(P.function) | |
{ | |
case PIN_FUNCTION_FLAG_NONE: | |
pinShape = ""; | |
break; | |
case PIN_FUNCTION_FLAG_DOT: | |
pinShape = "I"; | |
break; | |
case PIN_FUNCTION_FLAG_CLK: | |
pinShape = "C"; | |
break; | |
case PIN_FUNCTION_FLAG_CLK|PIN_FUNCTION_FLAG_DOT: | |
pinShape = "IC"; | |
break; | |
default: | |
pinShape = ""; | |
break; | |
} | |
if(P.contact) | |
{ | |
printf( "X %s %s %d %d %d %c %d %d %d %d %c %s\n", P.name, P.contact.name, | |
posX, posY, | |
pinLength, orient, | |
40, 40, gatePos, 1, | |
pinType, pinShape ); | |
} | |
else | |
{ | |
printf( "X %s %s %d %d %d %c %d %d %d %d %c %s\n", P.name, "~", | |
posX, posY, | |
pinLength, orient, | |
40, 40, gatePos, 1, | |
pinType, pinShape ); | |
} | |
} | |
} | |
//------------------------------------------------------ | |
//write rectangles entries | |
//------------------------------------------------------ | |
void write_kikad_elements( UL_GATE G, int gatePos ) | |
{ | |
int transX = G.x/g_Fact; | |
int transY = G.y/g_Fact; | |
//Write the polygon entries | |
write_kikad_polygon( G, transX, transY, gatePos ); | |
//Write the arc and polygon (line) entries | |
write_kikad_arc_line( G, transX, transY, gatePos ); | |
//Write the rectangle entries | |
write_kikad_rectangle( G, transX, transY, gatePos ); | |
//Write the circle entries | |
write_kikad_circle( G, transX, transY, gatePos ); | |
//Write the text entries | |
write_kikad_text( G, transX, transY, gatePos ); | |
//Write the pin entries | |
write_kikad_pins( G, transX, transY, gatePos ); | |
} | |
//------------------------------------------------------ | |
//Write kicad alias entries | |
//------------------------------------------------------ | |
void write_kikad_def_alias( UL_DEVICESET DEV, UL_GATE G, string symbolName, int countPart ) | |
{ | |
int prefix_X = 0; | |
int prefix_Y = 0; | |
int name_X = 0; | |
int name_Y = 0; | |
char orient = 'H'; | |
char hAlign = 'C'; | |
char vAlign = 'C'; | |
string nameString = ""; | |
string prefixString = ""; | |
G.symbol.texts(T) | |
{ | |
if( T.value == ">VALUE" || T.value == ">NAME" ) | |
{ | |
int transX = G.x/g_Fact; | |
int transY = G.y/g_Fact; | |
int angle = T.angle; | |
int posX = 0; | |
int posY = 0; | |
int offset = 0; | |
switch( angle ) | |
{ | |
case 0: | |
orient = 'H'; | |
hAlign = 'L'; | |
vAlign = 'B'; | |
break; | |
case 90: | |
offset = -(T.size / 2)/g_Fact; | |
orient = 'V'; | |
hAlign = 'L'; | |
vAlign = 'B'; | |
break; | |
case 180: | |
orient = 'H'; | |
hAlign = 'R'; | |
vAlign = 'T'; | |
break; | |
case 270: | |
orient = 'V'; | |
hAlign = 'L'; | |
vAlign = 'B'; | |
break; | |
} | |
if( T.value == ">VALUE" ) | |
{ | |
name_X = T.x/g_Fact - transX + offset; | |
name_Y = T.y/g_Fact - transY; | |
} | |
if( T.value == ">NAME" ) | |
{ | |
prefix_X = T.x/g_Fact - transX + offset; | |
prefix_Y = T.y/g_Fact - transY; | |
} | |
} | |
} | |
if( DEV.prefix == "" ) | |
{ | |
if( DEV.name == "" ) | |
printf("F0 \"%s\" %d %d %d %c %c %c %c\n", symbolName, name_X, name_Y, 50, | |
orient, 'V', hAlign, vAlign); | |
} | |
else | |
{ | |
printf("F0 \"%s\" %d %d %d %c %c %c %c\n", DEV.prefix, prefix_X, prefix_Y, | |
50, orient, 'V', hAlign, vAlign); | |
if( DEV.name != "" ) | |
{ | |
printf("F1 \"%s\" %d %d %d %c %c %c %c\n", symbolName, name_X, name_Y, | |
50, orient, 'V', hAlign, vAlign); | |
printf("F2 \"%s-%s\" 0 150 50 H I C C\n", DEV.library, DEV.name); | |
} | |
} | |
} | |
//------------------------------------------------------ | |
//write lib header | |
//------------------------------------------------------ | |
void write_kikad_lib( string fileName ) | |
{ | |
// write INDEX start tag | |
//printf("######################################################################\n"); | |
//printf("# Name: %s\n", LIB.name); | |
//printf("# Headline: %s\n", LIB.headline); | |
//printf("######################################################################\n"); | |
int oneRun = 0; | |
output(fileName, "wt") | |
{ | |
if(library) | |
{ | |
library(LIB) | |
{ | |
int t = time(); | |
printf("EESchema-LIBRARY Version 2.3 %02d/%02d/%04d-%02d:%02d:%02d\n", | |
t2day(t), t2month(t)+1, t2year(t), t2hour(t), t2minute(t), t2second(t)); | |
// printf("# Converted with eagle2kicad.ulp Version %.1f\n", VERSION); | |
int countDevices = 0; | |
LIB.devices(DEV) | |
{ | |
countDevices++; | |
} | |
// printf("# Device count = %d\n", countDevices); | |
LIB.devicesets(DEVSET) | |
{ | |
int countGates = 0; | |
// retrieve amount of gates | |
DEVSET.gates(G) | |
{ | |
countGates++; | |
} | |
string nameString = DEVSET.name; | |
string prefixString = DEVSET.prefix; | |
string drawPinnumberStr = "N"; | |
string drawPinnameStr = "N"; | |
if (drawPinnumber) { | |
drawPinnumberStr = "Y"; | |
} | |
if (drawPinname) { | |
drawPinnameStr = "Y"; | |
} | |
// printf("#\n"); | |
// printf("# Dev Name: %s\n", nameString); | |
// if(DEV.package) | |
// printf("# Package Name: %s\n", DEV.package.name); | |
// printf("# Dev Tech: %s\n", DEV.technologies); | |
// printf("# Dev Prefix: %s\n", DEV.prefix); | |
// printf("# Gate count = %d\n", countGates); | |
// printf("#\n"); | |
// check for missing prefix | |
if( DEVSET.prefix == "" ) | |
{ | |
prefixString = "??"; | |
g_missingPrefix = 1; | |
} | |
printf("DEF %s %s %d %d %s %s %d %c %c\n", nameString, prefixString, 0, 40, drawPinnumberStr, drawPinnameStr, countGates, 'L', 'N'); | |
printf("$FPLIST\n"); | |
DEVSET.devices(DEV) | |
{ | |
printf(" %s\n", DEV.package.name); | |
printf(" %s-%s\n", DEV.library, DEV.package.name); | |
} | |
printf("$ENDFPLIST\n"); | |
int gatePos = 0; | |
DEVSET.devices(DEV) | |
{ | |
DEV.gates(G) | |
{ | |
gatePos++; | |
//printf("# Gate Name: %s\n",G.name); | |
//printf("# Symbol Name: %s\n", G.symbol.name); | |
if( gatePos == 1) { | |
// Write kicad alias entries | |
write_kikad_def_alias(DEVSET, G, nameString, gatePos ); | |
printf("DRAW\n"); | |
} | |
write_kikad_elements(G, gatePos); | |
} | |
break; | |
} | |
printf("ENDDRAW\n"); | |
printf("ENDDEF\n\n"); | |
} | |
// printf("#End Library\n"); | |
} | |
} | |
} | |
} | |
//------------------------------------------------------ | |
// Select the path where the modfile will be saved | |
//------------------------------------------------------ | |
void openModPath( string startPath ) | |
{ | |
string dirName = ""; | |
dirName = dlgDirectory("Select a directory", startPath); | |
if( dirName != "" ) | |
{ | |
library(L) | |
{ | |
L.devices(DEV) | |
{ | |
g_mod_name = dirName + "/" + DEV.library + ".mod"; | |
} | |
} | |
} | |
} | |
//------------------------------------------------------ | |
// Select the path where the libfile will be saved | |
//------------------------------------------------------ | |
void openLibPath( string startPath ) | |
{ | |
string dirName = ""; | |
dirName = dlgDirectory("Select a directory", startPath); | |
if( dirName != "" ) | |
{ | |
library(L) | |
{ | |
L.devices(DEV) | |
{ | |
g_lib_name = dirName + "/" + DEV.library + ".lib"; | |
} | |
} | |
} | |
} | |
//------------------------------------------------------ | |
// main program | |
//------------------------------------------------------ | |
int result; | |
string ref; | |
int sameDir = 0; | |
string titleString; | |
sprintf( titleString, "Export to KiCAD, Version %.1f", VERSION ); | |
if (library) | |
{ | |
library(L) | |
{ | |
L.devices(DEV) | |
{ | |
g_lib_prefix = DEV.library; | |
} | |
g_mod_name = strsub(L.name, 0, strlen(L.name) - 3) + "mod"; | |
g_lib_name = strsub(L.name, 0, strlen(L.name) - 3) + "lib"; | |
//g_lib_name = "G:/PCB-Tools/kicad/library/1test.lib"; | |
//g_lib_name = "/opt/kicad/library/" + g_lib_prefix + ".lib"; | |
//g_mod_name = "/opt/kicad/modules/" + g_lib_prefix + ".mod"; | |
} | |
} | |
else | |
{ | |
dlgMessageBox("Please run from library or board editor." ); | |
exit(EXIT_FAILURE); | |
} | |
result = dlgDialog( titleString ) | |
{ | |
dlgTabWidget | |
{ | |
//=====================TAB1============================================================= | |
dlgTabPage("Symbol:") | |
{ | |
dlgHBoxLayout dlgSpacing(400); | |
dlgStretch(0); | |
dlgLabel("Export to file:"); | |
dlgStretch(0); | |
dlgHBoxLayout | |
{ | |
dlgStringEdit(g_lib_name); | |
dlgPushButton("...") openLibPath("C:\\"); | |
} | |
dlgHBoxLayout | |
{ | |
dlgCheckBox("Draw pin &names", drawPinname); | |
dlgCheckBox("Draw pin n&umbers", drawPinnumber); | |
} | |
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("Package:") | |
{ | |
dlgHBoxLayout dlgSpacing(400); | |
dlgStretch(0); | |
dlgLabel("Export to file:"); | |
dlgStretch(0); | |
dlgHBoxLayout | |
{ | |
dlgStringEdit(g_mod_name); | |
dlgPushButton("...") openModPath("C:\\"); | |
} | |
dlgHBoxLayout | |
{ | |
//dlgCheckBox("&Same output directory", sameDir); | |
} | |
dlgVBoxLayout | |
{ | |
dlgStretch(0); | |
dlgHBoxLayout | |
{ | |
dlgStretch(1); | |
dlgPushButton("+OK") dlgAccept(); | |
dlgStretch(0); | |
} | |
dlgHBoxLayout | |
{ | |
dlgStretch(1); | |
dlgPushButton("-Cancel") dlgReject(); | |
dlgStretch(0); | |
} | |
dlgStretch(10); | |
}; | |
dlgStretch(1); | |
} | |
} | |
}; | |
if(result) | |
{ | |
write_kikad_mod(g_mod_name); | |
write_kikad_lib(g_lib_name); | |
// A success message is useful | |
dlgMessageBox("Conversion finished"); | |
} | |
// but a cancel message only confuses the user | |
// else | |
// dlgMessageBox("Canceled!" ); | |
if( g_missingPrefix == 1 ) | |
{ | |
string msgString = "Prefix is missing in a device. It will be replaced by \"??\".\n"; | |
msgString += "Please open the exported lib file with an text editor and replace the ?? with your prefix.\n"; | |
dlgMessageBox(msgString ); | |
} | |
exit(EXIT_SUCCESS); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment