Date:2017-01-22 14:39:07 (1 year 10 months ago)
Author:--- erichvk
Commit:7081258910b767841129be93bff3c971d8db6cf1
Message:diff for gEDA PCB export in fped

I have

1) sorted out the tabbing

2) simplified > 1 element export by exporting elements in a layout (.pcb)

3) documented incompatibilities in the README

4) done it as a diff against origin master

let me know if you need anything else done

Cheers.

Erich

From dae69d9a63071a15c213c72e70b86fe963a67dd4 Mon Sep 17 00:00:00 2001
From: erich_heinzle <a1039181@gmail.com>
Date: Sun, 22 Jan 2017 23:48:57 +1030
Subject: [PATCH] support for export to gEDA format of single and multiple
footprints in a .pcb layout
Files: Makefile (2 diffs)
README (1 diff)
coord.c (1 diff)
coord.h (3 diffs)
file.c (3 diffs)
file.h (2 diffs)
geda.c (1 diff)
geda.h (1 diff)
gui.c (2 diffs)

Change Details

Makefile
33#
44# Written 2009-2012, 2015 by Werner Almesberger
55# Copyright 2009-2012, 2015 by Werner Almesberger
6# Copyright 2016, Erich Heinzle (gEDA additions)
67#
78# This program is free software; you can redistribute it and/or modify
89# it under the terms of the GNU General Public License as published by
...... 
1516UPLOAD = www-data@downloads.qi-hardware.com:werner/fped/
1617
1718OBJS = fped.o expr.o coord.o obj.o delete.o inst.o util.o error.o \
18       unparse.o file.o dump.o kicad.o postscript.o gnuplot.o meas.o \
19       unparse.o file.o dump.o kicad.o geda.o postscript.o gnuplot.o meas.o \
1920       layer.o overlap.o hole.o tsort.o bitset.o \
2021       cpp.o lex.yy.o y.tab.o \
2122       gui.o gui_util.o gui_style.o gui_inst.o gui_status.o gui_canvas.o \
README
8181process and verificative measurements helps efficient and accurate
8282review.
8383
84Leveraging the work already done, and growing the intellectual commons
85of available footprints has motivated the addition of an export to gEDA
86pcb format option. Single or multiple footprints are exported in a
87gEDA PCB layout (.pcb) file. A select all command can be used, followed
88by a "disperse elements" command, to allow viewing of multiple elements
89in the gEDA layout editor. An element can then be selected, cut to
90buffer, and exported to a footprint (.fp) file with the usual menu
91commands.
92
93gEDA PCB format footprints are exported in centimil units. Pads with
94offset centre holes are not faithfully reproduced; the pad is exported
95with minimum dimensions and centred on the hole. Trapezoidal and
96roundrect pads are not supported in gEDA.
8497
8598Footprint definition file format
8699--------------------------------
coord.c
33 *
44 * Written 2009, 2010, 2016 by Werner Almesberger
55 * Copyright 2009, 2010, 2016 by Werner Almesberger
6 * Copyright 2016, Erich Heinzle (gEDA additions)
67 *
78 * This program is free software; you can redistribute it and/or modify
89 * it under the terms of the GNU General Public License as published by
coord.h
33 *
44 * Written 2009, 2010, 2016 by Werner Almesberger
55 * Copyright 2009, 2010, 2016 by Werner Almesberger
6 * Copyright 2016, Erich Heinzle (gEDA additions)
67 *
78 * This program is free software; you can redistribute it and/or modify
89 * it under the terms of the GNU General Public License as published by
...... 
2223#define MM_UNITS (1000.0*MICRON_UNITS)
2324#define UM_UNITS MICRON_UNITS
2425#define KICAD_UNIT (MIL_UNITS/10.0)
26#define GEDA_UNIT (MIL_UNITS/100.0)
2527
2628#define MIL_IN_MM 0.0254
2729#define UM_IN_MM 0.001
...... 
7981    return (double) u/KICAD_UNIT;
8082}
8183
84static inline int units_to_geda(unit_type u)
85{
86    return (double) u/GEDA_UNIT;
87}
8288
8389static inline int coord_eq(struct coord a, struct coord b)
8490{
file.c
33 *
44 * Written 2009-2012 by Werner Almesberger
55 * Copyright 2009-2012 by Werner Almesberger
6 * Copyright 2016, Erich Heinzle (gEDA additions)
67 *
78 * This program is free software; you can redistribute it and/or modify
89 * it under the terms of the GNU General Public License as published by
...... 
1920
2021#include "dump.h"
2122#include "kicad.h"
23#include "geda.h"
2224#include "postscript.h"
2325#include "gnuplot.h"
2426#include "util.h"
...... 
171173    }
172174}
173175
176void write_geda(void)
177{
178    char *name;
179
180    if (save_file_name) {
181        name = set_extension(save_file_name, "pcb");
182        save_to(name, geda, NULL);
183        free(name);
184    } else {
185        if (!geda(stdout, NULL))
186        perror("stdout");
187    }
188}
189
174190
175191static void do_write_ps(int (*fn)(FILE *file, const char *one),
176192    const char *one)
file.h
33 *
44 * Written 2009-2011 by Werner Almesberger
55 * Copyright 2009-2011 by Werner Almesberger
6 * Copyright 2016, Erich Heinzle (gEDA additions)
67 *
78 * This program is free software; you can redistribute it and/or modify
89 * it under the terms of the GNU General Public License as published by
...... 
3031
3132void save_fpd(void);
3233void write_kicad(void);
34void write_geda(void);
3335void write_ps(const char *one);
3436void write_ps_fullpage(const char *one);
3537void write_gnuplot(const char *one);
geda.c
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}
geda.h
1/*
2 * geda_pcb.h - Dump objects in the gEDA PCB board/module format
3 *
4 * Written 2009, 2011 by Werner Almesberger, 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#ifndef GEDA_H
16#define GEDA_H
17
18#include <stdio.h>
19
20
21int geda(FILE *file, const char *one);
22
23#endif /* !GEDA_H */
gui.c
33 *
44 * Written 2009-2012, 2015-2016 by Werner Almesberger
55 * Copyright 2009-2012, 2015-2016 by Werner Almesberger
6 * Copyright 2016, Erich Heinzle (gEDA additions)
67 *
78 * This program is free software; you can redistribute it and/or modify
89 * it under the terms of the GNU General Public License as published by
...... 
149150    { "/File/Save as", NULL, save_as_fpd, 0, "<Item>" },
150151        { "/File/sep1", NULL, NULL, 0, "<Separator>" },
151152        { "/File/Write KiCad", NULL, write_kicad, 0, "<Item>" },
153    { "/File/Write gEDA", NULL, write_geda, 0, "<Item>" },
152154        { "/File/Write Postscript",
153155                NULL, write_ps, 0, "<Item>" },
154156        { "/File/sep2", NULL, NULL, 0, "<Separator>" },

Archive Download the corresponding diff file

Branches:
master



interactive