More work on holes: added documentation and Postscript output.

- overlap.c (inside, test_overlap): check for instance type 
- overlap.c (inside, test_overlap): support hole instances
- README: put a pointer to the GUI description at the beginning
- README, gui.html: documented role and creation of holes
- inst.h: holes can now link to pads and vice versa
- hole.c, obj.c (instantiate): connect holes with pads and apply consistency 
  checks
- postscript.c: added output for holes
- icons/hole.fig: make hatched surroundings of hole look more round



git-svn-id: http://svn.openmoko.org/trunk/eda/fped@5940 99fdad57-331a-0410-800a-d7fa5415bdb3
This commit is contained in:
werner 2010-04-25 13:09:36 +00:00
parent 1dda2ac2ae
commit 6db067a90f
10 changed files with 209 additions and 17 deletions

View File

@ -16,7 +16,7 @@ UPLOAD = werner@sita.openmoko.org:public_html/fped/
OBJS = fped.o expr.o coord.o obj.o delete.o inst.o util.o error.o \
unparse.o file.o dump.o kicad.o postscript.o meas.o \
layer.o overlap.o \
layer.o overlap.o hole.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_tool.o gui_over.o gui_meas.o gui_frame.o gui_frame_drag.o

22
README
View File

@ -9,6 +9,11 @@ The language is constrained such that anything that can be expressed in
the textual definition also has a straightforward equivalent operation
that can be performed through the GUI.
This README describes only the footprint definition language. A
description of the GUI can be found here:
http://people.openmoko.org/werner/fped/gui.html
This work is distributed under the terms of the GNU GENERAL PUBLIC
LICENSE, Version 2:
@ -251,6 +256,23 @@ If enclosed in a square, rounded pads form a circle.
rpad "<name>" <point-a> <point-b> [<type>]
Holes
- - -
Holes can be used for through-hole pins or for mechanical support.
In the former case, the hole must be placed inside a pad. Only one
hole per pad is allowed. Mechanical holes must be outside any pads.
Through-hole pads are always present on both sides of the board, i.e.,
when fped generates a KiCad module, the surface layers of a pad
containing a hole are propagated to the opposite side of the board.
Holes have the same shape as a rounded pad and their geometry is
defined in the same way:
hole <point-a> <point-b>
Measurements
- - - - - -

View File

@ -222,6 +222,15 @@ Tools are used to add new elements and to manipulate existing ones.
containing the pad. Move the mouse cursor to the first point, then
drag to the second point. The pad's name can be edited after selecting
the pad.
<DT><IMG src="manual/hole.png">
<DD> Add a hole. There are two purposes for holes:
<UL>
<LI> Pins of through-hole components. In this case, the hole has to be
inside a pad.
<LI> Mechanical support. In this case, the hole has to be outside any
pads.
</UL>
The construction of holes is the same as for pads.
<DT><IMG src="manual/line.png">&nbsp;<IMG src="manual/rect.png">
<DD> Add a line or a rectangle. Similar to pads, lines and rectangles
are defined by two points. The width of the line can be edited after

86
hole.c Normal file
View File

