From 1cff10b82435aecb5722bc0402da3ceda16aa05a Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Thu, 21 Jul 2016 23:54:32 -0300 Subject: [PATCH] sch2fig/: eeschema to FIG converter (WIP) --- sch2fig/Makefile | 19 ++++ sch2fig/fig.c | 144 ++++++++++++++++++++++++++ sch2fig/fig.h | 33 ++++++ sch2fig/lib.c | 264 +++++++++++++++++++++++++++++++++++++++++++++++ sch2fig/lib.h | 24 +++++ sch2fig/main.c | 69 +++++++++++++ sch2fig/sch.c | 181 ++++++++++++++++++++++++++++++++ sch2fig/sch.h | 45 ++++++++ 8 files changed, 779 insertions(+) create mode 100644 sch2fig/Makefile create mode 100644 sch2fig/fig.c create mode 100644 sch2fig/fig.h create mode 100644 sch2fig/lib.c create mode 100644 sch2fig/lib.h create mode 100644 sch2fig/main.c create mode 100644 sch2fig/sch.c create mode 100644 sch2fig/sch.h diff --git a/sch2fig/Makefile b/sch2fig/Makefile new file mode 100644 index 0000000..8d32c98 --- /dev/null +++ b/sch2fig/Makefile @@ -0,0 +1,19 @@ +NAME = sch2fig +OBJS = main.o sch.o lib.o fig.o + +CFLAGS = -g -Wall -Wextra -Wno-unused-parameter + +include ../../anelok/common/Makefile.c-common + +.PHONY: test + +all:: $(NAME) + +$(NAME): $(OBJS) + $(CC) -o $(NAME) $(OBJS) + +NEO900_HW = ../../../n9/ee/hw/ + +test: $(NAME) + $(NAME) $(NEO900_HW)/neo900.lib $(NEO900_HW)neo900_SS_1.sch \ + >out.fig diff --git a/sch2fig/fig.c b/sch2fig/fig.c new file mode 100644 index 0000000..89500ba --- /dev/null +++ b/sch2fig/fig.c @@ -0,0 +1,144 @@ +#include + +#include "fig.h" + + +#define COLOR_BLACK 0 +#define COLOR_BLUE 1 +#define COLOR_GREEN4 12 +#define COLOR_RED4 18 +#define COLOR_RED3 19 + +#define FONT_HELVETICA_BOLD 18 + +#define LAYER_TEXT 30 +#define LAYER_WIRES 50 +#define LAYER_LINES 60 +#define LAYER_COMP_DWG 70 + +#define WIDTH_WIRE 2 +#define WIDTH_LINE 2 +#define WIDTH_COMP_DWG 2 + +#define JUNCTION_R 50 + + +/* + * FIG works with 1/1200 in + * KiCad works with mil + * 1 point = 1/72 in + */ + + +static inline int cx(int x) +{ + return x * 1200 / 1000; +} + + +static inline int cy(int y) +{ + return y * 1200 / 1000; +} + + +static inline int pt(int x) +{ + return cx(x) * 72 * 1.5 / 1200; +} + + +void fig_rect(int sx, int sy, int ex, int ey) +{ + // Type Thick Depth StyleV Rad + // SubTy Color Pen Join FwdAr + // Style FillCol AreaFil Cap BwdAr + printf("2 2 0 %d %d 7 %d -1 -1 0.0 1 1 -1 0 0 5\n", + WIDTH_COMP_DWG, COLOR_RED4, LAYER_COMP_DWG); + printf("\t%d %d %d %d %d %d %d %d %d %d\n", + cx(sx), cy(sy), cx(ex), cy(sy), cx(ex), cy(ey), cx(sx), cy(ey), + cx(sx), cy(sy)); +} + + +void fig_poly(int points, int x[points], int y[points]) +{ + int i; + char ch = '\t'; + + // Type Thick Depth StyleV Rad + // SubTy Color Pen Join FwdAr + // Style FillCol AreaFil Cap BwdAr + printf("2 1 0 %d %d 7 %d -1 -1 0.0 1 1 -1 0 0 %d\n", + WIDTH_COMP_DWG, COLOR_RED4, LAYER_COMP_DWG, points); + for (i = 0; i != points; i++) { + printf("%c%d %d", ch, cx(x[i]), cy(y[i])); + ch = ' '; + } + printf("\n"); +} + + +void fig_text(int x, int y, const char *s, int dir, int dim, + enum fig_shape shape) +{ + // Type Depth FontSiz Height + // Just Pen Angle Length + // Color Font Flags X Y + printf("4 0 %d %d -1 %d %d %d 4 0.0 0.0 %d %d %s\\001\n", + COLOR_BLACK, LAYER_TEXT, FONT_HELVETICA_BOLD, + pt(dim), 0, cx(x), cy(y), s); +} + + +void fig_glabel(int x, int y, const char *s, int dir, int dim, + enum fig_shape shape) +{ +} + + +void fig_junction(int x, int y) +{ + // Type Thick Depth StyleV Cx Rx Sx Ex + // SubTy Color Pen Dir Cy Ry Sy Ey + // Style FillCol AreaFil Angle + printf("1 3 0 0 -1 %d %d -1 20 0.0 1 0.0 %d %d %d %d %d %d %d %d\n", + COLOR_GREEN4, LAYER_WIRES, cx(x), cy(y), JUNCTION_R, JUNCTION_R, + cx(x), cy(y), cx(x) + JUNCTION_R, cy(y)); +} + + +void fig_wire(int sx, int sy, int ex, int ey) +{ + // TypeStyle FillCol AreaFil Cap FwdAr + // SubTy Color Pen StyleV Rad BwdAr + // Thick Depth Join Points + printf("2 1 0 %d %d 7 %d -1 -1 0.0 1 1 -1 0 0 2\n", + WIDTH_WIRE, COLOR_GREEN4, LAYER_WIRES); + printf("\t%d %d %d %d\n", cx(sx), cy(sy), cx(ex), cy(ey)); +} + + +void fig_line(int sx, int sy, int ex, int ey) +{ + // TypeStyle FillCol AreaFil Cap FwdAr + // SubTy Color Pen StyleV Rad BwdAr + // Thick Depth Join Points + printf("2 1 0 %d %d 7 %d -1 -1 0.0 1 1 -1 0 0 2\n", + WIDTH_LINE, COLOR_BLUE, LAYER_LINES); + printf("\t%d %d %d %d\n", cx(sx), cy(sy), cx(ex), cy(ey)); +} + + +void fig_init(void) +{ + printf("#FIG 3.2\n"); + printf("Landscape\n"); + printf("Center\n"); + printf("Metric\n"); + printf("A4\n"); + printf("10.00\n"); + printf("Single\n"); + printf("-2\n"); + printf("1200 2\n"); +} diff --git a/sch2fig/fig.h b/sch2fig/fig.h new file mode 100644 index 0000000..c1985e2 --- /dev/null +++ b/sch2fig/fig.h @@ -0,0 +1,33 @@ +#ifndef FIG_H +#define FIG_H + +enum fig_shape { + fig_unspec, // UnSpc + fig_in, // Input + fig_out, // Output + fig_tri, // 3State +}; + + +/* libraries */ + +void fig_rect(int sx, int sy, int ex, int ey); +void fig_poly(int points, int x[points], int y[points]); + +/* schematics */ + +void fig_text(int x, int y, const char *s, int dir, int dim, + enum fig_shape shape); +void fig_glabel(int x, int y, const char *s, int dir, int dim, + enum fig_shape shape); + +void fig_junction(int x, int y); + +void fig_wire(int sx, int sy, int ex, int ey); +void fig_line(int sx, int sy, int ex, int ey); + +/* inititalization */ + +void fig_init(void); + +#endif /* !FIG_H */ diff --git a/sch2fig/lib.c b/sch2fig/lib.c new file mode 100644 index 0000000..672bec4 --- /dev/null +++ b/sch2fig/lib.c @@ -0,0 +1,264 @@ +#include +#include +#include +#include + +#include "fig.h" +#include "lib.h" + + +struct obj { + enum obj_type { + obj_poly, + obj_rect, + obj_circ, + obj_arc, + obj_text, + obj_pin, + } type; + unsigned unit; + unsigned convert; + union { + struct poly { + int thick; + char fill; + int points; + int *x; + int *y; + } poly; + struct { + int thick; + char fill; + int sx, sy; + int ex, ey; + } rect; + struct { + int x, y; + int r; + int thick; + char fill; + } circ; + struct { + char orient; + int x, y; + int dim; + char *s; + } text; + struct { + char *name; + char *number; + int x, y; + int length; + char orient; + int number_size; + int name_size; + char etype; + // @@@ shape + } pin; + } u; + struct obj *next; +}; + + +struct comp { + const char *name; + struct obj *objs; + struct comp *next; +}; + + +static struct comp *comps = NULL; +static struct comp **next_comp = &comps; +static struct obj **next_obj; + + +static inline int mx(int x, int y, int m[6]) +{ + return m[0] + x * m[1] + y * m[2]; +} + + +static inline int my(int x, int y, int m[6]) +{ + return m[3] + x * m[4] + y * m[5]; +} + + +static void draw_poly(const struct poly *poly, int m[6]) +{ + int n = poly->points; + int x[n]; + int y[n]; + int i; + + for (i = 0; i != n; i++) { + x[i] = mx(poly->x[i], poly->y[i], m); + y[i] = my(poly->x[i], poly->y[i], m); + } + fig_poly(n, x, y); +} + + +static void draw(const struct obj *obj, int m[6]) +{ + switch (obj->type) { + case obj_poly: + draw_poly(&obj->u.poly, m); + break; + case obj_rect: + fig_rect(mx(obj->u.rect.sx, obj->u.rect.sy, m), + my(obj->u.rect.sx, obj->u.rect.sy, m), + mx(obj->u.rect.ex, obj->u.rect.ey, m), + my(obj->u.rect.ex, obj->u.rect.ey, m)); + // @@@ + break; + case obj_circ: + break; + case obj_text: + break; + case obj_pin: + break; + default: + abort(); + } +} + + +void lib_exec(const char *name, unsigned unit, int m[4]) +{ + const struct comp *comp; + const struct obj *obj; + + for (comp = comps; comp; comp = comp->next) + if (!strcmp(comp->name, name)) + goto found; + fprintf(stderr, "\"%s\" not found\n", name); + exit(1); + +found: + for (obj = comp->objs; obj; obj = obj->next) { + if (obj->unit && obj->unit != unit) + continue; + draw(obj, m); + } +} + + +static bool parse_poly(struct obj *obj, const char *line, int points) +{ + int i, n; + + obj->u.poly.points = points; + obj->u.poly.x = malloc(sizeof(int) * points); + obj->u.poly.y = malloc(sizeof(int) * points); + for (i = 0; i != points; i++) { + if (sscanf(line, "%d %d %n", + obj->u.poly.x + i, obj->u.poly.y + i, &n) != 2) + return 0; + line += n; + } + if (sscanf(line, "%c", &obj->u.poly.fill) != 1) + return 0; + return 1; +} + + +bool lib_parse(struct lib_ctx *ctx, const char *line) +{ + int n = 0; + char *s; + unsigned points; + struct comp *comp; + struct obj *obj; + + ctx->lineno++; + + switch (ctx->state) { + case lib_skip: + if (sscanf(line, "DEF %ms", &s) == 1) { + ctx->state = lib_def; + comp = malloc(sizeof(struct comp)); + if (*s == '~') + s++; + comp->name = s; + comp->objs = NULL; + comp->next = NULL; + *next_comp = comp; + next_comp = &comp->next; + next_obj = &comp->objs; + return 1; + } + return 1; + case lib_def: + if (sscanf(line, "DRAW%n", &n) == 0 && n) { + ctx->state = lib_draw; + return 1; + } + return 1; + case lib_draw: + if (sscanf(line, "ENDDRAW%n", &n) == 0 && n) { + ctx->state = lib_skip; + return 1; + } + + obj = malloc(sizeof(struct obj)); + obj->next = NULL; + *next_obj = obj; + next_obj = &obj->next; + + if (sscanf(line, "P %u %u %u %u %n", + &points, &obj->unit, &obj->convert, &obj->u.poly.thick, + &n) == 4) { + obj->type = obj_poly; + if (parse_poly(obj, line + n, points)) + return 1; + break; + } + if (sscanf(line, "S %d %d %d %d %u %u %d %c", + &obj->u.rect.sx, &obj->u.rect.sy, &obj->u.rect.ex, + &obj->u.rect.ey, &obj->unit, &obj->convert, + &obj->u.rect.thick, &obj->u.rect.fill) == 8) { + obj->type = obj_rect; + return 1; + } + if (sscanf(line, "C %d %d %d %u %u %d %c", + &obj->u.circ.x, &obj->u.circ.y, &obj->u.circ.r, + &obj->unit, &obj->convert, &obj->u.circ.thick, + &obj->u.circ.fill) == 7) { + obj->type = obj_circ; + return 1; + } + if (sscanf(line, "A %n", &n) == 0 && n) { + obj->type = obj_arc; + return 1; // @@@ + } + if (sscanf(line, "T %c %d %d %d %u %u %ms", + &obj->u.text.orient, &obj->u.text.x, &obj->u.text.y, + &obj->u.text.dim, &obj->unit, &obj->convert, + &obj->u.text.s) == 7) { + obj->type = obj_text; + return 1; + } + if (sscanf(line, "X %ms %ms %d %d %d %c %d %d %u %u %c", + &obj->u.pin.name, &obj->u.pin.number, + &obj->u.pin.x, &obj->u.pin.y, &obj->u.pin.length, + &obj->u.pin.orient, + &obj->u.pin.number_size, &obj->u.pin.name_size, + &obj->unit, &obj->convert, &obj->u.pin.etype) == 11) { + obj->type = obj_pin; + return 1; + } + break; + default: + abort(); + } + fprintf(stderr, "%u: cannot parse\n\"%s\"\n", ctx->lineno, line); + exit(1); +} + + +void lib_init(struct lib_ctx *ctx) +{ + ctx->state = lib_skip; + ctx->lineno++; +} diff --git a/sch2fig/lib.h b/sch2fig/lib.h new file mode 100644 index 0000000..5ebc23c --- /dev/null +++ b/sch2fig/lib.h @@ -0,0 +1,24 @@ +#ifndef LIB_H +#define LIB_H + +#include + + +enum lib_state { + lib_skip, /* before a definition */ + lib_def, /* in definition */ + lib_draw, /* in drawings */ +}; + +struct lib_ctx { + enum lib_state state; + unsigned lineno; +}; + + +void lib_exec(const char *name, unsigned unit, int m[6]); + +bool lib_parse(struct lib_ctx *ctx, const char *line); +void lib_init(struct lib_ctx *ctx); + +#endif /* !LIB_H */ diff --git a/sch2fig/main.c b/sch2fig/main.c new file mode 100644 index 0000000..2561555 --- /dev/null +++ b/sch2fig/main.c @@ -0,0 +1,69 @@ +#include +#include +#include + +#include "fig.h" +#include "lib.h" +#include "sch.h" + + +static bool do_sch_parse(void *ctx, const char *line) +{ + return sch_parse(ctx, line); +} + + +static bool do_lib_parse(void *ctx, const char *line) +{ + return lib_parse(ctx, line); +} + + +static void read_file(const char *name, void *ctx, + bool (*parse)(void *ctx, const char *line)) +{ + FILE *file; + char buf[1000]; + char *nl; + + file = fopen(name, "r"); + while (fgets(buf, sizeof(buf), file)) { + nl = strchr(buf, '\n'); + if (nl) + *nl = 0; + if (!parse(ctx, buf)) + break; + } + fclose(file); +} + + +static void usage(const char *name) +{ + fprintf(stderr, "usage: %s [file.lib ...] file.sch\n", name); + exit(1); +} + + +int main(int argc, char **argv) +{ + int arg; + + if (argc < 2) + usage(*argv); + + fig_init(); + for (arg = 1; arg != argc; arg++) { + if (arg == argc - 1) { + struct sch_ctx ctx; + + sch_init(&ctx); + read_file(argv[arg], &ctx, do_sch_parse); + } else { + struct lib_ctx ctx; + + lib_init(&ctx); + read_file(argv[arg], &ctx, do_lib_parse); + } + } +} diff --git a/sch2fig/sch.c b/sch2fig/sch.c new file mode 100644 index 0000000..342e67d --- /dev/null +++ b/sch2fig/sch.c @@ -0,0 +1,181 @@ +#include +#include +#include +#include + +#include "fig.h" +#include "lib.h" +#include "sch.h" + + +static enum fig_shape do_decode_shape(const char *s) +{ + if (!strcmp(s, "UnSpc")) + return fig_unspec; + if (!strcmp(s, "Input")) + return fig_in; + if (!strcmp(s, "Output")) + return fig_out; + if (!strcmp(s, "3State")) + return fig_tri; + fprintf(stderr, "unknown shape: \"%s\"\n", s); + exit(1); +} + + +static enum fig_shape decode_shape(const char *s) +{ + enum fig_shape res; + + res = do_decode_shape(s); + free((void *) s); + return res; +} + + +bool sch_parse(struct sch_ctx *ctx, const char *line) +{ + int n = 0; + int x, y, ex, ey; + char *s; + int m[4]; + + ctx->lineno++; + + switch (ctx->state) { + case sch_basic: + if (sscanf(line, "$Comp%n", &n) == 0 && n) { + ctx->state = sch_comp; + return 1; + } + if (sscanf(line, "$Sheet%n", &n) == 0 && n) { + ctx->state = sch_sheet; + return 1; + } + + /* Text */ + + if (sscanf(line, "Text Notes %d %d %d %d", + &ctx->x, &ctx->y, &ctx->dir, &ctx->dim) == 4) { + ctx->state = sch_text; + ctx->text = fig_text; + return 1; + } + if (sscanf(line, "Text GLabel %d %d %d %d %ms", + &ctx->x, &ctx->y, &ctx->dir, &ctx->dim, &s) == 5) { + ctx->state = sch_text; + ctx->shape = decode_shape(s); + ctx->text = fig_glabel; + return 1; + } + if (sscanf(line, "Text HLabel %d %d %d %d %ms", + &ctx->x, &ctx->y, &ctx->dir, &ctx->dim, &s) == 5) { + ctx->state = sch_text; +abort(); + return 1; + } + if (sscanf(line, "Text Label%n", &n) == 0 && n) { + ctx->state = sch_text; +abort(); + return 1; + } + + /* Connection */ + + if (sscanf(line, "Connection ~ %d %d", &x, &y) == 2) { + fig_junction(x, y); + return 1; + } + + /* Wire */ + + if (sscanf(line, "Wire Wire Line%n", &n) == 0 && n) { + ctx->state = sch_wire; + ctx->wire = fig_wire; + return 1; + } + if (sscanf(line, "Wire Bus Line%n", &n) == 0 && n) { + ctx->state = sch_wire; +abort(); + return 1; + } + if (sscanf(line, "Wire Notes Line%n", &n) == 0 && n) { + ctx->state = sch_wire; + ctx->wire = fig_line; + return 1; + } + if (sscanf(line, "Wire Wire Bus%n", &n) == 0 && n) { + ctx->state = sch_wire; +abort(); + return 1; + } + if (sscanf(line, "Wire Bus Bus%n", &n) == 0 && n) { + ctx->state = sch_wire; +abort(); + return 1; + } + + /* EndSCHEMATC */ + + if (sscanf(line, "$EndSCHEMATC%n", &n) == 0 && n) + return 0; + break; + case sch_descr: + if (sscanf(line, "$EndDescr%n", &n) || !n) + return 1; + ctx->state = sch_basic; + return 1; + case sch_comp: + if (sscanf(line, "$EndComp%n", &n) == 0 && n) { + ctx->state = sch_basic; + free(ctx->comp); + ctx->comp = NULL; + return 1; + } + if (sscanf(line, "L %ms", &ctx->comp) == 1) + return 1; + if (sscanf(line, "U %u", &ctx->unit) == 1) + return 1; + if (sscanf(line, "P %d %d", &ctx->x, &ctx->y) == 2) + return 1; + if (sscanf(line, "F%d", &n) == 1) + return 1; // @@@ + n = sscanf(line, " %d %d %d %d", m + 1, m + 2, m + 4, m + 5); + if (n == 3) + return 1; + if (n == 4) { + m[0] = ctx->x; + m[3] = ctx->y; + lib_exec(ctx->comp, ctx->unit, m); + return 1; + } + break; + case sch_sheet: + if (sscanf(line, "$EndSheet%n", &n) || !n) + return 1; + ctx->state = sch_basic; + return 1; + case sch_text: + ctx->state = sch_basic; + ctx->text(ctx->x, ctx->y, line, ctx->dir, ctx->dim, + ctx->shape); + return 1; + case sch_wire: + if (sscanf(line, "%d %d %d %d", &x, &y, &ex, &ey) != 4) + break; + ctx->wire(x, y, ex, ey); + ctx->state = sch_basic; + return 1; + default: + abort(); + } + fprintf(stderr, "%u: cannot parse\n\"%s\"\n", ctx->lineno, line); + exit(1); +} + + +void sch_init(struct sch_ctx *ctx) +{ + ctx->state = sch_descr; + ctx->lineno++; +} diff --git a/sch2fig/sch.h b/sch2fig/sch.h new file mode 100644 index 0000000..395a587 --- /dev/null +++ b/sch2fig/sch.h @@ -0,0 +1,45 @@ +#ifndef SCH_H +#define SCH_H + +#include + + +enum sch_state { + sch_basic, /* basic state */ + sch_descr, /* prelude and description */ + sch_comp, /* component */ + sch_sheet, /* sub-sheet */ + sch_text, /* text or label */ + sch_wire, /* wire */ +}; + +struct sch_ctx { + enum sch_state state; + void (*wire)(int sx, int sy, int ex, int ey); + + /* text and component */ + + int x, y; /* saved coordinates */ + + /* text */ + + void (*text)(int x, int y, const char *s, int dir, int dim, + enum fig_shape shape); + int dir; /* orientation */ + int dim; /* dimension */ + enum fig_shape shape; + + /* component */ + + char *comp; /* current component */ + unsigned unit; /* unit of current component */ + + + unsigned lineno; +}; + + +bool sch_parse(struct sch_ctx *ctx, const char *line); +void sch_init(struct sch_ctx *ctx); + +#endif /* !SCH_H */