diff --git a/api/proto/common/types/project_settings.proto b/api/proto/common/types/project_settings.proto index 5af1320464..7e8b03e87a 100644 --- a/api/proto/common/types/project_settings.proto +++ b/api/proto/common/types/project_settings.proto @@ -49,6 +49,9 @@ message NetClassBoardSettings optional kiapi.board.types.PadStack microvia_stack = 7; optional kiapi.common.types.Color color = 8; + + // Since 10.0.0 + optional string tuning_profile = 9; } message NetClassSchematicSettings diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 8cf87308e6..3c7440e2d1 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -153,7 +153,7 @@ set( KICOMMON_SRCS project/project_archiver.cpp project/project_file.cpp project/project_local_settings.cpp - project/time_domain_parameters.cpp + project/tuning_profiles.cpp text_eval/text_eval_wrapper.cpp text_eval/text_eval_parser.cpp @@ -959,7 +959,7 @@ set( PCB_COMMON_SRCS ${CMAKE_SOURCE_DIR}/pcbnew/length_delay_calculation/length_delay_calculation.cpp ${CMAKE_SOURCE_DIR}/pcbnew/length_delay_calculation/length_delay_calculation_item.cpp - ${CMAKE_SOURCE_DIR}/pcbnew/length_delay_calculation/time_domain_parameters_user_defined.cpp + ${CMAKE_SOURCE_DIR}/pcbnew/length_delay_calculation/tuning_profile_parameters_user_defined.cpp widgets/net_selector.cpp ) diff --git a/common/dialogs/panel_setup_netclasses.cpp b/common/dialogs/panel_setup_netclasses.cpp index a1c6dbba18..91a62a0aa9 100644 --- a/common/dialogs/panel_setup_netclasses.cpp +++ b/common/dialogs/panel_setup_netclasses.cpp @@ -287,7 +287,7 @@ void PANEL_SETUP_NETCLASSES::loadNetclasses() [&]( int aRow, const NETCLASS* nc ) { m_netclassGrid->SetCellValue( aRow, GRID_NAME, nc->GetName() ); - m_netclassGrid->SetCellValue( aRow, GRID_DELAY_PROFILE, nc->GetDelayProfile() ); + m_netclassGrid->SetCellValue( aRow, GRID_DELAY_PROFILE, nc->GetTuningProfile() ); m_netclassGrid->SetOptionalUnitValue( aRow, GRID_WIREWIDTH, nc->GetWireWidthOpt() ); m_netclassGrid->SetOptionalUnitValue( aRow, GRID_BUSWIDTH, nc->GetBusWidthOpt() ); @@ -486,7 +486,7 @@ bool PANEL_SETUP_NETCLASSES::TransferDataFromWindow() nc->SetPriority( aRow ); nc->SetName( m_netclassGrid->GetCellValue( aRow, GRID_NAME ) ); - nc->SetDelayProfile( m_netclassGrid->GetCellValue( aRow, GRID_DELAY_PROFILE ) ); + nc->SetTuningProfile( m_netclassGrid->GetCellValue( aRow, GRID_DELAY_PROFILE ) ); nc->SetWireWidth( m_netclassGrid->GetOptionalUnitValue( aRow, GRID_WIREWIDTH ) ); nc->SetBusWidth( m_netclassGrid->GetOptionalUnitValue( aRow, GRID_BUSWIDTH ) ); diff --git a/common/dialogs/panel_setup_netclasses_base.cpp b/common/dialogs/panel_setup_netclasses_base.cpp index 127a5f60e1..a7a8c3355f 100644 --- a/common/dialogs/panel_setup_netclasses_base.cpp +++ b/common/dialogs/panel_setup_netclasses_base.cpp @@ -57,7 +57,7 @@ PANEL_SETUP_NETCLASSES_BASE::PANEL_SETUP_NETCLASSES_BASE( wxWindow* parent, wxWi m_netclassGrid->SetColLabelValue( 6, _("uVia Hole") ); m_netclassGrid->SetColLabelValue( 7, _("DP Width") ); m_netclassGrid->SetColLabelValue( 8, _("DP Gap") ); - m_netclassGrid->SetColLabelValue( 9, _("Delay Profile") ); + m_netclassGrid->SetColLabelValue( 9, _("Tuning Profile") ); m_netclassGrid->SetColLabelValue( 10, _("PCB Color") ); m_netclassGrid->SetColLabelValue( 11, _("Wire Thickness") ); m_netclassGrid->SetColLabelValue( 12, _("Bus Thickness") ); diff --git a/common/dialogs/panel_setup_netclasses_base.fbp b/common/dialogs/panel_setup_netclasses_base.fbp index 24fde54d1f..f30477045e 100644 --- a/common/dialogs/panel_setup_netclasses_base.fbp +++ b/common/dialogs/panel_setup_netclasses_base.fbp @@ -290,7 +290,7 @@ 1 wxALIGN_CENTER wxGRID_AUTOSIZE - "Name" "Clearance" "Track Width" "Via Size" "Via Hole" "uVia Size" "uVia Hole" "DP Width" "DP Gap" "Delay Profile" "PCB Color" "Wire Thickness" "Bus Thickness" "Color" "Line Style" + "Name" "Clearance" "Track Width" "Via Size" "Via Hole" "uVia Size" "uVia Hole" "DP Width" "DP Gap" "Tuning Profile" "PCB Color" "Wire Thickness" "Bus Thickness" "Color" "Line Style" wxALIGN_CENTER 15 diff --git a/common/netclass.cpp b/common/netclass.cpp index 3d4027ede5..bd42cca791 100644 --- a/common/netclass.cpp +++ b/common/netclass.cpp @@ -59,7 +59,7 @@ NETCLASS::NETCLASS( const wxString& aName, bool aInitWithDefaults ) : m_isDefaul SetName( aName ); SetPriority( -1 ); - SetDelayProfile( wxEmptyString ); + SetTuningProfile( wxEmptyString ); // Colors are a special optional case - always set, but UNSPECIFIED used in place of optional SetPcbColor( COLOR4D::UNSPECIFIED ); @@ -102,7 +102,7 @@ void NETCLASS::ResetParents() SetBusWidthParent( this ); SetSchematicColorParent( this ); SetLineStyleParent( this ); - SetDelayProfileParent( this ); + SetTuningProfileParent( this ); } @@ -180,6 +180,9 @@ void NETCLASS::Serialize( google::protobuf::Any &aContainer ) const if( m_pcbColor != COLOR4D::UNSPECIFIED ) PackColor( *board->mutable_color(), m_pcbColor ); + if( m_tuningProfile != wxEmptyString ) + board->set_tuning_profile( m_tuningProfile.ToUTF8() ); + project::NetClassSchematicSettings* schematic = nc.mutable_schematic(); if( m_wireWidth ) @@ -246,6 +249,9 @@ bool NETCLASS::Deserialize( const google::protobuf::Any &aContainer ) if( nc.board().has_color() ) m_pcbColor = UnpackColor( nc.board().color() ); + if( nc.board().has_tuning_profile() ) + m_tuningProfile = wxString::FromUTF8( nc.board().tuning_profile() ); + if( nc.schematic().has_wire_width() ) m_wireWidth = nc.schematic().wire_width().value_nm(); diff --git a/common/project/net_settings.cpp b/common/project/net_settings.cpp index 4ad03ffb31..32d56e3004 100644 --- a/common/project/net_settings.cpp +++ b/common/project/net_settings.cpp @@ -76,7 +76,7 @@ NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) : { "priority", nc->GetPriority() }, { "schematic_color", nc->GetSchematicColor( true ) }, { "pcb_color", nc->GetPcbColor( true ) }, - { "tuning_profile", nc->GetDelayProfile() } }; + { "tuning_profile", nc->GetTuningProfile() } }; auto saveInPcbUnits = []( nlohmann::json& json, const std::string& aKey, int aValue ) @@ -134,7 +134,7 @@ NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) : int priority = entry["priority"]; nc->SetPriority( priority ); - nc->SetDelayProfile( entry["tuning_profile"] ); + nc->SetTuningProfile( entry["tuning_profile"] ); if( auto value = getInPcbUnits( entry, "clearance" ) ) nc->SetClearance( *value ); @@ -925,10 +925,10 @@ void NET_SETTINGS::makeEffectiveNetclass( std::shared_ptr& effectiveNe effectiveNetclass->SetSchematicColorParent( nc ); } - if( nc->HasDelayProfile() ) + if( nc->HasTuningProfile() ) { - effectiveNetclass->SetDelayProfile( nc->GetDelayProfile() ); - effectiveNetclass->SetDelayProfileParent( nc ); + effectiveNetclass->SetTuningProfile( nc->GetTuningProfile() ); + effectiveNetclass->SetTuningProfileParent( nc ); } } @@ -1021,11 +1021,11 @@ bool NET_SETTINGS::addMissingDefaults( NETCLASS* nc ) const } // The tuning profile can be empty - only fill if a default tuning profile is set - if( !nc->HasDelayProfile() && m_defaultNetClass->HasDelayProfile() ) + if( !nc->HasTuningProfile() && m_defaultNetClass->HasTuningProfile() ) { addedDefault = true; - nc->SetDelayProfile( m_defaultNetClass->GetDelayProfile() ); - nc->SetDelayProfileParent( m_defaultNetClass.get() ); + nc->SetTuningProfile( m_defaultNetClass->GetTuningProfile() ); + nc->SetTuningProfileParent( m_defaultNetClass.get() ); } return addedDefault; diff --git a/common/project/project_file.cpp b/common/project/project_file.cpp index 623bb9e566..67b7e5c826 100644 --- a/common/project/project_file.cpp +++ b/common/project/project_file.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -160,8 +160,7 @@ PROJECT_FILE::PROJECT_FILE( const wxString& aFullPath ) : m_ComponentClassSettings = std::make_shared( this, "component_class_settings" ); - m_timeDomainParameters = - std::make_shared( this, "time_domain_parameters" ); + m_tuningProfileParameters = std::make_shared( this, "tuning_profiles" ); m_params.emplace_back( new PARAM_LAYER_PRESET( "board.layer_presets", &m_LayerPresets ) ); diff --git a/common/project/time_domain_parameters.cpp b/common/project/tuning_profiles.cpp similarity index 50% rename from common/project/time_domain_parameters.cpp rename to common/project/tuning_profiles.cpp index 3b7bdf14bf..361e3dd7ba 100644 --- a/common/project/time_domain_parameters.cpp +++ b/common/project/tuning_profiles.cpp @@ -21,18 +21,15 @@ #include #include - -#include -#include +#include #include #include -constexpr int timeDomainParametersSchemaVersion = 0; +constexpr int tuningParametersSchemaVersion = 0; -TIME_DOMAIN_PARAMETERS::TIME_DOMAIN_PARAMETERS( JSON_SETTINGS* aParent, const std::string& aPath ) : - NESTED_SETTINGS( "time_domain_parameters", timeDomainParametersSchemaVersion, aParent, - aPath, false ) +TUNING_PROFILES::TUNING_PROFILES( JSON_SETTINGS* aParent, const std::string& aPath ) : + NESTED_SETTINGS( "tuning_profiles", tuningParametersSchemaVersion, aParent, aPath, false ) { auto saveViaOverrideConfigurationLine = []( nlohmann::json& json_array, const DELAY_PROFILE_VIA_OVERRIDE_ENTRY& item ) @@ -71,14 +68,22 @@ TIME_DOMAIN_PARAMETERS::TIME_DOMAIN_PARAMETERS( JSON_SETTINGS* aParent, const st }; auto saveUserDefinedProfileConfigurationLine = - [&saveViaOverrideConfigurationLine]( nlohmann::json& json_array, const DELAY_PROFILE& item ) + [&saveViaOverrideConfigurationLine]( nlohmann::json& json_array, const TUNING_PROFILE& item ) { - nlohmann::json layer_velocities = nlohmann::json::array(); + nlohmann::json layer_entries = nlohmann::json::array(); - for( const auto& [layerId, velocity] : item.m_LayerPropagationDelays ) + for( const DELAY_PROFILE_TRACK_PROPAGATION_ENTRY& trackEntry : item.m_TrackPropagationEntries ) { - nlohmann::json layer_json = { { "layer", LSET::Name( layerId ) }, { "delay", velocity } }; - layer_velocities.push_back( layer_json ); + nlohmann::json layer_json; + + layer_json["signal_layer"] = LSET::Name( trackEntry.m_signalLayer ); + layer_json["top_reference_layer"] = LSET::Name( trackEntry.m_topReferenceLayer ); + layer_json["bottom_reference_layer"] = LSET::Name( trackEntry.m_bottomReferenceLayer ); + layer_json["width"] = trackEntry.m_width; + layer_json["diff_pair_gap"] = trackEntry.m_diffPairGap; + layer_json["delay"] = trackEntry.m_delay; + + layer_entries.push_back( layer_json ); } nlohmann::json via_overrides = nlohmann::json::array(); @@ -89,8 +94,12 @@ TIME_DOMAIN_PARAMETERS::TIME_DOMAIN_PARAMETERS( JSON_SETTINGS* aParent, const st } const nlohmann::json item_json = { { "profile_name", item.m_ProfileName.ToUTF8() }, + { "type", static_cast( item.m_Type ) }, + { "target_impedance", item.m_TargetImpedance }, + { "generate_drc_rules", item.m_GenerateNetClassDRCRules }, + { "enable_time_domain_tuning", item.m_EnableTimeDomainTuning }, + { "layer_entries", layer_entries }, { "via_prop_delay", item.m_ViaPropagationDelay }, - { "layer_delays", layer_velocities }, { "via_overrides", via_overrides } }; json_array.push_back( item_json ); @@ -98,19 +107,38 @@ TIME_DOMAIN_PARAMETERS::TIME_DOMAIN_PARAMETERS( JSON_SETTINGS* aParent, const st auto readUserDefinedProfileConfigurationLine = [&readViaOverrideConfigurationLine]( const nlohmann::json& entry ) { - const wxString profileName = entry["profile_name"]; - const int viaPropDelay = entry["via_prop_delay"]; - std::map traceDelays; + const wxString profileName = entry["profile_name"]; + const TUNING_PROFILE::PROFILE_TYPE profileType = static_cast( entry["type"] ); + const double targetImpedance = entry["target_impedance"]; + const bool generateDrcRules = entry["generate_drc_rules"]; + const bool enableTimeDomainTuning = entry["enable_time_domain_tuning"]; + const int viaPropDelay = entry["via_prop_delay"]; + std::vector trackEntries; + std::map trackEntriesMap; - for( const nlohmann::json& layerEntry : entry["layer_delays"] ) + for( const nlohmann::json& layerEntry : entry["layer_entries"] ) { - if( !layerEntry.is_object() || !layerEntry.contains( "layer" ) ) + if( !layerEntry.is_object() ) continue; - wxString layerName = layerEntry["layer"]; - int layerId = LSET::NameToLayer( layerName ); - const int velocity = layerEntry["delay"]; - traceDelays[static_cast( layerId )] = velocity; + wxString signalLayer = layerEntry["signal_layer"]; + wxString topRefLayer = layerEntry["top_reference_layer"]; + wxString bottomRefLayer = layerEntry["bottom_reference_layer"]; + int signalLayerId = LSET::NameToLayer( signalLayer ); + int topRefLayerId = LSET::NameToLayer( topRefLayer ); + int bottomRefLayerId = LSET::NameToLayer( bottomRefLayer ); + + DELAY_PROFILE_TRACK_PROPAGATION_ENTRY trackEntry; + trackEntry.m_signalLayer = static_cast( signalLayerId ); + trackEntry.m_topReferenceLayer = static_cast( topRefLayerId ); + trackEntry.m_bottomReferenceLayer = static_cast( bottomRefLayerId ); + trackEntry.m_width = layerEntry["width"]; + trackEntry.m_diffPairGap = layerEntry["diff_pair_gap"]; + trackEntry.m_delay = layerEntry["delay"]; + trackEntry.m_enableTimeDomainTuning = enableTimeDomainTuning; + + trackEntries.push_back( trackEntry ); + trackEntriesMap[static_cast( signalLayerId )] = trackEntry; } std::vector viaOverrides; @@ -123,18 +151,26 @@ TIME_DOMAIN_PARAMETERS::TIME_DOMAIN_PARAMETERS( JSON_SETTINGS* aParent, const st viaOverrides.push_back( readViaOverrideConfigurationLine( viaEntry ) ); } - DELAY_PROFILE item{ profileName, viaPropDelay, std::move( traceDelays ), std::move( viaOverrides ) }; + TUNING_PROFILE item{ profileName, + profileType, + targetImpedance, + generateDrcRules, + enableTimeDomainTuning, + std::move( trackEntries ), + viaPropDelay, + std::move( viaOverrides ), + std::move( trackEntriesMap ) }; return item; }; m_params.emplace_back( new PARAM_LAMBDA( - "delay_profiles_user_defined", + "tuning_profiles_impedance_geometric", [&]() -> nlohmann::json { nlohmann::json ret = nlohmann::json::array(); - for( const auto& entry : m_delayProfiles ) + for( const auto& entry : m_tuningProfiles ) saveUserDefinedProfileConfigurationLine( ret, entry ); return ret; @@ -144,21 +180,21 @@ TIME_DOMAIN_PARAMETERS::TIME_DOMAIN_PARAMETERS( JSON_SETTINGS* aParent, const st if( !aJson.is_array() ) return; - ClearDelayProfiles(); + ClearTuningProfiles(); for( const nlohmann::json& entry : aJson ) { if( !entry.is_object() || !entry.contains( "profile_name" ) ) continue; - m_delayProfiles.emplace_back( readUserDefinedProfileConfigurationLine( entry ) ); + m_tuningProfiles.emplace_back( readUserDefinedProfileConfigurationLine( entry ) ); } }, {} ) ); } -TIME_DOMAIN_PARAMETERS::~TIME_DOMAIN_PARAMETERS() +TUNING_PROFILES::~TUNING_PROFILES() { // Release early before destroying members if( m_parent ) @@ -169,28 +205,22 @@ TIME_DOMAIN_PARAMETERS::~TIME_DOMAIN_PARAMETERS() } -bool TIME_DOMAIN_PARAMETERS::operator==( const TIME_DOMAIN_PARAMETERS& aOther ) const +TUNING_PROFILE& TUNING_PROFILES::GetTuningProfile( wxString aProfileName ) { - /* - if( !std::equal( std::begin( m_netClasses ), std::end( m_netClasses ), - std::begin( aOther.m_netClasses ) ) ) - return false; + auto itr = std::find_if( m_tuningProfiles.begin(), m_tuningProfiles.end(), + [&aProfileName]( const TUNING_PROFILE& aProfile ) + { + return aProfile.m_ProfileName == aProfileName; + } ); - if( !std::equal( std::begin( m_netClassPatternAssignments ), - std::end( m_netClassPatternAssignments ), - std::begin( aOther.m_netClassPatternAssignments ) ) ) - return false; + if( itr == m_tuningProfiles.end() ) + return m_nullDelayProfile; - if( !std::equal( std::begin( m_netClassLabelAssignments ), - std::end( m_netClassLabelAssignments ), - std::begin( aOther.m_netClassLabelAssignments ) ) ) - return false; - - - if( !std::equal( std::begin( m_netColorAssignments ), std::end( m_netColorAssignments ), - std::begin( aOther.m_netColorAssignments ) ) ) - return false; - */ - - return true; + return *itr; +} + + +bool TUNING_PROFILES::operator==( const TUNING_PROFILES& aOther ) const +{ + return m_tuningProfiles == aOther.m_tuningProfiles; } diff --git a/common/transline_calculations/coupled_microstrip.cpp b/common/transline_calculations/coupled_microstrip.cpp index 66f86685d5..90b48877e7 100644 --- a/common/transline_calculations/coupled_microstrip.cpp +++ b/common/transline_calculations/coupled_microstrip.cpp @@ -60,10 +60,10 @@ void COUPLED_MICROSTRIP::Analyse() bool COUPLED_MICROSTRIP::Synthesize( const SYNTHESIZE_OPTS aOpts ) { if( aOpts == SYNTHESIZE_OPTS::FIX_WIDTH ) - return MinimiseZ0Error1D( TCP::PHYS_S, TCP::Z0_O ); + return MinimiseZ0Error1D( TCP::PHYS_S, TCP::Z0_O, false ); if( aOpts == SYNTHESIZE_OPTS::FIX_SPACING ) - return MinimiseZ0Error1D( TCP::PHYS_WIDTH, TCP::Z0_O ); + return MinimiseZ0Error1D( TCP::PHYS_WIDTH, TCP::Z0_O, false ); double Z0_e, Z0_o, ang_l_dest; double f1, f2, ft1, ft2, j11, j12, j21, j22, d_s_h, d_w_h, err; @@ -173,16 +173,16 @@ void COUPLED_MICROSTRIP::SetAnalysisResults() void COUPLED_MICROSTRIP::SetSynthesisResults() { - SetAnalysisResult( TCP::EPSILON_EFF_EVEN, er_eff_e ); - SetAnalysisResult( TCP::EPSILON_EFF_ODD, er_eff_o ); - SetAnalysisResult( TCP::UNIT_PROP_DELAY_EVEN, prop_delay_e ); - SetAnalysisResult( TCP::UNIT_PROP_DELAY_ODD, prop_delay_o ); - SetAnalysisResult( TCP::ATTEN_COND_EVEN, atten_cond_e ); - SetAnalysisResult( TCP::ATTEN_COND_ODD, atten_cond_o ); - SetAnalysisResult( TCP::ATTEN_DILECTRIC_EVEN, atten_dielectric_e ); - SetAnalysisResult( TCP::ATTEN_DILECTRIC_ODD, atten_dielectric_o ); - SetAnalysisResult( TCP::SKIN_DEPTH, GetParameter( TCP::SKIN_DEPTH ) ); - SetAnalysisResult( TCP::Z_DIFF, Zdiff ); + SetSynthesisResult( TCP::EPSILON_EFF_EVEN, er_eff_e ); + SetSynthesisResult( TCP::EPSILON_EFF_ODD, er_eff_o ); + SetSynthesisResult( TCP::UNIT_PROP_DELAY_EVEN, prop_delay_e ); + SetSynthesisResult( TCP::UNIT_PROP_DELAY_ODD, prop_delay_o ); + SetSynthesisResult( TCP::ATTEN_COND_EVEN, atten_cond_e ); + SetSynthesisResult( TCP::ATTEN_COND_ODD, atten_cond_o ); + SetSynthesisResult( TCP::ATTEN_DILECTRIC_EVEN, atten_dielectric_e ); + SetSynthesisResult( TCP::ATTEN_DILECTRIC_ODD, atten_dielectric_o ); + SetSynthesisResult( TCP::SKIN_DEPTH, GetParameter( TCP::SKIN_DEPTH ) ); + SetSynthesisResult( TCP::Z_DIFF, Zdiff ); const double Z0_E = GetParameter( TCP::Z0_E ); const double Z0_O = GetParameter( TCP::Z0_O ); @@ -198,12 +198,12 @@ void COUPLED_MICROSTRIP::SetSynthesisResults() const bool L_invalid = !std::isfinite( L ) || L < 0; const bool S_invalid = !std::isfinite( S ) || S <= 0; - SetAnalysisResult( TCP::Z0_E, Z0_E, Z0_E_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK ); - SetAnalysisResult( TCP::Z0_O, Z0_O, Z0_O_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK ); - SetAnalysisResult( TCP::ANG_L, ANG_L, ANG_L_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK ); - SetAnalysisResult( TCP::PHYS_WIDTH, W, W_invalid ? TRANSLINE_STATUS::TS_ERROR : TRANSLINE_STATUS::OK ); - SetAnalysisResult( TCP::PHYS_LEN, L, L_invalid ? TRANSLINE_STATUS::TS_ERROR : TRANSLINE_STATUS::OK ); - SetAnalysisResult( TCP::PHYS_S, S, S_invalid ? TRANSLINE_STATUS::TS_ERROR : TRANSLINE_STATUS::OK ); + SetSynthesisResult( TCP::Z0_E, Z0_E, Z0_E_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK ); + SetSynthesisResult( TCP::Z0_O, Z0_O, Z0_O_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK ); + SetSynthesisResult( TCP::ANG_L, ANG_L, ANG_L_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK ); + SetSynthesisResult( TCP::PHYS_WIDTH, W, W_invalid ? TRANSLINE_STATUS::TS_ERROR : TRANSLINE_STATUS::OK ); + SetSynthesisResult( TCP::PHYS_LEN, L, L_invalid ? TRANSLINE_STATUS::TS_ERROR : TRANSLINE_STATUS::OK ); + SetSynthesisResult( TCP::PHYS_S, S, S_invalid ? TRANSLINE_STATUS::TS_ERROR : TRANSLINE_STATUS::OK ); } diff --git a/common/transline_calculations/coupled_stripline.cpp b/common/transline_calculations/coupled_stripline.cpp index a4626962ae..80f3916f0a 100644 --- a/common/transline_calculations/coupled_stripline.cpp +++ b/common/transline_calculations/coupled_stripline.cpp @@ -71,10 +71,10 @@ void COUPLED_STRIPLINE::Analyse() bool COUPLED_STRIPLINE::Synthesize( const SYNTHESIZE_OPTS aOpts ) { if( aOpts == SYNTHESIZE_OPTS::FIX_WIDTH ) - return MinimiseZ0Error1D( TCP::PHYS_S, TCP::Z0_O ); + return MinimiseZ0Error1D( TCP::PHYS_S, TCP::Z0_O, false ); if( aOpts == SYNTHESIZE_OPTS::FIX_SPACING ) - return MinimiseZ0Error1D( TCP::PHYS_WIDTH, TCP::Z0_O ); + return MinimiseZ0Error1D( TCP::PHYS_WIDTH, TCP::Z0_O, false ); // This synthesis approach is modified from wcalc, which is released under GPL version 2 // Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2006 Dan McMahill diff --git a/common/transline_calculations/transline_calculation_base.cpp b/common/transline_calculations/transline_calculation_base.cpp index 38f1538453..0084dfde4a 100644 --- a/common/transline_calculations/transline_calculation_base.cpp +++ b/common/transline_calculations/transline_calculation_base.cpp @@ -63,7 +63,7 @@ void TRANSLINE_CALCULATION_BASE::SetSynthesisResult( const TRANSLINE_PARAMETERS bool TRANSLINE_CALCULATION_BASE::MinimiseZ0Error1D( const TRANSLINE_PARAMETERS aOptimise, - const TRANSLINE_PARAMETERS aMeasure ) + const TRANSLINE_PARAMETERS aMeasure, bool aRecalculateLength ) { double& var = GetParameterRef( aOptimise ); double& Z0_param = GetParameterRef( aMeasure ); @@ -125,17 +125,20 @@ bool TRANSLINE_CALCULATION_BASE::MinimiseZ0Error1D( const TRANSLINE_PARAMETERS a } /* Compute one last time, but with correct length */ - Z0_param = Z0_dest; - ANG_L_param = angl_l_dest; - SetParameter( TCP::PHYS_LEN, TC::C0 / GetParameter( TCP::FREQUENCY ) / sqrt( GetParameter( TCP::EPSILON_EFF ) ) - * ANG_L_param / 2.0 / M_PI ); /* in m */ - Analyse(); + if( aRecalculateLength ) + { + Z0_param = Z0_dest; + ANG_L_param = angl_l_dest; + SetParameter( TCP::PHYS_LEN, TC::C0 / GetParameter( TCP::FREQUENCY ) / sqrt( GetParameter( TCP::EPSILON_EFF ) ) + * ANG_L_param / 2.0 / M_PI ); /* in m */ + Analyse(); - /* Restore parameters */ - Z0_param = Z0_dest; - ANG_L_param = angl_l_dest; - SetParameter( TCP::PHYS_LEN, TC::C0 / GetParameter( TCP::FREQUENCY ) / sqrt( GetParameter( TCP::EPSILON_EFF ) ) - * ANG_L_param / 2.0 / M_PI ); /* in m */ + /* Restore parameters */ + Z0_param = Z0_dest; + ANG_L_param = angl_l_dest; + SetParameter( TCP::PHYS_LEN, TC::C0 / GetParameter( TCP::FREQUENCY ) / sqrt( GetParameter( TCP::EPSILON_EFF ) ) + * ANG_L_param / 2.0 / M_PI ); /* in m */ + } return error <= m_maxError; } diff --git a/common/transline_calculations/transline_calculation_base.h b/common/transline_calculations/transline_calculation_base.h index e55c750a67..9e5449523e 100644 --- a/common/transline_calculations/transline_calculation_base.h +++ b/common/transline_calculations/transline_calculation_base.h @@ -165,9 +165,11 @@ protected: * * @param aOptimise Parameter to optimise * @param aMeasure The parameter to measure / optimise against + * @param aRecalculateLength True if the angular length should be recalculated (not for differential pair usage) * @returns true if error < MAX_ERROR, otherwise false */ - bool MinimiseZ0Error1D( TRANSLINE_PARAMETERS aOptimise, TRANSLINE_PARAMETERS aMeasure ); + bool MinimiseZ0Error1D( TRANSLINE_PARAMETERS aOptimise, TRANSLINE_PARAMETERS aMeasure, + bool aRecalculateLength = false ); /** * minimizeZ0Error2D diff --git a/common/widgets/grid_text_button_helpers.cpp b/common/widgets/grid_text_button_helpers.cpp index 159a390e73..237a287ee6 100644 --- a/common/widgets/grid_text_button_helpers.cpp +++ b/common/widgets/grid_text_button_helpers.cpp @@ -621,3 +621,58 @@ void GRID_CELL_PATH_EDITOR::Create( wxWindow* aParent, wxWindowID aId, wxGridCellEditor::Create( aParent, aId, aEventHandler ); } + +class TEXT_BUTTON_RUN_FUNCTION final : public wxComboCtrl +{ +public: + TEXT_BUTTON_RUN_FUNCTION( wxWindow* aParent, DIALOG_SHIM* aParentDlg, std::function& aFunction, + int& aRow, int& aCol ) : + wxComboCtrl( aParent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 0, 0 ), + wxTE_PROCESS_ENTER | wxBORDER_NONE ), + m_dlg( aParentDlg ), + m_function( aFunction ), + m_row( aRow ), + m_col( aCol ) + { + SetButtonBitmaps( KiBitmapBundle( BITMAPS::small_refresh ) ); + + // win32 fix, avoids drawing the "native dropdown caret" + Customize( wxCC_IFLAG_HAS_NONSTANDARD_BUTTON ); + } + +protected: + void DoSetPopupControl( wxComboPopup* popup ) override { m_popup = nullptr; } + + void OnButtonClick() override { m_function( m_row, m_col ); } + + DIALOG_SHIM* m_dlg; + std::function& m_function; + int& m_row; + int& m_col; +}; + + +void GRID_CELL_RUN_FUNCTION_EDITOR::Create( wxWindow* aParent, wxWindowID aId, wxEvtHandler* aEventHandler ) +{ + m_control = new TEXT_BUTTON_RUN_FUNCTION( aParent, m_dlg, m_function, m_row, m_col ); + WX_GRID::CellEditorSetMargins( Combo() ); + +#if wxUSE_VALIDATORS + // validate text in textctrl, if validator is set + if( m_validator ) + { + Combo()->SetValidator( *m_validator ); + } +#endif + + wxGridCellEditor::Create( aParent, aId, aEventHandler ); +} + + +void GRID_CELL_RUN_FUNCTION_EDITOR::BeginEdit( int aRow, int aCol, wxGrid* aGrid ) +{ + m_row = aRow; + m_col = aCol; + + GRID_CELL_TEXT_BUTTON::BeginEdit( aRow, aCol, aGrid ); +} diff --git a/common/widgets/wx_grid.cpp b/common/widgets/wx_grid.cpp index a505911a51..eea3f18634 100644 --- a/common/widgets/wx_grid.cpp +++ b/common/widgets/wx_grid.cpp @@ -386,7 +386,8 @@ void WX_GRID::onCellEditorHidden( wxGridEvent& aEvent ) if( cellEditor ) { - if( GRID_CELL_MARK_AS_NULLABLE* nullable = dynamic_cast( cellEditor ) ) + if( const GRID_CELL_NULLABLE_INTERFACE* nullable = + dynamic_cast( cellEditor ) ) isNullable = nullable->IsNullable(); cellEditor->DecRef(); @@ -897,7 +898,14 @@ void WX_GRID::SetUnitValue( int aRow, int aCol, int aValue ) void WX_GRID::SetOptionalUnitValue( int aRow, int aCol, std::optional aValue ) { - SetCellValue( aRow, aCol, getUnitsProvider( aCol )->StringFromOptionalValue( aValue, true ) ); + EDA_DATA_TYPE cellDataType; + + if( m_autoEvalColsUnits.contains( aCol ) ) + cellDataType = m_autoEvalColsUnits[aCol].second; + else + cellDataType = EDA_DATA_TYPE::DISTANCE; + + SetCellValue( aRow, aCol, getUnitsProvider( aCol )->StringFromOptionalValue( aValue, true, cellDataType ) ); } diff --git a/include/netclass.h b/include/netclass.h index 466a3f5350..0e167f03ce 100644 --- a/include/netclass.h +++ b/include/netclass.h @@ -241,11 +241,11 @@ public: void SetPriority( int aPriority ) { m_Priority = aPriority; } int GetPriority() const { return m_Priority; } - bool HasDelayProfile() const { return !m_DelayProfile.empty(); } - void SetDelayProfile( const wxString& aDelayProfile ) { m_DelayProfile = aDelayProfile; } - wxString GetDelayProfile() const { return m_DelayProfile; } - void SetDelayProfileParent( NETCLASS* aParent ) { m_delayProfileParent = aParent; } - NETCLASS* GetDelayProfileParent() const { return m_delayProfileParent; } + bool HasTuningProfile() const { return !m_tuningProfile.empty(); } + void SetTuningProfile( const wxString& aTuningProfile ) { m_tuningProfile = aTuningProfile; } + wxString GetTuningProfile() const { return m_tuningProfile; } + void SetTuningProfileParent( NETCLASS* aParent ) { m_tuningProfileParent = aParent; } + NETCLASS* GetTuningProfileParent() const { return m_tuningProfileParent; } protected: bool m_isDefault; ///< Mark if this instance is the default netclass @@ -276,7 +276,7 @@ protected: COLOR4D m_pcbColor; ///< Optional PCB color override for this netclass - wxString m_DelayProfile; ///< The tuning profile name being used by this netclass + wxString m_tuningProfile; ///< The tuning profile name being used by this netclass // The NETCLASS providing each parameter NETCLASS* m_clearanceParent; @@ -293,7 +293,7 @@ protected: NETCLASS* m_busWidthParent; NETCLASS* m_schematicColorParent; NETCLASS* m_lineStyleParent; - NETCLASS* m_delayProfileParent; + NETCLASS* m_tuningProfileParent; }; #endif // CLASS_NETCLASS_H diff --git a/include/project/project_file.h b/include/project/project_file.h index bb403dc4ca..a1022763c1 100644 --- a/include/project/project_file.h +++ b/include/project/project_file.h @@ -32,7 +32,7 @@ class BOARD_DESIGN_SETTINGS; class ERC_SETTINGS; class NET_SETTINGS; class COMPONENT_CLASS_SETTINGS; -class TIME_DOMAIN_PARAMETERS; +class TUNING_PROFILES; class LAYER_PAIR_SETTINGS; class SCHEMATIC_SETTINGS; class TEMPLATES; @@ -144,10 +144,7 @@ public: return m_ComponentClassSettings; } - std::shared_ptr& TimeDomainParameters() - { - return m_timeDomainParameters; - } + std::shared_ptr& TuningProfileParameters() { return m_tuningProfileParameters; } /** * @return true if it should be safe to auto-save this file without user action @@ -237,9 +234,9 @@ public: std::shared_ptr m_ComponentClassSettings; /** - * Time domain parameters for this project + * Tuning profile parameters for this project */ - std::shared_ptr m_timeDomainParameters; + std::shared_ptr m_tuningProfileParameters; std::vector m_LayerPresets; /// List of stored layer presets std::vector m_Viewports; /// List of stored viewports (pos + zoom) diff --git a/include/project/time_domain_parameters.h b/include/project/time_domain_parameters.h deleted file mode 100644 index 9bb2db9e7f..0000000000 --- a/include/project/time_domain_parameters.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2020 CERN - * Copyright The KiCad Developers, see AUTHORS.txt for contributors. - * @author Jon Evans - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -#ifndef KICAD_TIME_DOMAIN_PARAMETERS_H -#define KICAD_TIME_DOMAIN_PARAMETERS_H - -#include -#include - -/** - * Represents a single line in the time domain configuration via overrides configuration grid - */ -struct DELAY_PROFILE_VIA_OVERRIDE_ENTRY -{ - PCB_LAYER_ID m_SignalLayerFrom; - PCB_LAYER_ID m_SignalLayerTo; - PCB_LAYER_ID m_ViaLayerFrom; - PCB_LAYER_ID m_ViaLayerTo; - int m_Delay; - - bool operator<( const DELAY_PROFILE_VIA_OVERRIDE_ENTRY& other ) const - { - if( m_SignalLayerFrom != other.m_SignalLayerFrom ) - return IsCopperLayerLowerThan( m_SignalLayerFrom, other.m_SignalLayerFrom ); - - if( m_SignalLayerTo != other.m_SignalLayerTo ) - return IsCopperLayerLowerThan( m_SignalLayerTo, other.m_SignalLayerTo ); - - if( m_ViaLayerFrom != other.m_ViaLayerFrom ) - return IsCopperLayerLowerThan( m_ViaLayerFrom, other.m_ViaLayerFrom ); - - if( m_ViaLayerTo != other.m_ViaLayerTo ) - return IsCopperLayerLowerThan( m_ViaLayerTo, other.m_ViaLayerTo ); - - return m_Delay < other.m_Delay; - } -}; - - -/** - * Represents a single line in the time domain configuration net class configuration grid - */ -struct DELAY_PROFILE -{ - wxString m_ProfileName; - int m_ViaPropagationDelay; - std::map m_LayerPropagationDelays; - std::vector m_ViaOverrides; -}; - - -/** - * TIME_DOMAIN_PARAMETERS stores the configuration for time-domain tuning - */ -class KICOMMON_API TIME_DOMAIN_PARAMETERS final : public NESTED_SETTINGS -{ -public: - TIME_DOMAIN_PARAMETERS( JSON_SETTINGS* aParent, const std::string& aPath ); - - virtual ~TIME_DOMAIN_PARAMETERS(); - - bool operator==( const TIME_DOMAIN_PARAMETERS& aOther ) const; - - bool operator!=( const TIME_DOMAIN_PARAMETERS& aOther ) const { return !operator==( aOther ); } - - void ClearDelayProfiles() { m_delayProfiles.clear(); } - - void AddDelayProfile( DELAY_PROFILE&& aTraceEntry ) { m_delayProfiles.emplace_back( std::move( aTraceEntry ) ); } - - const std::vector& GetDelayProfiles() const { return m_delayProfiles; } - -private: - std::vector m_delayProfiles; -}; - -#endif // KICAD_NET_SETTINGS_H diff --git a/include/project/tuning_profiles.h b/include/project/tuning_profiles.h new file mode 100644 index 0000000000..31ced6a6f8 --- /dev/null +++ b/include/project/tuning_profiles.h @@ -0,0 +1,225 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2020 CERN + * Copyright The KiCad Developers, see AUTHORS.txt for contributors. + * @author Jon Evans + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef KICAD_TUNING_PROFILES_H +#define KICAD_TUNING_PROFILES_H + +#include +#include + +/** + * Represents a single line in the time domain configuration via overrides configuration grid + */ +struct DELAY_PROFILE_VIA_OVERRIDE_ENTRY +{ + PCB_LAYER_ID m_SignalLayerFrom; + PCB_LAYER_ID m_SignalLayerTo; + PCB_LAYER_ID m_ViaLayerFrom; + PCB_LAYER_ID m_ViaLayerTo; + int m_Delay; + + bool operator<( const DELAY_PROFILE_VIA_OVERRIDE_ENTRY& other ) const + { + if( m_SignalLayerFrom != other.m_SignalLayerFrom ) + return IsCopperLayerLowerThan( m_SignalLayerFrom, other.m_SignalLayerFrom ); + + if( m_SignalLayerTo != other.m_SignalLayerTo ) + return IsCopperLayerLowerThan( m_SignalLayerTo, other.m_SignalLayerTo ); + + if( m_ViaLayerFrom != other.m_ViaLayerFrom ) + return IsCopperLayerLowerThan( m_ViaLayerFrom, other.m_ViaLayerFrom ); + + if( m_ViaLayerTo != other.m_ViaLayerTo ) + return IsCopperLayerLowerThan( m_ViaLayerTo, other.m_ViaLayerTo ); + + return m_Delay < other.m_Delay; + } + + bool operator==( const DELAY_PROFILE_VIA_OVERRIDE_ENTRY& other ) const + { + if( m_SignalLayerFrom != other.m_SignalLayerFrom ) + return false; + + if( m_SignalLayerTo != other.m_SignalLayerTo ) + return false; + + if( m_ViaLayerFrom != other.m_ViaLayerFrom ) + return false; + + if( m_ViaLayerTo != other.m_ViaLayerTo ) + return false; + + if( m_Delay != other.m_Delay ) + return false; + + return true; + } +}; + +class TUNING_PROFILES; + +/** +* Represents a single line in a time domain profile track propagation setup +*/ +class DELAY_PROFILE_TRACK_PROPAGATION_ENTRY +{ +public: + friend class TUNING_PROFILES; + + void SetSignalLayer( const PCB_LAYER_ID aLayer ) { m_signalLayer = aLayer; } + void SetTopReferenceLayer( const PCB_LAYER_ID aLayer ) { m_topReferenceLayer = aLayer; } + void SetBottomReferenceLayer( const PCB_LAYER_ID aLayer ) { m_bottomReferenceLayer = aLayer; } + + void SetWidth( const int aWidth ) { m_width = aWidth; } + void SetDiffPairGap( const int aDiffPairGap ) { m_diffPairGap = aDiffPairGap; } + void SetDelay( const int aDelay ) { m_delay = aDelay; } + void SetEnableTimeDomainTuning( bool aEnable ) { m_enableTimeDomainTuning = aEnable; } + + PCB_LAYER_ID GetSignalLayer() const { return m_signalLayer; } + PCB_LAYER_ID GetTopReferenceLayer() const { return m_topReferenceLayer; } + PCB_LAYER_ID GetBottomReferenceLayer() const { return m_bottomReferenceLayer; } + + int GetWidth() const { return m_width; } + int GetDiffPairGap() const { return m_diffPairGap; } + int GetDelay() const { return m_enableTimeDomainTuning ? m_delay : 0; } + + bool operator==( const DELAY_PROFILE_TRACK_PROPAGATION_ENTRY& other ) const + { + if( m_signalLayer != other.m_signalLayer ) + return false; + + if( m_topReferenceLayer != other.m_topReferenceLayer ) + return false; + + if( m_bottomReferenceLayer != other.m_bottomReferenceLayer ) + return false; + + if( m_width != other.m_width ) + return false; + + if( m_diffPairGap != other.m_diffPairGap ) + return false; + + if( m_delay != other.m_delay ) + return false; + + if( m_enableTimeDomainTuning != other.m_enableTimeDomainTuning ) + return false; + + return true; + } + +private: + PCB_LAYER_ID m_signalLayer{ UNDEFINED_LAYER }; + PCB_LAYER_ID m_topReferenceLayer{ UNDEFINED_LAYER }; + PCB_LAYER_ID m_bottomReferenceLayer{ UNDEFINED_LAYER }; + + int m_width{ 0 }; + int m_diffPairGap{ 0 }; + int m_delay{ 0 }; + + bool m_enableTimeDomainTuning{ false }; +}; + + +/** + * Represents a single line in the tuning profile configuration grid + */ +struct TUNING_PROFILE +{ + enum class PROFILE_TYPE + { + SINGLE, + DIFFERENTIAL + }; + + wxString m_ProfileName; + PROFILE_TYPE m_Type; + double m_TargetImpedance; + bool m_GenerateNetClassDRCRules; + bool m_EnableTimeDomainTuning; + std::vector m_TrackPropagationEntries; + int m_ViaPropagationDelay; + std::vector m_ViaOverrides; + + // This is not persisted - but is used for quick lookup for track statistics calculations + std::map m_TrackPropagationEntriesMap; + + bool operator==( const TUNING_PROFILE& aOther ) const + { + if( m_ProfileName != aOther.m_ProfileName ) + return false; + + if( m_Type != aOther.m_Type ) + return false; + + if( m_TargetImpedance != aOther.m_TargetImpedance ) + return false; + + if( m_GenerateNetClassDRCRules != aOther.m_GenerateNetClassDRCRules ) + return false; + + if( m_EnableTimeDomainTuning != aOther.m_EnableTimeDomainTuning ) + return false; + + if( m_TrackPropagationEntries != aOther.m_TrackPropagationEntries ) + return false; + + if( m_ViaPropagationDelay != aOther.m_ViaPropagationDelay ) + return false; + + if( m_ViaOverrides != aOther.m_ViaOverrides ) + return false; + + return true; + } +}; + + +/** + * TUNING_PROFILES stores the configuration for impedance / delay tuning profiles + */ +class KICOMMON_API TUNING_PROFILES final : public NESTED_SETTINGS +{ +public: + TUNING_PROFILES( JSON_SETTINGS* aParent, const std::string& aPath ); + + virtual ~TUNING_PROFILES(); + + bool operator==( const TUNING_PROFILES& aOther ) const; + + bool operator!=( const TUNING_PROFILES& aOther ) const { return !operator==( aOther ); } + + void ClearTuningProfiles() { m_tuningProfiles.clear(); } + + void AddTuningProfile( TUNING_PROFILE&& aTraceEntry ) { m_tuningProfiles.emplace_back( std::move( aTraceEntry ) ); } + + const std::vector& GetTuningProfiles() const { return m_tuningProfiles; } + + TUNING_PROFILE& GetTuningProfile( wxString aProfileName ); + +private: + std::vector m_tuningProfiles; + + TUNING_PROFILE m_nullDelayProfile; +}; + +#endif // KICAD_TUNING_PROFILES_H diff --git a/include/widgets/grid_icon_text_helpers.h b/include/widgets/grid_icon_text_helpers.h index cabd082b4a..5459158a1b 100644 --- a/include/widgets/grid_icon_text_helpers.h +++ b/include/widgets/grid_icon_text_helpers.h @@ -140,26 +140,45 @@ protected: }; +class GRID_CELL_NULLABLE_INTERFACE +{ +public: + GRID_CELL_NULLABLE_INTERFACE() : + m_isNullable( true ) + { + } + GRID_CELL_NULLABLE_INTERFACE( bool aIsNullable ) : + m_isNullable( aIsNullable ) + { + } + virtual ~GRID_CELL_NULLABLE_INTERFACE() = default; + + virtual bool IsNullable() const { return m_isNullable; } + +protected: + bool m_isNullable{ false }; +}; + + //---- Grid helpers: custom wxGridCellTextEditor ------------------------------------------ // // Note: This is used to mark WX_GRID cell as nullable -class GRID_CELL_MARK_AS_NULLABLE : public wxGridCellTextEditor +class GRID_CELL_MARK_AS_NULLABLE : public wxGridCellTextEditor, public GRID_CELL_NULLABLE_INTERFACE { public: - GRID_CELL_MARK_AS_NULLABLE() : m_isNullable( true ) {} - GRID_CELL_MARK_AS_NULLABLE( bool aIsNullable ) : m_isNullable( aIsNullable ) {} - - wxGridCellEditor* Clone() const override + GRID_CELL_MARK_AS_NULLABLE() : + GRID_CELL_NULLABLE_INTERFACE( true ) { - return new GRID_CELL_MARK_AS_NULLABLE( m_isNullable ); } + GRID_CELL_MARK_AS_NULLABLE( const bool aIsNullable ) : + GRID_CELL_NULLABLE_INTERFACE( aIsNullable ) + { + } + + wxGridCellEditor* Clone() const override { return new GRID_CELL_MARK_AS_NULLABLE( IsNullable() ); } void Reset() override {} - bool IsNullable() { return m_isNullable; } - -protected: - bool m_isNullable; wxDECLARE_NO_COPY_CLASS( GRID_CELL_MARK_AS_NULLABLE ); }; diff --git a/include/widgets/grid_text_button_helpers.h b/include/widgets/grid_text_button_helpers.h index 7a1c4259fd..4117cc71e9 100644 --- a/include/widgets/grid_text_button_helpers.h +++ b/include/widgets/grid_text_button_helpers.h @@ -25,6 +25,8 @@ #ifndef GRID_TEXT_BUTTON_HELPERS_H #define GRID_TEXT_BUTTON_HELPERS_H +#include + #include #include @@ -222,4 +224,39 @@ protected: }; +/** +* A cell editor which runs a provided function when the grid cell button is clicked. +* +* The function has the signature (int, int) -> void. The passed parameters are the (row, col) of the +* clicked grid cell +*/ +class GRID_CELL_RUN_FUNCTION_EDITOR : public GRID_CELL_TEXT_BUTTON, public GRID_CELL_NULLABLE_INTERFACE +{ +public: + GRID_CELL_RUN_FUNCTION_EDITOR( DIALOG_SHIM* aParent, const std::function aFunction, + const bool aIsNullable = false ) : + GRID_CELL_NULLABLE_INTERFACE( aIsNullable ), + m_dlg( aParent ), + m_row( -1 ), + m_col( -1 ), + m_function( aFunction ) + { + } + + wxGridCellEditor* Clone() const override + { + return new GRID_CELL_RUN_FUNCTION_EDITOR( m_dlg, m_function, IsNullable() ); + } + + void Create( wxWindow* aParent, wxWindowID aId, wxEvtHandler* aEventHandler ) override; + void BeginEdit( int aRow, int aCol, wxGrid* aGrid ) override; + + +protected: + DIALOG_SHIM* m_dlg; + int m_row; + int m_col; + std::function m_function; +}; + #endif // GRID_TEXT_BUTTON_HELPERS_H diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 3c95dd28e6..26d408088a 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -206,8 +206,10 @@ set( PCBNEW_DIALOGS dialogs/panel_setup_tracks_and_vias_base.cpp dialogs/panel_setup_tuning_patterns.cpp dialogs/panel_setup_tuning_patterns_base.cpp - dialogs/panel_setup_time_domain_parameters.cpp - dialogs/panel_setup_time_domain_parameters_base.cpp + dialogs/panel_setup_tuning_profiles_base.cpp + dialogs/panel_setup_tuning_profiles.cpp + dialogs/panel_setup_tuning_profile_info_base.cpp + dialogs/panel_setup_tuning_profile_info.cpp footprint_wizard.cpp footprint_wizard_frame.cpp footprint_wizard_frame_functions.cpp diff --git a/pcbnew/board.cpp b/pcbnew/board.cpp index 10e3890a8d..bf957cf58f 100644 --- a/pcbnew/board.cpp +++ b/pcbnew/board.cpp @@ -2408,9 +2408,9 @@ void BOARD::SynchronizeProperties() } -void BOARD::SynchronizeTimeDomainProperties() +void BOARD::SynchronizeTuningProfileProperties() { - m_lengthDelayCalc->SynchronizeTimeDomainProperties(); + m_lengthDelayCalc->SynchronizeTuningProfileProperties(); } diff --git a/pcbnew/board.h b/pcbnew/board.h index 0ffe8455f6..4e06e3c44b 100644 --- a/pcbnew/board.h +++ b/pcbnew/board.h @@ -1084,7 +1084,7 @@ public: /** * Ensure that all time domain properties providers are in sync with current settings */ - void SynchronizeTimeDomainProperties(); + void SynchronizeTuningProfileProperties(); /** * Return the Similarity. Because we compare board to board, we just return 1.0 here diff --git a/pcbnew/board_design_settings.cpp b/pcbnew/board_design_settings.cpp index 3c3e3d2495..e0818f482b 100644 --- a/pcbnew/board_design_settings.cpp +++ b/pcbnew/board_design_settings.cpp @@ -204,6 +204,8 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std: m_DRCSeverities[DRCE_MIRRORED_TEXT_ON_FRONT_LAYER] = RPT_SEVERITY_WARNING; m_DRCSeverities[DRCE_NONMIRRORED_TEXT_ON_BACK_LAYER] = RPT_SEVERITY_WARNING; + m_DRCSeverities[DRCE_MISSING_TUNING_PROFILE] = RPT_SEVERITY_WARNING; + m_MaxError = ARC_HIGH_DEF; m_ZoneKeepExternalFillets = false; m_UseHeightForLengthCalcs = true; diff --git a/pcbnew/dialogs/dialog_board_setup.cpp b/pcbnew/dialogs/dialog_board_setup.cpp index e640b9ac3f..dfd72cd6c4 100644 --- a/pcbnew/dialogs/dialog_board_setup.cpp +++ b/pcbnew/dialogs/dialog_board_setup.cpp @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include #include @@ -50,6 +50,7 @@ #include "dialog_board_setup.h" #include +#include #include @@ -62,7 +63,7 @@ DIALOG_BOARD_SETUP::DIALOG_BOARD_SETUP( PCB_EDIT_FRAME* aFrame, wxWindow* aParen m_layers( nullptr ), m_boardFinish( nullptr ), m_physicalStackup( nullptr ), - m_timeDomainParameters( nullptr ), + m_tuningProfiles( nullptr ), m_netClasses( nullptr ), m_currentPage( 0 ), m_layersPage( 0 ), @@ -78,7 +79,7 @@ DIALOG_BOARD_SETUP::DIALOG_BOARD_SETUP( PCB_EDIT_FRAME* aFrame, wxWindow* aParen m_netclassesPage( 0 ), m_customRulesPage( 0 ), m_severitiesPage( 0 ), - m_timeDomainParametersPage( 0 ) + m_tuningProfilesPage( 0 ) { SetEvtHandlerEnabled( false ); @@ -181,6 +182,16 @@ DIALOG_BOARD_SETUP::DIALOG_BOARD_SETUP( PCB_EDIT_FRAME* aFrame, wxWindow* aParen bds.m_SkewMeanderSettings ); }, _( "Length-tuning Patterns" ) ); + m_tuningProfilesPage = m_treebook->GetPageCount(); + m_treebook->AddLazySubPage( + [this]( wxWindow* aParent ) -> wxWindow* + { + BOARD* board = m_frame->GetBoard(); + return new PANEL_SETUP_TUNING_PROFILES( aParent, m_frame, board, + m_frame->Prj().GetProjectFile().TuningProfileParameters() ); + }, + _( "Tuning Profiles" ) ); + m_netclassesPage = m_treebook->GetPageCount(); m_treebook->AddLazySubPage( [this]( wxWindow* aParent ) -> wxWindow* @@ -203,56 +214,46 @@ DIALOG_BOARD_SETUP::DIALOG_BOARD_SETUP( PCB_EDIT_FRAME* aFrame, wxWindow* aParen }, _( "Component Classes" ) ); - m_timeDomainParametersPage = m_treebook->GetPageCount(); - m_treebook->AddLazySubPage( - [this]( wxWindow* aParent ) -> wxWindow* - { - BOARD* board = m_frame->GetBoard(); - return new PANEL_SETUP_TIME_DOMAIN_PARAMETERS( - aParent, m_frame, board, m_frame->Prj().GetProjectFile().TimeDomainParameters() ); - }, - _( "Time Domain Parameters" ) ); + m_customRulesPage = m_treebook->GetPageCount(); + m_treebook->AddLazySubPage( + [this]( wxWindow* aParent ) -> wxWindow* + { + return new PANEL_SETUP_RULES( aParent, m_frame ); + }, + _( "Custom Rules" ) ); - m_customRulesPage = m_treebook->GetPageCount(); - m_treebook->AddLazySubPage( - [this]( wxWindow* aParent ) -> wxWindow* - { - return new PANEL_SETUP_RULES( aParent, m_frame ); - }, - _( "Custom Rules" ) ); + m_severitiesPage = m_treebook->GetPageCount(); + m_treebook->AddLazySubPage( + [this]( wxWindow* aParent ) -> wxWindow* + { + BOARD* board = m_frame->GetBoard(); + return new PANEL_SETUP_SEVERITIES( aParent, DRC_ITEM::GetItemsWithSeverities(), + board->GetDesignSettings().m_DRCSeverities ); + }, + _( "Violation Severity" ) ); - m_severitiesPage = m_treebook->GetPageCount(); - m_treebook->AddLazySubPage( - [this]( wxWindow* aParent ) -> wxWindow* - { - BOARD* board = m_frame->GetBoard(); - return new PANEL_SETUP_SEVERITIES( aParent, DRC_ITEM::GetItemsWithSeverities(), - board->GetDesignSettings().m_DRCSeverities ); - }, - _( "Violation Severity" ) ); + m_treebook->AddPage( new wxPanel( GetTreebook() ), _( "Board Data" ) ); + m_embeddedFilesPage = m_treebook->GetPageCount(); + m_treebook->AddLazySubPage( + [this]( wxWindow* aParent ) -> wxWindow* + { + return new PANEL_EMBEDDED_FILES( aParent, m_frame->GetBoard(), NO_MARGINS ); + }, + _( "Embedded Files" ) ); - m_treebook->AddPage( new wxPanel( GetTreebook() ), _( "Board Data" ) ); - m_embeddedFilesPage = m_treebook->GetPageCount(); - m_treebook->AddLazySubPage( - [this]( wxWindow* aParent ) -> wxWindow* - { - return new PANEL_EMBEDDED_FILES( aParent, m_frame->GetBoard(), NO_MARGINS ); - }, - _( "Embedded Files" ) ); + for( size_t i = 0; i < m_treebook->GetPageCount(); ++i ) + m_treebook->ExpandNode( i ); - for( size_t i = 0; i < m_treebook->GetPageCount(); ++i ) - m_treebook->ExpandNode( i ); + SetEvtHandlerEnabled( true ); - SetEvtHandlerEnabled( true ); + finishDialogSettings(); - finishDialogSettings(); - - if( Prj().IsReadOnly() ) - { - m_infoBar->ShowMessage( _( "Project is missing or read-only. Some settings will not " - "be editable." ), - wxICON_WARNING ); - } + if( Prj().IsReadOnly() ) + { + m_infoBar->ShowMessage( _( "Project is missing or read-only. Some settings will not " + "be editable." ), + wxICON_WARNING ); + } wxBookCtrlEvent evt( wxEVT_TREEBOOK_PAGE_CHANGED, wxID_ANY, 0 ); @@ -273,12 +274,12 @@ void DIALOG_BOARD_SETUP::onPageChanged( wxBookCtrlEvent& aEvent ) if( m_physicalStackupPage > 0 ) // Don't run this during initialization { - if( m_currentPage == m_physicalStackupPage || m_currentPage == m_timeDomainParametersPage - || page == m_physicalStackupPage || page == m_timeDomainParametersPage || page == m_netclassesPage ) + if( m_currentPage == m_physicalStackupPage || page == m_physicalStackupPage || page == m_netclassesPage + || page == m_tuningProfilesPage ) { m_layers = RESOLVE_PAGE( PANEL_SETUP_LAYERS, m_layersPage ); m_physicalStackup = RESOLVE_PAGE( PANEL_SETUP_BOARD_STACKUP, m_physicalStackupPage ); - m_timeDomainParameters = RESOLVE_PAGE( PANEL_SETUP_TIME_DOMAIN_PARAMETERS, m_timeDomainParametersPage ); + m_tuningProfiles = RESOLVE_PAGE( PANEL_SETUP_TUNING_PROFILES, m_tuningProfilesPage ); m_netClasses = RESOLVE_PAGE( PANEL_SETUP_NETCLASSES, m_netclassesPage ); } @@ -287,21 +288,21 @@ void DIALOG_BOARD_SETUP::onPageChanged( wxBookCtrlEvent& aEvent ) { m_layers->SyncCopperLayers( m_physicalStackup->GetCopperLayerCount() ); - // Avoid calling SyncCopperLayers twice if moving from stackup to time domain directly - m_timeDomainParameters->SyncCopperLayers( m_physicalStackup->GetCopperLayerCount() ); + // Avoid calling SyncCopperLayers twice if moving from stackup to tuning profiles directly + m_tuningProfiles->SyncCopperLayers( m_physicalStackup->GetCopperLayerCount() ); } if( page == m_physicalStackupPage ) { m_physicalStackup->OnLayersOptionsChanged( m_layers->GetUILayerMask() ); } - else if( page == m_netclassesPage || m_currentPage == m_timeDomainParametersPage ) + else if( page == m_netclassesPage || m_currentPage == m_tuningProfilesPage ) { - m_netClasses->UpdateDelayProfileNames( m_timeDomainParameters->GetDelayProfileNames() ); + m_netClasses->UpdateDelayProfileNames( m_tuningProfiles->GetDelayProfileNames() ); } - else if( page == m_timeDomainParametersPage ) + else if( page == m_tuningProfilesPage ) { - m_timeDomainParameters->SyncCopperLayers( m_physicalStackup->GetCopperLayerCount() ); + m_tuningProfiles->SyncCopperLayers( m_physicalStackup->GetCopperLayerCount() ); } if( Prj().IsReadOnly() ) @@ -475,13 +476,12 @@ void DIALOG_BOARD_SETUP::onAuxiliaryAction( wxCommandEvent& aEvent ) RESOLVE_PAGE( PANEL_SETUP_SEVERITIES, m_severitiesPage )->ImportSettingsFrom( otherSettings.m_DRCSeverities ); } - - if( importDlg.m_TimeDomainParametersOpt->GetValue() ) + if( importDlg.m_TuningProfilesOpt->GetValue() ) { PROJECT_FILE& otherProjectFile = otherPrj->GetProjectFile(); - RESOLVE_PAGE( PANEL_SETUP_TIME_DOMAIN_PARAMETERS, m_timeDomainParametersPage ) - ->ImportSettingsFrom( otherProjectFile.TimeDomainParameters() ); + RESOLVE_PAGE( PANEL_SETUP_TUNING_PROFILES, m_tuningProfilesPage ) + ->ImportSettingsFrom( otherProjectFile.TuningProfileParameters() ); } if( otherPrj != &m_frame->Prj() ) diff --git a/pcbnew/dialogs/dialog_board_setup.h b/pcbnew/dialogs/dialog_board_setup.h index 52c8b1fc00..d70a9116fb 100644 --- a/pcbnew/dialogs/dialog_board_setup.h +++ b/pcbnew/dialogs/dialog_board_setup.h @@ -29,7 +29,6 @@ class PANEL_SETUP_CONSTRAINTS; class PANEL_SETUP_LAYERS; class PANEL_SETUP_TEXT_AND_GRAPHICS; class PANEL_SETUP_NETCLASSES; -class PANEL_SETUP_TIME_DOMAIN_PARAMETERS; class PANEL_SETUP_RULES; class PANEL_SETUP_TRACKS_AND_VIAS; class PANEL_SETUP_MASK_AND_PASTE; @@ -37,6 +36,7 @@ class PANEL_SETUP_BOARD_STACKUP; class PANEL_SETUP_BOARD_FINISH; class PANEL_SETUP_SEVERITIES; class PANEL_TEXT_VARIABLES; +class PANEL_SETUP_TUNING_PROFILES; class DIALOG_BOARD_SETUP : public PAGED_DIALOG @@ -54,7 +54,7 @@ protected: PANEL_SETUP_LAYERS* m_layers; PANEL_SETUP_BOARD_FINISH* m_boardFinish; PANEL_SETUP_BOARD_STACKUP* m_physicalStackup; - PANEL_SETUP_TIME_DOMAIN_PARAMETERS* m_timeDomainParameters; + PANEL_SETUP_TUNING_PROFILES* m_tuningProfiles; PANEL_SETUP_NETCLASSES* m_netClasses; private: @@ -74,7 +74,7 @@ private: size_t m_customRulesPage; size_t m_severitiesPage; size_t m_embeddedFilesPage; - size_t m_timeDomainParametersPage; + size_t m_tuningProfilesPage; }; diff --git a/pcbnew/dialogs/dialog_import_settings.cpp b/pcbnew/dialogs/dialog_import_settings.cpp index e7e2a9ced6..f531c5e65c 100644 --- a/pcbnew/dialogs/dialog_import_settings.cpp +++ b/pcbnew/dialogs/dialog_import_settings.cpp @@ -83,8 +83,8 @@ bool DIALOG_IMPORT_SETTINGS::UpdateImportSettingsButton() ( m_LayersOpt->IsChecked() || m_MaskAndPasteOpt->IsChecked() || m_ConstraintsOpt->IsChecked() || m_NetclassesOpt->IsChecked() || m_SeveritiesOpt->IsChecked() || m_TextAndGraphicsOpt->IsChecked() || m_FormattingOpt->IsChecked() || m_TracksAndViasOpt->IsChecked() || m_TuningPatternsOpt->IsChecked() - || m_CustomRulesOpt->IsChecked() || m_ComponentClassesOpt->IsChecked() - || m_TimeDomainParametersOpt->IsChecked() || m_TeardropsOpt->IsChecked() ); + || m_CustomRulesOpt->IsChecked() || m_ComponentClassesOpt->IsChecked() || m_TuningProfilesOpt->IsChecked() + || m_TeardropsOpt->IsChecked() ); m_sdbSizer1OK->Enable( buttonEnableState ); @@ -150,7 +150,7 @@ void DIALOG_IMPORT_SETTINGS::OnSelectAll( wxCommandEvent& event ) m_TeardropsOpt->SetValue( m_showSelectAllOnBtn ); m_TuningPatternsOpt->SetValue( m_showSelectAllOnBtn ); m_CustomRulesOpt->SetValue( m_showSelectAllOnBtn ); - m_TimeDomainParametersOpt->SetValue( m_showSelectAllOnBtn ); + m_TuningProfilesOpt->SetValue( m_showSelectAllOnBtn ); m_ComponentClassesOpt->SetValue( m_showSelectAllOnBtn ); // Ensure "Import Settings" button state is enabled as appropriate diff --git a/pcbnew/dialogs/dialog_import_settings_base.cpp b/pcbnew/dialogs/dialog_import_settings_base.cpp index 747e7a1515..dfcf7d14c5 100644 --- a/pcbnew/dialogs/dialog_import_settings_base.cpp +++ b/pcbnew/dialogs/dialog_import_settings_base.cpp @@ -78,8 +78,8 @@ DIALOG_IMPORT_SETTINGS_BASE::DIALOG_IMPORT_SETTINGS_BASE( wxWindow* parent, wxWi m_ComponentClassesOpt = new wxCheckBox( this, wxID_ANY, _("Component classes"), wxDefaultPosition, wxDefaultSize, 0 ); bLeftCol->Add( m_ComponentClassesOpt, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 ); - m_TimeDomainParametersOpt = new wxCheckBox( this, wxID_ANY, _("Time domain parameters"), wxDefaultPosition, wxDefaultSize, 0 ); - bLeftCol->Add( m_TimeDomainParametersOpt, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 ); + m_TuningProfilesOpt = new wxCheckBox( this, wxID_ANY, _("Tuning Profiles"), wxDefaultPosition, wxDefaultSize, 0 ); + bLeftCol->Add( m_TuningProfilesOpt, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 ); m_CustomRulesOpt = new wxCheckBox( this, wxID_ANY, _("Custom rules"), wxDefaultPosition, wxDefaultSize, 0 ); bLeftCol->Add( m_CustomRulesOpt, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); @@ -128,7 +128,7 @@ DIALOG_IMPORT_SETTINGS_BASE::DIALOG_IMPORT_SETTINGS_BASE( wxWindow* parent, wxWi m_TuningPatternsOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this ); m_NetclassesOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this ); m_ComponentClassesOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this ); - m_TimeDomainParametersOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this ); + m_TuningProfilesOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this ); m_CustomRulesOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this ); m_SeveritiesOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this ); m_selectAllButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnSelectAll ), NULL, this ); @@ -147,7 +147,7 @@ DIALOG_IMPORT_SETTINGS_BASE::~DIALOG_IMPORT_SETTINGS_BASE() m_TuningPatternsOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this ); m_NetclassesOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this ); m_ComponentClassesOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this ); - m_TimeDomainParametersOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this ); + m_TuningProfilesOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this ); m_CustomRulesOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this ); m_SeveritiesOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this ); m_selectAllButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnSelectAll ), NULL, this ); diff --git a/pcbnew/dialogs/dialog_import_settings_base.fbp b/pcbnew/dialogs/dialog_import_settings_base.fbp index 04b97a37b4..b1d48d9848 100644 --- a/pcbnew/dialogs/dialog_import_settings_base.fbp +++ b/pcbnew/dialogs/dialog_import_settings_base.fbp @@ -1050,7 +1050,7 @@ 0 0 wxID_ANY - Time domain parameters + Tuning Profiles 0 @@ -1058,7 +1058,7 @@ 0 1 - m_TimeDomainParametersOpt + m_TuningProfilesOpt 1 diff --git a/pcbnew/dialogs/dialog_import_settings_base.h b/pcbnew/dialogs/dialog_import_settings_base.h index dcc6fa3ad3..9e70c5603d 100644 --- a/pcbnew/dialogs/dialog_import_settings_base.h +++ b/pcbnew/dialogs/dialog_import_settings_base.h @@ -65,7 +65,7 @@ class DIALOG_IMPORT_SETTINGS_BASE : public DIALOG_SHIM wxCheckBox* m_TuningPatternsOpt; wxCheckBox* m_NetclassesOpt; wxCheckBox* m_ComponentClassesOpt; - wxCheckBox* m_TimeDomainParametersOpt; + wxCheckBox* m_TuningProfilesOpt; wxCheckBox* m_CustomRulesOpt; wxCheckBox* m_SeveritiesOpt; diff --git a/pcbnew/dialogs/panel_setup_time_domain_parameters.cpp b/pcbnew/dialogs/panel_setup_time_domain_parameters.cpp deleted file mode 100644 index 739b192e20..0000000000 --- a/pcbnew/dialogs/panel_setup_time_domain_parameters.cpp +++ /dev/null @@ -1,661 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright The KiCad Developers, see AUTHORS.txt for contributors. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -PANEL_SETUP_TIME_DOMAIN_PARAMETERS::PANEL_SETUP_TIME_DOMAIN_PARAMETERS( - wxWindow* aParentWindow, PCB_EDIT_FRAME* aFrame, BOARD* aBoard, - std::shared_ptr aTimeDomainParameters ) : - PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE( aParentWindow ), - m_timeDomainParameters( std::move( aTimeDomainParameters ) ), - m_frame( aFrame ), - m_board( aFrame->GetBoard() ) -{ - m_timeDomainParametersPane->SetBorders( true, false, false, false ); - m_viaDelayOverridesPane->SetBorders( true, false, false, false ); - - // Set up units - m_unitsProvider = std::make_unique( pcbIUScale, m_frame->GetUserUnits() ); - m_tracePropagationGrid->SetUnitsProvider( m_unitsProvider.get() ); - m_viaPropagationGrid->SetUnitsProvider( m_unitsProvider.get() ); - - Freeze(); - - m_splitter->SetMinimumPaneSize( FromDIP( m_splitter->GetMinimumPaneSize() ) ); - - // Set up the tuning profiles grid - m_tracePropagationGrid->BeginBatch(); - m_tracePropagationGrid->SetUseNativeColLabels(); - - m_tracePropagationGrid->EnsureColLabelsVisible(); - m_tracePropagationGrid->PushEventHandler( new GRID_TRICKS( m_tracePropagationGrid ) ); - m_tracePropagationGrid->SetSelectionMode( wxGrid::wxGridSelectRows ); - - m_addDelayProfileButton->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) ); - m_removeDelayProfileButton->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) ); - - m_tracePropagationGrid->EndBatch(); - - m_tracePropagationGrid->Connect( - wxEVT_GRID_CELL_CHANGING, - wxGridEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS::OnDelayProfileGridCellChanging ), nullptr, this ); - - // Set up the via override grid - m_viaPropagationGrid->BeginBatch(); - m_viaPropagationGrid->SetUseNativeColLabels(); - - m_viaPropagationGrid->EnsureColLabelsVisible(); - m_viaPropagationGrid->PushEventHandler( new GRID_TRICKS( m_viaPropagationGrid ) ); - m_viaPropagationGrid->SetSelectionMode( wxGrid::wxGridSelectRows ); - - std::vector viaColIds; - m_viaPropagationGrid->SetAutoEvalColUnits( VIA_GRID_DELAY, - m_unitsProvider->GetUnitsFromType( EDA_DATA_TYPE::TIME ) ); - viaColIds.push_back( VIA_GRID_DELAY ); - m_viaPropagationGrid->SetAutoEvalCols( viaColIds ); - m_viaPropagationGrid->EndBatch(); - - m_addViaOverrideButton->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) ); - m_removeViaOverrideButton->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) ); - - setColumnWidths(); - - Thaw(); -} - - -PANEL_SETUP_TIME_DOMAIN_PARAMETERS::~PANEL_SETUP_TIME_DOMAIN_PARAMETERS() -{ - // Delete the GRID_TRICKS - m_tracePropagationGrid->PopEventHandler( true ); - m_viaPropagationGrid->PopEventHandler( true ); - - m_tracePropagationGrid->Disconnect( - wxEVT_GRID_CELL_CHANGING, - wxGridEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS::OnDelayProfileGridCellChanging ), nullptr, this ); -} - - -bool PANEL_SETUP_TIME_DOMAIN_PARAMETERS::TransferDataToWindow() -{ - m_tracePropagationGrid->ClearRows(); - m_viaPropagationGrid->ClearRows(); - - const std::vector& delayProfiles = m_timeDomainParameters->GetDelayProfiles(); - - SyncCopperLayers( m_board->GetCopperLayerCount() ); - - for( const DELAY_PROFILE& profile : delayProfiles ) - { - addProfileRow( profile ); - - for( const DELAY_PROFILE_VIA_OVERRIDE_ENTRY& viaOverride : profile.m_ViaOverrides ) - addViaRow( profile.m_ProfileName, viaOverride ); - } - - updateViaProfileNamesEditor(); - - return true; -} - - -bool PANEL_SETUP_TIME_DOMAIN_PARAMETERS::TransferDataFromWindow() -{ - if( !Validate() ) - return false; - - m_timeDomainParameters->ClearDelayProfiles(); - - for( int i = 0; i < m_tracePropagationGrid->GetNumberRows(); ++i ) - { - DELAY_PROFILE profile = getProfileRow( i ); - wxString profileName = profile.m_ProfileName; - - for( int j = 0; j < m_viaPropagationGrid->GetNumberRows(); ++j ) - { - if( m_viaPropagationGrid->GetCellValue( j, VIA_GRID_PROFILE_NAME ) == profileName ) - profile.m_ViaOverrides.emplace_back( getViaRow( j ) ); - } - - m_timeDomainParameters->AddDelayProfile( std::move( profile ) ); - } - - return true; -} - - -void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::addProfileRow( const DELAY_PROFILE& aDelayProfile ) -{ - const int rowId = m_tracePropagationGrid->GetNumberRows(); - m_tracePropagationGrid->AppendRows(); - - m_tracePropagationGrid->SetCellValue( rowId, PROFILE_GRID_PROFILE_NAME, aDelayProfile.m_ProfileName ); - m_tracePropagationGrid->SetUnitValue( rowId, PROFILE_GRID_VIA_PROP_DELAY, aDelayProfile.m_ViaPropagationDelay ); - - for( const auto& [layerId, velocity] : aDelayProfile.m_LayerPropagationDelays ) - { - if( !m_copperLayerIdsToColumns.contains( layerId ) ) - continue; - - int col = m_copperLayerIdsToColumns[layerId]; - - if( col < m_tracePropagationGrid->GetNumberCols() ) - m_tracePropagationGrid->SetUnitValue( rowId, col, velocity ); - } -} - - -DELAY_PROFILE PANEL_SETUP_TIME_DOMAIN_PARAMETERS::getProfileRow( const int aRow ) -{ - DELAY_PROFILE entry; - entry.m_ProfileName = getProfileNameForProfileGridRow( aRow ); - entry.m_ViaPropagationDelay = m_tracePropagationGrid->GetUnitValue( aRow, PROFILE_GRID_VIA_PROP_DELAY ); - - std::map propDelays; - - for( const auto& [layer, col] : m_copperLayerIdsToColumns ) - propDelays[layer] = m_tracePropagationGrid->GetUnitValue( aRow, col ); - - entry.m_LayerPropagationDelays = std::move( propDelays ); - - return entry; -} - - -void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::addViaRow( const wxString& aProfileName, - const DELAY_PROFILE_VIA_OVERRIDE_ENTRY& aViaOverrideEntry ) const -{ - const int rowId = m_viaPropagationGrid->GetNumberRows(); - m_viaPropagationGrid->AppendRows(); - m_viaPropagationGrid->SetCellValue( rowId, VIA_GRID_PROFILE_NAME, aProfileName ); - m_viaPropagationGrid->SetCellValue( rowId, VIA_GRID_SIGNAL_LAYER_FROM, - m_board->GetLayerName( aViaOverrideEntry.m_SignalLayerFrom ) ); - m_viaPropagationGrid->SetCellValue( rowId, VIA_GRID_SIGNAL_LAYER_TO, - m_board->GetLayerName( aViaOverrideEntry.m_SignalLayerTo ) ); - m_viaPropagationGrid->SetCellValue( rowId, VIA_GRID_VIA_LAYER_FROM, - m_board->GetLayerName( aViaOverrideEntry.m_ViaLayerFrom ) ); - m_viaPropagationGrid->SetCellValue( rowId, VIA_GRID_VIA_LAYER_TO, - m_board->GetLayerName( aViaOverrideEntry.m_ViaLayerTo ) ); - m_viaPropagationGrid->SetUnitValue( rowId, VIA_GRID_DELAY, aViaOverrideEntry.m_Delay ); -} - - -DELAY_PROFILE_VIA_OVERRIDE_ENTRY PANEL_SETUP_TIME_DOMAIN_PARAMETERS::getViaRow( const int aRow ) -{ - // Get layer info - const wxString signalLayerFrom = m_viaPropagationGrid->GetCellValue( aRow, VIA_GRID_SIGNAL_LAYER_FROM ); - const wxString signalLayerTo = m_viaPropagationGrid->GetCellValue( aRow, VIA_GRID_SIGNAL_LAYER_TO ); - const wxString viaLayerFrom = m_viaPropagationGrid->GetCellValue( aRow, VIA_GRID_VIA_LAYER_FROM ); - const wxString viaLayerTo = m_viaPropagationGrid->GetCellValue( aRow, VIA_GRID_VIA_LAYER_TO ); - PCB_LAYER_ID signalLayerIdFrom = m_layerNamesToIDs[signalLayerFrom]; - PCB_LAYER_ID signalLayerIdTo = m_layerNamesToIDs[signalLayerTo]; - PCB_LAYER_ID viaLayerIdFrom = m_layerNamesToIDs[viaLayerFrom]; - PCB_LAYER_ID viaLayerIdTo = m_layerNamesToIDs[viaLayerTo]; - - // Order layers in stackup order (from F_Cu first) - if( IsCopperLayerLowerThan( signalLayerIdFrom, signalLayerIdTo ) ) - std::swap( signalLayerIdFrom, signalLayerIdTo ); - - if( IsCopperLayerLowerThan( viaLayerIdFrom, viaLayerIdTo ) ) - std::swap( viaLayerIdFrom, viaLayerIdTo ); - - const DELAY_PROFILE_VIA_OVERRIDE_ENTRY entry{ signalLayerIdFrom, signalLayerIdTo, viaLayerIdFrom, viaLayerIdTo, - m_viaPropagationGrid->GetUnitValue( aRow, VIA_GRID_DELAY ) }; - - return entry; -} - - -void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::SyncCopperLayers( int aNumCopperLayers ) -{ - m_prevLayerNamesToIDs = m_layerNamesToIDs; - m_copperLayerIdsToColumns.clear(); - m_copperColumnsToLayerId.clear(); - m_layerNames.clear(); - m_layerNamesToIDs.clear(); - - int colIdx = PROFILE_GRID_NUM_REQUIRED_COLS; - - for( const auto& layer : LSET::AllCuMask( aNumCopperLayers ).CuStack() ) - { - wxString layerName = m_board->GetLayerName( layer ); - m_layerNames.emplace_back( layerName ); - m_layerNamesToIDs[layerName] = layer; - m_copperLayerIdsToColumns[layer] = colIdx; - m_copperColumnsToLayerId[colIdx] = layer; - ++colIdx; - } - - updateProfileGridColumns(); - updateViaGridColumns(); - setColumnWidths(); -} - - -void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::setColumnWidths() -{ - const int minValueWidth = m_tracePropagationGrid->GetTextExtent( wxT( "000.00 ps/mm" ) ).x; - const int minNameWidth = m_tracePropagationGrid->GetTextExtent( wxT( "MMMMMMMMMMMM" ) ).x; - - for( int i = 0; i < m_tracePropagationGrid->GetNumberCols(); ++i ) - { - const int titleSize = m_tracePropagationGrid->GetTextExtent( m_tracePropagationGrid->GetColLabelValue( i ) ).x; - - if( i == PROFILE_GRID_PROFILE_NAME ) - m_tracePropagationGrid->SetColSize( i, std::max( titleSize, minNameWidth ) ); - else - m_tracePropagationGrid->SetColSize( i, std::max( titleSize, minValueWidth ) ); - } - - for( int i = 0; i < m_viaPropagationGrid->GetNumberCols(); ++i ) - { - const int titleSize = GetTextExtent( m_viaPropagationGrid->GetColLabelValue( i ) ).x; - if( i == VIA_GRID_PROFILE_NAME ) - m_viaPropagationGrid->SetColSize( i, std::max( titleSize, minNameWidth ) ); - else - m_viaPropagationGrid->SetColSize( i, titleSize + 30 ); - } -} - - -void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::updateProfileGridColumns() -{ - const int newCopperLayers = static_cast( m_copperLayerIdsToColumns.size() ); - const int curCopperLayers = m_tracePropagationGrid->GetNumberCols() - PROFILE_GRID_NUM_REQUIRED_COLS; - - if( newCopperLayers < curCopperLayers ) - { - // TODO: WARN OF DELETING DATA? - m_tracePropagationGrid->DeleteCols( curCopperLayers - newCopperLayers + PROFILE_GRID_NUM_REQUIRED_COLS, - curCopperLayers - newCopperLayers ); - } - else if( newCopperLayers > curCopperLayers ) - { - m_tracePropagationGrid->AppendCols( newCopperLayers - curCopperLayers ); - } - - std::vector copperColIds; - - m_tracePropagationGrid->SetAutoEvalColUnits( PROFILE_GRID_VIA_PROP_DELAY, - m_unitsProvider->GetUnitsFromType( EDA_DATA_TYPE::LENGTH_DELAY ) ); - copperColIds.push_back( PROFILE_GRID_VIA_PROP_DELAY ); - - for( const auto& [colIdx, layerId] : m_copperColumnsToLayerId ) - { - m_tracePropagationGrid->SetColLabelValue( colIdx, m_board->GetLayerName( layerId ) ); - m_tracePropagationGrid->SetAutoEvalColUnits( colIdx, - m_unitsProvider->GetUnitsFromType( EDA_DATA_TYPE::LENGTH_DELAY ) ); - copperColIds.push_back( colIdx ); - } - - m_tracePropagationGrid->SetAutoEvalCols( copperColIds ); - - m_tracePropagationGrid->EnsureColLabelsVisible(); - m_tracePropagationGrid->Refresh(); -} - - -void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::updateViaGridColumns() -{ - wxArrayString layerNames; - std::ranges::for_each( m_layerNames, - [&layerNames]( const wxString& aLayerName ) - { - layerNames.push_back( aLayerName ); - } ); - - // Save the current data - std::vector currentSignalLayersFrom; - std::vector currentSignalLayersTo; - std::vector currentViaLayersFrom; - std::vector currentViaLayersTo; - - for( int row = 0; row < m_viaPropagationGrid->GetNumberRows(); ++row ) - { - currentSignalLayersFrom.emplace_back( m_viaPropagationGrid->GetCellValue( row, VIA_GRID_SIGNAL_LAYER_FROM ) ); - currentSignalLayersTo.emplace_back( m_viaPropagationGrid->GetCellValue( row, VIA_GRID_SIGNAL_LAYER_TO ) ); - currentViaLayersFrom.emplace_back( m_viaPropagationGrid->GetCellValue( row, VIA_GRID_VIA_LAYER_FROM ) ); - currentViaLayersTo.emplace_back( m_viaPropagationGrid->GetCellValue( row, VIA_GRID_VIA_LAYER_TO ) ); - } - - // Reset the via layers lists - wxGridCellAttr* attr = new wxGridCellAttr; - attr->SetEditor( new wxGridCellChoiceEditor( layerNames, false ) ); - m_viaPropagationGrid->SetColAttr( VIA_GRID_SIGNAL_LAYER_FROM, attr ); - - attr = new wxGridCellAttr; - attr->SetEditor( new wxGridCellChoiceEditor( layerNames, false ) ); - m_viaPropagationGrid->SetColAttr( VIA_GRID_SIGNAL_LAYER_TO, attr ); - - attr = new wxGridCellAttr; - attr->SetEditor( new wxGridCellChoiceEditor( layerNames, false ) ); - m_viaPropagationGrid->SetColAttr( VIA_GRID_VIA_LAYER_FROM, attr ); - - attr = new wxGridCellAttr; - attr->SetEditor( new wxGridCellChoiceEditor( layerNames, false ) ); - m_viaPropagationGrid->SetColAttr( VIA_GRID_VIA_LAYER_TO, attr ); - - // Restore the data, changing or resetting layer names if required - for( int row = 0; row < m_viaPropagationGrid->GetNumberRows(); ++row ) - { - const PCB_LAYER_ID lastSignalFromId = m_prevLayerNamesToIDs[currentSignalLayersFrom[row]]; - - if( m_copperLayerIdsToColumns.contains( lastSignalFromId ) ) - m_viaPropagationGrid->SetCellValue( row, VIA_GRID_SIGNAL_LAYER_FROM, - m_board->GetLayerName( lastSignalFromId ) ); - else - m_viaPropagationGrid->SetCellValue( row, VIA_GRID_SIGNAL_LAYER_FROM, m_layerNames.front() ); - - const PCB_LAYER_ID lastSignalToId = m_prevLayerNamesToIDs[currentSignalLayersTo[row]]; - - if( m_copperLayerIdsToColumns.contains( lastSignalToId ) ) - m_viaPropagationGrid->SetCellValue( row, VIA_GRID_SIGNAL_LAYER_TO, - m_board->GetLayerName( lastSignalToId ) ); - else - m_viaPropagationGrid->SetCellValue( row, VIA_GRID_SIGNAL_LAYER_TO, m_layerNames.back() ); - - const PCB_LAYER_ID lastViaFromId = m_prevLayerNamesToIDs[currentViaLayersFrom[row]]; - - if( m_copperLayerIdsToColumns.contains( lastViaFromId ) ) - m_viaPropagationGrid->SetCellValue( row, VIA_GRID_VIA_LAYER_FROM, m_board->GetLayerName( lastViaFromId ) ); - else - m_viaPropagationGrid->SetCellValue( row, VIA_GRID_VIA_LAYER_FROM, m_layerNames.front() ); - - const PCB_LAYER_ID lastViaToId = m_prevLayerNamesToIDs[currentViaLayersTo[row]]; - - if( m_copperLayerIdsToColumns.contains( lastViaToId ) ) - m_viaPropagationGrid->SetCellValue( row, VIA_GRID_VIA_LAYER_TO, m_board->GetLayerName( lastViaToId ) ); - else - m_viaPropagationGrid->SetCellValue( row, VIA_GRID_VIA_LAYER_TO, m_layerNames.back() ); - } -} - - -void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::OnAddDelayProfileClick( wxCommandEvent& event ) -{ - m_tracePropagationGrid->OnAddRow( - [&]() -> std::pair - { - const int row = m_tracePropagationGrid->GetNumberRows(); - m_tracePropagationGrid->AppendRows(); - m_tracePropagationGrid->SetCellValue( row, PROFILE_GRID_PROFILE_NAME, "" ); - - for( int i = PROFILE_GRID_VIA_PROP_DELAY; i < m_tracePropagationGrid->GetNumberCols(); ++i ) - m_tracePropagationGrid->SetUnitValue( row, i, 0 ); - - return { row, PROFILE_GRID_PROFILE_NAME }; - } ); -} - - -void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::OnRemoveDelayProfileClick( wxCommandEvent& event ) -{ - m_tracePropagationGrid->OnDeleteRows( - [&]( int row ) - { - wxString profileName = getProfileNameForProfileGridRow( row ); - - // Delete associated via overrides - for( int viaRow = m_viaPropagationGrid->GetNumberRows() - 1; viaRow >= 0; --viaRow ) - { - if( m_viaPropagationGrid->GetCellValue( viaRow, VIA_GRID_PROFILE_NAME ) == profileName ) - m_viaPropagationGrid->DeleteRows( viaRow, 1 ); - } - - // Delete tuning profile - m_tracePropagationGrid->DeleteRows( row, 1 ); - - updateViaProfileNamesEditor(); - } ); -} - - -void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::OnAddViaOverrideClick( wxCommandEvent& event ) -{ - m_viaPropagationGrid->OnAddRow( - [&]() -> std::pair - { - const int row = m_viaPropagationGrid->GetNumberRows(); - - // Check we have delay profiles to override - if( m_tracePropagationGrid->GetNumberRows() == 0 ) - { - PAGED_DIALOG::GetDialog( this )->SetError( _( "No delay profiles to override" ), this, nullptr ); - return { row, -1 }; - } - - m_viaPropagationGrid->AppendRows(); - m_viaPropagationGrid->SetCellValue( row, VIA_GRID_PROFILE_NAME, getProfileNameForProfileGridRow( 0 ) ); - m_viaPropagationGrid->SetCellValue( row, VIA_GRID_SIGNAL_LAYER_FROM, m_layerNames.front() ); - m_viaPropagationGrid->SetCellValue( row, VIA_GRID_SIGNAL_LAYER_TO, m_layerNames.back() ); - m_viaPropagationGrid->SetCellValue( row, VIA_GRID_VIA_LAYER_FROM, m_layerNames.front() ); - m_viaPropagationGrid->SetCellValue( row, VIA_GRID_VIA_LAYER_TO, m_layerNames.back() ); - m_viaPropagationGrid->SetUnitValue( row, VIA_GRID_DELAY, 0 ); - - return { row, VIA_GRID_DELAY }; - } ); -} - - -void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::OnRemoveViaOverrideClick( wxCommandEvent& event ) -{ - m_viaPropagationGrid->OnDeleteRows( - [&]( int row ) - { - m_viaPropagationGrid->DeleteRows( row, 1 ); - } ); -} - - -void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::OnDelayProfileGridCellChanging( wxGridEvent& event ) -{ - if( event.GetCol() == PROFILE_GRID_PROFILE_NAME ) - { - if( validateDelayProfileName( event.GetRow(), event.GetString() ) ) - { - const wxString oldName = getProfileNameForProfileGridRow( event.GetRow() ); - wxString newName = event.GetString(); - newName.Trim( true ).Trim( false ); - - if( !oldName.IsEmpty() ) - { - wxWindowUpdateLocker updateLocker( m_viaPropagationGrid ); - - updateViaProfileNamesEditor( oldName, newName ); - - // Update changed profile names - for( int row = 0; row < m_viaPropagationGrid->GetNumberRows(); ++row ) - { - if( m_viaPropagationGrid->GetCellValue( row, VIA_GRID_PROFILE_NAME ) == oldName ) - m_viaPropagationGrid->SetCellValue( row, VIA_GRID_PROFILE_NAME, newName ); - } - } - else - { - updateViaProfileNamesEditor( oldName, newName ); - } - } - else - { - event.Veto(); - } - } -} - - -void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::updateViaProfileNamesEditor( const wxString& aOldName, - const wxString& aNewName ) const -{ - wxArrayString profileNames; - - for( int i = 0; i < m_tracePropagationGrid->GetNumberRows(); ++i ) - { - wxString profileName = getProfileNameForProfileGridRow( i ); - - if( profileName == aOldName ) - profileName = aNewName; - - profileNames.push_back( profileName ); - } - - std::ranges::sort( profileNames, - []( const wxString& a, const wxString& b ) - { - return a.CmpNoCase( b ) < 0; - } ); - - wxGridCellAttr* attr = new wxGridCellAttr; - attr->SetEditor( new wxGridCellChoiceEditor( profileNames, false ) ); - m_viaPropagationGrid->SetColAttr( VIA_GRID_PROFILE_NAME, attr ); -} - - -bool PANEL_SETUP_TIME_DOMAIN_PARAMETERS::validateDelayProfileName( int aRow, const wxString& aName, bool focusFirst ) -{ - wxString tmp = aName; - tmp.Trim( true ); - tmp.Trim( false ); - - if( tmp.IsEmpty() ) - { - const wxString msg = _( "Tuning profile must have a name" ); - PAGED_DIALOG::GetDialog( this )->SetError( msg, this, m_tracePropagationGrid, aRow, PROFILE_GRID_PROFILE_NAME ); - return false; - } - - for( int ii = 0; ii < m_tracePropagationGrid->GetNumberRows(); ii++ ) - { - if( ii != aRow && getProfileNameForProfileGridRow( ii ).CmpNoCase( tmp ) == 0 ) - { - const wxString msg = _( "Tuning profile name already in use" ); - PAGED_DIALOG::GetDialog( this )->SetError( msg, this, m_tracePropagationGrid, focusFirst ? aRow : ii, - PROFILE_GRID_PROFILE_NAME ); - return false; - } - } - - return true; -} - - -bool PANEL_SETUP_TIME_DOMAIN_PARAMETERS::Validate() -{ - if( !m_tracePropagationGrid->CommitPendingChanges() || !m_viaPropagationGrid->CommitPendingChanges() ) - return false; - - // Test delay profile parameters - for( int row = 0; row < m_tracePropagationGrid->GetNumberRows(); row++ ) - { - const wxString profileName = getProfileNameForProfileGridRow( row ); - - if( !validateDelayProfileName( row, profileName, false ) ) - return false; - } - - // Test via override parameters - if( !validateViaRows() ) - return false; - - return true; -} - - -bool PANEL_SETUP_TIME_DOMAIN_PARAMETERS::validateViaRows() -{ - std::map> rowCache; - - for( int row = 0; row < m_viaPropagationGrid->GetNumberRows(); row++ ) - { - DELAY_PROFILE_VIA_OVERRIDE_ENTRY entry = getViaRow( row ); - const wxString profileName = m_viaPropagationGrid->GetCellValue( row, VIA_GRID_PROFILE_NAME ); - std::set& viaOverrides = rowCache[profileName]; - - if( viaOverrides.contains( entry ) ) - { - const wxString msg = _( "Via override configuration is duplicated" ); - PAGED_DIALOG::GetDialog( this )->SetError( msg, this, m_viaPropagationGrid, row, VIA_GRID_PROFILE_NAME ); - return false; - } - else - { - viaOverrides.insert( entry ); - } - } - - return true; -} - - -std::vector PANEL_SETUP_TIME_DOMAIN_PARAMETERS::GetDelayProfileNames() const -{ - std::vector profileNames; - - for( int i = 0; i < m_tracePropagationGrid->GetNumberRows(); i++ ) - { - const wxString profileName = getProfileNameForProfileGridRow( i ); - profileNames.emplace_back( profileName ); - } - - std::ranges::sort( profileNames, - []( const wxString& a, const wxString& b ) - { - return a.CmpNoCase( b ) < 0; - } ); - - return profileNames; -} - - -void PANEL_SETUP_TIME_DOMAIN_PARAMETERS::ImportSettingsFrom( - const std::shared_ptr& aOtherParameters ) -{ - std::shared_ptr savedParameters = m_timeDomainParameters; - - m_timeDomainParameters = aOtherParameters; - TransferDataToWindow(); - - updateViaProfileNamesEditor(); - - m_viaPropagationGrid->ForceRefresh(); - - m_timeDomainParameters = std::move( savedParameters ); -} - - -wxString PANEL_SETUP_TIME_DOMAIN_PARAMETERS::getProfileNameForProfileGridRow( const int aRow ) const -{ - wxString profileName = m_tracePropagationGrid->GetCellValue( aRow, PROFILE_GRID_PROFILE_NAME ); - profileName.Trim( true ).Trim( false ); - return profileName; -} \ No newline at end of file diff --git a/pcbnew/dialogs/panel_setup_time_domain_parameters.h b/pcbnew/dialogs/panel_setup_time_domain_parameters.h deleted file mode 100644 index 90e310319c..0000000000 --- a/pcbnew/dialogs/panel_setup_time_domain_parameters.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright The KiCad Developers, see AUTHORS.txt for contributors. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - - -#ifndef PANEL_SETUP_TIME_DOMAIN_PARAMETERS_H -#define PANEL_SETUP_TIME_DOMAIN_PARAMETERS_H - -#include - -#include -#include -#include - -class NET_SETTINGS; - - -class PANEL_SETUP_TIME_DOMAIN_PARAMETERS : public PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE -{ -public: - PANEL_SETUP_TIME_DOMAIN_PARAMETERS( - wxWindow* aParentWindow, PCB_EDIT_FRAME* aFrame, BOARD* aBoard, - std::shared_ptr aTimeDomainParameters ); - ~PANEL_SETUP_TIME_DOMAIN_PARAMETERS() override; - - /** - * Called when switching to this tab to make sure that any changes to the copper layer count - * made on the physical stackup page are reflected here - * @param aNumCopperLayers is the number of copper layers in the board - */ - void SyncCopperLayers( int aNumCopperLayers ); - - /// Load parameter data from the settings object - bool TransferDataToWindow() override; - - /// Save parameter data to the settings object - bool TransferDataFromWindow() override; - - /// Returns all configured tuning profile names. Used by the netclass setup panel - std::vector GetDelayProfileNames() const; - - /// Load configuration from the given settings object - void ImportSettingsFrom( const std::shared_ptr& aOtherParameters ); - -private: - enum PROFILE_GRID_REQUIRED_COLS - { - PROFILE_GRID_PROFILE_NAME = 0, - PROFILE_GRID_VIA_PROP_DELAY, - PROFILE_GRID_NUM_REQUIRED_COLS - }; - - enum VIA_GRID_REQUIRED_COLS - { - VIA_GRID_PROFILE_NAME = 0, - VIA_GRID_SIGNAL_LAYER_FROM, - VIA_GRID_SIGNAL_LAYER_TO, - VIA_GRID_VIA_LAYER_FROM, - VIA_GRID_VIA_LAYER_TO, - VIA_GRID_DELAY - }; - - /// Optimise grid columns to fit titles and content - void setColumnWidths(); - - /// Updates the via override tuning profile name dropdown lists - /// Updates entries if aOldName and aNewName are passed - void updateViaProfileNamesEditor( const wxString& aOldName = wxEmptyString, - const wxString& aNewName = wxEmptyString ) const; - - /// Update the dynamic (per-layer) columns in the tuning profiles grid - void updateProfileGridColumns(); - - /// Update the dynamic (per-layer) columns in the via overrides grid - void updateViaGridColumns(); - - /// Adds a new tuning profile entry to the tuning profile grid - void OnAddDelayProfileClick( wxCommandEvent& event ) override; - - /// Removes a tuning profile entry from the tuning profile grid - void OnRemoveDelayProfileClick( wxCommandEvent& event ) override; - - /// Adds a new via override profile entry to the via overrides grid - void OnAddViaOverrideClick( wxCommandEvent& event ) override; - - /// Removes a via override profile entry from the via overrides grid - void OnRemoveViaOverrideClick( wxCommandEvent& event ) override; - - /// Validates a tuning profile row data - void OnDelayProfileGridCellChanging( wxGridEvent& event ); - - /// Validates a tuning profile name (checks for not empty and not duplicated) - bool validateDelayProfileName( int aRow, const wxString& aName, bool focusFirst = true ); - - /// Validates all data - bool Validate() override; - - /// Validates all via override rows - bool validateViaRows(); - - /// Adds a tuning profile row with the given persisted parameters - void addProfileRow( const DELAY_PROFILE& aDelayProfile ); - - /// Gets a tuning profile row as a set of persistable parameters - DELAY_PROFILE getProfileRow( int aRow ); - - /// Adds a via override row with the given persisted parameters - void addViaRow( const wxString& aProfileName, const DELAY_PROFILE_VIA_OVERRIDE_ENTRY& aViaOverrideEntry ) const; - - /// Gets a via override row as a set of persistable parameters - DELAY_PROFILE_VIA_OVERRIDE_ENTRY getViaRow( int aRow ); - - /// Gets the profile name for the given profile grid row - wxString getProfileNameForProfileGridRow( int aRow ) const; - - /// The parameters object to load / save data from / to - std::shared_ptr m_timeDomainParameters; - - /// The active edit frame - PCB_EDIT_FRAME* m_frame; - - /// The current board - BOARD* m_board; - - std::unique_ptr m_unitsProvider; - - // Layer / column lookups - std::map m_copperLayerIdsToColumns; - std::map m_copperColumnsToLayerId; - std::vector m_layerNames; - - // We cache these in case the names change on the layers panel - std::map m_layerNamesToIDs; - std::map m_prevLayerNamesToIDs; -}; - -#endif // PANEL_SETUP_TIME_DOMAIN_PARAMETERS_H diff --git a/pcbnew/dialogs/panel_setup_time_domain_parameters_base.cpp b/pcbnew/dialogs/panel_setup_time_domain_parameters_base.cpp deleted file mode 100644 index 8f25c84950..0000000000 --- a/pcbnew/dialogs/panel_setup_time_domain_parameters_base.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6) -// http://www.wxformbuilder.org/ -// -// PLEASE DO *NOT* EDIT THIS FILE! -/////////////////////////////////////////////////////////////////////////// - -#include "widgets/std_bitmap_button.h" -#include "widgets/wx_grid.h" -#include "widgets/wx_panel.h" - -#include "panel_setup_time_domain_parameters_base.h" - -/////////////////////////////////////////////////////////////////////////// - -PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name ) -{ - wxBoxSizer* bpanelTomeDomainSizer; - bpanelTomeDomainSizer = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bMargins; - bMargins = new wxBoxSizer( wxVERTICAL ); - - m_splitter = new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_3DSASH|wxSP_LIVE_UPDATE|wxSP_NO_XP_THEME ); - m_splitter->SetMinimumPaneSize( 160 ); - - m_timeDomainParametersPane = new WX_PANEL( m_splitter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bUpperSizer; - bUpperSizer = new wxBoxSizer( wxVERTICAL ); - - m_staticText3 = new wxStaticText( m_timeDomainParametersPane, wxID_ANY, _("Delay Profiles"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText3->Wrap( -1 ); - bUpperSizer->Add( m_staticText3, 0, wxTOP|wxLEFT|wxEXPAND, 8 ); - - - bUpperSizer->Add( 0, 3, 0, wxEXPAND, 5 ); - - m_tracePropagationGrid = new WX_GRID( m_timeDomainParametersPane, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxTAB_TRAVERSAL|wxVSCROLL ); - - // Grid - m_tracePropagationGrid->CreateGrid( 0, 2 ); - m_tracePropagationGrid->EnableEditing( true ); - m_tracePropagationGrid->EnableGridLines( true ); - m_tracePropagationGrid->EnableDragGridSize( false ); - m_tracePropagationGrid->SetMargins( 0, 0 ); - - // Columns - m_tracePropagationGrid->EnableDragColMove( false ); - m_tracePropagationGrid->EnableDragColSize( true ); - m_tracePropagationGrid->SetColLabelValue( 0, _("Profile Name") ); - m_tracePropagationGrid->SetColLabelValue( 1, _("Vias") ); - m_tracePropagationGrid->SetColLabelSize( wxGRID_AUTOSIZE ); - m_tracePropagationGrid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); - - // Rows - m_tracePropagationGrid->EnableDragRowSize( true ); - m_tracePropagationGrid->SetRowLabelSize( 0 ); - m_tracePropagationGrid->SetRowLabelAlignment( wxALIGN_LEFT, wxALIGN_CENTER ); - - // Label Appearance - - // Cell Defaults - m_tracePropagationGrid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_CENTER ); - bUpperSizer->Add( m_tracePropagationGrid, 1, wxEXPAND|wxFIXED_MINSIZE|wxRIGHT|wxLEFT, 5 ); - - wxBoxSizer* buttonBoxSizer; - buttonBoxSizer = new wxBoxSizer( wxHORIZONTAL ); - - m_addDelayProfileButton = new STD_BITMAP_BUTTON( m_timeDomainParametersPane, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - buttonBoxSizer->Add( m_addDelayProfileButton, 0, wxBOTTOM|wxLEFT, 5 ); - - - buttonBoxSizer->Add( 20, 0, 0, wxEXPAND, 5 ); - - m_removeDelayProfileButton = new STD_BITMAP_BUTTON( m_timeDomainParametersPane, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - buttonBoxSizer->Add( m_removeDelayProfileButton, 0, wxBOTTOM|wxLEFT, 5 ); - - - buttonBoxSizer->Add( 20, 0, 0, wxEXPAND, 5 ); - - - bUpperSizer->Add( buttonBoxSizer, 0, wxEXPAND|wxTOP, 3 ); - - - m_timeDomainParametersPane->SetSizer( bUpperSizer ); - m_timeDomainParametersPane->Layout(); - bUpperSizer->Fit( m_timeDomainParametersPane ); - m_viaDelayOverridesPane = new WX_PANEL( m_splitter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bUpperSizer1; - bUpperSizer1 = new wxBoxSizer( wxVERTICAL ); - - m_staticText31 = new wxStaticText( m_viaDelayOverridesPane, wxID_ANY, _("Via Delay Overrides"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText31->Wrap( -1 ); - bUpperSizer1->Add( m_staticText31, 0, wxTOP|wxLEFT|wxEXPAND, 8 ); - - - bUpperSizer1->Add( 0, 3, 0, wxEXPAND, 5 ); - - m_viaPropagationGrid = new WX_GRID( m_viaDelayOverridesPane, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxTAB_TRAVERSAL|wxVSCROLL ); - - // Grid - m_viaPropagationGrid->CreateGrid( 0, 6 ); - m_viaPropagationGrid->EnableEditing( true ); - m_viaPropagationGrid->EnableGridLines( true ); - m_viaPropagationGrid->EnableDragGridSize( false ); - m_viaPropagationGrid->SetMargins( 0, 0 ); - - // Columns - m_viaPropagationGrid->EnableDragColMove( false ); - m_viaPropagationGrid->EnableDragColSize( true ); - m_viaPropagationGrid->SetColLabelValue( 0, _("Profile Name") ); - m_viaPropagationGrid->SetColLabelValue( 1, _("Signal Layer From") ); - m_viaPropagationGrid->SetColLabelValue( 2, _("Signal Layer To") ); - m_viaPropagationGrid->SetColLabelValue( 3, _("Via Layer From") ); - m_viaPropagationGrid->SetColLabelValue( 4, _("Via Layer To") ); - m_viaPropagationGrid->SetColLabelValue( 5, _("Delay") ); - m_viaPropagationGrid->SetColLabelSize( wxGRID_AUTOSIZE ); - m_viaPropagationGrid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); - - // Rows - m_viaPropagationGrid->EnableDragRowSize( true ); - m_viaPropagationGrid->SetRowLabelSize( 0 ); - m_viaPropagationGrid->SetRowLabelAlignment( wxALIGN_LEFT, wxALIGN_CENTER ); - - // Label Appearance - - // Cell Defaults - m_viaPropagationGrid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_CENTER ); - bUpperSizer1->Add( m_viaPropagationGrid, 1, wxEXPAND|wxFIXED_MINSIZE|wxRIGHT|wxLEFT, 5 ); - - wxBoxSizer* buttonBoxSizer1; - buttonBoxSizer1 = new wxBoxSizer( wxHORIZONTAL ); - - m_addViaOverrideButton = new STD_BITMAP_BUTTON( m_viaDelayOverridesPane, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - buttonBoxSizer1->Add( m_addViaOverrideButton, 0, wxBOTTOM|wxLEFT, 5 ); - - - buttonBoxSizer1->Add( 20, 0, 0, wxEXPAND, 5 ); - - m_removeViaOverrideButton = new STD_BITMAP_BUTTON( m_viaDelayOverridesPane, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); - buttonBoxSizer1->Add( m_removeViaOverrideButton, 0, wxBOTTOM|wxLEFT, 5 ); - - - buttonBoxSizer1->Add( 20, 0, 0, wxEXPAND, 5 ); - - - bUpperSizer1->Add( buttonBoxSizer1, 0, wxEXPAND|wxTOP, 3 ); - - - m_viaDelayOverridesPane->SetSizer( bUpperSizer1 ); - m_viaDelayOverridesPane->Layout(); - bUpperSizer1->Fit( m_viaDelayOverridesPane ); - m_splitter->SplitHorizontally( m_timeDomainParametersPane, m_viaDelayOverridesPane, -1 ); - bMargins->Add( m_splitter, 1, wxEXPAND, 10 ); - - - bpanelTomeDomainSizer->Add( bMargins, 1, wxEXPAND|wxTOP, 2 ); - - - this->SetSizer( bpanelTomeDomainSizer ); - this->Layout(); - bpanelTomeDomainSizer->Fit( this ); - - // Connect Events - this->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnUpdateUI ) ); - m_tracePropagationGrid->Connect( wxEVT_SIZE, wxSizeEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnSizeTraceParametersGrid ), NULL, this ); - m_addDelayProfileButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnAddDelayProfileClick ), NULL, this ); - m_removeDelayProfileButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnRemoveDelayProfileClick ), NULL, this ); - m_viaPropagationGrid->Connect( wxEVT_SIZE, wxSizeEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnSizeTraceParametersGrid ), NULL, this ); - m_addViaOverrideButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnAddViaOverrideClick ), NULL, this ); - m_removeViaOverrideButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnRemoveViaOverrideClick ), NULL, this ); -} - -PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::~PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE() -{ - // Disconnect Events - this->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnUpdateUI ) ); - m_tracePropagationGrid->Disconnect( wxEVT_SIZE, wxSizeEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnSizeTraceParametersGrid ), NULL, this ); - m_addDelayProfileButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnAddDelayProfileClick ), NULL, this ); - m_removeDelayProfileButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnRemoveDelayProfileClick ), NULL, this ); - m_viaPropagationGrid->Disconnect( wxEVT_SIZE, wxSizeEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnSizeTraceParametersGrid ), NULL, this ); - m_addViaOverrideButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnAddViaOverrideClick ), NULL, this ); - m_removeViaOverrideButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE::OnRemoveViaOverrideClick ), NULL, this ); - -} diff --git a/pcbnew/dialogs/panel_setup_time_domain_parameters_base.fbp b/pcbnew/dialogs/panel_setup_time_domain_parameters_base.fbp deleted file mode 100644 index 07e4e39826..0000000000 --- a/pcbnew/dialogs/panel_setup_time_domain_parameters_base.fbp +++ /dev/null @@ -1,950 +0,0 @@ - - - - - C++ - - 1 - connect - none - - - 0 - 1 - res - UTF-8 - panel_setup_time_domain_parameters_base - 1000 - 1 - 1 - UI - panel_setup_time_domain_parameters_base - . - 0 - source_name - 1 - 0 - source_name - - - 1 - 1 - 0 - 0 - - 0 - wxAUI_MGR_DEFAULT - - - 1 - 0 - 1 - impl_virtual - - - 0 - wxID_ANY - - -1,-1 - PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE - - -1,-1 - ; forward_declare - - 0 - - - wxTAB_TRAVERSAL - OnUpdateUI - - - bpanelTomeDomainSizer - wxVERTICAL - none - - 2 - wxEXPAND|wxTOP - 1 - - - bMargins - wxVERTICAL - none - - 10 - wxEXPAND - 1 - - 1 - 1 - 1 - 1 - 0 - - 0 - 0 - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 0 - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - 160 - - 0 - - 1 - m_splitter - 1 - - - protected - 1 - - Resizable - 0.0 - -1 - -1 - 1 - - wxSPLIT_HORIZONTAL - wxSP_3DSASH|wxSP_LIVE_UPDATE|wxSP_NO_XP_THEME - ; ; forward_declare - 0 - - - - - - - 1 - 1 - 1 - 1 - 0 - - 0 - 0 - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 0 - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - - 1 - m_timeDomainParametersPane - 1 - - - protected - 1 - - Resizable - 1 - - WX_PANEL; widgets/wx_panel.h; forward_declare - 0 - - - - wxTAB_TRAVERSAL - - - bUpperSizer - wxVERTICAL - none - - 8 - wxTOP|wxLEFT|wxEXPAND - 0 - - 1 - 1 - 1 - 1 - 0 - - 0 - 0 - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 0 - 1 - - 1 - - 0 - 0 - wxID_ANY - Delay Profiles - 0 - - 0 - - - 0 - - 1 - m_staticText3 - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - - - -1 - - - - 5 - wxEXPAND - 0 - - 3 - protected - 0 - - - - 5 - wxEXPAND|wxFIXED_MINSIZE|wxRIGHT|wxLEFT - 1 - - 1 - 1 - 1 - 1 - 0 - - 0 - 0 - 0 - 0 - - - - 1 - - - wxALIGN_LEFT - - wxALIGN_CENTER - 0 - 1 - wxALIGN_CENTER - wxGRID_AUTOSIZE - "Profile Name" "Vias" - wxALIGN_CENTER - 2 - - - 1 - 0 - Dock - 0 - Left - 0 - 0 - 1 - 0 - 1 - 1 - 1 - - 1 - - - 1 - 0 - 0 - wxID_ANY - - - - 0 - 0 - - 0 - - - 0 - -1,-1 - 1 - m_tracePropagationGrid - 1 - - - protected - 1 - - Resizable - wxALIGN_LEFT - 0 - - wxALIGN_CENTER - - 0 - 1 - - WX_GRID; widgets/wx_grid.h; forward_declare - 0 - - - - wxHSCROLL|wxTAB_TRAVERSAL|wxVSCROLL - OnSizeTraceParametersGrid - - - - 3 - wxEXPAND|wxTOP - 0 - - - buttonBoxSizer - wxHORIZONTAL - none - - 5 - wxBOTTOM|wxLEFT - 0 - - 1 - 1 - 1 - 1 - 0 - - 0 - 0 - 0 - - - - - 1 - 0 - 1 - - 1 - - 0 - 0 - - Dock - 0 - Left - 0 - 1 - - 1 - - - 0 - 0 - wxID_ANY - Add Parameter - - 0 - - 0 - - - 0 - -1,-1 - 1 - m_addDelayProfileButton - 1 - - - protected - 1 - - - - Resizable - 1 - -1,-1 - - STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - OnAddDelayProfileClick - - - - 5 - wxEXPAND - 0 - - 0 - protected - 20 - - - - 5 - wxBOTTOM|wxLEFT - 0 - - 1 - 1 - 1 - 1 - 0 - - 0 - 0 - 0 - - - - - 1 - 0 - 1 - - 1 - - 0 - 0 - - Dock - 0 - Left - 0 - 1 - - 1 - - - 0 - 0 - wxID_ANY - Delete Parameter - - 0 - - 0 - - - 0 - -1,-1 - 1 - m_removeDelayProfileButton - 1 - - - protected - 1 - - - - Resizable - 1 - -1,-1 - - STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - OnRemoveDelayProfileClick - - - - 5 - wxEXPAND - 0 - - 0 - protected - 20 - - - - - - - - - - 1 - 1 - 1 - 1 - 0 - - 0 - 0 - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 0 - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - - 1 - m_viaDelayOverridesPane - 1 - - - protected - 1 - - Resizable - 1 - - WX_PANEL; widgets/wx_panel.h; forward_declare - 0 - - - - wxTAB_TRAVERSAL - - - bUpperSizer1 - wxVERTICAL - none - - 8 - wxTOP|wxLEFT|wxEXPAND - 0 - - 1 - 1 - 1 - 1 - 0 - - 0 - 0 - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 0 - 1 - - 1 - - 0 - 0 - wxID_ANY - Via Delay Overrides - 0 - - 0 - - - 0 - - 1 - m_staticText31 - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - - - -1 - - - - 5 - wxEXPAND - 0 - - 3 - protected - 0 - - - - 5 - wxEXPAND|wxFIXED_MINSIZE|wxRIGHT|wxLEFT - 1 - - 1 - 1 - 1 - 1 - 0 - - 0 - 0 - 0 - 0 - - - - 1 - - - wxALIGN_LEFT - - wxALIGN_CENTER - 0 - 1 - wxALIGN_CENTER - wxGRID_AUTOSIZE - "Profile Name" "Signal Layer From" "Signal Layer To" "Via Layer From" "Via Layer To" "Delay" - wxALIGN_CENTER - 6 - - - 1 - 0 - Dock - 0 - Left - 0 - 0 - 1 - 0 - 1 - 1 - 1 - - 1 - - - 1 - 0 - 0 - wxID_ANY - - - - 0 - 0 - - 0 - - - 0 - -1,-1 - 1 - m_viaPropagationGrid - 1 - - - protected - 1 - - Resizable - wxALIGN_LEFT - 0 - - wxALIGN_CENTER - - 0 - 1 - - WX_GRID; widgets/wx_grid.h; forward_declare - 0 - - - - wxHSCROLL|wxTAB_TRAVERSAL|wxVSCROLL - OnSizeTraceParametersGrid - - - - 3 - wxEXPAND|wxTOP - 0 - - - buttonBoxSizer1 - wxHORIZONTAL - none - - 5 - wxBOTTOM|wxLEFT - 0 - - 1 - 1 - 1 - 1 - 0 - - 0 - 0 - 0 - - - - - 1 - 0 - 1 - - 1 - - 0 - 0 - - Dock - 0 - Left - 0 - 1 - - 1 - - - 0 - 0 - wxID_ANY - Add Parameter - - 0 - - 0 - - - 0 - -1,-1 - 1 - m_addViaOverrideButton - 1 - - - protected - 1 - - - - Resizable - 1 - -1,-1 - - STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - OnAddViaOverrideClick - - - - 5 - wxEXPAND - 0 - - 0 - protected - 20 - - - - 5 - wxBOTTOM|wxLEFT - 0 - - 1 - 1 - 1 - 1 - 0 - - 0 - 0 - 0 - - - - - 1 - 0 - 1 - - 1 - - 0 - 0 - - Dock - 0 - Left - 0 - 1 - - 1 - - - 0 - 0 - wxID_ANY - Delete Parameter - - 0 - - 0 - - - 0 - -1,-1 - 1 - m_removeViaOverrideButton - 1 - - - protected - 1 - - - - Resizable - 1 - -1,-1 - - STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - OnRemoveViaOverrideClick - - - - 5 - wxEXPAND - 0 - - 0 - protected - 20 - - - - - - - - - - - - - - - diff --git a/pcbnew/dialogs/panel_setup_time_domain_parameters_base.h b/pcbnew/dialogs/panel_setup_time_domain_parameters_base.h deleted file mode 100644 index b05d18c433..0000000000 --- a/pcbnew/dialogs/panel_setup_time_domain_parameters_base.h +++ /dev/null @@ -1,71 +0,0 @@ -/////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6) -// http://www.wxformbuilder.org/ -// -// PLEASE DO *NOT* EDIT THIS FILE! -/////////////////////////////////////////////////////////////////////////// - -#pragma once - -#include -#include -#include -class STD_BITMAP_BUTTON; -class WX_GRID; -class WX_PANEL; - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////// -/// Class PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE -/////////////////////////////////////////////////////////////////////////////// -class PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE : public wxPanel -{ - private: - - protected: - wxSplitterWindow* m_splitter; - WX_PANEL* m_timeDomainParametersPane; - wxStaticText* m_staticText3; - WX_GRID* m_tracePropagationGrid; - STD_BITMAP_BUTTON* m_addDelayProfileButton; - STD_BITMAP_BUTTON* m_removeDelayProfileButton; - WX_PANEL* m_viaDelayOverridesPane; - wxStaticText* m_staticText31; - WX_GRID* m_viaPropagationGrid; - STD_BITMAP_BUTTON* m_addViaOverrideButton; - STD_BITMAP_BUTTON* m_removeViaOverrideButton; - - // Virtual event handlers, override them in your derived class - virtual void OnUpdateUI( wxUpdateUIEvent& event ) { event.Skip(); } - virtual void OnSizeTraceParametersGrid( wxSizeEvent& event ) { event.Skip(); } - virtual void OnAddDelayProfileClick( wxCommandEvent& event ) { event.Skip(); } - virtual void OnRemoveDelayProfileClick( wxCommandEvent& event ) { event.Skip(); } - virtual void OnAddViaOverrideClick( wxCommandEvent& event ) { event.Skip(); } - virtual void OnRemoveViaOverrideClick( wxCommandEvent& event ) { event.Skip(); } - - - public: - - PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString ); - - ~PANEL_SETUP_TIME_DOMAIN_PARAMETERS_BASE(); - -}; - diff --git a/pcbnew/dialogs/panel_setup_tuning_profile_info.cpp b/pcbnew/dialogs/panel_setup_tuning_profile_info.cpp new file mode 100644 index 0000000000..77d46879e1 --- /dev/null +++ b/pcbnew/dialogs/panel_setup_tuning_profile_info.cpp @@ -0,0 +1,1398 @@ +/* +* This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright The KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +PANEL_SETUP_TUNING_PROFILE_INFO::PANEL_SETUP_TUNING_PROFILE_INFO( wxWindow* aParentWindow, + PANEL_SETUP_TUNING_PROFILES* parentPanel ) : + PANEL_SETUP_TUNING_PROFILE_INFO_BASE( aParentWindow ), + m_parentPanel( parentPanel ), + m_viaPropagationUnits( parentPanel->m_frame, m_viaPropagationSpeedLabel, m_viaPropagationSpeed, + m_viaPropSpeedUnits ) +{ + Freeze(); + initPanel(); + Thaw(); +} + + +void PANEL_SETUP_TUNING_PROFILE_INFO::initPanel() +{ + if( EDA_UNIT_UTILS::IsImperialUnit( m_parentPanel->m_unitsProvider->GetUserUnits() ) ) + m_viaPropagationUnits.SetUnits( EDA_UNITS::PS_PER_INCH ); + else + m_viaPropagationUnits.SetUnits( EDA_UNITS::PS_PER_CM ); + + m_viaPropagationUnits.SetValue( 0 ); + + m_addTrackPropogationLayer->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) ); + m_deleteTrackPropogationLayer->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) ); + + m_addViaPropagationOverride->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) ); + m_removeViaPropagationOverride->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) ); + + m_targetImpedance->SetValue( "0" ); + + UNITS_PROVIDER* unitsProvider = m_parentPanel->m_unitsProvider.get(); + + m_trackPropagationGrid->SetUnitsProvider( unitsProvider ); + m_viaOverrides->SetUnitsProvider( unitsProvider ); + + // Configure the track grid + m_trackPropagationGrid->BeginBatch(); + m_trackPropagationGrid->SetUseNativeColLabels(); + + m_trackPropagationGrid->EnsureColLabelsVisible(); + m_trackPropagationGrid->PushEventHandler( new GRID_TRICKS( m_trackPropagationGrid ) ); + m_trackPropagationGrid->SetSelectionMode( wxGrid::wxGridSelectRows ); + + std::vector trackColIds; + m_trackPropagationGrid->SetAutoEvalColUnits( TRACK_GRID_DELAY, + unitsProvider->GetUnitsFromType( EDA_DATA_TYPE::LENGTH_DELAY ) ); + trackColIds.push_back( TRACK_GRID_DELAY ); + m_trackPropagationGrid->SetAutoEvalColUnits( TRACK_GRID_TRACK_WIDTH, + unitsProvider->GetUnitsFromType( EDA_DATA_TYPE::DISTANCE ) ); + trackColIds.push_back( TRACK_GRID_TRACK_WIDTH ); + m_trackPropagationGrid->SetAutoEvalColUnits( TRACK_GRID_TRACK_GAP, + unitsProvider->GetUnitsFromType( EDA_DATA_TYPE::DISTANCE ) ); + trackColIds.push_back( TRACK_GRID_TRACK_GAP ); + m_trackPropagationGrid->SetAutoEvalCols( trackColIds ); + + // Add the calculation editors + wxGridCellAttr* attr = new wxGridCellAttr; + attr->SetEditor( new GRID_CELL_RUN_FUNCTION_EDITOR( + m_parentPanel->m_dlg, + [this]( int row, int col ) + { + calculateTrackParametersForCell( row, col ); + }, + false ) ); + m_trackPropagationGrid->SetColAttr( TRACK_GRID_TRACK_WIDTH, attr ); + + attr = new wxGridCellAttr; + attr->SetEditor( new GRID_CELL_RUN_FUNCTION_EDITOR( + m_parentPanel->m_dlg, + [this]( int row, int col ) + { + calculateTrackParametersForCell( row, col ); + }, + false ) ); + m_trackPropagationGrid->SetColAttr( TRACK_GRID_TRACK_GAP, attr ); + + attr = new wxGridCellAttr; + attr->SetEditor( new GRID_CELL_RUN_FUNCTION_EDITOR( + m_parentPanel->m_dlg, + [this]( int row, int col ) + { + calculateTrackParametersForCell( row, col ); + }, + false ) ); + m_trackPropagationGrid->SetColAttr( TRACK_GRID_DELAY, attr ); + + m_trackPropagationGrid->EndBatch(); + + // Configure the via grid + m_viaOverrides->BeginBatch(); + m_viaOverrides->SetUseNativeColLabels(); + + m_viaOverrides->EnsureColLabelsVisible(); + m_viaOverrides->PushEventHandler( new GRID_TRICKS( m_viaOverrides ) ); + m_viaOverrides->SetSelectionMode( wxGrid::wxGridSelectRows ); + + std::vector viaColIds; + m_viaOverrides->SetAutoEvalColUnits( VIA_GRID_DELAY, unitsProvider->GetUnitsFromType( EDA_DATA_TYPE::TIME ) ); + viaColIds.push_back( VIA_GRID_DELAY ); + m_viaOverrides->SetAutoEvalCols( viaColIds ); + m_viaOverrides->EndBatch(); + + setColumnWidths(); + + // Hide the trace gap as we start in single mode + m_trackPropagationGrid->HideCol( TRACK_GRID_TRACK_GAP ); + + UpdateLayerNames(); +} + + +void PANEL_SETUP_TUNING_PROFILE_INFO::LoadProfile( const TUNING_PROFILE& aProfile ) +{ + m_name->SetValue( aProfile.m_ProfileName ); + m_type->SetSelection( static_cast( aProfile.m_Type ) ); + onChangeProfileType( aProfile.m_Type ); + m_targetImpedance->SetValue( wxString::FromDouble( aProfile.m_TargetImpedance ) ); + m_enableDrcGeneration->SetValue( aProfile.m_GenerateNetClassDRCRules ); + m_enableDelayTuning->SetValue( aProfile.m_EnableTimeDomainTuning ); + m_viaPropagationUnits.SetValue( aProfile.m_ViaPropagationDelay ); + + for( const auto& entry : aProfile.m_TrackPropagationEntries ) + { + const int row = m_trackPropagationGrid->GetNumberRows(); + m_trackPropagationGrid->AppendRows(); + + m_trackPropagationGrid->SetCellValue( row, TRACK_GRID_SIGNAL_LAYER, + m_parentPanel->m_board->GetLayerName( entry.GetSignalLayer() ) ); + + if( entry.GetTopReferenceLayer() != UNDEFINED_LAYER ) + m_trackPropagationGrid->SetCellValue( + row, TRACK_GRID_TOP_REFERENCE, + m_parentPanel->m_board->GetLayerName( entry.GetTopReferenceLayer() ) ); + + if( entry.GetBottomReferenceLayer() != UNDEFINED_LAYER ) + m_trackPropagationGrid->SetCellValue( + row, TRACK_GRID_BOTTOM_REFERENCE, + m_parentPanel->m_board->GetLayerName( entry.GetBottomReferenceLayer() ) ); + + m_trackPropagationGrid->SetUnitValue( row, TRACK_GRID_TRACK_WIDTH, entry.GetWidth() ); + m_trackPropagationGrid->SetUnitValue( row, TRACK_GRID_TRACK_GAP, entry.GetDiffPairGap() ); + m_trackPropagationGrid->SetUnitValue( row, TRACK_GRID_DELAY, entry.GetDelay() ); + } + + for( const auto& entry : aProfile.m_ViaOverrides ) + { + const int row = m_viaOverrides->GetNumberRows(); + m_viaOverrides->AppendRows(); + + m_viaOverrides->SetCellValue( row, VIA_GRID_SIGNAL_LAYER_FROM, + m_parentPanel->m_board->GetLayerName( entry.m_SignalLayerFrom ) ); + m_viaOverrides->SetCellValue( row, VIA_GRID_SIGNAL_LAYER_TO, + m_parentPanel->m_board->GetLayerName( entry.m_SignalLayerTo ) ); + m_viaOverrides->SetCellValue( row, VIA_GRID_VIA_LAYER_FROM, + m_parentPanel->m_board->GetLayerName( entry.m_ViaLayerFrom ) ); + m_viaOverrides->SetCellValue( row, VIA_GRID_VIA_LAYER_TO, + m_parentPanel->m_board->GetLayerName( entry.m_ViaLayerTo ) ); + m_viaOverrides->SetUnitValue( row, VIA_GRID_DELAY, entry.m_Delay ); + } + + UpdateLayerNames(); +} + + +TUNING_PROFILE PANEL_SETUP_TUNING_PROFILE_INFO::GetProfile() const +{ + TUNING_PROFILE profile; + profile.m_ProfileName = m_name->GetValue(); + profile.m_Type = static_cast( m_type->GetSelection() ); + profile.m_GenerateNetClassDRCRules = m_enableDrcGeneration->GetValue(); + profile.m_EnableTimeDomainTuning = m_enableDelayTuning->GetValue(); + profile.m_ViaPropagationDelay = m_viaPropagationUnits.GetValue(); + + double targetImpedance; + + if( m_targetImpedance->GetValue().ToDouble( &targetImpedance ) ) + profile.m_TargetImpedance = targetImpedance; + else + profile.m_TargetImpedance = 0.0; + + for( int row = 0; row < m_trackPropagationGrid->GetNumberRows(); row++ ) + { + DELAY_PROFILE_TRACK_PROPAGATION_ENTRY entry; + + wxString signalLayerName = m_trackPropagationGrid->GetCellValue( row, TRACK_GRID_SIGNAL_LAYER ); + entry.SetSignalLayer( m_parentPanel->m_layerNamesToIDs[signalLayerName] ); + + if( wxString topReferenceLayerName = m_trackPropagationGrid->GetCellValue( row, TRACK_GRID_TOP_REFERENCE ); + m_parentPanel->m_layerNamesToIDs.contains( topReferenceLayerName ) ) + { + entry.SetTopReferenceLayer( m_parentPanel->m_layerNamesToIDs[topReferenceLayerName] ); + } + else + { + entry.SetTopReferenceLayer( UNDEFINED_LAYER ); + } + + if( wxString bottomReferenceLayerName = + m_trackPropagationGrid->GetCellValue( row, TRACK_GRID_BOTTOM_REFERENCE ); + m_parentPanel->m_layerNamesToIDs.contains( bottomReferenceLayerName ) ) + { + entry.SetBottomReferenceLayer( m_parentPanel->m_layerNamesToIDs[bottomReferenceLayerName] ); + } + else + { + entry.SetBottomReferenceLayer( UNDEFINED_LAYER ); + } + + entry.SetWidth( m_trackPropagationGrid->GetUnitValue( row, TRACK_GRID_TRACK_WIDTH ) ); + entry.SetDiffPairGap( m_trackPropagationGrid->GetUnitValue( row, TRACK_GRID_TRACK_GAP ) ); + entry.SetDelay( m_trackPropagationGrid->GetUnitValue( row, TRACK_GRID_DELAY ) ); + entry.SetEnableTimeDomainTuning( profile.m_EnableTimeDomainTuning ); + + profile.m_TrackPropagationEntries.push_back( entry ); + profile.m_TrackPropagationEntriesMap[entry.GetSignalLayer()] = entry; + } + + for( int row = 0; row < m_viaOverrides->GetNumberRows(); row++ ) + { + const wxString signalLayerFrom = m_viaOverrides->GetCellValue( row, VIA_GRID_SIGNAL_LAYER_FROM ); + const wxString signalLayerTo = m_viaOverrides->GetCellValue( row, VIA_GRID_SIGNAL_LAYER_TO ); + const wxString viaLayerFrom = m_viaOverrides->GetCellValue( row, VIA_GRID_VIA_LAYER_FROM ); + const wxString viaLayerTo = m_viaOverrides->GetCellValue( row, VIA_GRID_VIA_LAYER_TO ); + PCB_LAYER_ID signalLayerIdFrom = m_parentPanel->m_layerNamesToIDs[signalLayerFrom]; + PCB_LAYER_ID signalLayerIdTo = m_parentPanel->m_layerNamesToIDs[signalLayerTo]; + PCB_LAYER_ID viaLayerIdFrom = m_parentPanel->m_layerNamesToIDs[viaLayerFrom]; + PCB_LAYER_ID viaLayerIdTo = m_parentPanel->m_layerNamesToIDs[viaLayerTo]; + + // Order layers in stackup order (from F_Cu first) + if( IsCopperLayerLowerThan( signalLayerIdFrom, signalLayerIdTo ) ) + std::swap( signalLayerIdFrom, signalLayerIdTo ); + + if( IsCopperLayerLowerThan( viaLayerIdFrom, viaLayerIdTo ) ) + std::swap( viaLayerIdFrom, viaLayerIdTo ); + + const DELAY_PROFILE_VIA_OVERRIDE_ENTRY entry{ signalLayerIdFrom, signalLayerIdTo, viaLayerIdFrom, viaLayerIdTo, + m_viaOverrides->GetUnitValue( row, VIA_GRID_DELAY ) }; + profile.m_ViaOverrides.push_back( entry ); + } + + return profile; +} + + +PANEL_SETUP_TUNING_PROFILE_INFO::~PANEL_SETUP_TUNING_PROFILE_INFO() +{ + m_trackPropagationGrid->PopEventHandler( true ); + m_viaOverrides->PopEventHandler( true ); +} + + +void PANEL_SETUP_TUNING_PROFILE_INFO::UpdateLayerNames() +{ + wxArrayString layerNames, layerNamesWithNone; + layerNamesWithNone.push_back( "" ); + std::ranges::for_each( m_parentPanel->m_layerNames, + [&layerNames, &layerNamesWithNone]( const wxString& aLayerName ) + { + layerNames.push_back( aLayerName ); + layerNamesWithNone.push_back( aLayerName ); + } ); + + + // Save the current data - track grid + std::vector currentSignalLayer; + std::vector currentTopReferenceLayer; + std::vector currentBottomReferenceLayer; + + for( int row = 0; row < m_trackPropagationGrid->GetNumberRows(); ++row ) + { + currentSignalLayer.emplace_back( m_trackPropagationGrid->GetCellValue( row, TRACK_GRID_SIGNAL_LAYER ) ); + currentTopReferenceLayer.emplace_back( m_trackPropagationGrid->GetCellValue( row, TRACK_GRID_TOP_REFERENCE ) ); + currentBottomReferenceLayer.emplace_back( + m_trackPropagationGrid->GetCellValue( row, TRACK_GRID_BOTTOM_REFERENCE ) ); + } + + // Save the current data - via grid + std::vector currentSignalLayersFrom; + std::vector currentSignalLayersTo; + std::vector currentViaLayersFrom; + std::vector currentViaLayersTo; + + for( int row = 0; row < m_viaOverrides->GetNumberRows(); ++row ) + { + currentSignalLayersFrom.emplace_back( m_viaOverrides->GetCellValue( row, VIA_GRID_SIGNAL_LAYER_FROM ) ); + currentSignalLayersTo.emplace_back( m_viaOverrides->GetCellValue( row, VIA_GRID_SIGNAL_LAYER_TO ) ); + currentViaLayersFrom.emplace_back( m_viaOverrides->GetCellValue( row, VIA_GRID_VIA_LAYER_FROM ) ); + currentViaLayersTo.emplace_back( m_viaOverrides->GetCellValue( row, VIA_GRID_VIA_LAYER_TO ) ); + } + + // Reset the via layers lists + wxGridCellAttr* attr = new wxGridCellAttr; + attr->SetEditor( new wxGridCellChoiceEditor( layerNames, false ) ); + m_trackPropagationGrid->SetColAttr( TRACK_GRID_SIGNAL_LAYER, attr ); + + attr = new wxGridCellAttr; + attr->SetEditor( new wxGridCellChoiceEditor( layerNamesWithNone, false ) ); + m_trackPropagationGrid->SetColAttr( TRACK_GRID_TOP_REFERENCE, attr ); + + attr = new wxGridCellAttr; + attr->SetEditor( new wxGridCellChoiceEditor( layerNamesWithNone, false ) ); + m_trackPropagationGrid->SetColAttr( TRACK_GRID_BOTTOM_REFERENCE, attr ); + + attr = new wxGridCellAttr; + attr->SetEditor( new wxGridCellChoiceEditor( layerNames, false ) ); + m_viaOverrides->SetColAttr( VIA_GRID_SIGNAL_LAYER_FROM, attr ); + + attr = new wxGridCellAttr; + attr->SetEditor( new wxGridCellChoiceEditor( layerNames, false ) ); + m_viaOverrides->SetColAttr( VIA_GRID_SIGNAL_LAYER_TO, attr ); + + attr = new wxGridCellAttr; + attr->SetEditor( new wxGridCellChoiceEditor( layerNames, false ) ); + m_viaOverrides->SetColAttr( VIA_GRID_VIA_LAYER_FROM, attr ); + + attr = new wxGridCellAttr; + attr->SetEditor( new wxGridCellChoiceEditor( layerNames, false ) ); + m_viaOverrides->SetColAttr( VIA_GRID_VIA_LAYER_TO, attr ); + + // Restore the data, changing or resetting layer names if required + for( int row = 0; row < m_trackPropagationGrid->GetNumberRows(); ++row ) + { + if( m_parentPanel->m_prevLayerNamesToIDs.contains( currentSignalLayer[row] ) ) + { + PCB_LAYER_ID lastSignalId = m_parentPanel->m_prevLayerNamesToIDs[currentSignalLayer[row]]; + + if( m_parentPanel->m_copperLayerIdsToIndex.contains( lastSignalId ) ) + m_trackPropagationGrid->SetCellValue( row, TRACK_GRID_SIGNAL_LAYER, + m_parentPanel->m_board->GetLayerName( lastSignalId ) ); + else + m_trackPropagationGrid->SetCellValue( row, TRACK_GRID_SIGNAL_LAYER, + m_parentPanel->m_layerNames.front() ); + } + else + { + m_trackPropagationGrid->SetCellValue( row, TRACK_GRID_SIGNAL_LAYER, m_parentPanel->m_layerNames.front() ); + } + + if( m_parentPanel->m_prevLayerNamesToIDs.contains( currentTopReferenceLayer[row] ) ) + { + const PCB_LAYER_ID lastTopReferenceId = m_parentPanel->m_prevLayerNamesToIDs[currentTopReferenceLayer[row]]; + + if( m_parentPanel->m_copperLayerIdsToIndex.contains( lastTopReferenceId ) ) + m_trackPropagationGrid->SetCellValue( row, TRACK_GRID_TOP_REFERENCE, + m_parentPanel->m_board->GetLayerName( lastTopReferenceId ) ); + else + m_trackPropagationGrid->SetCellValue( row, TRACK_GRID_TOP_REFERENCE, layerNamesWithNone[0] ); + } + else + { + m_trackPropagationGrid->SetCellValue( row, TRACK_GRID_TOP_REFERENCE, layerNamesWithNone[0] ); + } + + if( m_parentPanel->m_prevLayerNamesToIDs.contains( currentBottomReferenceLayer[row] ) ) + { + const PCB_LAYER_ID lastBottomReferenceId = + m_parentPanel->m_prevLayerNamesToIDs[currentBottomReferenceLayer[row]]; + + if( m_parentPanel->m_copperLayerIdsToIndex.contains( lastBottomReferenceId ) ) + m_trackPropagationGrid->SetCellValue( row, TRACK_GRID_BOTTOM_REFERENCE, + m_parentPanel->m_board->GetLayerName( lastBottomReferenceId ) ); + else + m_trackPropagationGrid->SetCellValue( row, TRACK_GRID_BOTTOM_REFERENCE, layerNamesWithNone[0] ); + } + else + { + m_trackPropagationGrid->SetCellValue( row, TRACK_GRID_BOTTOM_REFERENCE, layerNamesWithNone[0] ); + } + } + + for( int row = 0; row < m_viaOverrides->GetNumberRows(); ++row ) + { + const PCB_LAYER_ID lastSignalFromId = m_parentPanel->m_prevLayerNamesToIDs[currentSignalLayersFrom[row]]; + + if( m_parentPanel->m_copperLayerIdsToIndex.contains( lastSignalFromId ) ) + m_viaOverrides->SetCellValue( row, VIA_GRID_SIGNAL_LAYER_FROM, + m_parentPanel->m_board->GetLayerName( lastSignalFromId ) ); + else + m_viaOverrides->SetCellValue( row, VIA_GRID_SIGNAL_LAYER_FROM, m_parentPanel->m_layerNames.front() ); + + const PCB_LAYER_ID lastSignalToId = m_parentPanel->m_prevLayerNamesToIDs[currentSignalLayersTo[row]]; + + if( m_parentPanel->m_copperLayerIdsToIndex.contains( lastSignalToId ) ) + m_viaOverrides->SetCellValue( row, VIA_GRID_SIGNAL_LAYER_TO, + m_parentPanel->m_board->GetLayerName( lastSignalToId ) ); + else + m_viaOverrides->SetCellValue( row, VIA_GRID_SIGNAL_LAYER_TO, m_parentPanel->m_layerNames.back() ); + + const PCB_LAYER_ID lastViaFromId = m_parentPanel->m_prevLayerNamesToIDs[currentViaLayersFrom[row]]; + + if( m_parentPanel->m_copperLayerIdsToIndex.contains( lastViaFromId ) ) + m_viaOverrides->SetCellValue( row, VIA_GRID_VIA_LAYER_FROM, + m_parentPanel->m_board->GetLayerName( lastViaFromId ) ); + else + m_viaOverrides->SetCellValue( row, VIA_GRID_VIA_LAYER_FROM, m_parentPanel->m_layerNames.front() ); + + const PCB_LAYER_ID lastViaToId = m_parentPanel->m_prevLayerNamesToIDs[currentViaLayersTo[row]]; + + if( m_parentPanel->m_copperLayerIdsToIndex.contains( lastViaToId ) ) + m_viaOverrides->SetCellValue( row, VIA_GRID_VIA_LAYER_TO, + m_parentPanel->m_board->GetLayerName( lastViaToId ) ); + else + m_viaOverrides->SetCellValue( row, VIA_GRID_VIA_LAYER_TO, m_parentPanel->m_layerNames.back() ); + } +} + + +void PANEL_SETUP_TUNING_PROFILE_INFO::setColumnWidths() +{ + const int minValueWidth = m_trackPropagationGrid->GetTextExtent( wxT( "000.0000 ps/mm" ) ).x; + + for( int i = 0; i < m_trackPropagationGrid->GetNumberCols(); ++i ) + { + const int titleSize = m_trackPropagationGrid->GetTextExtent( m_trackPropagationGrid->GetColLabelValue( i ) ).x; + + if( i == TRACK_GRID_SIGNAL_LAYER || i == TRACK_GRID_TOP_REFERENCE || i == TRACK_GRID_BOTTOM_REFERENCE ) + m_trackPropagationGrid->SetColSize( i, titleSize + 30 ); + else + m_trackPropagationGrid->SetColSize( i, std::max( titleSize, minValueWidth ) ); + } + + for( int i = 0; i < m_viaOverrides->GetNumberCols(); ++i ) + { + const int titleSize = GetTextExtent( m_viaOverrides->GetColLabelValue( i ) ).x; + if( i == VIA_GRID_DELAY ) + m_viaOverrides->SetColSize( i, std::max( titleSize, minValueWidth ) ); + else + m_viaOverrides->SetColSize( i, titleSize + 30 ); + } + + const int impedanceWidth = m_targetImpedance->GetTextExtent( wxT( "0000.00" ) ).x; + m_targetImpedance->SetSize( impedanceWidth, m_targetImpedance->GetSize().GetHeight() ); + + Layout(); +} + + +void PANEL_SETUP_TUNING_PROFILE_INFO::OnProfileNameChanged( wxCommandEvent& event ) +{ + const wxString newName = event.GetString(); + m_parentPanel->UpdateProfileName( this, newName ); +} + + +void PANEL_SETUP_TUNING_PROFILE_INFO::OnChangeProfileType( wxCommandEvent& event ) +{ + if( event.GetSelection() == 0 ) + onChangeProfileType( TUNING_PROFILE::PROFILE_TYPE::SINGLE ); + else + onChangeProfileType( TUNING_PROFILE::PROFILE_TYPE::DIFFERENTIAL ); +} + + +void PANEL_SETUP_TUNING_PROFILE_INFO::onChangeProfileType( TUNING_PROFILE::PROFILE_TYPE aType ) const +{ + m_trackPropagationGrid->CommitPendingChanges(); + m_viaOverrides->CommitPendingChanges(); + + if( aType == TUNING_PROFILE::PROFILE_TYPE::SINGLE ) + m_trackPropagationGrid->HideCol( TRACK_GRID_TRACK_GAP ); + else + m_trackPropagationGrid->ShowCol( TRACK_GRID_TRACK_GAP ); +} + + +void PANEL_SETUP_TUNING_PROFILE_INFO::OnAddTrackRow( wxCommandEvent& event ) +{ + const int numRows = m_trackPropagationGrid->GetNumberRows(); + m_trackPropagationGrid->InsertRows( m_trackPropagationGrid->GetNumberRows() ); + + auto setFrontRowLayers = [&]( const int row ) + { + auto nameItr = m_parentPanel->m_layerNames.begin(); + + if( nameItr == m_parentPanel->m_layerNames.end() ) + return; + + m_trackPropagationGrid->SetCellValue( row, TRACK_GRID_SIGNAL_LAYER, *nameItr ); + + ++nameItr; + + if( nameItr == m_parentPanel->m_layerNames.end() ) + return; + + m_trackPropagationGrid->SetCellValue( row, TRACK_GRID_BOTTOM_REFERENCE, *nameItr ); + }; + + auto setRowLayers = [&]() + { + if( numRows == 0 ) + { + setFrontRowLayers( 0 ); + return; + } + + const wxString lastSignalLayerName = + m_trackPropagationGrid->GetCellValue( numRows - 1, TRACK_GRID_SIGNAL_LAYER ); + auto nameItr = std::find( m_parentPanel->m_layerNames.begin(), m_parentPanel->m_layerNames.end(), + lastSignalLayerName ); + + if( nameItr == m_parentPanel->m_layerNames.end() ) + return; + + if( nameItr == m_parentPanel->m_layerNames.end() - 1 ) + { + setFrontRowLayers( numRows ); + return; + } + + ++nameItr; + + if( nameItr == m_parentPanel->m_layerNames.end() ) + return; + + m_trackPropagationGrid->SetCellValue( numRows, TRACK_GRID_SIGNAL_LAYER, *nameItr ); + m_trackPropagationGrid->SetCellValue( numRows, TRACK_GRID_TOP_REFERENCE, *( nameItr - 1 ) ); + + ++nameItr; + + if( nameItr != m_parentPanel->m_layerNames.end() ) + m_trackPropagationGrid->SetCellValue( numRows, TRACK_GRID_BOTTOM_REFERENCE, *nameItr ); + }; + + setRowLayers(); + + m_trackPropagationGrid->SetUnitValue( numRows, TRACK_GRID_TRACK_WIDTH, 0 ); + m_trackPropagationGrid->SetUnitValue( numRows, TRACK_GRID_TRACK_GAP, 0 ); + m_trackPropagationGrid->SetUnitValue( numRows, TRACK_GRID_DELAY, 0 ); + UpdateLayerNames(); +} + + +void PANEL_SETUP_TUNING_PROFILE_INFO::OnRemoveTrackRow( wxCommandEvent& event ) +{ + wxArrayInt selRows = m_trackPropagationGrid->GetSelectedRows(); + + if( selRows.size() == 1 ) + m_trackPropagationGrid->DeleteRows( selRows[0] ); +} + + +void PANEL_SETUP_TUNING_PROFILE_INFO::OnAddViaOverride( wxCommandEvent& event ) +{ + const int numRows = m_viaOverrides->GetNumberRows(); + m_viaOverrides->InsertRows( numRows ); + m_viaOverrides->SetUnitValue( numRows, VIA_GRID_DELAY, 0 ); + m_viaOverrides->SetCellValue( numRows, VIA_GRID_SIGNAL_LAYER_FROM, m_parentPanel->m_layerNames.front() ); + m_viaOverrides->SetCellValue( numRows, VIA_GRID_SIGNAL_LAYER_TO, m_parentPanel->m_layerNames.back() ); + m_viaOverrides->SetCellValue( numRows, VIA_GRID_VIA_LAYER_FROM, m_parentPanel->m_layerNames.front() ); + m_viaOverrides->SetCellValue( numRows, VIA_GRID_VIA_LAYER_TO, m_parentPanel->m_layerNames.back() ); + UpdateLayerNames(); +} + + +void PANEL_SETUP_TUNING_PROFILE_INFO::OnRemoveViaOverride( wxCommandEvent& event ) +{ + wxArrayInt selRows = m_viaOverrides->GetSelectedRows(); + + if( selRows.size() == 1 ) + m_viaOverrides->DeleteRows( selRows[0] ); +} + + +wxString PANEL_SETUP_TUNING_PROFILE_INFO::GetProfileName() const +{ + return m_name->GetValue(); +} + + +double PANEL_SETUP_TUNING_PROFILE_INFO::calculateSkinDepth( const double aFreq, const double aMurc, + const double aSigma ) +{ + return 1.0 / sqrt( M_PI * aFreq * aMurc * TRANSLINE_CALCULATIONS::MU0 * aSigma ); +} + + +int PANEL_SETUP_TUNING_PROFILE_INFO::getStackupLayerId( const std::vector& aLayerList, + PCB_LAYER_ID aPcbLayerId ) +{ + bool layerFound = false; + int layerStackupId = 0; + + while( layerStackupId < static_cast( aLayerList.size() ) && !layerFound ) + { + if( aLayerList.at( layerStackupId )->GetBrdLayerId() != aPcbLayerId ) + ++layerStackupId; + else + layerFound = true; + } + + if( !layerFound ) + return -1; + + return layerStackupId; +} + + +double PANEL_SETUP_TUNING_PROFILE_INFO::getTargetImpedance() const +{ + const wxString zStr = m_targetImpedance->GetValue(); + + double z; + if( !zStr.ToDouble( &z ) ) + z = -1; + + return z; +} + + +std::pair PANEL_SETUP_TUNING_PROFILE_INFO::calculateAverageDielectricConstants( + const std::vector& aStackupLayerList, const std::vector& dielectricLayerStackupIds, + const EDA_IU_SCALE& aIuScale ) +{ + double e_r = 0.0; + double lossTangent = 0.0; + double totalHeight = 0.0; + + for( int i : dielectricLayerStackupIds ) + { + const BOARD_STACKUP_ITEM* layer = aStackupLayerList.at( i ); + totalHeight += aIuScale.IUTomm( layer->GetThickness() ) / 1000.0; + } + + for( int i : dielectricLayerStackupIds ) + { + const BOARD_STACKUP_ITEM* layer = aStackupLayerList.at( i ); + e_r += layer->GetEpsilonR() * aIuScale.IUTomm( layer->GetThickness() ) / ( 1000.0 * totalHeight ); + lossTangent += layer->GetLossTangent() * aIuScale.IUTomm( layer->GetThickness() ) / ( 1000.0 * totalHeight ); + } + + return { e_r, lossTangent }; +} + + +void PANEL_SETUP_TUNING_PROFILE_INFO::getDielectricDetails( const std::vector& aStackupLayerList, + const int aSignalLayerId, const int aReferenceLayerId, + std::vector& aDielectricLayerStackupIds, + double& aDielectricLayerHeight ) +{ + const EDA_IU_SCALE& iuScale = m_parentPanel->m_unitsProvider->GetIuScale(); + aDielectricLayerHeight = 0.0; + + for( int i = std::min( aSignalLayerId, aReferenceLayerId ) + 1; i < std::max( aSignalLayerId, aReferenceLayerId ); + ++i ) + { + const BOARD_STACKUP_ITEM* layer = aStackupLayerList.at( i ); + + if( layer->GetType() != BS_ITEM_TYPE_DIELECTRIC ) + continue; + + if( !layer->HasEpsilonRValue() ) + continue; + + aDielectricLayerStackupIds.push_back( i ); + aDielectricLayerHeight += iuScale.IUTomm( aStackupLayerList.at( i )->GetThickness() ) / 1000.0; + } +} + + +void PANEL_SETUP_TUNING_PROFILE_INFO::calculateTrackParametersForCell( const int aRow, const int aCol ) +{ + // Determine if this is a stripline or microstrip geometry + const wxString signalLayerName = m_trackPropagationGrid->GetCellValue( aRow, TRACK_GRID_SIGNAL_LAYER ); + + if( !m_parentPanel->m_layerNamesToIDs.contains( signalLayerName ) ) + return; + + const PCB_LAYER_ID signalLayer = m_parentPanel->m_layerNamesToIDs.at( signalLayerName ); + const TUNING_PROFILE::PROFILE_TYPE profileType = m_type->GetSelection() == 0 + ? TUNING_PROFILE::PROFILE_TYPE::SINGLE + : TUNING_PROFILE::PROFILE_TYPE::DIFFERENTIAL; + const bool isMicrostrip = IsFrontLayer( signalLayer ) || IsBackLayer( signalLayer ); + CalculationType calculationType; + + switch( aCol ) + { + case TRACK_GRID_TRACK_WIDTH: calculationType = CalculationType::WIDTH; break; + case TRACK_GRID_TRACK_GAP: calculationType = CalculationType::GAP; break; + case TRACK_GRID_DELAY: calculationType = CalculationType::DELAY; break; + default: calculationType = CalculationType::WIDTH; break; + } + + if( profileType == TUNING_PROFILE::PROFILE_TYPE::DIFFERENTIAL ) // Differential tracks mode + { + int calculatedWidth = 0; + int calculatedGap = 0; + int calculatedDelay = 0; + + std::tuple result; + + if( isMicrostrip ) + result = calculateDifferentialMicrostrip( aRow, calculationType ); + else + result = calculateDifferentialStripline( aRow, calculationType ); + + calculatedWidth = std::get<0>( result ); + calculatedGap = std::get<1>( result ); + calculatedDelay = std::get<2>( result ); + + const bool widthOk = calculatedWidth > 0; + const bool gapOk = calculatedGap > 0; + const bool delayOk = calculatedDelay > 0; + + if( !widthOk ) + { + DisplayErrorMessage( m_parentPanel->m_dlg, _( "Could not compute track width" ) ); + return; + } + else if( !gapOk ) + { + DisplayErrorMessage( m_parentPanel->m_dlg, _( "Could not compute differential pair gap" ) ); + return; + } + else if( !delayOk ) + { + DisplayErrorMessage( m_parentPanel->m_dlg, _( "Could not compute track propagation delay" ) ); + return; + } + + if( calculationType == CalculationType::WIDTH ) + { + m_trackPropagationGrid->SetUnitValue( aRow, TRACK_GRID_TRACK_WIDTH, calculatedWidth ); + } + else if( calculationType == CalculationType::GAP ) + { + m_trackPropagationGrid->SetUnitValue( aRow, TRACK_GRID_TRACK_GAP, calculatedGap ); + } + + m_trackPropagationGrid->SetUnitValue( aRow, TRACK_GRID_DELAY, calculatedDelay ); + } + else // Single track mode + { + int calculatedWidth = 0; + int calculatedDelay = 0; + + std::pair result; + + if( isMicrostrip ) + result = calculateSingleMicrostrip( aRow, calculationType ); + else + result = calculateSingleStripline( aRow, calculationType ); + + calculatedWidth = result.first; + calculatedDelay = result.second; + + const bool widthOk = calculatedWidth > 0; + const bool delayOk = calculatedDelay > 0; + + if( !widthOk ) + { + DisplayErrorMessage( m_parentPanel->m_dlg, _( "Could not compute track width" ) ); + return; + } + else if( !delayOk ) + { + DisplayErrorMessage( m_parentPanel->m_dlg, _( "Could not compute track propagation delay" ) ); + return; + } + + if( calculationType == CalculationType::WIDTH ) + { + m_trackPropagationGrid->SetUnitValue( aRow, TRACK_GRID_TRACK_WIDTH, calculatedWidth ); + } + + m_trackPropagationGrid->SetUnitValue( aRow, TRACK_GRID_DELAY, calculatedDelay ); + } +} + + +bool PANEL_SETUP_TUNING_PROFILE_INFO::ValidateProfile( const size_t aPageIndex ) +{ + if( m_name->GetValue() == wxEmptyString ) + { + m_parentPanel->m_tuningProfiles->SetSelection( aPageIndex ); + + const wxString msg = _( "Tuning profile must have a name" ); + PAGED_DIALOG::GetDialog( m_parentPanel )->SetError( msg, this, m_name ); + return false; + } + + std::set layerNames; + + for( int i = 0; i < m_trackPropagationGrid->GetNumberRows(); ++i ) + { + wxString layerName = m_trackPropagationGrid->GetCellValue( i, TRACK_GRID_SIGNAL_LAYER ); + + if( layerNames.contains( layerName ) ) + { + m_parentPanel->m_tuningProfiles->SetSelection( aPageIndex ); + + const wxString msg = _( "Duplicated signal layer configuration in tuning profile" ); + PAGED_DIALOG::GetDialog( m_parentPanel ) + ->SetError( msg, m_parentPanel, m_trackPropagationGrid, i, TRACK_GRID_SIGNAL_LAYER ); + return false; + } + + layerNames.insert( layerName ); + } + + return true; +} + + +/***************************************************************************************************************** + * SIMULATION / ANALYSIS PLUMBING + ****************************************************************************************************************/ + +std::pair PANEL_SETUP_TUNING_PROFILE_INFO::calculateSingleMicrostrip( const int aRow, + CalculationType aCalculationType ) +{ + const EDA_IU_SCALE& iuScale = m_parentPanel->m_unitsProvider->GetIuScale(); + + // Get the target impedance + const double targetZ = getTargetImpedance(); + + if( targetZ <= 0 ) + return { 0, 0 }; + + // Get the signal layer information from the stackup + BOARD_STACKUP stackup = m_parentPanel->m_board->GetStackupOrDefault(); + const std::vector& stackupLayerList = stackup.GetList(); + + const wxString signalLayerName = m_trackPropagationGrid->GetCellValue( aRow, TRACK_GRID_SIGNAL_LAYER ); + + if( !m_parentPanel->m_layerNamesToIDs.contains( signalLayerName ) ) + return { 0, 0 }; + + const PCB_LAYER_ID signalLayer = m_parentPanel->m_layerNamesToIDs[signalLayerName]; + + // Microstrip can only be on an outer copper layer + if( signalLayer != F_Cu && signalLayer != B_Cu ) + return { 0, 0 }; + + const int signalLayerStackupId = getStackupLayerId( stackupLayerList, signalLayer ); + + if( signalLayerStackupId == -1 ) + return { 0, 0 }; + + const double signalLayerThickness = + iuScale.IUTomm( stackupLayerList.at( signalLayerStackupId )->GetThickness() ) / 1000.0; + + // Get reference layer + wxString referenceLayerName; + + if( signalLayer == F_Cu ) + referenceLayerName = m_trackPropagationGrid->GetCellValue( aRow, TRACK_GRID_BOTTOM_REFERENCE ); + else + referenceLayerName = m_trackPropagationGrid->GetCellValue( aRow, TRACK_GRID_TOP_REFERENCE ); + + if( !m_parentPanel->m_layerNamesToIDs.contains( referenceLayerName ) ) + return { 0, 0 }; + + const PCB_LAYER_ID referenceLayer = m_parentPanel->m_layerNamesToIDs[referenceLayerName]; + const int referenceLayerStackupId = getStackupLayerId( stackupLayerList, referenceLayer ); + + if( signalLayerStackupId == referenceLayerStackupId ) + return { 0, 0 }; + + // Get the dielectric layers between signal and reference layers + std::vector dielectricLayerStackupIds; + double dielectricLayerHeight = 0; + getDielectricDetails( stackupLayerList, signalLayerStackupId, referenceLayerStackupId, dielectricLayerStackupIds, + dielectricLayerHeight ); + + if( dielectricLayerHeight <= 0.0 ) + return { 0, 0 }; + + // Calculate geometric average of the dielectric materials + const auto [e_r, tan_d] = + calculateAverageDielectricConstants( stackupLayerList, dielectricLayerStackupIds, iuScale ); + + if( aCalculationType == CalculationType::WIDTH ) + { + m_microstripCalc.SetParameter( TRANSLINE_PARAMETERS::PHYS_WIDTH, 0.001 ); + } + else if( aCalculationType == CalculationType::DELAY ) + { + const int widthInt = m_trackPropagationGrid->GetUnitValue( aRow, TRACK_GRID_TRACK_WIDTH ); + + const double width = iuScale.IUTomm( widthInt ) / 1000.0; + m_microstripCalc.SetParameter( TRANSLINE_PARAMETERS::PHYS_WIDTH, width ); + } + + // Run the synthesis or analysis + m_microstripCalc.SetParameter( TRANSLINE_PARAMETERS::SIGMA, 1.0 / RHO ); + m_microstripCalc.SetParameter( TRANSLINE_PARAMETERS::EPSILON_EFF, 1.0 ); + m_microstripCalc.SetParameter( TRANSLINE_PARAMETERS::SKIN_DEPTH, calculateSkinDepth( 1.0, 1.0, 1.0 / RHO ) ); + m_microstripCalc.SetParameter( TRANSLINE_PARAMETERS::EPSILONR, e_r ); + m_microstripCalc.SetParameter( TRANSLINE_PARAMETERS::H_T, 1e+20 ); + m_microstripCalc.SetParameter( TRANSLINE_PARAMETERS::H, dielectricLayerHeight ); + m_microstripCalc.SetParameter( TRANSLINE_PARAMETERS::T, signalLayerThickness ); + m_microstripCalc.SetParameter( TRANSLINE_PARAMETERS::Z0, targetZ ); + m_microstripCalc.SetParameter( TRANSLINE_PARAMETERS::FREQUENCY, 1000000000.0 ); + m_microstripCalc.SetParameter( TRANSLINE_PARAMETERS::ROUGH, 0 ); + m_microstripCalc.SetParameter( TRANSLINE_PARAMETERS::TAND, tan_d ); + m_microstripCalc.SetParameter( TRANSLINE_PARAMETERS::PHYS_LEN, 10 ); + m_microstripCalc.SetParameter( TRANSLINE_PARAMETERS::MUR, 1 ); + m_microstripCalc.SetParameter( TRANSLINE_PARAMETERS::MURC, 1 ); + m_microstripCalc.SetParameter( TRANSLINE_PARAMETERS::ANG_L, 1 ); + + if( aCalculationType == CalculationType::WIDTH ) + m_microstripCalc.Synthesize( SYNTHESIZE_OPTS::DEFAULT ); + else + m_microstripCalc.Analyse(); + + std::unordered_map>& results = + [this, aCalculationType]() -> decltype( m_microstripCalc.GetSynthesisResults() ) + { + if( aCalculationType == CalculationType::WIDTH ) + return m_microstripCalc.GetSynthesisResults(); + + return m_microstripCalc.GetAnalysisResults(); + }(); + + if( results[TRANSLINE_PARAMETERS::PHYS_WIDTH].second != TRANSLINE_STATUS::OK ) + return { 0, 0 }; + + if( results[TRANSLINE_PARAMETERS::UNIT_PROP_DELAY].second != TRANSLINE_STATUS::OK ) + return { 0, 0 }; + + int width = static_cast( EDA_UNIT_UTILS::UI::FromUserUnit( + iuScale, EDA_UNITS::MM, results[TRANSLINE_PARAMETERS::PHYS_WIDTH].first * 1000.0 ) ); + int propDelay = static_cast( EDA_UNIT_UTILS::UI::FromUserUnit( + iuScale, EDA_UNITS::PS_PER_CM, results[TRANSLINE_PARAMETERS::UNIT_PROP_DELAY].first ) ); + + return { width, propDelay }; +} + + +std::pair PANEL_SETUP_TUNING_PROFILE_INFO::calculateSingleStripline( const int aRow, + CalculationType aCalculationType ) +{ + const EDA_IU_SCALE& iuScale = m_parentPanel->m_unitsProvider->GetIuScale(); + + // Get the target impedance + const double targetZ = getTargetImpedance(); + + if( targetZ <= 0 ) + return { 0, 0 }; + + // Get the signal layer information from the stackup + BOARD_STACKUP stackup = m_parentPanel->m_board->GetStackupOrDefault(); + const std::vector& stackupLayerList = stackup.GetList(); + + const wxString signalLayerName = m_trackPropagationGrid->GetCellValue( aRow, TRACK_GRID_SIGNAL_LAYER ); + + if( !m_parentPanel->m_layerNamesToIDs.contains( signalLayerName ) ) + return { 0, 0 }; + + const PCB_LAYER_ID signalLayer = m_parentPanel->m_layerNamesToIDs[signalLayerName]; + const int signalLayerStackupId = getStackupLayerId( stackupLayerList, signalLayer ); + + if( signalLayerStackupId == -1 ) + return { 0, 0 }; + + const double signalLayerThickness = + iuScale.IUTomm( stackupLayerList.at( signalLayerStackupId )->GetThickness() ) / 1000.0; + + // Get top reference layer + const wxString topReferenceLayerName = m_trackPropagationGrid->GetCellValue( aRow, TRACK_GRID_TOP_REFERENCE ); + + if( !m_parentPanel->m_layerNamesToIDs.contains( topReferenceLayerName ) ) + return { 0, 0 }; + + const PCB_LAYER_ID topReferenceLayer = m_parentPanel->m_layerNamesToIDs[topReferenceLayerName]; + const int topReferenceLayerStackupId = getStackupLayerId( stackupLayerList, topReferenceLayer ); + + if( !IsCopperLayerLowerThan( signalLayer, topReferenceLayer ) ) + return { 0, 0 }; + + // Get bottom reference layer + wxString bottomReferenceLayerName = m_trackPropagationGrid->GetCellValue( aRow, TRACK_GRID_BOTTOM_REFERENCE ); + + if( !m_parentPanel->m_layerNamesToIDs.contains( bottomReferenceLayerName ) ) + return { 0, 0 }; + + const PCB_LAYER_ID bottomReferenceLayer = m_parentPanel->m_layerNamesToIDs[bottomReferenceLayerName]; + const int bottomReferenceLayerStackupId = getStackupLayerId( stackupLayerList, bottomReferenceLayer ); + + if( !IsCopperLayerLowerThan( bottomReferenceLayer, signalLayer ) ) + return { 0, 0 }; + + // Get the dielectric layers between signal and reference layers + std::vector topDielectricLayerStackupIds, bottomDielectricLayerStackupIds; + double topDielectricLayerHeight = 0.0; + double bottomDielectricLayerHeight = 0.0; + + getDielectricDetails( stackupLayerList, signalLayerStackupId, topReferenceLayerStackupId, + topDielectricLayerStackupIds, topDielectricLayerHeight ); + getDielectricDetails( stackupLayerList, signalLayerStackupId, bottomReferenceLayerStackupId, + bottomDielectricLayerStackupIds, bottomDielectricLayerHeight ); + + if( topDielectricLayerHeight <= 0.0 || bottomDielectricLayerHeight <= 0.0 ) + return { 0, 0 }; + + // Calculate geometric average of the dielectric materials + std::vector allDielectricLayerStackupIds( topDielectricLayerStackupIds ); + allDielectricLayerStackupIds.insert( allDielectricLayerStackupIds.end(), bottomDielectricLayerStackupIds.begin(), + bottomDielectricLayerStackupIds.end() ); + const auto [e_r, tan_d] = + calculateAverageDielectricConstants( stackupLayerList, allDielectricLayerStackupIds, iuScale ); + + if( aCalculationType == CalculationType::WIDTH ) + { + m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::PHYS_WIDTH, 0.001 ); + } + else if( aCalculationType == CalculationType::DELAY ) + { + const int widthInt = m_trackPropagationGrid->GetUnitValue( aRow, TRACK_GRID_TRACK_WIDTH ); + + const double width = iuScale.IUTomm( widthInt ) / 1000.0; + m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::PHYS_WIDTH, width ); + } + + // Run the synthesis + m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::SKIN_DEPTH, calculateSkinDepth( 1.0, 1.0, 1.0 / RHO ) ); + m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::EPSILONR, e_r ); + m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::T, signalLayerThickness ); + m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::STRIPLINE_A, topDielectricLayerHeight ); + m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::H, + topDielectricLayerHeight + signalLayerThickness + bottomDielectricLayerHeight ); + m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::Z0, targetZ ); + m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::PHYS_LEN, 1.0 ); + m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::FREQUENCY, 1000000000.0 ); + m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::TAND, tan_d ); + m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::ANG_L, 1.0 ); + m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::SIGMA, 1.0 / RHO ); + m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::MURC, 1 ); + + if( aCalculationType == CalculationType::WIDTH ) + m_striplineCalc.Synthesize( SYNTHESIZE_OPTS::DEFAULT ); + else + m_striplineCalc.Analyse(); + + std::unordered_map>& results = + [this, aCalculationType]() -> decltype( m_striplineCalc.GetSynthesisResults() ) + { + if( aCalculationType == CalculationType::WIDTH ) + return m_striplineCalc.GetSynthesisResults(); + + return m_striplineCalc.GetAnalysisResults(); + }(); + + if( results[TRANSLINE_PARAMETERS::PHYS_WIDTH].second != TRANSLINE_STATUS::OK ) + return { 0, 0 }; + + if( results[TRANSLINE_PARAMETERS::UNIT_PROP_DELAY].second != TRANSLINE_STATUS::OK ) + return { 0, 0 }; + + int width = static_cast( EDA_UNIT_UTILS::UI::FromUserUnit( + iuScale, EDA_UNITS::MM, results[TRANSLINE_PARAMETERS::PHYS_WIDTH].first * 1000.0 ) ); + int propDelay = static_cast( EDA_UNIT_UTILS::UI::FromUserUnit( + iuScale, EDA_UNITS::PS_PER_CM, results[TRANSLINE_PARAMETERS::UNIT_PROP_DELAY].first ) ); + + return { width, propDelay }; +} + + +std::tuple +PANEL_SETUP_TUNING_PROFILE_INFO::calculateDifferentialMicrostrip( const int aRow, CalculationType aCalculationType ) +{ + const EDA_IU_SCALE& iuScale = m_parentPanel->m_unitsProvider->GetIuScale(); + + // Get the target impedance + const double targetZ = getTargetImpedance(); + + if( targetZ <= 0 ) + return { 0, 0, 0 }; + + // Get the signal layer information from the stackup + BOARD_STACKUP stackup = m_parentPanel->m_board->GetStackupOrDefault(); + const std::vector& stackupLayerList = stackup.GetList(); + + const wxString signalLayerName = m_trackPropagationGrid->GetCellValue( aRow, TRACK_GRID_SIGNAL_LAYER ); + + if( !m_parentPanel->m_layerNamesToIDs.contains( signalLayerName ) ) + return { 0, 0, 0 }; + + const PCB_LAYER_ID signalLayer = m_parentPanel->m_layerNamesToIDs[signalLayerName]; + + // Microstrip can only be on an outer copper layer + if( signalLayer != F_Cu && signalLayer != B_Cu ) + return { 0, 0, 0 }; + + const int signalLayerStackupId = getStackupLayerId( stackupLayerList, signalLayer ); + + if( signalLayerStackupId == -1 ) + return { 0, 0, 0 }; + + const double signalLayerThickness = + iuScale.IUTomm( stackupLayerList.at( signalLayerStackupId )->GetThickness() ) / 1000.0; + + // Get reference layer + wxString referenceLayerName; + + if( signalLayer == F_Cu ) + referenceLayerName = m_trackPropagationGrid->GetCellValue( aRow, TRACK_GRID_BOTTOM_REFERENCE ); + else + referenceLayerName = m_trackPropagationGrid->GetCellValue( aRow, TRACK_GRID_TOP_REFERENCE ); + + if( !m_parentPanel->m_layerNamesToIDs.contains( referenceLayerName ) ) + return { 0, 0, 0 }; + + const PCB_LAYER_ID referenceLayer = m_parentPanel->m_layerNamesToIDs[referenceLayerName]; + const int referenceLayerStackupId = getStackupLayerId( stackupLayerList, referenceLayer ); + + if( signalLayerStackupId == referenceLayerStackupId ) + return { 0, 0, 0 }; + + // Get the dielectric layers between signal and reference layers + std::vector dielectricLayerStackupIds; + double dielectricLayerHeight = 0; + getDielectricDetails( stackupLayerList, signalLayerStackupId, referenceLayerStackupId, dielectricLayerStackupIds, + dielectricLayerHeight ); + + if( dielectricLayerHeight <= 0.0 ) + return { 0, 0, 0 }; + + // Calculate geometric average of the dielectric materials + const auto [e_r, tan_d] = + calculateAverageDielectricConstants( stackupLayerList, dielectricLayerStackupIds, iuScale ); + + // Get tuning parameters + double width = 0.0; + double gap = 0.0; + + const std::optional widthOpt = m_trackPropagationGrid->GetOptionalUnitValue( aRow, TRACK_GRID_TRACK_WIDTH ); + const std::optional gapOpt = m_trackPropagationGrid->GetOptionalUnitValue( aRow, TRACK_GRID_TRACK_GAP ); + + if( aCalculationType == CalculationType::WIDTH ) + { + if( !gapOpt ) + return { 0, 0, 0 }; + + gap = iuScale.IUTomm( gapOpt.value() ) / 1000.0; + } + else if( aCalculationType == CalculationType::GAP ) + { + if( !widthOpt ) + return { 0, 0, 0 }; + + width = iuScale.IUTomm( widthOpt.value() ) / 1000.0; + } + else if( aCalculationType == CalculationType::DELAY ) + { + if( !widthOpt || !gapOpt ) + return { 0, 0, 0 }; + + width = iuScale.IUTomm( widthOpt.value() ) / 1000.0; + gap = iuScale.IUTomm( gapOpt.value() ) / 1000.0; + } + + // Run the synthesis + m_coupledMicrostripCalc.SetParameter( TRANSLINE_PARAMETERS::Z0_E, targetZ / 2.0 ); + m_coupledMicrostripCalc.SetParameter( TRANSLINE_PARAMETERS::Z0_O, targetZ / 2.0 ); + m_coupledMicrostripCalc.SetParameter( TRANSLINE_PARAMETERS::Z_DIFF, targetZ ); + m_coupledMicrostripCalc.SetParameter( TRANSLINE_PARAMETERS::PHYS_WIDTH, width ); + m_coupledMicrostripCalc.SetParameter( TRANSLINE_PARAMETERS::PHYS_S, gap ); + m_coupledMicrostripCalc.SetParameter( TRANSLINE_PARAMETERS::EPSILONR, e_r ); + m_coupledMicrostripCalc.SetParameter( TRANSLINE_PARAMETERS::PHYS_LEN, 10 ); + m_coupledMicrostripCalc.SetParameter( TRANSLINE_PARAMETERS::H, dielectricLayerHeight ); + m_coupledMicrostripCalc.SetParameter( TRANSLINE_PARAMETERS::T, signalLayerThickness ); + m_coupledMicrostripCalc.SetParameter( TRANSLINE_PARAMETERS::H_T, 1e+20 ); + m_coupledMicrostripCalc.SetParameter( TRANSLINE_PARAMETERS::FREQUENCY, 1000000000.0 ); + m_coupledMicrostripCalc.SetParameter( TRANSLINE_PARAMETERS::MURC, 1 ); + m_coupledMicrostripCalc.SetParameter( TRANSLINE_PARAMETERS::SKIN_DEPTH, calculateSkinDepth( 1.0, 1.0, 1.0 / RHO ) ); + m_coupledMicrostripCalc.SetParameter( TRANSLINE_PARAMETERS::SIGMA, 1.0 / RHO ); + m_coupledMicrostripCalc.SetParameter( TRANSLINE_PARAMETERS::ROUGH, 0 ); + m_coupledMicrostripCalc.SetParameter( TRANSLINE_PARAMETERS::TAND, tan_d ); + m_coupledMicrostripCalc.SetParameter( TRANSLINE_PARAMETERS::ANG_L, 1 ); + + switch( aCalculationType ) + { + case CalculationType::WIDTH: m_coupledMicrostripCalc.Synthesize( SYNTHESIZE_OPTS::FIX_SPACING ); break; + case CalculationType::GAP: m_coupledMicrostripCalc.Synthesize( SYNTHESIZE_OPTS::FIX_WIDTH ); break; + case CalculationType::DELAY: m_coupledMicrostripCalc.Analyse(); break; + } + + std::unordered_map>& results = + [this, aCalculationType]() -> decltype( m_microstripCalc.GetSynthesisResults() ) + { + if( aCalculationType == CalculationType::WIDTH || aCalculationType == CalculationType::GAP ) + return m_coupledMicrostripCalc.GetSynthesisResults(); + + return m_coupledMicrostripCalc.GetAnalysisResults(); + }(); + + if( results[TRANSLINE_PARAMETERS::PHYS_WIDTH].second != TRANSLINE_STATUS::OK ) + return { 0, 0, 0 }; + + if( results[TRANSLINE_PARAMETERS::PHYS_S].second != TRANSLINE_STATUS::OK ) + return { 0, 0, 0 }; + + if( results[TRANSLINE_PARAMETERS::UNIT_PROP_DELAY_ODD].second != TRANSLINE_STATUS::OK ) + return { 0, 0, 0 }; + + int calcWidth = static_cast( EDA_UNIT_UTILS::UI::FromUserUnit( + iuScale, EDA_UNITS::MM, results[TRANSLINE_PARAMETERS::PHYS_WIDTH].first * 1000.0 ) ); + int calcGap = static_cast( EDA_UNIT_UTILS::UI::FromUserUnit( + iuScale, EDA_UNITS::MM, results[TRANSLINE_PARAMETERS::PHYS_S].first * 1000.0 ) ); + int propDelay = static_cast( EDA_UNIT_UTILS::UI::FromUserUnit( + iuScale, EDA_UNITS::PS_PER_CM, results[TRANSLINE_PARAMETERS::UNIT_PROP_DELAY_ODD].first ) ); + + return { calcWidth, calcGap, propDelay }; +} + + +std::tuple +PANEL_SETUP_TUNING_PROFILE_INFO::calculateDifferentialStripline( const int aRow, CalculationType aCalculationType ) +{ + const EDA_IU_SCALE& iuScale = m_parentPanel->m_unitsProvider->GetIuScale(); + + // Get the target impedance + const double targetZ = getTargetImpedance(); + + if( targetZ <= 0 ) + return { 0, 0, 0 }; + + // Get the signal layer information from the stackup + BOARD_STACKUP stackup = m_parentPanel->m_board->GetStackupOrDefault(); + const std::vector& stackupLayerList = stackup.GetList(); + + const wxString signalLayerName = m_trackPropagationGrid->GetCellValue( aRow, TRACK_GRID_SIGNAL_LAYER ); + + if( !m_parentPanel->m_layerNamesToIDs.contains( signalLayerName ) ) + return { 0, 0, 0 }; + + const PCB_LAYER_ID signalLayer = m_parentPanel->m_layerNamesToIDs[signalLayerName]; + const int signalLayerStackupId = getStackupLayerId( stackupLayerList, signalLayer ); + + if( signalLayerStackupId == -1 ) + return { 0, 0, 0 }; + + const double signalLayerThickness = + iuScale.IUTomm( stackupLayerList.at( signalLayerStackupId )->GetThickness() ) / 1000.0; + + // Get top reference layer + const wxString topReferenceLayerName = m_trackPropagationGrid->GetCellValue( aRow, TRACK_GRID_TOP_REFERENCE ); + + if( !m_parentPanel->m_layerNamesToIDs.contains( topReferenceLayerName ) ) + return { 0, 0, 0 }; + + const PCB_LAYER_ID topReferenceLayer = m_parentPanel->m_layerNamesToIDs[topReferenceLayerName]; + const int topReferenceLayerStackupId = getStackupLayerId( stackupLayerList, topReferenceLayer ); + + if( !IsCopperLayerLowerThan( signalLayer, topReferenceLayer ) ) + return { 0, 0, 0 }; + + // Get bottom reference layer + wxString bottomReferenceLayerName = m_trackPropagationGrid->GetCellValue( aRow, TRACK_GRID_BOTTOM_REFERENCE ); + + if( !m_parentPanel->m_layerNamesToIDs.contains( bottomReferenceLayerName ) ) + return { 0, 0, 0 }; + + const PCB_LAYER_ID bottomReferenceLayer = m_parentPanel->m_layerNamesToIDs[bottomReferenceLayerName]; + const int bottomReferenceLayerStackupId = getStackupLayerId( stackupLayerList, bottomReferenceLayer ); + + if( !IsCopperLayerLowerThan( bottomReferenceLayer, signalLayer ) ) + return { 0, 0, 0 }; + + // Get the dielectric layers between signal and reference layers + std::vector topDielectricLayerStackupIds, bottomDielectricLayerStackupIds; + double topDielectricLayerHeight = 0.0; + double bottomDielectricLayerHeight = 0.0; + + getDielectricDetails( stackupLayerList, signalLayerStackupId, topReferenceLayerStackupId, + topDielectricLayerStackupIds, topDielectricLayerHeight ); + getDielectricDetails( stackupLayerList, signalLayerStackupId, bottomReferenceLayerStackupId, + bottomDielectricLayerStackupIds, bottomDielectricLayerHeight ); + + if( topDielectricLayerHeight <= 0.0 || bottomDielectricLayerHeight <= 0.0 ) + return { 0, 0, 0 }; + + // Calculate geometric average of the dielectric materials + std::vector allDielectricLayerStackupIds( topDielectricLayerStackupIds ); + allDielectricLayerStackupIds.insert( allDielectricLayerStackupIds.end(), bottomDielectricLayerStackupIds.begin(), + bottomDielectricLayerStackupIds.end() ); + const auto [e_r, tan_d] = + calculateAverageDielectricConstants( stackupLayerList, allDielectricLayerStackupIds, iuScale ); + + // Get tuning parameters + double width = 0.0; + double gap = 0.0; + + const std::optional widthOpt = m_trackPropagationGrid->GetOptionalUnitValue( aRow, TRACK_GRID_TRACK_WIDTH ); + const std::optional gapOpt = m_trackPropagationGrid->GetOptionalUnitValue( aRow, TRACK_GRID_TRACK_GAP ); + + if( aCalculationType == CalculationType::WIDTH ) + { + if( !gapOpt ) + return { 0, 0, 0 }; + + gap = iuScale.IUTomm( gapOpt.value() ) / 1000.0; + } + else if( aCalculationType == CalculationType::GAP ) + { + if( !widthOpt ) + return { 0, 0, 0 }; + + width = iuScale.IUTomm( widthOpt.value() ) / 1000.0; + } + else if( aCalculationType == CalculationType::DELAY ) + { + if( !widthOpt || !gapOpt ) + return { 0, 0, 0 }; + + width = iuScale.IUTomm( widthOpt.value() ) / 1000.0; + gap = iuScale.IUTomm( gapOpt.value() ) / 1000.0; + } + + // Run the synthesis + m_coupledStriplineCalc.SetParameter( TRANSLINE_PARAMETERS::Z0_E, targetZ / 2.0 ); + m_coupledStriplineCalc.SetParameter( TRANSLINE_PARAMETERS::Z0_O, targetZ / 2.0 ); + m_coupledStriplineCalc.SetParameter( TRANSLINE_PARAMETERS::Z_DIFF, targetZ ); + m_coupledStriplineCalc.SetParameter( TRANSLINE_PARAMETERS::PHYS_WIDTH, width ); + m_coupledStriplineCalc.SetParameter( TRANSLINE_PARAMETERS::PHYS_S, gap ); + m_coupledStriplineCalc.SetParameter( TRANSLINE_PARAMETERS::T, signalLayerThickness ); + m_coupledStriplineCalc.SetParameter( TRANSLINE_PARAMETERS::H, topDielectricLayerHeight + signalLayerThickness + + bottomDielectricLayerHeight ); + m_coupledStriplineCalc.SetParameter( TRANSLINE_PARAMETERS::EPSILONR, e_r ); + m_coupledStriplineCalc.SetParameter( TRANSLINE_PARAMETERS::SKIN_DEPTH, calculateSkinDepth( 1.0, 1.0, 1.0 / RHO ) ); + m_coupledStriplineCalc.SetParameter( TRANSLINE_PARAMETERS::PHYS_LEN, 1.0 ); + m_coupledStriplineCalc.SetParameter( TRANSLINE_PARAMETERS::FREQUENCY, 1000000000.0 ); + m_coupledStriplineCalc.SetParameter( TRANSLINE_PARAMETERS::ANG_L, 1.0 ); + m_coupledStriplineCalc.SetParameter( TRANSLINE_PARAMETERS::SIGMA, 1.0 / RHO ); + m_coupledStriplineCalc.SetParameter( TRANSLINE_PARAMETERS::MURC, 1 ); + + switch( aCalculationType ) + { + case CalculationType::WIDTH: m_coupledStriplineCalc.Synthesize( SYNTHESIZE_OPTS::FIX_SPACING ); break; + case CalculationType::GAP: m_coupledStriplineCalc.Synthesize( SYNTHESIZE_OPTS::FIX_WIDTH ); break; + case CalculationType::DELAY: m_coupledStriplineCalc.Analyse(); break; + } + + std::unordered_map>& results = + [this, aCalculationType]() -> decltype( m_coupledStriplineCalc.GetSynthesisResults() ) + { + if( aCalculationType == CalculationType::WIDTH || aCalculationType == CalculationType::GAP ) + return m_coupledStriplineCalc.GetSynthesisResults(); + + return m_coupledStriplineCalc.GetAnalysisResults(); + }(); + + if( results[TRANSLINE_PARAMETERS::PHYS_WIDTH].second != TRANSLINE_STATUS::OK ) + return { 0, 0, 0 }; + + if( results[TRANSLINE_PARAMETERS::PHYS_S].second != TRANSLINE_STATUS::OK ) + return { 0, 0, 0 }; + + if( results[TRANSLINE_PARAMETERS::UNIT_PROP_DELAY_ODD].second != TRANSLINE_STATUS::OK ) + return { 0, 0, 0 }; + + int calcWidth = static_cast( EDA_UNIT_UTILS::UI::FromUserUnit( + iuScale, EDA_UNITS::MM, results[TRANSLINE_PARAMETERS::PHYS_WIDTH].first * 1000.0 ) ); + int calcGap = static_cast( EDA_UNIT_UTILS::UI::FromUserUnit( + iuScale, EDA_UNITS::MM, results[TRANSLINE_PARAMETERS::PHYS_S].first * 1000.0 ) ); + int propDelay = static_cast( EDA_UNIT_UTILS::UI::FromUserUnit( + iuScale, EDA_UNITS::PS_PER_CM, results[TRANSLINE_PARAMETERS::UNIT_PROP_DELAY_ODD].first ) ); + + return { calcWidth, calcGap, propDelay }; +} diff --git a/pcbnew/dialogs/panel_setup_tuning_profile_info.h b/pcbnew/dialogs/panel_setup_tuning_profile_info.h new file mode 100644 index 0000000000..e06809da98 --- /dev/null +++ b/pcbnew/dialogs/panel_setup_tuning_profile_info.h @@ -0,0 +1,184 @@ +/* +* This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright The KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef PANEL_SETUP_TUNING_PROFILE_INFO_H +#define PANEL_SETUP_TUNING_PROFILE_INFO_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class PANEL_SETUP_TUNING_PROFILES; + +class PANEL_SETUP_TUNING_PROFILE_INFO : public PANEL_SETUP_TUNING_PROFILE_INFO_BASE +{ +public: + PANEL_SETUP_TUNING_PROFILE_INFO( wxWindow* aParentWindow, PANEL_SETUP_TUNING_PROFILES* parentPanel ); + + ~PANEL_SETUP_TUNING_PROFILE_INFO() override; + + /// Updates the displayed layer names in all grids + void UpdateLayerNames(); + + /// Loads the given profile in to the panel + void LoadProfile( const TUNING_PROFILE& aProfile ); + + /// Saves the panel to the given profile + TUNING_PROFILE GetProfile() const; + + /// Updates the parent notebook control + void OnProfileNameChanged( wxCommandEvent& event ) override; + + /// Changes between Single and Differential profiles + void OnChangeProfileType( wxCommandEvent& event ) override; + + /// Adds a row to the track propagation grid + void OnAddTrackRow( wxCommandEvent& event ) override; + + /// Removes a row from the track propagation grid + void OnRemoveTrackRow( wxCommandEvent& event ) override; + + /// Adds a via override row + void OnAddViaOverride( wxCommandEvent& event ) override; + + /// Removes a via override row + void OnRemoveViaOverride( wxCommandEvent& event ) override; + + /// Gets the name of this profile + wxString GetProfileName() const; + + /// Validate this panel's data + bool ValidateProfile( size_t aPageIndex ); + +private: + enum TRACK_GRID_COLS + { + TRACK_GRID_SIGNAL_LAYER = 0, + TRACK_GRID_TOP_REFERENCE, + TRACK_GRID_BOTTOM_REFERENCE, + TRACK_GRID_TRACK_WIDTH, + TRACK_GRID_TRACK_GAP, + TRACK_GRID_DELAY + }; + + enum VIA_GRID_COLS + { + VIA_GRID_SIGNAL_LAYER_FROM = 0, + VIA_GRID_SIGNAL_LAYER_TO, + VIA_GRID_VIA_LAYER_FROM, + VIA_GRID_VIA_LAYER_TO, + VIA_GRID_DELAY + }; + + enum class CalculationType + { + WIDTH, + GAP, + DELAY + }; + + /// Initialises all controls on the panel + void initPanel(); + + /// Set up the widths of all grid columns + void setColumnWidths(); + + /// Calculates the track width or delay for the given propagation grid row + /// @returns pair of (width, unit propagation delay) in IU + std::pair calculateSingleMicrostrip( const int aRow, CalculationType aCalculationType ); + + /// Calculates the track width or delay for the given propagation grid row + /// @returns pair of (width, unit propagation delay) in IU + std::pair calculateSingleStripline( const int aRow, CalculationType aCalculationType ); + + /// Calculates the track width, pair gap, or delay for the given propagation grid row + /// @returns tuple of (width, diff pair gap, unit propagation delay) in IU + std::tuple calculateDifferentialMicrostrip( int aRow, CalculationType aCalculationType ); + + /// Calculates the track width, pair gap, or delay for the given propagation grid row + /// @returns tuple of (width, diff pair gap, unit propagation delay) in IU + std::tuple calculateDifferentialStripline( int aRow, CalculationType aCalculationType ); + + /// Calculate the effective skin depth for the given parameters + static double calculateSkinDepth( double aFreq, double aMurc, double aSigma ); + + /// Gets the index in to the layer list for the given layer. + /// @returns -1 if not found + static int getStackupLayerId( const std::vector& aLayerList, PCB_LAYER_ID aPcbLayerId ); + + /** + * Calculates the geometric average of the dielectric material properties. Note: This is a poor approximation as the + * electric field distribution is not equal across the dielectrics. However, it will do as an approximation before + * we have a field solver integrated. + * + * @returns (E_r, LossTangent) pair + */ + static std::pair + calculateAverageDielectricConstants( const std::vector& aStackupLayerList, + const std::vector& dielectricLayerStackupIds, + const EDA_IU_SCALE& aIuScale ); + + /// Gets the dielectric layers and heights for dielectrics between the two given copper layer IDs + void getDielectricDetails( const std::vector& aStackupLayerList, int aSignalLayerId, + int aReferenceLayerId, std::vector& aDielectricLayerStackupIds, + double& aDielectricLayerHeight ); + + /// Gets the target impedance for the profile + double getTargetImpedance() const; + + /// Calculates the required track parameters for the given track parameters grid row and col + void calculateTrackParametersForCell( int aRow, int aCol ); + + /// Sets the panel display for the given tuning type + void onChangeProfileType( TUNING_PROFILE::PROFILE_TYPE aType ) const; + + /// The parent setup panel + PANEL_SETUP_TUNING_PROFILES* m_parentPanel; + + /// Units for global via propagation unit delay + UNIT_BINDER m_viaPropagationUnits; + + /// Calculator for single microstrip parameters + MICROSTRIP m_microstripCalc; + + /// Calculator for single stripline parameters + STRIPLINE m_striplineCalc; + + /// Calculator for coupled (differential) microstrip parameters + COUPLED_MICROSTRIP m_coupledMicrostripCalc; + + /// Calculator for coupled (differential) stripline parameters + COUPLED_STRIPLINE m_coupledStriplineCalc; + + // Electrical resistivity or specific electrical resistance of copper (ohm*meter) + static constexpr double RHO = 1.72e-8; +}; + + +#endif //PANEL_SETUP_TUNING_PROFILE_INFO_H diff --git a/pcbnew/dialogs/panel_setup_tuning_profile_info_base.cpp b/pcbnew/dialogs/panel_setup_tuning_profile_info_base.cpp new file mode 100644 index 0000000000..61be0c75c7 --- /dev/null +++ b/pcbnew/dialogs/panel_setup_tuning_profile_info_base.cpp @@ -0,0 +1,270 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "widgets/std_bitmap_button.h" +#include "widgets/wx_grid.h" + +#include "panel_setup_tuning_profile_info_base.h" + +/////////////////////////////////////////////////////////////////////////// + +PANEL_SETUP_TUNING_PROFILE_INFO_BASE::PANEL_SETUP_TUNING_PROFILE_INFO_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name ) +{ + wxFlexGridSizer* fgSizer1; + fgSizer1 = new wxFlexGridSizer( 3, 1, 0, 0 ); + fgSizer1->AddGrowableCol( 0 ); + fgSizer1->AddGrowableRow( 2 ); + fgSizer1->SetFlexibleDirection( wxBOTH ); + fgSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_ALL ); + + wxFlexGridSizer* fgSizer2; + fgSizer2 = new wxFlexGridSizer( 1, 9, 0, 0 ); + fgSizer2->AddGrowableCol( 2 ); + fgSizer2->AddGrowableCol( 5 ); + fgSizer2->SetFlexibleDirection( wxHORIZONTAL ); + fgSizer2->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_ALL ); + + m_nameLabel = new wxStaticText( this, wxID_ANY, _("Name:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_nameLabel->Wrap( -1 ); + fgSizer2->Add( m_nameLabel, 0, wxALL, 5 ); + + m_name = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer2->Add( m_name, 0, wxALL|wxEXPAND, 5 ); + + + fgSizer2->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_typeLabel = new wxStaticText( this, wxID_ANY, _("Type:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_typeLabel->Wrap( -1 ); + fgSizer2->Add( m_typeLabel, 0, wxALL, 5 ); + + wxString m_typeChoices[] = { _("Single"), _("Differential") }; + int m_typeNChoices = sizeof( m_typeChoices ) / sizeof( wxString ); + m_type = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_typeNChoices, m_typeChoices, 0 ); + m_type->SetSelection( 0 ); + fgSizer2->Add( m_type, 0, wxALL, 5 ); + + + fgSizer2->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_targetImpedanceLabel = new wxStaticText( this, wxID_ANY, _("Target Impedance:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_targetImpedanceLabel->Wrap( -1 ); + fgSizer2->Add( m_targetImpedanceLabel, 0, wxALL, 5 ); + + m_targetImpedance = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + #ifdef __WXGTK__ + if ( !m_targetImpedance->HasFlag( wxTE_MULTILINE ) ) + { + m_targetImpedance->SetMaxLength( 15 ); + } + #else + m_targetImpedance->SetMaxLength( 15 ); + #endif + fgSizer2->Add( m_targetImpedance, 0, wxALL|wxEXPAND, 5 ); + + m_ohmsLabel = new wxStaticText( this, wxID_ANY, _("ohms"), wxDefaultPosition, wxDefaultSize, 0 ); + m_ohmsLabel->Wrap( -1 ); + fgSizer2->Add( m_ohmsLabel, 0, wxALL|wxRIGHT, 5 ); + + + fgSizer1->Add( fgSizer2, 1, wxEXPAND, 5 ); + + wxGridBagSizer* gbSizer1; + gbSizer1 = new wxGridBagSizer( 0, 0 ); + gbSizer1->SetFlexibleDirection( wxBOTH ); + gbSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_enableDrcGeneration = new wxCheckBox( this, wxID_ANY, _("Generate Net Class DRC Rules"), wxDefaultPosition, wxDefaultSize, 0 ); + m_enableDrcGeneration->SetValue(true); + gbSizer1->Add( m_enableDrcGeneration, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxALL, 5 ); + + m_enableDelayTuning = new wxCheckBox( this, wxID_ANY, _("Enable Time Domain Tuning"), wxDefaultPosition, wxDefaultSize, 0 ); + gbSizer1->Add( m_enableDelayTuning, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), wxALL, 5 ); + + m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + gbSizer1->Add( m_staticline1, wxGBPosition( 1, 0 ), wxGBSpan( 1, 2 ), wxEXPAND | wxALL, 5 ); + + + gbSizer1->AddGrowableCol( 0 ); + + fgSizer1->Add( gbSizer1, 1, wxEXPAND, 5 ); + + m_splitter1 = new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_3DSASH ); + m_splitter1->Connect( wxEVT_IDLE, wxIdleEventHandler( PANEL_SETUP_TUNING_PROFILE_INFO_BASE::m_splitter1OnIdle ), NULL, this ); + + m_panel3 = new wxPanel( m_splitter1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxStaticBoxSizer* sbSizer2; + sbSizer2 = new wxStaticBoxSizer( new wxStaticBox( m_panel3, wxID_ANY, _("Track Propagation") ), wxVERTICAL ); + + wxFlexGridSizer* fgSizer4; + fgSizer4 = new wxFlexGridSizer( 0, 1, 0, 0 ); + fgSizer4->AddGrowableCol( 0 ); + fgSizer4->AddGrowableRow( 0 ); + fgSizer4->SetFlexibleDirection( wxBOTH ); + fgSizer4->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_trackPropagationGrid = new WX_GRID( sbSizer2->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + + // Grid + m_trackPropagationGrid->CreateGrid( 0, 6 ); + m_trackPropagationGrid->EnableEditing( true ); + m_trackPropagationGrid->EnableGridLines( true ); + m_trackPropagationGrid->EnableDragGridSize( false ); + m_trackPropagationGrid->SetMargins( 0, 0 ); + + // Columns + m_trackPropagationGrid->AutoSizeColumns(); + m_trackPropagationGrid->EnableDragColMove( false ); + m_trackPropagationGrid->EnableDragColSize( true ); + m_trackPropagationGrid->SetColLabelValue( 0, _("Signal Layer") ); + m_trackPropagationGrid->SetColLabelValue( 1, _("Top Reference") ); + m_trackPropagationGrid->SetColLabelValue( 2, _("Bottom Reference") ); + m_trackPropagationGrid->SetColLabelValue( 3, _("Track Width") ); + m_trackPropagationGrid->SetColLabelValue( 4, _("Diff Pair Gap") ); + m_trackPropagationGrid->SetColLabelValue( 5, _("Unit Delay") ); + m_trackPropagationGrid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); + + // Rows + m_trackPropagationGrid->EnableDragRowSize( true ); + m_trackPropagationGrid->SetRowLabelSize( 0 ); + m_trackPropagationGrid->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); + + // Label Appearance + + // Cell Defaults + m_trackPropagationGrid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP ); + fgSizer4->Add( m_trackPropagationGrid, 0, wxALL|wxEXPAND, 5 ); + + wxBoxSizer* bSizer9; + bSizer9 = new wxBoxSizer( wxHORIZONTAL ); + + m_addTrackPropogationLayer = new STD_BITMAP_BUTTON( sbSizer2->GetStaticBox(), wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); + bSizer9->Add( m_addTrackPropogationLayer, 0, wxBOTTOM|wxLEFT|wxTOP, 5 ); + + + bSizer9->Add( 20, 0, 1, 0, 5 ); + + m_deleteTrackPropogationLayer = new STD_BITMAP_BUTTON( sbSizer2->GetStaticBox(), wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); + bSizer9->Add( m_deleteTrackPropogationLayer, 0, wxBOTTOM|wxLEFT|wxTOP, 5 ); + + + fgSizer4->Add( bSizer9, 1, 0, 5 ); + + + sbSizer2->Add( fgSizer4, 1, wxEXPAND, 5 ); + + + m_panel3->SetSizer( sbSizer2 ); + m_panel3->Layout(); + sbSizer2->Fit( m_panel3 ); + m_panel4 = new wxPanel( m_splitter1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxStaticBoxSizer* sbSizer3; + sbSizer3 = new wxStaticBoxSizer( new wxStaticBox( m_panel4, wxID_ANY, _("Via Propagation") ), wxVERTICAL ); + + wxFlexGridSizer* fgSizer3; + fgSizer3 = new wxFlexGridSizer( 3, 1, 0, 0 ); + fgSizer3->AddGrowableCol( 0 ); + fgSizer3->AddGrowableRow( 1 ); + fgSizer3->SetFlexibleDirection( wxBOTH ); + fgSizer3->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + wxBoxSizer* bSizer8; + bSizer8 = new wxBoxSizer( wxHORIZONTAL ); + + m_viaPropagationSpeedLabel = new wxStaticText( sbSizer3->GetStaticBox(), wxID_ANY, _("Via Propagation Speed:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_viaPropagationSpeedLabel->Wrap( -1 ); + bSizer8->Add( m_viaPropagationSpeedLabel, 0, wxALL, 5 ); + + m_viaPropagationSpeed = new wxTextCtrl( sbSizer3->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer8->Add( m_viaPropagationSpeed, 0, wxALL, 5 ); + + m_viaPropSpeedUnits = new wxStaticText( sbSizer3->GetStaticBox(), wxID_ANY, _("ps/cm"), wxDefaultPosition, wxDefaultSize, 0 ); + m_viaPropSpeedUnits->Wrap( -1 ); + bSizer8->Add( m_viaPropSpeedUnits, 0, wxALL, 5 ); + + + bSizer8->Add( 50, 0, 1, wxEXPAND, 5 ); + + m_viaDelayOverridesLabel = new wxStaticText( sbSizer3->GetStaticBox(), wxID_ANY, _("Via Delay Overrides:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_viaDelayOverridesLabel->Wrap( -1 ); + bSizer8->Add( m_viaDelayOverridesLabel, 0, wxALL, 5 ); + + + fgSizer3->Add( bSizer8, 1, 0, 5 ); + + m_viaOverrides = new WX_GRID( sbSizer3->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + + // Grid + m_viaOverrides->CreateGrid( 0, 5 ); + m_viaOverrides->EnableEditing( true ); + m_viaOverrides->EnableGridLines( true ); + m_viaOverrides->EnableDragGridSize( false ); + m_viaOverrides->SetMargins( 0, 0 ); + + // Columns + m_viaOverrides->AutoSizeColumns(); + m_viaOverrides->EnableDragColMove( false ); + m_viaOverrides->EnableDragColSize( true ); + m_viaOverrides->SetColLabelValue( 0, _("Signal Layer From") ); + m_viaOverrides->SetColLabelValue( 1, _("Signal Layer To") ); + m_viaOverrides->SetColLabelValue( 2, _("Via Layer From") ); + m_viaOverrides->SetColLabelValue( 3, _("Via Layer To") ); + m_viaOverrides->SetColLabelValue( 4, _("Delay") ); + m_viaOverrides->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); + + // Rows + m_viaOverrides->EnableDragRowSize( true ); + m_viaOverrides->SetRowLabelSize( 0 ); + m_viaOverrides->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); + + // Label Appearance + + // Cell Defaults + m_viaOverrides->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP ); + fgSizer3->Add( m_viaOverrides, 0, wxALL|wxEXPAND, 5 ); + + wxBoxSizer* bSizer91; + bSizer91 = new wxBoxSizer( wxHORIZONTAL ); + + m_addViaPropagationOverride = new STD_BITMAP_BUTTON( sbSizer3->GetStaticBox(), wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); + bSizer91->Add( m_addViaPropagationOverride, 0, wxBOTTOM|wxLEFT, 5 ); + + + bSizer91->Add( 20, 0, 1, wxEXPAND, 5 ); + + m_removeViaPropagationOverride = new STD_BITMAP_BUTTON( sbSizer3->GetStaticBox(), wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); + bSizer91->Add( m_removeViaPropagationOverride, 0, wxBOTTOM|wxLEFT, 5 ); + + + fgSizer3->Add( bSizer91, 1, 0, 5 ); + + + sbSizer3->Add( fgSizer3, 1, wxEXPAND, 5 ); + + + m_panel4->SetSizer( sbSizer3 ); + m_panel4->Layout(); + sbSizer3->Fit( m_panel4 ); + m_splitter1->SplitHorizontally( m_panel3, m_panel4, 0 ); + fgSizer1->Add( m_splitter1, 1, wxEXPAND, 5 ); + + + this->SetSizer( fgSizer1 ); + this->Layout(); + + // Connect Events + m_name->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_SETUP_TUNING_PROFILE_INFO_BASE::OnProfileNameChanged ), NULL, this ); + m_type->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( PANEL_SETUP_TUNING_PROFILE_INFO_BASE::OnChangeProfileType ), NULL, this ); + m_addTrackPropogationLayer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_TUNING_PROFILE_INFO_BASE::OnAddTrackRow ), NULL, this ); + m_deleteTrackPropogationLayer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_TUNING_PROFILE_INFO_BASE::OnRemoveTrackRow ), NULL, this ); + m_addViaPropagationOverride->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_TUNING_PROFILE_INFO_BASE::OnAddViaOverride ), NULL, this ); + m_removeViaPropagationOverride->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_TUNING_PROFILE_INFO_BASE::OnRemoveViaOverride ), NULL, this ); +} + +PANEL_SETUP_TUNING_PROFILE_INFO_BASE::~PANEL_SETUP_TUNING_PROFILE_INFO_BASE() +{ +} diff --git a/pcbnew/dialogs/panel_setup_tuning_profile_info_base.fbp b/pcbnew/dialogs/panel_setup_tuning_profile_info_base.fbp new file mode 100644 index 0000000000..b6aab0116f --- /dev/null +++ b/pcbnew/dialogs/panel_setup_tuning_profile_info_base.fbp @@ -0,0 +1,1791 @@ + + + + + C++ + ; + 0 + connect + none + + + 0 + 1 + res + UTF-8 + panel_setup_tuning_profile_info_base + 6000 + 1 + 1 + UI + PANEL_SETUP_TUNING_PROFILE_INFO_BASE + . + 0 + source_name + 1 + 0 + source_name + + 1 + 1 + 1 + 0 + 0 + + 0 + wxAUI_MGR_DEFAULT + + + 1 + 0 + 1 + impl_virtual + + + 0 + wxID_ANY + + + PANEL_SETUP_TUNING_PROFILE_INFO_BASE + + 719,506 + ; ; forward_declare + + 0 + + + wxTAB_TRAVERSAL + + 1 + wxBOTH + 0 + 2 + 0 + + fgSizer1 + wxFLEX_GROWMODE_ALL + none + 3 + 0 + + 5 + wxEXPAND + 1 + + 9 + wxHORIZONTAL + 2,5 + + 0 + + fgSizer2 + wxFLEX_GROWMODE_ALL + none + 1 + 0 + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Name: + 0 + + 0 + + + 0 + + 1 + m_nameLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + + 0 + + 1 + m_name + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + OnProfileNameChanged + + + + 5 + wxEXPAND + 1 + + 0 + protected + 0 + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Type: + 0 + + 0 + + + 0 + + 1 + m_typeLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + "Single" "Differential" + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_type + 1 + + + protected + 1 + + Resizable + 0 + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnChangeProfileType + + + + 5 + wxEXPAND + 1 + + 0 + protected + 0 + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Target Impedance: + 0 + + 0 + + + 0 + + 1 + m_targetImpedanceLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 15 + + 0 + + 1 + m_targetImpedance + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + 5 + wxALL|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + ohms + 0 + + 0 + + + 0 + + 1 + m_ohmsLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + + + 5 + wxEXPAND + 1 + + + wxBOTH + 0 + + 0 + + gbSizer1 + wxFLEX_GROWMODE_SPECIFIED + none + 0 + + 5 + 1 + 0 + wxALL + 0 + 1 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Generate Net Class DRC Rules + + 0 + + + 0 + + 1 + m_enableDrcGeneration + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + 1 + 1 + wxALL + 0 + 1 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Enable Time Domain Tuning + + 0 + + + 0 + + 1 + m_enableDelayTuning + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + 2 + 0 + wxEXPAND | wxALL + 1 + 1 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_staticline1 + 1 + + + protected + 1 + + Resizable + 1 + + wxLI_HORIZONTAL + ; ; forward_declare + 0 + + + + + + + + + + 5 + wxEXPAND + 1 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + + 0 + + 1 + m_splitter1 + 1 + + + protected + 1 + + Resizable + 0.0 + 0 + -1 + 1 + + wxSPLIT_HORIZONTAL + wxSP_3DSASH + ; ; forward_declare + 0 + + + + + + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_panel3 + 1 + + + protected + 1 + + Resizable + 1 + + ; ; forward_declare + 0 + + + + wxTAB_TRAVERSAL + + wxID_ANY + Track Propagation + + sbSizer2 + wxVERTICAL + 1 + none + + 5 + wxEXPAND + 1 + + 1 + wxBOTH + 0 + 0 + 0 + + fgSizer4 + wxFLEX_GROWMODE_SPECIFIED + none + 0 + 0 + + 5 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + 1 + 0 + + + + 1 + + + wxALIGN_LEFT + + wxALIGN_TOP + 0 + 1 + wxALIGN_CENTER + + "Signal Layer" "Top Reference" "Bottom Reference" "Track Width" "Diff Pair Gap" "Unit Delay" + wxALIGN_CENTER + 6 + + + 0 + 0 + Dock + 0 + Left + 0 + 0 + 1 + 0 + 1 + 1 + 1 + + 1 + + + 1 + 0 + 0 + wxID_ANY + + + + 0 + 0 + + 0 + + + 0 + + 1 + m_trackPropagationGrid + 1 + + + protected + 1 + + Resizable + wxALIGN_CENTER + 0 + + wxALIGN_CENTER + + 0 + 1 + + WX_GRID; widgets/wx_grid.h; forward_declare + 0 + + + + + + + + 5 + + 1 + + + bSizer9 + wxHORIZONTAL + none + + 5 + wxBOTTOM|wxLEFT|wxTOP + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + MyButton + + 0 + + 0 + + + 0 + + 1 + m_addTrackPropogationLayer + 1 + + + protected + 1 + + + + Resizable + 1 + + + STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnAddTrackRow + + + + 5 + + 1 + + 0 + protected + 20 + + + + 5 + wxBOTTOM|wxLEFT|wxTOP + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + MyButton + + 0 + + 0 + + + 0 + + 1 + m_deleteTrackPropogationLayer + 1 + + + protected + 1 + + + + Resizable + 1 + + + STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnRemoveTrackRow + + + + + + + + + + + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_panel4 + 1 + + + protected + 1 + + Resizable + 1 + + ; ; forward_declare + 0 + + + + wxTAB_TRAVERSAL + + wxID_ANY + Via Propagation + + sbSizer3 + wxVERTICAL + 1 + none + + 5 + wxEXPAND + 1 + + 1 + wxBOTH + 0 + 1 + 0 + + fgSizer3 + wxFLEX_GROWMODE_SPECIFIED + none + 3 + 0 + + 5 + + 1 + + + bSizer8 + wxHORIZONTAL + none + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Via Propagation Speed: + 0 + + 0 + + + 0 + + 1 + m_viaPropagationSpeedLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + + 0 + + 1 + m_viaPropagationSpeed + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + ps/cm + 0 + + 0 + + + 0 + + 1 + m_viaPropSpeedUnits + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxEXPAND + 1 + + 0 + protected + 50 + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Via Delay Overrides: + 0 + + 0 + + + 0 + + 1 + m_viaDelayOverridesLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + + + 5 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + 1 + 0 + + + + 1 + + + wxALIGN_LEFT + + wxALIGN_TOP + 0 + 1 + wxALIGN_CENTER + + "Signal Layer From" "Signal Layer To" "Via Layer From" "Via Layer To" "Delay" + wxALIGN_CENTER + 5 + + + 1 + 0 + Dock + 0 + Left + 0 + 0 + 1 + 0 + 1 + 1 + 1 + + 1 + + + 1 + 0 + 0 + wxID_ANY + + + + 0 + 0 + + 0 + + + 0 + + 1 + m_viaOverrides + 1 + + + protected + 1 + + Resizable + wxALIGN_CENTER + 0 + + wxALIGN_CENTER + + 0 + 1 + + WX_GRID; widgets/wx_grid.h; forward_declare + 0 + + + + + + + + 5 + + 1 + + + bSizer91 + wxHORIZONTAL + none + + 5 + wxBOTTOM|wxLEFT + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + MyButton + + 0 + + 0 + + + 0 + + 1 + m_addViaPropagationOverride + 1 + + + protected + 1 + + + + Resizable + 1 + + + STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnAddViaOverride + + + + 5 + wxEXPAND + 1 + + 0 + protected + 20 + + + + 5 + wxBOTTOM|wxLEFT + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + MyButton + + 0 + + 0 + + + 0 + + 1 + m_removeViaPropagationOverride + 1 + + + protected + 1 + + + + Resizable + 1 + + + STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnRemoveViaOverride + + + + + + + + + + + + + + + diff --git a/pcbnew/dialogs/panel_setup_tuning_profile_info_base.h b/pcbnew/dialogs/panel_setup_tuning_profile_info_base.h new file mode 100644 index 0000000000..5a10f3dd29 --- /dev/null +++ b/pcbnew/dialogs/panel_setup_tuning_profile_info_base.h @@ -0,0 +1,94 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include +#include +class STD_BITMAP_BUTTON; +class WX_GRID; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +/// Class PANEL_SETUP_TUNING_PROFILE_INFO_BASE +/////////////////////////////////////////////////////////////////////////////// +class PANEL_SETUP_TUNING_PROFILE_INFO_BASE : public wxPanel +{ + private: + + protected: + wxStaticText* m_nameLabel; + wxTextCtrl* m_name; + wxStaticText* m_typeLabel; + wxChoice* m_type; + wxStaticText* m_targetImpedanceLabel; + wxTextCtrl* m_targetImpedance; + wxStaticText* m_ohmsLabel; + wxCheckBox* m_enableDrcGeneration; + wxCheckBox* m_enableDelayTuning; + wxStaticLine* m_staticline1; + wxSplitterWindow* m_splitter1; + wxPanel* m_panel3; + WX_GRID* m_trackPropagationGrid; + STD_BITMAP_BUTTON* m_addTrackPropogationLayer; + STD_BITMAP_BUTTON* m_deleteTrackPropogationLayer; + wxPanel* m_panel4; + wxStaticText* m_viaPropagationSpeedLabel; + wxTextCtrl* m_viaPropagationSpeed; + wxStaticText* m_viaPropSpeedUnits; + wxStaticText* m_viaDelayOverridesLabel; + WX_GRID* m_viaOverrides; + STD_BITMAP_BUTTON* m_addViaPropagationOverride; + STD_BITMAP_BUTTON* m_removeViaPropagationOverride; + + // Virtual event handlers, override them in your derived class + virtual void OnProfileNameChanged( wxCommandEvent& event ) { event.Skip(); } + virtual void OnChangeProfileType( wxCommandEvent& event ) { event.Skip(); } + virtual void OnAddTrackRow( wxCommandEvent& event ) { event.Skip(); } + virtual void OnRemoveTrackRow( wxCommandEvent& event ) { event.Skip(); } + virtual void OnAddViaOverride( wxCommandEvent& event ) { event.Skip(); } + virtual void OnRemoveViaOverride( wxCommandEvent& event ) { event.Skip(); } + + + public: + + PANEL_SETUP_TUNING_PROFILE_INFO_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 719,506 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString ); + + ~PANEL_SETUP_TUNING_PROFILE_INFO_BASE(); + + void m_splitter1OnIdle( wxIdleEvent& ) + { + m_splitter1->SetSashPosition( 0 ); + m_splitter1->Disconnect( wxEVT_IDLE, wxIdleEventHandler( PANEL_SETUP_TUNING_PROFILE_INFO_BASE::m_splitter1OnIdle ), NULL, this ); + } + +}; + diff --git a/pcbnew/dialogs/panel_setup_tuning_profiles.cpp b/pcbnew/dialogs/panel_setup_tuning_profiles.cpp new file mode 100644 index 0000000000..dacd5c9d89 --- /dev/null +++ b/pcbnew/dialogs/panel_setup_tuning_profiles.cpp @@ -0,0 +1,200 @@ +/* +* This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright The KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +PANEL_SETUP_TUNING_PROFILES::PANEL_SETUP_TUNING_PROFILES( wxWindow* aParentWindow, PCB_EDIT_FRAME* aFrame, + BOARD* aBoard, + std::shared_ptr aTimeDomainParameters ) : + PANEL_SETUP_TUNING_PROFILES_BASE( aParentWindow ), + m_tuningProfileParameters( std::move( aTimeDomainParameters ) ), + m_dlg( dynamic_cast( aParentWindow ) ), + m_frame( aFrame ), + m_board( aFrame->GetBoard() ), + m_unitsProvider( std::make_unique( pcbIUScale, m_frame->GetUserUnits() ) ) +{ + Freeze(); + + m_addTuningProfileButton->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) ); + m_removeTuningProfileButton->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) ); + + Thaw(); +} + + +PANEL_SETUP_TUNING_PROFILES::~PANEL_SETUP_TUNING_PROFILES() +{ +} + + +bool PANEL_SETUP_TUNING_PROFILES::TransferDataToWindow() +{ + m_tuningProfiles->DeleteAllPages(); + SyncCopperLayers( m_board->GetCopperLayerCount() ); + + const std::vector& tuningProfiles = m_tuningProfileParameters->GetTuningProfiles(); + + for( const TUNING_PROFILE& profile : tuningProfiles ) + { + PANEL_SETUP_TUNING_PROFILE_INFO* panel = new PANEL_SETUP_TUNING_PROFILE_INFO( m_tuningProfiles, this ); + m_tuningProfiles->AddPage( panel, profile.m_ProfileName, true ); + panel->LoadProfile( profile ); + } + + return true; +} + + +bool PANEL_SETUP_TUNING_PROFILES::TransferDataFromWindow() +{ + if( !Validate() ) + return false; + + m_tuningProfileParameters->ClearTuningProfiles(); + + for( size_t i = 0; i < m_tuningProfiles->GetPageCount(); ++i ) + { + PANEL_SETUP_TUNING_PROFILE_INFO* panel = + dynamic_cast( m_tuningProfiles->GetPage( i ) ); + TUNING_PROFILE profile = panel->GetProfile(); + m_tuningProfileParameters->AddTuningProfile( std::move( profile ) ); + } + + return true; +} + + +void PANEL_SETUP_TUNING_PROFILES::SyncCopperLayers( const int aNumCopperLayers ) +{ + m_prevLayerNamesToIDs = m_layerNamesToIDs; + m_copperLayerIdsToIndex.clear(); + m_copperIndexToLayerId.clear(); + m_layerNames.clear(); + m_layerNamesToIDs.clear(); + + int layerIdx = 0; + + for( const auto& layer : LSET::AllCuMask( aNumCopperLayers ).CuStack() ) + { + wxString layerName = m_board->GetLayerName( layer ); + m_layerNames.emplace_back( layerName ); + m_layerNamesToIDs[layerName] = layer; + m_copperLayerIdsToIndex[layer] = layerIdx; + m_copperIndexToLayerId[layerIdx] = layer; + ++layerIdx; + } + + if( m_prevLayerNamesToIDs.empty() ) + m_prevLayerNamesToIDs = m_layerNamesToIDs; + + for( size_t i = 0; i < m_tuningProfiles->GetPageCount(); ++i ) + { + PANEL_SETUP_TUNING_PROFILE_INFO* panel = + static_cast( m_tuningProfiles->GetPage( i ) ); + panel->UpdateLayerNames(); + } +} + + +void PANEL_SETUP_TUNING_PROFILES::OnAddTuningProfileClick( wxCommandEvent& event ) +{ + PANEL_SETUP_TUNING_PROFILE_INFO* panel = new PANEL_SETUP_TUNING_PROFILE_INFO( m_tuningProfiles, this ); + m_tuningProfiles->AddPage( panel, "Profile ", true ); +} + + +void PANEL_SETUP_TUNING_PROFILES::OnRemoveTuningProfileClick( wxCommandEvent& event ) +{ + if( const wxWindow* page = m_tuningProfiles->GetCurrentPage() ) + { + const size_t pageIdx = m_tuningProfiles->FindPage( page ); + m_tuningProfiles->RemovePage( pageIdx ); + } +} + + +bool PANEL_SETUP_TUNING_PROFILES::Validate() +{ + for( size_t i = 0; i < m_tuningProfiles->GetPageCount(); ++i ) + { + PANEL_SETUP_TUNING_PROFILE_INFO* panel = + static_cast( m_tuningProfiles->GetPage( i ) ); + + if( !panel->ValidateProfile( i ) ) + return false; + } + + return true; +} + + +void PANEL_SETUP_TUNING_PROFILES::UpdateProfileName( PANEL_SETUP_TUNING_PROFILE_INFO* panel, wxString newName ) const +{ + const int pageId = m_tuningProfiles->FindPage( panel ); + + if( pageId == wxNOT_FOUND ) + return; + + m_tuningProfiles->SetPageText( pageId, newName ); +} + + +void PANEL_SETUP_TUNING_PROFILES::ImportSettingsFrom( const std::shared_ptr& aOtherParameters ) +{ + std::shared_ptr savedSettings = m_tuningProfileParameters; + + m_tuningProfileParameters = aOtherParameters; + TransferDataToWindow(); + + m_tuningProfileParameters = std::move( savedSettings ); +} + + +std::vector PANEL_SETUP_TUNING_PROFILES::GetDelayProfileNames() const +{ + std::vector names; + + size_t profileCount = m_tuningProfiles->GetPageCount(); + + for( size_t i = 0; i < profileCount; ++i ) + { + const PANEL_SETUP_TUNING_PROFILE_INFO* profilePage = + dynamic_cast( m_tuningProfiles->GetPage( i ) ); + + if( wxString name = profilePage->GetProfileName(); name != wxEmptyString ) + names.push_back( name ); + } + + return names; +} diff --git a/pcbnew/dialogs/panel_setup_tuning_profiles.h b/pcbnew/dialogs/panel_setup_tuning_profiles.h new file mode 100644 index 0000000000..bf2c5a55d6 --- /dev/null +++ b/pcbnew/dialogs/panel_setup_tuning_profiles.h @@ -0,0 +1,102 @@ +/* +* This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright The KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef PANEL_SETUP_TUNING_PROFILES_H +#define PANEL_SETUP_TUNING_PROFILES_H + +#include + +#include +#include +#include +#include + +class PANEL_SETUP_TUNING_PROFILE_INFO; + +class PANEL_SETUP_TUNING_PROFILES final : public PANEL_SETUP_TUNING_PROFILES_BASE +{ +public: + friend class PANEL_SETUP_TUNING_PROFILE_INFO; + + PANEL_SETUP_TUNING_PROFILES( wxWindow* aParentWindow, PCB_EDIT_FRAME* aFrame, BOARD* aBoard, + std::shared_ptr aTimeDomainParameters ); + ~PANEL_SETUP_TUNING_PROFILES() override; + + /** + * Called when switching to this tab to make sure that any changes to the copper layer count + * made on the physical stackup page are reflected here + * @param aNumCopperLayers is the number of copper layers in the board + */ + void SyncCopperLayers( int aNumCopperLayers ); + + /// Load parameter data from the settings object + bool TransferDataToWindow() override; + + /// Save parameter data to the settings object + bool TransferDataFromWindow() override; + + /// Returns all configured tuning profile names. Used by the netclass setup panel + std::vector GetDelayProfileNames() const; + + /// Load configuration from the given settings object + void ImportSettingsFrom( const std::shared_ptr& aOtherParameters ); + + /// Adds a new tuning profile entry to the tuning profile grid + void OnAddTuningProfileClick( wxCommandEvent& event ) override; + + /// Removes a tuning profile entry from the tuning profile grid + void OnRemoveTuningProfileClick( wxCommandEvent& event ) override; + + /// Validates all data + bool Validate() override; + + /// Update the notebook display of the name for a given panel + void UpdateProfileName( PANEL_SETUP_TUNING_PROFILE_INFO* panel, wxString newName ) const; + +private: + /// The parameters object to load / save data from / to + std::shared_ptr m_tuningProfileParameters; + + /// The parent dialog + DIALOG_SHIM* m_dlg; + + /// The active edit frame + PCB_EDIT_FRAME* m_frame; + + /// The current board + BOARD* m_board; + + std::unique_ptr m_unitsProvider; + + // Layer / index lookups + std::map m_copperLayerIdsToIndex; + std::map m_copperIndexToLayerId; + std::vector m_layerNames; + + // We cache these in case the names change on the layers panel + std::map m_layerNamesToIDs; + std::map m_prevLayerNamesToIDs; +}; + + +#endif //PANEL_SETUP_TUNING_PROFILES_H diff --git a/pcbnew/dialogs/panel_setup_tuning_profiles_base.cpp b/pcbnew/dialogs/panel_setup_tuning_profiles_base.cpp new file mode 100644 index 0000000000..2c671194b6 --- /dev/null +++ b/pcbnew/dialogs/panel_setup_tuning_profiles_base.cpp @@ -0,0 +1,53 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "widgets/std_bitmap_button.h" + +#include "panel_setup_tuning_profiles_base.h" + +/////////////////////////////////////////////////////////////////////////// + +PANEL_SETUP_TUNING_PROFILES_BASE::PANEL_SETUP_TUNING_PROFILES_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name ) +{ + wxFlexGridSizer* fgSizer1; + fgSizer1 = new wxFlexGridSizer( 2, 1, 0, 0 ); + fgSizer1->AddGrowableCol( 0 ); + fgSizer1->AddGrowableRow( 0 ); + fgSizer1->SetFlexibleDirection( wxBOTH ); + fgSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_ALL ); + + m_tuningProfiles = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + + fgSizer1->Add( m_tuningProfiles, 1, wxEXPAND | wxALL, 5 ); + + wxBoxSizer* bSizer91; + bSizer91 = new wxBoxSizer( wxHORIZONTAL ); + + m_addTuningProfileButton = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); + bSizer91->Add( m_addTuningProfileButton, 0, wxBOTTOM|wxLEFT, 5 ); + + + bSizer91->Add( 20, 0, 1, wxEXPAND, 5 ); + + m_removeTuningProfileButton = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); + bSizer91->Add( m_removeTuningProfileButton, 0, wxBOTTOM|wxLEFT, 5 ); + + + fgSizer1->Add( bSizer91, 1, wxTOP, 5 ); + + + this->SetSizer( fgSizer1 ); + this->Layout(); + + // Connect Events + m_addTuningProfileButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_TUNING_PROFILES_BASE::OnAddTuningProfileClick ), NULL, this ); + m_removeTuningProfileButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_TUNING_PROFILES_BASE::OnRemoveTuningProfileClick ), NULL, this ); +} + +PANEL_SETUP_TUNING_PROFILES_BASE::~PANEL_SETUP_TUNING_PROFILES_BASE() +{ +} diff --git a/pcbnew/dialogs/panel_setup_tuning_profiles_base.fbp b/pcbnew/dialogs/panel_setup_tuning_profiles_base.fbp new file mode 100644 index 0000000000..c25d833a1c --- /dev/null +++ b/pcbnew/dialogs/panel_setup_tuning_profiles_base.fbp @@ -0,0 +1,304 @@ + + + + + C++ + ; + 0 + connect + none + + + 0 + 1 + res + UTF-8 + panel_setup_tuning_profiles_base + 6000 + 1 + 1 + UI + PANEL_SETUP_TUNING_PROFILE_INFO_BASE + . + 0 + source_name + 1 + 0 + source_name + + 1 + 1 + 1 + 0 + 0 + + 0 + wxAUI_MGR_DEFAULT + + + 1 + 0 + 1 + impl_virtual + + + 0 + wxID_ANY + + + PANEL_SETUP_TUNING_PROFILES_BASE + + 719,506 + ; ; forward_declare + + 0 + + + wxTAB_TRAVERSAL + + 1 + wxBOTH + 0 + 0 + 0 + + fgSizer1 + wxFLEX_GROWMODE_ALL + none + 2 + 0 + + 5 + wxEXPAND | wxALL + 1 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_tuningProfiles + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + + + + 5 + wxTOP + 1 + + + bSizer91 + wxHORIZONTAL + none + + 5 + wxBOTTOM|wxLEFT + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + MyButton + + 0 + + 0 + + + 0 + + 1 + m_addTuningProfileButton + 1 + + + protected + 1 + + + + Resizable + 1 + + + STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnAddTuningProfileClick + + + + 5 + wxEXPAND + 1 + + 0 + protected + 20 + + + + 5 + wxBOTTOM|wxLEFT + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + MyButton + + 0 + + 0 + + + 0 + + 1 + m_removeTuningProfileButton + 1 + + + protected + 1 + + + + Resizable + 1 + + + STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnRemoveTuningProfileClick + + + + + + + + diff --git a/pcbnew/dialogs/panel_setup_tuning_profiles_base.h b/pcbnew/dialogs/panel_setup_tuning_profiles_base.h new file mode 100644 index 0000000000..530df9618c --- /dev/null +++ b/pcbnew/dialogs/panel_setup_tuning_profiles_base.h @@ -0,0 +1,55 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include +#include +class STD_BITMAP_BUTTON; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +/// Class PANEL_SETUP_TUNING_PROFILES_BASE +/////////////////////////////////////////////////////////////////////////////// +class PANEL_SETUP_TUNING_PROFILES_BASE : public wxPanel +{ + private: + + protected: + wxNotebook* m_tuningProfiles; + STD_BITMAP_BUTTON* m_addTuningProfileButton; + STD_BITMAP_BUTTON* m_removeTuningProfileButton; + + // Virtual event handlers, override them in your derived class + virtual void OnAddTuningProfileClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnRemoveTuningProfileClick( wxCommandEvent& event ) { event.Skip(); } + + + public: + + PANEL_SETUP_TUNING_PROFILES_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 719,506 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString ); + + ~PANEL_SETUP_TUNING_PROFILES_BASE(); + +}; + diff --git a/pcbnew/drc/drc_engine.cpp b/pcbnew/drc/drc_engine.cpp index 5fed91caa7..c77414cece 100644 --- a/pcbnew/drc/drc_engine.cpp +++ b/pcbnew/drc/drc_engine.cpp @@ -44,6 +44,8 @@ #include #include #include +#include +#include // wxListBox's performance degrades horrifically with very large datasets. It's not clear @@ -436,8 +438,121 @@ void DRC_ENGINE::loadImplicitRules() for( std::shared_ptr& ncRule : netclassItemSpecificRules ) addRule( ncRule ); - // 3) keepout area rules + // 4) tuning profile rules + auto addTuningSingleRule = [this, &bds]( const DELAY_PROFILE_TRACK_PROPAGATION_ENTRY& aLayerEntry, + const wxString& aProfileName, const wxString& aNetclassName ) + { + if( aLayerEntry.GetWidth() <= 0 ) + return; + std::shared_ptr tuningRule = std::make_shared(); + tuningRule->m_Name = wxString::Format( _( "tuning profile '%s'" ), aProfileName ); + tuningRule->m_Implicit = true; + + wxString expr = wxString::Format( wxT( "A.hasExactNetclass('%s') && A.Layer == '%s'" ), aNetclassName, + LSET::Name( aLayerEntry.GetSignalLayer() ) ); + tuningRule->m_Condition = new DRC_RULE_CONDITION( expr ); + + DRC_CONSTRAINT constraint( TRACK_WIDTH_CONSTRAINT ); + constraint.Value().SetMin( bds.m_TrackMinWidth ); + constraint.Value().SetOpt( aLayerEntry.GetWidth() ); + tuningRule->AddConstraint( constraint ); + + addRule( tuningRule ); + }; + + auto addTuningDifferentialRules = [this, &bds]( const DELAY_PROFILE_TRACK_PROPAGATION_ENTRY& aLayerEntry, + const wxString& aProfileName, const NETCLASS* aNetclass ) + { + if( aLayerEntry.GetWidth() <= 0 || aLayerEntry.GetDiffPairGap() <= 0 ) + return; + + std::shared_ptr tuningRule = std::make_shared(); + tuningRule->m_Name = wxString::Format( _( "tuning profile '%s'" ), aProfileName ); + tuningRule->m_Implicit = true; + + wxString expr = wxString::Format( wxT( "A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ), + aNetclass->GetName(), LSET::Name( aLayerEntry.GetSignalLayer() ) ); + tuningRule->m_Condition = new DRC_RULE_CONDITION( expr ); + + DRC_CONSTRAINT constraint( TRACK_WIDTH_CONSTRAINT ); + constraint.Value().SetMin( bds.m_TrackMinWidth ); + constraint.Value().SetOpt( aLayerEntry.GetWidth() ); + tuningRule->AddConstraint( constraint ); + + addRule( tuningRule ); + + std::shared_ptr tuningRule2 = std::make_shared(); + tuningRule2->m_Name = wxString::Format( _( "tuning profile '%s'" ), aProfileName ); + tuningRule2->m_Implicit = true; + + const wxString expr2 = + wxString::Format( wxT( "A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ), + aNetclass->GetName(), LSET::Name( aLayerEntry.GetSignalLayer() ) ); + tuningRule2->m_Condition = new DRC_RULE_CONDITION( expr2 ); + + DRC_CONSTRAINT constraint2( DIFF_PAIR_GAP_CONSTRAINT ); + constraint2.Value().SetMin( bds.m_TrackMinWidth ); + constraint2.Value().SetOpt( aLayerEntry.GetDiffPairGap() ); + tuningRule2->AddConstraint( constraint2 ); + + addRule( tuningRule2 ); + + // A narrower diffpair gap overrides the netclass min clearance + if( aLayerEntry.GetDiffPairGap() < aNetclass->GetClearance() ) + { + std::shared_ptr diffPairClearanceRule = std::make_shared(); + diffPairClearanceRule->m_Name = wxString::Format( _( "tuning profile '%s'" ), aProfileName ); + diffPairClearanceRule->m_Implicit = true; + + expr = wxString::Format( wxT( "A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ), + aNetclass->GetName(), LSET::Name( aLayerEntry.GetSignalLayer() ) ); + diffPairClearanceRule->m_Condition = new DRC_RULE_CONDITION( expr ); + + DRC_CONSTRAINT min_clearanceConstraint( CLEARANCE_CONSTRAINT ); + min_clearanceConstraint.Value().SetMin( aLayerEntry.GetDiffPairGap() ); + diffPairClearanceRule->AddConstraint( min_clearanceConstraint ); + + addRule( diffPairClearanceRule ); + } + }; + + if( PROJECT* project = m_board->GetProject() ) + { + std::shared_ptr tuningParams = project->GetProjectFile().TuningProfileParameters(); + + auto addNetclassTuningProfileRules = + [&tuningParams, &addTuningSingleRule, &addTuningDifferentialRules]( NETCLASS* aNetclass ) + { + if( aNetclass->HasTuningProfile() ) + { + const wxString delayProfileName = aNetclass->GetTuningProfile(); + const TUNING_PROFILE& profile = tuningParams->GetTuningProfile( delayProfileName ); + + if( !profile.m_GenerateNetClassDRCRules ) + return; + + for( const DELAY_PROFILE_TRACK_PROPAGATION_ENTRY& layerEntry : profile.m_TrackPropagationEntries ) + { + if( layerEntry.GetWidth() <= 0 ) + continue; + + if( profile.m_Type == TUNING_PROFILE::PROFILE_TYPE::SINGLE ) + addTuningSingleRule( layerEntry, delayProfileName, aNetclass->GetName() ); + else + addTuningDifferentialRules( layerEntry, delayProfileName, aNetclass ); + } + } + }; + + for( const auto& [netclassName, netclass] : bds.m_NetSettings->GetNetclasses() ) + addNetclassTuningProfileRules( netclass.get() ); + + for( const auto& [netclassName, netclass] : bds.m_NetSettings->GetCompositeNetclasses() ) + addNetclassTuningProfileRules( netclass.get() ); + } + + // 5) keepout area rules std::vector keepoutZones; for( ZONE* zone : m_board->Zones() ) diff --git a/pcbnew/drc/drc_item.cpp b/pcbnew/drc/drc_item.cpp index 32a955a9cf..2b074858a5 100644 --- a/pcbnew/drc/drc_item.cpp +++ b/pcbnew/drc/drc_item.cpp @@ -298,84 +298,87 @@ DRC_ITEM DRC_ITEM::nonMirroredTextOnBackLayer( DRCE_NONMIRRORED_TEXT_ON_BACK_LAY _HKI( "Non-Mirrored text on back layer" ), wxT( "nonmirrored_text_on_back_layer" ) ); -std::vector> DRC_ITEM::allItemTypes( - { - DRC_ITEM::heading_electrical, - DRC_ITEM::shortingItems, - DRC_ITEM::tracksCrossing, - DRC_ITEM::clearance, - DRC_ITEM::creepage, - DRC_ITEM::viaDangling, - DRC_ITEM::trackDangling, - DRC_ITEM::starvedThermal, +DRC_ITEM DRC_ITEM::missingTuningProfile( DRCE_MISSING_TUNING_PROFILE, _HKI( "Missing tuning profile" ), + wxT( "missing_tuning_profile" ) ); - DRC_ITEM::heading_DFM, - DRC_ITEM::edgeClearance, - DRC_ITEM::holeClearance, - DRC_ITEM::holeNearHole, - DRC_ITEM::holesCoLocated, - DRC_ITEM::trackWidth, - DRC_ITEM::trackAngle, - DRC_ITEM::trackSegmentLength, - DRC_ITEM::annularWidth, - DRC_ITEM::drillTooSmall, - DRC_ITEM::microviaDrillTooSmall, - DRC_ITEM::courtyardsOverlap, - DRC_ITEM::missingCourtyard, - DRC_ITEM::malformedCourtyard, - DRC_ITEM::invalidOutline, - DRC_ITEM::copperSliver, - DRC_ITEM::solderMaskBridge, - DRC_ITEM::connectionWidth, +std::vector> DRC_ITEM::allItemTypes( { + DRC_ITEM::heading_electrical, + DRC_ITEM::shortingItems, + DRC_ITEM::tracksCrossing, + DRC_ITEM::clearance, + DRC_ITEM::creepage, + DRC_ITEM::viaDangling, + DRC_ITEM::trackDangling, + DRC_ITEM::starvedThermal, - DRC_ITEM::heading_schematic_parity, - DRC_ITEM::duplicateFootprints, - DRC_ITEM::missingFootprint, - DRC_ITEM::extraFootprint, - DRC_ITEM::schematicParity, - DRC_ITEM::footprintFilters, - DRC_ITEM::netConflict, - DRC_ITEM::unconnectedItems, + DRC_ITEM::heading_DFM, + DRC_ITEM::edgeClearance, + DRC_ITEM::holeClearance, + DRC_ITEM::holeNearHole, + DRC_ITEM::holesCoLocated, + DRC_ITEM::trackWidth, + DRC_ITEM::trackAngle, + DRC_ITEM::trackSegmentLength, + DRC_ITEM::annularWidth, + DRC_ITEM::drillTooSmall, + DRC_ITEM::microviaDrillTooSmall, + DRC_ITEM::courtyardsOverlap, + DRC_ITEM::missingCourtyard, + DRC_ITEM::malformedCourtyard, + DRC_ITEM::invalidOutline, + DRC_ITEM::copperSliver, + DRC_ITEM::solderMaskBridge, + DRC_ITEM::connectionWidth, - DRC_ITEM::heading_signal_integrity, - DRC_ITEM::lengthOutOfRange, - DRC_ITEM::skewOutOfRange, - DRC_ITEM::viaCountOutOfRange, - DRC_ITEM::diffPairGapOutOfRange, - DRC_ITEM::diffPairUncoupledLengthTooLong, + DRC_ITEM::heading_schematic_parity, + DRC_ITEM::duplicateFootprints, + DRC_ITEM::missingFootprint, + DRC_ITEM::extraFootprint, + DRC_ITEM::schematicParity, + DRC_ITEM::footprintFilters, + DRC_ITEM::netConflict, + DRC_ITEM::unconnectedItems, - DRC_ITEM::heading_readability, - DRC_ITEM::silkOverlaps, - DRC_ITEM::silkMaskClearance, - DRC_ITEM::silkEdgeClearance, - DRC_ITEM::textHeightOutOfRange, - DRC_ITEM::textThicknessOutOfRange, - DRC_ITEM::mirroredTextOnFrontLayer, - DRC_ITEM::nonMirroredTextOnBackLayer, + DRC_ITEM::heading_signal_integrity, + DRC_ITEM::lengthOutOfRange, + DRC_ITEM::skewOutOfRange, + DRC_ITEM::viaCountOutOfRange, + DRC_ITEM::diffPairGapOutOfRange, + DRC_ITEM::diffPairUncoupledLengthTooLong, - DRC_ITEM::heading_misc, - DRC_ITEM::itemsNotAllowed, - DRC_ITEM::textOnEdgeCuts, - DRC_ITEM::zonesIntersect, - DRC_ITEM::isolatedCopper, - DRC_ITEM::footprint, - DRC_ITEM::padstack, - DRC_ITEM::pthInsideCourtyard, - DRC_ITEM::npthInsideCourtyard, - DRC_ITEM::itemOnDisabledLayer, - DRC_ITEM::unresolvedVariable, - DRC_ITEM::footprintTypeMismatch, - DRC_ITEM::libFootprintIssues, - DRC_ITEM::libFootprintMismatch, - DRC_ITEM::footprintTHPadhasNoHole, + DRC_ITEM::heading_readability, + DRC_ITEM::silkOverlaps, + DRC_ITEM::silkMaskClearance, + DRC_ITEM::silkEdgeClearance, + DRC_ITEM::textHeightOutOfRange, + DRC_ITEM::textThicknessOutOfRange, + DRC_ITEM::mirroredTextOnFrontLayer, + DRC_ITEM::nonMirroredTextOnBackLayer, - // DRC_ITEM types with no user-editable severities - // NOTE: this MUST be the last grouping in the list! - DRC_ITEM::heading_internal, - DRC_ITEM::padstackInvalid, - DRC_ITEM::genericError, - DRC_ITEM::genericWarning, - } ); + DRC_ITEM::heading_misc, + DRC_ITEM::itemsNotAllowed, + DRC_ITEM::textOnEdgeCuts, + DRC_ITEM::zonesIntersect, + DRC_ITEM::isolatedCopper, + DRC_ITEM::footprint, + DRC_ITEM::padstack, + DRC_ITEM::pthInsideCourtyard, + DRC_ITEM::npthInsideCourtyard, + DRC_ITEM::itemOnDisabledLayer, + DRC_ITEM::unresolvedVariable, + DRC_ITEM::footprintTypeMismatch, + DRC_ITEM::libFootprintIssues, + DRC_ITEM::libFootprintMismatch, + DRC_ITEM::footprintTHPadhasNoHole, + DRC_ITEM::missingTuningProfile, + + // DRC_ITEM types with no user-editable severities + // NOTE: this MUST be the last grouping in the list! + DRC_ITEM::heading_internal, + DRC_ITEM::padstackInvalid, + DRC_ITEM::genericError, + DRC_ITEM::genericWarning, +} ); std::shared_ptr DRC_ITEM::Create( int aErrorCode ) @@ -444,6 +447,7 @@ std::shared_ptr DRC_ITEM::Create( int aErrorCode ) case DRCE_PAD_TH_WITH_NO_HOLE: return std::make_shared( footprintTHPadhasNoHole ); case DRCE_MIRRORED_TEXT_ON_FRONT_LAYER: return std::make_shared( mirroredTextOnFrontLayer ); case DRCE_NONMIRRORED_TEXT_ON_BACK_LAYER: return std::make_shared( nonMirroredTextOnBackLayer ); + case DRCE_MISSING_TUNING_PROFILE: return std::make_shared( missingTuningProfile ); default: wxFAIL_MSG( wxT( "Unknown DRC error code" ) ); return nullptr; diff --git a/pcbnew/drc/drc_item.h b/pcbnew/drc/drc_item.h index 41f14ac477..5fd10eeb0d 100644 --- a/pcbnew/drc/drc_item.h +++ b/pcbnew/drc/drc_item.h @@ -34,7 +34,8 @@ class DRC_TEST_PROVIDER; class PCB_MARKER; class BOARD; -enum PCB_DRC_CODE { +enum PCB_DRC_CODE +{ DRCE_FIRST = 1, DRCE_UNCONNECTED_ITEMS = DRCE_FIRST, // items are unconnected DRCE_SHORTING_ITEMS, // items short two nets but are not a net-tie @@ -68,37 +69,37 @@ enum PCB_DRC_CODE { // (not convertible to a closed polygon with holes) DRCE_PTH_IN_COURTYARD, DRCE_NPTH_IN_COURTYARD, - DRCE_DISABLED_LAYER_ITEM, // item on a disabled layer - DRCE_INVALID_OUTLINE, // invalid board outline + DRCE_DISABLED_LAYER_ITEM, // item on a disabled layer + DRCE_INVALID_OUTLINE, // invalid board outline - DRCE_MISSING_FOOTPRINT, // footprint not found for netlist item - DRCE_DUPLICATE_FOOTPRINT, // more than one footprints found for netlist item - DRCE_EXTRA_FOOTPRINT, // netlist item not found for footprint - DRCE_NET_CONFLICT, // pad net doesn't match netlist - DRCE_SCHEMATIC_PARITY, // footprint attributes don't match symbol attributes - DRCE_FOOTPRINT_FILTERS, // footprint doesn't match symbol's footprint filters + DRCE_MISSING_FOOTPRINT, // footprint not found for netlist item + DRCE_DUPLICATE_FOOTPRINT, // more than one footprints found for netlist item + DRCE_EXTRA_FOOTPRINT, // netlist item not found for footprint + DRCE_NET_CONFLICT, // pad net doesn't match netlist + DRCE_SCHEMATIC_PARITY, // footprint attributes don't match symbol attributes + DRCE_FOOTPRINT_FILTERS, // footprint doesn't match symbol's footprint filters - DRCE_FOOTPRINT_TYPE_MISMATCH, // footprint attribute does not match actual pads - DRCE_LIB_FOOTPRINT_ISSUES, // footprint not found in active libraries - DRCE_LIB_FOOTPRINT_MISMATCH, // footprint does not match the current library - DRCE_PAD_TH_WITH_NO_HOLE, // footprint has Plated Through-Hole with no hole - DRCE_FOOTPRINT, // error in footprint definition + DRCE_FOOTPRINT_TYPE_MISMATCH, // footprint attribute does not match actual pads + DRCE_LIB_FOOTPRINT_ISSUES, // footprint not found in active libraries + DRCE_LIB_FOOTPRINT_MISMATCH, // footprint does not match the current library + DRCE_PAD_TH_WITH_NO_HOLE, // footprint has Plated Through-Hole with no hole + DRCE_FOOTPRINT, // error in footprint definition DRCE_UNRESOLVED_VARIABLE, - DRCE_ASSERTION_FAILURE, // user-defined (custom rule) assertion - DRCE_GENERIC_WARNING, // generic warning - DRCE_GENERIC_ERROR, // generic error + DRCE_ASSERTION_FAILURE, // user-defined (custom rule) assertion + DRCE_GENERIC_WARNING, // generic warning + DRCE_GENERIC_ERROR, // generic error DRCE_COPPER_SLIVER, - DRCE_SOLDERMASK_BRIDGE, // failure to maintain min soldermask web thickness - // between copper items with different nets + DRCE_SOLDERMASK_BRIDGE, // failure to maintain min soldermask web thickness + // between copper items with different nets - DRCE_SILK_MASK_CLEARANCE, // silkscreen clipped by mask (potentially leaving it - // over pads, exposed copper, etc.) + DRCE_SILK_MASK_CLEARANCE, // silkscreen clipped by mask (potentially leaving it + // over pads, exposed copper, etc.) DRCE_SILK_EDGE_CLEARANCE, DRCE_TEXT_HEIGHT, DRCE_TEXT_THICKNESS, - DRCE_OVERLAPPING_SILK, // silk-to-silk or silk-to-other clearance error + DRCE_OVERLAPPING_SILK, // silk-to-silk or silk-to-other clearance error DRCE_LENGTH_OUT_OF_RANGE, DRCE_SKEW_OUT_OF_RANGE, @@ -109,7 +110,9 @@ enum PCB_DRC_CODE { DRCE_MIRRORED_TEXT_ON_FRONT_LAYER, DRCE_NONMIRRORED_TEXT_ON_BACK_LAYER, - DRCE_LAST = DRCE_NONMIRRORED_TEXT_ON_BACK_LAYER + DRCE_MISSING_TUNING_PROFILE, // Tuning profile used in net class is not defined + + DRCE_LAST = DRCE_MISSING_TUNING_PROFILE }; @@ -242,6 +245,7 @@ private: static DRC_ITEM footprintTHPadhasNoHole; static DRC_ITEM mirroredTextOnFrontLayer; static DRC_ITEM nonMirroredTextOnBackLayer; + static DRC_ITEM missingTuningProfile; private: DRC_RULE* m_violatingRule = nullptr; diff --git a/pcbnew/drc/drc_test_provider_misc.cpp b/pcbnew/drc/drc_test_provider_misc.cpp index e6850ac599..def8289910 100644 --- a/pcbnew/drc/drc_test_provider_misc.cpp +++ b/pcbnew/drc/drc_test_provider_misc.cpp @@ -36,6 +36,8 @@ #include #include +#include +#include /* Miscellaneous tests: @@ -46,6 +48,7 @@ - DRCE_ASSERTION_FAILURE, ///< user-defined assertions - DRCE_GENERIC_WARNING ///< user-defined warnings - DRCE_GENERIC_ERROR ///< user-defined errors + - DRCE_MISSING_TUNING_PROFILES ///< tuning profile for netc lass not defined */ static void findClosestOutlineGap( BOARD* aBoard, PCB_SHAPE*& aItemA, PCB_SHAPE*& aItemB, @@ -126,6 +129,7 @@ private: void testDisabledLayers(); void testTextVars(); void testAssertions(); + void testMissingTuningProfiles(); BOARD* m_board; }; @@ -518,6 +522,43 @@ void DRC_TEST_PROVIDER_MISC::testTextVars() } +void DRC_TEST_PROVIDER_MISC::testMissingTuningProfiles() +{ + if( !m_board->GetProject() ) + return; + + std::shared_ptr netSettings = m_board->GetProject()->GetProjectFile().NetSettings(); + const std::shared_ptr tuningProfiles = + m_board->GetProject()->GetProjectFile().TuningProfileParameters(); + + std::set profileNames; + std::ranges::for_each( tuningProfiles->GetTuningProfiles(), + [&profileNames]( const TUNING_PROFILE& tuningProfile ) + { + if( const wxString name = tuningProfile.m_ProfileName; name != wxEmptyString ) + profileNames.insert( name ); + } ); + + for( const auto& [name, netclass] : netSettings->GetNetclasses() ) + { + if( m_drcEngine->IsErrorLimitExceeded( DRCE_MISSING_TUNING_PROFILE ) ) + return; + + const wxString profileName = netclass->GetTuningProfile(); + + if( netclass->HasTuningProfile() && !profileNames.contains( profileName ) ) + { + auto drcItem = DRC_ITEM::Create( DRCE_MISSING_TUNING_PROFILE ); + wxString errMsg = wxString::Format( "%s (Net Class: %s, Tuning Profile: %s)", drcItem->GetErrorText(), name, + profileName ); + drcItem->SetErrorMessage( errMsg ); + + reportViolation( drcItem, VECTOR2I(), UNDEFINED_LAYER ); + } + } +} + + bool DRC_TEST_PROVIDER_MISC::Run() { m_board = m_drcEngine->GetBoard(); @@ -556,6 +597,14 @@ bool DRC_TEST_PROVIDER_MISC::Run() testAssertions(); } + if( !m_drcEngine->IsErrorLimitExceeded( DRCE_MISSING_TUNING_PROFILE ) ) + { + if( !reportPhase( _( "Checking for missing tuning profiles..." ) ) ) + return false; // DRC cancelled + + testMissingTuningProfiles(); + } + return !m_drcEngine->IsCancelled(); } diff --git a/pcbnew/files.cpp b/pcbnew/files.cpp index 88775334df..fe9a984bd9 100644 --- a/pcbnew/files.cpp +++ b/pcbnew/files.cpp @@ -952,7 +952,7 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector& aFileSet, in GetBoard()->GetComponentClassManager().RebuildRequiredCaches(); // Initialise time domain tuning caches - GetBoard()->GetLengthCalculation()->SynchronizeTimeDomainProperties(); + GetBoard()->GetLengthCalculation()->SynchronizeTuningProfileProperties(); // Syncs the UI (appearance panel, etc) with the loaded board and project OnBoardLoaded(); diff --git a/pcbnew/length_delay_calculation/length_delay_calculation.cpp b/pcbnew/length_delay_calculation/length_delay_calculation.cpp index c55a21751d..f9fa838554 100644 --- a/pcbnew/length_delay_calculation/length_delay_calculation.cpp +++ b/pcbnew/length_delay_calculation/length_delay_calculation.cpp @@ -249,10 +249,10 @@ LENGTH_DELAY_STATS LENGTH_DELAY_CALCULATION::CalculateLengthDetails( std::vector wxLogTrace( wxT( "PNS_TUNE" ), wxT( "CalculateLengthDetails: calculating time domain statistics" ) ); // TODO(JJ): Populate this - TIME_DOMAIN_GEOMETRY_CONTEXT ctx; + TUNING_PROFILE_GEOMETRY_CONTEXT ctx; ctx.NetClass = aItems.front().GetEffectiveNetClass(); // We don't care if this is merged for net class lookup - const std::vector itemDelays = m_timeDomainParameters->GetPropagationDelays( aItems, ctx ); + const std::vector itemDelays = m_tuningProfileParameters->GetPropagationDelays( aItems, ctx ); wxASSERT( itemDelays.size() == aItems.size() ); @@ -660,29 +660,28 @@ LENGTH_DELAY_CALCULATION::GetLengthCalculationItem( const BOARD_CONNECTED_ITEM* } -void LENGTH_DELAY_CALCULATION::SetTimeDomainParametersProvider( - std::unique_ptr&& aProvider ) +void LENGTH_DELAY_CALCULATION::SetTuningProfileParametersProvider( + std::unique_ptr&& aProvider ) { - m_timeDomainParameters = std::move( aProvider ); + m_tuningProfileParameters = std::move( aProvider ); } -void LENGTH_DELAY_CALCULATION::SynchronizeTimeDomainProperties() const +void LENGTH_DELAY_CALCULATION::SynchronizeTuningProfileProperties() const { - m_timeDomainParameters->OnSettingsChanged(); + m_tuningProfileParameters->OnSettingsChanged(); } -int64_t LENGTH_DELAY_CALCULATION::CalculateLengthForDelay( const int64_t aDesiredDelay, - const TIME_DOMAIN_GEOMETRY_CONTEXT& aCtx ) const +int64_t LENGTH_DELAY_CALCULATION::CalculateLengthForDelay( const int64_t aDesiredDelay, + const TUNING_PROFILE_GEOMETRY_CONTEXT& aCtx ) const { - return m_timeDomainParameters->GetTrackLengthForPropagationDelay( aDesiredDelay, aCtx ); + return m_tuningProfileParameters->GetTrackLengthForPropagationDelay( aDesiredDelay, aCtx ); } -int64_t -LENGTH_DELAY_CALCULATION::CalculatePropagationDelayForShapeLineChain( const SHAPE_LINE_CHAIN& aShape, - const TIME_DOMAIN_GEOMETRY_CONTEXT& aCtx ) const +int64_t LENGTH_DELAY_CALCULATION::CalculatePropagationDelayForShapeLineChain( + const SHAPE_LINE_CHAIN& aShape, const TUNING_PROFILE_GEOMETRY_CONTEXT& aCtx ) const { - return m_timeDomainParameters->CalculatePropagationDelayForShapeLineChain( aShape, aCtx ); + return m_tuningProfileParameters->CalculatePropagationDelayForShapeLineChain( aShape, aCtx ); } diff --git a/pcbnew/length_delay_calculation/length_delay_calculation.h b/pcbnew/length_delay_calculation/length_delay_calculation.h index 971892402e..a4e848ac7e 100644 --- a/pcbnew/length_delay_calculation/length_delay_calculation.h +++ b/pcbnew/length_delay_calculation/length_delay_calculation.h @@ -24,8 +24,8 @@ #ifndef PCBNEW_LENGTH_DELAY_CALCULATION_H #define PCBNEW_LENGTH_DELAY_CALCULATION_H -#include "time_domain_parameters_iface.h" -#include "time_domain_parameters_user_defined.h" +#include "tuning_profile_parameters_iface.h" +#include "tuning_profile_parameters_user_defined.h" #include #include @@ -128,7 +128,7 @@ public: */ explicit LENGTH_DELAY_CALCULATION( BOARD* aBoard ) : m_board( aBoard ), - m_timeDomainParameters( std::make_unique( aBoard, this ) ) + m_tuningProfileParameters( std::make_unique( aBoard, this ) ) { } @@ -176,8 +176,8 @@ public: * @param aShape is the shape to calculate delay for * @param aCtx is the geometry context for which to query to propagation delay */ - int64_t CalculatePropagationDelayForShapeLineChain( const SHAPE_LINE_CHAIN& aShape, - const TIME_DOMAIN_GEOMETRY_CONTEXT& aCtx ) const; + int64_t CalculatePropagationDelayForShapeLineChain( const SHAPE_LINE_CHAIN& aShape, + const TUNING_PROFILE_GEOMETRY_CONTEXT& aCtx ) const; /** * @brief Calculates the length of track required for the given delay in a specific geometry context @@ -185,7 +185,7 @@ public: * @param aDesiredDelay is the desired track delay (in IU) * @param aCtx is the track geometry context to calculate propagation velocitiy against */ - int64_t CalculateLengthForDelay( int64_t aDesiredDelay, const TIME_DOMAIN_GEOMETRY_CONTEXT& aCtx ) const; + int64_t CalculateLengthForDelay( int64_t aDesiredDelay, const TUNING_PROFILE_GEOMETRY_CONTEXT& aCtx ) const; /// Optimises the given trace / line to minimise the electrical path length within the given pad static void OptimiseTraceInPad( SHAPE_LINE_CHAIN& aLine, const PAD* aPad, PCB_LAYER_ID aPcbLayer ); @@ -193,11 +193,11 @@ public: /// Return a LENGTH_CALCULATION_ITEM constructed from the given BOARD_CONNECTED_ITEM LENGTH_DELAY_CALCULATION_ITEM GetLengthCalculationItem( const BOARD_CONNECTED_ITEM* aBoardItem ) const; - /// Sets the provider for time domain parameter resolution - void SetTimeDomainParametersProvider( std::unique_ptr&& aProvider ); + /// Sets the provider for tuning profile parameter resolution + void SetTuningProfileParametersProvider( std::unique_ptr&& aProvider ); /// Ensure time domain properties provider is synced with board / project settings if required - void SynchronizeTimeDomainProperties() const; + void SynchronizeTuningProfileProperties() const; /** * Returns the stackup distance between the two given layers. @@ -210,8 +210,8 @@ protected: /// The parent board for all items BOARD* m_board; - /// The active provider of time domain parameters - std::unique_ptr m_timeDomainParameters; + /// The active provider of tuning profile parameters + std::unique_ptr m_tuningProfileParameters; /// Enum to describe whether track merging is attempted from the start or end of a track segment enum class MERGE_POINT diff --git a/pcbnew/length_delay_calculation/time_domain_parameters_iface.h b/pcbnew/length_delay_calculation/tuning_profile_parameters_iface.h similarity index 78% rename from pcbnew/length_delay_calculation/time_domain_parameters_iface.h rename to pcbnew/length_delay_calculation/tuning_profile_parameters_iface.h index 40f45c2aa2..0ccf723f9d 100644 --- a/pcbnew/length_delay_calculation/time_domain_parameters_iface.h +++ b/pcbnew/length_delay_calculation/tuning_profile_parameters_iface.h @@ -21,8 +21,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef PCBNEW_TIME_DOMAIN_PARAMETERS_INTERFACE_H -#define PCBNEW_TIME_DOMAIN_PARAMETERS_INTERFACE_H +#ifndef PCBNEW_TUNING_PROFILE_PARAMETERS_IFACE_H +#define PCBNEW_TUNING_PROFILE_PARAMETERS_IFACE_H #include #include @@ -32,7 +32,7 @@ class LENGTH_DELAY_CALCULATION; /** * A data structure to contain basic geometry data which can affect signal propagation calculations. */ -struct TIME_DOMAIN_GEOMETRY_CONTEXT +struct TUNING_PROFILE_GEOMETRY_CONTEXT { /// The net class this track belongs to const NETCLASS* NetClass; @@ -52,19 +52,20 @@ struct TIME_DOMAIN_GEOMETRY_CONTEXT /** - * Interface for providers of time domain parameter information. This interface is consumed by the - * LENGTH_TIME_CALCULATOR object to convert space-domain physical layout informaton (e.g. track lengths) in to + * Interface for providers of tuning profile parameter information. This interface is consumed by the + * LENGTH_TIME_CALCULATOR object to convert space-domain physical layout information (e.g. track lengths) in to * time-domain propagation information. */ -class TIME_DOMAIN_PARAMETERS_IFACE +class TUNING_PROFILE_PARAMETERS_IFACE { public: - explicit TIME_DOMAIN_PARAMETERS_IFACE( BOARD* aBoard, LENGTH_DELAY_CALCULATION* aCalculation ) : - m_board{ aBoard }, m_lengthCalculation{ aCalculation } + explicit TUNING_PROFILE_PARAMETERS_IFACE( BOARD* aBoard, LENGTH_DELAY_CALCULATION* aCalculation ) : + m_board{ aBoard }, + m_lengthCalculation{ aCalculation } { } - virtual ~TIME_DOMAIN_PARAMETERS_IFACE() = default; + virtual ~TUNING_PROFILE_PARAMETERS_IFACE() = default; /** * Event called by the length and time calculation architecture if the board stackup has changed. This can be used @@ -85,7 +86,7 @@ public: * @param aContext the geometry context in which to query to propagation delay */ virtual std::vector GetPropagationDelays( const std::vector& aItems, - const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext ) = 0; + const TUNING_PROFILE_GEOMETRY_CONTEXT& aContext ) = 0; /** * Gets the propagation delay (in internal units) for the given item in the given geometry context @@ -93,8 +94,8 @@ public: * @param aItem the board item to query propagation delay for * @param aContext is the geometry context in which to query to propagation delay */ - virtual int64_t GetPropagationDelay( const LENGTH_DELAY_CALCULATION_ITEM& aItem, - const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext ) = 0; + virtual int64_t GetPropagationDelay( const LENGTH_DELAY_CALCULATION_ITEM& aItem, + const TUNING_PROFILE_GEOMETRY_CONTEXT& aContext ) = 0; /** * Gets the track length (in internal distance units) required for the given propagation delay (in internal time @@ -103,8 +104,8 @@ public: * @param aContext the geometry context in which to query to propagation delay * @param aDelay the propagation delay for which a length should be calculated */ - virtual int64_t GetTrackLengthForPropagationDelay( int64_t aDelay, - const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext ) = 0; + virtual int64_t GetTrackLengthForPropagationDelay( int64_t aDelay, + const TUNING_PROFILE_GEOMETRY_CONTEXT& aContext ) = 0; /** * Gets the propagation delay for the given shape line chain @@ -112,8 +113,8 @@ public: * @param aShape is the shape to calculate delay for * @param aContext is the geometry context for which to query to propagation delay */ - virtual int64_t CalculatePropagationDelayForShapeLineChain( const SHAPE_LINE_CHAIN& aShape, - const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext ) = 0; + virtual int64_t CalculatePropagationDelayForShapeLineChain( const SHAPE_LINE_CHAIN& aShape, + const TUNING_PROFILE_GEOMETRY_CONTEXT& aContext ) = 0; protected: /// The board all calculations are for @@ -123,4 +124,4 @@ protected: LENGTH_DELAY_CALCULATION* m_lengthCalculation; }; -#endif //PCBNEW_TIME_DOMAIN_PARAMETERS_INTERFACE_H +#endif //PCBNEW_TUNING_PROFILE_PARAMETERS_IFACE_H diff --git a/pcbnew/length_delay_calculation/time_domain_parameters_user_defined.cpp b/pcbnew/length_delay_calculation/tuning_profile_parameters_user_defined.cpp similarity index 60% rename from pcbnew/length_delay_calculation/time_domain_parameters_user_defined.cpp rename to pcbnew/length_delay_calculation/tuning_profile_parameters_user_defined.cpp index b7037046d2..321a35746d 100644 --- a/pcbnew/length_delay_calculation/time_domain_parameters_user_defined.cpp +++ b/pcbnew/length_delay_calculation/tuning_profile_parameters_user_defined.cpp @@ -23,25 +23,25 @@ #include #include -#include +#include #include -void TIME_DOMAIN_PARAMETERS_USER_DEFINED::OnSettingsChanged() +void TUNING_PROFILE_PARAMETERS_USER_DEFINED::OnSettingsChanged() { rebuildCaches(); } std::vector -TIME_DOMAIN_PARAMETERS_USER_DEFINED::GetPropagationDelays( const std::vector& aItems, - const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext ) +TUNING_PROFILE_PARAMETERS_USER_DEFINED::GetPropagationDelays( const std::vector& aItems, + const TUNING_PROFILE_GEOMETRY_CONTEXT& aContext ) { if( aItems.empty() ) return {}; - const wxString delayProfileName = aItems.front().GetEffectiveNetClass()->GetDelayProfile(); - const DELAY_PROFILE* delayProfile = GetDelayProfile( delayProfileName ); + const wxString delayProfileName = aItems.front().GetEffectiveNetClass()->GetTuningProfile(); + const TUNING_PROFILE* delayProfile = GetTuningProfile( delayProfileName ); if( !delayProfile ) return std::vector( aItems.size(), 0 ); @@ -56,14 +56,14 @@ TIME_DOMAIN_PARAMETERS_USER_DEFINED::GetPropagationDelays( const std::vectorGetDelayProfile(); - const DELAY_PROFILE* delayProfile = GetDelayProfile( delayProfileName ); + const wxString delayProfileName = aItem.GetEffectiveNetClass()->GetTuningProfile(); + const TUNING_PROFILE* delayProfile = GetTuningProfile( delayProfileName ); if( !delayProfile ) return 0; @@ -72,9 +72,9 @@ int64_t TIME_DOMAIN_PARAMETERS_USER_DEFINED::GetPropagationDelay( const LENGTH_D } -int64_t TIME_DOMAIN_PARAMETERS_USER_DEFINED::getPropagationDelay( const LENGTH_DELAY_CALCULATION_ITEM& aItem, - const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext, - const DELAY_PROFILE* aDelayProfile ) const +int64_t TUNING_PROFILE_PARAMETERS_USER_DEFINED::getPropagationDelay( const LENGTH_DELAY_CALCULATION_ITEM& aItem, + const TUNING_PROFILE_GEOMETRY_CONTEXT& aContext, + const TUNING_PROFILE* aDelayProfile ) const { if( aItem.GetMergeStatus() == LENGTH_DELAY_CALCULATION_ITEM::MERGE_STATUS::MERGED_RETIRED ) return 0; @@ -83,12 +83,23 @@ int64_t TIME_DOMAIN_PARAMETERS_USER_DEFINED::getPropagationDelay( const LENGTH_D if( itemType == LENGTH_DELAY_CALCULATION_ITEM::TYPE::LINE ) { - const double delayUnit = aDelayProfile->m_LayerPropagationDelays.at( aItem.GetStartLayer() ); + double delayUnit = 0.0; + + if( aDelayProfile->m_TrackPropagationEntriesMap.contains( aItem.GetStartLayer() ) ) + { + const DELAY_PROFILE_TRACK_PROPAGATION_ENTRY& entry = + aDelayProfile->m_TrackPropagationEntriesMap.at( aItem.GetStartLayer() ); + delayUnit = entry.GetDelay(); + } + return static_cast( delayUnit * ( static_cast( aItem.GetLine().Length() ) / PCB_IU_PER_MM ) ); } if( itemType == LENGTH_DELAY_CALCULATION_ITEM::TYPE::VIA ) { + if( !aDelayProfile->m_EnableTimeDomainTuning ) + return 0; + const PCB_LAYER_ID signalStartLayer = aItem.GetStartLayer(); const PCB_LAYER_ID signalEndLayer = aItem.GetEndLayer(); const PCB_LAYER_ID viaStartLayer = aItem.GetVia()->Padstack().StartLayer(); @@ -117,7 +128,7 @@ int64_t TIME_DOMAIN_PARAMETERS_USER_DEFINED::getPropagationDelay( const LENGTH_D } -const DELAY_PROFILE* TIME_DOMAIN_PARAMETERS_USER_DEFINED::GetDelayProfile( const wxString& aDelayProfileName ) +const TUNING_PROFILE* TUNING_PROFILE_PARAMETERS_USER_DEFINED::GetTuningProfile( const wxString& aDelayProfileName ) { auto itr = m_delayProfilesCache.find( aDelayProfileName ); @@ -128,49 +139,61 @@ const DELAY_PROFILE* TIME_DOMAIN_PARAMETERS_USER_DEFINED::GetDelayProfile( const } -int64_t -TIME_DOMAIN_PARAMETERS_USER_DEFINED::GetTrackLengthForPropagationDelay( int64_t aDelay, - const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext ) +int64_t TUNING_PROFILE_PARAMETERS_USER_DEFINED::GetTrackLengthForPropagationDelay( + int64_t aDelay, const TUNING_PROFILE_GEOMETRY_CONTEXT& aContext ) { - const wxString delayProfileName = aContext.NetClass->GetDelayProfile(); - const DELAY_PROFILE* profile = GetDelayProfile( delayProfileName ); + const wxString delayProfileName = aContext.NetClass->GetTuningProfile(); + const TUNING_PROFILE* profile = GetTuningProfile( delayProfileName ); if( !profile ) return 0; - const double delayUnit = profile->m_LayerPropagationDelays.at( aContext.Layer ); // Time IU / MM - const double lengthInMM = static_cast( aDelay ) / delayUnit; // MM - return static_cast( lengthInMM * PCB_IU_PER_MM ); // Length IU + double delayUnit = 0.0; + + if( profile->m_TrackPropagationEntriesMap.contains( aContext.Layer ) ) + { + const DELAY_PROFILE_TRACK_PROPAGATION_ENTRY& entry = profile->m_TrackPropagationEntriesMap.at( aContext.Layer ); + delayUnit = entry.GetDelay(); + } + + const double lengthInMM = static_cast( aDelay ) / delayUnit; // MM + return static_cast( lengthInMM * PCB_IU_PER_MM ); // Length IU } -int64_t TIME_DOMAIN_PARAMETERS_USER_DEFINED::CalculatePropagationDelayForShapeLineChain( - const SHAPE_LINE_CHAIN& aShape, const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext ) +int64_t TUNING_PROFILE_PARAMETERS_USER_DEFINED::CalculatePropagationDelayForShapeLineChain( + const SHAPE_LINE_CHAIN& aShape, const TUNING_PROFILE_GEOMETRY_CONTEXT& aContext ) { - const wxString delayProfileName = aContext.NetClass->GetDelayProfile(); - const DELAY_PROFILE* profile = GetDelayProfile( delayProfileName ); + const wxString delayProfileName = aContext.NetClass->GetTuningProfile(); + const TUNING_PROFILE* profile = GetTuningProfile( delayProfileName ); if( !profile ) return 0; - const double delayUnit = profile->m_LayerPropagationDelays.at( aContext.Layer ); + double delayUnit = 0.0; + + if( profile->m_TrackPropagationEntriesMap.contains( aContext.Layer ) ) + { + const DELAY_PROFILE_TRACK_PROPAGATION_ENTRY& entry = profile->m_TrackPropagationEntriesMap.at( aContext.Layer ); + delayUnit = entry.GetDelay(); + } + return static_cast( delayUnit * ( static_cast( aShape.Length() ) / PCB_IU_PER_MM ) ); } -void TIME_DOMAIN_PARAMETERS_USER_DEFINED::rebuildCaches() +void TUNING_PROFILE_PARAMETERS_USER_DEFINED::rebuildCaches() { m_delayProfilesCache.clear(); m_viaOverridesCache.clear(); if( const PROJECT* project = m_board->GetProject() ) { - TIME_DOMAIN_PARAMETERS* params = project->GetProjectFile().TimeDomainParameters().get(); + TUNING_PROFILES* params = project->GetProjectFile().TuningProfileParameters().get(); - for( const DELAY_PROFILE& profile : params->GetDelayProfiles() ) + for( const TUNING_PROFILE& profile : params->GetTuningProfiles() ) { m_delayProfilesCache[profile.m_ProfileName] = &profile; - std::map& viaOverrides = m_viaOverridesCache[profile.m_ProfileName]; for( const DELAY_PROFILE_VIA_OVERRIDE_ENTRY& viaOverride : profile.m_ViaOverrides ) diff --git a/pcbnew/length_delay_calculation/time_domain_parameters_user_defined.h b/pcbnew/length_delay_calculation/tuning_profile_parameters_user_defined.h similarity index 76% rename from pcbnew/length_delay_calculation/time_domain_parameters_user_defined.h rename to pcbnew/length_delay_calculation/tuning_profile_parameters_user_defined.h index 0770622d62..836a969c3c 100644 --- a/pcbnew/length_delay_calculation/time_domain_parameters_user_defined.h +++ b/pcbnew/length_delay_calculation/tuning_profile_parameters_user_defined.h @@ -21,18 +21,18 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef PCB_NEW_TIME_DOMAIN_PARAMETERS_USER_DEFINED_H -#define PCB_NEW_TIME_DOMAIN_PARAMETERS_USER_DEFINED_H +#ifndef PCB_NEW_TUNING_PROFILE_PARAMETERS_USER_DEFINED_H +#define PCB_NEW_TUNING_PROFILE_PARAMETERS_USER_DEFINED_H -#include -#include +#include +#include -class TIME_DOMAIN_PARAMETERS_USER_DEFINED final : public TIME_DOMAIN_PARAMETERS_IFACE +class TUNING_PROFILE_PARAMETERS_USER_DEFINED final : public TUNING_PROFILE_PARAMETERS_IFACE { public: - explicit TIME_DOMAIN_PARAMETERS_USER_DEFINED( BOARD* aBoard, LENGTH_DELAY_CALCULATION* aCalculation ) : - TIME_DOMAIN_PARAMETERS_IFACE( aBoard, aCalculation ) + explicit TUNING_PROFILE_PARAMETERS_USER_DEFINED( BOARD* aBoard, LENGTH_DELAY_CALCULATION* aCalculation ) : + TUNING_PROFILE_PARAMETERS_IFACE( aBoard, aCalculation ) { } @@ -50,7 +50,7 @@ public: * @param aContext the geometry context in which to query to propagation delay */ std::vector GetPropagationDelays( const std::vector& aItems, - const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext ) override; + const TUNING_PROFILE_GEOMETRY_CONTEXT& aContext ) override; /** * Gets the propagation delay (in internal units) for the given item in the given geometry context @@ -58,8 +58,8 @@ public: * @param aItem the board item to query propagation delay for * @param aContext the geometry context in which to query to propagation delay */ - int64_t GetPropagationDelay( const LENGTH_DELAY_CALCULATION_ITEM& aItem, - const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext ) override; + int64_t GetPropagationDelay( const LENGTH_DELAY_CALCULATION_ITEM& aItem, + const TUNING_PROFILE_GEOMETRY_CONTEXT& aContext ) override; /** * Gets the track length (in internal distance units) required for the given propagation delay (in internal time @@ -68,7 +68,8 @@ public: * @param aContext the geometry context in which to query to propagation delay * @param aDelay the propagation delay for which a length should be calculated */ - int64_t GetTrackLengthForPropagationDelay( int64_t aDelay, const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext ) override; + int64_t GetTrackLengthForPropagationDelay( int64_t aDelay, + const TUNING_PROFILE_GEOMETRY_CONTEXT& aContext ) override; /** * Gets the propagation delay for the given shape line chain @@ -76,8 +77,8 @@ public: * @param aShape is the shape to calculate delay for * @param aContext is the geometry context for which to query to propagation delay */ - int64_t CalculatePropagationDelayForShapeLineChain( const SHAPE_LINE_CHAIN& aShape, - const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext ) override; + int64_t CalculatePropagationDelayForShapeLineChain( const SHAPE_LINE_CHAIN& aShape, + const TUNING_PROFILE_GEOMETRY_CONTEXT& aContext ) override; private: void rebuildCaches(); @@ -120,9 +121,9 @@ private: * @param aContext the geometry context in which to query to propagation delay * @param aDelayProfile the time domain tuning profile for the given item */ - int64_t getPropagationDelay( const LENGTH_DELAY_CALCULATION_ITEM& aItem, - const TIME_DOMAIN_GEOMETRY_CONTEXT& aContext, - const DELAY_PROFILE* aDelayProfile ) const; + int64_t getPropagationDelay( const LENGTH_DELAY_CALCULATION_ITEM& aItem, + const TUNING_PROFILE_GEOMETRY_CONTEXT& aContext, + const TUNING_PROFILE* aDelayProfile ) const; /** * Gets the tuning profile pointer for the given tuning profile name @@ -130,13 +131,13 @@ private: * @param aDelayProfileName the tuning profile name to return * @returns Valid pointer to a tuning profile, or nullptr if no profile found */ - const DELAY_PROFILE* GetDelayProfile( const wxString& aDelayProfileName ); + const TUNING_PROFILE* GetTuningProfile( const wxString& aDelayProfileName ); /// Cached map of tuning profile names to per-layer time domain parameters - std::map m_delayProfilesCache; + std::map m_delayProfilesCache; /// Cached per-tuning profile via overrides std::map> m_viaOverridesCache; }; -#endif //PCB_NEW_TIME_DOMAIN_PARAMETERS_USER_DEFINED_H +#endif //PCB_NEW_TUNING_PROFILE_PARAMETERS_USER_DEFINED_H diff --git a/pcbnew/pcb_edit_frame.cpp b/pcbnew/pcb_edit_frame.cpp index 82181473f9..5544dc26ef 100644 --- a/pcbnew/pcb_edit_frame.cpp +++ b/pcbnew/pcb_edit_frame.cpp @@ -1497,7 +1497,7 @@ void PCB_EDIT_FRAME::ShowBoardSetupDialog( const wxString& aInitialPage, wxWindo { // Note: We must synchronise time domain properties before nets and classes, otherwise the updates // called by the board listener events are using stale data - GetBoard()->SynchronizeTimeDomainProperties(); + GetBoard()->SynchronizeTuningProfileProperties(); GetBoard()->SynchronizeNetsAndNetClasses( true ); if( !GetBoard()->SynchronizeComponentClasses( std::unordered_set() ) ) diff --git a/pcbnew/router/pns_kicad_iface.cpp b/pcbnew/router/pns_kicad_iface.cpp index f2dcdd1cb4..5ed1ad48ed 100644 --- a/pcbnew/router/pns_kicad_iface.cpp +++ b/pcbnew/router/pns_kicad_iface.cpp @@ -2508,7 +2508,7 @@ int64_t PNS_KICAD_IFACE_BASE::CalculateLengthForDelay( int64_t aDesiredDelay, co const bool aIsDiffPairCoupled, const int aDiffPairCouplingGap, const int aPNSLayer, const NETCLASS* aNetClass ) { - TIME_DOMAIN_GEOMETRY_CONTEXT ctx; + TUNING_PROFILE_GEOMETRY_CONTEXT ctx; ctx.NetClass = aNetClass; ctx.Width = aWidth; ctx.IsDiffPairCoupled = aIsDiffPairCoupled; @@ -2524,7 +2524,7 @@ int64_t PNS_KICAD_IFACE_BASE::CalculateDelayForShapeLineChain( const SHAPE_LINE_ bool aIsDiffPairCoupled, int aDiffPairCouplingGap, int aPNSLayer, const NETCLASS* aNetClass ) { - TIME_DOMAIN_GEOMETRY_CONTEXT ctx; + TUNING_PROFILE_GEOMETRY_CONTEXT ctx; ctx.NetClass = aNetClass; ctx.Width = aWidth; ctx.IsDiffPairCoupled = aIsDiffPairCoupled; diff --git a/pcbnew/router/pns_meander_placer.cpp b/pcbnew/router/pns_meander_placer.cpp index 8c266de454..079adb02b9 100644 --- a/pcbnew/router/pns_meander_placer.cpp +++ b/pcbnew/router/pns_meander_placer.cpp @@ -27,7 +27,7 @@ #include "pns_solid.h" #include "pns_topology.h" -#include +#include namespace PNS { diff --git a/qa/data/pcbnew/drc_missing_tuning_profile.kicad_pcb b/qa/data/pcbnew/drc_missing_tuning_profile.kicad_pcb new file mode 100644 index 0000000000..8f8df05911 --- /dev/null +++ b/qa/data/pcbnew/drc_missing_tuning_profile.kicad_pcb @@ -0,0 +1,131 @@ +(kicad_pcb + (version 20250926) + (generator "pcbnew") + (generator_version "9.99") + (general + (thickness 1.6) + (legacy_teardrops no) + ) + (paper "A4") + (layers + (0 "F.Cu" signal) + (2 "B.Cu" signal) + (9 "F.Adhes" user "F.Adhesive") + (11 "B.Adhes" user "B.Adhesive") + (13 "F.Paste" user) + (15 "B.Paste" user) + (5 "F.SilkS" user "F.Silkscreen") + (7 "B.SilkS" user "B.Silkscreen") + (1 "F.Mask" user) + (3 "B.Mask" user) + (17 "Dwgs.User" user "User.Drawings") + (19 "Cmts.User" user "User.Comments") + (21 "Eco1.User" user "User.Eco1") + (23 "Eco2.User" user "User.Eco2") + (25 "Edge.Cuts" user) + (27 "Margin" user) + (31 "F.CrtYd" user "F.Courtyard") + (29 "B.CrtYd" user "B.Courtyard") + (35 "F.Fab" user) + (33 "B.Fab" user) + (39 "User.1" user) + (41 "User.2" user) + (43 "User.3" user) + (45 "User.4" user) + ) + (setup + (stackup + (layer "F.SilkS" + (type "Top Silk Screen") + ) + (layer "F.Paste" + (type "Top Solder Paste") + ) + (layer "F.Mask" + (type "Top Solder Mask") + (thickness 0.01) + ) + (layer "F.Cu" + (type "copper") + (thickness 0.035) + ) + (layer "dielectric 1" + (type "core") + (thickness 1.51) + (material "FR4") + (epsilon_r 4.5) + (loss_tangent 0.02) + ) + (layer "B.Cu" + (type "copper") + (thickness 0.035) + ) + (layer "B.Mask" + (type "Bottom Solder Mask") + (thickness 0.01) + ) + (layer "B.Paste" + (type "Bottom Solder Paste") + ) + (layer "B.SilkS" + (type "Bottom Silk Screen") + ) + (copper_finish "None") + (dielectric_constraints no) + ) + (pad_to_mask_clearance 0) + (allow_soldermask_bridges_in_footprints no) + (tenting + (front yes) + (back yes) + ) + (covering + (front no) + (back no) + ) + (plugging + (front no) + (back no) + ) + (capping no) + (filling no) + (pcbplotparams + (layerselection 0x00000000_00000000_55555555_5755f5ff) + (plot_on_all_layers_selection 0x00000000_00000000_00000000_00000000) + (disableapertmacros no) + (usegerberextensions no) + (usegerberattributes yes) + (usegerberadvancedattributes yes) + (creategerberjobfile yes) + (dashed_line_dash_ratio 12) + (dashed_line_gap_ratio 3) + (svgprecision 4) + (plotframeref no) + (mode 1) + (useauxorigin no) + (pdf_front_fp_property_popups yes) + (pdf_back_fp_property_popups yes) + (pdf_metadata yes) + (pdf_single_document no) + (dxfpolygonmode yes) + (dxfimperialunits yes) + (dxfusepcbnewfont yes) + (psnegative no) + (psa4output no) + (plot_black_and_white yes) + (sketchpadsonfab no) + (plotpadnumbers no) + (hidednponfab no) + (sketchdnponfab yes) + (crossoutdnponfab yes) + (subtractmaskfromsilk no) + (outputformat 1) + (mirror no) + (drillshape 1) + (scaleselection 1) + (outputdirectory "") + ) + ) + (net 0 "") + (embedded_fonts no) +) diff --git a/qa/data/pcbnew/drc_missing_tuning_profile.kicad_pro b/qa/data/pcbnew/drc_missing_tuning_profile.kicad_pro new file mode 100644 index 0000000000..e60ee565e9 --- /dev/null +++ b/qa/data/pcbnew/drc_missing_tuning_profile.kicad_pro @@ -0,0 +1,335 @@ +{ + "board": { + "3dviewports": [], + "design_settings": { + "defaults": { + "apply_defaults_to_fp_barcodes": false, + "apply_defaults_to_fp_dimensions": false, + "apply_defaults_to_fp_fields": false, + "apply_defaults_to_fp_shapes": false, + "apply_defaults_to_fp_text": false, + "board_outline_line_width": 0.05, + "copper_line_width": 0.2, + "copper_text_italic": false, + "copper_text_size_h": 1.5, + "copper_text_size_v": 1.5, + "copper_text_thickness": 0.3, + "copper_text_upright": false, + "courtyard_line_width": 0.05, + "dimension_precision": 4, + "dimension_units": 3, + "dimensions": { + "arrow_length": 1270000, + "extension_offset": 500000, + "keep_text_aligned": true, + "suppress_zeroes": true, + "text_position": 0, + "units_format": 0 + }, + "fab_line_width": 0.1, + "fab_text_italic": false, + "fab_text_size_h": 1.0, + "fab_text_size_v": 1.0, + "fab_text_thickness": 0.15, + "fab_text_upright": false, + "other_line_width": 0.1, + "other_text_italic": false, + "other_text_size_h": 1.0, + "other_text_size_v": 1.0, + "other_text_thickness": 0.15, + "other_text_upright": false, + "pads": { + "drill": 0.8, + "height": 1.27, + "width": 2.54 + }, + "silk_line_width": 0.1, + "silk_text_italic": false, + "silk_text_size_h": 1.0, + "silk_text_size_v": 1.0, + "silk_text_thickness": 0.1, + "silk_text_upright": false, + "zones": { + "min_clearance": 0.5 + } + }, + "diff_pair_dimensions": [], + "drc_exclusions": [], + "meta": { + "version": 2 + }, + "rule_severities": { + "annular_width": "error", + "clearance": "error", + "connection_width": "warning", + "copper_edge_clearance": "error", + "copper_sliver": "warning", + "courtyards_overlap": "error", + "creepage": "error", + "diff_pair_gap_out_of_range": "error", + "diff_pair_uncoupled_length_too_long": "error", + "drill_out_of_range": "error", + "duplicate_footprints": "warning", + "extra_footprint": "warning", + "footprint": "error", + "footprint_filters_mismatch": "ignore", + "footprint_symbol_mismatch": "warning", + "footprint_type_mismatch": "ignore", + "hole_clearance": "error", + "hole_to_hole": "warning", + "holes_co_located": "warning", + "invalid_outline": "error", + "isolated_copper": "warning", + "item_on_disabled_layer": "error", + "items_not_allowed": "error", + "length_out_of_range": "error", + "lib_footprint_issues": "warning", + "lib_footprint_mismatch": "warning", + "malformed_courtyard": "error", + "microvia_drill_out_of_range": "error", + "mirrored_text_on_front_layer": "warning", + "missing_courtyard": "ignore", + "missing_footprint": "warning", + "missing_tuning_profile": "warning", + "net_conflict": "warning", + "nonmirrored_text_on_back_layer": "warning", + "npth_inside_courtyard": "ignore", + "padstack": "warning", + "pth_inside_courtyard": "ignore", + "shorting_items": "error", + "silk_edge_clearance": "warning", + "silk_over_copper": "warning", + "silk_overlap": "warning", + "skew_out_of_range": "error", + "solder_mask_bridge": "error", + "starved_thermal": "error", + "text_height": "warning", + "text_on_edge_cuts": "error", + "text_thickness": "warning", + "through_hole_pad_without_hole": "error", + "too_many_vias": "error", + "track_angle": "error", + "track_dangling": "warning", + "track_segment_length": "error", + "track_width": "error", + "tracks_crossing": "error", + "unconnected_items": "error", + "unresolved_variable": "error", + "via_dangling": "warning", + "zones_intersect": "error" + }, + "rules": { + "max_error": 0.005, + "min_clearance": 0.0, + "min_connection": 0.0, + "min_copper_edge_clearance": 0.5, + "min_groove_width": 0.0, + "min_hole_clearance": 0.25, + "min_hole_to_hole": 0.25, + "min_microvia_diameter": 0.2, + "min_microvia_drill": 0.1, + "min_resolved_spokes": 2, + "min_silk_clearance": 0.0, + "min_text_height": 0.8, + "min_text_thickness": 0.08, + "min_through_hole_diameter": 0.3, + "min_track_width": 0.0, + "min_via_annular_width": 0.1, + "min_via_diameter": 0.5, + "solder_mask_to_copper_clearance": 0.0, + "use_height_for_length_calcs": true + }, + "teardrop_options": [ + { + "td_onpthpad": true, + "td_onroundshapesonly": false, + "td_onsmdpad": true, + "td_ontrackend": false, + "td_onvia": true + } + ], + "teardrop_parameters": [ + { + "td_allow_use_two_tracks": true, + "td_curve_segcount": 0, + "td_height_ratio": 1.0, + "td_length_ratio": 0.5, + "td_maxheight": 2.0, + "td_maxlen": 1.0, + "td_on_pad_in_zone": false, + "td_target_name": "td_round_shape", + "td_width_to_size_filter_ratio": 0.9 + }, + { + "td_allow_use_two_tracks": true, + "td_curve_segcount": 0, + "td_height_ratio": 1.0, + "td_length_ratio": 0.5, + "td_maxheight": 2.0, + "td_maxlen": 1.0, + "td_on_pad_in_zone": false, + "td_target_name": "td_rect_shape", + "td_width_to_size_filter_ratio": 0.9 + }, + { + "td_allow_use_two_tracks": true, + "td_curve_segcount": 0, + "td_height_ratio": 1.0, + "td_length_ratio": 0.5, + "td_maxheight": 2.0, + "td_maxlen": 1.0, + "td_on_pad_in_zone": false, + "td_target_name": "td_track_end", + "td_width_to_size_filter_ratio": 0.9 + } + ], + "track_widths": [], + "tuning_pattern_settings": { + "diff_pair_defaults": { + "corner_radius_percentage": 80, + "corner_style": 1, + "max_amplitude": 1.0, + "min_amplitude": 0.2, + "single_sided": false, + "spacing": 1.0 + }, + "diff_pair_skew_defaults": { + "corner_radius_percentage": 80, + "corner_style": 1, + "max_amplitude": 1.0, + "min_amplitude": 0.2, + "single_sided": false, + "spacing": 0.6 + }, + "single_track_defaults": { + "corner_radius_percentage": 80, + "corner_style": 1, + "max_amplitude": 1.0, + "min_amplitude": 0.2, + "single_sided": false, + "spacing": 0.6 + } + }, + "via_dimensions": [], + "zones_allow_external_fillets": false + }, + "ipc2581": { + "dist": "", + "distpn": "", + "internal_id": "", + "mfg": "", + "mpn": "" + }, + "layer_pairs": [], + "layer_presets": [], + "viewports": [] + }, + "boards": [], + "component_class_settings": { + "assignments": [], + "meta": { + "version": 0 + }, + "sheet_component_classes": { + "enabled": false + } + }, + "cvpcb": { + "equivalence_files": [] + }, + "libraries": { + "pinned_footprint_libs": [], + "pinned_symbol_libs": [] + }, + "meta": { + "filename": "drc_missing_tuning_profile.kicad_pro", + "version": 3 + }, + "net_settings": { + "classes": [ + { + "bus_width": 12, + "clearance": 0.2, + "diff_pair_gap": 0.25, + "diff_pair_via_gap": 0.25, + "diff_pair_width": 0.2, + "line_style": 0, + "microvia_diameter": 0.3, + "microvia_drill": 0.1, + "name": "Default", + "pcb_color": "rgba(0, 0, 0, 0.000)", + "priority": 2147483647, + "schematic_color": "rgba(0, 0, 0, 0.000)", + "track_width": 0.2, + "tuning_profile": "", + "via_diameter": 0.6, + "via_drill": 0.3, + "wire_width": 6 + }, + { + "name": "CLASS1", + "pcb_color": "rgba(0, 0, 0, 0.000)", + "priority": 1, + "schematic_color": "rgba(0, 0, 0, 0.000)", + "tuning_profile": "PROFILE1" + }, + { + "name": "CLASS2", + "pcb_color": "rgba(0, 0, 0, 0.000)", + "priority": 0, + "schematic_color": "rgba(0, 0, 0, 0.000)", + "tuning_profile": "PROFILE2" + } + ], + "meta": { + "version": 5 + }, + "net_colors": null, + "netclass_assignments": null, + "netclass_patterns": [] + }, + "pcbnew": { + "last_paths": { + "idf": "", + "netlist": "", + "plot": "", + "specctra_dsn": "", + "vrml": "" + }, + "page_layout_descr_file": "" + }, + "schematic": { + "bus_aliases": {}, + "legacy_lib_dir": "", + "legacy_lib_list": [] + }, + "sheets": [], + "text_variables": {}, + "tuning_profiles": { + "meta": { + "version": 0 + }, + "tuning_profiles_impedance_geometric": [ + { + "enable_time_domain_tuning": false, + "generate_drc_rules": true, + "layer_entries": [], + "profile_name": "PROFILE1", + "target_impedance": 0.0, + "type": 0, + "via_overrides": [], + "via_prop_delay": 0 + }, + { + "enable_time_domain_tuning": false, + "generate_drc_rules": true, + "layer_entries": [], + "profile_name": "PROFILE2_RENAME", + "target_impedance": 0.0, + "type": 0, + "via_overrides": [], + "via_prop_delay": 0 + } + ] + } +} diff --git a/qa/data/pcbnew/drc_missing_tuning_profile.kicad_sch b/qa/data/pcbnew/drc_missing_tuning_profile.kicad_sch new file mode 100644 index 0000000000..e811e1ab3f --- /dev/null +++ b/qa/data/pcbnew/drc_missing_tuning_profile.kicad_sch @@ -0,0 +1,14 @@ +(kicad_sch + (version 20250922) + (generator "eeschema") + (generator_version "9.99") + (uuid 834b6ea0-3699-46bc-922e-4fa7e8a4a2a9) + (paper "A4") + (lib_symbols) + (sheet_instances + (path "/" + (page "1") + ) + ) + (embedded_fonts no) +) \ No newline at end of file diff --git a/qa/data/pcbnew/time_calculations.kicad_pcb b/qa/data/pcbnew/time_calculations.kicad_pcb index 083dfe3770..d8c4dbf3a6 100644 --- a/qa/data/pcbnew/time_calculations.kicad_pcb +++ b/qa/data/pcbnew/time_calculations.kicad_pcb @@ -1,5 +1,5 @@ (kicad_pcb - (version 20250801) + (version 20250926) (generator "pcbnew") (generator_version "9.99") (general diff --git a/qa/data/pcbnew/time_calculations.kicad_pro b/qa/data/pcbnew/time_calculations.kicad_pro index 97b8ee9485..81deb5ee50 100644 --- a/qa/data/pcbnew/time_calculations.kicad_pro +++ b/qa/data/pcbnew/time_calculations.kicad_pro @@ -3,6 +3,8 @@ "3dviewports": [], "design_settings": { "defaults": { + "apply_defaults_to_fp_barcodes": false, + "apply_defaults_to_fp_dimensions": false, "apply_defaults_to_fp_fields": false, "apply_defaults_to_fp_shapes": false, "apply_defaults_to_fp_text": false, @@ -664,6 +666,7 @@ "sort_asc": true, "sort_field": "Reference" }, + "bus_aliases": {}, "connection_grid_size": 50.0, "drawing": { "dashed_lines_dash_length_ratio": 12.0, @@ -927,5 +930,336 @@ "via_layer_to": "In2.Cu" } ] + }, + "tuning_profiles": { + "meta": { + "version": 0 + }, + "tuning_profiles_impedance_geometric": [ + { + "enable_time_domain_tuning": true, + "generate_drc_rules": false, + "layer_entries": [ + { + "bottom_reference_layer": "UNDEFINED", + "delay": 1000000, + "diff_pair_gap": 0, + "signal_layer": "F.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + }, + { + "bottom_reference_layer": "UNDEFINED", + "delay": 0, + "diff_pair_gap": 0, + "signal_layer": "In1.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + }, + { + "bottom_reference_layer": "UNDEFINED", + "delay": 0, + "diff_pair_gap": 0, + "signal_layer": "In2.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + }, + { + "bottom_reference_layer": "UNDEFINED", + "delay": 0, + "diff_pair_gap": 0, + "signal_layer": "B.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + } + ], + "profile_name": "CLASS1", + "target_impedance": 0.0, + "type": 0, + "via_overrides": [], + "via_prop_delay": 0 + }, + { + "enable_time_domain_tuning": true, + "generate_drc_rules": false, + "layer_entries": [ + { + "bottom_reference_layer": "UNDEFINED", + "delay": 1000000, + "diff_pair_gap": 0, + "signal_layer": "F.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + }, + { + "bottom_reference_layer": "UNDEFINED", + "delay": 0, + "diff_pair_gap": 0, + "signal_layer": "In1.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + }, + { + "bottom_reference_layer": "UNDEFINED", + "delay": 0, + "diff_pair_gap": 0, + "signal_layer": "In2.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + }, + { + "bottom_reference_layer": "UNDEFINED", + "delay": 0, + "diff_pair_gap": 0, + "signal_layer": "B.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + } + ], + "profile_name": "CLASS2", + "target_impedance": 0.0, + "type": 0, + "via_overrides": [], + "via_prop_delay": 0 + }, + { + "enable_time_domain_tuning": true, + "generate_drc_rules": false, + "layer_entries": [ + { + "bottom_reference_layer": "UNDEFINED", + "delay": 1000000, + "diff_pair_gap": 0, + "signal_layer": "F.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + }, + { + "bottom_reference_layer": "UNDEFINED", + "delay": 1000000, + "diff_pair_gap": 0, + "signal_layer": "In1.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + }, + { + "bottom_reference_layer": "UNDEFINED", + "delay": 1000000, + "diff_pair_gap": 0, + "signal_layer": "In2.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + }, + { + "bottom_reference_layer": "UNDEFINED", + "delay": 2000000, + "diff_pair_gap": 0, + "signal_layer": "B.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + } + ], + "profile_name": "CLASS3", + "target_impedance": 0.0, + "type": 0, + "via_overrides": [], + "via_prop_delay": 0 + }, + { + "enable_time_domain_tuning": true, + "generate_drc_rules": false, + "layer_entries": [ + { + "bottom_reference_layer": "UNDEFINED", + "delay": 1000000, + "diff_pair_gap": 0, + "signal_layer": "F.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + }, + { + "bottom_reference_layer": "UNDEFINED", + "delay": 0, + "diff_pair_gap": 0, + "signal_layer": "In1.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + }, + { + "bottom_reference_layer": "UNDEFINED", + "delay": 0, + "diff_pair_gap": 0, + "signal_layer": "In2.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + }, + { + "bottom_reference_layer": "UNDEFINED", + "delay": 1000000, + "diff_pair_gap": 0, + "signal_layer": "B.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + } + ], + "profile_name": "CLASS4", + "target_impedance": 0.0, + "type": 0, + "via_overrides": [], + "via_prop_delay": 1000000 + }, + { + "enable_time_domain_tuning": true, + "generate_drc_rules": false, + "layer_entries": [ + { + "bottom_reference_layer": "UNDEFINED", + "delay": 1000000, + "diff_pair_gap": 0, + "signal_layer": "F.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + }, + { + "bottom_reference_layer": "UNDEFINED", + "delay": 0, + "diff_pair_gap": 0, + "signal_layer": "In1.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + }, + { + "bottom_reference_layer": "UNDEFINED", + "delay": 0, + "diff_pair_gap": 0, + "signal_layer": "In2.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + }, + { + "bottom_reference_layer": "UNDEFINED", + "delay": 1000000, + "diff_pair_gap": 0, + "signal_layer": "B.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + } + ], + "profile_name": "CLASS5", + "target_impedance": 0.0, + "type": 0, + "via_overrides": [ + { + "delay": 20000000, + "signal_layer_from": "F.Cu", + "signal_layer_to": "B.Cu", + "via_layer_from": "F.Cu", + "via_layer_to": "B.Cu" + } + ], + "via_prop_delay": 0 + }, + { + "enable_time_domain_tuning": true, + "generate_drc_rules": false, + "layer_entries": [ + { + "bottom_reference_layer": "UNDEFINED", + "delay": 1000000, + "diff_pair_gap": 0, + "signal_layer": "F.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + }, + { + "bottom_reference_layer": "UNDEFINED", + "delay": 2000000, + "diff_pair_gap": 0, + "signal_layer": "In1.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + }, + { + "bottom_reference_layer": "UNDEFINED", + "delay": 0, + "diff_pair_gap": 0, + "signal_layer": "In2.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + }, + { + "bottom_reference_layer": "UNDEFINED", + "delay": 0, + "diff_pair_gap": 0, + "signal_layer": "B.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + } + ], + "profile_name": "CLASS6", + "target_impedance": 0.0, + "type": 0, + "via_overrides": [ + { + "delay": 10000000, + "signal_layer_from": "F.Cu", + "signal_layer_to": "In1.Cu", + "via_layer_from": "F.Cu", + "via_layer_to": "In1.Cu" + }, + { + "delay": 20000000, + "signal_layer_from": "F.Cu", + "signal_layer_to": "In1.Cu", + "via_layer_from": "F.Cu", + "via_layer_to": "In2.Cu" + } + ], + "via_prop_delay": 0 + }, + { + "enable_time_domain_tuning": true, + "generate_drc_rules": false, + "layer_entries": [ + { + "bottom_reference_layer": "UNDEFINED", + "delay": 1000000, + "diff_pair_gap": 0, + "signal_layer": "F.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + }, + { + "bottom_reference_layer": "UNDEFINED", + "delay": 0, + "diff_pair_gap": 0, + "signal_layer": "In1.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + }, + { + "bottom_reference_layer": "UNDEFINED", + "delay": 0, + "diff_pair_gap": 0, + "signal_layer": "In2.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + }, + { + "bottom_reference_layer": "UNDEFINED", + "delay": 0, + "diff_pair_gap": 0, + "signal_layer": "B.Cu", + "top_reference_layer": "UNDEFINED", + "width": 0 + } + ], + "profile_name": "CLASS7", + "target_impedance": 0.0, + "type": 0, + "via_overrides": [], + "via_prop_delay": 0 + } + ] } } diff --git a/qa/pcbnew_utils/board_test_utils.cpp b/qa/pcbnew_utils/board_test_utils.cpp index 34850d14cb..03190da048 100644 --- a/qa/pcbnew_utils/board_test_utils.cpp +++ b/qa/pcbnew_utils/board_test_utils.cpp @@ -147,10 +147,10 @@ void LoadBoard( SETTINGS_MANAGER& aSettingsManager, const wxString& aRelPath, return; } - BOOST_TEST_CHECKPOINT( "Synchronize Time Domain Properties" ); + BOOST_TEST_CHECKPOINT( "Synchronize Tuning Profile Properties" ); try { - aBoard->GetLengthCalculation()->SynchronizeTimeDomainProperties(); + aBoard->GetLengthCalculation()->SynchronizeTuningProfileProperties(); } catch( const std::exception& e ) { diff --git a/qa/tests/pcbnew/CMakeLists.txt b/qa/tests/pcbnew/CMakeLists.txt index eec28c9d90..5b50b714db 100644 --- a/qa/tests/pcbnew/CMakeLists.txt +++ b/qa/tests/pcbnew/CMakeLists.txt @@ -77,6 +77,7 @@ set( QA_PCBNEW_SRCS drc/test_drc_lengths.cpp drc/test_drc_unconnected_items_exclusion_loss.cpp drc/test_drc_via_dangling.cpp + drc/test_drc_tuning_profiles.cpp pcb_io/altium/test_altium_rule_transformer.cpp pcb_io/altium/test_altium_pcblib_import.cpp diff --git a/qa/tests/pcbnew/drc/test_drc_tuning_profiles.cpp b/qa/tests/pcbnew/drc/test_drc_tuning_profiles.cpp new file mode 100644 index 0000000000..12894db2ef --- /dev/null +++ b/qa/tests/pcbnew/drc/test_drc_tuning_profiles.cpp @@ -0,0 +1,96 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright The KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include +#include + + +struct DRC_REGRESSION_TEST_FIXTURE +{ + DRC_REGRESSION_TEST_FIXTURE() : + m_settingsManager( true /* headless */ ) + { + } + + SETTINGS_MANAGER m_settingsManager; + std::unique_ptr m_board; +}; + + +BOOST_FIXTURE_TEST_CASE( DRCTuningProfiles, DRC_REGRESSION_TEST_FIXTURE ) +{ + std::vector> tests = { { "drc_missing_tuning_profile", 2 } }; + + for( const std::pair& test : tests ) + { + KI_TEST::LoadBoard( m_settingsManager, test.first, m_board ); + KI_TEST::FillZones( m_board.get() ); + + std::vector violations; + BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); + + // These DRC tests are not useful and do not work because they need a footprint library + // associated to the board + bds.m_DRCSeverities[DRCE_LIB_FOOTPRINT_ISSUES] = SEVERITY::RPT_SEVERITY_IGNORE; + bds.m_DRCSeverities[DRCE_LIB_FOOTPRINT_MISMATCH] = SEVERITY::RPT_SEVERITY_IGNORE; + bds.m_DRCSeverities[DRCE_DANGLING_VIA] = SEVERITY::RPT_SEVERITY_IGNORE; + + // Ensure that our desired error is fired + bds.m_DRCSeverities[DRCE_MISSING_TUNING_PROFILE] = SEVERITY::RPT_SEVERITY_ERROR; + + bds.m_DRCEngine->SetViolationHandler( + [&]( const std::shared_ptr& aItem, const VECTOR2I& aPos, int aLayer, + const std::function& aPathGenerator ) + { + if( bds.GetSeverity( aItem->GetErrorCode() ) == SEVERITY::RPT_SEVERITY_ERROR ) + violations.push_back( *aItem ); + } ); + + bds.m_DRCEngine->RunTests( EDA_UNITS::MM, true, false ); + + if( violations.size() == test.second ) + { + BOOST_CHECK_EQUAL( 1, 1 ); // quiet "did not check any assertions" warning + BOOST_TEST_MESSAGE( wxString::Format( "DRC missing tuning profile: %s, passed", test.first ) ); + } + else + { + UNITS_PROVIDER unitsProvider( pcbIUScale, EDA_UNITS::INCH ); + + std::map itemMap; + m_board->FillItemMap( itemMap ); + + for( const DRC_ITEM& item : violations ) + { + BOOST_TEST_MESSAGE( item.ShowReport( &unitsProvider, RPT_SEVERITY_ERROR, itemMap ) ); + } + + BOOST_ERROR( wxString::Format( "DRC missing tuning profile: %s, failed (violations found %d expected %d)", + test.first, (int) violations.size(), test.second ) ); + } + } +} diff --git a/qa/tools/pns/pns_log_viewer_frame.h b/qa/tools/pns/pns_log_viewer_frame.h index 46f0776588..e6f27dcf2c 100644 --- a/qa/tools/pns/pns_log_viewer_frame.h +++ b/qa/tools/pns/pns_log_viewer_frame.h @@ -194,7 +194,7 @@ public: const int aDiffPairCouplingGap, const int aPNSLayer, const NETCLASS* aNetClass ) override { - TIME_DOMAIN_GEOMETRY_CONTEXT ctx; + TUNING_PROFILE_GEOMETRY_CONTEXT ctx; ctx.NetClass = aNetClass; ctx.Width = aWidth; ctx.IsDiffPairCoupled = aIsDiffPairCoupled; @@ -208,7 +208,7 @@ public: int aDiffPairCouplingGap, int aPNSLayer, const NETCLASS* aNetClass ) override { - TIME_DOMAIN_GEOMETRY_CONTEXT ctx; + TUNING_PROFILE_GEOMETRY_CONTEXT ctx; ctx.NetClass = aNetClass; ctx.Width = aWidth; ctx.IsDiffPairCoupled = aIsDiffPairCoupled;