From e047cc074dbb55a57c011636447ef75deaca22b7 Mon Sep 17 00:00:00 2001 From: werner Date: Sun, 25 Apr 2010 15:27:27 +0000 Subject: [PATCH] Holes can now also be output as KiCad modules. - gui_style.c (gc_rim): slightly increased brightness when inactive - kicad.c (kicad_pad): move coordinate transform to new function kicad_centric - kicad.c: added pads with holes and mechanical holes - inst.h (struct inst.u.hole), inst.c (inst_hole): added "layers" field, like for pads - layer.c (LAYER_COPPER, LAYER_PASTE, LAYER_MASK): renamed to LAYER_*_TOP and added macros for corresponding bottom layers - layer.c (refine_layers): mirror top layers of through-hole pads - layer.h, layer.c (mech_hole_layers): return the layer set for mechanical layers git-svn-id: http://svn.openmoko.org/trunk/eda/fped@5941 99fdad57-331a-0410-800a-d7fa5415bdb3 --- gui_style.c | 2 +- inst.c | 1 + inst.h | 1 + kicad.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++------ layer.c | 63 ++++++++++++++++++++++++++----------- layer.h | 6 ++-- 6 files changed, 133 insertions(+), 31 deletions(-) diff --git a/gui_style.c b/gui_style.c index c308c61..33a45b9 100644 --- a/gui_style.c +++ b/gui_style.c @@ -71,7 +71,7 @@ void gui_setup_style(GdkDrawable *drawable) style(gc_pad_mask, "#000040", "#0000ff", "#ffff80", 2); style(gc_ptext, "#404040", "#ffffff", "#ffffff", 1); style(gc_hole, "#000000", "#000000", "#000000", 0); - style(gc_rim, "#202020", "#606060", "#ffff80", 3); + style(gc_rim, "#303030", "#606060", "#ffff80", 3); style(gc_meas, "#280040", "#ff00ff", "#ffff80", 1); style(gc_frame, "#005000", "#009000", "#ffff80", 1); diff --git a/inst.c b/inst.c index 88a8804..6f24c9e 100644 --- a/inst.c +++ b/inst.c @@ -933,6 +933,7 @@ int inst_hole(struct obj *obj, struct coord a, struct coord b) inst = add_inst(&hole_ops, ip_hole, a); inst->obj = obj; inst->u.hole.other = b; + inst->u.pad.layers = mech_hole_layers(); find_inst(inst); update_bbox(&inst->bbox, b); propagate_bbox(inst); diff --git a/inst.h b/inst.h index 54f75a0..cbf8f1f 100644 --- a/inst.h +++ b/inst.h @@ -102,6 +102,7 @@ struct inst { } pad; struct { struct coord other; + layer_type layers; /* bit-set of layers (mech only) */ struct inst *pad; /* through-hole pad of NULL */ } hole; struct { diff --git a/kicad.c b/kicad.c index 5e78422..4eb4b50 100644 --- a/kicad.c +++ b/kicad.c @@ -1,8 +1,8 @@ /* * kicad.c - Dump objects in the KiCad board/module format * - * 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 @@ -20,15 +20,22 @@ #include "kicad.h" -static void kicad_pad(FILE *file, const struct inst *inst) +static unit_type zeroize(unit_type n) +{ + return n == -1 || n == 1 ? 0 : n; +} + + +static void kicad_centric(struct coord a, struct coord b, + struct coord *center, struct coord *size) { 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); + min.x = units_to_kicad(a.x); + min.y = units_to_kicad(a.y); + max.x = units_to_kicad(b.x); + max.y = units_to_kicad(b.y); if (min.x > max.x) { tmp = min.x; @@ -41,6 +48,40 @@ static void kicad_pad(FILE *file, const struct inst *inst) max.y = tmp; } + size->x = max.x-min.x; + size->y = max.y-min.y; + center->x = (min.x+max.x)/2; + center->y = -(min.y+max.y)/2; +} + + +static void do_drill(FILE *file, const struct inst *pad, struct coord *ref) +{ + const struct inst *hole = pad->u.pad.hole; + struct coord center, size; + + if (!hole) + return; + + kicad_centric(hole->base, hole->u.hole.other, ¢er, &size); + + /* Allow for rounding errors */ + + fprintf(file, "Dr %d %d %d", size.x, + -zeroize(center.x-ref->x), -zeroize(center.y-ref->y)); + if (size.x < size.y-1 || size.x > size.y+1) + fprintf(file, " O %d %d", size.x, size.y); + fprintf(file, "\n"); + *ref = center; +} + + +static void kicad_pad(FILE *file, const struct inst *inst) +{ + struct coord center, size; + + kicad_centric(inst->base, inst->u.pad.other, ¢er, &size); + fprintf(file, "$PAD\n"); /* @@ -48,22 +89,49 @@ static void kicad_pad(FILE *file, const struct inst *inst) */ fprintf(file, "Sh \"%s\" %c %d %d 0 0 0\n", inst->u.pad.name, inst->obj->u.pad.rounded ? 'O' : 'R', - max.x-min.x, max.y-min.y); + size.x, size.y); + + /* + * Drill hole + */ + do_drill(file, inst, ¢er); /* * Attributes: pad type, N, layer mask */ - fprintf(file, "At SMD N %8.8X\n", (unsigned) inst->u.pad.layers); + fprintf(file, "At %s N %8.8X\n", + inst->u.pad.hole ? "STD" : "SMD", (unsigned) inst->u.pad.layers); /* * Position: Xpos, Ypos */ - fprintf(file, "Po %d %d\n", (min.x+max.x)/2, -(min.y+max.y)/2); + fprintf(file, "Po %d %d\n", center.x, center.y); fprintf(file, "$EndPAD\n"); } +static void kicad_hole(FILE *file, const struct inst *inst) +{ + struct coord center, size; + + if (inst->u.hole.pad) + return; + kicad_centric(inst->base, inst->u.hole.other, ¢er, &size); + fprintf(file, "$PAD\n"); + if (size.x < size.y-1 || size.x > size.y+1) { + fprintf(file, "Sh \"HOLE\" O %d %d 0 0 0\n", size.x, size.y); + fprintf(file, "Dr %d 0 0 O %d %d\n", size.x, size.x, size.y); + } else { + fprintf(file, "Sh \"HOLE\" C %d %d 0 0 0\n", size.x, size.x); + fprintf(file, "Dr %d 0 0\n", size.x); + } + fprintf(file, "At HOLE N %8.8X\n", (unsigned) inst->u.hole.layers); + fprintf(file, "Po %d %d\n", center.x, center.y); + fprintf(file, "$EndPAD\n"); +} + + static void kicad_line(FILE *file, const struct inst *inst) { /* @@ -152,6 +220,9 @@ static void kicad_inst(FILE *file, enum inst_prio prio, const struct inst *inst) case ip_pad_special: kicad_pad(file, inst); break; + case ip_hole: + kicad_hole(file, inst); + break; case ip_line: kicad_line(file, inst); break; diff --git a/layer.c b/layer.c index 75b0a47..eb952e5 100644 --- a/layer.c +++ b/layer.c @@ -1,8 +1,8 @@ /* * layer.c - PCB layers on a pad * - * 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 @@ -30,9 +30,12 @@ * Shorthands for the layers we use in a general sense. */ -#define LAYER_COPPER (1 << layer_top) -#define LAYER_PASTE (1 << layer_paste_top) -#define LAYER_MASK (1 << layer_mask_top) +#define LAYER_COPPER_TOP (1 << layer_top) +#define LAYER_PASTE_TOP (1 << layer_paste_top) +#define LAYER_MASK_TOP (1 << layer_mask_top) +#define LAYER_COPPER_BOTTOM (1 << layer_bottom) +#define LAYER_PASTE_BOTTOM (1 << layer_paste_bottom) +#define LAYER_MASK_BOTTOM (1 << layer_mask_bottom) /* ----- Conversion between pad types and layer sets ----------------------- */ @@ -44,16 +47,16 @@ layer_type pad_type_to_layers(enum pad_type type) switch (type) { case pt_normal: - layers = LAYER_PASTE; + layers = LAYER_PASTE_TOP; /* fall through */ case pt_bare: - layers |= LAYER_COPPER | LAYER_MASK; + layers |= LAYER_COPPER_TOP | LAYER_MASK_TOP; break; case pt_paste: - layers = LAYER_PASTE; + layers = LAYER_PASTE_TOP; break; case pt_mask: - layers = LAYER_MASK; + layers = LAYER_MASK_TOP; break; default: abort(); @@ -64,27 +67,37 @@ layer_type pad_type_to_layers(enum pad_type type) enum pad_type layers_to_pad_type(layer_type layers) { - if (layers & LAYER_COPPER) { - if (layers & LAYER_PASTE) + if (layers & LAYER_COPPER_TOP) { + if (layers & LAYER_PASTE_TOP) return pt_normal; return pt_bare; } else { - if (layers & LAYER_PASTE) + if (layers & LAYER_PASTE_TOP) return pt_paste; - if (layers & LAYER_MASK) + if (layers & LAYER_MASK_TOP) return pt_mask; abort(); } } +/* ----- layers in mechanical holes ---------------------------------------- */ + + +layer_type mech_hole_layers(void) +{ + return LAYER_PASTE_TOP | LAYER_PASTE_BOTTOM | + LAYER_MASK_TOP | LAYER_MASK_BOTTOM; +} + + /* ----- Refine layers after instantiation --------------------------------- */ static int refine_overlapping(struct inst *copper, struct inst *other) { - if (other->u.pad.layers & LAYER_PASTE) { - copper->u.pad.layers &= ~LAYER_PASTE; + if (other->u.pad.layers & LAYER_PASTE_TOP) { + copper->u.pad.layers &= ~LAYER_PASTE_TOP; if (!inside(other, copper)) { fail("solder paste without copper underneath " "(\"%s\" line %d, \"%s\" line %d)", @@ -94,8 +107,8 @@ static int refine_overlapping(struct inst *copper, struct inst *other) return 0; } } - if (other->u.pad.layers & LAYER_MASK) - copper->u.pad.layers &= ~LAYER_MASK; + if (other->u.pad.layers & LAYER_MASK_TOP) + copper->u.pad.layers &= ~LAYER_MASK_TOP; return 1; } @@ -131,6 +144,17 @@ static int refine_copper(const struct pkg *pkg_copper, struct inst *copper) } +static void mirror_layers(layer_type *layers) +{ + if (*layers & LAYER_COPPER_TOP) + *layers |= LAYER_COPPER_BOTTOM; + if (*layers & LAYER_PASTE_TOP) + *layers |= LAYER_PASTE_BOTTOM; + if (*layers & LAYER_MASK_TOP) + *layers |= LAYER_MASK_BOTTOM; +} + + int refine_layers(void) { const struct pkg *pkg; @@ -138,8 +162,11 @@ int refine_layers(void) for (pkg = pkgs; pkg; pkg = pkg->next) for (copper = pkg->insts[ip_pad_copper]; copper; - copper = copper->next) + copper = copper->next) { if (!refine_copper(pkg, copper)) return 0; + if (copper->u.pad.hole) + mirror_layers(&copper->u.pad.layers); + } return 1; } diff --git a/layer.h b/layer.h index adc0dc2..84cddd6 100644 --- a/layer.h +++ b/layer.h @@ -1,8 +1,8 @@ /* * layer.h - PCB layers on a pad * - * 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 @@ -73,6 +73,8 @@ enum pad_type { layer_type pad_type_to_layers(enum pad_type type); enum pad_type layers_to_pad_type(layer_type layers); +layer_type mech_hole_layers(void); + int refine_layers(void); #endif /* !LAYER_H */