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.
This commit is contained in:
Jeff Young 2023-07-05 18:25:52 +01:00
parent d5d2800b03
commit bde9c2cbc5
41 changed files with 3057 additions and 2528 deletions

View File

@ -481,6 +481,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& 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" ) );

View File

@ -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;

View File

@ -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 <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
@ -26,6 +26,7 @@
#include "dialog_sim_command.h"
#include <sim/ngspice_circuit_model.h>
#include <sim/ngspice.h>
#include <sim/simulator_frame.h>
#include <confirm.h>
@ -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<NGSPICE_CIRCUIT_MODEL> aCircuitModel,
std::shared_ptr<SPICE_SIMULATOR_SETTINGS>& 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<NGSPICE_SIMULATOR_SETTINGS*>( 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;
@ -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 );
}

View File

@ -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<NGSPICE_CIRCUIT_MODEL> aCircuitModel,
DIALOG_SIM_COMMAND( SIMULATOR_FRAME* aParent, std::shared_ptr<NGSPICE_CIRCUIT_MODEL> aCircuitModel,
std::shared_ptr<SPICE_SIMULATOR_SETTINGS>& 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<NGSPICE_CIRCUIT_MODEL> m_circuitModel;
std::shared_ptr<SPICE_SIMULATOR_SETTINGS> m_settings;
SPICE_VALIDATOR m_spiceValidator;
SPICE_VALIDATOR m_spiceEmptyValidator;
wxIntegerValidator<int> m_posIntValidator;
std::set<wxString> m_fftInputSignals;
};
#endif /* DIALOG_SIM_COMMAND_H */

View File

@ -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 );
}

File diff suppressed because it is too large Load Diff

View File

@ -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 <wx/intl.h>
#include "dialog_shim.h"
#include <wx/string.h>
#include <wx/radiobox.h>
#include <wx/stattext.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/stattext.h>
#include <wx/choice.h>
#include <wx/sizer.h>
#include <wx/radiobox.h>
#include <wx/textctrl.h>
#include <wx/valtext.h>
#include <wx/sizer.h>
#include <wx/panel.h>
#include <wx/checkbox.h>
#include <wx/gbsizer.h>
#include <wx/button.h>
#include <wx/bitmap.h>
#include <wx/image.h>
#include <wx/icon.h>
#include <wx/checkbox.h>
#include <wx/choice.h>
#include <wx/gbsizer.h>
#include <wx/button.h>
#include <wx/notebook.h>
#include <wx/srchctrl.h>
#include <wx/checklst.h>
#include <wx/simplebook.h>
#include <wx/dialog.h>
///////////////////////////////////////////////////////////////////////////
@ -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(); }

View File

@ -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();

View File

@ -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)" ) );

View File

@ -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() );
}
}

View File

@ -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;

View File

@ -251,23 +251,21 @@ std::vector<double> NGSPICE::GetPhaseVector( const std::string& aName, int aMaxL
}
bool NGSPICE::Attach( const std::shared_ptr<SIMULATION_MODEL>& aModel, REPORTER& aReporter )
bool NGSPICE::Attach( const std::shared_ptr<SIMULATION_MODEL>& aModel, const wxString& aSimCommand,
unsigned aSimOptions, REPORTER& aReporter )
{
NGSPICE_CIRCUIT_MODEL* model = dynamic_cast<NGSPICE_CIRCUIT_MODEL*>( aModel.get() );
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:

View File

@ -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<SIMULATION_MODEL>& aModel,
REPORTER& aReporter ) override final;
bool Attach( const std::shared_ptr<SIMULATION_MODEL>& aModel, const wxString& aSimCommand,
unsigned aSimOptions, REPORTER& aReporter ) override final;
///< Load a netlist for the simulation
bool LoadNetlist( const std::string& aNetlist ) override final;

View File

@ -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 ) );
}

View File

@ -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 */

View File

@ -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<mpScaleXLog>( 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<mpScaleXLog>( wxEmptyString, wxT( "Hz" ), mpALIGN_BOTTOM );
m_axis_x->SetNameAlign( mpALIGN_BOTTOM );
m_plotWin->AddLayer( m_axis_x );
m_axis_y1 = new LIN_SCALE<mpScaleY>( 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<double> tmp( aY, aY + aPoints );
std::vector<double> x( aX, aX + aPoints );
std::vector<double> 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<double>( 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 );

View File

@ -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 )
{
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<std::pair<wxString, wxString>>& 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<std::pair<wxString, wxString>> m_measurements;
};
wxDECLARE_EVENT( EVT_SIM_CURSOR_UPDATE, wxCommandEvent );

View File

@ -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 );

