1
0
mirror of git://projects.qi-hardware.com/fped.git synced 2024-11-22 13:14:04 +02:00

- added KiCad output

- when saving a file, we now make a backup of any existing file with the same
  name



git-svn-id: http://svn.openmoko.org/trunk/eda/fped@5416 99fdad57-331a-0410-800a-d7fa5415bdb3
This commit is contained in:
werner 2009-08-10 21:02:26 +00:00
parent a0f8375c97
commit 6f307d6ae7
8 changed files with 410 additions and 44 deletions

View File

@ -11,7 +11,7 @@
# #
OBJS = fped.o expr.o coord.o obj.o delete.o inst.o util.o error.o \ OBJS = fped.o expr.o coord.o obj.o delete.o inst.o util.o error.o \
unparse.o dump.o meas.o \ unparse.o dump.o kicad.o meas.o \
cpp.o lex.yy.o y.tab.o \ cpp.o lex.yy.o y.tab.o \
gui.o gui_util.o gui_style.o gui_inst.o gui_status.o gui_canvas.o \ gui.o gui_util.o gui_style.o gui_inst.o gui_status.o gui_canvas.o \
gui_tool.o gui_over.o gui_meas.o gui_frame.o gui_tool.o gui_over.o gui_meas.o gui_frame.o

1
TODO
View File

@ -2,7 +2,6 @@ Major missing features:
- populate input area (still needed: mm/mil, rezoom) - populate input area (still needed: mm/mil, rezoom)
- add default unit (combine with grid unit selection ?) - add default unit (combine with grid unit selection ?)
- consider adding auto/mm/mil selection for each dimension - consider adding auto/mm/mil selection for each dimension
- add KiCad output
- add postscript output - add postscript output
- add option to include/omit helper vecs and frames (done for display, still - add option to include/omit helper vecs and frames (done for display, still
need postscript) need postscript)

View File

@ -20,7 +20,7 @@
#define MICRON_UNITS 10 #define MICRON_UNITS 10
#define MIL_UNITS (25.4*MICRON_UNITS) #define MIL_UNITS (25.4*MICRON_UNITS)
#define MM_UNITS (1000.0*MICRON_UNITS) #define MM_UNITS (1000.0*MICRON_UNITS)
#define KICAD_UNIT (10.0*MIL_UNITS) #define KICAD_UNIT (MIL_UNITS/10.0)
#define MIL_IN_MM 0.0254 #define MIL_IN_MM 0.0254
@ -54,7 +54,7 @@ static inline double units_to_mm(unit_type u)
} }
static inline double units_to_kicad(unit_type u) static inline int units_to_kicad(unit_type u)
{ {
return (double) u/KICAD_UNIT; return (double) u/KICAD_UNIT;
} }

103
gui.c
View File

