From 6b15231f4bd064254993a5626e5890151d824c03 Mon Sep 17 00:00:00 2001 From: Jonathan Haas Date: Tue, 27 Sep 2022 08:40:41 +0200 Subject: [PATCH] Add code to set better default layer widths. This affects both the layer count dropdown and the "Adjust dielectric thickness" button. Changing layer widths will now maintain the same total board width and set layer widths to common manufacturer values. Layer widths can be locked (as before) to keep any manually defined values. --- .../panel_board_stackup.cpp | 119 ++++++++++++++++-- .../panel_board_stackup.h | 6 + 2 files changed, 116 insertions(+), 9 deletions(-) diff --git a/pcbnew/board_stackup_manager/panel_board_stackup.cpp b/pcbnew/board_stackup_manager/panel_board_stackup.cpp index a00bfdef5d..1db4080ac7 100644 --- a/pcbnew/board_stackup_manager/panel_board_stackup.cpp +++ b/pcbnew/board_stackup_manager/panel_board_stackup.cpp @@ -130,8 +130,10 @@ PANEL_SETUP_BOARD_STACKUP::~PANEL_SETUP_BOARD_STACKUP() void PANEL_SETUP_BOARD_STACKUP::onCopperLayersSelCount( wxCommandEvent& event ) { + int oldBoardWidth = static_cast( m_frame->ValueFromString( m_tcCTValue->GetValue() ) ); updateCopperLayerCount(); showOnlyActiveLayers(); + setDefaultLayerWidths( oldBoardWidth ); computeBoardThickness(); Layout(); } @@ -189,7 +191,7 @@ void PANEL_SETUP_BOARD_STACKUP::onAdjustDielectricThickness( wxCommandEvent& eve int iu_thickness = m_frame->ValueFromString( dlg.GetValue() ); - if( iu_thickness <= min_thickness ) + if( iu_thickness < min_thickness ) { wxMessageBox( wxString::Format( _("Value too small (min value %s)." ), m_frame->StringFromValue( min_thickness, true ) ) ); @@ -200,14 +202,7 @@ void PANEL_SETUP_BOARD_STACKUP::onAdjustDielectricThickness( wxCommandEvent& eve if( items_candidate.size() ) { - int thickness_layer = ( iu_thickness - min_thickness ) / items_candidate.size(); - wxString txt = m_frame->StringFromValue( thickness_layer, true ); - - for( BOARD_STACKUP_ROW_UI_ITEM* ui_item : items_candidate ) - { - wxTextCtrl* textCtrl = static_cast( ui_item->m_ThicknessCtrl ); - textCtrl->ChangeValue( txt ); - } + setDefaultLayerWidths( iu_thickness ); } else { @@ -425,6 +420,112 @@ wxColor PANEL_SETUP_BOARD_STACKUP::GetSelectedColor( int aRow ) const } +void PANEL_SETUP_BOARD_STACKUP::setDefaultLayerWidths( int targetThickness ) +{ + // This function tries to set the PCB thickness to the parameter and uses a fixed prepreg thickness + // of 0.1 mm. The core thickness is calculated accordingly as long as it also stays above 0.1mm. + // If the core thickness would be smaller than the default pregreg thickness given here, + // both are reduced towards zero to arrive at the correct PCB width + const int prePregDefaultThickness = pcbIUScale.mmToIU( 0.1 ); + + int copperLayerCount = GetCopperLayerCount(); + + // This code is for a symmetrical PCB stackup with even copper layer count + // If asymmetric stackups were to be implemented, the following layer count calculations + // for dielectric/core layers might need adjustments. + wxASSERT( copperLayerCount % 2 == 0 ); + + int dielectricLayerCount = copperLayerCount - 1; + int coreLayerCount = copperLayerCount / 2 - 1; + + wxASSERT( dielectricLayerCount > 0 ); + + bool currentLayerIsCore = false; + + // start with prepreg layer on the outside, except when creating two-layer-board + if( copperLayerCount == 2 ) + { + coreLayerCount = 1; + currentLayerIsCore = true; + } + + wxASSERT( coreLayerCount > 0 ); + + int prePregLayerCount = dielectricLayerCount - coreLayerCount; + + int totalWidthOfFixedItems = 0; + + for( BOARD_STACKUP_ROW_UI_ITEM& ui_item : m_rowUiItemsList ) + { + BOARD_STACKUP_ITEM* item = ui_item.m_Item; + + if( !item->IsThicknessEditable() || !ui_item.m_isEnabled ) + continue; + + wxCheckBox* cbLock = dynamic_cast( ui_item.m_ThicknessLockCtrl ); + wxChoice* layerType = dynamic_cast( ui_item.m_LayerTypeCtrl ); + + if( ( item->GetType() == BS_ITEM_TYPE_DIELECTRIC && !layerType ) || item->GetType() == BS_ITEM_TYPE_SOLDERMASK + || item->GetType() == BS_ITEM_TYPE_COPPER || ( cbLock && cbLock->GetValue() ) ) + { + // secondary dielectric layers, mask and copper layers and locked layers will be counted as fixed width + wxTextCtrl* textCtrl = static_cast( ui_item.m_ThicknessCtrl ); + int item_thickness = m_frame->ValueFromString( textCtrl->GetValue() ); + + totalWidthOfFixedItems += item_thickness; + } + } + + // Width that hasn't been allocated by fixed items + int remainingWidth = + targetThickness - totalWidthOfFixedItems - ( prePregDefaultThickness * prePregLayerCount ); + + int prePregThickness = prePregDefaultThickness; + int coreThickness = remainingWidth / coreLayerCount; + + if( coreThickness < prePregThickness ) + { + // There's not enough room for prepreg and core layers of at least 0.1 mm, so adjust both down + remainingWidth = targetThickness - totalWidthOfFixedItems; + prePregThickness = coreThickness = std::max( 0, remainingWidth / dielectricLayerCount ); + } + + for( BOARD_STACKUP_ROW_UI_ITEM& ui_item : m_rowUiItemsList ) + { + BOARD_STACKUP_ITEM* item = ui_item.m_Item; + + if( item->GetType() != BS_ITEM_TYPE_DIELECTRIC || !ui_item.m_isEnabled ) + continue; + + wxChoice* layerType = dynamic_cast( ui_item.m_LayerTypeCtrl ); + + if( !layerType ) + { + // ignore secondary dielectric layers + continue; + } + + wxCheckBox* cbLock = dynamic_cast( ui_item.m_ThicknessLockCtrl ); + + if( cbLock && cbLock->GetValue() ) + { + currentLayerIsCore = !currentLayerIsCore; + + // Don't override width of locked layer + continue; + } + + int layerThickness = currentLayerIsCore ? coreThickness : prePregThickness; + + wxTextCtrl* textCtrl = static_cast( ui_item.m_ThicknessCtrl ); + layerType->SetSelection( currentLayerIsCore ? 0 : 1 ); + textCtrl->SetValue( m_frame->StringFromValue( layerThickness ) ); + + currentLayerIsCore = !currentLayerIsCore; + } +} + + int PANEL_SETUP_BOARD_STACKUP::computeBoardThickness() { int thickness = 0; diff --git a/pcbnew/board_stackup_manager/panel_board_stackup.h b/pcbnew/board_stackup_manager/panel_board_stackup.h index a6f76adc16..5c40cebc47 100644 --- a/pcbnew/board_stackup_manager/panel_board_stackup.h +++ b/pcbnew/board_stackup_manager/panel_board_stackup.h @@ -189,6 +189,12 @@ private: */ int computeBoardThickness(); + /** + * Set the widths of dielectric layers to sensible defaults + * @param targetThickness target thickness of PCB in IU + */ + void setDefaultLayerWidths( int targetThickness ); + void onColorSelected( wxCommandEvent& event ); void onMaterialChange( wxCommandEvent& event ); void onThicknessChange( wxCommandEvent& event );