View File

@ -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 <sim/sim_types.h>
#include <sim/ngspice_circuit_model.h>
#include <wx/panel.h>
#include <wx/sizer.h>
#include <wx/stattext.h>
@ -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();

View File

@ -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

View File

@ -58,7 +58,8 @@ public:
*
* @return True in case of success, false otherwise.
*/
virtual bool Attach( const std::shared_ptr<SIMULATION_MODEL>& aModel, REPORTER& aReporter )
virtual bool Attach( const std::shared_ptr<SIMULATION_MODEL>& aModel,
const wxString& aSimCommand, unsigned aSimOptions, REPORTER& aReporter )
{
m_simModel = aModel;
return true;

View File

@ -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 )
{
if( !EditSimCommand() )
SIM_PLOT_PANEL_BASE* plotPanel = m_panel->GetCurrentPlotPanel();
if( !plotPanel )
return;
if( m_circuitModel->CommandToSimType( GetCurrentSimCommand() ) == ST_UNKNOWN )
return;
}
wxString schTextSimCommand = m_circuitModel->GetSchTextSimCommand();
SIM_TYPE schTextSimType = NGSPICE_CIRCUIT_MODEL::CommandToSimType( schTextSimCommand );
SIM_PLOT_PANEL_BASE* plotWindow = m_panel->GetCurrentPlotWindow();
if( !plotWindow )
if( plotPanel->GetSimCommand().Upper().StartsWith( wxT( "FFT" ) ) )
{
NewPlotPanel( schTextSimCommand, m_circuitModel->GetSimOptions() );
OnModify();
wxString tranSpicePlot;
if( SIM_PLOT_PANEL_BASE* tranPlotPanel = m_panel->GetPlotPanel( ST_TRAN ) )
tranSpicePlot = tranPlotPanel->GetSpicePlotName();
if( tranSpicePlot.IsEmpty() )
{
DisplayErrorMessage( this, _( "You must run a TRAN simulation first; its results"
"will be used for the fast Fourier transform." ) );
}
else
{
m_circuitModel->SetSimCommandOverride( plotWindow->GetSimCommand() );
m_simulator->Command( "setplot " + tranSpicePlot.ToStdString() );
if( plotWindow->GetSimType() == schTextSimType
&& schTextSimCommand != m_circuitModel->GetLastSchTextSimCommand() )
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
{
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<std::mutex> 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<wxString> SIMULATOR_FRAME::SimPlotVectors()
{
return m_panel->SimPlotVectors();
}
const std::vector<wxString> 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<SIM_PLOT_PANEL*>( 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<SIM_PLOT_PANEL*>( 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<SIM_PLOT_PANEL*>( 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<SIM_PLOT_PANEL*>( 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,14 +742,6 @@ void SIMULATOR_FRAME::onSimUpdate( wxCommandEvent& aEvent )
if( m_simulator->IsRunning() )
m_simulator->Stop();
if( m_panel->GetCurrentPlotWindow() != m_lastSimPlot )
{
// We need to rerun simulation, as the simulator currently stores results for another
// plot
StartSimulation();
}
else
{
std::unique_lock<std::mutex> simulatorLock( m_simulator->GetMutex(), std::try_to_lock );
if( simulatorLock.owns_lock() )
@ -782,7 +753,6 @@ void SIMULATOR_FRAME::onSimUpdate( wxCommandEvent& aEvent )
{
DisplayErrorMessage( this, _( "Another simulation is already running." ) );
}
}
updateInProgress = false;
}

View File

@ -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<wxString> SimPlotVectors();
/**
* @return the list of schematic signals + any user defined signals.
*/
const std::vector<wxString> 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<NGSPICE_CIRCUIT_MODEL> m_circuitModel;
SIM_PLOT_PANEL_BASE* m_lastSimPlot;
bool m_simFinished;
bool m_workbookModified;
};

View File

@ -37,13 +37,12 @@
#include <eda_pattern_match.h>
#include <string_utils.h>
#include <pgm_base.h>
#include "ngspice.h"
#include "simulator_panel.h"
#include <sim/simulator_panel.h>
#include <sim/simulator_frame.h>
#include <sim/sim_plot_panel.h>
#include <sim/spice_simulator.h>
#include "fmt/format.h"
#include "dialogs/dialog_text_entry.h"
#include <dialogs/dialog_text_entry.h>
#include <dialogs/dialog_sim_format_value.h>
#include <eeschema_settings.h>
@ -135,8 +134,11 @@ 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 );
if( SIM_PLOT_PANEL_BASE* panel = m_parent->GetCurrentPlotPanel() )
{
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" ) );
@ -146,9 +148,7 @@ void SIGNALS_GRID_TRICKS::showPopupMenu( wxMenu& menu, wxGridEvent& aEvent )
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( panel->GetSimType() == ST_TRAN )
{
menu.AppendSeparator();
menu.Append( MYID_FOURIER, _( "Perform Fourier Analysis..." ) );
@ -156,6 +156,8 @@ void SIGNALS_GRID_TRICKS::showPopupMenu( wxMenu& menu, wxGridEvent& aEvent )
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();
EDA_COMBINED_MATCHER matcher( aFilter.Upper(), CTX_SIGNAL );
SIM_PLOT_PANEL* plotPanel = dynamic_cast<SIM_PLOT_PANEL*>( GetCurrentPlotPanel() );
std::vector<wxString> 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<std::string> 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<wxString, int> 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<SIM_PLOT_PANEL*>( 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<SIM_PLOT_PANEL*>( 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<SIM_PLOT_PANEL*>( 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<SIM_PLOT_PANEL*>( 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<SIM_PLOT_PANEL*>( 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<SIM_PLOT_PANEL*>( 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<SIM_PLOT_PANEL*>( 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<int, wxString>& 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<int, wxString>& 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<int, wxString>& 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<SIM_PLOT_PANEL*>( 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<const SIM_PLOT_PANEL_BASE*>( 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 );
plotPanel = dynamic_cast<SIM_PLOT_PANEL_BASE*>( m_plotNotebook->GetPage( 0 ) );
plotPanel->SetLastSchTextSimCommand( file.GetNextLine() );
}
else
{
found = true;
}
}
}
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<const SIM_PLOT_PANEL_BASE*>( m_plotNotebook->GetPage( i ) );
auto* basePanel = dynamic_cast<SIM_PLOT_PANEL_BASE*>( 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<const SIM_PLOT_PANEL*>( basePanel );
SIM_PLOT_PANEL* plotPanel = dynamic_cast<SIM_PLOT_PANEL*>( 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<wxString> measurements;
std::vector<wxString> 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<SIM_PLOT_PANEL_BASE*>( 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();
@ -2218,9 +2231,10 @@ SIM_TRACE_TYPE SIMULATOR_PANEL::getXAxisType( SIM_TYPE aType ) const
{
/// @todo SPT_LOG_FREQUENCY
case ST_AC: return SPT_LIN_FREQUENCY;
case ST_S_PARAM: 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_TRANSIENT: return SPT_TIME;
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<SIM_PLOT_PANEL*>( GetCurrentPlotPanel() ) )
{
std::vector<std::pair<wxString, wxString>>& 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<SIM_PLOT_PANEL*>( 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<SIM_PLOT_PANEL*>( 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<SIM_PLOT_PANEL*>( GetCurrentPlotWindow() ) )
if( SIM_PLOT_PANEL* plotPanel = dynamic_cast<SIM_PLOT_PANEL*>( GetCurrentPlotPanel() ) )
plotPanel->ResetScales( true );
m_simConsole->Clear();
@ -2488,7 +2566,7 @@ void SIMULATOR_PANEL::OnSimReport( const wxString& aMsg )
}
std::vector<wxString> SIMULATOR_PANEL::Signals() const
std::vector<wxString> SIMULATOR_PANEL::SimPlotVectors() const
{
std::vector<wxString> signals;
@ -2499,20 +2577,32 @@ std::vector<wxString> SIMULATOR_PANEL::Signals() const
}
std::vector<wxString> SIMULATOR_PANEL::Signals() const
{
std::vector<wxString> 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<wxString> 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<SIM_PLOT_PANEL*>( plotPanelWindow );
SIM_PLOT_PANEL* plotPanel = dynamic_cast<SIM_PLOT_PANEL*>( 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 );
}

View File

@ -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<wxString> SimPlotVectors() const;
std::vector<wxString> 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<SIM_PLOT_PANEL_BASE*>( 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<SIM_PLOT_PANEL_BASE*>( m_plotNotebook->GetPage( ii ) );
if( candidate && candidate->GetSimType() == aType )
return candidate;
}
if( !plotWindow )
return nullptr;
return plotWindow->GetSimType() == ST_UNKNOWN ? nullptr
: dynamic_cast<SIM_PLOT_PANEL*>( plotWindow );
}
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;

View File

@ -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 );

View File

@ -118,8 +118,8 @@
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxBORDER_NONE</property>
<object class="splitteritem" expanded="0">
<object class="wxPanel" expanded="0">
<object class="splitteritem" expanded="1">
<object class="wxPanel" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -170,16 +170,16 @@
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property>
<object class="wxBoxSizer" expanded="0">
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size">-1,-1</property>
<property name="name">m_sizer11</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">protected</property>
<object class="sizeritem" expanded="0">
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxSplitterWindow" expanded="0">
<object class="wxSplitterWindow" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -236,8 +236,8 @@
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<object class="splitteritem" expanded="0">
<object class="wxPanel" expanded="0">
<object class="splitteritem" expanded="1">
<object class="wxPanel" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -288,7 +288,7 @@
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property>
<object class="wxBoxSizer" expanded="0">
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">m_sizerPlot</property>
<property name="orient">wxHORIZONTAL</property>
@ -353,6 +353,7 @@
<property name="window_style"></property>
<event name="OnAuiNotebookEndDrag">onPlotDragged</event>
<event name="OnAuiNotebookPageChanged">onPlotChanged</event>
<event name="OnAuiNotebookPageChanging">onPlotChanging</event>
<event name="OnAuiNotebookPageClose">onPlotClose</event>
<event name="OnAuiNotebookPageClosed">onPlotClosed</event>
</object>

View File

@ -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(); }

View File

@ -54,16 +54,17 @@ 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" );
}

View File

@ -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 );

View File

@ -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"

View File

@ -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" ), "",

View File

@ -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

View File

@ -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,27 +154,31 @@ int SIMULATOR_CONTROL::SaveWorkbook( const TOOL_EVENT& aEvent )
int SIMULATOR_CONTROL::ExportPlotAsPNG( const TOOL_EVENT& aEvent )
{
if( !m_simulatorFrame->GetCurrentPlot() )
return -1;
wxFileDialog saveDlg( m_simulatorFrame, _( "Save Plot as Image" ), "", "", PngFileWildcard(),
wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
if( SIM_PLOT_PANEL* plotPanel = GetCurrentPlotPanel() )
{
wxFileDialog saveDlg( m_simulatorFrame, _( "Save Plot as Image" ), "", "",
PngFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
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<SIM_PLOT_PANEL*>( m_simulatorFrame->GetCurrentPlotPanel() );
}
int SIMULATOR_CONTROL::ExportPlotAsCSV( const TOOL_EVENT& aEvent )
{
if( !m_simulatorFrame->GetCurrentPlot() )
return -1;
if( SIM_PLOT_PANEL* plotPanel = GetCurrentPlotPanel() )
{
const wxChar SEPARATOR = ';';
wxFileDialog saveDlg( m_simulatorFrame, _( "Save Plot Data" ), "", "", CsvFileWildcard(),
@ -176,12 +189,12 @@ int SIMULATOR_CONTROL::ExportPlotAsCSV( const TOOL_EVENT& aEvent )
wxFFile out( saveDlg.GetPath(), "wb" );
std::map<wxString, TRACE*> traces = m_simulatorFrame->GetCurrentPlot()->GetTraces();
std::map<wxString, TRACE*> traces = plotPanel->GetTraces();
if( traces.size() == 0 )
return -1;
SIM_TYPE simType = m_circuitModel->GetSimType();
SIM_TYPE simType = plotPanel->GetSimType();
std::size_t rowCount = traces.begin()->second->GetDataX().size();
@ -210,6 +223,8 @@ int SIMULATOR_CONTROL::ExportPlotAsCSV( const TOOL_EVENT& aEvent )
}
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,8 +302,17 @@ int SIMULATOR_CONTROL::EditSimCommand( const TOOL_EVENT& aEvent )
int SIMULATOR_CONTROL::RunSimulation( const TOOL_EVENT& aEvent )
{
if( m_simulator->IsRunning() )
{
m_simulator->Stop();
else
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();

View File

@ -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;

View File

@ -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,

View File

@ -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.

View File

@ -83,8 +83,8 @@ BOOST_AUTO_TEST_CASE( CommandToSimType )
std::vector<struct TEST_DATA> 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 )

View File

@ -458,6 +458,7 @@ set( BMAPS_MID
shape_3d_back
sheetset
simulator
sim_add_plot
sim_command
sim_run
sim_stop

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,148 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
id="Слой_1"
data-name="Слой 1"
viewBox="0 0 24 24"
version="1.1"
sodipodi:docname="sim_add_plot.svg"
inkscape:version="1.2.1 (9c6d41e, 2022-07-14)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1728"
inkscape:window-height="987"
id="namedview30"
showgrid="true"
inkscape:zoom="39.543586"
inkscape:cx="12.03735"
inkscape:cy="15.286929"
inkscape:window-x="0"
inkscape:window-y="38"
inkscape:window-maximized="0"
inkscape:document-rotation="0"
inkscape:current-layer="Слой_1"
inkscape:showpageshadow="2"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1">
<inkscape:grid
type="xygrid"
id="grid_kicad"
spacingx="0.5"
spacingy="0.5"
color="#9999ff"
opacity="0.13"
empspacing="2" />
</sodipodi:namedview>
<metadata
id="metadata43">
<rdf:RDF>
<cc:Work
rdf:about="">
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>simulator</dc:title>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<defs
id="defs159987">
<style
id="style159985">.cls-1{fill:#b9b9b9;}.cls-2,.cls-3{fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.25px;}.cls-2{stroke:#bf2641;}.cls-3{stroke:#1a81c4;}</style>
</defs>
<title
id="title159989">simulator</title>
<circle
style="fill:#ffffff;fill-opacity:1;stroke:#545454;stroke-width:1.37198;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path841"
cx="11.987356"
cy="11.987356"
r="10.289825" />
<path
style="fill:none;stroke:#545454;stroke-width:0.953986;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 2.251549,12.5 H 19.543938"
id="path843"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#545454;stroke-width:0.898072;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 5.5,16.008526 V 4.7248423"
id="path845"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#1a81c4;stroke-width:1.4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 3.5,14.5 c 0,0 1.3518787,-7 2.8518787,-7 1.5,0 1.6002744,8.070806 3.0698938,8.060622 C 11.421725,15.546763 10.617219,4.5 12.617219,4.5 c 2,0 1.314653,14.512198 2.814653,14.512198 1.201824,0 1.002258,-3.266618 1.988097,-4.624305 C 17.831854,13.820649 18.5,13 19,13"
id="path865"
sodipodi:nodetypes="cssssac" />
<ellipse
style="fill:none;fill-opacity:1;stroke:#545454;stroke-width:1.37119;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="circle851"
cx="12"
cy="12.012644"
rx="10.277575"
ry="10.290219" />
<g
id="g856"
style="display:inline"
transform="translate(-0.00609355,0.0252947)">
<circle
class="cls-5"
cx="16.800095"
cy="16.793707"
id="circle27864"
style="fill:#bf2641;stroke-width:0.971428"
r="6.8000002" />
<line
class="cls-6"
x1="17.094093"
y1="13.593705"
x2="17.094093"
y2="20.593706"
id="line27866"
style="fill:none;stroke:#f5f5f5;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none" />
<line
class="cls-6"
x1="20.594093"
y1="17.093706"
x2="13.594093"
y2="17.093706"
id="line27868"
style="fill:none;stroke:#f5f5f5;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none" />
</g>
<ellipse
style="fill:none;stroke:#ffffff;stroke-width:0.93712;stroke-dasharray:none;stroke-opacity:1"
id="path693"
cx="17.08"
cy="17.130001"
rx="6.8064399"
ry="6.8064404" />
</svg>

After

Width:  |  Height:  |  Size: 5.3 KiB