Plotting for noise simulations.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/2369
This commit is contained in:
parent
67c9d3932b
commit
7d3fa8fb4e
|
@ -264,17 +264,16 @@ DIALOG_SIM_COMMAND_BASE::DIALOG_SIM_COMMAND_BASE( wxWindow* parent, wxWindowID i
|
||||||
int m_noiseScaleNChoices = sizeof( m_noiseScaleChoices ) / sizeof( wxString );
|
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->SetSelection( 0 );
|
||||||
|
m_noiseScale->Hide();
|
||||||
|
|
||||||
bSizer10->Add( m_noiseScale, 0, wxALL, 5 );
|
bSizer10->Add( m_noiseScale, 0, wxALL, 5 );
|
||||||
|
|
||||||
|
|
||||||
bSizer10->Add( 30, 0, 0, wxEXPAND, 5 );
|
|
||||||
|
|
||||||
wxFlexGridSizer* fgSizer11;
|
wxFlexGridSizer* fgSizer11;
|
||||||
fgSizer11 = new wxFlexGridSizer( 0, 3, 3, 0 );
|
fgSizer11 = new wxFlexGridSizer( 0, 3, 3, 0 );
|
||||||
fgSizer11->SetFlexibleDirection( wxBOTH );
|
fgSizer11->SetFlexibleDirection( wxBOTH );
|
||||||
fgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
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 );
|
m_staticText11->Wrap( -1 );
|
||||||
fgSizer11->Add( m_staticText11, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxRIGHT|wxLEFT, 5 );
|
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 );
|
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 );
|
bSizer15->Add( bSizer10, 0, wxEXPAND|wxTOP, 5 );
|
||||||
|
|
|
@ -3076,7 +3076,7 @@
|
||||||
<property name="floatable">1</property>
|
<property name="floatable">1</property>
|
||||||
<property name="font"></property>
|
<property name="font"></property>
|
||||||
<property name="gripper">0</property>
|
<property name="gripper">0</property>
|
||||||
<property name="hidden">0</property>
|
<property name="hidden">1</property>
|
||||||
<property name="id">wxID_ANY</property>
|
<property name="id">wxID_ANY</property>
|
||||||
<property name="label">Frequency scale</property>
|
<property name="label">Frequency scale</property>
|
||||||
<property name="majorDimension">1</property>
|
<property name="majorDimension">1</property>
|
||||||
|
@ -3113,17 +3113,7 @@
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="1">
|
<object class="sizeritem" expanded="1">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="flag">wxEXPAND</property>
|
<property name="flag">wxALIGN_BOTTOM|wxTOP|wxBOTTOM|wxLEFT</property>
|
||||||
<property name="proportion">0</property>
|
|
||||||
<object class="spacer" expanded="1">
|
|
||||||
<property name="height">0</property>
|
|
||||||
<property name="permission">protected</property>
|
|
||||||
<property name="width">30</property>
|
|
||||||
</object>
|
|
||||||
</object>
|
|
||||||
<object class="sizeritem" expanded="1">
|
|
||||||
<property name="border">4</property>
|
|
||||||
<property name="flag">wxALIGN_BOTTOM|wxBOTTOM|wxLEFT</property>
|
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="wxFlexGridSizer" expanded="1">
|
<object class="wxFlexGridSizer" expanded="1">
|
||||||
<property name="cols">3</property>
|
<property name="cols">3</property>
|
||||||
|
@ -3169,7 +3159,7 @@
|
||||||
<property name="gripper">0</property>
|
<property name="gripper">0</property>
|
||||||
<property name="hidden">0</property>
|
<property name="hidden">0</property>
|
||||||
<property name="id">wxID_ANY</property>
|
<property name="id">wxID_ANY</property>
|
||||||
<property name="label">Number of points:</property>
|
<property name="label">Number of points per decade:</property>
|
||||||
<property name="markup">0</property>
|
<property name="markup">0</property>
|
||||||
<property name="max_size"></property>
|
<property name="max_size"></property>
|
||||||
<property name="maximize_button">0</property>
|
<property name="maximize_button">0</property>
|
||||||
|
|
|
@ -329,9 +329,11 @@ wxString NGSPICE::GetXAxis( SIM_TYPE aType ) const
|
||||||
switch( aType )
|
switch( aType )
|
||||||
{
|
{
|
||||||
case ST_AC:
|
case ST_AC:
|
||||||
case ST_NOISE:
|
|
||||||
return wxS( "frequency" );
|
return wxS( "frequency" );
|
||||||
|
|
||||||
|
case ST_NOISE:
|
||||||
|
return wxS( "noise1.frequency" );
|
||||||
|
|
||||||
case ST_DC:
|
case ST_DC:
|
||||||
// find plot, which ends with "-sweep"
|
// find plot, which ends with "-sweep"
|
||||||
for( wxString plot : AllPlots() )
|
for( wxString plot : AllPlots() )
|
||||||
|
|
|
@ -528,13 +528,28 @@ void SIM_PLOT_PANEL::updateAxes( int aNewTraceType )
|
||||||
m_axis_x->SetNameAlign( mpALIGN_BOTTOM );
|
m_axis_x->SetNameAlign( mpALIGN_BOTTOM );
|
||||||
m_plotWin->AddLayer( m_axis_x );
|
m_plotWin->AddLayer( m_axis_x );
|
||||||
|
|
||||||
m_axis_y1 = new mpScaleY( wxEmptyString, mpALIGN_LEFT, false );
|
if( ( aNewTraceType & SPT_CURRENT ) == 0 )
|
||||||
m_axis_y1->SetNameAlign( mpALIGN_LEFT );
|
{
|
||||||
m_plotWin->AddLayer( m_axis_y1 );
|
m_axis_y1 = new LIN_SCALE<mpScaleY>( wxEmptyString, wxT( "" ), mpALIGN_LEFT );
|
||||||
|
m_axis_y1->SetNameAlign( mpALIGN_LEFT );
|
||||||
|
m_plotWin->AddLayer( m_axis_y1 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_axis_y2 = new LIN_SCALE<mpScaleY>( wxEmptyString, wxT( "" ), mpALIGN_RIGHT );
|
||||||
|
m_axis_y2->SetNameAlign( mpALIGN_RIGHT );
|
||||||
|
m_plotWin->AddLayer( m_axis_y2 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_axis_x->SetName( _( "Frequency" ) );
|
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;
|
break;
|
||||||
|
|
||||||
case ST_TRANSIENT:
|
case ST_TRANSIENT:
|
||||||
|
|
|
@ -59,6 +59,7 @@ bool SIM_PLOT_PANEL_BASE::IsPlottable( SIM_TYPE aSimType )
|
||||||
case ST_AC:
|
case ST_AC:
|
||||||
case ST_DC:
|
case ST_DC:
|
||||||
case ST_TRANSIENT:
|
case ST_TRANSIENT:
|
||||||
|
case ST_NOISE:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -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() )
|
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
|
// Add .PROBE directives
|
||||||
for( const wxString& directive : circuitModel()->GetDirectives() )
|
for( const wxString& directive : circuitModel()->GetDirectives() )
|
||||||
{
|
{
|
||||||
|
@ -840,14 +847,26 @@ wxString SIMULATOR_PANEL::vectorNameFromSignalName( const wxString& aSignalName,
|
||||||
|
|
||||||
if( aTraceType )
|
if( aTraceType )
|
||||||
{
|
{
|
||||||
wxUniChar firstChar = aSignalName.Upper()[0];
|
wxString name = aSignalName.Upper();
|
||||||
|
|
||||||
if( firstChar == 'V' )
|
if( name == wxS( "INOISE" ) || name == wxS( "ONOISE" ) )
|
||||||
*aTraceType = SPT_VOLTAGE;
|
{
|
||||||
else if( firstChar == 'I' )
|
if( getNoiseSource().Upper().StartsWith( 'I' ) )
|
||||||
*aTraceType = SPT_CURRENT;
|
*aTraceType = SPT_CURRENT;
|
||||||
else if( firstChar == 'P' )
|
else
|
||||||
*aTraceType = SPT_POWER;
|
*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;
|
wxString suffix;
|
||||||
|
@ -1432,6 +1451,10 @@ void SIMULATOR_PANEL::updateTrace( const wxString& aVectorName, int aTraceType,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ST_NOISE:
|
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_DC:
|
||||||
case ST_TRANSIENT:
|
case ST_TRANSIENT:
|
||||||
data_y = simulator()->GetMagPlot( (const char*) simVectorName.c_str() );
|
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_AC: return SPT_LIN_FREQUENCY;
|
||||||
case ST_DC: return SPT_SWEEP;
|
case ST_DC: return SPT_SWEEP;
|
||||||
case ST_TRANSIENT: return SPT_TIME;
|
case ST_TRANSIENT: return SPT_TIME;
|
||||||
|
case ST_NOISE: return SPT_LIN_FREQUENCY;
|
||||||
default: wxFAIL_MSG( wxS( "Unhandled simulation type" ) ); return SPT_UNKNOWN;
|
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()
|
void SIMULATOR_PANEL::ToggleDarkModePlots()
|
||||||
{
|
{
|
||||||
m_darkMode = !m_darkMode;
|
m_darkMode = !m_darkMode;
|
||||||
|
@ -2359,6 +2400,7 @@ void SIMULATOR_PANEL::OnSimRefresh( bool aFinal )
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<wxString> oldSignals = m_signals;
|
std::vector<wxString> oldSignals = m_signals;
|
||||||
|
wxString msg;
|
||||||
|
|
||||||
applyUserDefinedSignals();
|
applyUserDefinedSignals();
|
||||||
rebuildSignalsList();
|
rebuildSignalsList();
|
||||||
|
@ -2366,6 +2408,23 @@ void SIMULATOR_PANEL::OnSimRefresh( bool aFinal )
|
||||||
// If there are any signals plotted, update them
|
// If there are any signals plotted, update them
|
||||||
if( SIM_PLOT_PANEL_BASE::IsPlottable( simType ) )
|
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<double> 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<SIM_PLOT_PANEL*>( plotPanelWindow );
|
SIM_PLOT_PANEL* plotPanel = dynamic_cast<SIM_PLOT_PANEL*>( plotPanelWindow );
|
||||||
wxCHECK_RET( plotPanel, wxT( "not a SIM_PLOT_PANEL" ) );
|
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() )
|
for( const std::string& vec : simulator()->AllPlots() )
|
||||||
{
|
{
|
||||||
std::vector<double> val_list = simulator()->GetRealPlot( vec, 1 );
|
std::vector<double> 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!
|
const size_t tab = 25; //characters
|
||||||
continue;
|
size_t padding = ( signal.length() < tab ) ? ( tab - signal.length() ) : 1;
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
value.Append( type == SPT_CURRENT ? wxS( "A" ) : wxS( "V" ) );
|
value.Append( type == SPT_CURRENT ? wxS( "A" ) : wxS( "V" ) );
|
||||||
|
|
||||||
|
|
|
@ -283,6 +283,8 @@ private:
|
||||||
*/
|
*/
|
||||||
SIM_TRACE_TYPE getXAxisType( SIM_TYPE aType ) const;
|
SIM_TRACE_TYPE getXAxisType( SIM_TYPE aType ) const;
|
||||||
|
|
||||||
|
wxString getNoiseSource() const;
|
||||||
|
|
||||||
void parseTraceParams( SIM_PLOT_PANEL* aPlotPanel, TRACE* aTrace, const wxString& aSignalName,
|
void parseTraceParams( SIM_PLOT_PANEL* aPlotPanel, TRACE* aTrace, const wxString& aSignalName,
|
||||||
const wxString& aParams );
|
const wxString& aParams );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue