From 492ef62053c0caa926b2efd3cb1beeaef9ccb44c Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Tue, 4 Jul 2023 11:04:20 +0100 Subject: [PATCH] ADDED support to save contributions from all noise generators. You must first check the checkbox in the Simulation Command dialog, after which the signals will appear in the User Defined Signals autocomplete lists. --- eeschema/dialogs/dialog_sim_command.cpp | 80 ++++++++++---------- eeschema/dialogs/dialog_sim_command_base.cpp | 5 +- eeschema/dialogs/dialog_sim_command_base.fbp | 66 +++++++++++++++- eeschema/dialogs/dialog_sim_command_base.h | 1 + eeschema/eeschema_id.h | 15 +--- eeschema/sim/ngspice.cpp | 24 +++--- eeschema/sim/ngspice.h | 4 +- eeschema/sim/ngspice_circuit_model.cpp | 8 +- eeschema/sim/ngspice_circuit_model.h | 2 +- eeschema/sim/simulator_frame.cpp | 2 +- eeschema/sim/simulator_frame.h | 5 +- eeschema/sim/simulator_panel.cpp | 38 ++++++---- eeschema/sim/simulator_panel.h | 2 +- eeschema/sim/spice_simulator.h | 2 +- 14 files changed, 166 insertions(+), 88 deletions(-) diff --git a/eeschema/dialogs/dialog_sim_command.cpp b/eeschema/dialogs/dialog_sim_command.cpp index a68f38782c..7ef066d20d 100644 --- a/eeschema/dialogs/dialog_sim_command.cpp +++ b/eeschema/dialogs/dialog_sim_command.cpp @@ -123,6 +123,41 @@ DIALOG_SIM_COMMAND::DIALOG_SIM_COMMAND( wxWindow* aParent, SetupStandardButtons(); } +bool DIALOG_SIM_COMMAND::TransferDataToWindow() +{ + /// @todo one day it could interpret the sim command and fill out appropriate fields. + if( empty( m_customTxt ) ) + loadDirectives(); + + m_fixIncludePaths->SetValue( m_settings->GetFixIncludePaths() ); + + NGSPICE_SIMULATOR_SETTINGS* ngspiceSettings = + dynamic_cast( m_settings.get() ); + + if( ngspiceSettings ) + { + switch( ngspiceSettings->GetModelMode() ) + { + case NGSPICE_MODEL_MODE::USER_CONFIG: m_compatibilityModeChoice->SetSelection( 0 ); break; + case NGSPICE_MODEL_MODE::NGSPICE: m_compatibilityModeChoice->SetSelection( 1 ); break; + case NGSPICE_MODEL_MODE::PSPICE: m_compatibilityModeChoice->SetSelection( 2 ); break; + case NGSPICE_MODEL_MODE::LTSPICE: m_compatibilityModeChoice->SetSelection( 3 ); break; + case NGSPICE_MODEL_MODE::LT_PSPICE: m_compatibilityModeChoice->SetSelection( 4 ); break; + case NGSPICE_MODEL_MODE::HSPICE: m_compatibilityModeChoice->SetSelection( 5 ); break; + default: + wxFAIL_MSG( wxString::Format( "Unknown NGSPICE_MODEL_MODE %d.", + ngspiceSettings->GetModelMode() ) ); + break; + } + } + + if( m_simCommand.IsEmpty() && !empty( m_customTxt ) ) + parseCommand( m_customTxt->GetValue() ); + + return true; +} + + wxString DIALOG_SIM_COMMAND::evaluateDCControls( wxChoice* aDcSource, wxTextCtrl* aDcStart, wxTextCtrl* aDcStop, wxTextCtrl* aDcIncr ) { @@ -241,14 +276,15 @@ bool DIALOG_SIM_COMMAND::TransferDataFromWindow() if( !ref.IsEmpty() ) ref = wxS( "," ) + m_circuitModel->GetItemName( std::string( ref.ToUTF8() ) ); - m_simCommand.Printf( ".noise v(%s%s) %s %s %s %s %s", + m_simCommand.Printf( ".noise v(%s%s) %s %s %s %s %s %s", output, ref, noiseSource, scaleToString( m_noiseScale->GetSelection() ), m_noisePointsNumber->GetValue(), SPICE_VALUE( m_noiseFreqStart->GetValue() ).ToSpiceString(), - SPICE_VALUE( m_noiseFreqStop->GetValue() ).ToSpiceString() ); + SPICE_VALUE( m_noiseFreqStop->GetValue() ).ToSpiceString(), + m_saveAllNoise->GetValue() ? "1" : "" ); } else if( page == m_pgOP ) // DC operating point analysis { @@ -330,41 +366,6 @@ bool DIALOG_SIM_COMMAND::TransferDataFromWindow() } -bool DIALOG_SIM_COMMAND::TransferDataToWindow() -{ - /// @todo one day it could interpret the sim command and fill out appropriate fields. - if( empty( m_customTxt ) ) - loadDirectives(); - - m_fixIncludePaths->SetValue( m_settings->GetFixIncludePaths() ); - - NGSPICE_SIMULATOR_SETTINGS* ngspiceSettings = - dynamic_cast( m_settings.get() ); - - if( ngspiceSettings ) - { - switch( ngspiceSettings->GetModelMode() ) - { - case NGSPICE_MODEL_MODE::USER_CONFIG: m_compatibilityModeChoice->SetSelection( 0 ); break; - case NGSPICE_MODEL_MODE::NGSPICE: m_compatibilityModeChoice->SetSelection( 1 ); break; - case NGSPICE_MODEL_MODE::PSPICE: m_compatibilityModeChoice->SetSelection( 2 ); break; - case NGSPICE_MODEL_MODE::LTSPICE: m_compatibilityModeChoice->SetSelection( 3 ); break; - case NGSPICE_MODEL_MODE::LT_PSPICE: m_compatibilityModeChoice->SetSelection( 4 ); break; - case NGSPICE_MODEL_MODE::HSPICE: m_compatibilityModeChoice->SetSelection( 5 ); break; - default: - wxFAIL_MSG( wxString::Format( "Unknown NGSPICE_MODEL_MODE %d.", - ngspiceSettings->GetModelMode() ) ); - break; - } - } - - if( m_simCommand.IsEmpty() && !empty( m_customTxt ) ) - parseCommand( m_customTxt->GetValue() ); - - return true; -} - - void DIALOG_SIM_COMMAND::updateDCSources( wxChar aType, wxChoice* aSource ) { wxString prevSelection; @@ -485,9 +486,10 @@ void DIALOG_SIM_COMMAND::parseCommand( const wxString& aCommand ) SPICE_VALUE pts; SPICE_VALUE fStart; SPICE_VALUE fStop; + bool saveAll; m_circuitModel->ParseNoiseCommand( aCommand, &output, &ref, &source, &scale, &pts, - &fStart, &fStop ); + &fStart, &fStop, &saveAll ); m_noiseMeas->SetStringSelection( output ); m_noiseRef->SetStringSelection( ref ); @@ -505,6 +507,8 @@ void DIALOG_SIM_COMMAND::parseCommand( const wxString& aCommand ) m_noisePointsNumber->SetValue( pts.ToSpiceString() ); m_noiseFreqStart->SetValue( fStart.ToSpiceString() ); m_noiseFreqStop->SetValue( fStop.ToSpiceString() ); + + m_saveAllNoise->SetValue( saveAll ); } else if( token == ".tran" ) { diff --git a/eeschema/dialogs/dialog_sim_command_base.cpp b/eeschema/dialogs/dialog_sim_command_base.cpp index df5894c496..3b2f87b5d5 100644 --- a/eeschema/dialogs/dialog_sim_command_base.cpp +++ b/eeschema/dialogs/dialog_sim_command_base.cpp @@ -312,11 +312,14 @@ DIALOG_SIM_COMMAND_BASE::DIALOG_SIM_COMMAND_BASE( wxWindow* parent, wxWindowID i fgSizer11->Add( m_noiseFreqStopUnits, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - bSizer10->Add( fgSizer11, 0, wxALIGN_BOTTOM|wxTOP|wxBOTTOM|wxLEFT, 5 ); + bSizer10->Add( fgSizer11, 0, wxALIGN_BOTTOM|wxTOP|wxLEFT, 5 ); bSizer15->Add( bSizer10, 0, wxEXPAND|wxTOP, 5 ); + m_saveAllNoise = new wxCheckBox( m_pgNoise, wxID_ANY, _("Save contributions from all noise generators"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer15->Add( m_saveAllNoise, 0, wxALL, 10 ); + m_pgNoise->SetSizer( bSizer15 ); m_pgNoise->Layout(); diff --git a/eeschema/dialogs/dialog_sim_command_base.fbp b/eeschema/dialogs/dialog_sim_command_base.fbp index b143e9312b..00d2eb4fd5 100644 --- a/eeschema/dialogs/dialog_sim_command_base.fbp +++ b/eeschema/dialogs/dialog_sim_command_base.fbp @@ -3113,7 +3113,7 @@ 5 - wxALIGN_BOTTOM|wxTOP|wxBOTTOM|wxLEFT + wxALIGN_BOTTOM|wxTOP|wxLEFT 0 3 @@ -3638,6 +3638,70 @@ + + 10 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Save contributions from all noise generators + + 0 + + + 0 + + 1 + m_saveAllNoise + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + diff --git a/eeschema/dialogs/dialog_sim_command_base.h b/eeschema/dialogs/dialog_sim_command_base.h index 1e683cea1a..3c0be70970 100644 --- a/eeschema/dialogs/dialog_sim_command_base.h +++ b/eeschema/dialogs/dialog_sim_command_base.h @@ -97,6 +97,7 @@ class DIALOG_SIM_COMMAND_BASE : public DIALOG_SHIM wxStaticText* m_staticText31; wxTextCtrl* m_noiseFreqStop; wxStaticText* m_noiseFreqStopUnits; + wxCheckBox* m_saveAllNoise; wxPanel* m_pgOP; wxStaticText* m_staticText13; wxPanel* m_pgPoleZero; diff --git a/eeschema/eeschema_id.h b/eeschema/eeschema_id.h index 606fa590a6..6b40066848 100644 --- a/eeschema/eeschema_id.h +++ b/eeschema/eeschema_id.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2008 Wayne Stambaugh - * Copyright (C) 2008-2021 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 2008-2023 KiCad Developers, see change_log.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -28,14 +28,6 @@ #include -/** - * The maximum number of items in the clarify selection context menu. While in - * most cases it is highly unlikely that there would ever be more than 10 items - * at the current cursor, there are some exceptions (a bunch of pins created at - * once, for instance). The current setting of 200 is arbitrary. - */ -#define MAX_SELECT_ITEM_IDS 200 - /** * The maximum number of units per package. * While counts approaching 100 start to make the unit-selection popup menu @@ -75,11 +67,6 @@ enum id_eeschema_frm ID_LIBVIEW_SYM_FILTER, ID_LIBVIEW_SYM_LIST, - ID_SIM_RUN, - ID_SIM_TUNE, - ID_SIM_PROBE, - ID_SIM_ADD_SIGNALS, - ID_END_EESCHEMA_ID_LIST, // End of IDs specific to Eeschema // These ID are used in context menus, diff --git a/eeschema/sim/ngspice.cpp b/eeschema/sim/ngspice.cpp index 918df09b82..ef1081956b 100644 --- a/eeschema/sim/ngspice.cpp +++ b/eeschema/sim/ngspice.cpp @@ -84,25 +84,25 @@ void NGSPICE::Init( const SPICE_SIMULATOR_SETTINGS* aSettings ) } -std::vector NGSPICE::AllPlots() const +std::vector NGSPICE::AllVectors() const { LOCALE_IO c_locale; // ngspice works correctly only with C locale char* currentPlot = m_ngSpice_CurPlot(); - char** allPlots = m_ngSpice_AllVecs( currentPlot ); - int noOfPlots = 0; + char** allVectors = m_ngSpice_AllVecs( currentPlot ); + int noOfVectors = 0; std::vector retVal; - if( allPlots != nullptr ) + if( allVectors != nullptr ) { - for( char** plot = allPlots; *plot != nullptr; plot++ ) - noOfPlots++; + for( char** plot = allVectors; *plot != nullptr; plot++ ) + noOfVectors++; - retVal.reserve( noOfPlots ); + retVal.reserve( noOfVectors ); - for( int i = 0; i < noOfPlots; i++, allPlots++ ) + for( int i = 0; i < noOfVectors; i++, allVectors++ ) { - std::string vec = *allPlots; + std::string vec = *allVectors; retVal.push_back( vec ); } } @@ -336,10 +336,10 @@ wxString NGSPICE::GetXAxis( SIM_TYPE aType ) const case ST_DC: // find plot, which ends with "-sweep" - for( wxString plot : AllPlots() ) + for( wxString vector : AllVectors() ) { - if( plot.Lower().EndsWith( wxS( "-sweep" ) ) ) - return plot; + if( vector.Lower().EndsWith( wxS( "-sweep" ) ) ) + return vector; } return wxS( "sweep" ); diff --git a/eeschema/sim/ngspice.h b/eeschema/sim/ngspice.h index c1179d6713..9a9cc04e82 100644 --- a/eeschema/sim/ngspice.h +++ b/eeschema/sim/ngspice.h @@ -80,8 +80,8 @@ public: ///< @copydoc SPICE_SIMULATOR::GetXAxis() wxString GetXAxis( SIM_TYPE aType ) const override final; - ///< @copydoc SPICE_SIMULATOR::AllPlots() - std::vector AllPlots() const override final; + ///< @copydoc SPICE_SIMULATOR::AllVectors() + std::vector AllVectors() const override final; ///< @copydoc SPICE_SIMULATOR::GetPlot() std::vector GetPlot( const std::string& aName, int aMaxLen = -1 ) override final; diff --git a/eeschema/sim/ngspice_circuit_model.cpp b/eeschema/sim/ngspice_circuit_model.cpp index b1f91d2112..58157dd6b4 100644 --- a/eeschema/sim/ngspice_circuit_model.cpp +++ b/eeschema/sim/ngspice_circuit_model.cpp @@ -147,7 +147,7 @@ bool NGSPICE_CIRCUIT_MODEL::ParseDCCommand( const wxString& aCmd, SPICE_DC_PARAM bool NGSPICE_CIRCUIT_MODEL::ParseNoiseCommand( const wxString& aCmd, wxString* aOutput, wxString* aRef, wxString* aSource, wxString* aScale, SPICE_VALUE* aPts, SPICE_VALUE* aFStart, - SPICE_VALUE* aFStop ) + SPICE_VALUE* aFStop, bool* aSaveAll ) { if( !aCmd.Lower().StartsWith( wxS( ".noise" ) ) ) return false; @@ -197,7 +197,13 @@ bool NGSPICE_CIRCUIT_MODEL::ParseNoiseCommand( const wxString& aCmd, wxString* a } if( !token.IsEmpty() ) + { *aFStop = SPICE_VALUE( token ); + token = tokens.GetNextToken(); + } + + if( !token.IsEmpty() ) + *aSaveAll = true; return true; } diff --git a/eeschema/sim/ngspice_circuit_model.h b/eeschema/sim/ngspice_circuit_model.h index a58d1e1ada..45bf1adfeb 100644 --- a/eeschema/sim/ngspice_circuit_model.h +++ b/eeschema/sim/ngspice_circuit_model.h @@ -129,7 +129,7 @@ public: bool ParseNoiseCommand( const wxString& aCmd, wxString* aOutput, wxString* aRef, wxString* aSource, wxString* aScale, SPICE_VALUE* aPts, - SPICE_VALUE* aFStart, SPICE_VALUE* aFStop ); + SPICE_VALUE* aFStart, SPICE_VALUE* aFStop, bool* aSaveAll ); /** * Determine if a directive is a simulation command. diff --git a/eeschema/sim/simulator_frame.cpp b/eeschema/sim/simulator_frame.cpp index 38f607b71a..a8b0f9a6e9 100644 --- a/eeschema/sim/simulator_frame.cpp +++ b/eeschema/sim/simulator_frame.cpp @@ -427,7 +427,7 @@ void SIMULATOR_FRAME::NewPlotPanel( const wxString& aSimCommand, int aOptions ) } -const std::vector& SIMULATOR_FRAME::Signals() +const std::vector SIMULATOR_FRAME::Signals() { return m_panel->Signals(); } diff --git a/eeschema/sim/simulator_frame.h b/eeschema/sim/simulator_frame.h index 8bcdebf000..1c825f868c 100644 --- a/eeschema/sim/simulator_frame.h +++ b/eeschema/sim/simulator_frame.h @@ -95,7 +95,10 @@ public: */ bool EditSimCommand(); - const std::vector& Signals(); + /** + * @return the list of signals in the current simulation results. + */ + const std::vector Signals(); const std::map& UserDefinedSignals(); diff --git a/eeschema/sim/simulator_panel.cpp b/eeschema/sim/simulator_panel.cpp index d14fc09b75..717e66332f 100644 --- a/eeschema/sim/simulator_panel.cpp +++ b/eeschema/sim/simulator_panel.cpp @@ -741,8 +741,8 @@ void SIMULATOR_PANEL::rebuildSignalsList() if( simType == ST_NOISE ) { - addSignal( wxS( "inoise" ) ); - addSignal( wxS( "onoise" ) ); + addSignal( wxS( "inoise_spectrum" ) ); + addSignal( wxS( "onoise_spectrum" ) ); } // Add .PROBE directives @@ -847,18 +847,16 @@ wxString SIMULATOR_PANEL::vectorNameFromSignalName( const wxString& aSignalName, if( aTraceType ) { - wxString name = aSignalName.Upper(); - - if( name == wxS( "INOISE" ) || name == wxS( "ONOISE" ) ) + if( circuitModel()->GetSimType() == ST_NOISE ) { if( getNoiseSource().Upper().StartsWith( 'I' ) ) *aTraceType = SPT_CURRENT; else *aTraceType = SPT_VOLTAGE; } - else if( !name.IsEmpty() ) + else { - wxUniChar firstChar = name[0]; + wxUniChar firstChar = aSignalName.Upper()[0]; if( firstChar == 'V' ) *aTraceType = SPT_VOLTAGE; @@ -1451,10 +1449,6 @@ void SIMULATOR_PANEL::updateTrace( const wxString& aVectorName, int aTraceType, break; case ST_NOISE: - simVectorName = wxString::Format( wxS( "noise1.%s_spectrum" ), simVectorName ); - data_y = simulator()->GetMagPlot( (const char*) simVectorName.c_str() ); - break; - case ST_DC: case ST_TRANSIENT: data_y = simulator()->GetMagPlot( (const char*) simVectorName.c_str() ); @@ -2137,9 +2131,10 @@ wxString SIMULATOR_PANEL::getNoiseSource() const SPICE_VALUE pts; SPICE_VALUE fStart; SPICE_VALUE fStop; + bool saveAll; circuitModel()->ParseNoiseCommand( circuitModel()->GetSimCommand(), &output, &ref, &source, - &scale, &pts, &fStart, &fStop ); + &scale, &pts, &fStart, &fStop, &saveAll ); return source; } @@ -2388,6 +2383,17 @@ void SIMULATOR_PANEL::OnSimReport( const wxString& aMsg ) } +std::vector SIMULATOR_PANEL::Signals() +{ + std::vector signals; + + for( const std::string& vec : simulator()->AllVectors() ) + signals.emplace_back( vec ); + + return signals; +} + + void SIMULATOR_PANEL::OnSimRefresh( bool aFinal ) { SIM_TYPE simType = circuitModel()->GetSimType(); @@ -2413,7 +2419,9 @@ void SIMULATOR_PANEL::OnSimRefresh( bool aFinal ) m_simConsole->AppendText( _( "\n\nSimulation results:\n\n" ) ); m_simConsole->SetInsertionPointEnd(); - for( const std::string& vec : simulator()->AllPlots() ) + simulator()->Command( "setplot noise2" ); + + for( const std::string& vec : simulator()->AllVectors() ) { std::vector val_list = simulator()->GetRealPlot( vec, 1 ); wxString value = SPICE_VALUE( val_list[ 0 ] ).ToSpiceString(); @@ -2423,6 +2431,8 @@ void SIMULATOR_PANEL::OnSimRefresh( bool aFinal ) m_simConsole->AppendText( msg ); m_simConsole->SetInsertionPointEnd(); } + + simulator()->Command( "setplot noise1" ); } SIM_PLOT_PANEL* plotPanel = dynamic_cast( plotPanelWindow ); @@ -2483,7 +2493,7 @@ void SIMULATOR_PANEL::OnSimRefresh( bool aFinal ) m_simConsole->AppendText( _( "\n\nSimulation results:\n\n" ) ); m_simConsole->SetInsertionPointEnd(); - for( const std::string& vec : simulator()->AllPlots() ) + for( const std::string& vec : simulator()->AllVectors() ) { std::vector val_list = simulator()->GetRealPlot( vec, 1 ); wxString value = SPICE_VALUE( val_list[ 0 ] ).ToSpiceString(); diff --git a/eeschema/sim/simulator_panel.h b/eeschema/sim/simulator_panel.h index 301bdccc22..619a59df26 100644 --- a/eeschema/sim/simulator_panel.h +++ b/eeschema/sim/simulator_panel.h @@ -91,7 +91,7 @@ public: */ SIM_PLOT_PANEL_BASE* NewPlotPanel( const wxString& aSimCommand, int aSimOptions ); - const std::vector& Signals() { return m_signals; } + std::vector Signals(); const std::map& UserDefinedSignals() { return m_userDefinedSignals; } void SetUserDefinedSignals( const std::map& aSignals ); diff --git a/eeschema/sim/spice_simulator.h b/eeschema/sim/spice_simulator.h index 3306d432a7..d3087ee0d4 100644 --- a/eeschema/sim/spice_simulator.h +++ b/eeschema/sim/spice_simulator.h @@ -91,7 +91,7 @@ public: * * @return List of vector names. ?May not match to the net name elements. */ - virtual std::vector AllPlots() const = 0; + virtual std::vector AllVectors() const = 0; /** * Return a requested vector with complex values. If the vector is real, then