kicad.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. /*
  2. * kicad.c - Dump objects in the KiCad board/module format
  3. *
  4. * Written 2009-2011 by Werner Almesberger
  5. * Copyright 2009-2011 by Werner Almesberger
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. */
  12. #include <stdlib.h>
  13. #include <stdio.h>
  14. #include <time.h>
  15. #include <assert.h>
  16. #include "coord.h"
  17. #include "inst.h"
  18. #include "kicad.h"
  19. static unit_type zeroize(unit_type n)
  20. {
  21. return n == -1 || n == 1 ? 0 : n;
  22. }
  23. static void kicad_centric(struct coord a, struct coord b,
  24. struct coord *center, struct coord *size)
  25. {
  26. struct coord min, max;
  27. min.x = units_to_kicad(a.x);
  28. min.y = units_to_kicad(a.y);
  29. max.x = units_to_kicad(b.x);
  30. max.y = units_to_kicad(b.y);
  31. sort_coord(&min, &max);
  32. size->x = max.x-min.x;
  33. size->y = max.y-min.y;
  34. center->x = (min.x+max.x)/2;
  35. center->y = -(min.y+max.y)/2;
  36. }
  37. static void do_drill(FILE *file, const struct inst *pad, struct coord *ref)
  38. {
  39. const struct inst *hole = pad->u.pad.hole;
  40. struct coord center, size;
  41. if (!hole)
  42. return;
  43. kicad_centric(hole->base, hole->u.hole.other, &center, &size);
  44. /* Allow for rounding errors */
  45. fprintf(file, "Dr %d %d %d", size.x,
  46. -zeroize(center.x-ref->x), -zeroize(center.y-ref->y));
  47. if (size.x < size.y-1 || size.x > size.y+1)
  48. fprintf(file, " O %d %d", size.x, size.y);
  49. fprintf(file, "\n");
  50. *ref = center;
  51. }
  52. static void kicad_pad(FILE *file, const struct inst *inst)
  53. {
  54. struct coord center, size;
  55. kicad_centric(inst->base, inst->u.pad.other, &center, &size);
  56. fprintf(file, "$PAD\n");
  57. /*
  58. * name, shape (rectangle), Xsize, Ysize, Xdelta, Ydelta, Orientation
  59. */
  60. fprintf(file, "Sh \"%s\" %c %d %d 0 0 0\n",
  61. inst->u.pad.name, inst->obj->u.pad.rounded ? 'O' : 'R',
  62. size.x, size.y);
  63. /*
  64. * Drill hole
  65. */
  66. do_drill(file, inst, &center);
  67. /*
  68. * Attributes: pad type, N, layer mask
  69. */
  70. fprintf(file, "At %s N %8.8X\n",
  71. inst->u.pad.hole ? "STD" : "SMD", (unsigned) inst->u.pad.layers);
  72. /*
  73. * Position: Xpos, Ypos
  74. */
  75. fprintf(file, "Po %d %d\n", center.x, center.y);
  76. fprintf(file, "$EndPAD\n");
  77. }
  78. static void kicad_hole(FILE *file, const struct inst *inst)
  79. {
  80. struct coord center, size;
  81. if (inst->u.hole.pad)
  82. return;
  83. kicad_centric(inst->base, inst->u.hole.other, &center, &size);
  84. fprintf(file, "$PAD\n");
  85. if (size.x < size.y-1 || size.x > size.y+1) {
  86. fprintf(file, "Sh \"HOLE\" O %d %d 0 0 0\n", size.x, size.y);
  87. fprintf(file, "Dr %d 0 0 O %d %d\n", size.x, size.x, size.y);
  88. } else {
  89. fprintf(file, "Sh \"HOLE\" C %d %d 0 0 0\n", size.x, size.x);
  90. fprintf(file, "Dr %d 0 0\n", size.x);
  91. }
  92. fprintf(file, "At HOLE N %8.8X\n", (unsigned) inst->u.hole.layers);
  93. fprintf(file, "Po %d %d\n", center.x, center.y);
  94. fprintf(file, "$EndPAD\n");
  95. }
  96. static void kicad_line(FILE *file, const struct inst *inst)
  97. {
  98. /*
  99. * Xstart, Ystart, Xend, Yend, Width, Layer
  100. */
  101. fprintf(file, "DS %d %d %d %d %d %d\n",
  102. units_to_kicad(inst->base.x),
  103. -units_to_kicad(inst->base.y),
  104. units_to_kicad(inst->u.rect.end.x),
  105. -units_to_kicad(inst->u.rect.end.y),
  106. units_to_kicad(inst->u.rect.width),
  107. layer_silk_top);
  108. }
  109. static void kicad_rect(FILE *file, const struct inst *inst)
  110. {
  111. unit_type xa, ya, xb, yb;
  112. unit_type width;
  113. xa = units_to_kicad(inst->base.x);
  114. ya = units_to_kicad(inst->base.y);
  115. xb = units_to_kicad(inst->u.rect.end.x);
  116. yb = units_to_kicad(inst->u.rect.end.y);
  117. width = units_to_kicad(inst->u.rect.width);
  118. fprintf(file, "DS %d %d %d %d %d %d\n",
  119. xa, -ya, xa, -yb, width, layer_silk_top);
  120. fprintf(file, "DS %d %d %d %d %d %d\n",
  121. xa, -yb, xb, -yb, width, layer_silk_top);
  122. fprintf(file, "DS %d %d %d %d %d %d\n",
  123. xb, -yb, xb, -ya, width, layer_silk_top);
  124. fprintf(file, "DS %d %d %d %d %d %d\n",
  125. xb, -ya, xa, -ya, width, layer_silk_top);
  126. }
  127. static void kicad_circ(FILE *file, const struct inst *inst)
  128. {
  129. /*
  130. * Xcenter, Ycenter, Xpoint, Ypoint, Width, Layer
  131. */
  132. fprintf(file, "DC %d %d %d %d %d %d\n",
  133. units_to_kicad(inst->base.x),
  134. -units_to_kicad(inst->base.y),
  135. units_to_kicad(inst->base.x),
  136. -units_to_kicad(inst->base.y+inst->u.arc.r),
  137. units_to_kicad(inst->u.arc.width),
  138. layer_silk_top);
  139. }
  140. static void kicad_arc(FILE *file, const struct inst *inst)
  141. {
  142. struct coord p;
  143. double a;
  144. /*
  145. * The documentation says:
  146. * Xstart, Ystart, Xend, Yend, Angle, Width, Layer
  147. *
  148. * But it's really:
  149. * Xcenter, Ycenter, Xend, Yend, ...
  150. */
  151. p = rotate_r(inst->base, inst->u.arc.r, inst->u.arc.a2);
  152. a = inst->u.arc.a2-inst->u.arc.a1;
  153. while (a <= 0)
  154. a += 360;
  155. while (a > 360)
  156. a -= 360;
  157. fprintf(file, "DA %d %d %d %d %d %d %d\n",
  158. units_to_kicad(inst->base.x),
  159. -units_to_kicad(inst->base.y),
  160. units_to_kicad(p.x),
  161. -units_to_kicad(p.y),
  162. (int) (a*10.0),
  163. units_to_kicad(inst->u.arc.width),
  164. layer_silk_top);
  165. }
  166. static void kicad_inst(FILE *file, enum inst_prio prio, const struct inst *inst)
  167. {
  168. switch (prio) {
  169. case ip_pad_copper:
  170. case ip_pad_special:
  171. kicad_pad(file, inst);
  172. break;
  173. case ip_hole:
  174. kicad_hole(file, inst);
  175. break;
  176. case ip_line:
  177. kicad_line(file, inst);
  178. break;
  179. case ip_rect:
  180. kicad_rect(file, inst);
  181. break;
  182. case ip_circ:
  183. kicad_circ(file, inst);
  184. break;
  185. case ip_arc:
  186. kicad_arc(file, inst);
  187. break;
  188. default:
  189. /*
  190. * Don't try to export vectors, frame references, or
  191. * measurements.
  192. */
  193. break;
  194. }
  195. }
  196. static void kicad_module(FILE *file, const struct pkg *pkg, time_t now)
  197. {
  198. enum inst_prio prio;
  199. const struct inst *inst;
  200. /*
  201. * Module library name
  202. */
  203. fprintf(file, "$MODULE %s\n", pkg->name);
  204. /*
  205. * Xpos = 0, Ypos = 0, 15 layers, last modification, timestamp,
  206. * moveable, not autoplaced.
  207. */
  208. fprintf(file, "Po 0 0 0 15 %8.8lX 00000000 ~~\n", (long) now);
  209. /*
  210. * Module library name again
  211. */
  212. fprintf(file, "Li %s\n", pkg->name);
  213. #if 0 /* optional */
  214. /*
  215. * Description
  216. */
  217. fprintf(file, "Cd %s\n", pkg->name);
  218. #endif
  219. /*
  220. *
  221. */
  222. fprintf(file, "Sc %8.8lX\n", (long) now);
  223. /*
  224. * Attributes: SMD = listed in the automatic insertion list
  225. */
  226. fprintf(file, "At SMD\n");
  227. /*
  228. * Rotation cost: 0 for 90 deg, 0 for 180 deg, 0 = disable rotation
  229. */
  230. fprintf(file, "Op 0 0 0\n");
  231. /*
  232. * Text fields: Tn = field number, Xpos, Ypos, Xsize ("emspace"),
  233. * Ysize ("emspace"), rotation, pen width, N (none), V = visible,
  234. * comment layer. All dimensions are 1/10 mil.
  235. */
  236. fprintf(file, "T0 0 -150 200 200 0 40 N V %d \"%s\"\n",
  237. layer_comment, pkg->name);
  238. fprintf(file, "T1 0 150 200 200 0 40 N I %d \"Val*\"\n",
  239. layer_comment);
  240. FOR_INST_PRIOS_UP(prio) {
  241. for (inst = pkgs->insts[prio]; inst; inst = inst->next)
  242. kicad_inst(file, prio, inst);
  243. for (inst = pkg->insts[prio]; inst; inst = inst->next)
  244. kicad_inst(file, prio, inst);
  245. }
  246. fprintf(file, "$EndMODULE %s\n", pkg->name);
  247. }
  248. int kicad(FILE *file, const char *one)
  249. {
  250. const struct pkg *pkg;
  251. time_t now = time(NULL);
  252. assert(!one);
  253. fprintf(file, "PCBNEW-LibModule-V1 %s", ctime(&now));
  254. fprintf(file, "$INDEX\n");
  255. for (pkg = pkgs; pkg; pkg = pkg->next)
  256. if (pkg->name)
  257. fprintf(file, "%s\n", pkg->name);
  258. fprintf(file, "$EndINDEX\n");
  259. for (pkg = pkgs; pkg; pkg = pkg->next)
  260. if (pkg->name)
  261. kicad_module(file, pkg, now);
  262. fprintf(file, "$EndLIBRARY\n");
  263. fflush(file);
  264. return !ferror(file);
  265. }