Root/geda.c

Source at commit 7081258910b767841129be93bff3c971d8db6cf1 created 2 years 9 months ago.
By Erich Heinzle, diff for gEDA PCB export in fped
1/*
2 * geda.c - Dump objects in the gEDA PCB board/module format
3 *
4 * Written 2009, 2011 by Werner Almesberger, and 2016 by Erich Heinzle
5 * Copyright 2009, 2011 by Werner Almesberger
6 * Copyright 2016, Erich Heinzle
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 */
13
14
15#include <stdlib.h>
16#include <stdio.h>
17#include <assert.h>
18
19#include "coord.h"
20#include "inst.h"
21#include "geda.h"
22
23
24static void geda_centric(struct coord a, struct coord b,
25    struct coord *center, struct coord *size)
26{
27    struct coord min, max;
28
29    min.x = units_to_geda(a.x);
30    min.y = units_to_geda(a.y);
31    max.x = units_to_geda(b.x);
32    max.y = units_to_geda(b.y);
33
34    sort_coord(&min, &max);
35
36    size->x = max.x-min.x;
37    size->y = max.y-min.y;
38    center->x = (min.x+max.x)/2;
39    center->y = -(min.y+max.y)/2;
40}
41
42static unit_type geda_pad_width(struct coord size)
43{
44    if (size.x >= size.y) {
45        return size.y;
46    } else {
47        return size.x;
48    }
49}
50
51static void geda_pad_start_finish(struct coord a, struct coord b,
52    struct coord *start, struct coord *finish)
53{
54        struct coord size, center, min, max;
55
56        min.x = units_to_geda(a.x);
57        min.y = units_to_geda(a.y);
58        max.x = units_to_geda(b.x);
59        max.y = units_to_geda(b.y);
60
61        sort_coord(&min, &max);
62
63        size.x = max.x-min.x;
64        size.y = max.y-min.y;
65        center.x = (min.x+max.x)/2;
66        center.y = -(min.y+max.y)/2;
67    /* gEDA pads are drawn as a line, of a certain thickness */
68    if (size.x >= size.y) { /* wider than tall, width = size.y */
69        start->x = min.x + size.y/2;
70        start->y = -center.y;
71        finish->x = max.x - size.y/2;
72        finish->y = -center.y;
73    } else { /* taller than wide, width = size.x */
74        start->y = (min.y + size.x/2);
75            start->x = center.x;
76            finish->y = (max.y - size.x/2);
77            finish->x = center.x;
78    }
79}
80
81static void do_geda_drill(FILE *file, const struct inst *pad, struct coord *padSize)
82{
83    const struct inst *hole = pad->u.pad.hole;
84    struct coord center, size;
85    
86    if (!hole)
87        return;
88
89    geda_centric(hole->base, hole->u.hole.other, &center, &size);
90
91    fprintf(file, "%d %d ", center.x, -center.y); /* x,y position of hole */
92    if (padSize->x <= padSize->y) { /* sort out diameter of copper annulus, remembering obrounds*/
93        fprintf(file, "%d ", padSize->x);
94    } else {
95        fprintf(file, "%d ", padSize->y);
96    }
97    fprintf(file, "100 100 %d", size.x); /* default copper clearance, mask, then drill size */
98}
99
100
101static void geda_pad(FILE *file, const struct inst *inst)
102{
103    struct coord center, size, start, finish;
104
105    geda_centric(inst->base, inst->u.pad.other, &center, &size);
106
107    if (inst->u.pad.hole) { /* pin */
108        /* Pin[X Y Thickness Clearance Mask Drill Name Number SFlags] */
109        fprintf(file, "\tPin[");
110        do_geda_drill(file, inst, &size); /* need pad size to figure out annulus */
111        fprintf(file, " \"%s\" \"%s\"", inst->u.pad.name, inst->u.pad.name);
112        if (inst->obj->u.pad.rounded) { /* round pin */
113            fprintf(file, " \"\"]\n");
114        } else { /* square pad, ignore octagonal for now */
115            fprintf(file, " \"square\"]\n");
116        }
117    } else { /* SMD */
118        /* Pad[X1 Y1 X2 Y2 Thickness Clearance Mask Name Number SFlags] */
119        geda_pad_start_finish(inst->base, inst->u.pad.other, &start, &finish);
120        fprintf(file, "\tPad[%d %d %d %d %d 100 100 \"%s\" \"%s\" \"square\"]\n", start.x, -start.y, finish.x, -finish.y, geda_pad_width(size), inst->u.pad.name, inst->u.pad.name);
121    }
122}
123
124
125static void geda_hole(FILE *file, const struct inst *inst)
126{
127    struct coord center, size;
128    if (inst->u.hole.pad)
129        return;
130    geda_centric(inst->base, inst->u.hole.other, &center, &size);
131
132    /* Pin[X Y Thickness Clearance Mask Drill Name Number SFlags] */
133
134    fprintf(file, "\tPin[%d %d", center.x, center.y);
135    if (size.x <= size.y) { /* see which obround dimension is smallest */
136        fprintf(file, " %d 100 100 %d", size.x, size.x);
137        /* obround hole turned into round hole of diameter size.x */
138    } else {
139        fprintf(file, " %d 100 100 %d", size.y, size.y);
140        /* obround hole turned into round hole of diameter size.y */
141    }
142    fprintf(file, " \"\" \"\" \"hole\"]\n");
143}
144
145static void geda_line(FILE *file, const struct inst *inst)
146{
147    /*
148     * Xstart, Ystart, Xend, Yend, Width
149     */
150    fprintf(file, "\tElementLine[%d %d %d %d %d]\n",
151        units_to_geda(inst->base.x),
152        -units_to_geda(inst->base.y),
153        units_to_geda(inst->u.rect.end.x),
154        -units_to_geda(inst->u.rect.end.y),
155        units_to_geda(inst->u.rect.width));
156}
157
158
159static void geda_rect(FILE *file, const struct inst *inst)
160{
161    unit_type xa, ya, xb, yb;
162    unit_type width;
163
164    xa = units_to_geda(inst->base.x);
165    ya = units_to_geda(inst->base.y);
166    xb = units_to_geda(inst->u.rect.end.x);
167    yb = units_to_geda(inst->u.rect.end.y);
168    width = units_to_geda(inst->u.rect.width);
169
170    fprintf(file, "\tElementLine[%d %d %d %d %d]\n",
171        xa, -ya, xa, -yb, width);
172    fprintf(file, "\tElementLine[%d %d %d %d %d]\n",
173        xa, -yb, xb, -yb, width);
174    fprintf(file, "\tElementLine[%d %d %d %d %d]\n",
175        xb, -yb, xb, -ya, width);
176    fprintf(file, "\tElementLine[%d %d %d %d %d]\n",
177        xb, -ya, xa, -ya, width);
178}
179
180
181static void geda_circ(FILE *file, const struct inst *inst)
182{
183    /*
184     * Xcenter, Ycenter, Width, Height, startAngle, stopAngle, Width
185     */
186    fprintf(file, "\tElementArc[ %d %d %d %d 0 360 %d]\n",
187        units_to_geda(inst->base.x),
188        -units_to_geda(inst->base.y),
189        units_to_geda(inst->u.arc.r),
190            units_to_geda(inst->u.arc.r),
191        units_to_geda(inst->u.arc.width));
192}
193
194
195static void geda_arc(FILE *file, const struct inst *inst)
196{
197    double b;
198
199    /*
200     * Xcenter, Ycenter, Width, Height, startAngle, stopAngle, Width
201     *
202     */
203    b = inst->u.arc.a1 - 180;
204    while (b <= 0)
205        b += 360;
206    while (b > 360)
207        b -= 360;
208    fprintf(file, "\tElementArc[%d %d %d %d %d %d %d]\n",
209        units_to_geda(inst->base.x),
210        -units_to_geda(inst->base.y),
211            units_to_geda(inst->u.arc.r),
212            units_to_geda(inst->u.arc.r),
213        (int) b,
214        (int) (inst->u.arc.a2-inst->u.arc.a1),
215        units_to_geda(inst->u.arc.width));
216}
217
218static void geda_layout_header(FILE *file)
219{
220    fprintf(file, "# release: pcb 20110918\n\n");
221    fprintf(file, "# To read pcb files, the pcb version (or the git source date) must be >= the file version\n");
222    fprintf(file, "FileVersion[20070407]\n\n");
223    fprintf(file, "PCB[\"\" 600000 500000]\n\n");
224    fprintf(file, "Grid[2500.0 0 0 1]\n");
225    fprintf(file, "Cursor[2500 62500 0.000000]\n");
226    fprintf(file, "PolyArea[3100.006200]\n");
227    fprintf(file, "Thermal[0.500000]\n");
228    fprintf(file, "DRC[1200 900 1000 700 1500 1000]\n");
229    fprintf(file, "Flags(\"nameonpcb,clearnew,snappin\")\n");
230    fprintf(file, "Groups(\"1,3,4,c:2,5,6,s:7:8\")\n");
231    fprintf(file, "Styles[\"Signal,1000,7874,3150,2000:Power,2000,8661,3937,2000:Fat,8000,13780,4724,2500:Sig-tight,1000,6400,3150,1200\"]\n\n");
232    fprintf(file, "Attribute(\"PCB::grid::unit\" \"mil\")");
233}
234
235static void geda_layout_footer(FILE *file)
236{
237    fprintf(file, "Layer(1 \"component\")\n(\n)\n");
238    fprintf(file, "Layer(2 \"solder\")\n(\n)\n");
239    fprintf(file, "Layer(3 \"comp-GND\")\n(\n)\n");
240    fprintf(file, "Layer(4 \"comp-power\")\n(\n)\n");
241    fprintf(file, "Layer(5 \"sold-GND\")\n(\n)\n");
242    fprintf(file, "Layer(6 \"sold-power\")\n(\n)\n");
243    fprintf(file, "Layer(7 \"signal3\")\n(\n)\n");
244    fprintf(file, "Layer(8 \"outline\")\n(\n)\n");
245    fprintf(file, "Layer(9 \"silk\")\n(\n)\n");
246    fprintf(file, "Layer(10 \"silk\")\n(\n)\n");
247}
248
249static void geda_inst(FILE *file, enum inst_prio prio, const struct inst *inst)
250{
251    switch (prio) {
252    case ip_pad_copper:
253    case ip_pad_special:
254        geda_pad(file, inst);
255        break;
256    case ip_hole:
257        geda_hole(file, inst); /* obround is exported as a round circle */
258        break;
259    case ip_line:
260        geda_line(file, inst);
261        break;
262    case ip_rect:
263        geda_rect(file, inst);
264        break;
265    case ip_circ:
266        geda_circ(file, inst);
267        break;
268    case ip_arc:
269        geda_arc(file, inst);
270        break;
271    default:
272        /*
273         * Don't try to export vectors, frame references, or
274         * measurements.
275         */
276        break;
277    }
278}
279
280
281static void geda_module(FILE *file, const struct pkg *pkg, time_t now)
282{
283    enum inst_prio prio;
284    const struct inst *inst;
285
286    fprintf(file, "# Footprint generated by FPED utility\n");
287    fprintf(file, "Element[\"\" \"%s\" \"\" \"\" 0 0 -25590 -14874 0 100 \"\"]\n", pkg->name);
288    fprintf(file, "(\n");
289
290    FOR_INST_PRIOS_UP(prio) {
291        for (inst = pkgs->insts[prio]; inst; inst = inst->next)
292            geda_inst(file, prio, inst);
293        for (inst = pkg->insts[prio]; inst; inst = inst->next)
294            geda_inst(file, prio, inst);
295    }
296
297    fprintf(file, ")\n\n"); /* extra newline between elements */
298}
299
300
301int geda(FILE *file, const char *one)
302{
303    const struct pkg *pkg;
304    time_t now = time(NULL);
305
306    assert(!one);
307
308    geda_layout_header(file); /* we place one or more elements in a layout file */
309
310    for (pkg = pkgs; pkg; pkg = pkg->next)
311        if (pkg->name)
312            fprintf(file, "# %s\n", pkg->name);
313
314    for (pkg = pkgs; pkg; pkg = pkg->next)
315        if (pkg->name)
316            geda_module(file, pkg, now);
317
318    geda_layout_footer(file);
319
320    fflush(file);
321    return !ferror(file);
322}
323

Archive Download this file

Branches:
master



interactive