Root/
Source at commit 57dbeb1aadf3d3fad2e5bebcc9a1d147b9f22019 created 11 years 8 months ago. By Werner Almesberger, gui_status.c (show_pad_type): share pad type to name translation | |
---|---|
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 | |
44 | layer_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 | |
71 | enum 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 | |
89 | const 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 | |
111 | layer_type mech_hole_layers(void) |
112 | { |
113 | return LAYER_MASK_TOP | LAYER_MASK_BOTTOM; |
114 | } |
115 | |
116 | |
117 | /* ----- Refine layers after instantiation --------------------------------- */ |
118 | |
119 | |
120 | static 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 | |
139 | static 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 | |
171 | static 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 | |
182 | int 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 |
Branches:
master