@ -12,11 +12,16 @@
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include "util.h"
#include "inst.h" #include "inst.h"
#include "obj.h" #include "obj.h"
#include "dump.h" #include "dump.h"
#include "kicad.h"
#include "gui_util.h" #include "gui_util.h"
#include "gui_style.h" #include "gui_style.h"
#include "gui_status.h" #include "gui_status.h"
@ -46,24 +51,95 @@ static GtkWidget *stuff_image[2], *meas_image[2];
/* ----- menu bar ---------------------------------------------------------- */ /* ----- menu bar ---------------------------------------------------------- */
static void menu_save(GtkWidget *widget, gpointer user) static char *set_extension(const char *name, const char *ext)
{
char *s = stralloc(name);
char *slash, *dot;
char *res;
slash = strrchr(s, '/');
dot = strrchr(slash ? slash : s, '.');
if (dot)
*dot = 0;
res = stralloc_printf("%s.%s", s, ext);
free(s);
return res;
}
static void save_with_backup(const char *name, int (*fn)(FILE *file))
{ {
FILE *file; FILE *file;
char *s = stralloc(name);
char *slash, *dot, *tmp;
int n;
struct stat st;
if (!save_file) { slash = strrchr(s, '/');
dot = strrchr(slash ? slash : s, '.');
if (dot)
*dot = 0;
n = 0;
while (1) {
tmp = stralloc_printf("%s~%d%s%s",
s, n, dot ? "." : "", dot ? dot+1 : "");
if (stat(tmp, &st) < 0) {
if (errno == ENOENT)
break;
perror(tmp);
free(tmp);
return;
}
free(tmp);
n++;
}
if (rename(name, tmp) < 0) {
if (errno != ENOENT) {
perror(name);
free(tmp);
return;
}
} else {
fprintf(stderr, "renamed %s to %s\n", name, tmp);
}
free(tmp);
file = fopen(name, "w");
if (!file) {
perror(name);
return;
}
if (!fn(file))
perror(name);
if (fclose(file) == EOF)
perror(name);
fprintf(stderr, "saved to %s\n", name);
}
static void menu_save(GtkWidget *widget, gpointer user)
{
if (save_file)
save_with_backup(save_file, dump);
else {
if (!dump(stdout)) if (!dump(stdout))
perror("stdout"); perror("stdout");
return;
} }
file = fopen(save_file, "w"); }
if (!file) {
perror(save_file);
return; static void menu_save_kicad(GtkWidget *widget, gpointer user)
{
char *name;
if (save_file) {
name = set_extension(save_file, "mod");
save_with_backup(name, kicad);
free(name);
} else {
if (!kicad(stdout))
perror("stdout");
} }
if (!dump(file))
perror(save_file);
if (fclose(file) == EOF)
perror(save_file);
} }
@ -86,6 +162,11 @@ static void make_menu_bar(GtkWidget *hbox)
g_signal_connect(G_OBJECT(save), "activate", g_signal_connect(G_OBJECT(save), "activate",
G_CALLBACK(menu_save), NULL); G_CALLBACK(menu_save), NULL);
save = gtk_menu_item_new_with_label("Save as KiCad");
gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), save);
g_signal_connect(G_OBJECT(save), "activate",
G_CALLBACK(menu_save_kicad), NULL);
quit = gtk_menu_item_new_with_label("Quit"); quit = gtk_menu_item_new_with_label("Quit");
gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), quit); gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), quit);
g_signal_connect(G_OBJECT(quit), "activate", g_signal_connect(G_OBJECT(quit), "activate",

31
inst.c
View File

@ -29,39 +29,12 @@
#include "inst.h" #include "inst.h"
enum inst_prio {
ip_frame, /* frames have their own selection */
ip_pad, /* pads also accept clicks inside */
ip_circ, /* circles don't overlap easily */
ip_arc, /* arc are like circles, just shorter */
ip_rect, /* rectangles have plenty of sides */
ip_meas, /* mesurements are like lines but set a bit apart */
ip_line, /* lines are easly overlapped by other things */
ip_vec, /* vectors only have the end point */
ip_n, /* number of priorities */
};
#define FOR_INST_PRIOS_UP(prio) \
for (prio = 0; prio != ip_n; prio++)
#define FOR_INST_PRIOS_DOWN(prio) \
for (prio = ip_n-1; prio != (enum inst_prio) -1; prio--)
#define FOR_INSTS_UP(prio, inst) \
FOR_INST_PRIOS_UP(prio) \
for (inst = insts[prio]; inst; inst = inst->next)
#define FOR_INSTS_DOWN(prio, inst) \
FOR_INST_PRIOS_DOWN(prio) \
for (inst = insts[prio]; inst; inst = inst->next)
struct inst *selected_inst = NULL; struct inst *selected_inst = NULL;
struct inst *insts[ip_n];
struct bbox active_frame_bbox; struct bbox active_frame_bbox;
static struct inst *curr_frame = NULL; static struct inst *curr_frame = NULL;
static struct inst *insts[ip_n], **next_inst[ip_n]; static struct inst **next_inst[ip_n];
static struct inst *prev_insts[ip_n]; static struct inst *prev_insts[ip_n];
static unsigned long active_set = 0; static unsigned long active_set = 0;

31
inst.h
View File

@ -36,8 +36,23 @@ struct bbox {
struct coord max; struct coord max;
}; };
enum inst_prio {
ip_frame, /* frames have their own selection */
ip_pad, /* pads also accept clicks inside */
ip_circ, /* circles don't overlap easily */
ip_arc, /* arc are like circles, just shorter */
ip_rect, /* rectangles have plenty of sides */
ip_meas, /* mesurements are like lines but set a bit apart */
ip_line, /* lines are easly overlapped by other things */
ip_vec, /* vectors only have the end point */
ip_n, /* number of priorities */
};
struct inst; struct inst;
struct inst_ops { struct inst_ops {
void (*debug)(struct inst *self); void (*debug)(struct inst *self);
void (*save)(FILE *file, struct inst *self); void (*save)(FILE *file, struct inst *self);
@ -95,9 +110,25 @@ struct inst {
extern struct inst *selected_inst; extern struct inst *selected_inst;
extern struct inst *insts[ip_n];
extern struct bbox active_frame_bbox; extern struct bbox active_frame_bbox;
#define FOR_INST_PRIOS_UP(prio) \
for (prio = 0; prio != ip_n; prio++)
#define FOR_INST_PRIOS_DOWN(prio) \
for (prio = ip_n-1; prio != (enum inst_prio) -1; prio--)
#define FOR_INSTS_UP(prio, inst) \
FOR_INST_PRIOS_UP(prio) \
for (inst = insts[prio]; inst; inst = inst->next)
#define FOR_INSTS_DOWN(prio, inst) \
FOR_INST_PRIOS_DOWN(prio) \
for (inst = insts[prio]; inst; inst = inst->next)
void inst_select_outside(void *item, void (*deselect)(void *item)); void inst_select_outside(void *item, void (*deselect)(void *item));
int inst_select(struct coord pos); int inst_select(struct coord pos);
void inst_deselect(void); void inst_deselect(void);

260
kicad.c Normal file
View File

@ -0,0 +1,260 @@
/*
* kicad.c - Dump objects in the KiCad board/module format
*
* Written 2009 by Werner Almesberger
* Copyright 2009 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 <stdio.h>
#include <time.h>
#include "coord.h"
#include "inst.h"
#include "kicad.h"
enum kicad_layer {
layer_bottom, /* "copper" */
layer_l15,
layer_l14,
layer_l13,
layer_l12,
layer_l11,
layer_l10,
layer_l9,
layer_l8,
layer_l7,
layer_l6,
layer_l5,
layer_l4,
layer_l3,
layer_l2,
layer_top, /* "component" */
layer_glue_bottom, /* adhesive, copper side */
layer_glue_top, /* adhesive, component side */
layer_paste_bottom, /* solder paste */
layer_paste_top,
layer_silk_bottom, /* silk screen */
layer_silk_top,
layer_mask_bottom, /* solder mask */
layer_mask_top,
layer_draw, /* general drawing */
layer_comment,
layer_eco1,
layer_eco2,
layer_edge, /* edge */
};
static void kicad_pad(FILE *file, const struct inst *inst)
{
struct coord min, max;
unit_type tmp;
min.x = units_to_kicad(inst->base.x);
min.y = units_to_kicad(inst->base.y);
max.x = units_to_kicad(inst->u.pad.other.x);
max.y = units_to_kicad(inst->u.pad.other.y);
if (min.x > max.x) {
tmp = min.x;
min.x = max.x;
max.x = tmp;
}
if (min.y > max.y) {
tmp = min.y;
min.y = max.y;
max.y = tmp;
}
fprintf(file, "$PAD\n");
/*
* name, shape (rectangle), Xsize, Ysize, Xdelta, Ydelta, Orientation
*/
fprintf(file, "Sh \"%s\" R %d %d 0 0 0\n",
inst->u.pad.name, max.x-min.x, max.y-min.y);
/*
* Attributes: pad type, N, layer mask
*/
fprintf(file, "At SMD N %8.8X\n",
(1 << layer_top) |
(1 << layer_paste_top) |
(1 << layer_mask_top));
/*
* Position: Xpos, Ypos
*/
fprintf(file, "Po %d %d\n", (min.x+max.x)/2, -(min.y+max.y)/2);
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)
{
fprintf(stderr, "NOT YET IMPLEMENTED\n");
}
static void kicad_inst(FILE *file, enum inst_prio prio, const struct inst *inst)
{
switch (prio) {
case ip_pad:
kicad_pad(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:
break;
}
}
static void kicad_module(FILE *file, const char *name, time_t now)
{
enum inst_prio prio;
const struct inst *inst;
/*
* Module library name
*/
fprintf(file, "$MODULE %s\n", 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", name);
#if 0 /* optional */
/*
* Description
*/
fprintf(file, "Cd %s\n", 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, name);
fprintf(file, "T1 0 150 200 200 0 40 N I %d \"Val*\"\n",
layer_comment);
FOR_INSTS_UP(prio, inst)
kicad_inst(file, prio, inst);
fprintf(file, "$EndMODULE %s\n", name);
}
int kicad(FILE *file)
{
time_t now = time(NULL);
fprintf(file, "PCBNEW-LibModule-V1 %s\n", ctime(&now));
fprintf(file, "$INDEX\n");
fprintf(file, "%s\n", part_name);
fprintf(file, "$EndINDEX\n");
kicad_module(file, part_name, now);
fprintf(file, "$EndLIBRARY\n");
fflush(file);
return !ferror(file);
}

22
kicad.h Normal file
View File

@ -0,0 +1,22 @@
/*
* kicad.h - Dump objects in the KiCad board/module format
*
* Written 2009 by Werner Almesberger
* Copyright 2009 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.
*/
#ifndef KICAD_H
#define KICAD_H
#include <stdio.h>
int kicad(FILE *file);
#endif /* !KICAD_H */