simulator: update dialog to handle R, I & TEMP DC sweeps

Fixes https://gitlab.com/kicad/code/kicad/-/issues/2370
Fixes https://gitlab.com/kicad/code/kicad/-/issues/6195
Fixes https://gitlab.com/kicad/code/kicad/-/issues/2386
This commit is contained in:
Sylwester Kocjan
2021-01-25 21:29:13 +00:00
committed by Seth Hillbrand
parent 96af236493
commit 6a48e21eb2
14 changed files with 1285 additions and 1230 deletions
+82 -128
View File
@@ -29,6 +29,8 @@
#include <algorithm>
#include <limits>
#include <wx/regex.h>
static wxString formatFloat( double x, int nDigits )
{
wxString rv, fmt;
@@ -120,145 +122,66 @@ static int countDecimalDigits( double x, int maxDigits )
}
static void formatSILabels( mpScaleBase* scale, const wxString& aUnit, int nDigits )
template <typename parent>
class LIN_SCALE : public parent
{
double maxVis = scale->AbsVisibleMaxValue();
private:
const wxString m_unit;
wxString suffix;
int power, digits = 0;
getSISuffix( maxVis, aUnit, power, suffix );
double sf = pow( 10.0, power );
for( auto &l : scale->TickLabels() )
{
int k = countDecimalDigits( l.pos / sf, nDigits );
digits = std::max( digits, k );
}
for( auto &l : scale->TickLabels() )
{
l.label = formatFloat ( l.pos / sf, digits ) + suffix;
l.visible = true;
}
}
class FREQUENCY_LOG_SCALE : public mpScaleXLog
{
public:
FREQUENCY_LOG_SCALE( wxString name, int flags ) :
mpScaleXLog( name, flags ) {};
LIN_SCALE( wxString name, wxString unit, int flags ) : parent( name, flags ), m_unit( unit ){};
void formatLabels() override
{
const wxString unit = wxT( "Hz" );
double maxVis = parent::AbsVisibleMaxValue();
wxString suffix;
int power;
int power, digits = 0;
int constexpr DIGITS = 3;
for( auto &l : TickLabels() )
getSISuffix( maxVis, m_unit, power, suffix );
double sf = pow( 10.0, power );
for( auto& l : parent::TickLabels() )
{
getSISuffix( l.pos, unit, power, suffix );
double sf = pow( 10.0, power );
int k = countDecimalDigits( l.pos / sf, 3 );
int k = countDecimalDigits( l.pos / sf, DIGITS );
l.label = formatFloat( l.pos / sf, k ) + suffix;
digits = std::max( digits, k );
}
for( auto& l : parent::TickLabels() )
{
l.label = formatFloat( l.pos / sf, digits ) + suffix;
l.visible = true;
}
}
};
class FREQUENCY_LIN_SCALE : public mpScaleX
template <typename parent>
class LOG_SCALE : public parent
{
private:
const wxString m_unit;
public:
FREQUENCY_LIN_SCALE( wxString name, int flags ) :
mpScaleX( name, flags, false , 0 ) {};
LOG_SCALE( wxString name, wxString unit, int flags ) : parent( name, flags ), m_unit( unit ){};
void formatLabels() override
{
formatSILabels( this, wxT( "Hz" ), 3 );
}
};
wxString suffix;
int power;
for( auto& l : parent::TickLabels() )
{
getSISuffix( l.pos, m_unit, power, suffix );
double sf = pow( 10.0, power );
int k = countDecimalDigits( l.pos / sf, 3 );
class TIME_SCALE : public mpScaleX
{
public:
TIME_SCALE( wxString name, int flags ) :
mpScaleX( name, flags, false, 0 ) {};
void formatLabels() override
{
formatSILabels( this, wxT( "s" ), 3 );
}
};
class VOLTAGE_SCALE_X : public mpScaleX
{
public:
VOLTAGE_SCALE_X( wxString name, int flags ) :
mpScaleX( name, flags, false, 0 ) {};
void formatLabels() override
{
formatSILabels( this, wxT( "V" ), 3 );
}
};
class GAIN_SCALE : public mpScaleY
{
public:
GAIN_SCALE( wxString name, int flags ) :
mpScaleY( name, flags, false ) {};
void formatLabels() override
{
formatSILabels( this, wxT( "dBV" ), 3 );
}
};
class PHASE_SCALE : public mpScaleY
{
public:
PHASE_SCALE( wxString name, int flags ) :
mpScaleY( name, flags, false ) {};
void formatLabels() override
{
formatSILabels( this, wxT( "\u00B0" ), 3 ); // degree sign
}
};
class VOLTAGE_SCALE_Y : public mpScaleY
{
public:
VOLTAGE_SCALE_Y( wxString name, int flags ) :
mpScaleY( name, flags, false ) {};
void formatLabels() override
{
formatSILabels( this, wxT( "V" ), 3 );
}
};
class CURRENT_SCALE : public mpScaleY
{
public:
CURRENT_SCALE( wxString name, int flags ) :
mpScaleY( name, flags, false ) {};
void formatLabels() override
{
formatSILabels( this, wxT( "A" ), 3 );
l.label = formatFloat( l.pos / sf, k ) + suffix;
l.visible = true;
}
}
};
@@ -363,9 +286,9 @@ void CURSOR::UpdateReference()
}
SIM_PLOT_PANEL::SIM_PLOT_PANEL( SIM_TYPE aType, wxWindow* parent, SIM_PLOT_FRAME* aMainFrame,
SIM_PLOT_PANEL::SIM_PLOT_PANEL( wxString aCommand, wxWindow* parent, SIM_PLOT_FRAME* aMainFrame,
wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name )
: SIM_PANEL_BASE( aType, parent, id, pos, size, style, name ),
: SIM_PANEL_BASE( aCommand, parent, id, pos, size, style, name ),
m_colorIdx( 0 ),
m_axis_x( nullptr ),
m_axis_y1( nullptr ),
@@ -385,27 +308,26 @@ SIM_PLOT_PANEL::SIM_PLOT_PANEL( SIM_TYPE aType, wxWindow* parent, SIM_PLOT_FRAME
switch( GetType() )
{
case ST_AC:
m_axis_x = new FREQUENCY_LOG_SCALE( _( "Frequency" ), mpALIGN_BOTTOM );
m_axis_y1 = new GAIN_SCALE( _( "Gain" ), mpALIGN_LEFT );
m_axis_y2 = new PHASE_SCALE( _( "Phase" ), mpALIGN_RIGHT );
m_axis_x = new LOG_SCALE<mpScaleXLog>( _( "Frequency" ), wxT( "Hz" ), mpALIGN_BOTTOM );
m_axis_y1 = new LIN_SCALE<mpScaleY>( _( "Gain" ), wxT( "dBV" ), mpALIGN_LEFT );
m_axis_y2 = new LIN_SCALE<mpScaleY>( _( "Phase" ), wxT( "\u00B0" ),
mpALIGN_RIGHT ); // degree sign
m_axis_y2->SetMasterScale( m_axis_y1 );
break;
case ST_DC:
m_axis_x = new VOLTAGE_SCALE_X( _( "Voltage (swept)" ), mpALIGN_BOTTOM );
m_axis_y1 = new VOLTAGE_SCALE_Y( _( "Voltage (measured)" ), mpALIGN_LEFT );
m_axis_y2 = new CURRENT_SCALE( _( "Current" ), mpALIGN_RIGHT );
prepareDCAxes();
break;
case ST_NOISE:
m_axis_x = new FREQUENCY_LOG_SCALE( _( "Frequency" ), mpALIGN_BOTTOM );
m_axis_x = new LOG_SCALE<mpScaleXLog>( _( "Frequency" ), wxT( "Hz" ), mpALIGN_BOTTOM );
m_axis_y1 = new mpScaleY( _( "noise [(V or A)^2/Hz]" ), mpALIGN_LEFT );
break;
case ST_TRANSIENT:
m_axis_x = new TIME_SCALE( _( "Time" ), mpALIGN_BOTTOM );
m_axis_y1 = new VOLTAGE_SCALE_Y( _( "Voltage" ), mpALIGN_LEFT );
m_axis_y2 = new CURRENT_SCALE( _( "Current" ), mpALIGN_RIGHT );
m_axis_x = new LIN_SCALE<mpScaleX>( _( "Time" ), wxT( "s" ), mpALIGN_BOTTOM );
m_axis_y1 = new LIN_SCALE<mpScaleY>( _( "Voltage" ), wxT( "V" ), mpALIGN_LEFT );
m_axis_y2 = new LIN_SCALE<mpScaleY>( _( "Current" ), wxT( "A" ), mpALIGN_RIGHT );
m_axis_y2->SetMasterScale( m_axis_y1 );
break;
@@ -455,6 +377,38 @@ SIM_PLOT_PANEL::~SIM_PLOT_PANEL()
}
void SIM_PLOT_PANEL::prepareDCAxes()
{
wxRegEx simCmd( "^.dc[[:space:]]+([[:alnum:]]+\\M).*", wxRE_ADVANCED | wxRE_ICASE );
if( simCmd.Matches( m_simCommand ) )
{
switch( static_cast<char>( simCmd.GetMatch( m_simCommand.Lower(), 1 ).GetChar( 0 ) ) )
{
case 'v':
m_axis_x =
new LIN_SCALE<mpScaleX>( _( "Voltage (swept)" ), wxT( "V" ), mpALIGN_BOTTOM );
break;
case 'i':
m_axis_x =
new LIN_SCALE<mpScaleX>( _( "Current (swept)" ), wxT( "A" ), mpALIGN_BOTTOM );
break;
case 'r':
m_axis_x = new LIN_SCALE<mpScaleX>( _( "Resistance (swept)" ), wxT( "\u03A9" ),
mpALIGN_BOTTOM );
break;
case 't':
m_axis_x = new LIN_SCALE<mpScaleX>( _( "Temperature (swept)" ), wxT( "\u00B0C" ),
mpALIGN_BOTTOM );
break;
}
m_axis_y1 = new LIN_SCALE<mpScaleY>( _( "Voltage (measured)" ), wxT( "V" ), mpALIGN_LEFT );
m_axis_y2 = new LIN_SCALE<mpScaleY>( _( "Current" ), wxT( "A" ), mpALIGN_RIGHT );
}
}
void SIM_PLOT_PANEL::UpdatePlotColors()
{
// Update bg and fg colors: