KiCad PCB EDA Suite
Loading...
Searching...
No Matches
board_stackup.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) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2009-2021 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 3
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 along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21
22#include "board_stackup.h"
23#include <base_units.h>
24#include <string_utils.h>
25#include <layer_ids.h>
27#include <board.h>
28#include <i18n_utility.h> // For _HKI definition
30
31
33{
34 DIELECTRIC_PRMS item_prms;
35 m_DielectricPrmsList.emplace_back( item_prms );
37 m_Type = aType;
39 SetEnabled( true );
40
41 // Initialize parameters to a usual value for allowed types:
42 switch( m_Type )
43 {
47 break;
48
50 m_TypeName = KEY_CORE; // or prepreg
52 SetMaterial( wxT( "FR4" ) ); // or other dielectric name
53 SetLossTangent( 0.02 ); // for FR4
54 SetEpsilonR( 4.5 ); // for FR4
55 break;
56
58 m_TypeName = wxT( "solderpaste" );
59 break;
60
62 m_TypeName = wxT( "soldermask" );
64 SetMaterial( NotSpecifiedPrm() ); // or other solder mask material name
67 break;
68
70 m_TypeName = wxT( "silkscreen" );
72 SetMaterial( NotSpecifiedPrm() ); // or other silkscreen material name
74 break;
75
77 break;
78 }
79}
80
81
83{
84 m_LayerId = aOther.m_LayerId;
86 m_Type = aOther.m_Type;
87 m_enabled = aOther.m_enabled;
89 m_TypeName = aOther.m_TypeName;
90 m_LayerName = aOther.m_LayerName;
91}
92
93
94void BOARD_STACKUP_ITEM::AddDielectricPrms( int aDielectricPrmsIdx )
95{
96 // add a DIELECTRIC_PRMS item to m_DielectricPrmsList
97 DIELECTRIC_PRMS new_prms;
98
99 m_DielectricPrmsList.emplace( m_DielectricPrmsList.begin() + aDielectricPrmsIdx, new_prms );
100}
101
102
103void BOARD_STACKUP_ITEM::RemoveDielectricPrms( int aDielectricPrmsIdx )
104{
105 // Remove a DIELECTRIC_PRMS item from m_DielectricPrmsList if possible
106
107 if( GetSublayersCount() < 2
108 || aDielectricPrmsIdx < 0
109 || aDielectricPrmsIdx >= GetSublayersCount() )
110 {
111 return;
112 }
113
114 m_DielectricPrmsList.erase( m_DielectricPrmsList.begin() + aDielectricPrmsIdx );
115}
116
117
118
120{
121 // A reasonable thickness for copper layers:
122 return pcbIUScale.mmToIU( 0.035 );
123}
124
125
127{
128 // A reasonable thickness for solder mask:
129 return pcbIUScale.mmToIU( 0.01 );
130}
131
132
133// Getters:
134wxString BOARD_STACKUP_ITEM::GetColor( int aDielectricSubLayer ) const
135{
136 wxASSERT( aDielectricSubLayer >= 0 && aDielectricSubLayer < GetSublayersCount() );
137
138 return m_DielectricPrmsList[aDielectricSubLayer].m_Color;
139}
140
141int BOARD_STACKUP_ITEM::GetThickness( int aDielectricSubLayer ) const
142{
143 wxASSERT( aDielectricSubLayer >= 0 && aDielectricSubLayer < GetSublayersCount() );
144
145 return m_DielectricPrmsList[aDielectricSubLayer].m_Thickness;
146}
147
148
149double BOARD_STACKUP_ITEM::GetLossTangent( int aDielectricSubLayer ) const
150{
151 wxASSERT( aDielectricSubLayer >= 0 && aDielectricSubLayer < GetSublayersCount() );
152
153 return m_DielectricPrmsList[aDielectricSubLayer].m_LossTangent;
154}
155
156
157double BOARD_STACKUP_ITEM::GetEpsilonR( int aDielectricSubLayer ) const
158{
159 wxASSERT( aDielectricSubLayer >= 0 && aDielectricSubLayer < GetSublayersCount() );
160
161 return m_DielectricPrmsList[aDielectricSubLayer].m_EpsilonR;
162}
163
164
165bool BOARD_STACKUP_ITEM::IsThicknessLocked( int aDielectricSubLayer ) const
166{
167 wxASSERT( aDielectricSubLayer >= 0 && aDielectricSubLayer < GetSublayersCount() );
168
169 return m_DielectricPrmsList[aDielectricSubLayer].m_ThicknessLocked;
170}
171
172
173wxString BOARD_STACKUP_ITEM::GetMaterial( int aDielectricSubLayer ) const
174{
175 wxASSERT( aDielectricSubLayer >= 0 && aDielectricSubLayer < GetSublayersCount() );
176
177 return m_DielectricPrmsList[aDielectricSubLayer].m_Material;
178}
179
180
181// Setters:
182void BOARD_STACKUP_ITEM::SetColor( const wxString& aColorName , int aDielectricSubLayer )
183{
184 wxASSERT( aDielectricSubLayer >= 0 && aDielectricSubLayer < GetSublayersCount() );
185
186 if( aDielectricSubLayer >= 0 && aDielectricSubLayer < GetSublayersCount() )
187 m_DielectricPrmsList[aDielectricSubLayer].m_Color = aColorName;
188}
189
190
191void BOARD_STACKUP_ITEM::SetThickness( int aThickness, int aDielectricSubLayer )
192{
193 wxASSERT( aDielectricSubLayer >= 0 && aDielectricSubLayer < GetSublayersCount() );
194
195 if( aDielectricSubLayer >= 0 && aDielectricSubLayer < GetSublayersCount() )
196 m_DielectricPrmsList[aDielectricSubLayer].m_Thickness = aThickness;
197}
198
199
200void BOARD_STACKUP_ITEM::SetLossTangent( double aTg, int aDielectricSubLayer )
201{
202 wxASSERT( aDielectricSubLayer >= 0 && aDielectricSubLayer < GetSublayersCount() );
203
204 if( aDielectricSubLayer >= 0 && aDielectricSubLayer < GetSublayersCount() )
205 m_DielectricPrmsList[aDielectricSubLayer].m_LossTangent = aTg;
206}
207
208
209void BOARD_STACKUP_ITEM::SetEpsilonR( double aEpsilon, int aDielectricSubLayer )
210{
211 wxASSERT( aDielectricSubLayer >= 0 && aDielectricSubLayer < GetSublayersCount() );
212
213 if( aDielectricSubLayer >= 0 && aDielectricSubLayer < GetSublayersCount() )
214 m_DielectricPrmsList[aDielectricSubLayer].m_EpsilonR = aEpsilon;
215}
216
217
218void BOARD_STACKUP_ITEM::SetThicknessLocked( bool aLocked, int aDielectricSubLayer )
219{
220 wxASSERT( aDielectricSubLayer >= 0 && aDielectricSubLayer < GetSublayersCount() );
221
222 if( aDielectricSubLayer >= 0 && aDielectricSubLayer < GetSublayersCount() )
223 m_DielectricPrmsList[aDielectricSubLayer].m_ThicknessLocked = aLocked;
224}
225
226
227void BOARD_STACKUP_ITEM::SetMaterial( const wxString& aName, int aDielectricSubLayer )
228{
229 wxASSERT( aDielectricSubLayer >= 0 && aDielectricSubLayer < GetSublayersCount() );
230
231 if( aDielectricSubLayer >= 0 && aDielectricSubLayer < GetSublayersCount() )
232 m_DielectricPrmsList[aDielectricSubLayer].m_Material = aName;
233}
234
235
237{
240};
241
242
244{
247};
248
249
250bool BOARD_STACKUP_ITEM::HasMaterialValue( int aDielectricSubLayer ) const
251{
252 // return true if the material is specified
253 return IsMaterialEditable() && IsPrmSpecified( GetMaterial( aDielectricSubLayer ) );
254}
255
256
258{
262}
263
264
266{
270}
271
272
274{
278}
279
280
281wxString BOARD_STACKUP_ITEM::FormatEpsilonR( int aDielectricSubLayer ) const
282{
283 // return a wxString to print/display Epsilon R
284 // note: we do not want scientific notation
285 wxString txt = UIDouble2Str( GetEpsilonR( aDielectricSubLayer ) );
286 return txt;
287}
288
289
290wxString BOARD_STACKUP_ITEM::FormatLossTangent( int aDielectricSubLayer ) const
291{
292 // return a wxString to print/display Loss Tangent
293 // note: we do not want scientific notation
294 wxString txt = UIDouble2Str( GetLossTangent( aDielectricSubLayer ) );
295 return txt;
296}
297
298
300{
301 // return a wxString to print/display a dielectric name
302 wxString lname;
303 lname.Printf( _( "Dielectric %d" ), GetDielectricLayerId() );
304
305 return lname;
306}
307
308
310{
311 m_HasDielectricConstrains = false; // True if some dielectric layers have constrains
312 // (Loss tg and Epison R)
313 m_HasThicknessConstrains = false; // True if some dielectric or copper layers have constrains
315 m_CastellatedPads = false; // True if some castellated pads exist
316 m_EdgePlating = false; // True if edge board is plated
317 m_FinishType = wxT( "None" ); // undefined finish type
318}
319
320
322{
328 m_FinishType = aOther.m_FinishType;
329
330 // All items in aOther.m_list have to be duplicated, because aOther.m_list
331 // manage pointers to these items
332 for( BOARD_STACKUP_ITEM* item : aOther.m_list )
333 {
334 BOARD_STACKUP_ITEM* dup_item = new BOARD_STACKUP_ITEM( *item );
335 Add( dup_item );
336 }
337}
338
339
341{
347 m_FinishType = aOther.m_FinishType;
348
349 RemoveAll();
350
351 // All items in aOther.m_list have to be duplicated, because aOther.m_list
352 // manage pointers to these items
353 for( BOARD_STACKUP_ITEM* item : aOther.m_list )
354 {
355 BOARD_STACKUP_ITEM* dup_item = new BOARD_STACKUP_ITEM( *item );
356 Add( dup_item );
357 }
358
359 return *this;
360}
361
362
364{
365 for( BOARD_STACKUP_ITEM* item : m_list )
366 delete item;
367
368 m_list.clear();
369}
370
371
373{
374 if( aIndex < 0 || aIndex >= GetCount() )
375 return nullptr;
376
377 return GetList()[aIndex];
378}
379
380
382{
383 // return the board thickness from the thickness of BOARD_STACKUP_ITEM list
384 int thickness = 0;
385
386 for( BOARD_STACKUP_ITEM* item : m_list )
387 {
388 if( item->IsThicknessEditable() && item->IsEnabled() )
389 {
390 thickness += item->GetThickness();
391
392 // dielectric layers can have more than one main layer
393 // add thickness of all sublayers
394 for( int idx = 1; idx < item->GetSublayersCount(); idx++ )
395 {
396 thickness += item->GetThickness( idx );
397 }
398 }
399 }
400
401 return thickness;
402}
403
404
406{
407 bool change = false;
408 // Build the suitable stackup:
409 BOARD_STACKUP stackup;
410 stackup.BuildDefaultStackupList( aSettings );
411
412 // First, find removed layers:
413 for( BOARD_STACKUP_ITEM* curr_item: m_list )
414 {
415 bool found = false;
416
417 for( BOARD_STACKUP_ITEM* item: stackup.GetList() )
418 {
419 if( curr_item->GetBrdLayerId() != UNDEFINED_LAYER )
420 {
421 if( item->GetBrdLayerId() == curr_item->GetBrdLayerId() )
422 {
423 found = true;
424 break;
425 }
426 }
427 else // curr_item = dielectric layer
428 {
429 if( item->GetBrdLayerId() != UNDEFINED_LAYER )
430 continue;
431
432 if( item->GetDielectricLayerId() == curr_item->GetDielectricLayerId() )
433 {
434 found = true;
435 break;
436 }
437 }
438 }
439
440 if( !found ) // a layer was removed: a change is found
441 {
442 change = true;
443 break;
444 }
445 }
446
447 // Now initialize all stackup items to the initial values, when exist
448 for( BOARD_STACKUP_ITEM* item : stackup.GetList() )
449 {
450 bool found = false;
451 // Search for initial settings:
452 for( const BOARD_STACKUP_ITEM* initial_item : m_list )
453 {
454 if( item->GetBrdLayerId() != UNDEFINED_LAYER )
455 {
456 if( item->GetBrdLayerId() == initial_item->GetBrdLayerId() )
457 {
458 *item = *initial_item;
459 found = true;
460 break;
461 }
462 }
463 else // dielectric layer: see m_DielectricLayerId for identification
464 {
465 // Compare dielectric layer with dielectric layer
466 if( initial_item->GetBrdLayerId() != UNDEFINED_LAYER )
467 continue;
468
469 if( item->GetDielectricLayerId() == initial_item->GetDielectricLayerId() )
470 {
471 *item = *initial_item;
472 found = true;
473 break;
474 }
475 }
476 }
477
478 if( !found )
479 {
480 change = true;
481 }
482 }
483
484 // Transfer layer settings:
485 *this = stackup;
486
487 // Transfer other stackup settings from aSettings
488 const BOARD_STACKUP& source_stackup = aSettings->GetStackupDescriptor();
491 m_CastellatedPads = source_stackup.m_CastellatedPads;
492 m_EdgePlating = source_stackup.m_EdgePlating;
493 m_FinishType = source_stackup.m_FinishType;
494
495 return change;
496}
497
498
500 int aActiveCopperLayersCount )
501{
502 // Creates a default stackup, according to the current BOARD_DESIGN_SETTINGS settings.
503 // Note: the m_TypeName string is made translatable using _HKI marker, but is not
504 // translated when building the stackup.
505 // It will be used as this in files, and can be translated only in dialog
506 // if aSettings == NULL, build a full stackup (with 32 copper layers)
507 LSET enabledLayer = aSettings ? aSettings->GetEnabledLayers() : StackupAllowedBrdLayers();
508 int copperLayerCount = aSettings ? aSettings->GetCopperLayerCount() : B_Cu+1;
509
510 // We need to calculate a suitable dielectric layer thickness.
511 // If no settings, and if aActiveCopperLayersCount is given, use it
512 // (If no settings, and no aActiveCopperLayersCount, the full 32 layers are used)
513 int activeCuLayerCount = copperLayerCount;
514
515 if( aSettings == nullptr && aActiveCopperLayersCount > 0 )
516 activeCuLayerCount = aActiveCopperLayersCount;
517
518 int brd__thickness = aSettings ? aSettings->GetBoardThickness() : pcbIUScale.mmToIU( 1.6 );
519 int diel_thickness = brd__thickness -
520 ( BOARD_STACKUP_ITEM::GetCopperDefaultThickness() * activeCuLayerCount );
521
522 // Take in account the solder mask thickness:
523 int sm_count = ( enabledLayer & LSET( 2, F_Mask, B_Mask) ).count();
524 diel_thickness -= BOARD_STACKUP_ITEM::GetMaskDefaultThickness() * sm_count;
525 diel_thickness /= std::max( 1, activeCuLayerCount - 1 );
526
527 int dielectric_idx = 0;
528
529 // Add silk screen, solder mask and solder paste layers on top
530 if( enabledLayer[F_SilkS] )
531 {
533 item->SetBrdLayerId( F_SilkS );
534 item->SetTypeName( _HKI( "Top Silk Screen" ) );
535 Add( item );
536 }
537
538 if( enabledLayer[F_Paste] )
539 {
541 item->SetBrdLayerId( F_Paste );
542 item->SetTypeName( _HKI( "Top Solder Paste" ) );
543 Add( item );
544 }
545
546 if( enabledLayer[F_Mask] )
547 {
549 item->SetBrdLayerId( F_Mask );
550 item->SetTypeName( _HKI( "Top Solder Mask" ) );
551 Add( item );
552 }
553
554 // Add copper and dielectric layers
555 for( int ii = 0; ii < copperLayerCount; ii++ )
556 {
558 item->SetBrdLayerId( ( PCB_LAYER_ID )ii );
559 item->SetTypeName( KEY_COPPER );
560 Add( item );
561
562 if( ii == copperLayerCount-1 )
563 {
564 item->SetBrdLayerId( B_Cu );
565 break;
566 }
567
568 // Add the dielectric layer:
570 item->SetThickness( diel_thickness );
571 item->SetDielectricLayerId( dielectric_idx + 1 );
572
573 // Display a dielectric default layer name:
574 if( (dielectric_idx & 1) == 0 )
575 {
576 item->SetTypeName( KEY_CORE );
577 item->SetMaterial( wxT( "FR4" ) );
578 }
579 else
580 {
581 item->SetTypeName( KEY_PREPREG );
582 item->SetMaterial( wxT( "FR4" ) );
583 }
584
585 Add( item );
586 dielectric_idx++;
587 }
588
589 // Add silk screen, solder mask and solder paste layers on bottom
590 if( enabledLayer[B_Mask] )
591 {
593 item->SetBrdLayerId( B_Mask );
594 item->SetTypeName( _HKI( "Bottom Solder Mask" ) );
595 Add( item );
596 }
597
598 if( enabledLayer[B_Paste] )
599 {
601 item->SetBrdLayerId( B_Paste );
602 item->SetTypeName( _HKI( "Bottom Solder Paste" ) );
603 Add( item );
604 }
605
606 if( enabledLayer[B_SilkS] )
607 {
609 item->SetBrdLayerId( B_SilkS );
610 item->SetTypeName( _HKI( "Bottom Silk Screen" ) );
611 Add( item );
612 }
613
614 // Transfer other stackup settings from aSettings
615 if( aSettings )
616 {
617 const BOARD_STACKUP& source_stackup = aSettings->GetStackupDescriptor();
619 m_CastellatedPads = source_stackup.m_CastellatedPads;
620 m_EdgePlating = source_stackup.m_EdgePlating;
621 m_FinishType = source_stackup.m_FinishType;
622 }
623}
624
625
627 const BOARD* aBoard, int aNestLevel ) const
628{
629 // Board stackup is the ordered list from top to bottom of
630 // physical layers and substrate used to build the board.
631 if( m_list.empty() )
632 return;
633
634 aFormatter->Print( aNestLevel, "(stackup\n" );
635 int nest_level = aNestLevel+1;
636
637 // Note:
638 // Unspecified parameters are not stored in file.
639 for( BOARD_STACKUP_ITEM* item: m_list )
640 {
641 wxString layer_name;
642
643 if( item->GetBrdLayerId() == UNDEFINED_LAYER )
644 layer_name.Printf( wxT( "dielectric %d" ), item->GetDielectricLayerId() );
645 else
646 layer_name = LSET::Name( item->GetBrdLayerId() );
647
648 aFormatter->Print( nest_level, "(layer %s (type %s)",
649 aFormatter->Quotew( layer_name ).c_str(),
650 aFormatter->Quotew( item->GetTypeName() ).c_str() );
651
652 // Output other parameters ( in sub layer list there is at least one item)
653 for( int idx = 0; idx < item->GetSublayersCount(); idx++ )
654 {
655 if( idx ) // not for the main (first) layer.
656 {
657 aFormatter->Print( 0, "\n" );
658 aFormatter->Print( nest_level+1, "addsublayer" );
659 }
660
661 if( item->IsColorEditable() && IsPrmSpecified( item->GetColor( idx ) ) )
662 {
663 aFormatter->Print( 0, " (color %s)",
664 aFormatter->Quotew( item->GetColor( idx ) ).c_str() );
665 }
666
667 if( item->IsThicknessEditable() )
668 {
669 if( item->GetType() == BS_ITEM_TYPE_DIELECTRIC && item->IsThicknessLocked( idx ) )
670 aFormatter->Print( 0, " (thickness %s locked)",
671 EDA_UNIT_UTILS::FormatInternalUnits( pcbIUScale, item->GetThickness( idx ) ).c_str() );
672 else
673 aFormatter->Print( 0, " (thickness %s)",
674 EDA_UNIT_UTILS::FormatInternalUnits( pcbIUScale, item->GetThickness( idx ) ).c_str() );
675 }
676
677 if( item->HasMaterialValue( idx ) )
678 aFormatter->Print( 0, " (material %s)",
679 aFormatter->Quotew( item->GetMaterial( idx ) ).c_str() );
680
681 if( item->HasEpsilonRValue() && item->HasMaterialValue( idx ) )
682 aFormatter->Print( 0, " (epsilon_r %g)", item->GetEpsilonR( idx ) );
683
684 if( item->HasLossTangentValue() && item->HasMaterialValue( idx ) )
685 aFormatter->Print( 0, " (loss_tangent %s)",
686 FormatDouble2Str( item->GetLossTangent( idx ) ).c_str() );
687 }
688
689 aFormatter->Print( 0, ")\n" );
690 }
691
692 // Other infos about board, related to layers and other fabrication specifications
694 {
695 aFormatter->Print( nest_level, "(copper_finish %s)\n",
696 aFormatter->Quotew( m_FinishType ).c_str() );
697 }
698
699 aFormatter->Print( nest_level, "(dielectric_constraints %s)\n",
700 m_HasDielectricConstrains ? "yes" : "no" );
701
703 {
704 aFormatter->Print( nest_level, "(edge_connector %s)\n",
705 m_EdgeConnectorConstraints > 1 ? "bevelled": "yes" );
706 }
707
709 aFormatter->Print( nest_level, "(castellated_pads yes)\n" );
710
711 if( m_EdgePlating )
712 aFormatter->Print( nest_level, "(edge_plating yes)\n" );
713
714 aFormatter->Print( aNestLevel, ")\n" );
715}
716
717
718int BOARD_STACKUP::GetLayerDistance( PCB_LAYER_ID aFirstLayer, PCB_LAYER_ID aSecondLayer ) const
719{
720 wxASSERT( IsCopperLayer( aFirstLayer ) && IsCopperLayer( aSecondLayer ) );
721
722 if( aFirstLayer == aSecondLayer )
723 return 0;
724
725 if( aSecondLayer < aFirstLayer )
726 std::swap( aFirstLayer, aSecondLayer );
727
728 int total = 0;
729 bool start = false;
730 bool half = false;
731
732 for( BOARD_STACKUP_ITEM* item : m_list )
733 {
734 // Will be UNDEFINED_LAYER for dielectrics
735 PCB_LAYER_ID layer = item->GetBrdLayerId();
736
737 if( layer != UNDEFINED_LAYER && !IsCopperLayer( layer ) )
738 continue; // Silk/mask layer
739
740 // Reached the start copper layer? Start counting the next dielectric after it
741 if( !start && ( layer != UNDEFINED_LAYER && layer >= aFirstLayer ) )
742 {
743 start = true;
744 half = true;
745 }
746 else if( !start )
747 continue;
748
749 // Reached the stop copper layer? we're done
750 if( start && ( layer != UNDEFINED_LAYER && layer >= aSecondLayer ) )
751 half = true;
752
753 for( int sublayer = 0; sublayer < item->GetSublayersCount(); sublayer++ )
754 {
755 int subThickness = item->GetThickness( sublayer );
756 total += half ? ( subThickness / 2 ) : subThickness;
757 }
758
759 half = false;
760
761 if( layer != UNDEFINED_LAYER && layer >= aSecondLayer )
762 break;
763 }
764
765 return total;
766}
767
768
769bool IsPrmSpecified( const wxString& aPrmValue )
770{
771 // return true if the param value is specified:
772
773 if( !aPrmValue.IsEmpty()
774 && ( aPrmValue.CmpNoCase( NotSpecifiedPrm() ) != 0 )
775 && aPrmValue != wxGetTranslation( NotSpecifiedPrm() ) )
776 return true;
777
778 return false;
779}
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
bool IsPrmSpecified(const wxString &aPrmValue)
@ BS_EDGE_CONNECTOR_NONE
Definition: board_stackup.h:55
BOARD_STACKUP_ITEM_TYPE
Definition: board_stackup.h:41
@ BS_ITEM_TYPE_UNDEFINED
Definition: board_stackup.h:42
@ BS_ITEM_TYPE_COPPER
Definition: board_stackup.h:43
@ BS_ITEM_TYPE_SILKSCREEN
Definition: board_stackup.h:49
@ BS_ITEM_TYPE_DIELECTRIC
Definition: board_stackup.h:44
@ BS_ITEM_TYPE_SOLDERPASTE
Definition: board_stackup.h:46
@ BS_ITEM_TYPE_SOLDERMASK
Definition: board_stackup.h:47
Container for design settings for a BOARD object.
LSET GetEnabledLayers() const
Return a bit-mask of all the layers that are enabled.
int GetBoardThickness() const
The full thickness of the board including copper and masks.
BOARD_STACKUP & GetStackupDescriptor()
Manage one layer needed to make a physical board.
Definition: board_stackup.h:91
void AddDielectricPrms(int aDielectricPrmsIdx)
Add (insert) a DIELECTRIC_PRMS item to m_DielectricPrmsList all values are set to default.
PCB_LAYER_ID m_LayerId
type name of layer (copper, silk screen, core, prepreg ...)
int GetSublayersCount() const
void SetDielectricLayerId(int aLayerId)
double GetEpsilonR(int aDielectricSubLayer=0) const
wxString GetColor(int aDielectricSubLayer=0) const
bool HasEpsilonRValue() const
void SetThickness(int aThickness, int aDielectricSubLayer=0)
bool IsMaterialEditable() const
BOARD_STACKUP_ITEM_TYPE m_Type
bool HasMaterialValue(int aDielectricSubLayer=0) const
void SetThicknessLocked(bool aLocked, int aDielectricSubLayer=0)
wxString FormatDielectricLayerName() const
void SetMaterial(const wxString &aName, int aDielectricSubLayer=0)
BOARD_STACKUP_ITEM(BOARD_STACKUP_ITEM_TYPE aType)
bool HasLossTangentValue() const
bool IsThicknessEditable() const
void SetLossTangent(double aTg, int aDielectricSubLayer=0)
int GetThickness(int aDielectricSubLayer=0) const
void SetEnabled(bool aEnable)
std::vector< DIELECTRIC_PRMS > m_DielectricPrmsList
the "layer" id for dielectric layers, from 1 (top) to 31 (bottom) (only 31 dielectric layers for 32 c...
static int GetMaskDefaultThickness()
wxString GetMaterial(int aDielectricSubLayer=0) const
wxString m_TypeName
name of layer as shown in layer manager. Useful to create reports
void SetBrdLayerId(PCB_LAYER_ID aBrdLayerId)
void SetTypeName(const wxString &aName)
bool IsThicknessLocked(int aDielectricSubLayer=0) const
wxString FormatEpsilonR(int aDielectricSubLayer=0) const
int m_DielectricLayerId
the layer id (F.Cu to B.Cu, F.Silk, B.silk, F.Mask, B.Mask) and UNDEFINED_LAYER (-1) for dielectric l...
void SetColor(const wxString &aColorName, int aDielectricSubLayer=0)
void SetEpsilonR(double aEpsilon, int aDielectricSubLayer=0)
void RemoveDielectricPrms(int aDielectricPrmsIdx)
Remove a DIELECTRIC_PRMS item from m_DielectricPrmsList.
int GetDielectricLayerId() const
bool IsColorEditable() const
wxString FormatLossTangent(int aDielectricSubLayer=0) const
double GetLossTangent(int aDielectricSubLayer=0) const
static int GetCopperDefaultThickness()
Manage layers needed to make a physical board.
void RemoveAll()
Delete all items in list and clear the list.
void FormatBoardStackup(OUTPUTFORMATTER *aFormatter, const BOARD *aBoard, int aNestLevel) const
Write the stackup info on board file.
bool m_CastellatedPads
True if castellated pads exist.
const std::vector< BOARD_STACKUP_ITEM * > & GetList() const
static LSET StackupAllowedBrdLayers()
int GetCount() const
bool SynchronizeWithBoard(BOARD_DESIGN_SETTINGS *aSettings)
Synchronize the BOARD_STACKUP_ITEM* list with the board.
int BuildBoardThicknessFromStackup() const
bool m_HasDielectricConstrains
True if some layers have impedance controlled tracks or have specific constrains for micro-wave appli...
void Add(BOARD_STACKUP_ITEM *aItem)
Add a new item in stackup layer.
void BuildDefaultStackupList(const BOARD_DESIGN_SETTINGS *aSettings, int aActiveCopperLayersCount=0)
Create a default stackup, according to the current BOARD_DESIGN_SETTINGS settings.
BOARD_STACKUP & operator=(const BOARD_STACKUP &aOther)
BOARD_STACKUP_ITEM * GetStackupLayer(int aIndex)
int GetLayerDistance(PCB_LAYER_ID aFirstLayer, PCB_LAYER_ID aSecondLayer) const
Calculate the distance (height) between the two given copper layers.
std::vector< BOARD_STACKUP_ITEM * > m_list
bool m_EdgePlating
True if the edge board is plated.
BS_EDGE_CONNECTOR_CONSTRAINTS m_EdgeConnectorConstraints
If the board has edge connector cards, some constrains can be specified in job file: BS_EDGE_CONNECTO...
bool m_HasThicknessConstrains
True if some layers (copper and/or dielectric) have specific thickness.
wxString m_FinishType
The name of external copper finish.
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:270
A helper class to manage a dielectric layer set of parameters.
Definition: board_stackup.h:65
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:536
static const wxChar * Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Definition: lset.cpp:82
An interface used to output 8 bit text in a convenient way.
Definition: richio.h:322
std::string Quotew(const wxString &aWrapee) const
Definition: richio.cpp:543
int PRINTF_FUNC Print(int nestLevel, const char *fmt,...)
Format and write text to the output stream.
Definition: richio.cpp:475
#define _HKI(x)
#define _(s)
Some functions to handle hotkeys in KiCad.
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:831
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:59
@ F_Paste
Definition: layer_ids.h:101
@ B_Mask
Definition: layer_ids.h:106
@ B_Cu
Definition: layer_ids.h:95
@ F_Mask
Definition: layer_ids.h:107
@ B_Paste
Definition: layer_ids.h:100
@ F_SilkS
Definition: layer_ids.h:104
@ UNDEFINED_LAYER
Definition: layer_ids.h:60
@ B_SilkS
Definition: layer_ids.h:103
std::string FormatInternalUnits(const EDA_IU_SCALE &aIuScale, int aValue)
Converts aValue from internal units to a string appropriate for writing to file.
Definition: eda_units.cpp:142
wxString NotSpecifiedPrm()
#define KEY_PREPREG
#define KEY_COPPER
#define KEY_CORE
#define DEFAULT_EPSILON_R_SILKSCREEN
#define DEFAULT_EPSILON_R_SOLDERMASK
std::string UIDouble2Str(double aValue)
Print a float number without using scientific notation and no trailing 0 We want to avoid scientific ...
std::string FormatDouble2Str(double aValue)
Print a float number without using scientific notation and no trailing 0 This function is intended in...
constexpr int mmToIU(double mm) const
Definition: base_units.h:89