From bde9c2cbc542ed7cf6c14cd162122f177000b94d Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Wed, 5 Jul 2023 18:25:52 +0100 Subject: [PATCH] ADDED FFT analyses. CHANGED abandon the unpredictable behaviour of the Simulation Command dialog. You now separately add simulation tabs (which have invariant command types once created), and the dialog edits the current tab. Also a bunch of bug fixes to make multiple simulation plots actually work. --- common/bitmap_info.cpp | 1 + common/widgets/mathplot.cpp | 8 +- eeschema/dialogs/dialog_sim_command.cpp | 213 +- eeschema/dialogs/dialog_sim_command.h | 30 +- eeschema/dialogs/dialog_sim_command_base.cpp | 414 +- eeschema/dialogs/dialog_sim_command_base.fbp | 3409 +++++++++-------- eeschema/dialogs/dialog_sim_command_base.h | 96 +- .../dialogs/dialog_symbol_fields_table.cpp | 1 + .../dialogs/dialog_user_defined_signals.cpp | 2 +- .../netlist_exporter_spice.cpp | 28 +- .../netlist_exporter_spice.h | 7 +- eeschema/sim/ngspice.cpp | 23 +- eeschema/sim/ngspice.h | 4 +- eeschema/sim/ngspice_circuit_model.cpp | 56 +- eeschema/sim/ngspice_circuit_model.h | 65 +- eeschema/sim/sim_plot_panel.cpp | 53 +- eeschema/sim/sim_plot_panel.h | 25 +- eeschema/sim/sim_plot_panel_base.cpp | 23 +- eeschema/sim/sim_plot_panel_base.h | 30 +- eeschema/sim/sim_types.h | 14 +- eeschema/sim/simulator.h | 3 +- eeschema/sim/simulator_frame.cpp | 208 +- eeschema/sim/simulator_frame.h | 16 +- eeschema/sim/simulator_panel.cpp | 414 +- eeschema/sim/simulator_panel.h | 34 +- eeschema/sim/simulator_panel_base.cpp | 2 + eeschema/sim/simulator_panel_base.fbp | 17 +- eeschema/sim/simulator_panel_base.h | 1 + eeschema/sim/spice_simulator.cpp | 23 +- eeschema/sim/toolbars_simulator_frame.cpp | 2 + eeschema/sim/user_defined_signals_help_md.h | 4 +- eeschema/tools/ee_actions.cpp | 8 +- eeschema/tools/ee_actions.h | 1 - eeschema/tools/simulator_control.cpp | 168 +- eeschema/tools/simulator_control.h | 3 + include/bitmaps/bitmaps_list.h | 1 + include/widgets/mathplot.h | 5 +- qa/tests/spice/test_ngspice_helpers.cpp | 24 +- resources/bitmaps_png/CMakeLists.txt | 1 + resources/bitmaps_png/png/sim_add_plot_24.png | Bin 0 -> 1141 bytes .../sources/light/sim_add_plot.svg | 148 + 41 files changed, 3057 insertions(+), 2528 deletions(-) create mode 100644 resources/bitmaps_png/png/sim_add_plot_24.png create mode 100644 resources/bitmaps_png/sources/light/sim_add_plot.svg diff --git a/common/bitmap_info.cpp b/common/bitmap_info.cpp index 6ce70852e4..ee79a5f1e0 100644 --- a/common/bitmap_info.cpp +++ b/common/bitmap_info.cpp @@ -481,6 +481,7 @@ void BuildBitmapInfo( std::unordered_map>& aBi aBitmapInfoCache[BITMAPS::shape_3d_back].emplace_back( BITMAPS::shape_3d_back, wxT( "shape_3d_back_24.png" ), 24, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::sheetset].emplace_back( BITMAPS::sheetset, wxT( "sheetset_24.png" ), 24, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::simulator].emplace_back( BITMAPS::simulator, wxT( "simulator_24.png" ), 24, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::sim_add_plot].emplace_back( BITMAPS::sim_add_plot, wxT( "sim_add_plot_24.png" ), 24, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::sim_command].emplace_back( BITMAPS::sim_command, wxT( "sim_command_24.png" ), 24, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::sim_run].emplace_back( BITMAPS::sim_run, wxT( "sim_run_24.png" ), 24, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::sim_stop].emplace_back( BITMAPS::sim_stop, wxT( "sim_stop_24.png" ), 24, wxT( "light" ) ); diff --git a/common/widgets/mathplot.cpp b/common/widgets/mathplot.cpp index 3b715c8947..eeb888113b 100644 --- a/common/widgets/mathplot.cpp +++ b/common/widgets/mathplot.cpp @@ -1676,12 +1676,8 @@ mpWindow::mpWindow() : } } -mpWindow::mpWindow( wxWindow* parent, - wxWindowID id, - const wxPoint& pos, - const wxSize& size, - long flag ) - : wxWindow( parent, id, pos, size, flag, wxT( "mathplot" ) ) +mpWindow::mpWindow( wxWindow* parent, wxWindowID id ) : + wxWindow( parent, id, wxDefaultPosition, wxDefaultSize, 0, wxT( "mathplot" ) ) { m_zooming = false; m_scaleX = m_scaleY = 1.0; diff --git a/eeschema/dialogs/dialog_sim_command.cpp b/eeschema/dialogs/dialog_sim_command.cpp index 7c11045a1d..6b62c6c358 100644 --- a/eeschema/dialogs/dialog_sim_command.cpp +++ b/eeschema/dialogs/dialog_sim_command.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2016-2022 CERN - * Copyright (C) 2016-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors. * @author Maciej Suminski * * This program is free software; you can redistribute it and/or @@ -26,6 +26,7 @@ #include "dialog_sim_command.h" #include #include +#include #include @@ -56,10 +57,11 @@ static wxString getStringSelection( const wxChoice* aCtrl ) } -DIALOG_SIM_COMMAND::DIALOG_SIM_COMMAND( wxWindow* aParent, +DIALOG_SIM_COMMAND::DIALOG_SIM_COMMAND( SIMULATOR_FRAME* aParent, std::shared_ptr aCircuitModel, std::shared_ptr& aSettings ) : DIALOG_SIM_COMMAND_BASE( aParent ), + m_simulatorFrame( aParent ), m_circuitModel( aCircuitModel ), m_settings( aSettings ), m_spiceEmptyValidator( true ) @@ -91,6 +93,8 @@ DIALOG_SIM_COMMAND::DIALOG_SIM_COMMAND( wxWindow* aParent, m_transInitial->SetValidator( m_spiceEmptyValidator ); m_transMaxStep->SetValidator( m_spiceEmptyValidator ); + m_inputSignalsFilter->SetDescriptiveText( _( "Filter" ) ); + wxChar type1 = getStringSelection( m_dcSourceType1 ).Upper().GetChar( 0 ); updateDCSources( type1, m_dcSource1 ); @@ -112,15 +116,6 @@ DIALOG_SIM_COMMAND::DIALOG_SIM_COMMAND( wxWindow* aParent, m_noiseSrc->Append( item.refName ); } - refreshUIControls(); - - // Hide pages that aren't fully implemented yet - // wxPanel::Hide() isn't enough on some platforms - m_simPages->RemovePage( m_simPages->FindPage( m_pgDistortion ) ); - m_simPages->RemovePage( m_simPages->FindPage( m_pgPoleZero ) ); - m_simPages->RemovePage( m_simPages->FindPage( m_pgSensitivity ) ); - m_simPages->RemovePage( m_simPages->FindPage( m_pgTransferFunction ) ); - if( !dynamic_cast( aSettings.get() ) ) m_compatibilityMode->Show( false ); @@ -158,6 +153,7 @@ bool DIALOG_SIM_COMMAND::TransferDataToWindow() if( m_simCommand.IsEmpty() && !empty( m_customTxt ) ) parseCommand( m_customTxt->GetValue() ); + refreshUIControls(); return true; } @@ -225,7 +221,7 @@ bool DIALOG_SIM_COMMAND::TransferDataFromWindow() wxString previousSimCommand = m_simCommand; wxWindow* page = m_simPages->GetCurrentPage(); - if( page == m_pgAC ) // AC analysis + if( page == m_pgAC ) // AC small-signal analysis { if( !m_pgAC->Validate() ) return false; @@ -236,7 +232,7 @@ bool DIALOG_SIM_COMMAND::TransferDataFromWindow() SPICE_VALUE( m_acFreqStart->GetValue() ).ToSpiceString(), SPICE_VALUE( m_acFreqStop->GetValue() ).ToSpiceString() ); } - else if( page == m_pgSP ) // S-params analysis + else if( page == m_pgSP ) // S-params analysis { if( !m_pgSP->Validate() ) return false; @@ -276,7 +272,22 @@ bool DIALOG_SIM_COMMAND::TransferDataFromWindow() m_simCommand = simCmd; } - else if( page == m_pgNoise ) // Noise analysis + else if( page == m_pgFFT ) // Fast Fourier transform + { + wxString vectors; + + for( int ii = 0; ii < (int) m_inputSignalsList->GetCount(); ++ii ) + { + if( m_inputSignalsList->IsChecked( ii ) ) + vectors += wxS( " " ) + m_inputSignalsList->GetString( ii ); + } + + if( m_linearize->IsChecked() ) + m_simCommand = wxT( "linearize" ) + vectors + wxS( "\n" ); + + m_simCommand = wxT( "fft" ) + vectors; + } + else if( page == m_pgNOISE ) // Noise analysis { wxString output = m_noiseMeas->GetStringSelection(); wxString ref = m_noiseRef->GetStringSelection(); @@ -305,9 +316,9 @@ bool DIALOG_SIM_COMMAND::TransferDataFromWindow() { m_simCommand = wxString( ".op" ); } - else if( page == m_pgTransient ) // Transient analysis + else if( page == m_pgTRAN ) // Transient analysis { - if( !m_pgTransient->Validate() ) + if( !m_pgTRAN->Validate() ) return false; const wxString spc = wxS( " " ); @@ -430,11 +441,37 @@ void DIALOG_SIM_COMMAND::parseCommand( const wxString& aCommand ) if( aCommand.IsEmpty() ) return; - wxStringTokenizer tokenizer( aCommand, " " ); + if( aCommand == wxT( "*" ) ) + { + SetTitle( _( "New Simulation" ) ); + + m_commandType->Clear(); + + for( SIM_TYPE type : { ST_AC, ST_DC, ST_NOISE, ST_OP, ST_TRAN, ST_SP, ST_FFT } ) + { + m_commandType->Append( SPICE_SIMULATOR::TypeToName( type, true ) + + wxT( " \u2014 " ) + + SPICE_SIMULATOR::TypeToName( type, false ) ); + } + + m_commandTypeSizer->Show( true ); + return; + } + + SIM_TYPE simType = NGSPICE_CIRCUIT_MODEL::CommandToSimType( aCommand ); + + SetTitle( SPICE_SIMULATOR::TypeToName( simType, true ) + + wxT( " \u2014 " ) + + SPICE_SIMULATOR::TypeToName( simType, false ) ); + + m_commandTypeSizer->Show( false ); + + wxStringTokenizer tokenizer( aCommand, wxS( " \t\n\r" ), wxTOKEN_STRTOK ); wxString token = tokenizer.GetNextToken().Lower(); - if( token == ".ac" ) + switch( simType ) { + case ST_AC: m_simPages->SetSelection( m_simPages->FindPage( m_pgAC ) ); token = tokenizer.GetNextToken().Lower(); @@ -451,9 +488,9 @@ void DIALOG_SIM_COMMAND::parseCommand( const wxString& aCommand ) m_acPointsNumber->SetValue( tokenizer.GetNextToken() ); m_acFreqStart->SetValue( SPICE_VALUE( tokenizer.GetNextToken() ).ToSpiceString() ); m_acFreqStop->SetValue( SPICE_VALUE( tokenizer.GetNextToken() ).ToSpiceString() ); - } - else if( token == ".sp" ) - { + break; + + case ST_SP: m_simPages->SetSelection( m_simPages->FindPage( m_pgSP ) ); token = tokenizer.GetNextToken().Lower(); @@ -472,11 +509,11 @@ void DIALOG_SIM_COMMAND::parseCommand( const wxString& aCommand ) m_spFreqStop->SetValue( SPICE_VALUE( tokenizer.GetNextToken() ).ToSpiceString() ); if( tokenizer.HasMoreTokens() ) - m_spDoNoise->SetValue( - SPICE_VALUE( tokenizer.GetNextToken() ).ToSpiceString() == "1" ? true - : false ); - } - else if( token == ".dc" ) + m_spDoNoise->SetValue( SPICE_VALUE( tokenizer.GetNextToken() ).ToSpiceString() == "1" ); + + break; + + case ST_DC: { m_simPages->SetSelection( m_simPages->FindPage( m_pgDC ) ); @@ -512,11 +549,12 @@ void DIALOG_SIM_COMMAND::parseCommand( const wxString& aCommand ) m_dcEnable2->SetValue( true ); } - refreshUIControls(); + break; } - else if( token == ".noise" ) + + case ST_NOISE: { - m_simPages->SetSelection( m_simPages->FindPage( m_pgNoise ) ); + m_simPages->SetSelection( m_simPages->FindPage( m_pgNOISE ) ); wxString output; wxString ref; @@ -548,10 +586,11 @@ void DIALOG_SIM_COMMAND::parseCommand( const wxString& aCommand ) m_noiseFreqStop->SetValue( fStop.ToSpiceString() ); m_saveAllNoise->SetValue( saveAll ); + break; } - else if( token == ".tran" ) - { - m_simPages->SetSelection( m_simPages->FindPage( m_pgTransient ) ); + + case ST_TRAN: + m_simPages->SetSelection( m_simPages->FindPage( m_pgTRAN ) ); // If the fields below are empty, it will be caught by the exception handler m_transStep->SetValue( SPICE_VALUE( tokenizer.GetNextToken() ).ToSpiceString() ); @@ -574,14 +613,51 @@ void DIALOG_SIM_COMMAND::parseCommand( const wxString& aCommand ) if( token.IsSameAs( wxS( "uic" ) ) ) m_useInitialConditions->SetValue( true ); - } - else if( token == ".op" ) - { + + break; + + case ST_OP: m_simPages->SetSelection( m_simPages->FindPage( m_pgOP ) ); - } - else if( !empty( m_customTxt ) ) // Custom directives + break; + + case ST_FFT: { + m_simPages->SetSelection( m_simPages->FindPage( m_pgFFT ) ); + + while( tokenizer.HasMoreTokens() ) + m_fftInputSignals.insert( tokenizer.GetNextToken() ); + + break; + } + + default: m_simPages->SetSelection( m_simPages->FindPage( m_pgCustom ) ); + break; + } +} + + +void DIALOG_SIM_COMMAND::OnCommandType( wxCommandEvent& event ) +{ + int sel = ST_UNKNOWN; + wxString str = m_commandType->GetString( event.GetSelection() ); + + for( int type = ST_UNKNOWN; type < ST_LAST; ++type ) + { + if( str.StartsWith( SPICE_SIMULATOR::TypeToName( (SIM_TYPE) type, true ) ) ) + sel = type; + } + + switch( sel ) + { + case ST_AC: m_simPages->SetSelection( m_simPages->FindPage( m_pgAC ) ); break; + case ST_SP: m_simPages->SetSelection( m_simPages->FindPage( m_pgSP ) ); break; + case ST_DC: m_simPages->SetSelection( m_simPages->FindPage( m_pgDC ) ); break; + case ST_NOISE: m_simPages->SetSelection( m_simPages->FindPage( m_pgNOISE ) ); break; + case ST_TRAN: m_simPages->SetSelection( m_simPages->FindPage( m_pgTRAN ) ); break; + case ST_OP: m_simPages->SetSelection( m_simPages->FindPage( m_pgOP ) ); break; + case ST_FFT: m_simPages->SetSelection( m_simPages->FindPage( m_pgFFT ) ); break; + default: m_simPages->SetSelection( m_simPages->FindPage( m_pgCustom ) ); break; } } @@ -619,6 +695,22 @@ void DIALOG_SIM_COMMAND::onSwapDCSources( wxCommandEvent& event ) } +void DIALOG_SIM_COMMAND::onDCSource1Selected( wxCommandEvent& event ) +{ + wxChar type = m_dcSourceType1->GetString( m_dcSourceType1->GetSelection() ).Upper()[ 0 ]; + updateDCSources( type, m_dcSource1 ); + updateDCUnits( type, m_dcSource1, m_src1DCStartValUnit, m_src1DCEndValUnit, m_src1DCStepUnit ); +} + + +void DIALOG_SIM_COMMAND::onDCSource2Selected( wxCommandEvent& event ) +{ + wxChar type = m_dcSourceType2->GetString( m_dcSourceType2->GetSelection() ).Upper()[ 0 ]; + updateDCSources( type, m_dcSource2 ); + updateDCUnits( type, m_dcSource2, m_src2DCStartValUnit, m_src2DCEndValUnit, m_src2DCStepUnit ); +} + + void DIALOG_SIM_COMMAND::onDCEnableSecondSource( wxCommandEvent& event ) { bool is2ndSrcEnabled = m_dcEnable2->IsChecked(); @@ -661,3 +753,50 @@ void DIALOG_SIM_COMMAND::loadDirectives() } +void DIALOG_SIM_COMMAND::OnFilterText( wxCommandEvent& aEvent ) +{ + for( int ii = 0; ii < (int) m_inputSignalsList->GetCount(); ++ii ) + { + if( m_inputSignalsList->IsChecked( ii ) ) + m_fftInputSignals.insert( m_inputSignalsList->GetString( ii ) ); + else + m_fftInputSignals.erase( m_inputSignalsList->GetString( ii ) ); + } + + m_inputSignalsList->Clear(); + + wxString aFilter = m_inputSignalsFilter->GetValue(); + + if( aFilter.IsEmpty() ) + aFilter = wxS( "*" ); + + EDA_COMBINED_MATCHER matcher( aFilter.Upper(), CTX_SIGNAL ); + + for( const wxString& signal : m_simulatorFrame->Signals() ) + { + if( matcher.Find( signal.Upper() ) ) + { + m_inputSignalsList->Append( signal ); + + if( m_fftInputSignals.count( signal ) ) + m_inputSignalsList->Check( m_inputSignalsList->GetCount() - 1 ); + } + } +} + + +void DIALOG_SIM_COMMAND::OnFilterMouseMoved( wxMouseEvent& aEvent ) +{ + wxPoint pos = aEvent.GetPosition(); + wxRect ctrlRect = m_inputSignalsFilter->GetScreenRect(); + int buttonWidth = ctrlRect.GetHeight(); // Presume buttons are square + + if( m_inputSignalsFilter->IsSearchButtonVisible() && pos.x < buttonWidth ) + SetCursor( wxCURSOR_ARROW ); + else if( m_inputSignalsFilter->IsCancelButtonVisible() && pos.x > ctrlRect.GetWidth() - buttonWidth ) + SetCursor( wxCURSOR_ARROW ); + else + SetCursor( wxCURSOR_IBEAM ); +} + + diff --git a/eeschema/dialogs/dialog_sim_command.h b/eeschema/dialogs/dialog_sim_command.h index dee7b272cd..d8dbc6341a 100644 --- a/eeschema/dialogs/dialog_sim_command.h +++ b/eeschema/dialogs/dialog_sim_command.h @@ -35,12 +35,13 @@ class NGSPICE_CIRCUIT_MODEL; class SPICE_SIMULATOR_SETTINGS; +class SIMULATOR_FRAME; class DIALOG_SIM_COMMAND : public DIALOG_SIM_COMMAND_BASE { public: - DIALOG_SIM_COMMAND( wxWindow* aParent, std::shared_ptr aCircuitModel, + DIALOG_SIM_COMMAND( SIMULATOR_FRAME* aParent, std::shared_ptr aCircuitModel, std::shared_ptr& aSettings ); const wxString& GetSimCommand() const @@ -52,6 +53,7 @@ public: { parseCommand( aCommand ); m_simCommand = aCommand; + refreshUIControls(); } int GetSimOptions() const @@ -107,6 +109,7 @@ private: wxQueueEvent( m_dcEnable2, new wxCommandEvent( wxEVT_CHECKBOX ) ); wxQueueEvent( m_dcSourceType1, new wxCommandEvent( wxEVT_RADIOBOX ) ); wxQueueEvent( m_dcSourceType2, new wxCommandEvent( wxEVT_RADIOBOX ) ); + wxQueueEvent( m_inputSignalsFilter, new wxCommandEvent( wxEVT_TEXT ) ); } /** @@ -151,23 +154,8 @@ private: void onDCEnableSecondSource( wxCommandEvent& event ) override; void onSwapDCSources( wxCommandEvent& event ) override; - void onDCSource1Selected( wxCommandEvent& event ) override - { - wxChar type = - m_dcSourceType1->GetString( m_dcSourceType1->GetSelection() ).Upper().GetChar( 0 ); - updateDCSources( type, m_dcSource1 ); - updateDCUnits( type, m_dcSource1, m_src1DCStartValUnit, m_src1DCEndValUnit, - m_src1DCStepUnit ); - } - - void onDCSource2Selected( wxCommandEvent& event ) override - { - wxChar type = - m_dcSourceType2->GetString( m_dcSourceType2->GetSelection() ).Upper().GetChar( 0 ); - updateDCSources( type, m_dcSource2 ); - updateDCUnits( type, m_dcSource2, m_src2DCStartValUnit, m_src2DCEndValUnit, - m_src2DCStepUnit ); - } + void onDCSource1Selected( wxCommandEvent& event ) override; + void onDCSource2Selected( wxCommandEvent& event ) override; static wxString scaleToString( int aOption ) { @@ -180,15 +168,21 @@ private: } } + void OnCommandType( wxCommandEvent& event ) override; + void OnFilterMouseMoved( wxMouseEvent& event ) override; + void OnFilterText( wxCommandEvent& event ) override; + void loadDirectives(); private: + SIMULATOR_FRAME* m_simulatorFrame; wxString m_simCommand; std::shared_ptr m_circuitModel; std::shared_ptr m_settings; SPICE_VALIDATOR m_spiceValidator; SPICE_VALIDATOR m_spiceEmptyValidator; wxIntegerValidator m_posIntValidator; + std::set m_fftInputSignals; }; #endif /* DIALOG_SIM_COMMAND_H */ diff --git a/eeschema/dialogs/dialog_sim_command_base.cpp b/eeschema/dialogs/dialog_sim_command_base.cpp index cec533a98f..60542c08ab 100644 --- a/eeschema/dialogs/dialog_sim_command_base.cpp +++ b/eeschema/dialogs/dialog_sim_command_base.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version 3.10.1-88b0f50) +// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b) // http://www.wxformbuilder.org/ // // PLEASE DO *NOT* EDIT THIS FILE! @@ -16,7 +16,22 @@ DIALOG_SIM_COMMAND_BASE::DIALOG_SIM_COMMAND_BASE( wxWindow* parent, wxWindowID i wxBoxSizer* bSizer1; bSizer1 = new wxBoxSizer( wxVERTICAL ); - m_simPages = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + m_commandTypeSizer = new wxBoxSizer( wxHORIZONTAL ); + + m_commandTypeLabel = new wxStaticText( this, wxID_ANY, _("Simulation type:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_commandTypeLabel->Wrap( -1 ); + m_commandTypeSizer->Add( m_commandTypeLabel, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + wxString m_commandTypeChoices[] = { _("AC"), _("DC"), _("OP"), _("TRAN"), _("FFT"), _("NOISE"), _("SP"), _("Custom") }; + int m_commandTypeNChoices = sizeof( m_commandTypeChoices ) / sizeof( wxString ); + m_commandType = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_commandTypeNChoices, m_commandTypeChoices, 0 ); + m_commandType->SetSelection( 0 ); + m_commandTypeSizer->Add( m_commandType, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer1->Add( m_commandTypeSizer, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 10 ); + + m_simPages = new wxSimplebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); m_pgAC = new wxPanel( m_simPages, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); wxBoxSizer* bSizer3; bSizer3 = new wxBoxSizer( wxVERTICAL ); @@ -75,69 +90,7 @@ DIALOG_SIM_COMMAND_BASE::DIALOG_SIM_COMMAND_BASE( wxWindow* parent, wxWindowID i m_pgAC->SetSizer( bSizer3 ); m_pgAC->Layout(); bSizer3->Fit( m_pgAC ); - m_simPages->AddPage( m_pgAC, _("AC"), false ); - m_pgSP = new wxPanel( m_simPages, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer31; - bSizer31 = new wxBoxSizer( wxVERTICAL ); - - wxString m_spScaleChoices[] = { _("Decade"), _("Octave"), _("Linear") }; - int m_spScaleNChoices = sizeof( m_spScaleChoices ) / sizeof( wxString ); - m_spScale = new wxRadioBox( m_pgSP, wxID_ANY, _("Frequency scale"), wxDefaultPosition, wxDefaultSize, m_spScaleNChoices, m_spScaleChoices, 1, wxRA_SPECIFY_COLS ); - m_spScale->SetSelection( 0 ); - m_spScale->Hide(); - - bSizer31->Add( m_spScale, 0, wxALL|wxEXPAND, 5 ); - - wxFlexGridSizer* fgSizer12; - fgSizer12 = new wxFlexGridSizer( 0, 3, 5, 0 ); - fgSizer12->SetFlexibleDirection( wxHORIZONTAL ); - fgSizer12->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - m_staticText12 = new wxStaticText( m_pgSP, wxID_ANY, _("Number of points per decade:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText12->Wrap( -1 ); - fgSizer12->Add( m_staticText12, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - - m_spPointsNumber = new wxTextCtrl( m_pgSP, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer12->Add( m_spPointsNumber, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); - - - fgSizer12->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_staticText22 = new wxStaticText( m_pgSP, wxID_ANY, _("Start frequency:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText22->Wrap( -1 ); - fgSizer12->Add( m_staticText22, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - - m_spFreqStart = new wxTextCtrl( m_pgSP, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - m_spFreqStart->SetMinSize( wxSize( 100,-1 ) ); - - fgSizer12->Add( m_spFreqStart, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); - - m_staticText191 = new wxStaticText( m_pgSP, wxID_ANY, _("Hz"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText191->Wrap( -1 ); - fgSizer12->Add( m_staticText191, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 ); - - m_staticText32 = new wxStaticText( m_pgSP, wxID_ANY, _("Stop frequency:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText32->Wrap( -1 ); - fgSizer12->Add( m_staticText32, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - - m_spFreqStop = new wxTextCtrl( m_pgSP, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer12->Add( m_spFreqStop, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); - - m_staticText1101 = new wxStaticText( m_pgSP, wxID_ANY, _("Hz"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText1101->Wrap( -1 ); - fgSizer12->Add( m_staticText1101, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 ); - - m_spDoNoise = new wxCheckBox( m_pgSP, wxID_ANY, _("Compute noise current correlation matrix"), wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer12->Add( m_spDoNoise, 0, wxALL, 5 ); - - - bSizer31->Add( fgSizer12, 0, wxEXPAND|wxALL, 5 ); - - - m_pgSP->SetSizer( bSizer31 ); - m_pgSP->Layout(); - bSizer31->Fit( m_pgSP ); - m_simPages->AddPage( m_pgSP, _("S-params"), false ); + m_simPages->AddPage( m_pgAC, _("a page"), false ); m_pgDC = new wxPanel( m_simPages, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); wxBoxSizer* bSizer82; bSizer82 = new wxBoxSizer( wxVERTICAL ); @@ -267,10 +220,126 @@ DIALOG_SIM_COMMAND_BASE::DIALOG_SIM_COMMAND_BASE( wxWindow* parent, wxWindowID i m_pgDC->SetSizer( bSizer82 ); m_pgDC->Layout(); bSizer82->Fit( m_pgDC ); - m_simPages->AddPage( m_pgDC, _("DC Transfer"), false ); - m_pgDistortion = new wxPanel( m_simPages, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_simPages->AddPage( m_pgDistortion, _("Distortion"), false ); - m_pgNoise = new wxPanel( m_simPages, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_simPages->AddPage( m_pgDC, _("a page"), false ); + m_pgOP = new wxPanel( m_simPages, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer8; + bSizer8 = new wxBoxSizer( wxVERTICAL ); + + + m_pgOP->SetSizer( bSizer8 ); + m_pgOP->Layout(); + bSizer8->Fit( m_pgOP ); + m_simPages->AddPage( m_pgOP, _("a page"), false ); + m_pgTRAN = new wxPanel( m_simPages, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer81; + bSizer81 = new wxBoxSizer( wxVERTICAL ); + + wxGridBagSizer* gbSizer2; + gbSizer2 = new wxGridBagSizer( 4, 0 ); + gbSizer2->SetFlexibleDirection( wxBOTH ); + gbSizer2->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + gbSizer2->SetEmptyCellSize( wxSize( -1,8 ) ); + + m_timeLabel = new wxStaticText( m_pgTRAN, wxID_ANY, _("Time step:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_timeLabel->Wrap( -1 ); + gbSizer2->Add( m_timeLabel, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + m_transStep = new wxTextCtrl( m_pgTRAN, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_transStep->SetMinSize( wxSize( 100,-1 ) ); + + gbSizer2->Add( m_transStep, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + m_timeUnits = new wxStaticText( m_pgTRAN, wxID_ANY, _("seconds"), wxDefaultPosition, wxDefaultSize, 0 ); + m_timeUnits->Wrap( -1 ); + gbSizer2->Add( m_timeUnits, wxGBPosition( 0, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + m_transFinalLabel = new wxStaticText( m_pgTRAN, wxID_ANY, _("Final time:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_transFinalLabel->Wrap( -1 ); + gbSizer2->Add( m_transFinalLabel, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + m_transFinal = new wxTextCtrl( m_pgTRAN, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + gbSizer2->Add( m_transFinal, wxGBPosition( 1, 1 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + m_transFinalUnits = new wxStaticText( m_pgTRAN, wxID_ANY, _("seconds"), wxDefaultPosition, wxDefaultSize, 0 ); + m_transFinalUnits->Wrap( -1 ); + gbSizer2->Add( m_transFinalUnits, wxGBPosition( 1, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + m_transInitialLabel = new wxStaticText( m_pgTRAN, wxID_ANY, _("Initial time:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_transInitialLabel->Wrap( -1 ); + gbSizer2->Add( m_transInitialLabel, wxGBPosition( 2, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + m_transInitial = new wxTextCtrl( m_pgTRAN, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + gbSizer2->Add( m_transInitial, wxGBPosition( 2, 1 ), wxGBSpan( 1, 1 ), wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + + m_transInitialUnits = new wxStaticText( m_pgTRAN, wxID_ANY, _("seconds"), wxDefaultPosition, wxDefaultSize, 0 ); + m_transInitialUnits->Wrap( -1 ); + gbSizer2->Add( m_transInitialUnits, wxGBPosition( 2, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + m_transInitialHelp = new wxStaticText( m_pgTRAN, wxID_ANY, _("(optional; default 0)"), wxDefaultPosition, wxDefaultSize, 0 ); + m_transInitialHelp->Wrap( -1 ); + gbSizer2->Add( m_transInitialHelp, wxGBPosition( 2, 3 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + m_maxStepLabel = new wxStaticText( m_pgTRAN, wxID_ANY, _("Max time step:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_maxStepLabel->Wrap( -1 ); + gbSizer2->Add( m_maxStepLabel, wxGBPosition( 3, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + m_transMaxStep = new wxTextCtrl( m_pgTRAN, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + gbSizer2->Add( m_transMaxStep, wxGBPosition( 3, 1 ), wxGBSpan( 1, 1 ), wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + + m_transMaxStepUnit = new wxStaticText( m_pgTRAN, wxID_ANY, _("seconds"), wxDefaultPosition, wxDefaultSize, 0 ); + m_transMaxStepUnit->Wrap( -1 ); + gbSizer2->Add( m_transMaxStepUnit, wxGBPosition( 3, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + m_transMaxHelp = new wxStaticText( m_pgTRAN, wxID_ANY, _("(optional; default min{tstep, (tstop-tstart)/50})"), wxDefaultPosition, wxDefaultSize, 0 ); + m_transMaxHelp->Wrap( -1 ); + gbSizer2->Add( m_transMaxHelp, wxGBPosition( 3, 3 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + m_useInitialConditions = new wxCheckBox( m_pgTRAN, wxID_ANY, _("Use initial conditions"), wxDefaultPosition, wxDefaultSize, 0 ); + gbSizer2->Add( m_useInitialConditions, wxGBPosition( 5, 0 ), wxGBSpan( 1, 3 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + + bSizer81->Add( gbSizer2, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); + + + m_pgTRAN->SetSizer( bSizer81 ); + m_pgTRAN->Layout(); + bSizer81->Fit( m_pgTRAN ); + m_simPages->AddPage( m_pgTRAN, _("a page"), false ); + m_pgFFT = new wxPanel( m_simPages, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer151; + bSizer151 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer14; + bSizer14 = new wxBoxSizer( wxVERTICAL ); + + m_signalsLabel = new wxStaticText( m_pgFFT, wxID_ANY, _("Input signals:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_signalsLabel->Wrap( -1 ); + bSizer14->Add( m_signalsLabel, 0, wxBOTTOM|wxLEFT, 5 ); + + m_inputSignalsFilter = new wxSearchCtrl( m_pgFFT, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + #ifndef __WXMAC__ + m_inputSignalsFilter->ShowSearchButton( true ); + #endif + m_inputSignalsFilter->ShowCancelButton( true ); + bSizer14->Add( m_inputSignalsFilter, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); + + wxArrayString m_inputSignalsListChoices; + m_inputSignalsList = new wxCheckListBox( m_pgFFT, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_inputSignalsListChoices, 0 ); + bSizer14->Add( m_inputSignalsList, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + m_linearize = new wxCheckBox( m_pgFFT, wxID_ANY, _("Linearize inputs before performing FFT"), wxDefaultPosition, wxDefaultSize, 0 ); + m_linearize->SetValue(true); + bSizer14->Add( m_linearize, 0, wxALL, 5 ); + + + bSizer151->Add( bSizer14, 1, wxTOP|wxRIGHT|wxLEFT, 5 ); + + + m_pgFFT->SetSizer( bSizer151 ); + m_pgFFT->Layout(); + bSizer151->Fit( m_pgFFT ); + m_simPages->AddPage( m_pgFFT, _("a page"), false ); + m_pgNOISE = new wxPanel( m_simPages, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); wxBoxSizer* bSizer15; bSizer15 = new wxBoxSizer( wxVERTICAL ); @@ -279,37 +348,37 @@ DIALOG_SIM_COMMAND_BASE::DIALOG_SIM_COMMAND_BASE( wxWindow* parent, wxWindowID i fgSizer7->SetFlexibleDirection( wxBOTH ); fgSizer7->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_staticText14 = new wxStaticText( m_pgNoise, wxID_ANY, _("Measured node:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText14 = new wxStaticText( m_pgNOISE, wxID_ANY, _("Measured node:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText14->Wrap( -1 ); fgSizer7->Add( m_staticText14, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); wxArrayString m_noiseMeasChoices; - m_noiseMeas = new wxChoice( m_pgNoise, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_noiseMeasChoices, 0 ); + m_noiseMeas = new wxChoice( m_pgNOISE, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_noiseMeasChoices, 0 ); m_noiseMeas->SetSelection( 0 ); fgSizer7->Add( m_noiseMeas, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT|wxEXPAND, 5 ); fgSizer7->Add( 0, 0, 1, wxEXPAND, 5 ); - m_staticText15 = new wxStaticText( m_pgNoise, wxID_ANY, _("Reference node:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText15 = new wxStaticText( m_pgNOISE, wxID_ANY, _("Reference node:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText15->Wrap( -1 ); fgSizer7->Add( m_staticText15, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); wxArrayString m_noiseRefChoices; - m_noiseRef = new wxChoice( m_pgNoise, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_noiseRefChoices, 0 ); + m_noiseRef = new wxChoice( m_pgNOISE, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_noiseRefChoices, 0 ); m_noiseRef->SetSelection( 0 ); fgSizer7->Add( m_noiseRef, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT|wxEXPAND, 5 ); - m_staticText23 = new wxStaticText( m_pgNoise, wxID_ANY, _("(optional; default GND)"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText23 = new wxStaticText( m_pgNOISE, wxID_ANY, _("(optional; default GND)"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText23->Wrap( -1 ); fgSizer7->Add( m_staticText23, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - m_staticText16 = new wxStaticText( m_pgNoise, wxID_ANY, _("Noise source:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText16 = new wxStaticText( m_pgNOISE, wxID_ANY, _("Noise source:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText16->Wrap( -1 ); fgSizer7->Add( m_staticText16, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); wxArrayString m_noiseSrcChoices; - m_noiseSrc = new wxChoice( m_pgNoise, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_noiseSrcChoices, 0 ); + m_noiseSrc = new wxChoice( m_pgNOISE, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_noiseSrcChoices, 0 ); m_noiseSrc->SetSelection( 0 ); fgSizer7->Add( m_noiseSrc, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT|wxEXPAND, 5 ); @@ -324,7 +393,7 @@ DIALOG_SIM_COMMAND_BASE::DIALOG_SIM_COMMAND_BASE( wxWindow* parent, wxWindowID i wxString m_noiseScaleChoices[] = { _("Decade"), _("Octave"), _("Linear") }; int m_noiseScaleNChoices = sizeof( m_noiseScaleChoices ) / sizeof( wxString ); - m_noiseScale = new wxRadioBox( m_pgNoise, wxID_ANY, _("Frequency scale"), wxDefaultPosition, wxDefaultSize, m_noiseScaleNChoices, m_noiseScaleChoices, 1, wxRA_SPECIFY_COLS ); + m_noiseScale = new wxRadioBox( m_pgNOISE, wxID_ANY, _("Frequency scale"), wxDefaultPosition, wxDefaultSize, m_noiseScaleNChoices, m_noiseScaleChoices, 1, wxRA_SPECIFY_COLS ); m_noiseScale->SetSelection( 0 ); m_noiseScale->Hide(); @@ -335,11 +404,11 @@ DIALOG_SIM_COMMAND_BASE::DIALOG_SIM_COMMAND_BASE( wxWindow* parent, wxWindowID i fgSizer11->SetFlexibleDirection( wxBOTH ); fgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_staticText11 = new wxStaticText( m_pgNoise, wxID_ANY, _("Number of points per decade:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText11 = new wxStaticText( m_pgNOISE, wxID_ANY, _("Number of points per decade:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText11->Wrap( -1 ); fgSizer11->Add( m_staticText11, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxRIGHT|wxLEFT, 5 ); - m_noisePointsNumber = new wxTextCtrl( m_pgNoise, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_noisePointsNumber = new wxTextCtrl( m_pgNOISE, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_noisePointsNumber->SetMinSize( wxSize( 80,-1 ) ); fgSizer11->Add( m_noisePointsNumber, 1, wxALIGN_CENTER_VERTICAL|wxTOP, 5 ); @@ -347,29 +416,29 @@ DIALOG_SIM_COMMAND_BASE::DIALOG_SIM_COMMAND_BASE( wxWindow* parent, wxWindowID i fgSizer11->Add( 0, 0, 1, wxEXPAND, 5 ); - m_staticText21 = new wxStaticText( m_pgNoise, wxID_ANY, _("Start frequency:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText21 = new wxStaticText( m_pgNOISE, wxID_ANY, _("Start frequency:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText21->Wrap( -1 ); fgSizer11->Add( m_staticText21, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - m_noiseFreqStart = new wxTextCtrl( m_pgNoise, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_noiseFreqStart = new wxTextCtrl( m_pgNOISE, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_noiseFreqStart->SetMinSize( wxSize( 80,-1 ) ); fgSizer11->Add( m_noiseFreqStart, 1, wxALIGN_CENTER_VERTICAL, 5 ); - m_noiseFreqStartUnits = new wxStaticText( m_pgNoise, wxID_ANY, _("Hz"), wxDefaultPosition, wxDefaultSize, 0 ); + m_noiseFreqStartUnits = new wxStaticText( m_pgNOISE, wxID_ANY, _("Hz"), wxDefaultPosition, wxDefaultSize, 0 ); m_noiseFreqStartUnits->Wrap( -1 ); fgSizer11->Add( m_noiseFreqStartUnits, 0, wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticText31 = new wxStaticText( m_pgNoise, wxID_ANY, _("Stop frequency:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText31 = new wxStaticText( m_pgNOISE, wxID_ANY, _("Stop frequency:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText31->Wrap( -1 ); fgSizer11->Add( m_staticText31, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - m_noiseFreqStop = new wxTextCtrl( m_pgNoise, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_noiseFreqStop = new wxTextCtrl( m_pgNOISE, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_noiseFreqStop->SetMinSize( wxSize( 80,-1 ) ); fgSizer11->Add( m_noiseFreqStop, 1, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 ); - m_noiseFreqStopUnits = new wxStaticText( m_pgNoise, wxID_ANY, _("Hz"), wxDefaultPosition, wxDefaultSize, 0 ); + m_noiseFreqStopUnits = new wxStaticText( m_pgNOISE, wxID_ANY, _("Hz"), wxDefaultPosition, wxDefaultSize, 0 ); m_noiseFreqStopUnits->Wrap( -1 ); fgSizer11->Add( m_noiseFreqStopUnits, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); @@ -379,120 +448,77 @@ DIALOG_SIM_COMMAND_BASE::DIALOG_SIM_COMMAND_BASE( wxWindow* parent, wxWindowID i bSizer15->Add( bSizer10, 0, wxEXPAND|wxTOP, 5 ); - m_saveAllNoise = new wxCheckBox( m_pgNoise, wxID_ANY, _("Save contributions from all noise generators"), wxDefaultPosition, wxDefaultSize, 0 ); + m_saveAllNoise = new wxCheckBox( m_pgNOISE, wxID_ANY, _("Save contributions from all noise generators"), wxDefaultPosition, wxDefaultSize, 0 ); + m_saveAllNoise->SetValue(true); bSizer15->Add( m_saveAllNoise, 0, wxALL, 10 ); - m_pgNoise->SetSizer( bSizer15 ); - m_pgNoise->Layout(); - bSizer15->Fit( m_pgNoise ); - m_simPages->AddPage( m_pgNoise, _("Noise"), false ); - m_pgOP = new wxPanel( m_simPages, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer8; - bSizer8 = new wxBoxSizer( wxVERTICAL ); + m_pgNOISE->SetSizer( bSizer15 ); + m_pgNOISE->Layout(); + bSizer15->Fit( m_pgNOISE ); + m_simPages->AddPage( m_pgNOISE, _("a page"), false ); + m_pgSP = new wxPanel( m_simPages, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer31; + bSizer31 = new wxBoxSizer( wxVERTICAL ); + + wxString m_spScaleChoices[] = { _("Decade"), _("Octave"), _("Linear") }; + int m_spScaleNChoices = sizeof( m_spScaleChoices ) / sizeof( wxString ); + m_spScale = new wxRadioBox( m_pgSP, wxID_ANY, _("Frequency scale"), wxDefaultPosition, wxDefaultSize, m_spScaleNChoices, m_spScaleChoices, 1, wxRA_SPECIFY_COLS ); + m_spScale->SetSelection( 0 ); + m_spScale->Hide(); + + bSizer31->Add( m_spScale, 0, wxALL|wxEXPAND, 5 ); + + wxFlexGridSizer* fgSizer12; + fgSizer12 = new wxFlexGridSizer( 0, 3, 5, 0 ); + fgSizer12->SetFlexibleDirection( wxHORIZONTAL ); + fgSizer12->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_staticText12 = new wxStaticText( m_pgSP, wxID_ANY, _("Number of points per decade:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText12->Wrap( -1 ); + fgSizer12->Add( m_staticText12, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + + m_spPointsNumber = new wxTextCtrl( m_pgSP, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer12->Add( m_spPointsNumber, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); - bSizer8->Add( 0, 0, 1, wxEXPAND, 5 ); + fgSizer12->Add( 0, 0, 1, wxEXPAND, 5 ); - m_staticText13 = new wxStaticText( m_pgOP, wxID_ANY, _("This tab has no settings"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText13->Wrap( -1 ); - bSizer8->Add( m_staticText13, 0, wxALIGN_CENTER, 5 ); + m_staticText22 = new wxStaticText( m_pgSP, wxID_ANY, _("Start frequency:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText22->Wrap( -1 ); + fgSizer12->Add( m_staticText22, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + + m_spFreqStart = new wxTextCtrl( m_pgSP, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_spFreqStart->SetMinSize( wxSize( 100,-1 ) ); + + fgSizer12->Add( m_spFreqStart, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); + + m_staticText191 = new wxStaticText( m_pgSP, wxID_ANY, _("Hz"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText191->Wrap( -1 ); + fgSizer12->Add( m_staticText191, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 ); + + m_staticText32 = new wxStaticText( m_pgSP, wxID_ANY, _("Stop frequency:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText32->Wrap( -1 ); + fgSizer12->Add( m_staticText32, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + + m_spFreqStop = new wxTextCtrl( m_pgSP, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer12->Add( m_spFreqStop, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); + + m_staticText1101 = new wxStaticText( m_pgSP, wxID_ANY, _("Hz"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText1101->Wrap( -1 ); + fgSizer12->Add( m_staticText1101, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 ); + + m_spDoNoise = new wxCheckBox( m_pgSP, wxID_ANY, _("Compute noise current correlation matrix"), wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer12->Add( m_spDoNoise, 0, wxALL, 5 ); - bSizer8->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizer31->Add( fgSizer12, 0, wxEXPAND|wxALL, 5 ); - m_pgOP->SetSizer( bSizer8 ); - m_pgOP->Layout(); - bSizer8->Fit( m_pgOP ); - m_simPages->AddPage( m_pgOP, _("Operating Point"), false ); - m_pgPoleZero = new wxPanel( m_simPages, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_pgPoleZero->Hide(); - - m_simPages->AddPage( m_pgPoleZero, _("Pole-Zero"), false ); - m_pgSensitivity = new wxPanel( m_simPages, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_pgSensitivity->Hide(); - - m_simPages->AddPage( m_pgSensitivity, _("Sensitivity"), false ); - m_pgTransferFunction = new wxPanel( m_simPages, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_pgTransferFunction->Hide(); - - m_simPages->AddPage( m_pgTransferFunction, _("Transfer Function"), false ); - m_pgTransient = new wxPanel( m_simPages, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer81; - bSizer81 = new wxBoxSizer( wxVERTICAL ); - - wxGridBagSizer* gbSizer2; - gbSizer2 = new wxGridBagSizer( 4, 0 ); - gbSizer2->SetFlexibleDirection( wxBOTH ); - gbSizer2->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - gbSizer2->SetEmptyCellSize( wxSize( -1,8 ) ); - - m_timeLabel = new wxStaticText( m_pgTransient, wxID_ANY, _("Time step:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_timeLabel->Wrap( -1 ); - gbSizer2->Add( m_timeLabel, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - m_transStep = new wxTextCtrl( m_pgTransient, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - m_transStep->SetMinSize( wxSize( 100,-1 ) ); - - gbSizer2->Add( m_transStep, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - m_timeUnits = new wxStaticText( m_pgTransient, wxID_ANY, _("seconds"), wxDefaultPosition, wxDefaultSize, 0 ); - m_timeUnits->Wrap( -1 ); - gbSizer2->Add( m_timeUnits, wxGBPosition( 0, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - m_transFinalLabel = new wxStaticText( m_pgTransient, wxID_ANY, _("Final time:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_transFinalLabel->Wrap( -1 ); - gbSizer2->Add( m_transFinalLabel, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - m_transFinal = new wxTextCtrl( m_pgTransient, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - gbSizer2->Add( m_transFinal, wxGBPosition( 1, 1 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - m_transFinalUnits = new wxStaticText( m_pgTransient, wxID_ANY, _("seconds"), wxDefaultPosition, wxDefaultSize, 0 ); - m_transFinalUnits->Wrap( -1 ); - gbSizer2->Add( m_transFinalUnits, wxGBPosition( 1, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - m_transInitialLabel = new wxStaticText( m_pgTransient, wxID_ANY, _("Initial time:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_transInitialLabel->Wrap( -1 ); - gbSizer2->Add( m_transInitialLabel, wxGBPosition( 2, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - m_transInitial = new wxTextCtrl( m_pgTransient, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - gbSizer2->Add( m_transInitial, wxGBPosition( 2, 1 ), wxGBSpan( 1, 1 ), wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - m_transInitialUnits = new wxStaticText( m_pgTransient, wxID_ANY, _("seconds"), wxDefaultPosition, wxDefaultSize, 0 ); - m_transInitialUnits->Wrap( -1 ); - gbSizer2->Add( m_transInitialUnits, wxGBPosition( 2, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - m_transInitialHelp = new wxStaticText( m_pgTransient, wxID_ANY, _("(optional; default 0)"), wxDefaultPosition, wxDefaultSize, 0 ); - m_transInitialHelp->Wrap( -1 ); - gbSizer2->Add( m_transInitialHelp, wxGBPosition( 2, 3 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - m_maxStepLabel = new wxStaticText( m_pgTransient, wxID_ANY, _("Max time step:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_maxStepLabel->Wrap( -1 ); - gbSizer2->Add( m_maxStepLabel, wxGBPosition( 3, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - m_transMaxStep = new wxTextCtrl( m_pgTransient, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - gbSizer2->Add( m_transMaxStep, wxGBPosition( 3, 1 ), wxGBSpan( 1, 1 ), wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - m_transMaxStepUnit = new wxStaticText( m_pgTransient, wxID_ANY, _("seconds"), wxDefaultPosition, wxDefaultSize, 0 ); - m_transMaxStepUnit->Wrap( -1 ); - gbSizer2->Add( m_transMaxStepUnit, wxGBPosition( 3, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - m_transMaxHelp = new wxStaticText( m_pgTransient, wxID_ANY, _("(optional; default min{tstep, (tstop-tstart)/50})"), wxDefaultPosition, wxDefaultSize, 0 ); - m_transMaxHelp->Wrap( -1 ); - gbSizer2->Add( m_transMaxHelp, wxGBPosition( 3, 3 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - m_useInitialConditions = new wxCheckBox( m_pgTransient, wxID_ANY, _("Use initial conditions"), wxDefaultPosition, wxDefaultSize, 0 ); - gbSizer2->Add( m_useInitialConditions, wxGBPosition( 5, 0 ), wxGBSpan( 1, 3 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - - bSizer81->Add( gbSizer2, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); - - - m_pgTransient->SetSizer( bSizer81 ); - m_pgTransient->Layout(); - bSizer81->Fit( m_pgTransient ); - m_simPages->AddPage( m_pgTransient, _("Transient"), true ); + m_pgSP->SetSizer( bSizer31 ); + m_pgSP->Layout(); + bSizer31->Fit( m_pgSP ); + m_simPages->AddPage( m_pgSP, _("a page"), false ); m_pgCustom = new wxPanel( m_simPages, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); wxBoxSizer* bSizer2; bSizer2 = new wxBoxSizer( wxVERTICAL ); @@ -513,9 +539,9 @@ DIALOG_SIM_COMMAND_BASE::DIALOG_SIM_COMMAND_BASE( wxWindow* parent, wxWindowID i m_pgCustom->SetSizer( bSizer2 ); m_pgCustom->Layout(); bSizer2->Fit( m_pgCustom ); - m_simPages->AddPage( m_pgCustom, _("Custom"), false ); + m_simPages->AddPage( m_pgCustom, _("a page"), false ); - bSizer1->Add( m_simPages, 1, wxALL|wxEXPAND, 10 ); + bSizer1->Add( m_simPages, 1, wxEXPAND | wxALL, 5 ); wxBoxSizer* bSizer88; bSizer88 = new wxBoxSizer( wxVERTICAL ); @@ -570,10 +596,13 @@ DIALOG_SIM_COMMAND_BASE::DIALOG_SIM_COMMAND_BASE( wxWindow* parent, wxWindowID i // Connect Events this->Connect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( DIALOG_SIM_COMMAND_BASE::onInitDlg ) ); + m_commandType->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SIM_COMMAND_BASE::OnCommandType ), NULL, this ); m_dcEnable2->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SIM_COMMAND_BASE::onDCEnableSecondSource ), NULL, this ); m_dcSourceType1->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SIM_COMMAND_BASE::onDCSource1Selected ), NULL, this ); m_dcSourceType2->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SIM_COMMAND_BASE::onDCSource2Selected ), NULL, this ); m_swapDCSources->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SIM_COMMAND_BASE::onSwapDCSources ), NULL, this ); + m_inputSignalsFilter->Connect( wxEVT_MOTION, wxMouseEventHandler( DIALOG_SIM_COMMAND_BASE::OnFilterMouseMoved ), NULL, this ); + m_inputSignalsFilter->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_SIM_COMMAND_BASE::OnFilterText ), NULL, this ); m_loadDirectives->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SIM_COMMAND_BASE::onLoadDirectives ), NULL, this ); } @@ -581,10 +610,13 @@ DIALOG_SIM_COMMAND_BASE::~DIALOG_SIM_COMMAND_BASE() { // Disconnect Events this->Disconnect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( DIALOG_SIM_COMMAND_BASE::onInitDlg ) ); + m_commandType->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SIM_COMMAND_BASE::OnCommandType ), NULL, this ); m_dcEnable2->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SIM_COMMAND_BASE::onDCEnableSecondSource ), NULL, this ); m_dcSourceType1->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SIM_COMMAND_BASE::onDCSource1Selected ), NULL, this ); m_dcSourceType2->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SIM_COMMAND_BASE::onDCSource2Selected ), NULL, this ); m_swapDCSources->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SIM_COMMAND_BASE::onSwapDCSources ), NULL, this ); + m_inputSignalsFilter->Disconnect( wxEVT_MOTION, wxMouseEventHandler( DIALOG_SIM_COMMAND_BASE::OnFilterMouseMoved ), NULL, this ); + m_inputSignalsFilter->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_SIM_COMMAND_BASE::OnFilterText ), NULL, this ); m_loadDirectives->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SIM_COMMAND_BASE::onLoadDirectives ), NULL, this ); } diff --git a/eeschema/dialogs/dialog_sim_command_base.fbp b/eeschema/dialogs/dialog_sim_command_base.fbp index c1544814e6..a828e01bb1 100644 --- a/eeschema/dialogs/dialog_sim_command_base.fbp +++ b/eeschema/dialogs/dialog_sim_command_base.fbp @@ -64,9 +64,146 @@ none 10 - wxALL|wxEXPAND + wxEXPAND|wxTOP|wxRIGHT|wxLEFT + 0 + + + m_commandTypeSizer + wxHORIZONTAL + protected + + 5 + wxALL|wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Simulation type: + 0 + + 0 + + + 0 + + 1 + m_commandTypeLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALL|wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + "AC" "DC" "OP" "TRAN" "FFT" "NOISE" "SP" "Custom" + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_commandType + 1 + + + protected + 1 + + Resizable + 0 + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnCommandType + + + + + + 5 + wxEXPAND | wxALL 1 - + 1 1 1 @@ -77,7 +214,6 @@ - 1 0 @@ -100,7 +236,7 @@ 0 - -1,-1 + 1 m_simPages 1 @@ -112,18 +248,16 @@ Resizable 1 - - + ; ; forward_declare 0 - - - AC + + a page 0 - + 1 1 1 @@ -174,7 +308,7 @@ wxTAB_TRAVERSAL - + bSizer3 wxVERTICAL @@ -245,11 +379,11 @@ - + 5 wxEXPAND|wxALL 0 - + 3 wxHORIZONTAL @@ -773,729 +907,10 @@ - - - S-params + + a page 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - - 1 - m_pgSP - 1 - - - protected - 1 - - Resizable - 1 - - - 0 - - - - wxTAB_TRAVERSAL - - - bSizer31 - wxVERTICAL - none - - 5 - wxALL|wxEXPAND - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - "Decade" "Octave" "Linear" - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 1 - wxID_ANY - Frequency scale - 1 - - 0 - - - 0 - - 1 - m_spScale - 1 - - - protected - 1 - - Resizable - 0 - 1 - - wxRA_SPECIFY_COLS - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - 5 - wxEXPAND|wxALL - 0 - - 3 - wxHORIZONTAL - - - 0 - - fgSizer12 - wxFLEX_GROWMODE_SPECIFIED - none - 0 - 5 - - 5 - wxALIGN_CENTER_VERTICAL|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Number of points per decade: - 0 - - 0 - - - 0 - - 1 - m_staticText12 - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - - - -1 - - - - 5 - wxEXPAND|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - - 0 - - 1 - m_spPointsNumber - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NUMERIC - wxTextValidator - - - - - - - - - 5 - wxEXPAND - 1 - - 0 - protected - 0 - - - - 5 - wxALIGN_CENTER_VERTICAL|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Start frequency: - 0 - - 0 - - - 0 - - 1 - m_staticText22 - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - - - -1 - - - - 5 - wxEXPAND|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - - 0 - 100,-1 - 1 - m_spFreqStart - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NUMERIC - wxTextValidator - - - - - - - - - 5 - wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Hz - 0 - - 0 - - - 0 - - 1 - m_staticText191 - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - - - -1 - - - - 5 - wxALIGN_CENTER_VERTICAL|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Stop frequency: - 0 - - 0 - - - 0 - - 1 - m_staticText32 - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - - - -1 - - - - 5 - wxEXPAND|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - - 0 - - 1 - m_spFreqStop - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NUMERIC - wxTextValidator - - - - - - - - - 5 - wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Hz - 0 - - 0 - - - 0 - - 1 - m_staticText1101 - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - - - -1 - - - - 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Compute noise current correlation matrix - - 0 - - - 0 - - 1 - m_spDoNoise - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - DC Transfer - 0 - + 1 1 1 @@ -1546,16 +961,16 @@ wxTAB_TRAVERSAL - + bSizer82 wxVERTICAL none - + 5 wxALL 0 - + wxBOTH @@ -1898,14 +1313,14 @@ -1 - + 5 1 1 wxBOTTOM|wxRIGHT|wxLEFT 0 1 - + 1 1 1 @@ -3076,21 +2491,21 @@ - + 5 wxEXPAND 0 - + 10 protected 0 - + 10 wxALL 0 - + 1 1 1 @@ -3163,11 +2578,10 @@ - - - Distortion + + a page 0 - + 1 1 1 @@ -3202,7 +2616,7 @@ 0 1 - m_pgDistortion + m_pgOP 1 @@ -3218,13 +2632,18 @@ wxTAB_TRAVERSAL + + + bSizer8 + wxVERTICAL + none + - - - Noise + + a page 0 - + 1 1 1 @@ -3259,7 +2678,7 @@ 0 1 - m_pgNoise + m_pgTRAN 1 @@ -3275,16 +2694,1398 @@ wxTAB_TRAVERSAL - + + + bSizer81 + wxVERTICAL + none + + 5 + wxEXPAND|wxTOP|wxRIGHT|wxLEFT + 1 + + -1,8 + wxBOTH + + + 0 + -1,-1 + gbSizer2 + wxFLEX_GROWMODE_SPECIFIED + none + 4 + + 5 + 1 + 0 + wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT + 0 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Time step: + 0 + + 0 + + + 0 + + 1 + m_timeLabel + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + 5 + 1 + 1 + wxALIGN_CENTER_VERTICAL|wxEXPAND + 0 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + + 0 + 100,-1 + 1 + m_transStep + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NUMERIC + wxTextValidator + + + + + + + + + 5 + 1 + 2 + wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT + 0 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + seconds + 0 + + 0 + + + 0 + + 1 + m_timeUnits + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + 5 + 1 + 0 + wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT + 1 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Final time: + 0 + + 0 + + + 0 + + 1 + m_transFinalLabel + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + 5 + 1 + 1 + wxALIGN_CENTER_VERTICAL|wxEXPAND + 1 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + + 0 + + 1 + m_transFinal + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NUMERIC + wxTextValidator + + + + + + + + + 5 + 1 + 2 + wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT + 1 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + seconds + 0 + + 0 + + + 0 + + 1 + m_transFinalUnits + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + 5 + 1 + 0 + wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT + 2 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Initial time: + 0 + + 0 + + + 0 + + 1 + m_transInitialLabel + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + 5 + 1 + 1 + wxEXPAND|wxALIGN_CENTER_VERTICAL + 2 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + + 0 + + 1 + m_transInitial + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NUMERIC + wxTextValidator + + + + + + + + + 5 + 1 + 2 + wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT + 2 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + seconds + 0 + + 0 + + + 0 + + 1 + m_transInitialUnits + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + 5 + 1 + 3 + wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT + 2 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + (optional; default 0) + 0 + + 0 + + + 0 + + 1 + m_transInitialHelp + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + 5 + 1 + 0 + wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT + 3 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Max time step: + 0 + + 0 + + + 0 + + 1 + m_maxStepLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + 1 + 1 + wxEXPAND|wxALIGN_CENTER_VERTICAL + 3 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + + 0 + + 1 + m_transMaxStep + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + 5 + 1 + 2 + wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT + 3 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + seconds + 0 + + 0 + + + 0 + + 1 + m_transMaxStepUnit + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + 1 + 3 + wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT + 3 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + (optional; default min{tstep, (tstop-tstart)/50}) + 0 + + 0 + + + 0 + + 1 + m_transMaxHelp + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + 3 + 0 + wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT + 5 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Use initial conditions + + 0 + + + 0 + + 1 + m_useInitialConditions + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + a page + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_pgFFT + 1 + + + protected + 1 + + Resizable + 1 + + ; ; forward_declare + 0 + + + + wxTAB_TRAVERSAL + + + bSizer151 + wxVERTICAL + none + + 5 + wxTOP|wxRIGHT|wxLEFT + 1 + + + bSizer14 + wxVERTICAL + none + + 5 + wxBOTTOM|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Input signals: + 0 + + 0 + + + 0 + + 1 + m_signalsLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxEXPAND|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + 1 + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + -1,-1 + 1 + m_inputSignalsFilter + 1 + + + protected + 1 + + Resizable + 1 + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + OnFilterMouseMoved + OnFilterText + + + + 5 + wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_inputSignalsList + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Linearize inputs before performing FFT + + 0 + + + 0 + + 1 + m_linearize + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + a page + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_pgNOISE + 1 + + + protected + 1 + + Resizable + 1 + + + 0 + + + + wxTAB_TRAVERSAL + bSizer15 wxVERTICAL none - + 5 wxALL 0 - + 3 wxBOTH @@ -3357,11 +4158,11 @@ -1 - + 5 wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT|wxEXPAND 0 - + 1 1 1 @@ -3492,11 +4293,11 @@ -1 - + 5 wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT|wxEXPAND 0 - + 1 1 1 @@ -3678,11 +4479,11 @@ -1 - + 5 wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT|wxEXPAND 0 - + 1 1 1 @@ -3754,11 +4555,11 @@ - + 5 wxEXPAND|wxTOP 0 - + bSizer10 wxHORIZONTAL @@ -3829,11 +4630,11 @@ - + 5 wxALIGN_BOTTOM|wxTOP|wxLEFT 0 - + 3 wxBOTH @@ -3970,11 +4771,11 @@ - + 5 wxEXPAND 1 - + 0 protected 0 @@ -4105,11 +4906,11 @@ - + 5 wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL 0 - + 1 1 1 @@ -4291,11 +5092,11 @@ - + 5 wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT 0 - + 1 1 1 @@ -4356,11 +5157,11 @@ - + 10 wxALL 0 - + 1 1 1 @@ -4374,7 +5175,7 @@ 1 0 - 0 + 1 1 1 @@ -4423,11 +5224,10 @@ - - - Operating Point + + a page 0 - + 1 1 1 @@ -4462,7 +5262,7 @@ 0 1 - m_pgOP + m_pgSP 1 @@ -4478,26 +5278,16 @@ wxTAB_TRAVERSAL - + - bSizer8 + bSizer31 wxVERTICAL none 5 - wxEXPAND - 1 - - 0 - protected - 0 - - - - 5 - wxALIGN_CENTER + wxALL|wxEXPAND 0 - + 1 1 1 @@ -4511,6 +5301,7 @@ 1 0 + "Decade" "Octave" "Linear" 1 1 @@ -4523,10 +5314,10 @@ 1 0 - 0 + 1 wxID_ANY - This tab has no settings - 0 + Frequency scale + 1 0 @@ -4534,7 +5325,7 @@ 0 1 - m_staticText13 + m_spScale 1 @@ -4542,284 +5333,42 @@ 1 Resizable + 0 1 - + wxRA_SPECIFY_COLS 0 + + wxFILTER_NONE + wxDefaultValidator + - -1 5 - wxEXPAND - 1 - - 0 - protected - 0 - - - - - - - - Pole-Zero - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 1 - wxID_ANY - - 0 - - - 0 - - 1 - m_pgPoleZero - 1 - - - protected - 1 - - Resizable - 1 - - - 0 - - - - wxTAB_TRAVERSAL - - - - - Sensitivity - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 1 - wxID_ANY - - 0 - - - 0 - - 1 - m_pgSensitivity - 1 - - - protected - 1 - - Resizable - 1 - - - 0 - - - - wxTAB_TRAVERSAL - - - - - Transfer Function - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 1 - wxID_ANY - - 0 - - - 0 - - 1 - m_pgTransferFunction - 1 - - - protected - 1 - - Resizable - 1 - - - 0 - - - - wxTAB_TRAVERSAL - - - - - Transient - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - - 1 - m_pgTransient - 1 - - - protected - 1 - - Resizable - 1 - - - 0 - - - - wxTAB_TRAVERSAL - - - bSizer81 - wxVERTICAL - none - - 5 - wxEXPAND|wxTOP|wxRIGHT|wxLEFT - 1 - - -1,8 - wxBOTH + wxEXPAND|wxALL + 0 + + 3 + wxHORIZONTAL 0 - -1,-1 - gbSizer2 + + fgSizer12 wxFLEX_GROWMODE_SPECIFIED none - 4 - + 0 + 5 + 5 - 1 - 0 - wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT - 0 - 1 + wxALIGN_CENTER_VERTICAL|wxLEFT + 0 1 1 @@ -4848,7 +5397,7 @@ 0 0 wxID_ANY - Time step: + Number of points per decade: 0 0 @@ -4857,7 +5406,7 @@ 0 1 - m_timeLabel + m_staticText12 1 @@ -4877,13 +5426,145 @@ -1 - + 5 - 1 - 1 - wxALIGN_CENTER_VERTICAL|wxEXPAND - 0 - 1 + wxEXPAND|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + + 0 + + 1 + m_spPointsNumber + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NUMERIC + wxTextValidator + + + + + + + + + 5 + wxEXPAND + 1 + + 0 + protected + 0 + + + + 5 + wxALIGN_CENTER_VERTICAL|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Start frequency: + 0 + + 0 + + + 0 + + 1 + m_staticText22 + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + 5 + wxEXPAND|wxRIGHT|wxLEFT + 0 1 1 @@ -4920,7 +5601,7 @@ 0 100,-1 1 - m_transStep + m_spFreqStart 1 @@ -4944,13 +5625,10 @@ - + 5 - 1 - 2 - wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT - 0 - 1 + wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT + 0 1 1 @@ -4979,7 +5657,7 @@ 0 0 wxID_ANY - seconds + Hz 0 0 @@ -4988,7 +5666,7 @@ 0 1 - m_timeUnits + m_staticText191 1 @@ -5008,13 +5686,10 @@ -1 - + 5 - 1 - 0 - wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT - 1 - 1 + wxALIGN_CENTER_VERTICAL|wxLEFT + 0 1 1 @@ -5043,7 +5718,7 @@ 0 0 wxID_ANY - Final time: + Stop frequency: 0 0 @@ -5052,7 +5727,7 @@ 0 1 - m_transFinalLabel + m_staticText32 1 @@ -5072,13 +5747,10 @@ -1 - + 5 - 1 - 1 - wxALIGN_CENTER_VERTICAL|wxEXPAND - 1 - 1 + wxEXPAND|wxRIGHT|wxLEFT + 0 1 1 @@ -5115,7 +5787,7 @@ 0 1 - m_transFinal + m_spFreqStop 1 @@ -5139,13 +5811,10 @@ - + 5 - 1 - 2 - wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT - 1 - 1 + wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT + 0 1 1 @@ -5174,7 +5843,7 @@ 0 0 wxID_ANY - seconds + Hz 0 0 @@ -5183,7 +5852,7 @@ 0 1 - m_transFinalUnits + m_staticText1101 1 @@ -5203,532 +5872,11 @@ -1 - + 5 - 1 - 0 - wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT - 2 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Initial time: - 0 - - 0 - - - 0 - - 1 - m_transInitialLabel - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - - - -1 - - - - 5 - 1 - 1 - wxEXPAND|wxALIGN_CENTER_VERTICAL - 2 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - - 0 - - 1 - m_transInitial - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NUMERIC - wxTextValidator - - - - - - - - - 5 - 1 - 2 - wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT - 2 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - seconds - 0 - - 0 - - - 0 - - 1 - m_transInitialUnits - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - - - -1 - - - - 5 - 1 - 3 - wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT - 2 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - (optional; default 0) - 0 - - 0 - - - 0 - - 1 - m_transInitialHelp - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - - - -1 - - - - 5 - 1 - 0 - wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT - 3 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Max time step: - 0 - - 0 - - - 0 - - 1 - m_maxStepLabel - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - - - -1 - - - - 5 - 1 - 1 - wxEXPAND|wxALIGN_CENTER_VERTICAL - 3 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - - 0 - - 1 - m_transMaxStep - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - 5 - 1 - 2 - wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT - 3 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - seconds - 0 - - 0 - - - 0 - - 1 - m_transMaxStepUnit - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - - - -1 - - - - 5 - 1 - 3 - wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT - 3 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - (optional; default min{tstep, (tstop-tstart)/50}) - 0 - - 0 - - - 0 - - 1 - m_transMaxHelp - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - - - -1 - - - - 5 - 3 - 0 - wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT - 5 - 1 - + wxALL + 0 + 1 1 1 @@ -5757,7 +5905,7 @@ 0 0 wxID_ANY - Use initial conditions + Compute noise current correlation matrix 0 @@ -5765,7 +5913,7 @@ 0 1 - m_useInitialConditions + m_spDoNoise 1 @@ -5793,11 +5941,10 @@ - - - Custom + + a page 0 - + 1 1 1 @@ -5848,7 +5995,7 @@ wxTAB_TRAVERSAL - + bSizer2 wxVERTICAL diff --git a/eeschema/dialogs/dialog_sim_command_base.h b/eeschema/dialogs/dialog_sim_command_base.h index 7f1d12e465..76fe44efc5 100644 --- a/eeschema/dialogs/dialog_sim_command_base.h +++ b/eeschema/dialogs/dialog_sim_command_base.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version 3.10.1-88b0f50) +// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b) // http://www.wxformbuilder.org/ // // PLEASE DO *NOT* EDIT THIS FILE! @@ -12,24 +12,26 @@ #include #include "dialog_shim.h" #include -#include +#include #include #include #include #include -#include +#include +#include +#include #include #include -#include #include +#include +#include +#include #include #include #include -#include -#include -#include -#include -#include +#include +#include +#include #include /////////////////////////////////////////////////////////////////////////// @@ -43,7 +45,10 @@ class DIALOG_SIM_COMMAND_BASE : public DIALOG_SHIM private: protected: - wxNotebook* m_simPages; + wxBoxSizer* m_commandTypeSizer; + wxStaticText* m_commandTypeLabel; + wxChoice* m_commandType; + wxSimplebook* m_simPages; wxPanel* m_pgAC; wxRadioBox* m_acScale; wxStaticText* m_staticText1; @@ -54,17 +59,6 @@ class DIALOG_SIM_COMMAND_BASE : public DIALOG_SHIM wxStaticText* m_staticText3; wxTextCtrl* m_acFreqStop; wxStaticText* m_staticText110; - wxPanel* m_pgSP; - wxRadioBox* m_spScale; - wxStaticText* m_staticText12; - wxTextCtrl* m_spPointsNumber; - wxStaticText* m_staticText22; - wxTextCtrl* m_spFreqStart; - wxStaticText* m_staticText191; - wxStaticText* m_staticText32; - wxTextCtrl* m_spFreqStop; - wxStaticText* m_staticText1101; - wxCheckBox* m_spDoNoise; wxPanel* m_pgDC; wxCheckBox* m_dcEnable2; wxChoice* m_dcSourceType1; @@ -90,8 +84,29 @@ class DIALOG_SIM_COMMAND_BASE : public DIALOG_SHIM wxTextCtrl* m_dcIncr2; wxStaticText* m_src2DCStepUnit; wxButton* m_swapDCSources; - wxPanel* m_pgDistortion; - wxPanel* m_pgNoise; + wxPanel* m_pgOP; + wxPanel* m_pgTRAN; + wxStaticText* m_timeLabel; + wxTextCtrl* m_transStep; + wxStaticText* m_timeUnits; + wxStaticText* m_transFinalLabel; + wxTextCtrl* m_transFinal; + wxStaticText* m_transFinalUnits; + wxStaticText* m_transInitialLabel; + wxTextCtrl* m_transInitial; + wxStaticText* m_transInitialUnits; + wxStaticText* m_transInitialHelp; + wxStaticText* m_maxStepLabel; + wxTextCtrl* m_transMaxStep; + wxStaticText* m_transMaxStepUnit; + wxStaticText* m_transMaxHelp; + wxCheckBox* m_useInitialConditions; + wxPanel* m_pgFFT; + wxStaticText* m_signalsLabel; + wxSearchCtrl* m_inputSignalsFilter; + wxCheckListBox* m_inputSignalsList; + wxCheckBox* m_linearize; + wxPanel* m_pgNOISE; wxStaticText* m_staticText14; wxChoice* m_noiseMeas; wxStaticText* m_staticText15; @@ -109,27 +124,17 @@ class DIALOG_SIM_COMMAND_BASE : public DIALOG_SHIM wxTextCtrl* m_noiseFreqStop; wxStaticText* m_noiseFreqStopUnits; wxCheckBox* m_saveAllNoise; - wxPanel* m_pgOP; - wxStaticText* m_staticText13; - wxPanel* m_pgPoleZero; - wxPanel* m_pgSensitivity; - wxPanel* m_pgTransferFunction; - wxPanel* m_pgTransient; - wxStaticText* m_timeLabel; - wxTextCtrl* m_transStep; - wxStaticText* m_timeUnits; - wxStaticText* m_transFinalLabel; - wxTextCtrl* m_transFinal; - wxStaticText* m_transFinalUnits; - wxStaticText* m_transInitialLabel; - wxTextCtrl* m_transInitial; - wxStaticText* m_transInitialUnits; - wxStaticText* m_transInitialHelp; - wxStaticText* m_maxStepLabel; - wxTextCtrl* m_transMaxStep; - wxStaticText* m_transMaxStepUnit; - wxStaticText* m_transMaxHelp; - wxCheckBox* m_useInitialConditions; + wxPanel* m_pgSP; + wxRadioBox* m_spScale; + wxStaticText* m_staticText12; + wxTextCtrl* m_spPointsNumber; + wxStaticText* m_staticText22; + wxTextCtrl* m_spFreqStart; + wxStaticText* m_staticText191; + wxStaticText* m_staticText32; + wxTextCtrl* m_spFreqStop; + wxStaticText* m_staticText1101; + wxCheckBox* m_spDoNoise; wxPanel* m_pgCustom; wxStaticText* m_staticText18; wxTextCtrl* m_customTxt; @@ -146,10 +151,13 @@ class DIALOG_SIM_COMMAND_BASE : public DIALOG_SHIM // Virtual event handlers, override them in your derived class virtual void onInitDlg( wxInitDialogEvent& event ) { event.Skip(); } + virtual void OnCommandType( wxCommandEvent& event ) { event.Skip(); } virtual void onDCEnableSecondSource( wxCommandEvent& event ) { event.Skip(); } virtual void onDCSource1Selected( wxCommandEvent& event ) { event.Skip(); } virtual void onDCSource2Selected( wxCommandEvent& event ) { event.Skip(); } virtual void onSwapDCSources( wxCommandEvent& event ) { event.Skip(); } + virtual void OnFilterMouseMoved( wxMouseEvent& event ) { event.Skip(); } + virtual void OnFilterText( wxCommandEvent& event ) { event.Skip(); } virtual void onLoadDirectives( wxCommandEvent& event ) { event.Skip(); } diff --git a/eeschema/dialogs/dialog_symbol_fields_table.cpp b/eeschema/dialogs/dialog_symbol_fields_table.cpp index 7ba97d905c..5c9c661630 100644 --- a/eeschema/dialogs/dialog_symbol_fields_table.cpp +++ b/eeschema/dialogs/dialog_symbol_fields_table.cpp @@ -743,6 +743,7 @@ void DIALOG_SYMBOL_FIELDS_TABLE::OnFilterMouseMoved( wxMouseEvent& aEvent ) SetCursor( wxCURSOR_IBEAM ); } + void DIALOG_SYMBOL_FIELDS_TABLE::OnFieldsCtrlSelectionChanged( wxDataViewEvent& event ) { int row = m_fieldsCtrl->GetSelectedRow(); diff --git a/eeschema/dialogs/dialog_user_defined_signals.cpp b/eeschema/dialogs/dialog_user_defined_signals.cpp index f96d37d9eb..3dbe448109 100644 --- a/eeschema/dialogs/dialog_user_defined_signals.cpp +++ b/eeschema/dialogs/dialog_user_defined_signals.cpp @@ -143,7 +143,7 @@ void DIALOG_USER_DEFINED_SIGNALS::onScintillaCharAdded( wxStyledTextEvent &aEven wxStyledTextCtrl* textCtrl = aTricks->Scintilla(); wxArrayString tokens; - for( const wxString& signal : m_frame->Signals() ) + for( const wxString& signal : m_frame->SimPlotVectors() ) tokens.push_back( signal ); tokens.push_back( wxS( "sqrt(x)" ) ); diff --git a/eeschema/netlist_exporters/netlist_exporter_spice.cpp b/eeschema/netlist_exporters/netlist_exporter_spice.cpp index 2aa8358a38..e941fbc29c 100644 --- a/eeschema/netlist_exporters/netlist_exporter_spice.cpp +++ b/eeschema/netlist_exporters/netlist_exporter_spice.cpp @@ -106,32 +106,32 @@ bool NETLIST_EXPORTER_SPICE::WriteNetlist( const wxString& aOutFileName, unsigne { m_libMgr.SetReporter( &aReporter ); FILE_OUTPUTFORMATTER formatter( aOutFileName, wxT( "wt" ), '\'' ); - return DoWriteNetlist( formatter, aNetlistOptions, aReporter ); + return DoWriteNetlist( wxEmptyString, aNetlistOptions, formatter, aReporter ); } -bool NETLIST_EXPORTER_SPICE::DoWriteNetlist( OUTPUTFORMATTER& aFormatter, unsigned aNetlistOptions, - REPORTER& aReporter ) +bool NETLIST_EXPORTER_SPICE::DoWriteNetlist( const wxString& aSimCommand, unsigned aSimOptions, + OUTPUTFORMATTER& aFormatter, REPORTER& aReporter ) { LOCALE_IO dummy; // Cleanup list to avoid duplicate if the netlist exporter is run more than once. m_rawIncludes.clear(); - bool result = ReadSchematicAndLibraries( aNetlistOptions, aReporter ); + bool result = ReadSchematicAndLibraries( aSimOptions, aReporter ); - WriteHead( aFormatter, aNetlistOptions ); + WriteHead( aFormatter, aSimOptions ); - writeIncludes( aFormatter, aNetlistOptions ); + writeIncludes( aFormatter, aSimOptions ); writeModels( aFormatter ); // Skip this if there is no netlist to avoid an ngspice segfault if( !m_items.empty() ) - WriteDirectives( aFormatter, aNetlistOptions ); + WriteDirectives( aSimCommand, aSimOptions, aFormatter ); writeItems( aFormatter ); - WriteTail( aFormatter, aNetlistOptions ); + WriteTail( aFormatter, aSimOptions ); return result; } @@ -588,16 +588,16 @@ void NETLIST_EXPORTER_SPICE::writeItems( OUTPUTFORMATTER& aFormatter ) } -void NETLIST_EXPORTER_SPICE::WriteDirectives( OUTPUTFORMATTER& aFormatter, - unsigned aNetlistOptions ) const +void NETLIST_EXPORTER_SPICE::WriteDirectives( const wxString& aSimCommand, unsigned aSimOptions, + OUTPUTFORMATTER& aFormatter ) const { - if( aNetlistOptions & OPTION_SAVE_ALL_VOLTAGES ) + if( aSimOptions & OPTION_SAVE_ALL_VOLTAGES ) aFormatter.Print( 0, ".save all\n" ); - if( aNetlistOptions & OPTION_SAVE_ALL_CURRENTS ) + if( aSimOptions & OPTION_SAVE_ALL_CURRENTS ) aFormatter.Print( 0, ".probe alli\n" ); - if( aNetlistOptions & OPTION_SAVE_ALL_DISSIPATIONS ) + if( aSimOptions & OPTION_SAVE_ALL_DISSIPATIONS ) { for( const SPICE_ITEM& item : m_items ) { @@ -638,7 +638,7 @@ void NETLIST_EXPORTER_SPICE::WriteDirectives( OUTPUTFORMATTER& aFormatter, || isSimCommand( candidate, wxS( ".TF" ) ) ); } - if( !simCommand || ( aNetlistOptions & OPTION_SIM_COMMAND ) ) + if( !simCommand || ( aSimOptions & OPTION_SIM_COMMAND ) ) aFormatter.Print( 0, "%s\n", UTF8( directive ).c_str() ); } } diff --git a/eeschema/netlist_exporters/netlist_exporter_spice.h b/eeschema/netlist_exporters/netlist_exporter_spice.h index 1b62d76e6b..2ac03d7b84 100644 --- a/eeschema/netlist_exporters/netlist_exporter_spice.h +++ b/eeschema/netlist_exporters/netlist_exporter_spice.h @@ -76,8 +76,8 @@ public: /** * Write the netlist in aFormatter. */ - bool DoWriteNetlist( OUTPUTFORMATTER& aFormatter, unsigned aNetlistOptions, - REPORTER& aReporter ); + bool DoWriteNetlist( const wxString& aSimCommand, unsigned aSimOptions, + OUTPUTFORMATTER& aFormatter, REPORTER& aReporter ); /** * Write the netlist head (title and so on). @@ -132,7 +132,8 @@ public: protected: void ReadDirectives( unsigned aNetlistOptions ); - virtual void WriteDirectives( OUTPUTFORMATTER& candidate, unsigned aNetlistOptions ) const; + virtual void WriteDirectives( const wxString& aSimCommand, unsigned aSimOptions, + OUTPUTFORMATTER& candidate ) const; virtual std::string GenerateItemPinNetName( const std::string& aNetName, int& aNcCounter ) const; diff --git a/eeschema/sim/ngspice.cpp b/eeschema/sim/ngspice.cpp index c1bd773d0c..56857e1145 100644 --- a/eeschema/sim/ngspice.cpp +++ b/eeschema/sim/ngspice.cpp @@ -251,23 +251,21 @@ std::vector NGSPICE::GetPhaseVector( const std::string& aName, int aMaxL } -bool NGSPICE::Attach( const std::shared_ptr& aModel, REPORTER& aReporter ) +bool NGSPICE::Attach( const std::shared_ptr& aModel, const wxString& aSimCommand, + unsigned aSimOptions, REPORTER& aReporter ) { NGSPICE_CIRCUIT_MODEL* model = dynamic_cast( aModel.get() ); - STRING_FORMATTER formatter; + STRING_FORMATTER formatter; - if( model && model->GetNetlist( &formatter, aReporter ) ) + if( model && model->GetNetlist( aSimCommand, aSimOptions, &formatter, aReporter ) ) { - SIMULATOR::Attach( aModel, aReporter ); - + SIMULATOR::Attach( aModel, aSimCommand, aSimOptions, aReporter ); LoadNetlist( formatter.GetString() ); - return true; } else { - SIMULATOR::Attach( nullptr, aReporter ); - + SIMULATOR::Attach( nullptr, wxEmptyString, 0, aReporter ); return false; } } @@ -335,11 +333,10 @@ wxString NGSPICE::GetXAxis( SIM_TYPE aType ) const switch( aType ) { case ST_AC: - case ST_S_PARAM: - return wxS( "frequency" ); - + case ST_SP: case ST_NOISE: - return wxS( "noise1.frequency" ); + case ST_FFT: + return wxS( "frequency" ); case ST_DC: // find plot, which ends with "-sweep" @@ -351,7 +348,7 @@ wxString NGSPICE::GetXAxis( SIM_TYPE aType ) const return wxS( "sweep" ); - case ST_TRANSIENT: + case ST_TRAN: return wxS( "time" ); default: diff --git a/eeschema/sim/ngspice.h b/eeschema/sim/ngspice.h index 827d3e81bd..73b66da5c1 100644 --- a/eeschema/sim/ngspice.h +++ b/eeschema/sim/ngspice.h @@ -59,8 +59,8 @@ public: void Init( const SPICE_SIMULATOR_SETTINGS* aSettings = nullptr ) override final; ///< @copydoc SPICE_SIMULATOR::Attach() - bool Attach( const std::shared_ptr& aModel, - REPORTER& aReporter ) override final; + bool Attach( const std::shared_ptr& aModel, const wxString& aSimCommand, + unsigned aSimOptions, REPORTER& aReporter ) override final; ///< Load a netlist for the simulation bool LoadNetlist( const std::string& aNetlist ) override final; diff --git a/eeschema/sim/ngspice_circuit_model.cpp b/eeschema/sim/ngspice_circuit_model.cpp index 4fe09e90b3..42aa8d3671 100644 --- a/eeschema/sim/ngspice_circuit_model.cpp +++ b/eeschema/sim/ngspice_circuit_model.cpp @@ -84,13 +84,7 @@ wxString NGSPICE_CIRCUIT_MODEL::GetSchTextSimCommand() simCmd += wxString::Format( wxT( "%s\r\n" ), directive ); } - return simCmd; -} - - -SIM_TYPE NGSPICE_CIRCUIT_MODEL::GetSimType() -{ - return CommandToSimType( GetSimCommand() ); + return simCmd.Trim(); } @@ -98,28 +92,18 @@ SIM_TYPE NGSPICE_CIRCUIT_MODEL::CommandToSimType( const wxString& aCmd ) { wxString cmd = aCmd.Lower().Trim(); - if( cmd.StartsWith( wxT( ".ac" ) ) ) - return ST_AC; - else if( cmd.StartsWith( wxT( ".dc" ) ) ) - return ST_DC; - else if( cmd.StartsWith( wxT( ".tran" ) ) ) - return ST_TRANSIENT; - else if( cmd == wxT( ".op" ) ) - return ST_OP; - else if( cmd.StartsWith( wxT( ".disto" ) ) ) - return ST_DISTORTION; - else if( cmd.StartsWith( wxT( ".noise" ) ) ) - return ST_NOISE; - else if( cmd.StartsWith( wxT( ".pz" ) ) ) - return ST_POLE_ZERO; - else if( cmd.StartsWith( wxT( ".sens" ) ) ) - return ST_SENSITIVITY; - else if( cmd.StartsWith( wxT( ".sp" ) ) ) - return ST_S_PARAM; - else if( cmd.StartsWith( wxT( ".tf" ) ) ) - return ST_TRANS_FUNC; - else - return ST_UNKNOWN; + if( cmd == wxT( ".op" ) ) return ST_OP; + else if( cmd.StartsWith( wxT( ".ac" ) ) ) return ST_AC; + else if( cmd.StartsWith( wxT( ".dc" ) ) ) return ST_DC; + else if( cmd.StartsWith( wxT( ".tran" ) ) ) return ST_TRAN; + else if( cmd.StartsWith( wxT( ".disto" ) ) ) return ST_DISTO; + else if( cmd.StartsWith( wxT( ".noise" ) ) ) return ST_NOISE; + else if( cmd.StartsWith( wxT( ".pz" ) ) ) return ST_PZ; + else if( cmd.StartsWith( wxT( ".sens" ) ) ) return ST_SENS; + else if( cmd.StartsWith( wxT( ".sp" ) ) ) return ST_SP; + else if( cmd.StartsWith( wxT( ".tf" ) ) ) return ST_TF; + else if( cmd.StartsWith( wxT( "fft" ) ) ) return ST_FFT; + else return ST_UNKNOWN; } @@ -211,14 +195,14 @@ bool NGSPICE_CIRCUIT_MODEL::ParseNoiseCommand( const wxString& aCmd, wxString* a } -void NGSPICE_CIRCUIT_MODEL::WriteDirectives( OUTPUTFORMATTER& aFormatter, - unsigned aNetlistOptions ) const +void NGSPICE_CIRCUIT_MODEL::WriteDirectives( const wxString& aSimCommand, unsigned aSimOptions, + OUTPUTFORMATTER& aFormatter ) const { - if( GetSimCommandOverride().IsEmpty() ) - aNetlistOptions |= OPTION_SIM_COMMAND; + if( aSimCommand.IsEmpty() ) + aSimOptions |= OPTION_SIM_COMMAND; - NETLIST_EXPORTER_SPICE::WriteDirectives( aFormatter, aNetlistOptions ); + NETLIST_EXPORTER_SPICE::WriteDirectives( aSimCommand, aSimOptions, aFormatter ); - if( !GetSimCommandOverride().IsEmpty() ) - aFormatter.Print( 0, "%s\n", TO_UTF8( GetSimCommandOverride() ) ); + if( !aSimCommand.IsEmpty() ) + aFormatter.Print( 0, "%s\n", TO_UTF8( aSimCommand ) ); } diff --git a/eeschema/sim/ngspice_circuit_model.h b/eeschema/sim/ngspice_circuit_model.h index 45bf1adfeb..79945d21de 100644 --- a/eeschema/sim/ngspice_circuit_model.h +++ b/eeschema/sim/ngspice_circuit_model.h @@ -48,8 +48,7 @@ class NGSPICE_CIRCUIT_MODEL : public NETLIST_EXPORTER_SPICE, public SIMULATION_M { public: NGSPICE_CIRCUIT_MODEL( SCHEMATIC_IFACE* aSchematic, wxWindow* aDialogParent = nullptr ) : - NETLIST_EXPORTER_SPICE( aSchematic, aDialogParent ), - m_options( NETLIST_EXPORTER_SPICE::OPTION_DEFAULT_FLAGS ) + NETLIST_EXPORTER_SPICE( aSchematic, aDialogParent ) {} virtual ~NGSPICE_CIRCUIT_MODEL() {} @@ -64,60 +63,18 @@ public: */ SIM_TRACE_TYPE VectorToSignal( const std::string& aVector, wxString& aSignal ) const; - void SetSimOptions( int aOptions ) { m_options = aOptions; } - int GetSimOptions() const { return m_options; } - - bool GetNetlist( OUTPUTFORMATTER* aFormatter, REPORTER& aReporter ) + bool GetNetlist( const wxString& aSimCommand, unsigned aSimOptions, + OUTPUTFORMATTER* aFormatter, REPORTER& aReporter ) { - return NGSPICE_CIRCUIT_MODEL::DoWriteNetlist( *aFormatter, m_options, aReporter ); + return NGSPICE_CIRCUIT_MODEL::DoWriteNetlist( aSimCommand, aSimOptions, *aFormatter, + aReporter ); } - /** - * Override the simulation command directive. - */ - void SetSimCommandOverride( const wxString& aCmd ) - { - if( aCmd != m_simCommand ) - { - m_lastSchTextSimCommand = GetSchTextSimCommand(); - m_simCommand = aCmd; - } - } - - /** - * Return the command directive that is in use (either from the sheet or from m_simCommand) - * @return - */ - wxString GetSimCommand() - { - return m_simCommand.IsEmpty() ? GetSchTextSimCommand() : m_simCommand; - } - - /** - * Return the simulation command directive if stored separately (not as a sheet directive). - */ - wxString GetSimCommandOverride() const { return m_simCommand; } - - /** - * Return simulation type basing on the simulation command directives. - * - * Simulation directives set using SetSimCommandOverride() have priority over the ones placed in - * schematic sheets. - */ - SIM_TYPE GetSimType(); - /** * Return simulation command directives placed in schematic sheets (if any). */ wxString GetSchTextSimCommand(); - /** - * Return the sim command present as a sheet directive when the sim command override was last - * updated. - * @return - */ - wxString GetLastSchTextSimCommand() const { return m_lastSchTextSimCommand; } - /** * Parse a two-source .dc command directive into its symbols. * @@ -145,16 +102,8 @@ public: static SIM_TYPE CommandToSimType( const wxString& aCmd ); protected: - void WriteDirectives( OUTPUTFORMATTER& aFormatter, unsigned aNetlistOptions ) const override; - -private: - ///< Custom simulation command (has priority over the schematic sheet simulation commands) - wxString m_simCommand; - - ///< Value of schematic sheet simulation command when override was last updated - wxString m_lastSchTextSimCommand; - - int m_options; + void WriteDirectives( const wxString& aSimCommand, unsigned aSimOptions, + OUTPUTFORMATTER& aFormatter ) const override; }; #endif /* NGSPICE_CIRCUIT_MODEL_H */ diff --git a/eeschema/sim/sim_plot_panel.cpp b/eeschema/sim/sim_plot_panel.cpp index 927a5a4520..0aacd1682c 100644 --- a/eeschema/sim/sim_plot_panel.cpp +++ b/eeschema/sim/sim_plot_panel.cpp @@ -405,10 +405,9 @@ void CURSOR::UpdateReference() } -SIM_PLOT_PANEL::SIM_PLOT_PANEL( const wxString& aCommand, int aOptions, wxWindow* parent, - wxWindowID id, const wxPoint& pos, const wxSize& size, long style, - const wxString& name ) : - SIM_PLOT_PANEL_BASE( aCommand, aOptions, parent, id, pos, size, style, name ), +SIM_PLOT_PANEL::SIM_PLOT_PANEL( const wxString& aSimCommand, unsigned aSimOptions, + wxWindow* parent ) : + SIM_PLOT_PANEL_BASE( aSimCommand, aSimOptions, parent ), m_axis_x( nullptr ), m_axis_y1( nullptr ), m_axis_y2( nullptr ), @@ -416,7 +415,7 @@ SIM_PLOT_PANEL::SIM_PLOT_PANEL( const wxString& aCommand, int aOptions, wxWindow m_dotted_cp( false ) { m_sizer = new wxBoxSizer( wxVERTICAL ); - m_plotWin = new mpWindow( this, wxID_ANY, pos, size, style ); + m_plotWin = new mpWindow( this, wxID_ANY ); m_plotWin->LimitView( true ); m_plotWin->SetMargins( 35, 70, 35, 70 ); @@ -517,7 +516,7 @@ void SIM_PLOT_PANEL::updateAxes( int aNewTraceType ) m_axis_y2->SetName( _( "Phase" ) ); break; - case ST_S_PARAM: + case ST_SP: if( !m_axis_x ) { m_axis_x = new LOG_SCALE( wxEmptyString, wxT( "Hz" ), mpALIGN_BOTTOM ); @@ -574,7 +573,23 @@ void SIM_PLOT_PANEL::updateAxes( int aNewTraceType ) break; - case ST_TRANSIENT: + case ST_FFT: + if( !m_axis_x ) + { + m_axis_x = new LOG_SCALE( wxEmptyString, wxT( "Hz" ), mpALIGN_BOTTOM ); + m_axis_x->SetNameAlign( mpALIGN_BOTTOM ); + m_plotWin->AddLayer( m_axis_x ); + + m_axis_y1 = new LIN_SCALE( wxEmptyString, wxT( "dB" ), mpALIGN_LEFT ); + m_axis_y1->SetNameAlign( mpALIGN_LEFT ); + m_plotWin->AddLayer( m_axis_y1 ); + } + + m_axis_x->SetName( _( "Frequency" ) ); + m_axis_y1->SetName( _( "Intensity" ) ); + break; + + case ST_TRAN: if( !m_axis_x ) { m_axis_x = new TIME_SCALE( wxEmptyString, wxT( "s" ), mpALIGN_BOTTOM ); @@ -777,7 +792,7 @@ TRACE* SIM_PLOT_PANEL::AddTrace( const wxString& aVectorName, int aType ) { updateAxes( aType ); - if( GetSimType() == ST_TRANSIENT || GetSimType() == ST_DC ) + if( GetSimType() == ST_TRAN || GetSimType() == ST_DC ) { bool hasVoltageTraces = false; @@ -815,27 +830,37 @@ TRACE* SIM_PLOT_PANEL::AddTrace( const wxString& aVectorName, int aType ) void SIM_PLOT_PANEL::SetTraceData( TRACE* trace, unsigned int aPoints, const double* aX, const double* aY ) { - std::vector tmp( aY, aY + aPoints ); + std::vector x( aX, aX + aPoints ); + std::vector y( aY, aY + aPoints ); - if( GetSimType() == ST_AC ) + if( GetSimType() == ST_AC || GetSimType() == ST_SP || GetSimType() == ST_FFT ) + { + // log( 0 ) is not valid. + { + x.erase( x.begin() ); + y.erase( y.begin() ); + } + } + + if( GetSimType() == ST_AC || GetSimType() == ST_FFT ) { if( trace->GetType() & SPT_AC_PHASE ) { for( unsigned int i = 0; i < aPoints; i++ ) - tmp[i] = tmp[i] * 180.0 / M_PI; // convert to degrees + y[i] = y[i] * 180.0 / M_PI; // convert to degrees } else { for( unsigned int i = 0; i < aPoints; i++ ) { // log( 0 ) is not valid. - if( tmp[i] != 0 ) - tmp[i] = 20 * log( tmp[i] ) / log( 10.0 ); // convert to dB + if( y[i] != 0 ) + y[i] = 20 * log( y[i] ) / log( 10.0 ); // convert to dB } } } - trace->SetData( std::vector( aX, aX + aPoints ), tmp ); + trace->SetData( x, y ); if( ( trace->GetType() & SPT_AC_PHASE ) || ( trace->GetType() & SPT_CURRENT ) ) trace->SetScale( m_axis_x, m_axis_y2 ); diff --git a/eeschema/sim/sim_plot_panel.h b/eeschema/sim/sim_plot_panel.h index ada4980694..9d028aa420 100644 --- a/eeschema/sim/sim_plot_panel.h +++ b/eeschema/sim/sim_plot_panel.h @@ -194,9 +194,7 @@ protected: class SIM_PLOT_PANEL : public SIM_PLOT_PANEL_BASE { public: - SIM_PLOT_PANEL( const wxString& aCommand, int aOptions, wxWindow* parent, wxWindowID id, - const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, - long style = 0, const wxString& name = wxPanelNameStr ); + SIM_PLOT_PANEL( const wxString& aSimCommand, unsigned aSimOptions, wxWindow* parent ); virtual ~SIM_PLOT_PANEL(); @@ -239,10 +237,18 @@ public: void ShowGrid( bool aEnable ) { - m_axis_x->SetTicks( !aEnable ); - m_axis_y1->SetTicks( !aEnable ); - m_axis_y2->SetTicks( !aEnable ); - m_axis_y3->SetTicks( !aEnable ); + if( m_axis_x ) + m_axis_x->SetTicks( !aEnable ); + + if( m_axis_y1 ) + m_axis_y1->SetTicks( !aEnable ); + + if( m_axis_y2 ) + m_axis_y2->SetTicks( !aEnable ); + + if( m_axis_y3 ) + m_axis_y3->SetTicks( !aEnable ); + m_plotWin->UpdateAll(); } @@ -320,6 +326,8 @@ public: bool DeleteTrace( const wxString& aVectorName, int aTraceType ); void DeleteTrace( TRACE* aTrace ); + std::vector>& Measurements() { return m_measurements; } + private: wxString getTraceId( const wxString& aVectorName, int aType ) const { @@ -349,6 +357,9 @@ private: mpInfoLegend* m_legend; bool m_dotted_cp; + + // Measurements (and their format strings) + std::vector> m_measurements; }; wxDECLARE_EVENT( EVT_SIM_CURSOR_UPDATE, wxCommandEvent ); diff --git a/eeschema/sim/sim_plot_panel_base.cpp b/eeschema/sim/sim_plot_panel_base.cpp index e9a61fd9a5..5f31d780df 100644 --- a/eeschema/sim/sim_plot_panel_base.cpp +++ b/eeschema/sim/sim_plot_panel_base.cpp @@ -37,12 +37,11 @@ SIM_PLOT_PANEL_BASE::SIM_PLOT_PANEL_BASE() : } -SIM_PLOT_PANEL_BASE::SIM_PLOT_PANEL_BASE( const wxString& aCommand, int aOptions, wxWindow* parent, - wxWindowID id, const wxPoint& pos, const wxSize& size, - long style, const wxString& name ) : - wxWindow( parent, id, pos, size, style, name ), - m_simCommand( aCommand ), - m_simOptions( aOptions ) +SIM_PLOT_PANEL_BASE::SIM_PLOT_PANEL_BASE( const wxString& aSimCommand, unsigned aSimOptions, + wxWindow* parent ) : + wxWindow( parent, wxID_ANY ), + m_simCommand( aSimCommand ), + m_simOptions( aSimOptions ) { } @@ -58,9 +57,10 @@ bool SIM_PLOT_PANEL_BASE::IsPlottable( SIM_TYPE aSimType ) { case ST_AC: case ST_DC: - case ST_S_PARAM: - case ST_TRANSIENT: + case ST_SP: + case ST_TRAN: case ST_NOISE: + case ST_FFT: return true; default: @@ -75,10 +75,9 @@ SIM_TYPE SIM_PLOT_PANEL_BASE::GetSimType() const } -SIM_NOPLOT_PANEL::SIM_NOPLOT_PANEL( const wxString& aCommand, int aOptions, wxWindow* parent, - wxWindowID id, const wxPoint& pos, const wxSize& size, - long style, const wxString& name ) : - SIM_PLOT_PANEL_BASE( aCommand, aOptions, parent, id, pos, size, style, name ) +SIM_NOPLOT_PANEL::SIM_NOPLOT_PANEL( const wxString& aSimCommand, unsigned aSimOptions, + wxWindow* parent ) : + SIM_PLOT_PANEL_BASE( aSimCommand, aSimOptions, parent ) { m_sizer = new wxBoxSizer( wxVERTICAL ); m_sizer->Add( 0, 1, 1, wxEXPAND, 5 ); diff --git a/eeschema/sim/sim_plot_panel_base.h b/eeschema/sim/sim_plot_panel_base.h index e7ae89bad2..286717ce12 100644 --- a/eeschema/sim/sim_plot_panel_base.h +++ b/eeschema/sim/sim_plot_panel_base.h @@ -26,8 +26,8 @@ #ifndef __SIM_PLOT_PANEL_BASE_H #define __SIM_PLOT_PANEL_BASE_H -#include "sim_types.h" -#include "ngspice_circuit_model.h" +#include +#include #include #include #include @@ -37,9 +37,7 @@ class SIM_PLOT_PANEL_BASE : public wxWindow { public: SIM_PLOT_PANEL_BASE(); - SIM_PLOT_PANEL_BASE( const wxString& aCommand, int aOptions, wxWindow* parent, wxWindowID id, - const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, - long style = 0, const wxString& name = wxPanelNameStr ); + SIM_PLOT_PANEL_BASE( const wxString& aSimCommand, unsigned aSimOptions, wxWindow* parent ); virtual ~SIM_PLOT_PANEL_BASE(); static bool IsPlottable( SIM_TYPE aSimType ); @@ -49,29 +47,29 @@ public: SIM_TYPE GetSimType() const; const wxString& GetSimCommand() const { return m_simCommand; } - void SetSimCommand( const wxString& aSimCommand ) - { - wxCHECK_RET( GetSimType() == NGSPICE_CIRCUIT_MODEL::CommandToSimType( aSimCommand ), - "Cannot change the type of simulation of the existing plot panel" ); - - m_simCommand = aSimCommand; - } + void SetSimCommand( const wxString& aSimCommand ) { m_simCommand = aSimCommand; } int GetSimOptions() const { return m_simOptions; } void SetSimOptions( int aOptions ) { m_simOptions = aOptions; } + wxString GetLastSchTextSimCommand() const { return m_lastSchTextSimCommand; } + void SetLastSchTextSimCommand( const wxString& aCmd ) { m_lastSchTextSimCommand = aCmd; } + + const wxString& GetSpicePlotName() const { return m_spicePlotName; } + void SetSpicePlotName( const wxString& aPlotName ) { m_spicePlotName = aPlotName; } + private: wxString m_simCommand; - int m_simOptions; + unsigned m_simOptions; + wxString m_lastSchTextSimCommand; + wxString m_spicePlotName; }; class SIM_NOPLOT_PANEL : public SIM_PLOT_PANEL_BASE { public: - SIM_NOPLOT_PANEL( const wxString& aCommand, int aOptions, wxWindow* parent, wxWindowID id, - const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, - long style = 0, const wxString& name = wxPanelNameStr ); + SIM_NOPLOT_PANEL( const wxString& aSimCommand, unsigned aSimOptions, wxWindow* parent ); virtual ~SIM_NOPLOT_PANEL(); diff --git a/eeschema/sim/sim_types.h b/eeschema/sim/sim_types.h index 9ad2b07c45..737610a70f 100644 --- a/eeschema/sim/sim_types.h +++ b/eeschema/sim/sim_types.h @@ -33,14 +33,16 @@ enum SIM_TYPE ST_UNKNOWN, ST_AC, ST_DC, - ST_DISTORTION, + ST_DISTO, ST_NOISE, ST_OP, - ST_POLE_ZERO, - ST_SENSITIVITY, - ST_TRANS_FUNC, - ST_TRANSIENT, - ST_S_PARAM + ST_PZ, + ST_SENS, + ST_TF, + ST_TRAN, + ST_SP, + ST_FFT, + ST_LAST }; ///< Possible trace types diff --git a/eeschema/sim/simulator.h b/eeschema/sim/simulator.h index 0330f7754a..8ff88ea48d 100644 --- a/eeschema/sim/simulator.h +++ b/eeschema/sim/simulator.h @@ -58,7 +58,8 @@ public: * * @return True in case of success, false otherwise. */ - virtual bool Attach( const std::shared_ptr& aModel, REPORTER& aReporter ) + virtual bool Attach( const std::shared_ptr& aModel, + const wxString& aSimCommand, unsigned aSimOptions, REPORTER& aReporter ) { m_simModel = aModel; return true; diff --git a/eeschema/sim/simulator_frame.cpp b/eeschema/sim/simulator_frame.cpp index c211eba432..67891a3671 100644 --- a/eeschema/sim/simulator_frame.cpp +++ b/eeschema/sim/simulator_frame.cpp @@ -113,7 +113,6 @@ SIMULATOR_FRAME::SIMULATOR_FRAME( KIWAY* aKiway, wxWindow* aParent ) : m_schematicFrame( nullptr ), m_toolBar( nullptr ), m_panel( nullptr ), - m_lastSimPlot( nullptr ), m_simFinished( false ), m_workbookModified( false ) { @@ -168,7 +167,7 @@ SIMULATOR_FRAME::SIMULATOR_FRAME( KIWAY* aKiway, wxWindow* aParent ) : Bind( wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( SIMULATOR_FRAME::onExit ), this, wxID_EXIT ); - Bind( EVT_SIM_UPDATE, &SIMULATOR_FRAME::onSimUpdate, this ); + Bind( EVT_SIM_UPDATE, &SIMULATOR_FRAME::onUpdateSim, this ); Bind( EVT_SIM_REPORT, &SIMULATOR_FRAME::onSimReport, this ); Bind( EVT_SIM_STARTED, &SIMULATOR_FRAME::onSimStarted, this ); Bind( EVT_SIM_FINISHED, &SIMULATOR_FRAME::onSimFinished, this ); @@ -196,7 +195,7 @@ SIMULATOR_FRAME::~SIMULATOR_FRAME() { NULL_REPORTER devnull; - m_simulator->Attach( nullptr, devnull ); + m_simulator->Attach( nullptr, wxEmptyString, 0, devnull ); m_simulator->SetReporter( nullptr ); delete m_reporter; } @@ -285,8 +284,8 @@ WINDOW_SETTINGS* SIMULATOR_FRAME::GetWindowSettings( APP_SETTINGS_BASE* aCfg ) wxString SIMULATOR_FRAME::GetCurrentSimCommand() const { - if( m_panel->GetCurrentPlotWindow() ) - return m_panel->GetCurrentPlotWindow()->GetSimCommand(); + if( m_panel->GetCurrentPlotPanel() ) + return m_panel->GetCurrentPlotPanel()->GetSimCommand(); else return m_circuitModel->GetSchTextSimCommand(); } @@ -300,10 +299,10 @@ SIM_TYPE SIMULATOR_FRAME::GetCurrentSimType() const int SIMULATOR_FRAME::GetCurrentOptions() const { - if( m_panel->GetCurrentPlotWindow() ) - return m_panel->GetCurrentPlotWindow()->GetSimOptions(); + if( SIM_PLOT_PANEL_BASE* plotPanel = m_panel->GetCurrentPlotPanel() ) + return plotPanel->GetSimOptions(); else - return m_circuitModel->GetSimOptions(); + return NETLIST_EXPORTER_SPICE::OPTION_DEFAULT_FLAGS; } @@ -338,7 +337,7 @@ void SIMULATOR_FRAME::UpdateTitle() -bool SIMULATOR_FRAME::LoadSimulator() +bool SIMULATOR_FRAME::LoadSimulator( const wxString& aSimCommand, unsigned aSimOptions ) { wxString errors; WX_STRING_REPORTER reporter( &errors ); @@ -350,7 +349,7 @@ bool SIMULATOR_FRAME::LoadSimulator() if( ADVANCED_CFG::GetCfg().m_IncrementalConnectivity ) m_schematicFrame->RecalculateConnections( nullptr, GLOBAL_CLEANUP ); - if( !m_simulator->Attach( m_circuitModel, reporter ) ) + if( !m_simulator->Attach( m_circuitModel, aSimCommand, aSimOptions, reporter ) ) { DisplayErrorMessage( this, _( "Errors during netlist generation.\n\n" ) + errors ); return false; @@ -362,56 +361,69 @@ bool SIMULATOR_FRAME::LoadSimulator() void SIMULATOR_FRAME::StartSimulation() { - if( m_circuitModel->CommandToSimType( GetCurrentSimCommand() ) == ST_UNKNOWN ) + SIM_PLOT_PANEL_BASE* plotPanel = m_panel->GetCurrentPlotPanel(); + + if( !plotPanel ) + return; + + if( plotPanel->GetSimCommand().Upper().StartsWith( wxT( "FFT" ) ) ) { - if( !EditSimCommand() ) - return; + wxString tranSpicePlot; - if( m_circuitModel->CommandToSimType( GetCurrentSimCommand() ) == ST_UNKNOWN ) - return; - } + if( SIM_PLOT_PANEL_BASE* tranPlotPanel = m_panel->GetPlotPanel( ST_TRAN ) ) + tranSpicePlot = tranPlotPanel->GetSpicePlotName(); - wxString schTextSimCommand = m_circuitModel->GetSchTextSimCommand(); - SIM_TYPE schTextSimType = NGSPICE_CIRCUIT_MODEL::CommandToSimType( schTextSimCommand ); - SIM_PLOT_PANEL_BASE* plotWindow = m_panel->GetCurrentPlotWindow(); + if( tranSpicePlot.IsEmpty() ) + { + DisplayErrorMessage( this, _( "You must run a TRAN simulation first; its results" + "will be used for the fast Fourier transform." ) ); + } + else + { + m_simulator->Command( "setplot " + tranSpicePlot.ToStdString() ); - if( !plotWindow ) - { - NewPlotPanel( schTextSimCommand, m_circuitModel->GetSimOptions() ); - OnModify(); + wxArrayString commands = wxSplit( plotPanel->GetSimCommand(), '\n' ); + + for( const wxString& command : commands ) + { + wxBusyCursor wait; + m_simulator->Command( command.ToStdString() ); + } + + plotPanel->SetSpicePlotName( m_simulator->CurrentPlotName() ); + m_panel->OnSimRefresh( true ); + +#if 0 + m_simulator->Command( "setplot" ); // Print available plots to console + m_simulator->Command( "display" ); // Print vectors in current plot to console +#endif + } + + return; } else { - m_circuitModel->SetSimCommandOverride( plotWindow->GetSimCommand() ); - - if( plotWindow->GetSimType() == schTextSimType - && schTextSimCommand != m_circuitModel->GetLastSchTextSimCommand() ) + if( m_panel->GetPlotIndex( plotPanel ) == 0 + && m_circuitModel->GetSchTextSimCommand() != plotPanel->GetLastSchTextSimCommand() ) { if( IsOK( this, _( "Schematic sheet simulation command directive has changed. " "Do you wish to update the Simulation Command?" ) ) ) { - m_circuitModel->SetSimCommandOverride( wxEmptyString ); - plotWindow->SetSimCommand( schTextSimCommand ); + plotPanel->SetSimCommand( m_circuitModel->GetSchTextSimCommand() ); + plotPanel->SetLastSchTextSimCommand( plotPanel->GetSimCommand() ); OnModify(); } } } - m_circuitModel->SetSimOptions( GetCurrentOptions() ); - - if( !LoadSimulator() ) + if( !LoadSimulator( plotPanel->GetSimCommand(), plotPanel->GetSimOptions() ) ) return; std::unique_lock simulatorLock( m_simulator->GetMutex(), std::try_to_lock ); if( simulatorLock.owns_lock() ) { - wxBusyCursor toggle; - m_panel->OnSimUpdate(); - - // Prevents memory leak on succeding simulations by deleting old vectors - m_simulator->Clean(); m_simulator->Run(); } else @@ -421,12 +433,18 @@ void SIMULATOR_FRAME::StartSimulation() } -void SIMULATOR_FRAME::NewPlotPanel( const wxString& aSimCommand, int aOptions ) +void SIMULATOR_FRAME::NewPlotPanel( const wxString& aSimCommand, unsigned aOptions ) { m_panel->NewPlotPanel( aSimCommand, aOptions ); } +const std::vector SIMULATOR_FRAME::SimPlotVectors() +{ + return m_panel->SimPlotVectors(); +} + + const std::vector SIMULATOR_FRAME::Signals() { return m_panel->Signals(); @@ -463,9 +481,9 @@ void SIMULATOR_FRAME::AddTuner( const SCH_SHEET_PATH& aSheetPath, SCH_SYMBOL* aS } -SIM_PLOT_PANEL* SIMULATOR_FRAME::GetCurrentPlot() const +SIM_PLOT_PANEL_BASE* SIMULATOR_FRAME::GetCurrentPlotPanel() const { - return m_panel->GetCurrentPlot(); + return m_panel->GetCurrentPlotPanel(); } @@ -511,11 +529,14 @@ void SIMULATOR_FRAME::ToggleDarkModePlots() bool SIMULATOR_FRAME::EditSimCommand() { - SIM_PLOT_PANEL_BASE* plotPanelWindow = m_panel->GetCurrentPlotWindow(); + SIM_PLOT_PANEL_BASE* plotPanel = m_panel->GetCurrentPlotPanel(); DIALOG_SIM_COMMAND dlg( this, m_circuitModel, m_simulator->Settings() ); wxString errors; WX_STRING_REPORTER reporter( &errors ); + if( !plotPanel ) + return false; + if( !m_circuitModel->ReadSchematicAndLibraries( NETLIST_EXPORTER_SPICE::OPTION_DEFAULT_FLAGS, reporter ) ) { @@ -523,55 +544,15 @@ bool SIMULATOR_FRAME::EditSimCommand() + errors ); } - if( m_panel->GetPlotIndex( plotPanelWindow ) != wxNOT_FOUND ) - { - dlg.SetSimCommand( plotPanelWindow->GetSimCommand() ); - dlg.SetSimOptions( plotPanelWindow->GetSimOptions() ); - } - else - { - dlg.SetSimOptions( NETLIST_EXPORTER_SPICE::OPTION_DEFAULT_FLAGS ); - } + dlg.SetSimCommand( plotPanel->GetSimCommand() ); + dlg.SetSimOptions( plotPanel->GetSimOptions() ); if( dlg.ShowModal() == wxID_OK ) { - wxString oldCommand; - - if( m_panel->GetPlotIndex( plotPanelWindow ) != wxNOT_FOUND ) - oldCommand = plotPanelWindow->GetSimCommand(); - else - oldCommand = wxString(); - - const wxString& newCommand = dlg.GetSimCommand(); - int newOptions = dlg.GetSimOptions(); - SIM_TYPE newSimType = NGSPICE_CIRCUIT_MODEL::CommandToSimType( newCommand ); - - if( !plotPanelWindow ) - { - m_circuitModel->SetSimCommandOverride( newCommand ); - m_circuitModel->SetSimOptions( newOptions ); - NewPlotPanel( newCommand, newOptions ); - } - // If it is a new simulation type, open a new plot. For the DC sim, check if sweep - // source type has changed (char 4 will contain 'v', 'i', 'r' or 't'. - else if( plotPanelWindow->GetSimType() != newSimType - || ( newSimType == ST_DC - && oldCommand.Lower().GetChar( 4 ) != newCommand.Lower().GetChar( 4 ) ) ) - { - NewPlotPanel( newCommand, newOptions ); - } - else - { - if( m_panel->GetPlotIndex( plotPanelWindow ) == 0 ) - m_circuitModel->SetSimCommandOverride( newCommand ); - - // Update simulation command in the current plot - plotPanelWindow->SetSimCommand( newCommand ); - plotPanelWindow->SetSimOptions( newOptions ); - } - + plotPanel->SetSimCommand( dlg.GetSimCommand() ); + plotPanel->SetSimOptions( dlg.GetSimOptions() ); + m_panel->OnPlotSettingsChanged(); OnModify(); - m_simulator->Init(); return true; } @@ -633,22 +614,22 @@ void SIMULATOR_FRAME::setupUIConditions() auto showGridCondition = [this]( const SELECTION& aSel ) { - SIM_PLOT_PANEL* plot = GetCurrentPlot(); - return plot && plot->IsGridShown(); + SIM_PLOT_PANEL* plotPanel = dynamic_cast( GetCurrentPlotPanel() ); + return plotPanel && plotPanel->IsGridShown(); }; auto showLegendCondition = [this]( const SELECTION& aSel ) { - SIM_PLOT_PANEL* plot = GetCurrentPlot(); - return plot && plot->IsLegendShown(); + SIM_PLOT_PANEL* plotPanel = dynamic_cast( GetCurrentPlotPanel() ); + return plotPanel && plotPanel->IsLegendShown(); }; auto showDottedCondition = [this]( const SELECTION& aSel ) { - SIM_PLOT_PANEL* plot = GetCurrentPlot(); - return plot && plot->GetDottedSecondary(); + SIM_PLOT_PANEL* plotPanel = dynamic_cast( GetCurrentPlotPanel() ); + return plotPanel && plotPanel->GetDottedSecondary(); }; auto darkModePlotCondition = @@ -669,10 +650,16 @@ void SIMULATOR_FRAME::setupUIConditions() return m_simFinished; }; + auto haveSim = + [this]( const SELECTION& aSel ) + { + return GetCurrentPlotPanel() != nullptr; + }; + auto havePlot = [this]( const SELECTION& aSel ) { - return GetCurrentPlot() != nullptr; + return dynamic_cast( GetCurrentPlotPanel() ) != nullptr; }; #define ENABLE( x ) ACTION_CONDITIONS().Enable( x ) @@ -690,7 +677,8 @@ void SIMULATOR_FRAME::setupUIConditions() mgr->SetConditions( EE_ACTIONS::toggleDottedSecondary, CHECK( showDottedCondition ) ); mgr->SetConditions( EE_ACTIONS::toggleDarkModePlots, CHECK( darkModePlotCondition ) ); - mgr->SetConditions( EE_ACTIONS::simCommand, ENABLE( SELECTION_CONDITIONS::ShowAlways ) ); + mgr->SetConditions( EE_ACTIONS::newPlot, ENABLE( SELECTION_CONDITIONS::ShowAlways ) ); + mgr->SetConditions( EE_ACTIONS::simCommand, ENABLE( haveSim ) ); mgr->SetConditions( EE_ACTIONS::runSimulation, ENABLE( !simRunning ) ); mgr->SetConditions( EE_ACTIONS::stopSimulation, ENABLE( simRunning ) ); mgr->SetConditions( EE_ACTIONS::simProbe, ENABLE( simFinished ) ); @@ -710,13 +698,6 @@ void SIMULATOR_FRAME::onSimStarted( wxCommandEvent& aEvent ) void SIMULATOR_FRAME::onSimFinished( wxCommandEvent& aEvent ) { - SetCursor( wxCURSOR_ARROW ); - - SIM_TYPE simType = m_circuitModel->GetSimType(); - - if( simType == ST_UNKNOWN ) - return; - // Sometimes (for instance with a directive like wrdata my_file.csv "my_signal") // the simulator is in idle state (simulation is finished), but still running, during // the time the file is written. So gives a slice of time to fully finish the work: @@ -745,12 +726,10 @@ void SIMULATOR_FRAME::onSimFinished( wxCommandEvent& aEvent ) m_schematicFrame->RefreshOperatingPointDisplay(); m_schematicFrame->GetCanvas()->Refresh(); - - m_lastSimPlot = m_panel->GetCurrentPlotWindow(); } -void SIMULATOR_FRAME::onSimUpdate( wxCommandEvent& aEvent ) +void SIMULATOR_FRAME::onUpdateSim( wxCommandEvent& aEvent ) { static bool updateInProgress = false; @@ -763,25 +742,16 @@ void SIMULATOR_FRAME::onSimUpdate( wxCommandEvent& aEvent ) if( m_simulator->IsRunning() ) m_simulator->Stop(); - if( m_panel->GetCurrentPlotWindow() != m_lastSimPlot ) + std::unique_lock simulatorLock( m_simulator->GetMutex(), std::try_to_lock ); + + if( simulatorLock.owns_lock() ) { - // We need to rerun simulation, as the simulator currently stores results for another - // plot - StartSimulation(); + m_panel->OnSimUpdate(); + m_simulator->Run(); } else { - std::unique_lock simulatorLock( m_simulator->GetMutex(), std::try_to_lock ); - - if( simulatorLock.owns_lock() ) - { - m_panel->OnSimUpdate(); - m_simulator->Run(); - } - else - { - DisplayErrorMessage( this, _( "Another simulation is already running." ) ); - } + DisplayErrorMessage( this, _( "Another simulation is already running." ) ); } updateInProgress = false; diff --git a/eeschema/sim/simulator_frame.h b/eeschema/sim/simulator_frame.h index 1c825f868c..06e305be23 100644 --- a/eeschema/sim/simulator_frame.h +++ b/eeschema/sim/simulator_frame.h @@ -77,7 +77,7 @@ public: * Check and load the current netlist into the simulator. * @return true if document is fully annotated and netlist was loaded successfully. */ - bool LoadSimulator(); + bool LoadSimulator( const wxString& aSimCommand, unsigned aSimOptions ); void StartSimulation(); @@ -87,7 +87,7 @@ public: * @param aSimCommand is requested simulation command. * @param aSimOptions netlisting options */ - void NewPlotPanel( const wxString& aSimCommand, int aSimOptions ); + void NewPlotPanel( const wxString& aSimCommand, unsigned aSimOptions ); /** * Shows a dialog for editing the current tab's simulation command, or creating a new tab @@ -96,7 +96,12 @@ public: bool EditSimCommand(); /** - * @return the list of signals in the current simulation results. + * @return the list of vectors (signals) in the current simulation results. + */ + const std::vector SimPlotVectors(); + + /** + * @return the list of schematic signals + any user defined signals. */ const std::vector Signals(); @@ -127,7 +132,7 @@ public: /** * Return the current tab (or NULL if there is none). */ - SIM_PLOT_PANEL* GetCurrentPlot() const; + SIM_PLOT_PANEL_BASE* GetCurrentPlotPanel() const; /** * Toggle dark-mode of the plot tabs. @@ -187,7 +192,7 @@ private: bool canCloseWindow( wxCloseEvent& aEvent ) override; void doCloseWindow() override; - void onSimUpdate( wxCommandEvent& aEvent ); + void onUpdateSim( wxCommandEvent& aEvent ); void onSimReport( wxCommandEvent& aEvent ); void onSimStarted( wxCommandEvent& aEvent ); void onSimFinished( wxCommandEvent& aEvent ); @@ -203,7 +208,6 @@ private: SIM_THREAD_REPORTER* m_reporter; std::shared_ptr m_circuitModel; - SIM_PLOT_PANEL_BASE* m_lastSimPlot; bool m_simFinished; bool m_workbookModified; }; diff --git a/eeschema/sim/simulator_panel.cpp b/eeschema/sim/simulator_panel.cpp index efe47669ed..caaf73e9cf 100644 --- a/eeschema/sim/simulator_panel.cpp +++ b/eeschema/sim/simulator_panel.cpp @@ -37,13 +37,12 @@ #include #include #include -#include "ngspice.h" -#include "simulator_panel.h" +#include #include #include #include #include "fmt/format.h" -#include "dialogs/dialog_text_entry.h" +#include #include #include @@ -135,26 +134,29 @@ void SIGNALS_GRID_TRICKS::showPopupMenu( wxMenu& menu, wxGridEvent& aEvent ) m_grid->SetGridCursor( m_menuRow, m_menuCol ); - wxString msg = m_grid->GetCellValue( m_menuRow, m_menuCol ); - - menu.Append( MYID_MEASURE_MIN, _( "Measure Min" ) ); - menu.Append( MYID_MEASURE_MAX, _( "Measure Max" ) ); - menu.Append( MYID_MEASURE_AVG, _( "Measure Average" ) ); - menu.Append( MYID_MEASURE_RMS, _( "Measure RMS" ) ); - menu.Append( MYID_MEASURE_PP, _( "Measure Peak-to-peak" ) ); - menu.Append( MYID_MEASURE_MIN_AT, _( "Measure Time of Min" ) ); - menu.Append( MYID_MEASURE_MAX_AT, _( "Measure Time of Max" ) ); - menu.Append( MYID_MEASURE_INTEGRAL, _( "Measure Integral" ) ); - - SIM_PLOT_PANEL* panel = m_parent->GetCurrentPlot(); - - if( panel && panel->GetSimType() == ST_TRANSIENT ) + if( SIM_PLOT_PANEL_BASE* panel = m_parent->GetCurrentPlotPanel() ) { - menu.AppendSeparator(); - menu.Append( MYID_FOURIER, _( "Perform Fourier Analysis..." ) ); - } + if( panel->GetSimType() == ST_TRAN || panel->GetSimType() == ST_AC + || panel->GetSimType() == ST_DC || panel->GetSimType() == ST_SP ) + { + menu.Append( MYID_MEASURE_MIN, _( "Measure Min" ) ); + menu.Append( MYID_MEASURE_MAX, _( "Measure Max" ) ); + menu.Append( MYID_MEASURE_AVG, _( "Measure Average" ) ); + menu.Append( MYID_MEASURE_RMS, _( "Measure RMS" ) ); + menu.Append( MYID_MEASURE_PP, _( "Measure Peak-to-peak" ) ); + menu.Append( MYID_MEASURE_MIN_AT, _( "Measure Time of Min" ) ); + menu.Append( MYID_MEASURE_MAX_AT, _( "Measure Time of Max" ) ); + menu.Append( MYID_MEASURE_INTEGRAL, _( "Measure Integral" ) ); - menu.AppendSeparator(); + if( panel->GetSimType() == ST_TRAN ) + { + menu.AppendSeparator(); + menu.Append( MYID_FOURIER, _( "Perform Fourier Analysis..." ) ); + } + + menu.AppendSeparator(); + } + } } GRID_TRICKS::showPopupMenu( menu, aEvent ); @@ -588,10 +590,12 @@ void SIMULATOR_PANEL::InitWorkbook() if( !LoadWorkbook( filename.GetFullPath() ) ) simulator()->Settings()->SetWorkbookFilename( "" ); } - else if( m_simulatorFrame->LoadSimulator() ) + else if( m_simulatorFrame->LoadSimulator( wxEmptyString, 0 ) ) { - if( !circuitModel()->GetSchTextSimCommand().IsEmpty() ) - NewPlotPanel( circuitModel()->GetSchTextSimCommand(), circuitModel()->GetSimOptions() ); + wxString schTextSimCommand = circuitModel()->GetSchTextSimCommand(); + + if( !schTextSimCommand.IsEmpty() ) + NewPlotPanel( schTextSimCommand, NETLIST_EXPORTER_SPICE::OPTION_DEFAULT_FLAGS ); rebuildSignalsList(); rebuildSignalsGrid( m_filter->GetValue() ); @@ -627,16 +631,34 @@ void SIMULATOR_PANEL::rebuildSignalsGrid( wxString aFilter ) if( aFilter.IsEmpty() ) aFilter = wxS( "*" ); - EDA_COMBINED_MATCHER matcher( aFilter, CTX_SIGNAL ); - SIM_PLOT_PANEL* plotPanel = GetCurrentPlot(); - int row = 0; + EDA_COMBINED_MATCHER matcher( aFilter.Upper(), CTX_SIGNAL ); + SIM_PLOT_PANEL* plotPanel = dynamic_cast( GetCurrentPlotPanel() ); + std::vector signals; + int row = 0; - for( const wxString& signal : m_signals ) + wxCHECK( plotPanel, /* void */ ); + + if( plotPanel->GetSimType() == ST_FFT ) { - if( matcher.StartsWith( signal ) ) + wxStringTokenizer tokenizer( plotPanel->GetSimCommand(), wxT( " \t\r\n" ), wxTOKEN_STRTOK ); + + while( tokenizer.HasMoreTokens() && tokenizer.GetNextToken().Lower() != wxT( "fft" ) ) + {}; + + while( tokenizer.HasMoreTokens() ) + signals.emplace_back( tokenizer.GetNextToken() ); + } + else + { + signals.insert( signals.end(), m_signals.begin(), m_signals.end() ); + } + + for( const wxString& signal : signals ) + { + if( matcher.Find( signal.Upper() ) ) { int traceType = SPT_UNKNOWN; - wxString vectorName = vectorNameFromSignalName( signal, &traceType ); + wxString vectorName = vectorNameFromSignalName( plotPanel, signal, &traceType ); TRACE* trace = plotPanel ? plotPanel->GetTrace( vectorName, traceType ) : nullptr; m_signalsGrid->AppendRows( 1 ); @@ -714,7 +736,7 @@ void SIMULATOR_PANEL::rebuildSignalsList() wxString unconnected = wxString( wxS( "unconnected-(" ) ); if( simType == ST_UNKNOWN ) - simType = ST_TRANSIENT; + simType = ST_TRAN; unconnected.Replace( '(', '_' ); // Convert to SPICE markup @@ -726,7 +748,7 @@ void SIMULATOR_PANEL::rebuildSignalsList() m_signals.push_back( aSignalName + _( " (gain)" ) ); m_signals.push_back( aSignalName + _( " (phase)" ) ); } - else if( simType == ST_S_PARAM ) + else if( simType == ST_SP ) { m_signals.push_back( aSignalName + _( " (amplitude)" ) ); m_signals.push_back( aSignalName + _( " (phase)" ) ); @@ -738,7 +760,7 @@ void SIMULATOR_PANEL::rebuildSignalsList() }; if( ( options & NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_VOLTAGES ) - && ( simType == ST_TRANSIENT || simType == ST_DC || simType == ST_AC ) ) + && ( simType == ST_TRAN || simType == ST_DC || simType == ST_AC || simType == ST_FFT) ) { for( const std::string& net : circuitModel()->GetNets() ) { @@ -754,7 +776,7 @@ void SIMULATOR_PANEL::rebuildSignalsList() } if( ( options & NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_CURRENTS ) - && ( simType == ST_TRANSIENT || simType == ST_DC ) ) + && ( simType == ST_TRAN || simType == ST_DC ) ) { for( const SPICE_ITEM& item : circuitModel()->GetItems() ) { @@ -765,7 +787,7 @@ void SIMULATOR_PANEL::rebuildSignalsList() } if( ( options & NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_DISSIPATIONS ) - && ( simType == ST_TRANSIENT || simType == ST_DC ) ) + && ( simType == ST_TRAN || simType == ST_DC ) ) { for( const SPICE_ITEM& item : circuitModel()->GetItems() ) { @@ -783,7 +805,7 @@ void SIMULATOR_PANEL::rebuildSignalsList() addSignal( wxS( "onoise_spectrum" ) ); } - if( simType == ST_S_PARAM ) + if( simType == ST_SP ) { std::vector portnums; @@ -845,14 +867,15 @@ void SIMULATOR_PANEL::rebuildSignalsList() } -SIM_PLOT_PANEL_BASE* SIMULATOR_PANEL::NewPlotPanel( const wxString& aSimCommand, int aOptions ) +SIM_PLOT_PANEL_BASE* SIMULATOR_PANEL::NewPlotPanel( const wxString& aSimCommand, + unsigned aSimOptions ) { SIM_PLOT_PANEL_BASE* plotPanel = nullptr; SIM_TYPE simType = NGSPICE_CIRCUIT_MODEL::CommandToSimType( aSimCommand ); if( SIM_PLOT_PANEL_BASE::IsPlottable( simType ) ) { - SIM_PLOT_PANEL* panel = new SIM_PLOT_PANEL( aSimCommand, aOptions, m_plotNotebook, wxID_ANY ); + SIM_PLOT_PANEL* panel = new SIM_PLOT_PANEL( aSimCommand, aSimOptions, m_plotNotebook ); plotPanel = panel; COMMON_SETTINGS::INPUT cfg = Pgm().GetCommonSettings()->m_Input; @@ -860,7 +883,7 @@ SIM_PLOT_PANEL_BASE* SIMULATOR_PANEL::NewPlotPanel( const wxString& aSimCommand, } else { - plotPanel = new SIM_NOPLOT_PANEL( aSimCommand, aOptions, m_plotNotebook, wxID_ANY ); + plotPanel = new SIM_NOPLOT_PANEL( aSimCommand, aSimOptions, m_plotNotebook ); } wxString pageTitle( simulator()->TypeToName( simType, true ) ); @@ -904,7 +927,8 @@ wxString vectorNameFromSignalId( int aUserDefinedSignalId ) * For user-defined signals we display the user-oriented signal name such as "V(out)-V(in)", * but the simulator vector we actually have to plot will be "user0" or some-such. */ -wxString SIMULATOR_PANEL::vectorNameFromSignalName( const wxString& aSignalName, int* aTraceType ) +wxString SIMULATOR_PANEL::vectorNameFromSignalName( SIM_PLOT_PANEL* aPlotPanel, + const wxString& aSignalName, int* aTraceType ) { std::map suffixes; suffixes[ _( " (amplitude)" ) ] = SPT_SP_AMP; @@ -913,7 +937,7 @@ wxString SIMULATOR_PANEL::vectorNameFromSignalName( const wxString& aSignalName, if( aTraceType ) { - if( circuitModel()->GetSimType() == ST_NOISE ) + if( aPlotPanel && aPlotPanel->GetSimType() == ST_NOISE ) { if( getNoiseSource().Upper().StartsWith( 'I' ) ) *aTraceType = SPT_CURRENT; @@ -967,17 +991,17 @@ void SIMULATOR_PANEL::onSignalsGridCellChanged( wxGridEvent& aEvent ) int row = aEvent.GetRow(); int col = aEvent.GetCol(); wxString text = m_signalsGrid->GetCellValue( row, col ); - SIM_PLOT_PANEL* plot = GetCurrentPlot(); + SIM_PLOT_PANEL* plotPanel = dynamic_cast( GetCurrentPlotPanel() ); wxString signalName = m_signalsGrid->GetCellValue( row, COL_SIGNAL_NAME ); int traceType = SPT_UNKNOWN; - wxString vectorName = vectorNameFromSignalName( signalName, &traceType ); + wxString vectorName = vectorNameFromSignalName( plotPanel, signalName, &traceType ); if( col == COL_SIGNAL_SHOW ) { if( text == wxS( "1" ) ) - updateTrace( vectorName, traceType, plot ); + updateTrace( vectorName, traceType, plotPanel ); else - plot->DeleteTrace( vectorName, traceType ); + plotPanel->DeleteTrace( vectorName, traceType ); // Update enabled/visible states of other controls updateSignalsGrid(); @@ -987,13 +1011,13 @@ void SIMULATOR_PANEL::onSignalsGridCellChanged( wxGridEvent& aEvent ) else if( col == COL_SIGNAL_COLOR ) { KIGFX::COLOR4D color( m_signalsGrid->GetCellValue( row, COL_SIGNAL_COLOR ) ); - TRACE* trace = plot->GetTrace( vectorName, traceType ); + TRACE* trace = plotPanel->GetTrace( vectorName, traceType ); if( trace ) { trace->SetTraceColour( color.ToColour() ); - plot->UpdateTraceStyle( trace ); - plot->UpdatePlotColors(); + plotPanel->UpdateTraceStyle( trace ); + plotPanel->UpdatePlotColors(); m_simulatorFrame->OnModify(); } } @@ -1002,12 +1026,12 @@ void SIMULATOR_PANEL::onSignalsGridCellChanged( wxGridEvent& aEvent ) for( int ii = 0; ii < m_signalsGrid->GetNumberRows(); ++ii ) { signalName = m_signalsGrid->GetCellValue( ii, COL_SIGNAL_NAME ); - vectorName = vectorNameFromSignalName( signalName, &traceType ); + vectorName = vectorNameFromSignalName( plotPanel, signalName, &traceType ); int id = col == COL_CURSOR_1 ? 1 : 2; bool enable = ii == row && text == wxS( "1" ); - plot->EnableCursor( vectorName, traceType, id, enable, signalName ); + plotPanel->EnableCursor( vectorName, traceType, id, enable, signalName ); m_simulatorFrame->OnModify(); } @@ -1022,7 +1046,7 @@ void SIMULATOR_PANEL::onCursorsGridCellChanged( wxGridEvent& aEvent ) if( m_SuppressGridEvents > 0 ) return; - SIM_PLOT_PANEL* plotPanel = GetCurrentPlot(); + SIM_PLOT_PANEL* plotPanel = dynamic_cast( GetCurrentPlotPanel() ); if( !plotPanel ) return; @@ -1092,7 +1116,7 @@ void SIMULATOR_PANEL::DeleteMeasurement( int aRow ) void SIMULATOR_PANEL::onMeasurementsGridCellChanged( wxGridEvent& aEvent ) { - SIM_PLOT_PANEL* plotPanel = GetCurrentPlot(); + SIM_PLOT_PANEL* plotPanel = dynamic_cast( GetCurrentPlotPanel() ); if( !plotPanel ) return; @@ -1158,7 +1182,7 @@ void SIMULATOR_PANEL::UpdateMeasurement( int aRow ) " +" "([a-zA-Z])\\(([^\\)]+)\\)" ) ); - SIM_PLOT_PANEL* plotPanel = GetCurrentPlot(); + SIM_PLOT_PANEL* plotPanel = dynamic_cast( GetCurrentPlotPanel() ); if( !plotPanel ) return; @@ -1200,23 +1224,24 @@ void SIMULATOR_PANEL::UpdateMeasurement( int aRow ) { switch( plotPanel->GetSimType() ) { - case SIM_TYPE::ST_TRANSIENT: + case SIM_TYPE::ST_TRAN: if ( signalType == 'P' ) units = wxS( "J" ); else units += wxS( ".s" ); break; case SIM_TYPE::ST_AC: - case SIM_TYPE::ST_S_PARAM: - case SIM_TYPE::ST_DISTORTION: + case SIM_TYPE::ST_SP: + case SIM_TYPE::ST_DISTO: case SIM_TYPE::ST_NOISE: - case SIM_TYPE::ST_SENSITIVITY: // If there is a vector, it is frequency + case SIM_TYPE::ST_FFT: + case SIM_TYPE::ST_SENS: // If there is a vector, it is frequency units += wxS( "·Hz" ); break; case SIM_TYPE::ST_DC: // Could be a lot of things : V, A, deg C, ohm, ... case SIM_TYPE::ST_OP: // There is no vector for integration - case SIM_TYPE::ST_POLE_ZERO: // There is no vector for integration - case SIM_TYPE::ST_TRANS_FUNC: // There is no vector for integration + case SIM_TYPE::ST_PZ: // There is no vector for integration + case SIM_TYPE::ST_TF: // There is no vector for integration default: units += wxS( "·?" ); @@ -1246,7 +1271,7 @@ void SIMULATOR_PANEL::UpdateMeasurement( int aRow ) void SIMULATOR_PANEL::AddTuner( const SCH_SHEET_PATH& aSheetPath, SCH_SYMBOL* aSymbol ) { - SIM_PLOT_PANEL_BASE* plotPanel = GetCurrentPlotWindow(); + SIM_PLOT_PANEL* plotPanel = dynamic_cast( GetCurrentPlotPanel() ); if( !plotPanel ) return; @@ -1332,7 +1357,7 @@ void SIMULATOR_PANEL::AddMeasurement( const wxString& aCmd ) return; // Don't create duplicates } - SIM_PLOT_PANEL* plotPanel = GetCurrentPlot(); + SIM_PLOT_PANEL* plotPanel = dynamic_cast( GetCurrentPlotPanel() ); if( !plotPanel ) return; @@ -1384,16 +1409,14 @@ const NGSPICE_CIRCUIT_MODEL* SIMULATOR_PANEL::GetExporter() const void SIMULATOR_PANEL::AddTrace( const wxString& aName, SIM_TRACE_TYPE aType ) { - SIM_PLOT_PANEL* plotPanel = GetCurrentPlot(); - - if( !plotPanel ) + if( !GetCurrentPlotPanel() ) { m_simConsole->AppendText( _( "Error: no current simulation.\n" ) ); m_simConsole->SetInsertionPointEnd(); return; } - SIM_TYPE simType = NGSPICE_CIRCUIT_MODEL::CommandToSimType( plotPanel->GetSimCommand() ); + SIM_TYPE simType = NGSPICE_CIRCUIT_MODEL::CommandToSimType( GetCurrentPlotPanel()->GetSimCommand() ); if( simType == ST_UNKNOWN ) { @@ -1408,12 +1431,15 @@ void SIMULATOR_PANEL::AddTrace( const wxString& aName, SIM_TRACE_TYPE aType ) return; } + SIM_PLOT_PANEL* plotPanel = dynamic_cast( GetCurrentPlotPanel() ); + wxCHECK( plotPanel, /* void */ ); + if( simType == ST_AC ) { updateTrace( aName, aType | SPT_AC_GAIN, plotPanel ); updateTrace( aName, aType | SPT_AC_PHASE, plotPanel ); } - if( simType == ST_S_PARAM ) + else if( simType == ST_SP ) { updateTrace( aName, aType | SPT_AC_GAIN, plotPanel ); updateTrace( aName, aType | SPT_AC_PHASE, plotPanel ); @@ -1440,7 +1466,7 @@ void SIMULATOR_PANEL::SetUserDefinedSignals( const std::map& aNew for( const auto& [ id, existingSignal ] : m_userDefinedSignals ) { int traceType = SPT_UNKNOWN; - wxString vectorName = vectorNameFromSignalName( existingSignal, &traceType ); + wxString vectorName = vectorNameFromSignalName( plotPanel, existingSignal, &traceType ); if( aNewSignals.count( id ) == 0 ) { @@ -1449,7 +1475,7 @@ void SIMULATOR_PANEL::SetUserDefinedSignals( const std::map& aNew for( int subType : { SPT_AC_GAIN, SPT_AC_PHASE } ) plotPanel->DeleteTrace( vectorName, traceType | subType ); } - else if( plotPanel->GetSimType() == ST_S_PARAM ) + else if( plotPanel->GetSimType() == ST_SP ) { for( int subType : { SPT_SP_AMP, SPT_AC_PHASE } ) plotPanel->DeleteTrace( vectorName, traceType | subType ); @@ -1469,7 +1495,7 @@ void SIMULATOR_PANEL::SetUserDefinedSignals( const std::map& aNew trace->SetName( aNewSignals.at( id ) ); } } - else if( plotPanel->GetSimType() == ST_S_PARAM ) + else if( plotPanel->GetSimType() == ST_SP ) { for( int subType : { SPT_SP_AMP, SPT_AC_PHASE } ) { @@ -1542,7 +1568,7 @@ void SIMULATOR_PANEL::updateTrace( const wxString& aVectorName, int aTraceType, wxFAIL_MSG( wxT( "Plot type missing AC_PHASE or AC_MAG bit" ) ); break; - case ST_S_PARAM: + case ST_SP: if( aTraceType & SPT_SP_AMP ) data_y = simulator()->GetGainVector( (const char*) simVectorName.c_str() ); else if( aTraceType & SPT_AC_PHASE ) @@ -1554,7 +1580,8 @@ void SIMULATOR_PANEL::updateTrace( const wxString& aVectorName, int aTraceType, case ST_NOISE: case ST_DC: - case ST_TRANSIENT: + case ST_TRAN: + case ST_FFT: data_y = simulator()->GetGainVector( (const char*) simVectorName.c_str() ); break; @@ -1569,7 +1596,7 @@ void SIMULATOR_PANEL::updateTrace( const wxString& aVectorName, int aTraceType, SPICE_DC_PARAMS source1, source2; if( simType == ST_DC - && circuitModel()->ParseDCCommand( circuitModel()->GetSimCommand(), &source1, &source2 ) + && circuitModel()->ParseDCCommand( aPlotPanel->GetSimCommand(), &source1, &source2 ) && !source2.m_source.IsEmpty() ) { // Source 1 is the inner loop, so lets add traces for each Source 2 (outer loop) step @@ -1610,15 +1637,15 @@ void SIMULATOR_PANEL::updateTrace( const wxString& aVectorName, int aTraceType, void SIMULATOR_PANEL::updateSignalsGrid() { - SIM_PLOT_PANEL* plot = GetCurrentPlot(); + SIM_PLOT_PANEL* plotPanel = dynamic_cast( GetCurrentPlotPanel() ); for( int row = 0; row < m_signalsGrid->GetNumberRows(); ++row ) { wxString signalName = m_signalsGrid->GetCellValue( row, COL_SIGNAL_NAME ); int traceType = SPT_UNKNOWN; - wxString vectorName = vectorNameFromSignalName( signalName, &traceType ); + wxString vectorName = vectorNameFromSignalName( plotPanel, signalName, &traceType ); - if( TRACE* trace = plot ? plot->GetTrace( vectorName, traceType ) : nullptr ) + if( TRACE* trace = plotPanel ? plotPanel->GetTrace( vectorName, traceType ) : nullptr ) { m_signalsGrid->SetCellValue( row, COL_SIGNAL_SHOW, wxS( "1" ) ); @@ -1941,26 +1968,30 @@ bool SIMULATOR_PANEL::LoadWorkbook( const wxString& aPath ) if( plotPanel ) traceInfo[ plotPanel ].emplace_back( std::make_tuple( traceType, name, param ) ); } + + if( version > 4 ) + { + long measurementCount; + + file.GetNextLine().ToLong( &measurementCount ); + + for( int ii = 0; ii < (int) measurementCount; ++ ii ) + { + wxString measurement = file.GetNextLine(); + wxString format = file.GetNextLine(); + + if( plotPanel ) + plotPanel->Measurements().emplace_back( measurement, format ); + } + } } long userDefinedSignalCount; - long measurementCount; if( file.GetNextLine().ToLong( &userDefinedSignalCount ) ) { for( int ii = 0; ii < (int) userDefinedSignalCount; ++ii ) m_userDefinedSignals[ ii ] = file.GetNextLine(); - - file.GetNextLine().ToLong( &measurementCount ); - - m_measurementsGrid->ClearRows(); - m_measurementsGrid->AppendRows( (int) measurementCount + 1 /* empty row at end */ ); - - for( int row = 0; row < (int) measurementCount; ++row ) - { - m_measurementsGrid->SetCellValue( row, COL_MEASUREMENT, file.GetNextLine() ); - m_measurementsGrid->SetCellValue( row, COL_MEASUREMENT_FORMAT, file.GetNextLine() ); - } } for( const auto& [ plotPanel, traceInfoVector ] : traceInfo ) @@ -1985,7 +2016,7 @@ bool SIMULATOR_PANEL::LoadWorkbook( const wxString& aPath ) } else { - wxString vectorName = vectorNameFromSignalName( signalName, nullptr ); + wxString vectorName = vectorNameFromSignalName( plotPanel, signalName, nullptr ); TRACE* trace = plotPanel->AddTrace( vectorName, (int) traceType ); if( version >= 4 && trace ) @@ -1996,35 +2027,15 @@ bool SIMULATOR_PANEL::LoadWorkbook( const wxString& aPath ) plotPanel->UpdatePlotColors(); } - m_simulatorFrame->LoadSimulator(); - - wxString schTextSimCommand = circuitModel()->GetSchTextSimCommand().Lower(); - SIM_TYPE schTextSimType = NGSPICE_CIRCUIT_MODEL::CommandToSimType( schTextSimCommand ); - - if( schTextSimType != ST_UNKNOWN ) + if( SIM_PLOT_PANEL_BASE* plotPanel = GetCurrentPlotPanel() ) { - bool found = false; + m_simulatorFrame->LoadSimulator( plotPanel->GetSimCommand(), plotPanel->GetSimOptions() ); - for( int ii = 0; ii < (int) m_plotNotebook->GetPageCount(); ++ii ) + if( version >= 5 ) { - auto* plot = dynamic_cast( m_plotNotebook->GetPage( ii ) ); - - if( plot && plot->GetSimType() == schTextSimType ) - { - if( schTextSimType == ST_DC ) - { - wxString plotSimCommand = plot->GetSimCommand().Lower(); - found = plotSimCommand.GetChar( 4 ) == schTextSimCommand.GetChar( 4 ); - } - else - { - found = true; - } - } + plotPanel = dynamic_cast( m_plotNotebook->GetPage( 0 ) ); + plotPanel->SetLastSchTextSimCommand( file.GetNextLine() ); } - - if( !found ) - NewPlotPanel( schTextSimCommand, circuitModel()->GetSimOptions() ); } rebuildSignalsList(); @@ -2032,6 +2043,7 @@ bool SIMULATOR_PANEL::LoadWorkbook( const wxString& aPath ) rebuildSignalsGrid( m_filter->GetValue() ); updateSignalsGrid(); updatePlotCursors(); + rebuildMeasurementsGrid(); file.Close(); @@ -2064,13 +2076,13 @@ bool SIMULATOR_PANEL::SaveWorkbook( const wxString& aPath ) file.Create(); } - file.AddLine( wxT( "version 4" ) ); + file.AddLine( wxT( "version 5" ) ); file.AddLine( wxString::Format( wxT( "%llu" ), m_plotNotebook->GetPageCount() ) ); for( size_t i = 0; i < m_plotNotebook->GetPageCount(); i++ ) { - auto* basePanel = dynamic_cast( m_plotNotebook->GetPage( i ) ); + auto* basePanel = dynamic_cast( m_plotNotebook->GetPage( i ) ); if( !basePanel ) { @@ -2097,7 +2109,7 @@ bool SIMULATOR_PANEL::SaveWorkbook( const wxString& aPath ) file.AddLine( EscapeString( command, CTX_LINE ) ); - const SIM_PLOT_PANEL* plotPanel = dynamic_cast( basePanel ); + SIM_PLOT_PANEL* plotPanel = dynamic_cast( basePanel ); if( !plotPanel ) { @@ -2171,6 +2183,14 @@ bool SIMULATOR_PANEL::SaveWorkbook( const wxString& aPath ) plotPanel->GetLegendPosition().x, plotPanel->GetLegendPosition().y - 40 ) ); } + + file.AddLine( wxString::Format( wxT( "%llu" ), plotPanel->Measurements().size() ) ); + + for( const auto& [ measurement, format ] : plotPanel->Measurements() ) + { + file.AddLine( measurement ); + file.AddLine( format ); + } } file.AddLine( wxString::Format( wxT( "%llu" ), m_userDefinedSignals.size() ) ); @@ -2178,25 +2198,18 @@ bool SIMULATOR_PANEL::SaveWorkbook( const wxString& aPath ) for( const auto& [ id, signal ] : m_userDefinedSignals ) file.AddLine( signal ); - std::vector measurements; - std::vector formats; + // Store the value of any simulation command found on the schematic sheet in a SCH_TEXT + // object. If this changes we want to warn the user and ask them if they want to update + // the corresponding panel's sim command. + wxString lastSchTextSimCommand; - for( int i = 0; i < m_measurementsGrid->GetNumberRows(); ++i ) + if( m_plotNotebook->GetPageCount() > 0 ) { - if( !m_measurementsGrid->GetCellValue( i, COL_MEASUREMENT ).IsEmpty() ) - { - measurements.push_back( m_measurementsGrid->GetCellValue( i, COL_MEASUREMENT ) ); - formats.push_back( m_measurementsGrid->GetCellValue( i, COL_MEASUREMENT_FORMAT ) ); - } + auto* basePanel = dynamic_cast( m_plotNotebook->GetPage( 0 ) ); + lastSchTextSimCommand = basePanel->GetLastSchTextSimCommand(); } - file.AddLine( wxString::Format( wxT( "%llu" ), measurements.size() ) ); - - for( size_t i = 0; i < measurements.size(); i++ ) - { - file.AddLine( measurements[i] ); - file.AddLine( formats[i] ); - } + file.AddLine( lastSchTextSimCommand ); bool res = file.Write(); file.Close(); @@ -2217,12 +2230,13 @@ SIM_TRACE_TYPE SIMULATOR_PANEL::getXAxisType( SIM_TYPE aType ) const switch( aType ) { /// @todo SPT_LOG_FREQUENCY - case ST_AC: return SPT_LIN_FREQUENCY; - case ST_S_PARAM: return SPT_LIN_FREQUENCY; - case ST_DC: return SPT_SWEEP; - case ST_TRANSIENT: return SPT_TIME; - case ST_NOISE: return SPT_LIN_FREQUENCY; - default: wxFAIL_MSG( wxS( "Unhandled simulation type" ) ); return SPT_UNKNOWN; + case ST_AC: return SPT_LIN_FREQUENCY; + case ST_SP: return SPT_LIN_FREQUENCY; + case ST_FFT: return SPT_LIN_FREQUENCY; + case ST_DC: return SPT_SWEEP; + case ST_TRAN: return SPT_TIME; + case ST_NOISE: return SPT_LIN_FREQUENCY; + default: wxFAIL_MSG( wxS( "Unhandled simulation type" ) ); return SPT_UNKNOWN; } } @@ -2238,8 +2252,11 @@ wxString SIMULATOR_PANEL::getNoiseSource() const SPICE_VALUE fStop; bool saveAll; - circuitModel()->ParseNoiseCommand( circuitModel()->GetSimCommand(), &output, &ref, &source, - &scale, &pts, &fStart, &fStop, &saveAll ); + if( GetCurrentPlotPanel() ) + { + circuitModel()->ParseNoiseCommand( GetCurrentPlotPanel()->GetSimCommand(), &output, &ref, + &source, &scale, &pts, &fStart, &fStop, &saveAll ); + } return source; } @@ -2280,7 +2297,7 @@ void SIMULATOR_PANEL::onPlotClosed( wxAuiNotebookEvent& event ) rebuildSignalsGrid( m_filter->GetValue() ); updatePlotCursors(); - SIM_PLOT_PANEL_BASE* panel = GetCurrentPlotWindow(); + SIM_PLOT_PANEL_BASE* panel = GetCurrentPlotPanel(); if( !panel || panel->GetSimType() != ST_OP ) { @@ -2293,11 +2310,72 @@ void SIMULATOR_PANEL::onPlotClosed( wxAuiNotebookEvent& event ) } -void SIMULATOR_PANEL::onPlotChanged( wxAuiNotebookEvent& event ) +void SIMULATOR_PANEL::onPlotChanging( wxAuiNotebookEvent& event ) +{ + if( SIM_PLOT_PANEL* plotPanel = dynamic_cast( GetCurrentPlotPanel() ) ) + { + std::vector>& measurements = plotPanel->Measurements(); + + measurements.clear(); + + for( int row = 0; row < m_measurementsGrid->GetNumberRows(); ++row ) + { + if( !m_measurementsGrid->GetCellValue( row, COL_MEASUREMENT ).IsEmpty() ) + { + measurements.emplace_back( m_measurementsGrid->GetCellValue( row, COL_MEASUREMENT ), + m_measurementsGrid->GetCellValue( row, COL_MEASUREMENT_FORMAT ) ); + } + } + } + + event.Skip(); +} + + +void SIMULATOR_PANEL::OnPlotSettingsChanged() { rebuildSignalsList(); rebuildSignalsGrid( m_filter->GetValue() ); updatePlotCursors(); + + rebuildMeasurementsGrid(); + + for( int row = 0; row < m_measurementsGrid->GetNumberRows(); ++row ) + UpdateMeasurement( row ); +} + + +void SIMULATOR_PANEL::onPlotChanged( wxAuiNotebookEvent& event ) +{ + if( SIM_PLOT_PANEL_BASE* plotWindow = GetCurrentPlotPanel() ) + simulator()->Command( "setplot " + plotWindow->GetSpicePlotName().ToStdString() ); + + OnPlotSettingsChanged(); + + event.Skip(); +} + + +void SIMULATOR_PANEL::rebuildMeasurementsGrid() +{ + m_measurementsGrid->ClearRows(); + + if( SIM_PLOT_PANEL* plotPanel = dynamic_cast( GetCurrentPlotPanel() ) ) + { + for( const auto& [ measurement, format ] : plotPanel->Measurements() ) + { + int row = m_measurementsGrid->GetNumberRows(); + m_measurementsGrid->AppendRows(); + m_measurementsGrid->SetCellValue( row, COL_MEASUREMENT, measurement ); + m_measurementsGrid->SetCellValue( row, COL_MEASUREMENT_FORMAT, format ); + } + + if( plotPanel->GetSimType() == ST_TRAN || plotPanel->GetSimType() == ST_AC + || plotPanel->GetSimType() == ST_DC || plotPanel->GetSimType() == ST_SP ) + { + m_measurementsGrid->AppendRows(); // Empty row at end + } + } } @@ -2331,7 +2409,7 @@ void SIMULATOR_PANEL::updatePlotCursors() m_cursorsGrid->ClearRows(); - SIM_PLOT_PANEL* plotPanel = GetCurrentPlot(); + SIM_PLOT_PANEL* plotPanel = dynamic_cast( GetCurrentPlotPanel() ); if( !plotPanel ) return; @@ -2469,7 +2547,7 @@ void SIMULATOR_PANEL::onPlotCursorUpdate( wxCommandEvent& aEvent ) void SIMULATOR_PANEL::OnSimUpdate() { - if( SIM_PLOT_PANEL* plotPanel = dynamic_cast( GetCurrentPlotWindow() ) ) + if( SIM_PLOT_PANEL* plotPanel = dynamic_cast( GetCurrentPlotPanel() ) ) plotPanel->ResetScales( true ); m_simConsole->Clear(); @@ -2488,7 +2566,7 @@ void SIMULATOR_PANEL::OnSimReport( const wxString& aMsg ) } -std::vector SIMULATOR_PANEL::Signals() const +std::vector SIMULATOR_PANEL::SimPlotVectors() const { std::vector signals; @@ -2499,20 +2577,32 @@ std::vector SIMULATOR_PANEL::Signals() const } +std::vector SIMULATOR_PANEL::Signals() const +{ + std::vector signals; + + for( const wxString& signal : m_signals ) + signals.emplace_back( signal ); + + for( const auto& [ id, signal ] : m_userDefinedSignals ) + signals.emplace_back( signal ); + + return signals; +} + + void SIMULATOR_PANEL::OnSimRefresh( bool aFinal ) { - SIM_TYPE simType = circuitModel()->GetSimType(); - SIM_PLOT_PANEL_BASE* plotPanelWindow = GetCurrentPlotWindow(); + SIM_PLOT_PANEL_BASE* plotPanelBase = GetCurrentPlotPanel(); - if( !plotPanelWindow || plotPanelWindow->GetSimType() != simType ) - { - plotPanelWindow = NewPlotPanel( circuitModel()->GetSimCommand(), - circuitModel()->GetSimOptions() ); - } + if( !plotPanelBase ) + return; + SIM_TYPE simType = plotPanelBase->GetSimType(); std::vector oldSignals = m_signals; wxString msg; + plotPanelBase->SetSpicePlotName( simulator()->CurrentPlotName() ); applyUserDefinedSignals(); rebuildSignalsList(); @@ -2527,7 +2617,8 @@ void SIMULATOR_PANEL::OnSimRefresh( bool aFinal ) // The simulator will create noise1 & noise2 on the first run, noise3 and noise4 // on the second, etc. The first plot for each run contains the spectral density // noise vectors and second contains the integrated noise. - simulator()->Command( "setplot noise2" ); + long number; + simulator()->CurrentPlotName().Mid( 5 ).ToLong( &number ); for( const std::string& vec : simulator()->AllVectors() ) { @@ -2540,10 +2631,11 @@ void SIMULATOR_PANEL::OnSimRefresh( bool aFinal ) m_simConsole->SetInsertionPointEnd(); } - simulator()->Command( "setplot noise1" ); + simulator()->Command( fmt::format( "setplot noise{}", number - 1 ) ); + plotPanelBase->SetSpicePlotName( simulator()->CurrentPlotName() ); } - SIM_PLOT_PANEL* plotPanel = dynamic_cast( plotPanelWindow ); + SIM_PLOT_PANEL* plotPanel = dynamic_cast( plotPanelBase ); wxCHECK_RET( plotPanel, wxT( "not a SIM_PLOT_PANEL" ) ); // Map of TRACE* to { vectorName, traceType } @@ -2555,7 +2647,7 @@ void SIMULATOR_PANEL::OnSimRefresh( bool aFinal ) for( const wxString& signal : m_signals ) { int traceType = SPT_UNKNOWN; - wxString vectorName = vectorNameFromSignalName( signal, &traceType ); + wxString vectorName = vectorNameFromSignalName( plotPanel, signal, &traceType ); if( simType == ST_AC ) { @@ -2565,7 +2657,7 @@ void SIMULATOR_PANEL::OnSimRefresh( bool aFinal ) traceMap[ trace ] = { vectorName, traceType }; } } - if( simType == ST_S_PARAM ) + else if( simType == ST_SP ) { for( int subType : { SPT_SP_AMP, SPT_AC_PHASE } ) { @@ -2603,6 +2695,11 @@ void SIMULATOR_PANEL::OnSimRefresh( bool aFinal ) plotPanel->ResetScales( true ); plotPanel->GetPlotWin()->Fit(); + + updatePlotCursors(); + + for( int row = 0; row < m_measurementsGrid->GetNumberRows(); ++row ) + UpdateMeasurement( row ); } else if( simType == ST_OP ) { @@ -2634,11 +2731,6 @@ void SIMULATOR_PANEL::OnSimRefresh( bool aFinal ) m_schematicFrame->Schematic().SetOperatingPoint( signal, val_list.at( 0 ) ); } } - - updatePlotCursors(); - - for( int row = 0; row < m_measurementsGrid->GetNumberRows(); ++row ) - UpdateMeasurement( row ); } diff --git a/eeschema/sim/simulator_panel.h b/eeschema/sim/simulator_panel.h index 911ba2d88f..50b830d51e 100644 --- a/eeschema/sim/simulator_panel.h +++ b/eeschema/sim/simulator_panel.h @@ -79,7 +79,9 @@ public: * @param aSimOptions netlisting options * @return The new plot panel. */ - SIM_PLOT_PANEL_BASE* NewPlotPanel( const wxString& aSimCommand, int aSimOptions ); + SIM_PLOT_PANEL_BASE* NewPlotPanel( const wxString& aSimCommand, unsigned aSimOptions ); + + std::vector SimPlotVectors() const; std::vector Signals() const; @@ -194,23 +196,22 @@ public: /** * Return the currently opened plot panel (or NULL if there is none). */ - SIM_PLOT_PANEL_BASE* GetCurrentPlotWindow() const + SIM_PLOT_PANEL_BASE* GetCurrentPlotPanel() const { return dynamic_cast( m_plotNotebook->GetCurrentPage() ); } - /** - * Return the current tab (or NULL if there is none). - */ - SIM_PLOT_PANEL* GetCurrentPlot() const + SIM_PLOT_PANEL_BASE* GetPlotPanel( SIM_TYPE aType ) const { - SIM_PLOT_PANEL_BASE* plotWindow = GetCurrentPlotWindow(); + for( int ii = 0; ii < (int) m_plotNotebook->GetPageCount(); ++ii ) + { + auto* candidate = dynamic_cast( m_plotNotebook->GetPage( ii ) ); - if( !plotWindow ) - return nullptr; + if( candidate && candidate->GetSimType() == aType ) + return candidate; + } - return plotWindow->GetSimType() == ST_UNKNOWN ? nullptr - : dynamic_cast( plotWindow ); + return nullptr; } int GetPlotIndex( SIM_PLOT_PANEL_BASE* aPlot ) const @@ -218,6 +219,8 @@ public: return m_plotNotebook->GetPageIndex( aPlot ); } + void OnPlotSettingsChanged(); + void OnSimUpdate(); void OnSimReport( const wxString& aMsg ); void OnSimRefresh( bool aFinal ); @@ -226,7 +229,8 @@ private: /** * Get the simulator output vector name for a given signal name and type. */ - wxString vectorNameFromSignalName( const wxString& aSignalName, int* aTraceType ); + wxString vectorNameFromSignalName( SIM_PLOT_PANEL* aPlotPanel, const wxString& aSignalName, + int* aTraceType ); /** * Update a trace in a particular SIM_PLOT_PANEL. If the panel does not contain the given @@ -265,6 +269,11 @@ private: */ void applyUserDefinedSignals(); + /** + * Rebuild the measurements grid for the current plot. + */ + void rebuildMeasurementsGrid(); + /** * Apply component values specified using tuner sliders to the current netlist. */ @@ -286,6 +295,7 @@ private: // Event handlers void onPlotClose( wxAuiNotebookEvent& event ) override; void onPlotClosed( wxAuiNotebookEvent& event ) override; + void onPlotChanging( wxAuiNotebookEvent& event ) override; void onPlotChanged( wxAuiNotebookEvent& event ) override; void onPlotDragged( wxAuiNotebookEvent& event ) override; diff --git a/eeschema/sim/simulator_panel_base.cpp b/eeschema/sim/simulator_panel_base.cpp index 908e024b30..cd6ad26b30 100644 --- a/eeschema/sim/simulator_panel_base.cpp +++ b/eeschema/sim/simulator_panel_base.cpp @@ -280,6 +280,7 @@ SIMULATOR_PANEL_BASE::SIMULATOR_PANEL_BASE( wxWindow* parent, wxWindowID id, con // Connect Events m_plotNotebook->Connect( wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, wxAuiNotebookEventHandler( SIMULATOR_PANEL_BASE::onPlotDragged ), NULL, this ); m_plotNotebook->Connect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, wxAuiNotebookEventHandler( SIMULATOR_PANEL_BASE::onPlotChanged ), NULL, this ); + m_plotNotebook->Connect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, wxAuiNotebookEventHandler( SIMULATOR_PANEL_BASE::onPlotChanging ), NULL, this ); m_plotNotebook->Connect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, wxAuiNotebookEventHandler( SIMULATOR_PANEL_BASE::onPlotClose ), NULL, this ); m_plotNotebook->Connect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, wxAuiNotebookEventHandler( SIMULATOR_PANEL_BASE::onPlotClosed ), NULL, this ); m_filter->Connect( wxEVT_MOTION, wxMouseEventHandler( SIMULATOR_PANEL_BASE::OnFilterMouseMoved ), NULL, this ); @@ -294,6 +295,7 @@ SIMULATOR_PANEL_BASE::~SIMULATOR_PANEL_BASE() // Disconnect Events m_plotNotebook->Disconnect( wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, wxAuiNotebookEventHandler( SIMULATOR_PANEL_BASE::onPlotDragged ), NULL, this ); m_plotNotebook->Disconnect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, wxAuiNotebookEventHandler( SIMULATOR_PANEL_BASE::onPlotChanged ), NULL, this ); + m_plotNotebook->Disconnect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, wxAuiNotebookEventHandler( SIMULATOR_PANEL_BASE::onPlotChanging ), NULL, this ); m_plotNotebook->Disconnect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, wxAuiNotebookEventHandler( SIMULATOR_PANEL_BASE::onPlotClose ), NULL, this ); m_plotNotebook->Disconnect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, wxAuiNotebookEventHandler( SIMULATOR_PANEL_BASE::onPlotClosed ), NULL, this ); m_filter->Disconnect( wxEVT_MOTION, wxMouseEventHandler( SIMULATOR_PANEL_BASE::OnFilterMouseMoved ), NULL, this ); diff --git a/eeschema/sim/simulator_panel_base.fbp b/eeschema/sim/simulator_panel_base.fbp index 76bbf5c639..1f954d0883 100644 --- a/eeschema/sim/simulator_panel_base.fbp +++ b/eeschema/sim/simulator_panel_base.fbp @@ -118,8 +118,8 @@ wxBORDER_NONE - - + + 1 1 1 @@ -170,16 +170,16 @@ wxTAB_TRAVERSAL - + -1,-1 m_sizer11 wxVERTICAL protected - + 5 wxEXPAND 1 - + 1 1 1 @@ -236,8 +236,8 @@ - - + + 1 1 1 @@ -288,7 +288,7 @@ wxTAB_TRAVERSAL - + m_sizerPlot wxHORIZONTAL @@ -353,6 +353,7 @@ onPlotDragged onPlotChanged + onPlotChanging onPlotClose onPlotClosed diff --git a/eeschema/sim/simulator_panel_base.h b/eeschema/sim/simulator_panel_base.h index dad1021adf..f0ddc5e6a1 100644 --- a/eeschema/sim/simulator_panel_base.h +++ b/eeschema/sim/simulator_panel_base.h @@ -67,6 +67,7 @@ class SIMULATOR_PANEL_BASE : public wxPanel // Virtual event handlers, override them in your derived class virtual void onPlotDragged( wxAuiNotebookEvent& event ) { event.Skip(); } virtual void onPlotChanged( wxAuiNotebookEvent& event ) { event.Skip(); } + virtual void onPlotChanging( wxAuiNotebookEvent& event ) { event.Skip(); } virtual void onPlotClose( wxAuiNotebookEvent& event ) { event.Skip(); } virtual void onPlotClosed( wxAuiNotebookEvent& event ) { event.Skip(); } virtual void OnFilterMouseMoved( wxMouseEvent& event ) { event.Skip(); } diff --git a/eeschema/sim/spice_simulator.cpp b/eeschema/sim/spice_simulator.cpp index d064b2b3f5..d159caae73 100644 --- a/eeschema/sim/spice_simulator.cpp +++ b/eeschema/sim/spice_simulator.cpp @@ -54,18 +54,19 @@ wxString SPICE_SIMULATOR::TypeToName( SIM_TYPE aType, bool aShortName ) { switch( aType ) { - case ST_OP: return aShortName ? wxString( wxT( "OP" ) ) : _( "Operating Point" ); - case ST_AC: return aShortName ? wxString( wxT( "AC" ) ) : _( "AC" ); - case ST_DC: return aShortName ? wxString( wxT( "DC" ) ) : _( "DC Sweep" ); - case ST_TRANSIENT: return aShortName ? wxString( wxT( "TRAN" ) ) : _( "Transient" ); - case ST_DISTORTION: return aShortName ? wxString( wxT( "DISTO" ) ) : _( "Distortion" ); - case ST_NOISE: return aShortName ? wxString( wxT( "NOISE" ) ) : _( "Noise" ); - case ST_POLE_ZERO: return aShortName ? wxString( wxT( "PZ" ) ) : _( "Pole-zero" ); - case ST_SENSITIVITY: return aShortName ? wxString( wxT( "SENS" ) ) : _( "Sensitivity" ); - case ST_TRANS_FUNC: return aShortName ? wxString( wxT( "TF" ) ) : _( "Transfer function" ); - case ST_S_PARAM: return aShortName ? wxString( wxT( "SP" ) ) : _( "S-Parameters" ); + case ST_OP: return aShortName ? wxString( wxT( "OP" ) ) : _( "DC Operating Point" ); + case ST_AC: return aShortName ? wxString( wxT( "AC" ) ) : _( "Small-Signal Analysis" ); + case ST_DC: return aShortName ? wxString( wxT( "DC" ) ) : _( "DC Sweep Analysis" ); + case ST_TRAN: return aShortName ? wxString( wxT( "TRAN" ) ) : _( "Transient Analysis" ); + case ST_DISTO: return aShortName ? wxString( wxT( "DISTO" ) ) : _( "Small-Signal Distortion Analysis" ); + case ST_NOISE: return aShortName ? wxString( wxT( "NOISE" ) ) : _( "Noise Analysis" ); + case ST_PZ: return aShortName ? wxString( wxT( "PZ" ) ) : _( "Pole-Zero Analysis" ); + case ST_SENS: return aShortName ? wxString( wxT( "SENS" ) ) : _( "Sensitivity Analysis" ); + case ST_TF: return aShortName ? wxString( wxT( "TF" ) ) : _( "Transfer Function Analysis" ); + case ST_SP: return aShortName ? wxString( wxT( "SP" ) ) : _( "S-Parameter Analysis" ); + case ST_FFT: return aShortName ? wxString( wxT( "FFT" ) ) : _( "Frequency Content Analysis" ); default: - case ST_UNKNOWN: return aShortName ? wxString( wxT( "??" ) ) : _( "Unknown" ); + case ST_UNKNOWN: return aShortName ? wxString( wxT( "??" ) ) : _( "Unknown" ); } } diff --git a/eeschema/sim/toolbars_simulator_frame.cpp b/eeschema/sim/toolbars_simulator_frame.cpp index 19087d53ae..187120d3b0 100644 --- a/eeschema/sim/toolbars_simulator_frame.cpp +++ b/eeschema/sim/toolbars_simulator_frame.cpp @@ -49,6 +49,7 @@ void SIMULATOR_FRAME::ReCreateHToolbar() m_toolBar->Add( EE_ACTIONS::saveWorkbook ); m_toolBar->AddScaledSeparator( this ); + m_toolBar->Add( EE_ACTIONS::newPlot ); m_toolBar->Add( EE_ACTIONS::simCommand ); m_toolBar->AddScaledSeparator( this ); @@ -134,6 +135,7 @@ void SIMULATOR_FRAME::doReCreateMenuBar() simulationMenu->Add( EE_ACTIONS::simTune ); simulationMenu->AppendSeparator(); + simulationMenu->Add( EE_ACTIONS::editUserDefinedSignals ); simulationMenu->Add( EE_ACTIONS::showNetlist ); diff --git a/eeschema/sim/user_defined_signals_help_md.h b/eeschema/sim/user_defined_signals_help_md.h index 1d47c428b6..89f71de85b 100644 --- a/eeschema/sim/user_defined_signals_help_md.h +++ b/eeschema/sim/user_defined_signals_help_md.h @@ -1,5 +1,7 @@ // Do not edit this file, it is autogenerated by CMake from the .md file -_HKI( " sqrt(x)\n" +_HKI( "SPICE functions:\n" +"\n" +" sqrt(x)\n" " sin(x)\n" " cos(x)\n" " tan(x)\n" diff --git a/eeschema/tools/ee_actions.cpp b/eeschema/tools/ee_actions.cpp index 1eb32b3e5e..a10e34e65d 100644 --- a/eeschema/tools/ee_actions.cpp +++ b/eeschema/tools/ee_actions.cpp @@ -1121,7 +1121,7 @@ TOOL_ACTION EE_ACTIONS::newPlot( "eeschema.Simulation.newPlot", AS_GLOBAL, MD_CTRL + 'N', LEGACY_HK_NAME( "New" ), _( "New Plot" ), "", - BITMAPS::new_generic ); + BITMAPS::sim_add_plot ); TOOL_ACTION EE_ACTIONS::openWorkbook( "eeschema.Simulation.openWorkbook", AS_GLOBAL, @@ -1201,12 +1201,6 @@ TOOL_ACTION EE_ACTIONS::editUserDefinedSignals( "eeschema.Simulation.editUserDef _( "Add, edit or delete user-defined simulation signals" ), BITMAPS::sim_add_signal ); -TOOL_ACTION EE_ACTIONS::showFFT( "eeschema.Simulation.showFFT", - AS_GLOBAL, 0, "", - _( "Show FFT" ), - _( "Show frequency distribution of transient analysis data using fast Fourier transform" ), - BITMAPS::mw_add_shape ); - TOOL_ACTION EE_ACTIONS::showNetlist( "eeschema.Simulation.showNetlist", AS_GLOBAL, 0, "", _( "Show SPICE Netlist" ), "", diff --git a/eeschema/tools/ee_actions.h b/eeschema/tools/ee_actions.h index ac689538cc..67a2fa06ed 100644 --- a/eeschema/tools/ee_actions.h +++ b/eeschema/tools/ee_actions.h @@ -277,7 +277,6 @@ public: static TOOL_ACTION runSimulation; static TOOL_ACTION stopSimulation; static TOOL_ACTION editUserDefinedSignals; - static TOOL_ACTION showFFT; static TOOL_ACTION showNetlist; // Net highlighting diff --git a/eeschema/tools/simulator_control.cpp b/eeschema/tools/simulator_control.cpp index 47e12d8bfc..91058b0ac6 100644 --- a/eeschema/tools/simulator_control.cpp +++ b/eeschema/tools/simulator_control.cpp @@ -62,14 +62,23 @@ void SIMULATOR_CONTROL::Reset( RESET_REASON aReason ) int SIMULATOR_CONTROL::NewPlot( const TOOL_EVENT& aEvent ) { - SIM_TYPE type = m_circuitModel->GetSimType(); + DIALOG_SIM_COMMAND dlg( m_simulatorFrame, m_circuitModel, m_simulator->Settings() ); + wxString errors; + WX_STRING_REPORTER reporter( &errors ); - if( SIM_PLOT_PANEL_BASE::IsPlottable( type ) ) + if( !m_circuitModel->ReadSchematicAndLibraries( NETLIST_EXPORTER_SPICE::OPTION_DEFAULT_FLAGS, + reporter ) ) { - m_simulatorFrame->NewPlotPanel( m_circuitModel->GetSimCommand(), - m_circuitModel->GetSimOptions() ); + DisplayErrorMessage( m_simulatorFrame, + _( "Errors during netlist generation.\n\n" ) + errors ); } + dlg.SetSimCommand( wxS( "*" ) ); + dlg.SetSimOptions( NETLIST_EXPORTER_SPICE::OPTION_DEFAULT_FLAGS ); + + if( dlg.ShowModal() == wxID_OK ) + m_simulatorFrame->NewPlotPanel( dlg.GetSimCommand(), dlg.GetSimOptions() ); + return 0; } @@ -145,71 +154,77 @@ int SIMULATOR_CONTROL::SaveWorkbook( const TOOL_EVENT& aEvent ) int SIMULATOR_CONTROL::ExportPlotAsPNG( const TOOL_EVENT& aEvent ) { - if( !m_simulatorFrame->GetCurrentPlot() ) - return -1; + if( SIM_PLOT_PANEL* plotPanel = GetCurrentPlotPanel() ) + { + wxFileDialog saveDlg( m_simulatorFrame, _( "Save Plot as Image" ), "", "", + PngFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); - wxFileDialog saveDlg( m_simulatorFrame, _( "Save Plot as Image" ), "", "", PngFileWildcard(), - wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); + if( saveDlg.ShowModal() == wxID_CANCEL ) + return -1; - if( saveDlg.ShowModal() == wxID_CANCEL ) - return -1; - - m_simulatorFrame->GetCurrentPlot()->GetPlotWin()->SaveScreenshot( saveDlg.GetPath(), - wxBITMAP_TYPE_PNG ); + plotPanel->GetPlotWin()->SaveScreenshot( saveDlg.GetPath(), wxBITMAP_TYPE_PNG ); + } return 0; } +SIM_PLOT_PANEL* SIMULATOR_CONTROL::GetCurrentPlotPanel() +{ + return dynamic_cast( m_simulatorFrame->GetCurrentPlotPanel() ); +} + + int SIMULATOR_CONTROL::ExportPlotAsCSV( const TOOL_EVENT& aEvent ) { - if( !m_simulatorFrame->GetCurrentPlot() ) - return -1; - - const wxChar SEPARATOR = ';'; - - wxFileDialog saveDlg( m_simulatorFrame, _( "Save Plot Data" ), "", "", CsvFileWildcard(), - wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); - - if( saveDlg.ShowModal() == wxID_CANCEL ) - return -1; - - wxFFile out( saveDlg.GetPath(), "wb" ); - - std::map traces = m_simulatorFrame->GetCurrentPlot()->GetTraces(); - - if( traces.size() == 0 ) - return -1; - - SIM_TYPE simType = m_circuitModel->GetSimType(); - - std::size_t rowCount = traces.begin()->second->GetDataX().size(); - - // write column header names on the first row - wxString xAxisName( m_simulator->GetXAxis( simType ) ); - out.Write( wxString::Format( wxT( "%s%c" ), xAxisName, SEPARATOR ) ); - - for( const auto& [name, trace] : traces ) - out.Write( wxString::Format( wxT( "%s%c" ), name, SEPARATOR ) ); - - out.Write( wxS( "\r\n" ) ); - - // write each row's numerical value - for ( std::size_t curRow=0; curRow < rowCount; curRow++ ) + if( SIM_PLOT_PANEL* plotPanel = GetCurrentPlotPanel() ) { - double xAxisValue = traces.begin()->second->GetDataX().at( curRow ); - out.Write( wxString::Format( wxT( "%g%c" ), xAxisValue, SEPARATOR ) ); + const wxChar SEPARATOR = ';'; + + wxFileDialog saveDlg( m_simulatorFrame, _( "Save Plot Data" ), "", "", CsvFileWildcard(), + wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); + + if( saveDlg.ShowModal() == wxID_CANCEL ) + return -1; + + wxFFile out( saveDlg.GetPath(), "wb" ); + + std::map traces = plotPanel->GetTraces(); + + if( traces.size() == 0 ) + return -1; + + SIM_TYPE simType = plotPanel->GetSimType(); + + std::size_t rowCount = traces.begin()->second->GetDataX().size(); + + // write column header names on the first row + wxString xAxisName( m_simulator->GetXAxis( simType ) ); + out.Write( wxString::Format( wxT( "%s%c" ), xAxisName, SEPARATOR ) ); for( const auto& [name, trace] : traces ) - { - double yAxisValue = trace->GetDataY().at( curRow ); - out.Write( wxString::Format( wxT( "%g%c" ), yAxisValue, SEPARATOR ) ); - } + out.Write( wxString::Format( wxT( "%s%c" ), name, SEPARATOR ) ); out.Write( wxS( "\r\n" ) ); + + // write each row's numerical value + for ( std::size_t curRow=0; curRow < rowCount; curRow++ ) + { + double xAxisValue = traces.begin()->second->GetDataX().at( curRow ); + out.Write( wxString::Format( wxT( "%g%c" ), xAxisValue, SEPARATOR ) ); + + for( const auto& [name, trace] : traces ) + { + double yAxisValue = trace->GetDataY().at( curRow ); + out.Write( wxString::Format( wxT( "%g%c" ), yAxisValue, SEPARATOR ) ); + } + + out.Write( wxS( "\r\n" ) ); + } + + out.Close(); } - out.Close(); return 0; } @@ -223,14 +238,11 @@ int SIMULATOR_CONTROL::Close( const TOOL_EVENT& aEvent ) int SIMULATOR_CONTROL::Zoom( const TOOL_EVENT& aEvent ) { - if( m_simulatorFrame->GetCurrentPlot() ) + if( SIM_PLOT_PANEL* plotPanel = GetCurrentPlotPanel() ) { - if( aEvent.IsAction( &ACTIONS::zoomInCenter ) ) - m_simulatorFrame->GetCurrentPlot()->GetPlotWin()->ZoomIn(); - else if( aEvent.IsAction( &ACTIONS::zoomOutCenter ) ) - m_simulatorFrame->GetCurrentPlot()->GetPlotWin()->ZoomOut(); - else if( aEvent.IsAction( &ACTIONS::zoomFitScreen ) ) - m_simulatorFrame->GetCurrentPlot()->GetPlotWin()->Fit(); + if( aEvent.IsAction( &ACTIONS::zoomInCenter ) ) plotPanel->GetPlotWin()->ZoomIn(); + else if( aEvent.IsAction( &ACTIONS::zoomOutCenter ) ) plotPanel->GetPlotWin()->ZoomOut(); + else if( aEvent.IsAction( &ACTIONS::zoomFitScreen ) ) plotPanel->GetPlotWin()->Fit(); } return 0; @@ -239,11 +251,9 @@ int SIMULATOR_CONTROL::Zoom( const TOOL_EVENT& aEvent ) int SIMULATOR_CONTROL::ToggleGrid( const TOOL_EVENT& aEvent ) { - SIM_PLOT_PANEL* plot = m_simulatorFrame->GetCurrentPlot(); - - if( plot ) + if( SIM_PLOT_PANEL* plotPanel = GetCurrentPlotPanel() ) { - plot->ShowGrid( !plot->IsGridShown() ); + plotPanel->ShowGrid( !plotPanel->IsGridShown() ); m_simulatorFrame->OnModify(); } @@ -253,11 +263,9 @@ int SIMULATOR_CONTROL::ToggleGrid( const TOOL_EVENT& aEvent ) int SIMULATOR_CONTROL::ToggleLegend( const TOOL_EVENT& aEvent ) { - SIM_PLOT_PANEL* plot = m_simulatorFrame->GetCurrentPlot(); - - if( plot ) + if( SIM_PLOT_PANEL* plotPanel = GetCurrentPlotPanel() ) { - plot->ShowLegend( !plot->IsLegendShown() ); + plotPanel->ShowLegend( !plotPanel->IsLegendShown() ); m_simulatorFrame->OnModify(); } @@ -267,11 +275,9 @@ int SIMULATOR_CONTROL::ToggleLegend( const TOOL_EVENT& aEvent ) int SIMULATOR_CONTROL::ToggleDottedSecondary( const TOOL_EVENT& aEvent ) { - SIM_PLOT_PANEL* plot = m_simulatorFrame->GetCurrentPlot(); - - if( plot ) + if( SIM_PLOT_PANEL* plotPanel = GetCurrentPlotPanel() ) { - plot->SetDottedSecondary( !plot->GetDottedSecondary() ); + plotPanel->SetDottedSecondary( !plotPanel->GetDottedSecondary() ); m_simulatorFrame->OnModify(); } @@ -296,9 +302,18 @@ int SIMULATOR_CONTROL::EditSimCommand( const TOOL_EVENT& aEvent ) int SIMULATOR_CONTROL::RunSimulation( const TOOL_EVENT& aEvent ) { if( m_simulator->IsRunning() ) + { m_simulator->Stop(); - else - m_simulatorFrame->StartSimulation(); + return 0; + } + + if( !GetCurrentPlotPanel() ) + NewPlot( aEvent ); + + if( !GetCurrentPlotPanel() ) + return 0; + + m_simulatorFrame->StartSimulation(); return 0; } @@ -444,8 +459,9 @@ int SIMULATOR_CONTROL::ShowNetlist( const TOOL_EVENT& aEvent ) STRING_FORMATTER formatter; NETLIST_VIEW_DIALOG dlg( m_simulatorFrame ); - m_circuitModel->SetSimOptions( m_simulatorFrame->GetCurrentOptions() ); - m_circuitModel->GetNetlist( &formatter, *dlg.GetReporter() ); + m_circuitModel->GetNetlist( m_simulatorFrame->GetCurrentSimCommand(), + m_simulatorFrame->GetCurrentOptions(), + &formatter, *dlg.GetReporter() ); dlg.SetNetlist( wxString( formatter.GetString() ) ); dlg.ShowModal(); diff --git a/eeschema/tools/simulator_control.h b/eeschema/tools/simulator_control.h index 9978229640..5de83e3feb 100644 --- a/eeschema/tools/simulator_control.h +++ b/eeschema/tools/simulator_control.h @@ -30,6 +30,7 @@ class SIMULATOR_FRAME; class NGSPICE_CIRCUIT_MODEL; class SPICE_SIMULATOR; +class SIM_PLOT_PANEL; /** @@ -84,6 +85,8 @@ private: */ wxString getDefaultPath(); + SIM_PLOT_PANEL* GetCurrentPlotPanel(); + ///< Set up handlers for various events. void setTransitions() override; diff --git a/include/bitmaps/bitmaps_list.h b/include/bitmaps/bitmaps_list.h index f40b1863aa..73a5c560d5 100644 --- a/include/bitmaps/bitmaps_list.h +++ b/include/bitmaps/bitmaps_list.h @@ -525,6 +525,7 @@ enum class BITMAPS : unsigned int show_zone_outline_only, show_zone_triangulation, showtrack, + sim_add_plot, sim_add_signal, sim_command, sim_probe, diff --git a/include/widgets/mathplot.h b/include/widgets/mathplot.h index 0bae6ef16c..2a64ed848e 100644 --- a/include/widgets/mathplot.h +++ b/include/widgets/mathplot.h @@ -1060,10 +1060,7 @@ class WXDLLIMPEXP_MATHPLOT mpWindow : public wxWindow { public: mpWindow(); - mpWindow( wxWindow* parent, wxWindowID id, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long flags = 0 ); + mpWindow( wxWindow* parent, wxWindowID id ); ~mpWindow(); /** Get reference to context menu of the plot canvas. diff --git a/qa/tests/spice/test_ngspice_helpers.cpp b/qa/tests/spice/test_ngspice_helpers.cpp index 342a2e963b..db24489cd5 100644 --- a/qa/tests/spice/test_ngspice_helpers.cpp +++ b/qa/tests/spice/test_ngspice_helpers.cpp @@ -83,8 +83,8 @@ BOOST_AUTO_TEST_CASE( CommandToSimType ) std::vector testData = { { ".op", ST_OP }, { ".option TEMP=27", ST_UNKNOWN }, - { ".tran 0 1 0.1", ST_TRANSIENT }, - { ".tran 0 1 0.1 UIC", ST_TRANSIENT }, + { ".tran 0 1 0.1", ST_TRAN }, + { ".tran 0 1 0.1 UIC", ST_TRAN }, { ".ac dec 10 1 10K", ST_AC }, { ".ac dec 10 1K 100MEG", ST_AC }, { ".ac lin 100 1 100HZ", ST_AC }, @@ -93,18 +93,18 @@ BOOST_AUTO_TEST_CASE( CommandToSimType ) { ".dc VCE 0 10 .25 IB 0 10u 1u", ST_DC }, { ".dc RLoad 1k 2k 100", ST_DC }, { ".dc TEMP -15 75 5", ST_DC }, - { ".disto dec 10 1kHz 100MEG", ST_DISTORTION }, - { ".disto dec 10 1kHz 100MEG 0.9", ST_DISTORTION }, + { ".disto dec 10 1kHz 100MEG", ST_DISTO }, + { ".disto dec 10 1kHz 100MEG 0.9", ST_DISTO }, { ".noise v(5) VIN dec 10 1kHz 100MEG", ST_NOISE }, { ".noise v(5,3) V1 oct 8 1.0 1.0e6 1", ST_NOISE }, - { ".pz 1 0 3 0 cur pol", ST_POLE_ZERO }, - { ".pz 2 3 5 0 vol zer", ST_POLE_ZERO }, - { ".pz 4 1 4 1 cur pz", ST_POLE_ZERO }, - { ".SENS V(1,OUT)", ST_SENSITIVITY }, - { ".SENS V(OUT) AC DEC 10 100 100k", ST_SENSITIVITY }, - { ".SENS I(VTEST)", ST_SENSITIVITY }, - { ".tf v(5, 3) VIN", ST_TRANS_FUNC }, - { ".tf i(VLOAD) VIN", ST_TRANS_FUNC }, + { ".pz 1 0 3 0 cur pol", ST_PZ }, + { ".pz 2 3 5 0 vol zer", ST_PZ }, + { ".pz 4 1 4 1 cur pz", ST_PZ }, + { ".SENS V(1,OUT)", ST_SENS }, + { ".SENS V(OUT) AC DEC 10 100 100k", ST_SENS }, + { ".SENS I(VTEST)", ST_SENS }, + { ".tf v(5, 3) VIN", ST_TF }, + { ".tf i(VLOAD) VIN", ST_TF }, }; for( auto& step : testData ) diff --git a/resources/bitmaps_png/CMakeLists.txt b/resources/bitmaps_png/CMakeLists.txt index c10191ba1f..cafb926077 100644 --- a/resources/bitmaps_png/CMakeLists.txt +++ b/resources/bitmaps_png/CMakeLists.txt @@ -458,6 +458,7 @@ set( BMAPS_MID shape_3d_back sheetset simulator + sim_add_plot sim_command sim_run sim_stop diff --git a/resources/bitmaps_png/png/sim_add_plot_24.png b/resources/bitmaps_png/png/sim_add_plot_24.png new file mode 100644 index 0000000000000000000000000000000000000000..b964484f40cc8c2e9884d6fcab465afc4b6cb7b7 GIT binary patch literal 1141 zcmV-*1d98KP)T3QeY1h9UD7qjx*@ApHi z)q?giOER*(TN32KbL3z)o3U|p2|<)}_T%&q2XJ%%I1Po)5N&4U>g1qMZ-)3_G=uZXDBQ?U(W+a(<^vVe+%9HK@=O!&CNtW zmG-Diz>-6y$P;?m62i_7BUE3zaNxqA?0AvsPrx)PE)C=TpM6CMd_EuY)pbE8U~EAu zMcQ!ab34l0zQJ#|WBkNZ(ahS(dM9w?ixECo_qcK5>L~6t>g($%g6Z`HS*mkqD9J&O zo#{k;N#x1AGBVGdUjNF8cdm```KLcQ;59iR#ut&94kFD=Os26MnunCj@zQ0OOELjz zMjud@F^D}Mo1tksDNCWdKEdZ@=dIBH;YVV`i%j4zcy;Gs+b^y(wx>`DD0}xa>~8NvRjnE&9Rhys=|yZ{2txU5GVnk}9V|yR z^6x)O4`cSnUtl&EiQqn2qE;r+?sH~d9aN??t}=N@rv9lo>bi_v4&m8XWiYZkHYbwN z7zdU~o;rlE%|Qg}0zu$-6y{uRt ztUQ6$YE`s| z$w&rC&u#8xK3Io2(;$<^!7aHE=LC0$oNH^=5!jBO<$L2c*QneoSQLE}g~?ty&49%00000NkvXX Hu0mjfuOuW) literal 0 HcmV?d00001 diff --git a/resources/bitmaps_png/sources/light/sim_add_plot.svg b/resources/bitmaps_png/sources/light/sim_add_plot.svg new file mode 100644 index 0000000000..1d30627069 --- /dev/null +++ b/resources/bitmaps_png/sources/light/sim_add_plot.svg @@ -0,0 +1,148 @@ + + + + + + + + + + image/svg+xml + + simulator + + + + + + + + + + + + + + + simulator + + + + + + + + + + + +