Root/layer.c

Source at commit 8a1a3103964533b0d517a29312ddeabdab1d6271 created 4 years 9 months ago.
By Werner Almesberger, inst.c (find_point_vec): correct indentation
1/*
2 * layer.c - PCB layers on a pad
3 *
4 * Written 2009-2012 by Werner Almesberger
5 * Copyright 2009-2012 by Werner Almesberger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13/*
14 * We don't reject solder paste pads that don't cover anything yet.
15 * That way, things can be constructed step by step without getting blue
16 * screens all the time.
17 */
18
19
20#include <stdlib.h>
21
22#include "error.h"
23#include "overlap.h"
24#include "inst.h"
25#include "obj.h"
26#include "layer.h"
27
28
29/*
30 * Shorthands for the layers we use in a general sense.
31 */
32
33#define LAYER_COPPER_TOP (1 << layer_top)
34#define LAYER_PASTE_TOP (1 << layer_paste_top)
35#define LAYER_MASK_TOP (1 << layer_mask_top)
36#define LAYER_COPPER_BOTTOM (1 << layer_bottom)
37#define LAYER_PASTE_BOTTOM (1 << layer_paste_bottom)
38#define LAYER_MASK_BOTTOM (1 << layer_mask_bottom)
39
40
41/* ----- Conversion between pad types and layer sets ----------------------- */
42
43
44layer_type pad_type_to_layers(enum pad_type type)
45{
46    layer_type layers = 0;
47
48    switch (type) {
49    case pt_normal:
50        layers = LAYER_PASTE_TOP;
51        /* fall through */
52    case pt_bare:
53        layers |= LAYER_COPPER_TOP | LAYER_MASK_TOP;
54        break;
55    case pt_trace:
56        layers = LAYER_COPPER_TOP;
57        break;
58    case pt_paste:
59        layers = LAYER_PASTE_TOP;
60        break;
61    case pt_mask:
62        layers = LAYER_MASK_TOP;
63        break;
64    default:
65        abort();
66    }
67    return layers;
68}
69
70
71enum pad_type layers_to_pad_type(layer_type layers)
72{
73    if (layers & LAYER_COPPER_TOP) {
74        if (layers & LAYER_PASTE_TOP)
75            return pt_normal;
76        if (layers & LAYER_MASK_TOP)
77            return pt_bare;
78        return pt_trace;
79    } else {
80        if (layers & LAYER_PASTE_TOP)
81            return pt_paste;
82        if (layers & LAYER_MASK_TOP)
83            return pt_mask;
84        abort();
85    }
86}
87
88
89const char *pad_type_name(enum pad_type type)
90{
91    switch (type) {
92    case pt_normal:
93        return "normal";
94    case pt_bare:
95        return "bare";
96    case pt_trace:
97        return "trace";
98    case pt_paste:
99        return "paste";
100    case pt_mask:
101        return "mask";
102    default:
103        abort();
104    }
105}
106
107
108/* ----- layers in mechanical holes ---------------------------------------- */
109
110
111layer_type mech_hole_layers(void)
112{
113    return LAYER_MASK_TOP | LAYER_MASK_BOTTOM;
114}
115
116
117/* ----- Refine layers after instantiation --------------------------------- */
118
119
120static int refine_overlapping(struct inst *copper, struct inst *other)
121{
122    if (other->u.pad.layers & LAYER_PASTE_TOP) {
123        copper->u.pad.layers &= ~LAYER_PASTE_TOP;
124        if (!inside(other, copper)) {
125            fail("solder paste without copper underneath "
126                "(\"%s\" line %d, \"%s\" line %d)",
127                copper->u.pad.name, copper->obj->lineno,
128                other->u.pad.name, other->obj->lineno);
129            instantiation_error = other->obj;
130            return 0;
131        }
132    }
133    if (other->u.pad.layers & LAYER_MASK_TOP)
134        copper->u.pad.layers &= ~LAYER_MASK_TOP;
135    return 1;
136}
137
138
139static int refine_copper(const struct pkg *pkg_copper, struct inst *copper,
140    enum allow_overlap allow)
141{
142    const struct pkg *pkg;
143    struct inst *other;
144
145    for (pkg = pkgs; pkg; pkg = pkg->next) {
146        /*
147         * Pads in distinct packages can happily coexist.
148         */
149        if (pkg != pkgs && pkg_copper != pkgs && pkg_copper != pkg)
150            continue;
151        for (other = pkg->insts[ip_pad_copper]; other;
152            other = other->next)
153            if (copper != other && overlap(copper, other, allow)) {
154                fail("overlapping copper pads "
155                    "(\"%s\" line %d, \"%s\" line %d)",
156                    copper->u.pad.name, copper->obj->lineno,
157                    other->u.pad.name, other->obj->lineno);
158                instantiation_error = copper->obj;
159                return 0;
160            }
161        for (other = pkg->insts[ip_pad_special]; other;
162            other = other->next)
163            if (overlap(copper, other, ao_none))
164                if (!refine_overlapping(copper, other))
165                    return 0;
166    }
167    return 1;
168}
169
170
171static void mirror_layers(layer_type *layers)
172{
173    if (*layers & LAYER_COPPER_TOP)
174        *layers |= LAYER_COPPER_BOTTOM;
175    if (*layers & LAYER_PASTE_TOP)
176        *layers |= LAYER_PASTE_BOTTOM;
177    if (*layers & LAYER_MASK_TOP)
178        *layers |= LAYER_MASK_BOTTOM;
179}
180
181
182int refine_layers(enum allow_overlap allow)
183{
184    const struct pkg *pkg;
185    struct inst *copper;
186
187    for (pkg = pkgs; pkg; pkg = pkg->next)
188        for (copper = pkg->insts[ip_pad_copper]; copper;
189            copper = copper->next) {
190            if (!refine_copper(pkg, copper, allow))
191                return 0;
192            if (copper->u.pad.hole)
193                mirror_layers(&copper->u.pad.layers);
194        }
195    return 1;
196}
197

Archive Download this file

Branches:
master



interactive