123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- /*
- * kicad.c - Dump objects in the KiCad board/module format
- *
- * Written 2009-2011 by Werner Almesberger
- * Copyright 2009-2011 by Werner Almesberger
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <time.h>
- #include <assert.h>
- #include "coord.h"
- #include "inst.h"
- #include "kicad.h"
- static unit_type zeroize(unit_type n)
- {
- return n == -1 || n == 1 ? 0 : n;
- }
- static void kicad_centric(struct coord a, struct coord b,
- struct coord *center, struct coord *size)
- {
- struct coord min, max;
- min.x = units_to_kicad(a.x);
- min.y = units_to_kicad(a.y);
- max.x = units_to_kicad(b.x);
- max.y = units_to_kicad(b.y);
- sort_coord(&min, &max);
- size->x = max.x-min.x;
- size->y = max.y-min.y;
- center->x = (min.x+max.x)/2;
- center->y = -(min.y+max.y)/2;
- }
- static void do_drill(FILE *file, const struct inst *pad, struct coord *ref)
- {
- const struct inst *hole = pad->u.pad.hole;
- struct coord center, size;
- if (!hole)
- return;
- kicad_centric(hole->base, hole->u.hole.other, ¢er, &size);
- /* Allow for rounding errors */
- fprintf(file, "Dr %d %d %d", size.x,
- -zeroize(center.x-ref->x), -zeroize(center.y-ref->y));
- if (size.x < size.y-1 || size.x > size.y+1)
- fprintf(file, " O %d %d", size.x, size.y);
- fprintf(file, "\n");
- *ref = center;
- }
- static void kicad_pad(FILE *file, const struct inst *inst)
- {
- struct coord center, size;
- kicad_centric(inst->base, inst->u.pad.other, ¢er, &size);
- fprintf(file, "$PAD\n");
- /*
- * name, shape (rectangle), Xsize, Ysize, Xdelta, Ydelta, Orientation
- */
- fprintf(file, "Sh \"%s\" %c %d %d 0 0 0\n",
- inst->u.pad.name, inst->obj->u.pad.rounded ? 'O' : 'R',
- size.x, size.y);
- /*
- * Drill hole
- */
- do_drill(file, inst, ¢er);
- /*
- * Attributes: pad type, N, layer mask
- */
- fprintf(file, "At %s N %8.8X\n",
- inst->u.pad.hole ? "STD" : "SMD", (unsigned) inst->u.pad.layers);
- /*
- * Position: Xpos, Ypos
- */
- fprintf(file, "Po %d %d\n", center.x, center.y);
- fprintf(file, "$EndPAD\n");
- }
- static void kicad_hole(FILE *file, const struct inst *inst)
- {
- struct coord center, size;
- if (inst->u.hole.pad)
- return;
- kicad_centric(inst->base, inst->u.hole.other, ¢er, &size);
- fprintf(file, "$PAD\n");
- if (size.x < size.y-1 || size.x > size.y+1) {
- fprintf(file, "Sh \"HOLE\" O %d %d 0 0 0\n", size.x, size.y);
- fprintf(file, "Dr %d 0 0 O %d %d\n", size.x, size.x, size.y);
- } else {
- fprintf(file, "Sh \"HOLE\" C %d %d 0 0 0\n", size.x, size.x);
- fprintf(file, "Dr %d 0 0\n", size.x);
- }
- fprintf(file, "At HOLE N %8.8X\n", (unsigned) inst->u.hole.layers);
- fprintf(file, "Po %d %d\n", center.x, center.y);
- fprintf(file, "$EndPAD\n");
- }
- static void kicad_line(FILE *file, const struct inst *inst)
- {
- /*
- * Xstart, Ystart, Xend, Yend, Width, Layer
- */
- fprintf(file, "DS %d %d %d %d %d %d\n",
- units_to_kicad(inst->base.x),
- -units_to_kicad(inst->base.y),
- units_to_kicad(inst->u.rect.end.x),
- -units_to_kicad(inst->u.rect.end.y),
- units_to_kicad(inst->u.rect.width),
- layer_silk_top);
- }
- static void kicad_rect(FILE *file, const struct inst *inst)
- {
- unit_type xa, ya, xb, yb;
- unit_type width;
- xa = units_to_kicad(inst->base.x);
- ya = units_to_kicad(inst->base.y);
- xb = units_to_kicad(inst->u.rect.end.x);
- yb = units_to_kicad(inst->u.rect.end.y);
- width = units_to_kicad(inst->u.rect.width);
- fprintf(file, "DS %d %d %d %d %d %d\n",
- xa, -ya, xa, -yb, width, layer_silk_top);
- fprintf(file, "DS %d %d %d %d %d %d\n",
- xa, -yb, xb, -yb, width, layer_silk_top);
- fprintf(file, "DS %d %d %d %d %d %d\n",
- xb, -yb, xb, -ya, width, layer_silk_top);
- fprintf(file, "DS %d %d %d %d %d %d\n",
- xb, -ya, xa, -ya, width, layer_silk_top);
- }
- static void kicad_circ(FILE *file, const struct inst *inst)
- {
- /*
- * Xcenter, Ycenter, Xpoint, Ypoint, Width, Layer
- */
- fprintf(file, "DC %d %d %d %d %d %d\n",
- units_to_kicad(inst->base.x),
- -units_to_kicad(inst->base.y),
- units_to_kicad(inst->base.x),
- -units_to_kicad(inst->base.y+inst->u.arc.r),
- units_to_kicad(inst->u.arc.width),
- layer_silk_top);
- }
- static void kicad_arc(FILE *file, const struct inst *inst)
- {
- struct coord p;
- double a;
- /*
- * The documentation says:
- * Xstart, Ystart, Xend, Yend, Angle, Width, Layer
- *
- * But it's really:
- * Xcenter, Ycenter, Xend, Yend, ...
- */
- p = rotate_r(inst->base, inst->u.arc.r, inst->u.arc.a2);
- a = inst->u.arc.a2-inst->u.arc.a1;
- while (a <= 0)
- a += 360;
- while (a > 360)
- a -= 360;
- fprintf(file, "DA %d %d %d %d %d %d %d\n",
- units_to_kicad(inst->base.x),
- -units_to_kicad(inst->base.y),
- units_to_kicad(p.x),
- -units_to_kicad(p.y),
- (int) (a*10.0),
- units_to_kicad(inst->u.arc.width),
- layer_silk_top);
- }
- static void kicad_inst(FILE *file, enum inst_prio prio, const struct inst *inst)
- {
- switch (prio) {
- case ip_pad_copper:
- case ip_pad_special:
- kicad_pad(file, inst);
- break;
- case ip_hole:
- kicad_hole(file, inst);
- break;
- case ip_line:
- kicad_line(file, inst);
- break;
- case ip_rect:
- kicad_rect(file, inst);
- break;
- case ip_circ:
- kicad_circ(file, inst);
- break;
- case ip_arc:
- kicad_arc(file, inst);
- break;
- default:
- /*
- * Don't try to export vectors, frame references, or
- * measurements.
- */
- break;
- }
- }
- static void kicad_module(FILE *file, const struct pkg *pkg, time_t now)
- {
- enum inst_prio prio;
- const struct inst *inst;
- /*
- * Module library name
- */
- fprintf(file, "$MODULE %s\n", pkg->name);
- /*
- * Xpos = 0, Ypos = 0, 15 layers, last modification, timestamp,
- * moveable, not autoplaced.
- */
- fprintf(file, "Po 0 0 0 15 %8.8lX 00000000 ~~\n", (long) now);
- /*
- * Module library name again
- */
- fprintf(file, "Li %s\n", pkg->name);
- #if 0 /* optional */
- /*
- * Description
- */
- fprintf(file, "Cd %s\n", pkg->name);
- #endif
- /*
- *
- */
- fprintf(file, "Sc %8.8lX\n", (long) now);
- /*
- * Attributes: SMD = listed in the automatic insertion list
- */
- fprintf(file, "At SMD\n");
- /*
- * Rotation cost: 0 for 90 deg, 0 for 180 deg, 0 = disable rotation
- */
- fprintf(file, "Op 0 0 0\n");
- /*
- * Text fields: Tn = field number, Xpos, Ypos, Xsize ("emspace"),
- * Ysize ("emspace"), rotation, pen width, N (none), V = visible,
- * comment layer. All dimensions are 1/10 mil.
- */
- fprintf(file, "T0 0 -150 200 200 0 40 N V %d \"%s\"\n",
- layer_comment, pkg->name);
- fprintf(file, "T1 0 150 200 200 0 40 N I %d \"Val*\"\n",
- layer_comment);
- FOR_INST_PRIOS_UP(prio) {
- for (inst = pkgs->insts[prio]; inst; inst = inst->next)
- kicad_inst(file, prio, inst);
- for (inst = pkg->insts[prio]; inst; inst = inst->next)
- kicad_inst(file, prio, inst);
- }
- fprintf(file, "$EndMODULE %s\n", pkg->name);
- }
- int kicad(FILE *file, const char *one)
- {
- const struct pkg *pkg;
- time_t now = time(NULL);
- assert(!one);
- fprintf(file, "PCBNEW-LibModule-V1 %s", ctime(&now));
- fprintf(file, "$INDEX\n");
- for (pkg = pkgs; pkg; pkg = pkg->next)
- if (pkg->name)
- fprintf(file, "%s\n", pkg->name);
- fprintf(file, "$EndINDEX\n");
- for (pkg = pkgs; pkg; pkg = pkg->next)
- if (pkg->name)
- kicad_module(file, pkg, now);
- fprintf(file, "$EndLIBRARY\n");
- fflush(file);
- return !ferror(file);
- }
|