@ -0,0 +1,86 @@
/*
* hole.c - Classify holes and connect them with pads
*
* Written 2010 by Werner Almesberger
* Copyright 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include "error.h"
#include "inst.h"
#include "overlap.h"
#include "hole.h"
static int check_through_hole(struct inst *pad, struct inst *hole)
{
if (!overlap(pad, hole))
return 1;
if (!inside(hole, pad)) {
fail("hole (line %d) not completely inside "
"pad \"%s\" (line %d)", hole->obj->lineno,
pad->u.pad.name, pad->obj->lineno);
instantiation_error = pad->obj;
return 0;
}
if (hole->u.hole.pad) {
/*
* A hole can only be on several pads if the pads themselves
* overlap. We'll catch this error in refine_copper.
*/
return 1;
}
if (pad->u.pad.hole) {
fail("pad \"%s\" (line %d) has multiple holes (lines %d, %d)",
pad->u.pad.name, pad->obj->lineno,
hole->obj->lineno, pad->u.pad.hole->obj->lineno);
instantiation_error = pad->obj;
return 0;
}
pad->u.pad.hole = hole;
hole->u.hole.pad = pad;
return 1;
}
static int connect_holes(const struct pkg *pkg)
{
struct inst *pad, *hole;
for (pad = pkg->insts[ip_pad_copper]; pad; pad = pad->next)
for (hole = pkg->insts[ip_hole]; hole; hole = hole->next)
if (!check_through_hole(pad, hole))
return 0;
return 1;
}
static void clear_links(const struct pkg *pkg)
{
struct inst *pad, *hole;
for (pad = pkg->insts[ip_pad_copper]; pad; pad = pad->next)
pad->u.pad.hole = NULL;
for (pad = pkg->insts[ip_pad_special]; pad; pad = pad->next)
pad->u.pad.hole = NULL;
for (hole = pkg->insts[ip_hole]; hole; hole = hole->next)
hole->u.hole.pad = NULL;
}
int link_holes(void)
{
const struct pkg *pkg;
for (pkg = pkgs; pkg; pkg = pkg->next) {
clear_links(pkg);
if (!connect_holes(pkg))
return 0;
}
return 1;
}

18
hole.h Normal file
View File

@ -0,0 +1,18 @@
/*
* hole.h - Classify holes and connect them with pads
*
* Written 2010 by Werner Almesberger
* Copyright 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef HOLE_H
#define HOLE_H
int link_holes(void);
#endif /* !HOLE_H */

View File

@ -7,12 +7,11 @@ A4
Single
-2
1200 2
6 3600 2400 6000 4800
1 3 0 8 0 7 45 -1 20 0.000 1 0.0000 4800 3600 600 600 4800 3600 5400 3600
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
3600 2400 6000 2400 6000 4800 3600 4800 3600 2400
2 1 0 5 0 7 50 -1 20 0.000 0 1 -1 0 0 2
3900 4500 5700 2700
4050 4350 5550 2850
2 1 0 5 0 7 50 -1 20 0.000 0 1 -1 0 0 2
3900 3900 5100 2700
2 1 0 5 0 7 50 -1 20 0.000 0 1 -1 0 0 2
@ -21,4 +20,3 @@ Single
4500 4500 5700 3300
2 1 0 5 0 7 50 -1 20 0.000 0 1 -1 0 0 2
5100 4500 5700 3900
-6

2
inst.h
View File

