KiCad PCB EDA Suite
lset.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2014 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
5  * Copyright (C) 2014-2017 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 
26 #include <stdarg.h>
27 #include <assert.h>
28 
30 #include <class_board.h>
31 
32 
33 LSET::LSET( const LAYER_ID* aArray, unsigned aCount ) :
34  BASE_SET()
35 {
36  for( unsigned i=0; i<aCount; ++i )
37  set( aArray[i] );
38 }
39 
40 
41 LSET::LSET( unsigned aIdCount, int aFirst, ... ) :
42  BASE_SET()
43 {
44  // The constructor, without the mandatory aFirst argument, could have been confused
45  // by the compiler with the LSET( LAYER_ID ). With aFirst, that ambiguity is not
46  // present. Therefore aIdCount must always be >=1.
47  wxASSERT_MSG( aIdCount > 0, wxT( "aIdCount must be >= 1" ) );
48 
49  set( aFirst );
50 
51  if( --aIdCount )
52  {
53  va_list ap;
54 
55  va_start( ap, aFirst );
56 
57  for( unsigned i=0; i<aIdCount; ++i )
58  {
59  LAYER_ID id = (LAYER_ID) va_arg( ap, int );
60 
61  // printf( "%s: id:%d LAYER_ID_COUNT:%d\n", __func__, id, LAYER_ID_COUNT );
62 
63  assert( unsigned( id ) < LAYER_ID_COUNT );
64 
65  set( id );
66  }
67 
68  va_end( ap );
69  }
70 }
71 
72 
73 const wxChar* LSET::Name( LAYER_ID aLayerId )
74 {
75  const wxChar* txt;
76 
77  // using a switch to explicitly show the mapping more clearly
78  switch( aLayerId )
79  {
80  case F_Cu: txt = wxT( "F.Cu" ); break;
81  case In1_Cu: txt = wxT( "In1.Cu" ); break;
82  case In2_Cu: txt = wxT( "In2.Cu" ); break;
83  case In3_Cu: txt = wxT( "In3.Cu" ); break;
84  case In4_Cu: txt = wxT( "In4.Cu" ); break;
85  case In5_Cu: txt = wxT( "In5.Cu" ); break;
86  case In6_Cu: txt = wxT( "In6.Cu" ); break;
87  case In7_Cu: txt = wxT( "In7.Cu" ); break;
88  case In8_Cu: txt = wxT( "In8.Cu" ); break;
89  case In9_Cu: txt = wxT( "In9.Cu" ); break;
90  case In10_Cu: txt = wxT( "In10.Cu" ); break;
91  case In11_Cu: txt = wxT( "In11.Cu" ); break;
92  case In12_Cu: txt = wxT( "In12.Cu" ); break;
93  case In13_Cu: txt = wxT( "In13.Cu" ); break;
94  case In14_Cu: txt = wxT( "In14.Cu" ); break;
95  case In15_Cu: txt = wxT( "In15.Cu" ); break;
96  case In16_Cu: txt = wxT( "In16.Cu" ); break;
97  case In17_Cu: txt = wxT( "In17.Cu" ); break;
98  case In18_Cu: txt = wxT( "In18.Cu" ); break;
99  case In19_Cu: txt = wxT( "In19.Cu" ); break;
100  case In20_Cu: txt = wxT( "In20.Cu" ); break;
101  case In21_Cu: txt = wxT( "In21.Cu" ); break;
102  case In22_Cu: txt = wxT( "In22.Cu" ); break;
103  case In23_Cu: txt = wxT( "In23.Cu" ); break;
104  case In24_Cu: txt = wxT( "In24.Cu" ); break;
105  case In25_Cu: txt = wxT( "In25.Cu" ); break;
106  case In26_Cu: txt = wxT( "In26.Cu" ); break;
107  case In27_Cu: txt = wxT( "In27.Cu" ); break;
108  case In28_Cu: txt = wxT( "In28.Cu" ); break;
109  case In29_Cu: txt = wxT( "In29.Cu" ); break;
110  case In30_Cu: txt = wxT( "In30.Cu" ); break;
111  case B_Cu: txt = wxT( "B.Cu" ); break;
112 
113  // Technicals
114  case B_Adhes: txt = wxT( "B.Adhes" ); break;
115  case F_Adhes: txt = wxT( "F.Adhes" ); break;
116  case B_Paste: txt = wxT( "B.Paste" ); break;
117  case F_Paste: txt = wxT( "F.Paste" ); break;
118  case B_SilkS: txt = wxT( "B.SilkS" ); break;
119  case F_SilkS: txt = wxT( "F.SilkS" ); break;
120  case B_Mask: txt = wxT( "B.Mask" ); break;
121  case F_Mask: txt = wxT( "F.Mask" ); break;
122 
123  // Users
124  case Dwgs_User: txt = wxT( "Dwgs.User" ); break;
125  case Cmts_User: txt = wxT( "Cmts.User" ); break;
126  case Eco1_User: txt = wxT( "Eco1.User" ); break;
127  case Eco2_User: txt = wxT( "Eco2.User" ); break;
128  case Edge_Cuts: txt = wxT( "Edge.Cuts" ); break;
129  case Margin: txt = wxT( "Margin" ); break;
130 
131  // Footprint
132  case F_CrtYd: txt = wxT( "F.CrtYd" ); break;
133  case B_CrtYd: txt = wxT( "B.CrtYd" ); break;
134  case F_Fab: txt = wxT( "F.Fab" ); break;
135  case B_Fab: txt = wxT( "B.Fab" ); break;
136 
137  default:
138  wxASSERT_MSG( 0, wxT( "aLayerId out of range" ) );
139  txt = wxT( "BAD INDEX!" ); break;
140  }
141 
142  return txt;
143 }
144 
145 
147 {
148  // desired sequence
149  static const LAYER_ID sequence[] = {
150  F_Cu,
151  In1_Cu,
152  In2_Cu,
153  In3_Cu,
154  In4_Cu,
155  In5_Cu,
156  In6_Cu,
157  In7_Cu,
158  In8_Cu,
159  In9_Cu,
160  In10_Cu,
161  In11_Cu,
162  In12_Cu,
163  In13_Cu,
164  In14_Cu,
165  In15_Cu,
166  In16_Cu,
167  In17_Cu,
168  In18_Cu,
169  In19_Cu,
170  In20_Cu,
171  In21_Cu,
172  In22_Cu,
173  In23_Cu,
174  In24_Cu,
175  In25_Cu,
176  In26_Cu,
177  In27_Cu,
178  In28_Cu,
179  In29_Cu,
180  In30_Cu,
181  B_Cu, // 31
182  };
183 
184  return Seq( sequence, DIM( sequence ) );
185 }
186 
187 
188 LSEQ LSET::Technicals( LSET aSetToOmit ) const
189 {
190  // desired sequence
191  static const LAYER_ID sequence[] = {
192  B_Adhes,
193  F_Adhes,
194  B_Paste,
195  F_Paste,
196  B_SilkS,
197  F_SilkS,
198  B_Mask,
199  F_Mask,
200  B_CrtYd,
201  F_CrtYd,
202  B_Fab,
203  F_Fab,
204  };
205 
206  LSET subset = ~aSetToOmit & *this;
207 
208  return subset.Seq( sequence, DIM( sequence ) );
209 }
210 
211 
213 {
214  // desired
215  static const LAYER_ID sequence[] = {
216  Dwgs_User,
217  Cmts_User,
218  Eco1_User,
219  Eco2_User,
220  Edge_Cuts,
221  Margin,
222  };
223 
224  return Seq( sequence, DIM( sequence ) );
225 }
226 
227 
228 std::string LSET::FmtBin() const
229 {
230  std::string ret;
231 
232  int bit_count = size();
233 
234  for( int bit=0; bit<bit_count; ++bit )
235  {
236  if( bit )
237  {
238  if( !( bit % 8 ) )
239  ret += '|';
240  else if( !( bit % 4 ) )
241  ret += '_';
242  }
243 
244  ret += (*this)[bit] ? '1' : '0';
245  }
246 
247  // reverse of string
248  return std::string( ret.rbegin(), ret.rend() );
249 }
250 
251 
252 std::string LSET::FmtHex() const
253 {
254  std::string ret;
255 
256  static const char hex[] = "0123456789abcdef";
257 
258  int nibble_count = ( size() + 3 ) / 4;
259 
260  for( int nibble=0; nibble<nibble_count; ++nibble )
261  {
262  unsigned ndx = 0;
263 
264  // test 4 consecutive bits and set ndx to 0-15:
265  for( int nibble_bit=0; nibble_bit<4; ++nibble_bit )
266  {
267  if( (*this)[nibble_bit + nibble*4] )
268  ndx |= (1 << nibble_bit);
269  }
270 
271  if( nibble && !( nibble % 8 ) )
272  ret += '_';
273 
274  assert( ndx < DIM( hex ) );
275 
276  ret += hex[ndx];
277  }
278 
279  // reverse of string
280  return std::string( ret.rbegin(), ret.rend() );
281 }
282 
283 
284 int LSET::ParseHex( const char* aStart, int aCount )
285 {
286  LSET tmp;
287 
288  const char* rstart = aStart + aCount - 1;
289  const char* rend = aStart - 1;
290 
291  const int bitcount = size();
292 
293  int nibble_ndx = 0;
294 
295  while( rstart > rend )
296  {
297  int cc = *rstart--;
298 
299  if( cc == '_' )
300  continue;
301 
302  int nibble;
303 
304  if( cc >= '0' && cc <= '9' )
305  nibble = cc - '0';
306  else if( cc >= 'a' && cc <= 'f' )
307  nibble = cc - 'a' + 10;
308  else if( cc >= 'A' && cc <= 'F' )
309  nibble = cc - 'A' + 10;
310  else
311  break;
312 
313  int bit = nibble_ndx * 4;
314 
315  for( int ndx=0; bit<bitcount && ndx<4; ++bit, ++ndx )
316  if( nibble & (1<<ndx) )
317  tmp.set( bit );
318 
319  if( bit >= bitcount )
320  break;
321 
322  ++nibble_ndx;
323  }
324 
325  int byte_count = aStart + aCount - 1 - rstart;
326 
327  assert( byte_count >= 0 );
328 
329  if( byte_count > 0 )
330  *this = tmp;
331 
332  return byte_count;
333 }
334 
335 
336 LSEQ LSET::Seq( const LAYER_ID* aWishListSequence, unsigned aCount ) const
337 {
338  LSEQ ret;
339 
340 #if defined(DEBUG) && 0
341  LSET dup_detector;
342 
343  for( unsigned i=0; i<aCount; ++i )
344  {
345  LAYER_ID id = aWishListSequence[i];
346 
347  if( test( id ) )
348  {
349  wxASSERT_MSG( !dup_detector[id], wxT( "Duplicate in aWishListSequence" ) );
350  dup_detector[id] = true;
351 
352  ret.push_back( id );
353  }
354  }
355 #else
356 
357  for( unsigned i=0; i<aCount; ++i )
358  {
359  LAYER_ID id = aWishListSequence[i];
360 
361  if( test( id ) )
362  ret.push_back( id );
363  }
364 #endif
365 
366  return ret;
367 }
368 
369 
371 {
372  LSEQ ret;
373 
374  for( unsigned i=0; i<size(); ++i )
375  {
376  if( test(i) )
377  ret.push_back( LAYER_ID( i ) );
378  }
379 
380  return ret;
381 }
382 
383 
385 {
386  // bottom-to-top stack-up layers
387  static const LAYER_ID sequence[] = {
388  B_Fab,
389  B_CrtYd,
390  B_Adhes,
391  B_SilkS,
392  B_Paste,
393  B_Mask,
394  B_Cu,
395  In30_Cu,
396  In29_Cu,
397  In28_Cu,
398  In27_Cu,
399  In26_Cu,
400  In25_Cu,
401  In24_Cu,
402  In23_Cu,
403  In22_Cu,
404  In21_Cu,
405  In20_Cu,
406  In19_Cu,
407  In18_Cu,
408  In17_Cu,
409  In16_Cu,
410  In15_Cu,
411  In14_Cu,
412  In13_Cu,
413  In12_Cu,
414  In11_Cu,
415  In10_Cu,
416  In9_Cu,
417  In8_Cu,
418  In7_Cu,
419  In6_Cu,
420  In5_Cu,
421  In4_Cu,
422  In3_Cu,
423  In2_Cu,
424  In1_Cu,
425  F_Cu,
426  F_Mask,
427  F_Paste,
428  F_SilkS,
429  F_Adhes,
430  F_CrtYd,
431  F_Fab,
432  Dwgs_User,
433  Cmts_User,
434  Eco1_User,
435  Eco2_User,
436  Margin,
437  Edge_Cuts,
438  };
439 
440  return Seq( sequence, DIM( sequence ) );
441 }
442 
443 
444 LAYER_ID FlipLayer( LAYER_ID aLayerId, int aCopperLayersCount )
445 {
446  switch( aLayerId )
447  {
448  case B_Cu: return F_Cu;
449  case F_Cu: return B_Cu;
450 
451  case B_SilkS: return F_SilkS;
452  case F_SilkS: return B_SilkS;
453 
454  case B_Adhes: return F_Adhes;
455  case F_Adhes: return B_Adhes;
456 
457  case B_Mask: return F_Mask;
458  case F_Mask: return B_Mask;
459 
460  case B_Paste: return F_Paste;
461  case F_Paste: return B_Paste;
462 
463  case B_CrtYd: return F_CrtYd;
464  case F_CrtYd: return B_CrtYd;
465 
466  case B_Fab: return F_Fab;
467  case F_Fab: return B_Fab;
468 
469  default: // change internal layer if aCopperLayersCount is >= 4
470  if( IsCopperLayer( aLayerId ) && aCopperLayersCount >= 4 )
471  {
472  // internal copper layers count is aCopperLayersCount-2
473  LAYER_ID fliplayer = LAYER_ID(aCopperLayersCount - 2 - ( aLayerId - In1_Cu ) );
474  // Ensure fliplayer has a value which does not crash pcbnew:
475  if( fliplayer < F_Cu )
476  fliplayer = F_Cu;
477 
478  if( fliplayer > B_Cu )
479  fliplayer = B_Cu;
480 
481  return fliplayer;
482  }
483 
484  // No change for the other layers
485  return aLayerId;
486  }
487 }
488 
489 
490 LSET FlipLayerMask( LSET aMask, int aCopperLayersCount )
491 {
492  // layers on physical outside of a board:
493  const static LSET and_mask( 16, // !! update count
494  B_Cu, F_Cu,
495  B_SilkS, F_SilkS,
496  B_Adhes, F_Adhes,
497  B_Mask, F_Mask,
498  B_Paste, F_Paste,
499  B_Adhes, F_Adhes,
500  B_CrtYd, F_CrtYd,
501  B_Fab, F_Fab
502  );
503 
504  LSET newMask = aMask & ~and_mask;
505 
506  if( aMask[B_Cu] )
507  newMask.set( F_Cu );
508 
509  if( aMask[F_Cu] )
510  newMask.set( B_Cu );
511 
512  if( aMask[B_SilkS] )
513  newMask.set( F_SilkS );
514 
515  if( aMask[F_SilkS] )
516  newMask.set( B_SilkS );
517 
518  if( aMask[B_Adhes] )
519  newMask.set( F_Adhes );
520 
521  if( aMask[F_Adhes] )
522  newMask.set( B_Adhes );
523 
524  if( aMask[B_Mask] )
525  newMask.set( F_Mask );
526 
527  if( aMask[F_Mask] )
528  newMask.set( B_Mask );
529 
530  if( aMask[B_Paste] )
531  newMask.set( F_Paste );
532 
533  if( aMask[F_Paste] )
534  newMask.set( B_Paste );
535 
536  if( aMask[B_Adhes] )
537  newMask.set( F_Adhes );
538 
539  if( aMask[F_Adhes] )
540  newMask.set( B_Adhes );
541 
542  if( aMask[B_CrtYd] )
543  newMask.set( F_CrtYd );
544 
545  if( aMask[F_CrtYd] )
546  newMask.set( B_CrtYd );
547 
548  if( aMask[B_Fab] )
549  newMask.set( F_Fab );
550 
551  if( aMask[F_Fab] )
552  newMask.set( B_Fab );
553 
554  if( aCopperLayersCount >= 4 ) // Internal layers exist
555  {
556  LSET internalMask = aMask & ~LSET::InternalCuMask();
557 
558  if( internalMask != LSET::InternalCuMask() )
559  { // the mask does not include all internal layers. Therefore
560  // the flipped mask for internal copper layers must be built
561  int innerLayerCnt = aCopperLayersCount -2;
562 
563  for( int ii = 0; ii < innerLayerCnt; ii++ )
564  {
565  if( internalMask[innerLayerCnt - ii + In1_Cu] )
566  newMask.set( ii + In1_Cu );
567  else
568  newMask.reset( ii + In1_Cu );
569  }
570  }
571  }
572 
573  return newMask;
574 }
575 
576 
578 {
579  unsigned set_count = count();
580 
581  if( !set_count )
582  return UNSELECTED_LAYER;
583  else if( set_count > 1 )
584  return UNDEFINED_LAYER;
585 
586  for( unsigned i=0; i < size(); ++i )
587  {
588  if( test( i ) )
589  return LAYER_ID( i );
590  }
591 
592  wxASSERT( 0 ); // set_count was verified as 1 above, what did you break?
593 
594  return UNDEFINED_LAYER;
595 }
596 
597 
599 {
600  static const LAYER_ID cu_internals[] = {
601  In1_Cu,
602  In2_Cu,
603  In3_Cu,
604  In4_Cu,
605  In5_Cu,
606  In6_Cu,
607  In7_Cu,
608  In8_Cu,
609  In9_Cu,
610  In10_Cu,
611  In11_Cu,
612  In12_Cu,
613  In13_Cu,
614  In14_Cu,
615  In15_Cu,
616  In16_Cu,
617  In17_Cu,
618  In18_Cu,
619  In19_Cu,
620  In20_Cu,
621  In21_Cu,
622  In22_Cu,
623  In23_Cu,
624  In24_Cu,
625  In25_Cu,
626  In26_Cu,
627  In27_Cu,
628  In28_Cu,
629  In29_Cu,
630  In30_Cu,
631  };
632 
633  static const LSET saved( cu_internals, DIM( cu_internals ) );
634  return saved;
635 }
636 
637 
638 LSET LSET::AllCuMask( int aCuLayerCount )
639 {
640  // retain all in static as the full set, which is a common case.
641  static const LSET all = InternalCuMask().set( F_Cu ).set( B_Cu );
642 
643  if( aCuLayerCount == MAX_CU_LAYERS )
644  return all;
645 
646  // subtract out some Cu layers not wanted in the mask.
647  LSET ret = all;
648  int clear_count = MAX_CU_LAYERS - aCuLayerCount;
649 
650  clear_count = Clamp( 0, clear_count, MAX_CU_LAYERS - 2 );
651 
652  for( LAYER_NUM elem=In30_Cu; clear_count; --elem, --clear_count )
653  {
654  ret.set( elem, false );
655  }
656 
657  return ret;
658 }
659 
660 
662 {
663  static const LSET saved = LSET().set() & ~AllCuMask();
664  return saved;
665 }
666 
667 
669 {
670  static const LSET saved( 2, F_Cu, B_Cu );
671  return saved;
672 }
673 
674 
676 {
677  static const LSET saved = LSET().set();
678  return saved;
679 }
680 
681 
683 {
684  static const LSET saved( 6, B_SilkS, B_Mask, B_Adhes, B_Paste, B_CrtYd, B_Fab );
685  return saved;
686 }
687 
689 {
690  static const LSET saved( 4, B_SilkS, B_Mask, B_Adhes, B_Paste );
691  return saved;
692 }
693 
695 {
696  static const LSET saved( 6, F_SilkS, F_Mask, F_Adhes, F_Paste, F_CrtYd, F_Fab );
697  return saved;
698 }
699 
700 
702 {
703  static const LSET saved( 4, F_SilkS, F_Mask, F_Adhes, F_Paste );
704  return saved;
705 }
706 
707 
709 {
710  static const LSET saved = BackTechMask() | FrontTechMask();
711  return saved;
712 }
713 
714 
716 {
717  static const LSET saved = BackBoardTechMask() | FrontBoardTechMask();
718  return saved;
719 }
720 
721 
723 {
724  static const LSET saved( 6,
725  Dwgs_User,
726  Cmts_User,
727  Eco1_User,
728  Eco2_User,
729  Edge_Cuts,
730  Margin
731  );
732 
733  return saved;
734 }
735 
736 
738 {
739  static const LSET saved = FrontTechMask().set( F_Cu );
740  return saved;
741 }
742 
743 
745 {
746  static const LSET saved = BackTechMask().set( B_Cu );
747  return saved;
748 }
749 
750 
752 {
753  LAYER_ID order[LAYER_ID_COUNT];
754 
755  // Assmuming that the LAYER_ID order is according to preferred UI order, as of
756  // today this is true. When that becomes not true, its easy to change the order
757  // in here to compensate.
758 
759  for( unsigned i=0; i<DIM(order); ++i )
760  order[i] = LAYER_ID( i );
761 
762  return Seq( order, DIM( order ) );
763 }
764 
765 
766 LAYER_ID ToLAYER_ID( int aLayer )
767 {
768  wxASSERT( unsigned( aLayer ) < LAYER_ID_COUNT );
769  return LAYER_ID( aLayer );
770 }
771 
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu LAYER_IDs.
Definition: lset.cpp:638
static LSET FrontBoardTechMask()
Function FrontBoardTechMask returns a mask holding technical layers used in a board fabrication (no C...
Definition: lset.cpp:701
#define DIM(x)
of elements in an array
Definition: macros.h:98
LSET FlipLayerMask(LSET aMask, int aCopperLayersCount)
Calculate the mask layer when flipping a footprint BACK and FRONT copper layers, mask, paste, solder layers are swapped internal layers are flipped only if the copper layers count is known.
Definition: lset.cpp:490
std::string FmtHex() const
Function FmtHex returns a hex string showing contents of this LSEQ.
Definition: lset.cpp:252
const T & Clamp(const T &lower, const T &value, const T &upper)
Function Clamp limits value within the range lower <= value <= upper.
Definition: macros.h:127
static LSET BackTechMask()
Function BackTechMask returns a mask holding all technical layers (no CU layer) on back side...
Definition: lset.cpp:682
LSEQ CuStack() const
Function CuStack returns a sequence of copper layers in starting from the front/top and extending to ...
Definition: lset.cpp:146
Class BOARD to handle a board.
LSEQ Seq(const LAYER_ID *aWishListSequence, unsigned aCount) const
Function Seq returns an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:336
static const wxChar * Name(LAYER_ID aLayerId)
Function Name returns the fixed name association with aLayerId.
Definition: lset.cpp:73
static LSET AllNonCuMask()
Function AllNonCuMask returns a mask holding all layer minus CU layers.
Definition: lset.cpp:661
LAYER_ID ExtractLayer() const
Find the first set LAYER_ID.
Definition: lset.cpp:577
static LSET FrontTechMask()
Function FrontTechMask returns a mask holding all technical layers (no CU layer) on front side...
Definition: lset.cpp:694
static LSET AllTechMask()
Function AllTechMask returns a mask holding all technical layers (no CU layer) on both side...
Definition: lset.cpp:708
static LSET FrontMask()
Function FrontMask returns a mask holding all technical layers and the external CU layer on front sid...
Definition: lset.cpp:737
LSEQ SeqStackupBottom2Top() const
Function SeqStackBottom2Top returns the sequence that is typical for a bottom-to-top stack-up...
Definition: lset.cpp:384
LSEQ Seq() const
Function Seq returns a LSEQ from this LSET in ascending LAYER_ID order.
Definition: lset.cpp:370
std::bitset< LAYER_ID_COUNT > BASE_SET
Class LSET is a set of LAYER_IDs.
static LSET InternalCuMask()
Function InternalCuMask() returns a complete set of internal copper layers, which is all Cu layers ex...
Definition: lset.cpp:598
static LSET ExternalCuMask()
Function ExternalCuMask returns a mask holding the Front and Bottom layers.
Definition: lset.cpp:668
static LSET AllLayersMask()
Definition: lset.cpp:675
LSEQ Technicals(LSET aSubToOmit=LSET()) const
Function Technicals returns a sequence of technical layers.
Definition: lset.cpp:188
Class LSEQ is a sequence (and therefore also a set) of LAYER_IDs.
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
Board layer functions and definitions.
LSET()
Constructor LSET() creates an empty (cleared) set.
LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:766
LAYER_ID FlipLayer(LAYER_ID aLayerId, int aCopperLayersCount)
Function FlippedLayerNumber.
Definition: lset.cpp:444
LAYER_ID
Enum LAYER_ID is the set of PCB layers.
static LSET BackBoardTechMask()
Function BackBoardTechMask returns a mask holding technical layers used in a board fabrication (no CU...
Definition: lset.cpp:688
std::string FmtBin() const
Function FmtBin returns a binary string showing contents of this LSEQ.
Definition: lset.cpp:228
static long bit[8][9]
Definition: solve.cpp:826
static LSET BackMask()
Function BackMask returns a mask holding all technical layers and the external CU layer on back side...
Definition: lset.cpp:744
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
static LSET AllBoardTechMask()
Function AllTechMask returns a mask holding board technical layers (no CU layer) on both side...
Definition: lset.cpp:715
LSEQ Users() const
*_User layers.
Definition: lset.cpp:212
static LSET UserMask()
Definition: lset.cpp:722
int ParseHex(const char *aStart, int aCount)
Function ParseHex understands the output of FmtHex() and replaces this set's values with those given ...
Definition: lset.cpp:284
LSEQ UIOrder() const
Definition: lset.cpp:751