Root/kicad.c

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

Archive Download this file

Branches:
master



interactive