Horizon
priv.h
1 /*
2  * Copyright 2019 Martin Ã…berg
3  *
4  * This file is part of Footag.
5  *
6  * Footag is free software: you can redistribute it and/or modify it under the
7  * terms of the GNU General Public License as published by the Free Software
8  * Foundation, either version 3 of the License, or (at your option) any later
9  * version.
10  *
11  * Footag is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <footag/footag.h>
21 #include <math.h>
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #ifndef UNUSED
26  #define UNUSED(i) (void) (sizeof (i))
27 #endif
28 
29 #ifndef NELEM
30  #define NELEM(a) ((sizeof a) / (sizeof (a[0])))
31 #endif
32 
33 struct footag_op {
34  size_t size;
35  int (*init)(struct footag_ctx *ctx);
36  int (*fini)(struct footag_ctx *ctx);
37  int (*calc)(struct footag_ctx *ctx);
38  const char * (*hint)(
39  struct footag_ctx *ctx,
40  const struct footag_param *p
41  );
42  /* Description of component type, for use by application. */
43  const struct footag_typeinfo *info;
44  /* Parameter template, terminated with */
45  const struct footag_param *temp;
46 };
47 
48 struct footag_ctx {
49  const struct footag_op *op;
50  struct footag_param *param;
51  struct footag_spec spec;
52 };
53 
54 #define ITEM_NONE { \
55  .type = FOOTAG_DATA_NONE, \
56 }
57 
58 #define ITEM_BOOL(_val) { \
59  .type = FOOTAG_DATA_BOOL, \
60  .data = { \
61  .b = (_val), \
62  }, \
63 }
64 
65 #define ITEM_INTEGER(_val, _step, _min, _max) { \
66  .type = FOOTAG_DATA_INTEGER, \
67  .data = { \
68  .i = { \
69  .val = (_val), \
70  .step = (_step), \
71  .min = (_min), \
72  .max = (_max), \
73  }, \
74  }, \
75 }
76 
77 #define ITEM_FLOAT(_val) { \
78  .type = FOOTAG_DATA_FLOAT, \
79  .data = { \
80  .f = (_val), \
81  }, \
82 }
83 
84 #define ITEM_LENGTH(_val) { \
85  .type = FOOTAG_DATA_LENGTH, \
86  .data = { \
87  .l = (_val), \
88  }, \
89 }
90 
91 /* nom, plus minus */
92 #define ITEM_TOL_PM(_nom, _pm) { \
93  .type = FOOTAG_DATA_TOL, \
94  .data = { \
95  .t = { \
96  .nom = (_nom), \
97  .min = (_nom - _pm), \
98  .max = (_nom + _pm), \
99  } \
100  }, \
101 }
102 
103 /* min, max */
104 #define ITEM_TOL_MM(_min, _max) { \
105  .type = FOOTAG_DATA_TOL, \
106  .data = { \
107  .t = { \
108  .nom = ((_min + _max) / 2.0), \
109  .min = (_min), \
110  .max = (_max), \
111  } \
112  }, \
113 }
114 
115 #define ITEM_TOL_DATA(a, b) { \
116  .nom = (a) <= (b) ? ((a + b) / 2.0) : (a), \
117  .min = (a) <= (b) ? (a) : (a - b), \
118  .max = (a) <= (b) ? (b) : (a + b), \
119 }
120 
121 #define ITEM_TOL(_a, _b) { \
122  .type = FOOTAG_DATA_TOL, \
123  .data = { \
124  .t = ITEM_TOL_DATA(_a, _b), \
125  }, \
126 }
127 
128 #define ITEM_ENUM(_val, _num, ...) { \
129  .type = FOOTAG_DATA_ENUM, \
130  .data = { \
131  .e = { \
132  .val = _val, \
133  .num = _num, \
134  .strs = (const char *const []) { __VA_ARGS__ }, \
135  }, \
136  }, \
137 }
138 
139 #define ITEM_BITMASK(_val, _num, ...) { \
140  .type = FOOTAG_DATA_BITMASK, \
141  .data = { \
142  .m = { \
143  .val = _val, \
144  .num = _num, \
145  .strs = (const char *const []) { __VA_ARGS__ }, \
146  }, \
147  }, \
148 }
149 
150 #define PARAM_HEADER(_id, _name, _abbr) \
151  .id = PARAM_ ## _id, \
152  .name = _name, \
153  .abbr = _abbr
154 
155 #define PARAM_TERM { \
156  PARAM_HEADER(DONE, "done", "done"), \
157  .item = ITEM_NONE, \
158 }
159 
160 #define PARAM_TOPIC(_name) { \
161  .id = PARAM_TOPIC, \
162  .name = _name, \
163  .abbr = "", \
164  .item = ITEM_NONE, \
165 }
166 
167 #define PARAM_B(_id, _name, _abbr, _val) { \
168  PARAM_HEADER(_id, _name, _abbr), \
169  .item = ITEM_BOOL(_val), \
170 }
171 
172 #define PARAM_I(_id, _name, _abbr, _val, _step, _min, _max) { \
173  PARAM_HEADER(_id, _name, _abbr), \
174  .item = ITEM_INTEGER(_val, _step, _min, _max), \
175 }
176 
177 #define PARAM_F(_id, _name, _abbr, _val) { \
178  PARAM_HEADER(_id, _name, _abbr), \
179  .item = ITEM_FLOAT(_val), \
180 }
181 
182 #define PARAM_L(_id, _name, _abbr, _val) { \
183  PARAM_HEADER(_id, _name, _abbr), \
184  .item = ITEM_LENGTH(_val), \
185 }
186 
187 #define PARAM_TPM(_id, _name, _abbr, _nom, _pm) { \
188  PARAM_HEADER(_id, _name, _abbr), \
189  .item = ITEM_TOL_PM(_nom, _pm), \
190 }
191 
192 #define PARAM_TMM(_id, _name, _abbr, _min, _max) { \
193  PARAM_HEADER(_id, _name, _abbr), \
194  .item = ITEM_TOL_MM(_min, _max), \
195 }
196 
197 /*
198  * interprets _a and _b, based on their values, as one of the following:
199  * 1. _a: nominal, _b: plus/minus
200  * 2. _a: min, _b: max
201  */
202 #define PARAM_T(_id, _name, _abbr, _a, _b) { \
203  PARAM_HEADER(_id, _name, _abbr), \
204  .item = ITEM_TOL(_a, _b), \
205 }
206 
207 #define PARAM_E(_id, _name, _abbr, _val, _num, ...) { \
208  PARAM_HEADER(_id, _name, _abbr), \
209  .item = ITEM_ENUM(_val, _num, __VA_ARGS__), \
210 }
211 
212 #define PARAM_M(_id, _name, _abbr, _val, _num, ...) { \
213  PARAM_HEADER(_id, _name, _abbr), \
214  .item = ITEM_BITMASK(_val, _num, __VA_ARGS__), \
215 }
216 
217 #define PARAM_CALC_IPC7351B \
218  PARAM_TOPIC("Calc"), \
219  PARAM_E(CALC_D, "Density", "-", FOOTAG_LEVEL_N, FOOTAG_LEVEL_NUM, \
220  "Most", "Nominal", "Least" \
221  ), \
222  PARAM_L(CALC_F, "Fabrication", "-", 0.10), \
223  PARAM_L(CALC_P, "Placement", "-", 0.10), \
224  PARAM_TOPIC("Generate"), \
225  PARAM_E(CALC_ROUND, "Round-off", "-", 3, 4, \
226  "None", "0.01 mm", "0.02 mm", "0.05 mm" \
227  )
228 
229 #define PARAM_CALC_IPC7351B_HIRES \
230  PARAM_TOPIC("Calc"), \
231  PARAM_E(CALC_D, "Density", "-", FOOTAG_LEVEL_N, FOOTAG_LEVEL_NUM, \
232  "Most", "Nominal", "Least" \
233  ), \
234  PARAM_L(CALC_F, "Fabrication", "-", 0.05), \
235  PARAM_L(CALC_P, "Placement", "-", 0.05), \
236  PARAM_TOPIC("Generate"), \
237  PARAM_E(CALC_ROUND, "Round-off", "-", 1, 4, \
238  "None", "0.01 mm", "0.02 mm", "0.05 mm" \
239  )
240 
241 #define PARAM_CALC_IPC7251DRAFT1 \
242  PARAM_TOPIC("Calc"), \
243  PARAM_E(CALC_D, "Level", "-", FOOTAG_LEVEL_N, FOOTAG_LEVEL_NUM, \
244  "A (Maximum)", "B (Nominal)", "C (Least)" \
245  ), \
246  PARAM_TOPIC("Generate"), \
247  PARAM_E(CALC_ROUND, "Round-off", "-", 3, 4, \
248  "None", "0.01 mm", "0.02 mm", "0.05 mm" \
249  )
250 
251 #define PARAM_PADSTACK_SMD_RECTS \
252  PARAM_E(CALC_STACK, "Padstack", "-", 1, 2, \
253  "Rectangular", "Rounded rectangular" \
254  )
255 
256 int footag_init_from_template(
257  struct footag_ctx *ctx,
258  const struct footag_param *temp
259 );
260 
261 int footag_init_default(
262  struct footag_ctx *ctx
263 );
264 
265 int footag_init_twopin(
266  struct footag_ctx *ctx
267 );
268 
269 int footag_fini_default(
270  struct footag_ctx *ctx
271 );
272 
273 const union footag_data *footag_data_by_name(
274  struct footag_ctx *ctx,
275  const char *topic,
276  const char *name
277 );
278 
279 const union footag_data *footag_data_by_id(
280  struct footag_ctx *ctx,
281  int id
282 );
283 
284 #define GETID(_ctx, _id) footag_data_by_id(_ctx, PARAM_ ## _id)
285 
286 enum {
287  PARAM_DONE = FOOTAG_PARAM_DONE,
288  PARAM_IGNORE = FOOTAG_PARAM_IGNORE,
289  PARAM_TOPIC = FOOTAG_PARAM_TOPIC,
290  PARAM_BODY_L,
291  PARAM_BODY_W,
292  PARAM_BODY_H,
293  /* number of pins */
294  PARAM_BODY_N,
295  PARAM_BODY_Nx,
296  /* rows */
297  PARAM_BODY_R,
298  /* columns */
299  PARAM_BODY_C,
300  /* perimeter rows and columns */
301  PARAM_BODY_PR,
302  PARAM_BODY_PC,
303  /* polarized */
304  PARAM_BODY_POL,
305  PARAM_LEAD_L,
306  PARAM_LEAD_W,
307  PARAM_LEAD_W1,
308  /* diameter */
309  PARAM_LEAD_D,
310  /* pullback */
311  PARAM_LEAD_PB,
312  /* span */
313  PARAM_LEAD_S,
314  PARAM_LEAD_Sx,
315  /* pitch: spacing between leads or castellations */
316  PARAM_LEAD_P,
317  PARAM_CALC_D,
318  PARAM_CALC_F,
319  PARAM_CALC_P,
320  PARAM_CALC_STACK,
321  PARAM_CALC_ROUND,
322  PARAM_NAME_ROW,
323  PARAM_CUSTOM,
324 };
325 
326 /* translate from PARAM_CALC_D to FOOTAG_LEVEL_ */
327 static inline int footag_get_density(
328  const struct footag_enum *e
329 )
330 {
331  return e->val;
332 }
333 
334 /*
335  * IPC-7351B seems to say 0.05
336  */
337 static const double ROUNDOFF_TO_GRID[4] = {
338  [0] = 0.00,
339  [1] = 0.01,
340  [2] = 0.02,
341  [3] = 0.05,
342 };
343 
344 /* NOTE: snap is an operation and grid is a property */
345 static inline double snap(double v, double grid)
346 {
347  if (!grid) { return v; }
348  return round(v / grid) * grid;
349 }
350 
351 /*
352  * round to grid:
353  * - placement
354  * - dimensions
355  * - parameter (radius)
356  */
357 void footag_snap(
358  struct footag_spec *s,
359  double grid
360 );
361 
362 void footag_setcourtyard(
363  struct footag_spec *s,
364  double cyexc
365 );
366 
367 static inline double footag_padypos(double pitch, int rows, int row)
368 {
369  double y;
370  y = - 1 * ((rows / 2.0) - 1.0 / 2);
371  y += row;
372  y *= pitch;
373  return y;
374 }
375 
376 void footag_gridnames(
377  struct footag_pad *p,
378  const struct footag_bitmask *const skipmask,
379  int rows,
380  int cols
381 );
382 
383 void footag_gennames(
384  struct footag_pad *p,
385  int npads,
386  int startnum,
387  int deltanum
388 );
389 
390 void footag_genrow(
391  struct footag_pad *p,
392  double addx, double addy,
393  double pitch,
394  /* start positions */
395  int x, int y,
396  int dx, int dy,
397  int rows,
398  long angle
399 );
400 
401 void footag_gentworow(
402  struct footag_pad *p,
403  double dist,
404  double w, double h,
405  double pitch,
406  int npads,
407  enum footag_padstack stack
408 );
409 
410 void footag_genquad(
411  struct footag_pad *p,
412  double distrow,
413  double wrow, double hrow,
414  double distcol,
415  double wcol, double hcol,
416  double pitch,
417  int rows, int cols,
418  enum footag_padstack stack
419 );
420 
421 void footag_gengrid(
422  struct footag_pad *p,
423  double w, double h,
424  double pitch,
425  int rows, int cols,
426  int prows, int pcols,
427  enum footag_padstack stack
428 );
429 
430 void footag_genlrow(
431  struct footag_pad *p,
432  double dist,
433  double w, double h,
434  double pitch,
435  int npads,
436  enum footag_padstack stack
437 );
438 
439 void footag_genrrow(
440  struct footag_pad *p,
441  double dist,
442  double w, double h,
443  double pitch,
444  int npads,
445  enum footag_padstack stack
446 );
447 
448 void footag_gentwopin(
449  struct footag_pad *p,
450  double dist,
451  double w, double h,
452  enum footag_padstack stack
453 );
454 
455 void footag_ipc7351b_setrrectpad(
456  struct footag_pad *p
457 );
458 
459 void footag_ipc7351b_setrrectpads(
460  const struct footag_spec *s
461 );
462 
463 int footag_realloc_pads(
464  struct footag_ctx *ctx,
465  int npads
466 );
467 
468 static inline int intmin(int a, int b) { return a < b ? a : b; }
469 static inline int intmax(int a, int b) { return a < b ? b : a; }
470 
471 static inline struct footag_rlimit footag_crlimit(
472  double w,
473  double h
474 )
475 {
476  return (const struct footag_rlimit) {
477  .minx = - w / 2.0,
478  .maxx = w / 2.0,
479  .miny = - h / 2.0,
480  .maxy = h / 2.0,
481  };
482 }
483 
484 const char *footag_hint_ipc7251draft1(
485  struct footag_ctx *ctx,
486  const struct footag_param *p
487 );
488 
489 struct ipcb_ref;
490 void footag_setref_ipc7351b(
491  struct footag_spec *s,
492  const struct ipcb_ref *ref
493 );
494 
495 struct ipc7251_ref;
496 void footag_setref_ipc7251draft1(
497  struct footag_spec *s,
498  const struct ipc7251_ref *ref
499 );
500 
footag_typeinfo
Definition: footag.h:184
ipc7251_ref
Definition: ipc7251draft1.h:52
footag_rlimit
Definition: footag.h:122
footag_enum
Definition: footag.h:45
footag_param
Definition: footag.h:85
footag_spec
Definition: footag.h:139
footag_pad
Definition: footag.h:109
footag_data
Definition: footag.h:64
footag_op
Definition: priv.h:33
ipcb_ref
Definition: ipc7351b.h:111
footag_bitmask
Definition: footag.h:51
footag_ctx
Definition: priv.h:48