diff --git a/eeschema/dialogs/dialog_sim_command_base.cpp b/eeschema/dialogs/dialog_sim_command_base.cpp
index 8d77f5d170..df5894c496 100644
--- a/eeschema/dialogs/dialog_sim_command_base.cpp
+++ b/eeschema/dialogs/dialog_sim_command_base.cpp
@@ -264,17 +264,16 @@ DIALOG_SIM_COMMAND_BASE::DIALOG_SIM_COMMAND_BASE( wxWindow* parent, wxWindowID i
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->SetSelection( 0 );
+ m_noiseScale->Hide();
+
bSizer10->Add( m_noiseScale, 0, wxALL, 5 );
-
- bSizer10->Add( 30, 0, 0, wxEXPAND, 5 );
-
wxFlexGridSizer* fgSizer11;
fgSizer11 = new wxFlexGridSizer( 0, 3, 3, 0 );
fgSizer11->SetFlexibleDirection( wxBOTH );
fgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
- m_staticText11 = new wxStaticText( m_pgNoise, wxID_ANY, _("Number of points:"), 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 );
@@ -313,7 +312,7 @@ 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|wxBOTTOM|wxLEFT, 4 );
+ bSizer10->Add( fgSizer11, 0, wxALIGN_BOTTOM|wxTOP|wxBOTTOM|wxLEFT, 5 );
bSizer15->Add( bSizer10, 0, wxEXPAND|wxTOP, 5 );
diff --git a/eeschema/dialogs/dialog_sim_command_base.fbp b/eeschema/dialogs/dialog_sim_command_base.fbp
index 11f6b9a328..b143e9312b 100644
--- a/eeschema/dialogs/dialog_sim_command_base.fbp
+++ b/eeschema/dialogs/dialog_sim_command_base.fbp
@@ -3076,7 +3076,7 @@
1
0
- 0
+ 1
wxID_ANY
Frequency scale
1
@@ -3113,17 +3113,7 @@
-
- 4
- wxALIGN_BOTTOM|wxBOTTOM|wxLEFT
+ wxALIGN_BOTTOM|wxTOP|wxBOTTOM|wxLEFT
0
3
@@ -3169,7 +3159,7 @@
0
0
wxID_ANY
- Number of points:
+ Number of points per decade:
0
0
diff --git a/eeschema/sim/ngspice.cpp b/eeschema/sim/ngspice.cpp
index 3aa2ee8756..918df09b82 100644
--- a/eeschema/sim/ngspice.cpp
+++ b/eeschema/sim/ngspice.cpp
@@ -329,9 +329,11 @@ wxString NGSPICE::GetXAxis( SIM_TYPE aType ) const
switch( aType )
{
case ST_AC:
- case ST_NOISE:
return wxS( "frequency" );
+ case ST_NOISE:
+ return wxS( "noise1.frequency" );
+
case ST_DC:
// find plot, which ends with "-sweep"
for( wxString plot : AllPlots() )
diff --git a/eeschema/sim/sim_plot_panel.cpp b/eeschema/sim/sim_plot_panel.cpp
index 0165ca4448..dd0a322175 100644
--- a/eeschema/sim/sim_plot_panel.cpp
+++ b/eeschema/sim/sim_plot_panel.cpp
@@ -528,13 +528,28 @@ void SIM_PLOT_PANEL::updateAxes( int aNewTraceType )
m_axis_x->SetNameAlign( mpALIGN_BOTTOM );
m_plotWin->AddLayer( m_axis_x );
- m_axis_y1 = new mpScaleY( wxEmptyString, mpALIGN_LEFT, false );
- m_axis_y1->SetNameAlign( mpALIGN_LEFT );
- m_plotWin->AddLayer( m_axis_y1 );
+ if( ( aNewTraceType & SPT_CURRENT ) == 0 )
+ {
+ m_axis_y1 = new LIN_SCALE( wxEmptyString, wxT( "" ), mpALIGN_LEFT );
+ m_axis_y1->SetNameAlign( mpALIGN_LEFT );
+ m_plotWin->AddLayer( m_axis_y1 );
+ }
+ else
+ {
+ m_axis_y2 = new LIN_SCALE( wxEmptyString, wxT( "" ), mpALIGN_RIGHT );
+ m_axis_y2->SetNameAlign( mpALIGN_RIGHT );
+ m_plotWin->AddLayer( m_axis_y2 );
+ }
}
m_axis_x->SetName( _( "Frequency" ) );
- m_axis_y1->SetName( _( "noise [(V or A)^2/Hz]" ) );
+
+ if( m_axis_y1 )
+ m_axis_y1->SetName( _( "Noise (V/√Hz)" ) );
+
+ if( m_axis_y2 )
+ m_axis_y2->SetName( _( "Noise (A/√Hz)" ) );
+
break;
case ST_TRANSIENT:
diff --git a/eeschema/sim/sim_plot_panel_base.cpp b/eeschema/sim/sim_plot_panel_base.cpp
index c69842f6d0..b8c05e1504 100644
--- a/eeschema/sim/sim_plot_panel_base.cpp
+++ b/eeschema/sim/sim_plot_panel_base.cpp
@@ -59,6 +59,7 @@ bool SIM_PLOT_PANEL_BASE::IsPlottable( SIM_TYPE aSimType )
case ST_AC:
case ST_DC:
case ST_TRANSIENT:
+ case ST_NOISE:
return true;
default:
diff --git a/eeschema/sim/simulator_panel.cpp b/eeschema/sim/simulator_panel.cpp
index 9fd7a4b9ff..d14fc09b75 100644
--- a/eeschema/sim/simulator_panel.cpp
+++ b/eeschema/sim/simulator_panel.cpp
@@ -699,7 +699,8 @@ void SIMULATOR_PANEL::rebuildSignalsList()
}
};
- if( options & NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_VOLTAGES )
+ if( ( options & NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_VOLTAGES )
+ && ( simType == ST_TRANSIENT || simType == ST_DC || simType == ST_AC ) )
{
for( const std::string& net : circuitModel()->GetNets() )
{
@@ -738,6 +739,12 @@ void SIMULATOR_PANEL::rebuildSignalsList()
}
}
+ if( simType == ST_NOISE )
+ {
+ addSignal( wxS( "inoise" ) );
+ addSignal( wxS( "onoise" ) );
+ }
+
// Add .PROBE directives
for( const wxString& directive : circuitModel()->GetDirectives() )
{
@@ -840,14 +847,26 @@ wxString SIMULATOR_PANEL::vectorNameFromSignalName( const wxString& aSignalName,
if( aTraceType )
{
- wxUniChar firstChar = aSignalName.Upper()[0];
+ wxString name = aSignalName.Upper();
- if( firstChar == 'V' )
- *aTraceType = SPT_VOLTAGE;
- else if( firstChar == 'I' )
- *aTraceType = SPT_CURRENT;
- else if( firstChar == 'P' )
- *aTraceType = SPT_POWER;
+ if( name == wxS( "INOISE" ) || name == wxS( "ONOISE" ) )
+ {
+ if( getNoiseSource().Upper().StartsWith( 'I' ) )
+ *aTraceType = SPT_CURRENT;
+ else
+ *aTraceType = SPT_VOLTAGE;
+ }
+ else if( !name.IsEmpty() )
+ {
+ wxUniChar firstChar = name[0];
+
+ if( firstChar == 'V' )
+ *aTraceType = SPT_VOLTAGE;
+ else if( firstChar == 'I' )
+ *aTraceType = SPT_CURRENT;
+ else if( firstChar == 'P' )
+ *aTraceType = SPT_POWER;
+ }
}
wxString suffix;
@@ -1432,6 +1451,10 @@ 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() );
@@ -2099,11 +2122,29 @@ SIM_TRACE_TYPE SIMULATOR_PANEL::getXAxisType( SIM_TYPE aType ) const
case ST_AC: return SPT_LIN_FREQUENCY;
case ST_DC: return SPT_SWEEP;
case ST_TRANSIENT: return SPT_TIME;
+ case ST_NOISE: return SPT_LIN_FREQUENCY;
default: wxFAIL_MSG( wxS( "Unhandled simulation type" ) ); return SPT_UNKNOWN;
}
}
+wxString SIMULATOR_PANEL::getNoiseSource() const
+{
+ wxString output;
+ wxString ref;
+ wxString source;
+ wxString scale;
+ SPICE_VALUE pts;
+ SPICE_VALUE fStart;
+ SPICE_VALUE fStop;
+
+ circuitModel()->ParseNoiseCommand( circuitModel()->GetSimCommand(), &output, &ref, &source,
+ &scale, &pts, &fStart, &fStop );
+
+ return source;
+}
+
+
void SIMULATOR_PANEL::ToggleDarkModePlots()
{
m_darkMode = !m_darkMode;
@@ -2359,6 +2400,7 @@ void SIMULATOR_PANEL::OnSimRefresh( bool aFinal )
}
std::vector oldSignals = m_signals;
+ wxString msg;
applyUserDefinedSignals();
rebuildSignalsList();
@@ -2366,6 +2408,23 @@ void SIMULATOR_PANEL::OnSimRefresh( bool aFinal )
// If there are any signals plotted, update them
if( SIM_PLOT_PANEL_BASE::IsPlottable( simType ) )
{
+ if( simType == ST_NOISE && aFinal )
+ {
+ m_simConsole->AppendText( _( "\n\nSimulation results:\n\n" ) );
+ m_simConsole->SetInsertionPointEnd();
+
+ for( const std::string& vec : simulator()->AllPlots() )
+ {
+ std::vector val_list = simulator()->GetRealPlot( vec, 1 );
+ wxString value = SPICE_VALUE( val_list[ 0 ] ).ToSpiceString();
+
+ msg.Printf( wxS( "%s: %sV\n" ), vec, value );
+
+ m_simConsole->AppendText( msg );
+ m_simConsole->SetInsertionPointEnd();
+ }
+ }
+
SIM_PLOT_PANEL* plotPanel = dynamic_cast( plotPanelWindow );
wxCHECK_RET( plotPanel, wxT( "not a SIM_PLOT_PANEL" ) );
@@ -2427,17 +2486,12 @@ void SIMULATOR_PANEL::OnSimRefresh( bool aFinal )
for( const std::string& vec : simulator()->AllPlots() )
{
std::vector val_list = simulator()->GetRealPlot( vec, 1 );
+ wxString value = SPICE_VALUE( val_list[ 0 ] ).ToSpiceString();
+ wxString signal;
+ SIM_TRACE_TYPE type = circuitModel()->VectorToSignal( vec, signal );
- if( val_list.size() == 0 ) // The list of values can be empty!
- continue;
-
- wxString value = SPICE_VALUE( val_list.at( 0 ) ).ToSpiceString();
- wxString msg;
- wxString signal;
- SIM_TRACE_TYPE type = circuitModel()->VectorToSignal( vec, signal );
-
- const size_t tab = 25; //characters
- size_t padding = ( signal.length() < tab ) ? ( tab - signal.length() ) : 1;
+ const size_t tab = 25; //characters
+ size_t padding = ( signal.length() < tab ) ? ( tab - signal.length() ) : 1;
value.Append( type == SPT_CURRENT ? wxS( "A" ) : wxS( "V" ) );
diff --git a/eeschema/sim/simulator_panel.h b/eeschema/sim/simulator_panel.h
index 546ffeeb87..301bdccc22 100644
--- a/eeschema/sim/simulator_panel.h
+++ b/eeschema/sim/simulator_panel.h
@@ -283,6 +283,8 @@ private:
*/
SIM_TRACE_TYPE getXAxisType( SIM_TYPE aType ) const;
+ wxString getNoiseSource() const;
+
void parseTraceParams( SIM_PLOT_PANEL* aPlotPanel, TRACE* aTrace, const wxString& aSignalName,
const wxString& aParams );