diff --git a/README b/README index cb091f2..c2ef8a1 100644 --- a/README +++ b/README @@ -106,7 +106,7 @@ The file has the following structure: frame definitions ... package name -unit +setup objects ... @@ -124,6 +124,14 @@ from the previous vector to (2mm, 2mm), and then make a line connecting the two points. +Setup +- - - + +The setup section defines settings that affect the entire footprint. +It is optional and can contain a "unit" directive and an "allow" +directive. + + Units - - - @@ -154,6 +162,24 @@ When saving a footprint definition, the default unit is set to the unit set in the GUI. +Allow +- - - + +fped normally disallows overlapping pads. This restriction can be +relaxed with the "allow" directive. + +allow touch + +Allows pads touching but not having more than their border in common. + +allow overlap + +Do not check for overlaps at all. + +If the "allow" directive is omitted, fped defaults to allowing +neigher overlap nor touch. + + Vectors - - - - diff --git a/dump.c b/dump.c index 949cba0..4aa0eb0 100644 --- a/dump.c +++ b/dump.c @@ -569,6 +569,23 @@ static void dump_unit(FILE *file) } +static void dump_allow(FILE *file) +{ + switch (allow_overlap) { + case ao_none: + break; + case ao_touch: + fprintf(file, "allow touch\n"); + break; + case ao_any: + fprintf(file, "allow overlap\n"); + break; + default: + abort(); + } +} + + static void reverse_frames(FILE *file, struct frame *last) { if (last) { @@ -589,6 +606,8 @@ int dump(FILE *file) reverse_frames(file, frames->next); fprintf(file, "package \"%s\"\n", pkg_name); dump_unit(file); + dump_allow(file); + fprintf(file, "\n"); dump_frame(file, frames, ""); fflush(file); diff --git a/fpd.l b/fpd.l index 44a3adf..279f8d8 100644 --- a/fpd.l +++ b/fpd.l @@ -61,6 +61,8 @@ void scan_values(const char *s) /* keywords are only accepted at the beginning of a line */ %s NOKEYWORD +/* ALLOW is followed by special keywords (we could use NOKEYWORD as well) */ +%s ALLOW NUM [0-9]+\.?[0-9]* SP [\t ]* @@ -123,6 +125,10 @@ SP [\t ]* "unit" { BEGIN(NOKEYWORD); return TOK_UNIT; } +"allow" BEGIN(ALLOW); +"overlap" return TOK_ALLOW_OVERLAP; +"touch" return TOK_ALLOW_TOUCH; + "%del" { BEGIN(NOKEYWORD); return TOK_DBG_DEL; } "%move" { BEGIN(NOKEYWORD); diff --git a/fpd.y b/fpd.y index df65945..9f5b5ac 100644 --- a/fpd.y +++ b/fpd.y @@ -459,6 +459,7 @@ static int dbg_meas(const char *name) %token TOK_NEXT TOK_NEXT_INVERTED TOK_MAX TOK_MAX_INVERTED %token TOK_DBG_DEL TOK_DBG_MOVE TOK_DBG_FRAME TOK_DBG_PRINT %token TOK_DBG_DUMP TOK_DBG_EXIT TOK_DBG_TSORT TOK_DBG_MEAS +%token TOK_ALLOW_OVERLAP TOK_ALLOW_TOUCH %token NUMBER %token STRING @@ -508,8 +509,8 @@ all: ; fpd: - frame_defs part_name opt_unit opt_frame_items opt_measurements - | frame_defs unit opt_frame_items opt_measurements + frame_defs part_name opt_setup opt_frame_items opt_measurements + | frame_defs setup opt_frame_items opt_measurements | frame_defs frame_items opt_measurements | frame_defs opt_measurements ; @@ -532,8 +533,15 @@ part_name: } ; -opt_unit: - | unit +opt_setup: + | setup + ; + +setup: + unit + | allow + | unit allow + | allow unit ; unit: @@ -552,6 +560,17 @@ unit: } ; +allow: + TOK_ALLOW_TOUCH + { + allow_overlap = ao_touch; + } + | TOK_ALLOW_OVERLAP + { + allow_overlap = ao_any; + } + ; + frame_defs: | frame_defs frame_def ; diff --git a/hole.c b/hole.c index c438fee..1b90995 100644 --- a/hole.c +++ b/hole.c @@ -19,7 +19,7 @@ static int check_through_hole(struct inst *pad, struct inst *hole) { - if (!overlap(pad, hole)) + if (!overlap(pad, hole, ao_none)) return 1; if (!inside(hole, pad)) { fail("hole (line %d) not completely inside " diff --git a/layer.c b/layer.c index eb952e5..e2716de 100644 --- a/layer.c +++ b/layer.c @@ -113,7 +113,8 @@ static int refine_overlapping(struct inst *copper, struct inst *other) } -static int refine_copper(const struct pkg *pkg_copper, struct inst *copper) +static int refine_copper(const struct pkg *pkg_copper, struct inst *copper, + enum allow_overlap allow) { const struct pkg *pkg; struct inst *other; @@ -126,7 +127,7 @@ static int refine_copper(const struct pkg *pkg_copper, struct inst *copper) continue; for (other = pkg->insts[ip_pad_copper]; other; other = other->next) - if (copper != other && overlap(copper, other)) { + if (copper != other && overlap(copper, other, allow)) { fail("overlapping copper pads " "(\"%s\" line %d, \"%s\" line %d)", copper->u.pad.name, copper->obj->lineno, @@ -136,7 +137,7 @@ static int refine_copper(const struct pkg *pkg_copper, struct inst *copper) } for (other = pkg->insts[ip_pad_special]; other; other = other->next) - if (overlap(copper, other)) + if (overlap(copper, other, ao_none)) if (!refine_overlapping(copper, other)) return 0; } @@ -155,7 +156,7 @@ static void mirror_layers(layer_type *layers) } -int refine_layers(void) +int refine_layers(enum allow_overlap allow) { const struct pkg *pkg; struct inst *copper; @@ -163,7 +164,7 @@ int refine_layers(void) for (pkg = pkgs; pkg; pkg = pkg->next) for (copper = pkg->insts[ip_pad_copper]; copper; copper = copper->next) { - if (!refine_copper(pkg, copper)) + if (!refine_copper(pkg, copper, allow)) return 0; if (copper->u.pad.hole) mirror_layers(&copper->u.pad.layers); diff --git a/layer.h b/layer.h index 84cddd6..1a1b276 100644 --- a/layer.h +++ b/layer.h @@ -15,6 +15,8 @@ #include +#include "overlap.h" + typedef uint32_t layer_type; @@ -75,6 +77,6 @@ enum pad_type layers_to_pad_type(layer_type layers); layer_type mech_hole_layers(void); -int refine_layers(void); +int refine_layers(enum allow_overlap allow); #endif /* !LAYER_H */ diff --git a/obj.c b/obj.c index 8eedaf7..8408eae 100644 --- a/obj.c +++ b/obj.c @@ -22,6 +22,7 @@ #include "meas.h" #include "inst.h" #include "hole.h" +#include "overlap.h" #include "layer.h" #include "delete.h" #include "obj.h" @@ -37,6 +38,7 @@ char *pkg_name = NULL; struct frame *frames = NULL; struct frame *active_frame = NULL; void *instantiation_error = NULL; +enum allow_overlap allow_overlap = ao_none; static struct bitset *frame_set; /* frames visited in "call chain" */ @@ -498,7 +500,7 @@ int instantiate(void) if (ok) ok = link_holes(); if (ok) - ok = refine_layers(); + ok = refine_layers(allow_overlap); if (ok) ok = instantiate_meas(n_frames); if (ok) diff --git a/obj.h b/obj.h index bd1c3c5..27d2dca 100644 --- a/obj.h +++ b/obj.h @@ -20,6 +20,7 @@ #include "expr.h" #include "coord.h" #include "meas.h" +#include "overlap.h" #include "layer.h" @@ -242,6 +243,7 @@ extern char *pkg_name; /* anonymous common package first */ extern struct frame *frames; /* root frame first */ extern struct frame *active_frame; extern void *instantiation_error; +extern enum allow_overlap allow_overlap; struct inst; diff --git a/overlap.c b/overlap.c index 92b4971..ff76dd8 100644 --- a/overlap.c +++ b/overlap.c @@ -71,15 +71,23 @@ struct shape { static int circle_circle_overlap(struct coord c1, unit_type r1, - struct coord c2, unit_type r2) + struct coord c2, unit_type r2, enum allow_overlap allow) { + if (allow == ao_touch) + return dist_point(c1, c2) < r1+r2; return dist_point(c1, c2) <= r1+r2; } static int circle_rect_overlap(struct coord c, unit_type r, - struct coord min, struct coord max) + struct coord min, struct coord max, enum allow_overlap allow) { + if (allow == ao_touch) { + if (c.x <= min.x-r || c.x >= max.x+r) + return 0; + if (c.y <= min.y-r || c.y >= max.y+r) + return 0; + } if (c.x < min.x-r || c.x > max.x+r) return 0; if (c.y < min.y-r || c.y > max.y+r) @@ -89,8 +97,14 @@ static int circle_rect_overlap(struct coord c, unit_type r, static int rect_rect_overlap(struct coord min1, struct coord max1, - struct coord min2, struct coord max2) + struct coord min2, struct coord max2, enum allow_overlap allow) { + if (allow == ao_touch) { + if (max1.x <= min2.x || max2.x <= min1.x) + return 0; + if (max1.y <= min2.y || max2.y <= min1.y) + return 0; + } if (max1.x < min2.x || max2.x < min1.x) return 0; if (max1.y < min2.y || max2.y < min1.y) @@ -99,15 +113,18 @@ static int rect_rect_overlap(struct coord min1, struct coord max1, } -static int shapes_overlap(const struct shape *a, const struct shape *b) +static int shapes_overlap(const struct shape *a, const struct shape *b, + enum allow_overlap allow) { if (a->circle && !b->circle) - return shapes_overlap(b, a); + return shapes_overlap(b, a, allow); if (a->circle) /* b must be circle, too */ - return circle_circle_overlap(a->center, a->r, b->center, b->r); + return circle_circle_overlap(a->center, a->r, b->center, b->r, + allow); if (b->circle) /* a must be rect */ - return circle_rect_overlap(b->center, b->r, a->min, a->max); - return rect_rect_overlap(a->min, a->max, b->min, b->max); + return circle_rect_overlap(b->center, b->r, a->min, a->max, + allow); + return rect_rect_overlap(a->min, a->max, b->min, b->max, allow); } @@ -115,11 +132,11 @@ static int shapes_overlap(const struct shape *a, const struct shape *b) static int test_overlap(const struct inst *a, const struct inst *b, - const struct shape *other); + const struct shape *other, enum allow_overlap allow); static int do_circle(const struct inst *next, const struct shape *other, - unit_type x, unit_type y, unit_type r) + unit_type x, unit_type y, unit_type r, enum allow_overlap allow) { struct shape shape = { .circle = 1, @@ -131,13 +148,14 @@ static int do_circle(const struct inst *next, const struct shape *other, }; if (next) - return test_overlap(next, NULL, &shape); - return shapes_overlap(other, &shape); + return test_overlap(next, NULL, &shape, allow); + return shapes_overlap(other, &shape, allow); } static int do_rect(const struct inst *next, const struct shape *other, - unit_type x, unit_type y, unit_type w, unit_type h) + unit_type x, unit_type y, unit_type w, unit_type h, + enum allow_overlap allow) { struct shape shape = { .circle = 0, @@ -152,13 +170,13 @@ static int do_rect(const struct inst *next, const struct shape *other, }; if (next) - return test_overlap(next, NULL, &shape); - return shapes_overlap(other, &shape); + return test_overlap(next, NULL, &shape, allow); + return shapes_overlap(other, &shape, allow); } static int test_overlap(const struct inst *a, const struct inst *b, - const struct shape *other) + const struct shape *other, enum allow_overlap allow) { struct coord min, max; unit_type h, w, r; @@ -183,23 +201,26 @@ static int test_overlap(const struct inst *a, const struct inst *b, w = max.x-min.x; if (!rounded) - return do_rect(b, other, min.x, min.y, w, h); + return do_rect(b, other, min.x, min.y, w, h, allow); if (h > w) { r = w/2; - return do_circle(b, other, min.x+r, max.y-r, r) || - do_rect(b, other, min.x, min.y+r, w, h-2*r) || - do_circle(b, other, min.x+r, min.y+r, r); + return do_circle(b, other, min.x+r, max.y-r, r, allow) || + do_rect(b, other, min.x, min.y+r, w, h-2*r, allow) || + do_circle(b, other, min.x+r, min.y+r, r, allow); } else { r = h/2; - return do_circle(b, other, min.x+r, min.y+r, r) || - do_rect(b, other, min.x+r, min.y, w-2*r, h) || - do_circle(b, other, max.x-r, min.y+r, r); + return do_circle(b, other, min.x+r, min.y+r, r, allow) || + do_rect(b, other, min.x+r, min.y, w-2*r, h, allow) || + do_circle(b, other, max.x-r, min.y+r, r, allow); } } -int overlap(const struct inst *a, const struct inst *b) +int overlap(const struct inst *a, const struct inst *b, + enum allow_overlap allow) { - return test_overlap(a, b, NULL); + if (allow == ao_any) + return 0; + return test_overlap(a, b, NULL, allow); } diff --git a/overlap.h b/overlap.h index 78ce565..30b42c1 100644 --- a/overlap.h +++ b/overlap.h @@ -1,8 +1,8 @@ /* * overlap.h - Test for overlaps * - * Written 2009 by Werner Almesberger - * Copyright 2009 by Werner Almesberger + * Written 2009, 2010 by Werner Almesberger + * Copyright 2009, 2010 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 @@ -13,7 +13,19 @@ #ifndef OVERLAP_H #define OVERLAP_H -#include "inst.h" + +enum allow_overlap { + ao_none, + ao_touch, + ao_any, +}; + + +/* + * Avoid inst.h -> layer.h -> overlay.h -> inst.h loop + */ + +struct inst; /* @@ -27,6 +39,7 @@ int inside(const struct inst *a, const struct inst *b); * "overlap" returns 1 if "a" and "b" have at least one point in common. */ -int overlap(const struct inst *a, const struct inst *b); +int overlap(const struct inst *a, const struct inst *b, + enum allow_overlap allow); #endif /* !OVERLAP_H */