@ -98,9 +98,11 @@ struct inst {
char *name;
struct coord other;
layer_type layers; /* bit-set of layers */
struct inst *hole; /* through-hole or NULL */
} pad;
struct {
struct coord other;
struct inst *pad; /* through-hole pad of NULL */
} hole;
struct {
unit_type r;

3
obj.c
View File

@ -20,6 +20,7 @@
#include "expr.h"
#include "meas.h"
#include "inst.h"
#include "hole.h"
#include "layer.h"
#include "delete.h"
#include "obj.h"
@ -475,6 +476,8 @@ int instantiate(void)
activate_found();
find_vec = NULL;
find_obj = NULL;
if (ok)
ok = link_holes();
if (ok)
ok = refine_layers();
if (ok)

View File

@ -1,8 +1,8 @@
/*
* overlap.c - 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
@ -11,6 +11,8 @@
*/
#include <stdlib.h>
#include "coord.h"
#include "obj.h"
#include "inst.h"
@ -18,7 +20,7 @@
/*
* @@@ result may be too optimistic if "b" is arounded pad.
* @@@ result may be too optimistic if "b" is a rounded pad
*/
int inside(const struct inst *a, const struct inst *b)
@ -27,11 +29,29 @@ int inside(const struct inst *a, const struct inst *b)
struct coord min_b, max_b;
min_a = a->base;
max_a = a->u.pad.other;
switch (a->obj->type) {
case ot_pad:
max_a = a->u.pad.other;
break;
case ot_hole:
max_a = a->u.hole.other;
break;
default:
abort();
}
sort_coord(&min_a, &max_a);
min_b = b->base;
max_b = b->u.pad.other;
switch (b->obj->type) {
case ot_pad:
max_b = b->u.pad.other;
break;
case ot_hole:
max_b = b->u.hole.other;
break;
default:
abort();
}
sort_coord(&min_b, &max_b);
return min_a.x >= min_b.x && max_a.x <= max_b.x &&
@ -142,15 +162,27 @@ static int test_overlap(const struct inst *a, const struct inst *b,
{
struct coord min, max;
unit_type h, w, r;
int rounded;
min = a->base;
max = a->u.pad.other;
switch (a->obj->type) {
case ot_pad:
max = a->u.pad.other;
rounded = a->obj->u.pad.rounded;
break;
case ot_hole:
max = a->u.hole.other;
rounded = 1;
break;
default:
abort();
}
sort_coord(&min, &max);
h = max.y-min.y;
w = max.x-min.x;
if (!a->obj->u.pad.rounded)
if (!rounded)
return do_rect(b, other, min.x, min.y, w, h);
if (h > w) {

View File

@ -64,6 +64,8 @@
#define PS_HATCH mm_to_units(0.1)
#define PS_HATCH_LINE mm_to_units(0.015)
#define PS_RIM_LINE mm_to_units(0.02)
#define PS_FONT_OUTLINE mm_to_units(0.025)
#define PS_VEC_LINE mm_to_units(0.02)
@ -220,21 +222,19 @@ static void ps_pad(FILE *file, const struct inst *inst, int show_name)
fprintf(file, " closepath gsave %s grestore stroke\n",
hatch(inst->u.pad.layers));
if (show_name)
if (show_name && !inst->u.pad.hole)
ps_pad_name(file, inst);
}
static void ps_rpad(FILE *file, const struct inst *inst, int show_name)
static void ps_rounded_rect(FILE *file, struct coord a, struct coord b)
{
struct coord a = inst->base;
struct coord b = inst->u.pad.other;
unit_type h, w, r;
sort_coord(&a, &b);
h = b.y-a.y;
w = b.x-a.x;
fprintf(file, "0 setgray %d setlinewidth\n", PS_HATCH_LINE);
if (h > w) {
r = w/2;
fprintf(file, " %d %d moveto\n", b.x, b.y-r);
@ -248,14 +248,33 @@ static void ps_rpad(FILE *file, const struct inst *inst, int show_name)
fprintf(file, " %d %d lineto\n", a.x+r, b.y);
fprintf(file, " %d %d %d 90 270 arc\n", a.x+r, a.y+r, r);
}
}
static void ps_rpad(FILE *file, const struct inst *inst, int show_name)
{
fprintf(file, "0 setgray %d setlinewidth\n", PS_HATCH_LINE);
ps_rounded_rect(file, inst->base, inst->u.pad.other);
fprintf(file, " closepath gsave %s grestore stroke\n",
hatch(inst->u.pad.layers));
if (show_name)
if (show_name && !inst->u.pad.hole)
ps_pad_name(file, inst);
}
static void ps_hole(FILE *file, const struct inst *inst, int show_name)
{
fprintf(file, "1 setgray %d setlinewidth\n", PS_RIM_LINE);
ps_rounded_rect(file, inst->base, inst->u.hole.other);
fprintf(file, " closepath gsave fill grestore\n");
fprintf(file, " 0 setgray stroke\n");
if (show_name && inst->u.hole.pad)
ps_pad_name(file, inst->u.hole.pad);
}
static void ps_line(FILE *file, const struct inst *inst)
{
struct coord a = inst->base;
@ -485,6 +504,9 @@ static void ps_foreground(FILE *file, enum inst_prio prio,
else
ps_pad(file, inst, active_params.show_pad_names);
break;
case ip_hole:
ps_hole(file, inst, active_params.show_pad_names);
break;
case ip_vec:
if (active_params.show_stuff)
ps_vec(file, inst);