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 PCB_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( PCB_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  PCB_LAYER_ID id = (PCB_LAYER_ID) va_arg( ap, int );
60 
61  // printf( "%s: id:%d PCB_LAYER_ID_COUNT:%d\n", __func__, id, PCB_LAYER_ID_COUNT );
62 
63  assert( unsigned( id ) < PCB_LAYER_ID_COUNT );
64 
65  set( id );
66  }
67 
68  va_end( ap );
69  }
70 }
71 
72 
73 const wxChar* LSET::Name( PCB_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  // Rescue
138  case Rescue: txt = wxT( "Rescue" ); break;
139 
140  default:
141  std::cout << aLayerId << std::endl;
142  wxASSERT_MSG( 0, wxT( "aLayerId out of range" ) );
143  txt = wxT( "BAD INDEX!" ); break;
144  }
145 
146  return txt;
147 }
148 
149 
151 {
152  // desired sequence
153  static const PCB_LAYER_ID sequence[] = {
154  F_Cu,
155  In1_Cu,
156  In2_Cu,
157  In3_Cu,
158  In4_Cu,
159  In5_Cu,
160  In6_Cu,
161  In7_Cu,
162  In8_Cu,
163  In9_Cu,
164  In10_Cu,
165  In11_Cu,
166  In12_Cu,
167  In13_Cu,
168  In14_Cu,
169  In15_Cu,
170  In16_Cu,
171  In17_Cu,
172  In18_Cu,
173  In19_Cu,
174  In20_Cu,
175  In21_Cu,
176  In22_Cu,
177  In23_Cu,
178  In24_Cu,
179  In25_Cu,
180  In26_Cu,
181  In27_Cu,
182  In28_Cu,
183  In29_Cu,
184  In30_Cu,
185  B_Cu, // 31
186  };
187 
188  return Seq( sequence, arrayDim( sequence ) );
189 }
190 
191 
192 LSEQ LSET::Technicals( LSET aSetToOmit ) const
193 {
194  // desired sequence
195  static const PCB_LAYER_ID sequence[] = {
196  F_Adhes,
197  B_Adhes,
198  F_Paste,
199  B_Paste,
200  F_SilkS,
201  B_SilkS,
202  F_Mask,
203  B_Mask,
204  F_CrtYd,
205  B_CrtYd,
206  F_Fab,
207  B_Fab,
208  };
209 
210  LSET subset = ~aSetToOmit & *this;
211 
212  return subset.Seq( sequence, arrayDim( sequence ) );
213 }
214 
215 
217 {
218  // desired
219  static const PCB_LAYER_ID sequence[] = {
220  Dwgs_User,
221  Cmts_User,
222  Eco1_User,
223  Eco2_User,
224  Edge_Cuts,
225  Margin,
226  };
227 
228  return Seq( sequence, arrayDim( sequence ) );
229 }
230 
231 
233 {
234  static const PCB_LAYER_ID sequence[] = {
235  F_Adhes,
236  B_Adhes,
237  F_Paste,
238  B_Paste,
239  F_SilkS,
240  B_SilkS,
241  F_Mask,
242  B_Mask,
243  Dwgs_User,
244  Cmts_User,
245  Eco1_User,
246  Eco2_User,
247  Edge_Cuts,
248  Margin,
249  F_CrtYd,
250  B_CrtYd,
251  F_Fab,
252  B_Fab,
253  };
254 
255  return Seq( sequence, arrayDim( sequence ) );
256 }
257 
258 
259 std::string LSET::FmtBin() const
260 {
261  std::string ret;
262 
263  int bit_count = size();
264 
265  for( int bit=0; bit<bit_count; ++bit )
266  {
267  if( bit )
268  {
269  if( !( bit % 8 ) )
270  ret += '|';
271  else if( !( bit % 4 ) )
272  ret += '_';
273  }
274 
275  ret += (*this)[bit] ? '1' : '0';
276  }
277 
278  // reverse of string
279  return std::string( ret.rbegin(), ret.rend() );
280 }
281 
282 
283 std::string LSET::FmtHex() const
284 {
285  std::string ret;
286 
287  static const char hex[] = "0123456789abcdef";
288 
289  int nibble_count = ( size() + 3 ) / 4;
290 
291  for( int nibble=0; nibble<nibble_count; ++nibble )
292  {
293  unsigned ndx = 0;
294 
295  // test 4 consecutive bits and set ndx to 0-15:
296  for( int nibble_bit=0; nibble_bit<4; ++nibble_bit )
297  {
298  if( (*this)[nibble_bit + nibble*4] )
299  ndx |= (1 << nibble_bit);
300  }
301 
302  if( nibble && !( nibble % 8 ) )
303  ret += '_';
304 
305  assert( ndx < arrayDim( hex ) );
306 
307  ret += hex[ndx];
308  }
309 
310  // reverse of string
311  return std::string( ret.rbegin(), ret.rend() );
312 }
313 
314 
315 int LSET::ParseHex( const char* aStart, int aCount )
316 {
317  LSET tmp;
318 
319  const char* rstart = aStart + aCount - 1;
320  const char* rend = aStart - 1;
321 
322  const int bitcount = size();
323 
324  int nibble_ndx = 0;
325 
326  while( rstart > rend )
327  {
328  int cc = *rstart--;
329 
330  if( cc == '_' )
331  continue;
332 
333  int nibble;
334 
335  if( cc >= '0' && cc <= '9' )
336  nibble = cc - '0';
337  else if( cc >= 'a' && cc <= 'f' )
338  nibble = cc - 'a' + 10;
339  else if( cc >= 'A' && cc <= 'F' )
340  nibble = cc - 'A' + 10;
341  else
342  break;
343 
344  int bit = nibble_ndx * 4;
345 
346  for( int ndx=0; bit<bitcount && ndx<4; ++bit, ++ndx )
347  if( nibble & (1<<ndx) )
348  tmp.set( bit );
349 
350  if( bit >= bitcount )
351  break;
352 
353  ++nibble_ndx;
354  }
355 
356  int byte_count = aStart + aCount - 1 - rstart;
357 
358  assert( byte_count >= 0 );
359 
360  if( byte_count > 0 )
361  *this = tmp;
362 
363  return byte_count;
364 }
365 
366 
367 LSEQ LSET::Seq( const PCB_LAYER_ID* aWishListSequence, unsigned aCount ) const
368 {
369  LSEQ ret;
370 
371 #if defined(DEBUG) && 0
372  LSET dup_detector;
373 
374  for( unsigned i=0; i<aCount; ++i )
375  {
376  PCB_LAYER_ID id = aWishListSequence[i];
377 
378  if( test( id ) )
379  {
380  wxASSERT_MSG( !dup_detector[id], wxT( "Duplicate in aWishListSequence" ) );
381  dup_detector[id] = true;
382 
383  ret.push_back( id );
384  }
385  }
386 #else
387 
388  for( unsigned i=0; i<aCount; ++i )
389  {
390  PCB_LAYER_ID id = aWishListSequence[i];
391 
392  if( test( id ) )
393  ret.push_back( id );
394  }
395 #endif
396 
397  return ret;
398 }
399 
400 
402 {
403  LSEQ ret;
404 
405  for( unsigned i=0; i<size(); ++i )
406  {
407  if( test(i) )
408  ret.push_back( PCB_LAYER_ID( i ) );
409  }
410 
411  return ret;
412 }
413 
414 
416 {
417  // bottom-to-top stack-up layers
418  static const PCB_LAYER_ID sequence[] = {
419  B_Fab,
420  B_CrtYd,
421  B_Adhes,
422  B_SilkS,
423  B_Paste,
424  B_Mask,
425  B_Cu,
426  In30_Cu,
427  In29_Cu,
428  In28_Cu,
429  In27_Cu,
430  In26_Cu,
431  In25_Cu,
432  In24_Cu,
433  In23_Cu,
434  In22_Cu,
435  In21_Cu,
436  In20_Cu,
437  In19_Cu,
438  In18_Cu,
439  In17_Cu,
440  In16_Cu,
441  In15_Cu,
442  In14_Cu,
443  In13_Cu,
444  In12_Cu,
445  In11_Cu,
446  In10_Cu,
447  In9_Cu,
448  In8_Cu,
449  In7_Cu,
450  In6_Cu,
451  In5_Cu,
452  In4_Cu,
453  In3_Cu,
454  In2_Cu,
455  In1_Cu,
456  F_Cu,
457  F_Mask,
458  F_Paste,
459  F_SilkS,
460  F_Adhes,
461  F_CrtYd,
462  F_Fab,
463  Dwgs_User,
464  Cmts_User,
465  Eco1_User,
466  Eco2_User,
467  Margin,
468  Edge_Cuts,
469  };
470 
471  return Seq( sequence, arrayDim( sequence ) );
472 }
473 
474 
475 PCB_LAYER_ID FlipLayer( PCB_LAYER_ID aLayerId, int aCopperLayersCount )
476 {
477  switch( aLayerId )
478  {
479  case B_Cu: return F_Cu;
480  case F_Cu: return B_Cu;
481 
482  case B_SilkS: return F_SilkS;
483  case F_SilkS: return B_SilkS;
484 
485  case B_Adhes: return F_Adhes;
486  case F_Adhes: return B_Adhes;
487 
488  case B_Mask: return F_Mask;
489  case F_Mask: return B_Mask;
490 
491  case B_Paste: return F_Paste;
492  case F_Paste: return B_Paste;
493 
494  case B_CrtYd: return F_CrtYd;
495  case F_CrtYd: return B_CrtYd;
496 
497  case B_Fab: return F_Fab;
498  case F_Fab: return B_Fab;
499 
500  default: // change internal layer if aCopperLayersCount is >= 4
501  if( IsCopperLayer( aLayerId ) && aCopperLayersCount >= 4 )
502  {
503  // internal copper layers count is aCopperLayersCount-2
504  PCB_LAYER_ID fliplayer = PCB_LAYER_ID(aCopperLayersCount - 2 - ( aLayerId - In1_Cu ) );
505  // Ensure fliplayer has a value which does not crash pcbnew:
506  if( fliplayer < F_Cu )
507  fliplayer = F_Cu;
508 
509  if( fliplayer > B_Cu )
510  fliplayer = B_Cu;
511 
512  return fliplayer;
513  }
514 
515  // No change for the other layers
516  return aLayerId;
517  }
518 }
519 
520 
521 LSET FlipLayerMask( LSET aMask, int aCopperLayersCount )
522 {
523  // layers on physical outside of a board:
524  const static LSET and_mask( 16, // !! update count
525  B_Cu, F_Cu,
526  B_SilkS, F_SilkS,
527  B_Adhes, F_Adhes,
528  B_Mask, F_Mask,
529  B_Paste, F_Paste,
530  B_Adhes, F_Adhes,
531  B_CrtYd, F_CrtYd,
532  B_Fab, F_Fab
533  );
534 
535  LSET newMask = aMask & ~and_mask;
536 
537  if( aMask[B_Cu] )
538  newMask.set( F_Cu );
539 
540  if( aMask[F_Cu] )
541  newMask.set( B_Cu );
542 
543  if( aMask[B_SilkS] )
544  newMask.set( F_SilkS );
545 
546  if( aMask[F_SilkS] )
547  newMask.set( B_SilkS );
548 
549  if( aMask[B_Adhes] )
550  newMask.set( F_Adhes );
551 
552  if( aMask[F_Adhes] )
553  newMask.set( B_Adhes );
554 
555  if( aMask[B_Mask] )
556  newMask.set( F_Mask );
557 
558  if( aMask[F_Mask] )
559  newMask.set( B_Mask );
560 
561  if( aMask[B_Paste] )
562  newMask.set( F_Paste );
563 
564  if( aMask[F_Paste] )
565  newMask.set( B_Paste );
566 
567  if( aMask[B_Adhes] )
568  newMask.set( F_Adhes );
569 
570  if( aMask[F_Adhes] )
571  newMask.set( B_Adhes );
572 
573  if( aMask[B_CrtYd] )
574  newMask.set( F_CrtYd );
575 
576  if( aMask[F_CrtYd] )
577  newMask.set( B_CrtYd );
578 
579  if( aMask[B_Fab] )
580  newMask.set( F_Fab );
581 
582  if( aMask[F_Fab] )
583  newMask.set( B_Fab );
584 
585  if( aCopperLayersCount >= 4 ) // Internal layers exist
586  {
587  LSET internalMask = aMask & LSET::InternalCuMask();
588 
589  if( internalMask != LSET::InternalCuMask() )
590  {
591  // the mask does not include all internal layers. Therefore
592  // the flipped mask for internal copper layers must be built
593  int innerLayerCnt = aCopperLayersCount -2;
594 
595  // the flipped mask is the innerLayerCnt bits rewritten in reverse order
596  // ( bits innerLayerCnt to 1 rewritten in bits 1 to innerLayerCnt )
597  for( int ii = 0; ii < innerLayerCnt; ii++ )
598  {
599  if( internalMask[innerLayerCnt - ii] )
600  {
601  newMask.set( ii + In1_Cu );
602  }
603  else
604  {
605  newMask.reset( ii + In1_Cu );
606  }
607  }
608  }
609  }
610 
611  return newMask;
612 }
613 
614 
616 {
617  unsigned set_count = count();
618 
619  if( !set_count )
620  return UNSELECTED_LAYER;
621  else if( set_count > 1 )
622  return UNDEFINED_LAYER;
623 
624  for( unsigned i=0; i < size(); ++i )
625  {
626  if( test( i ) )
627  return PCB_LAYER_ID( i );
628  }
629 
630  wxASSERT( 0 ); // set_count was verified as 1 above, what did you break?
631 
632  return UNDEFINED_LAYER;
633 }
634 
635 
637 {
638  static const PCB_LAYER_ID cu_internals[] = {
639  In1_Cu,
640  In2_Cu,
641  In3_Cu,
642  In4_Cu,
643  In5_Cu,
644  In6_Cu,
645  In7_Cu,
646  In8_Cu,
647  In9_Cu,
648  In10_Cu,
649  In11_Cu,
650  In12_Cu,
651  In13_Cu,
652  In14_Cu,
653  In15_Cu,
654  In16_Cu,
655  In17_Cu,
656  In18_Cu,
657  In19_Cu,
658  In20_Cu,
659  In21_Cu,
660  In22_Cu,
661  In23_Cu,
662  In24_Cu,
663  In25_Cu,
664  In26_Cu,
665  In27_Cu,
666  In28_Cu,
667  In29_Cu,
668  In30_Cu,
669  };
670 
671  static const LSET saved( cu_internals, arrayDim( cu_internals ) );
672  return saved;
673 }
674 
675 
676 LSET LSET::AllCuMask( int aCuLayerCount )
677 {
678  // retain all in static as the full set, which is a common case.
679  static const LSET all = InternalCuMask().set( F_Cu ).set( B_Cu );
680 
681  if( aCuLayerCount == MAX_CU_LAYERS )
682  return all;
683 
684  // subtract out some Cu layers not wanted in the mask.
685  LSET ret = all;
686  int clear_count = MAX_CU_LAYERS - aCuLayerCount;
687 
688  clear_count = Clamp( 0, clear_count, MAX_CU_LAYERS - 2 );
689 
690  for( LAYER_NUM elem=In30_Cu; clear_count; --elem, --clear_count )
691  {
692  ret.set( elem, false );
693  }
694 
695  return ret;
696 }
697 
698 
700 {
701  static const LSET saved = LSET().set() & ~AllCuMask();
702  return saved;
703 }
704 
705 
707 {
708  static const LSET saved( 2, F_Cu, B_Cu );
709  return saved;
710 }
711 
712 
714 {
715  static const LSET saved = LSET().set();
716  return saved;
717 }
718 
719 
721 {
722  static const LSET saved( 6, B_SilkS, B_Mask, B_Adhes, B_Paste, B_CrtYd, B_Fab );
723  return saved;
724 }
725 
727 {
728  static const LSET saved( 4, B_SilkS, B_Mask, B_Adhes, B_Paste );
729  return saved;
730 }
731 
733 {
734  static const LSET saved( 6, F_SilkS, F_Mask, F_Adhes, F_Paste, F_CrtYd, F_Fab );
735  return saved;
736 }
737 
738 
740 {
741  static const LSET saved( 4, F_SilkS, F_Mask, F_Adhes, F_Paste );
742  return saved;
743 }
744 
745 
747 {
748  static const LSET saved = BackTechMask() | FrontTechMask();
749  return saved;
750 }
751 
752 
754 {
755  static const LSET saved = BackBoardTechMask() | FrontBoardTechMask();
756  return saved;
757 }
758 
759 
761 {
762  static const LSET saved( 6,
763  Dwgs_User,
764  Cmts_User,
765  Eco1_User,
766  Eco2_User,
767  Edge_Cuts,
768  Margin
769  );
770 
771  return saved;
772 }
773 
774 
776 {
777  static const LSET saved = FrontTechMask().set( F_Cu );
778  return saved;
779 }
780 
781 
783 {
784  static const LSET saved = BackTechMask().set( B_Cu );
785  return saved;
786 }
787 
788 
790 {
791  static const LSET saved = InternalCuMask().set( Edge_Cuts ).set( Margin );
792  return saved;
793 }
794 
795 
797 {
798  static const LSET saved( 1, Edge_Cuts );
799  return saved;
800 }
801 
802 
804 {
805  LSEQ order = CuStack();
806  LSEQ techuser = TechAndUserUIOrder();
807  order.insert( order.end(), techuser.begin(), techuser.end() );
808 
809  return order;
810 }
811 
812 
814 {
815  wxASSERT( aLayer < GAL_LAYER_ID_END );
816  return PCB_LAYER_ID( aLayer );
817 }
818 
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:676
static LSET FrontBoardTechMask()
Function FrontBoardTechMask returns a mask holding technical layers used in a board fabrication (no C...
Definition: lset.cpp:739
LSEQ CuStack() const
Function CuStack returns a sequence of copper layers in starting from the front/top and extending to ...
Definition: lset.cpp:150
LSET FlipLayerMask(LSET aMask, int aCopperLayersCount)
Calculate the mask layer when flipping a footprint BACK and FRONT copper layers, mask,...
Definition: lset.cpp:521
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:139
static LSET ForbiddenFootprintLayers()
Function ForbiddenFootprintLayers Layers which are not allowed within footprint definitions.
Definition: lset.cpp:789
static LSET BackTechMask()
Function BackTechMask returns a mask holding all technical layers (no CU layer) on back side.
Definition: lset.cpp:720
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Function FlippedLayerNumber.
Definition: lset.cpp:475
static LSET AllNonCuMask()
Function AllNonCuMask returns a mask holding all layer minus CU layers.
Definition: lset.cpp:699
static LSET FrontTechMask()
Function FrontTechMask returns a mask holding all technical layers (no CU layer) on front side.
Definition: lset.cpp:732
LSEQ SeqStackupBottom2Top() const
Function SeqStackBottom2Top returns the sequence that is typical for a bottom-to-top stack-up.
Definition: lset.cpp:415
LSEQ Users() const
*_User layers.
Definition: lset.cpp:216
Add new GAL layers here.
static LSET AllTechMask()
Function AllTechMask returns a mask holding all technical layers (no CU layer) on both side.
Definition: lset.cpp:746
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Function Seq returns an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:367
static LSET FrontMask()
Function FrontMask returns a mask holding all technical layers and the external CU layer on front sid...
Definition: lset.cpp:775
LSEQ TechAndUserUIOrder() const
Returns the technical and user layers in the order shown in layer widget.
Definition: lset.cpp:232
std::bitset< PCB_LAYER_ID_COUNT > BASE_SET
LSEQ Seq() const
Function Seq returns a LSEQ from this LSET in ascending PCB_LAYER_ID order.
Definition: lset.cpp:401
PCB_LAYER_ID
A quick note on layer IDs:
Class LSET is a set of PCB_LAYER_IDs.
static const wxChar * Name(PCB_LAYER_ID aLayerId)
Function Name returns the fixed name association with aLayerId.
Definition: lset.cpp:73
static LSET InternalCuMask()
Function InternalCuMask() returns a complete set of internal copper layers, which is all Cu layers ex...
Definition: lset.cpp:636
static LSET ExternalCuMask()
Function ExternalCuMask returns a mask holding the Front and Bottom layers.
Definition: lset.cpp:706
static LSET AllLayersMask()
Definition: lset.cpp:713
LSEQ Technicals(LSET aSubToOmit=LSET()) const
Function Technicals returns a sequence of technical layers.
Definition: lset.cpp:192
Class LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Definition: macros.h:108
Board layer functions and definitions.
LSET()
Constructor LSET() creates an empty (cleared) set.
std::string FmtBin() const
Function FmtBin returns a binary string showing contents of this LSEQ.
Definition: lset.cpp:259
PCB_LAYER_ID ExtractLayer() const
Find the first set PCB_LAYER_ID.
Definition: lset.cpp:615
static LSET BackBoardTechMask()
Function BackBoardTechMask returns a mask holding technical layers used in a board fabrication (no CU...
Definition: lset.cpp:726
size_t i
Definition: json11.cpp:649
std::string FmtHex() const
Function FmtHex returns a hex string showing contents of this LSEQ.
Definition: lset.cpp:283
static LSET BackMask()
Function BackMask returns a mask holding all technical layers and the external CU layer on back side.
Definition: lset.cpp:782
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:753
static LSET ForbiddenTextLayers()
Function ForbiddenTextLayers Layers which are now allowed to have text on them.
Definition: lset.cpp:796
static LSET UserMask()
Definition: lset.cpp:760
LSEQ UIOrder() const
Definition: lset.cpp:803
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:315
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:813