Simulator code formatting and clean up
This commit is contained in:
parent
957c6ec417
commit
eeeb3e0a9a
|
@ -44,8 +44,6 @@ wxString NETLIST_EXPORTER_PSPICE_SIM::GetSpiceVector( const wxString& aName, SIM
|
||||||
return wxString::Format( "V(%d)", it->second );
|
return wxString::Format( "V(%d)", it->second );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @todo check is Lower() is required
|
|
||||||
else if( aType & SPT_CURRENT )
|
else if( aType & SPT_CURRENT )
|
||||||
{
|
{
|
||||||
return wxString::Format( "@%s[%s]", GetSpiceDevice( aName ).Lower(),
|
return wxString::Format( "@%s[%s]", GetSpiceDevice( aName ).Lower(),
|
||||||
|
@ -183,5 +181,4 @@ void NETLIST_EXPORTER_PSPICE_SIM::writeDirectives( OUTPUTFORMATTER* aFormatter,
|
||||||
// Finish with our custom simulation command
|
// Finish with our custom simulation command
|
||||||
aFormatter->Print( 0, "%s\n", (const char*) m_simCommand.c_str() );
|
aFormatter->Print( 0, "%s\n", (const char*) m_simCommand.c_str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,30 +64,53 @@ public:
|
||||||
*/
|
*/
|
||||||
static const std::vector<wxString>& GetCurrents( SPICE_PRIMITIVE aPrimitive );
|
static const std::vector<wxString>& GetCurrents( SPICE_PRIMITIVE aPrimitive );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Overrides the simulation command directive.
|
||||||
|
*/
|
||||||
void SetSimCommand( const wxString& aCmd )
|
void SetSimCommand( const wxString& aCmd )
|
||||||
{
|
{
|
||||||
m_simCommand = aCmd;
|
m_simCommand = aCmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the simulation command directive.
|
||||||
|
*/
|
||||||
const wxString& GetSimCommand() const
|
const wxString& GetSimCommand() const
|
||||||
{
|
{
|
||||||
return m_simCommand;
|
return m_simCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clears the simulation command directive.
|
||||||
|
*/
|
||||||
void ClearSimCommand()
|
void ClearSimCommand()
|
||||||
{
|
{
|
||||||
m_simCommand.Clear();
|
m_simCommand.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns simulation type basing on the simulation command directives.
|
||||||
|
* Simulation directives set using SetSimCommand() have priority over the ones placed in
|
||||||
|
* schematic sheets.
|
||||||
|
*/
|
||||||
SIM_TYPE GetSimType();
|
SIM_TYPE GetSimType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns simulation command directives placed in schematic sheets (if any).
|
||||||
|
*/
|
||||||
wxString GetSheetSimCommand();
|
wxString GetSheetSimCommand();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Determines if a directive is a simulation command.
|
||||||
|
*/
|
||||||
static bool IsSimCommand( const wxString& aCmd )
|
static bool IsSimCommand( const wxString& aCmd )
|
||||||
{
|
{
|
||||||
return CommandToSimType( aCmd ) != ST_UNKNOWN;
|
return CommandToSimType( aCmd ) != ST_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns simulation type basing on a simulation command directive.
|
||||||
|
*/
|
||||||
static SIM_TYPE CommandToSimType( const wxString& aCmd );
|
static SIM_TYPE CommandToSimType( const wxString& aCmd );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -95,7 +118,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
///> Overridden simulation command
|
///> Custom simulation command (has priority over the schematic sheet simulation commands)
|
||||||
wxString m_simCommand;
|
wxString m_simCommand;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,6 @@ NGSPICE::NGSPICE()
|
||||||
m_ngSpice_AllPlots = (ngSpice_AllPlots) m_dll->GetSymbol( "ngSpice_AllPlots" );
|
m_ngSpice_AllPlots = (ngSpice_AllPlots) m_dll->GetSymbol( "ngSpice_AllPlots" );
|
||||||
m_ngSpice_AllVecs = (ngSpice_AllVecs) m_dll->GetSymbol( "ngSpice_AllVecs" );
|
m_ngSpice_AllVecs = (ngSpice_AllVecs) m_dll->GetSymbol( "ngSpice_AllVecs" );
|
||||||
m_ngSpice_Running = (ngSpice_Running) m_dll->GetSymbol( "ngSpice_running" );
|
m_ngSpice_Running = (ngSpice_Running) m_dll->GetSymbol( "ngSpice_running" );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -243,7 +242,7 @@ bool NGSPICE::LoadNetlist( const string& aNetlist )
|
||||||
bool NGSPICE::Run()
|
bool NGSPICE::Run()
|
||||||
{
|
{
|
||||||
setlocale( LC_ALL, "C" );
|
setlocale( LC_ALL, "C" );
|
||||||
bool rv = Command( "bg_run" );
|
bool rv = Command( "bg_run" ); // bg_* commands execute in a separate thread
|
||||||
setlocale( LC_ALL, "" );
|
setlocale( LC_ALL, "" );
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -252,7 +251,7 @@ bool NGSPICE::Run()
|
||||||
bool NGSPICE::Stop()
|
bool NGSPICE::Stop()
|
||||||
{
|
{
|
||||||
setlocale( LC_ALL, "C" );
|
setlocale( LC_ALL, "C" );
|
||||||
bool rv = Command( "bg_halt" );
|
bool rv = Command( "bg_halt" ); // bg_* commands execute in a separate thread
|
||||||
setlocale( LC_ALL, "" );
|
setlocale( LC_ALL, "" );
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -301,10 +300,11 @@ string NGSPICE::GetXAxis( SIM_TYPE aType ) const
|
||||||
return string( "" );
|
return string( "" );
|
||||||
}
|
}
|
||||||
|
|
||||||
int NGSPICE::cbControlledExit ( int status, bool immediate, bool exit_upon_quit, int id, void *user )
|
|
||||||
|
int NGSPICE::cbControlledExit( int status, bool immediate, bool exit_upon_quit, int id, void* user )
|
||||||
{
|
{
|
||||||
printf("stat %d immed %d quit %d\n", status, !!immediate, !!exit_upon_quit);
|
//printf("stat %d immed %d quit %d\n", status, !!immediate, !!exit_upon_quit);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -36,32 +36,54 @@ public:
|
||||||
NGSPICE();
|
NGSPICE();
|
||||||
virtual ~NGSPICE();
|
virtual ~NGSPICE();
|
||||||
|
|
||||||
|
///> @copydoc SPICE_SIMULATOR::Init()
|
||||||
void Init() override;
|
void Init() override;
|
||||||
|
|
||||||
|
///> @copydoc SPICE_SIMULATOR::LoadNetlist()
|
||||||
bool LoadNetlist( const std::string& aNetlist ) override;
|
bool LoadNetlist( const std::string& aNetlist ) override;
|
||||||
|
|
||||||
|
///> @copydoc SPICE_SIMULATOR::Run()
|
||||||
bool Run() override;
|
bool Run() override;
|
||||||
|
|
||||||
|
///> @copydoc SPICE_SIMULATOR::Stop()
|
||||||
bool Stop() override;
|
bool Stop() override;
|
||||||
|
|
||||||
|
///> @copydoc SPICE_SIMULATOR::IsRunning()
|
||||||
bool IsRunning() override;
|
bool IsRunning() override;
|
||||||
|
|
||||||
|
///> @copydoc SPICE_SIMULATOR::Command()
|
||||||
bool Command( const std::string& aCmd ) override;
|
bool Command( const std::string& aCmd ) override;
|
||||||
|
|
||||||
|
///> @copydoc SPICE_SIMULATOR::GetXAxis()
|
||||||
std::string GetXAxis( SIM_TYPE aType ) const override;
|
std::string GetXAxis( SIM_TYPE aType ) const override;
|
||||||
|
|
||||||
|
///> @copydoc SPICE_SIMULATOR::GetPlot()
|
||||||
std::vector<COMPLEX> GetPlot( const std::string& aName, int aMaxLen = -1 ) override;
|
std::vector<COMPLEX> GetPlot( const std::string& aName, int aMaxLen = -1 ) override;
|
||||||
|
|
||||||
|
///> @copydoc SPICE_SIMULATOR::GetRealPlot()
|
||||||
std::vector<double> GetRealPlot( const std::string& aName, int aMaxLen = -1 ) override;
|
std::vector<double> GetRealPlot( const std::string& aName, int aMaxLen = -1 ) override;
|
||||||
|
|
||||||
|
///> @copydoc SPICE_SIMULATOR::GetImagPlot()
|
||||||
std::vector<double> GetImagPlot( const std::string& aName, int aMaxLen = -1 ) override;
|
std::vector<double> GetImagPlot( const std::string& aName, int aMaxLen = -1 ) override;
|
||||||
|
|
||||||
|
///> @copydoc SPICE_SIMULATOR::GetMagPlot()
|
||||||
std::vector<double> GetMagPlot( const std::string& aName, int aMaxLen = -1 ) override;
|
std::vector<double> GetMagPlot( const std::string& aName, int aMaxLen = -1 ) override;
|
||||||
|
|
||||||
|
///> @copydoc SPICE_SIMULATOR::GetPhasePlot()
|
||||||
std::vector<double> GetPhasePlot( const std::string& aName, int aMaxLen = -1 ) override;
|
std::vector<double> GetPhasePlot( const std::string& aName, int aMaxLen = -1 ) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// ngspice library functions
|
||||||
typedef void (*ngSpice_Init)( SendChar*, SendStat*, ControlledExit*,
|
typedef void (*ngSpice_Init)( SendChar*, SendStat*, ControlledExit*,
|
||||||
SendData*, SendInitData*, BGThreadRunning*, void* );
|
SendData*, SendInitData*, BGThreadRunning*, void* );
|
||||||
|
typedef int (*ngSpice_Circ)( char** circarray );
|
||||||
|
typedef int (*ngSpice_Command)( char* command );
|
||||||
|
typedef pvector_info (*ngGet_Vec_Info)( char* vecname );
|
||||||
|
typedef char** (*ngSpice_AllPlots)( void );
|
||||||
|
typedef char** (*ngSpice_AllVecs)( char* plotname );
|
||||||
|
typedef bool (*ngSpice_Running)( void );
|
||||||
|
|
||||||
// ngspice library functions
|
///> Handles to DLL functions
|
||||||
typedef int (*ngSpice_Circ)(char** circarray);
|
|
||||||
typedef int (*ngSpice_Command)(char* command);
|
|
||||||
typedef pvector_info (*ngGet_Vec_Info)(char* vecname);
|
|
||||||
typedef char** (*ngSpice_AllPlots)(void);
|
|
||||||
typedef char** (*ngSpice_AllVecs)(char* plotname);
|
|
||||||
typedef bool (*ngSpice_Running)(void);
|
|
||||||
|
|
||||||
ngSpice_Init m_ngSpice_Init;
|
ngSpice_Init m_ngSpice_Init;
|
||||||
ngSpice_Circ m_ngSpice_Circ;
|
ngSpice_Circ m_ngSpice_Circ;
|
||||||
ngSpice_Command m_ngSpice_Command;
|
ngSpice_Command m_ngSpice_Command;
|
||||||
|
@ -72,10 +94,11 @@ private:
|
||||||
|
|
||||||
wxDynamicLibrary* m_dll;
|
wxDynamicLibrary* m_dll;
|
||||||
|
|
||||||
|
// Callback functions
|
||||||
static int cbSendChar( char* what, int id, void* user );
|
static int cbSendChar( char* what, int id, void* user );
|
||||||
static int cbSendStat( char* what, int id, void* user );
|
static int cbSendStat( char* what, int id, void* user );
|
||||||
static int cbBGThreadRunning( bool is_running, int id, void* user );
|
static int cbBGThreadRunning( bool is_running, int id, void* user );
|
||||||
static int cbControlledExit ( int status, bool immediate, bool exit_upon_quit, int id, void *user );
|
static int cbControlledExit( int status, bool immediate, bool exit_upon_quit, int id, void* user );
|
||||||
|
|
||||||
void dump();
|
void dump();
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,6 +45,7 @@ SIM_PLOT_TYPE operator|( SIM_PLOT_TYPE aFirst, SIM_PLOT_TYPE aSecond )
|
||||||
return (SIM_PLOT_TYPE) res;
|
return (SIM_PLOT_TYPE) res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class SIM_THREAD_REPORTER : public SPICE_REPORTER
|
class SIM_THREAD_REPORTER : public SPICE_REPORTER
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -117,11 +118,17 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent )
|
||||||
Connect( EVT_SIM_FINISHED, wxCommandEventHandler( SIM_PLOT_FRAME::onSimFinished ), NULL, this );
|
Connect( EVT_SIM_FINISHED, wxCommandEventHandler( SIM_PLOT_FRAME::onSimFinished ), NULL, this );
|
||||||
Connect( EVT_SIM_CURSOR_UPDATE, wxCommandEventHandler( SIM_PLOT_FRAME::onCursorUpdate ), NULL, this );
|
Connect( EVT_SIM_CURSOR_UPDATE, wxCommandEventHandler( SIM_PLOT_FRAME::onCursorUpdate ), NULL, this );
|
||||||
|
|
||||||
m_toolSimulate = m_toolBar->AddTool( ID_SIM_RUN, _("Run/Stop Simulation"), KiBitmap( sim_run_xpm ), _("Run Simulation"), wxITEM_NORMAL );
|
// Toolbar buttons
|
||||||
m_toolAddSignals = m_toolBar->AddTool( ID_SIM_ADD_SIGNALS, _("Add Signals"), KiBitmap( sim_add_signal_xpm ), _("Add signals to plot"), wxITEM_NORMAL );
|
m_toolSimulate = m_toolBar->AddTool( ID_SIM_RUN, _( "Run/Stop Simulation" ),
|
||||||
m_toolProbe = m_toolBar->AddTool( ID_SIM_PROBE, _("Probe"), KiBitmap( sim_probe_xpm ),_("Probe signals on the schematic"), wxITEM_NORMAL );
|
KiBitmap( sim_run_xpm ), _( "Run Simulation" ), wxITEM_NORMAL );
|
||||||
m_toolTune = m_toolBar->AddTool( ID_SIM_TUNE, _("Tune"), KiBitmap( sim_tune_xpm ), _("Tune component values"), wxITEM_NORMAL );
|
m_toolAddSignals = m_toolBar->AddTool( ID_SIM_ADD_SIGNALS, _( "Add Signals" ),
|
||||||
m_toolSettings = m_toolBar->AddTool( wxID_ANY, _("Settings"), KiBitmap( sim_settings_xpm ), _("Simulation settings"), wxITEM_NORMAL );
|
KiBitmap( sim_add_signal_xpm ), _( "Add signals to plot" ), wxITEM_NORMAL );
|
||||||
|
m_toolProbe = m_toolBar->AddTool( ID_SIM_PROBE, _( "Probe" ),
|
||||||
|
KiBitmap( sim_probe_xpm ), _( "Probe signals on the schematic" ), wxITEM_NORMAL );
|
||||||
|
m_toolTune = m_toolBar->AddTool( ID_SIM_TUNE, _( "Tune" ),
|
||||||
|
KiBitmap( sim_tune_xpm ), _( "Tune component values" ), wxITEM_NORMAL );
|
||||||
|
m_toolSettings = m_toolBar->AddTool( wxID_ANY, _( "Settings" ),
|
||||||
|
KiBitmap( sim_settings_xpm ), _( "Simulation settings" ), wxITEM_NORMAL );
|
||||||
|
|
||||||
Connect( m_toolSimulate->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( SIM_PLOT_FRAME::onSimulate ), NULL, this );
|
Connect( m_toolSimulate->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( SIM_PLOT_FRAME::onSimulate ), NULL, this );
|
||||||
Connect( m_toolAddSignals->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( SIM_PLOT_FRAME::onAddSignal ), NULL, this );
|
Connect( m_toolAddSignals->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( SIM_PLOT_FRAME::onAddSignal ), NULL, this );
|
||||||
|
@ -129,6 +136,7 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent )
|
||||||
Connect( m_toolTune->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( SIM_PLOT_FRAME::onTune ), NULL, this );
|
Connect( m_toolTune->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( SIM_PLOT_FRAME::onTune ), NULL, this );
|
||||||
Connect( m_toolSettings->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( SIM_PLOT_FRAME::onSettings ), NULL, this );
|
Connect( m_toolSettings->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( SIM_PLOT_FRAME::onSettings ), NULL, this );
|
||||||
|
|
||||||
|
// Bind toolbar buttons event to existing menu event handlers, so they behave the same
|
||||||
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onSimulate, this, m_runSimulation->GetId() );
|
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onSimulate, this, m_runSimulation->GetId() );
|
||||||
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onAddSignal, this, m_addSignals->GetId() );
|
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onAddSignal, this, m_addSignals->GetId() );
|
||||||
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onProbe, this, m_probeSignals->GetId() );
|
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onProbe, this, m_probeSignals->GetId() );
|
||||||
|
@ -136,7 +144,7 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent )
|
||||||
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onSettings, this, m_settings->GetId() );
|
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onSettings, this, m_settings->GetId() );
|
||||||
|
|
||||||
m_toolBar->Realize();
|
m_toolBar->Realize();
|
||||||
m_plotNotebook->SetPageText(0, _("Welcome!") );
|
m_plotNotebook->SetPageText( 0, _( "Welcome!" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -180,8 +188,6 @@ void SIM_PLOT_FRAME::StartSimulation()
|
||||||
updateTuners();
|
updateTuners();
|
||||||
applyTuners();
|
applyTuners();
|
||||||
m_simulator->Run();
|
m_simulator->Run();
|
||||||
|
|
||||||
Layout();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -746,21 +752,6 @@ void SIM_PLOT_FRAME::menuShowLegendUpdate( wxUpdateUIEvent& event )
|
||||||
event.Check( plot ? plot->IsLegendShown() : false );
|
event.Check( plot ? plot->IsLegendShown() : false );
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
void SIM_PLOT_FRAME::menuShowCoords( wxCommandEvent& event )
|
|
||||||
{
|
|
||||||
SIM_PLOT_PANEL* plot = CurrentPlot();
|
|
||||||
plot->ShowCoords( !plot->IsCoordsShown() );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SIM_PLOT_FRAME::menuShowCoordsUpdate( wxUpdateUIEvent& event )
|
|
||||||
{
|
|
||||||
SIM_PLOT_PANEL* plot = CurrentPlot();
|
|
||||||
event.Check( plot ? plot->IsCoordsShown() : false );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void SIM_PLOT_FRAME::onPlotClose( wxAuiNotebookEvent& event )
|
void SIM_PLOT_FRAME::onPlotClose( wxAuiNotebookEvent& event )
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,7 +27,8 @@
|
||||||
#define __sim_plot_frame__
|
#define __sim_plot_frame__
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@file Subclass of SIM_PLOT_FRAME_BASE, which is generated by wxFormBuilder. */
|
* @file Subclass of SIM_PLOT_FRAME_BASE, which is generated by wxFormBuilder.
|
||||||
|
*/
|
||||||
|
|
||||||
#include "sim_plot_frame_base.h"
|
#include "sim_plot_frame_base.h"
|
||||||
#include "sim_types.h"
|
#include "sim_types.h"
|
||||||
|
@ -49,7 +50,7 @@ class NETLIST_EXPORTER_PSPICE_SIM;
|
||||||
class SIM_PLOT_PANEL;
|
class SIM_PLOT_PANEL;
|
||||||
class TUNER_SLIDER;
|
class TUNER_SLIDER;
|
||||||
|
|
||||||
/// @todo description
|
///> Trace descriptor class
|
||||||
class TRACE_DESC
|
class TRACE_DESC
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -102,191 +103,218 @@ private:
|
||||||
/** Implementing SIM_PLOT_FRAME_BASE */
|
/** Implementing SIM_PLOT_FRAME_BASE */
|
||||||
class SIM_PLOT_FRAME : public SIM_PLOT_FRAME_BASE
|
class SIM_PLOT_FRAME : public SIM_PLOT_FRAME_BASE
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/** Constructor */
|
/** Constructor */
|
||||||
SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent );
|
SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent );
|
||||||
~SIM_PLOT_FRAME();
|
~SIM_PLOT_FRAME();
|
||||||
|
|
||||||
void StartSimulation();
|
void StartSimulation();
|
||||||
void StopSimulation();
|
void StopSimulation();
|
||||||
bool IsSimulationRunning();
|
bool IsSimulationRunning();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a new plot panel for a given simulation type and adds it to the main
|
* @brief Creates a new plot panel for a given simulation type and adds it to the main
|
||||||
* notebook.
|
* notebook.
|
||||||
* @param aSimType is requested simulation type.
|
* @param aSimType is requested simulation type.
|
||||||
* @return The new plot panel.
|
* @return The new plot panel.
|
||||||
*/
|
*/
|
||||||
SIM_PLOT_PANEL* NewPlotPanel( SIM_TYPE aSimType );
|
SIM_PLOT_PANEL* NewPlotPanel( SIM_TYPE aSimType );
|
||||||
|
|
||||||
void AddVoltagePlot( const wxString& aNetName );
|
/**
|
||||||
void AddCurrentPlot( const wxString& aDeviceName, const wxString& aParam );
|
* @brief Adds a voltage plot for a given net name.
|
||||||
|
* @param aNetName is the net name for which a voltage plot should be created.
|
||||||
|
*/
|
||||||
|
void AddVoltagePlot( const wxString& aNetName );
|
||||||
|
|
||||||
void AddTuner( SCH_COMPONENT* aComponent );
|
/**
|
||||||
void RemoveTuner( TUNER_SLIDER* aTuner, bool aErase = true );
|
* @brief Adds a current plot for a particular device.
|
||||||
|
* @param aDeviceName is the device name (e.g. R1, C1).
|
||||||
|
* @param aParam is the current type (e.g. I, Ic, Id).
|
||||||
|
*/
|
||||||
|
void AddCurrentPlot( const wxString& aDeviceName, const wxString& aParam );
|
||||||
|
|
||||||
SIM_PLOT_PANEL* CurrentPlot() const;
|
/**
|
||||||
|
* @brief Adds a tuner for a component.
|
||||||
|
*/
|
||||||
|
void AddTuner( SCH_COMPONENT* aComponent );
|
||||||
|
|
||||||
private:
|
/**
|
||||||
void relayout();
|
* @brief Removes an existing tuner.
|
||||||
/**
|
* @param aTuner is the tuner to be removed.
|
||||||
* @brief Adds a new plot to the current panel.
|
* @param aErase decides whether the tuner should be also removed from the tuners list.
|
||||||
* @param aName is the device/net name.
|
* Otherwise it is removed only from the SIM_PLOT_FRAME pane.
|
||||||
* @param aType describes the type of plot.
|
*/
|
||||||
* @param aParam is the parameter for the device/net (e.g. I, Id, V).
|
void RemoveTuner( TUNER_SLIDER* aTuner, bool aErase = true );
|
||||||
*/
|
|
||||||
void addPlot( const wxString& aName, SIM_PLOT_TYPE aType, const wxString& aParam );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Removes a plot with a specific title.
|
* @brief Returns the currently opened plot panel (or NULL if there is none).
|
||||||
* @param aPlotName is the full plot title (e.g. I(Net-C1-Pad1)).
|
*/
|
||||||
* @param aErase decides if plot should be removed from corresponding TRACE_MAP (see m_plots).
|
SIM_PLOT_PANEL* CurrentPlot() const;
|
||||||
*/
|
|
||||||
void removePlot( const wxString& aPlotName, bool aErase = true );
|
|
||||||
|
|
||||||
void updateNetlistExporter();
|
private:
|
||||||
|
/**
|
||||||
|
* @brief Adds a new plot to the current panel.
|
||||||
|
* @param aName is the device/net name.
|
||||||
|
* @param aType describes the type of plot.
|
||||||
|
* @param aParam is the parameter for the device/net (e.g. I, Id, V).
|
||||||
|
*/
|
||||||
|
void addPlot( const wxString& aName, SIM_PLOT_TYPE aType, const wxString& aParam );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Updates plot in a particular SIM_PLOT_PANEL. If the panel does not contain
|
* @brief Removes a plot with a specific title.
|
||||||
* the plot, it will be added.
|
* @param aPlotName is the full plot title (e.g. I(Net-C1-Pad1)).
|
||||||
* @param aDescriptor contains the plot description.
|
* @param aErase decides if plot should be removed from corresponding TRACE_MAP (see m_plots).
|
||||||
* @param aPanel is the panel that should receive the update.
|
*/
|
||||||
* @return True if a plot was successfully added/updated.
|
void removePlot( const wxString& aPlotName, bool aErase = true );
|
||||||
*/
|
|
||||||
bool updatePlot( const TRACE_DESC& aDescriptor, SIM_PLOT_PANEL* aPanel );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Updates the list of currently plotted signals.
|
* @brief Reloads the current schematic for the netlist exporter.
|
||||||
*/
|
*/
|
||||||
void updateSignalList();
|
void updateNetlistExporter();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Updates the cursor values list.
|
* @brief Updates plot in a particular SIM_PLOT_PANEL. If the panel does not contain
|
||||||
*/
|
* the plot, it will be added.
|
||||||
void updateCursors();
|
* @param aDescriptor contains the plot description.
|
||||||
|
* @param aPanel is the panel that should receive the update.
|
||||||
|
* @return True if a plot was successfully added/updated.
|
||||||
|
*/
|
||||||
|
bool updatePlot( const TRACE_DESC& aDescriptor, SIM_PLOT_PANEL* aPanel );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Filters out tuners for components that do not exist anymore.
|
* @brief Updates the list of currently plotted signals.
|
||||||
* Decisions are based on the current NETLIST_EXPORTER data.
|
*/
|
||||||
*/
|
void updateSignalList();
|
||||||
void updateTuners();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Applies component values specified using tunder sliders to the current netlist.
|
* @brief Updates the cursor values list.
|
||||||
*/
|
*/
|
||||||
void applyTuners();
|
void updateCursors();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Loads plot settings from a file.
|
* @brief Filters out tuners for components that do not exist anymore.
|
||||||
* @param aPath is the file name.
|
* Decisions are based on the current NETLIST_EXPORTER data.
|
||||||
* @return True if successful.
|
*/
|
||||||
*/
|
void updateTuners();
|
||||||
bool loadWorkbook( const wxString& aPath );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Saves plot settings to a file.
|
* @brief Applies component values specified using tunder sliders to the current netlist.
|
||||||
* @param aPath is the file name.
|
*/
|
||||||
* @return True if successful.
|
void applyTuners();
|
||||||
*/
|
|
||||||
bool saveWorkbook( const wxString& aPath );
|
|
||||||
|
|
||||||
SIM_PLOT_TYPE GetXAxisType( SIM_TYPE aType ) const;
|
/**
|
||||||
|
* @brief Loads plot settings from a file.
|
||||||
|
* @param aPath is the file name.
|
||||||
|
* @return True if successful.
|
||||||
|
*/
|
||||||
|
bool loadWorkbook( const wxString& aPath );
|
||||||
|
|
||||||
// Menu handlers
|
/**
|
||||||
void menuNewPlot( wxCommandEvent& aEvent ) override;
|
* @brief Saves plot settings to a file.
|
||||||
void menuOpenWorkbook( wxCommandEvent& event ) override;
|
* @param aPath is the file name.
|
||||||
void menuSaveWorkbook( wxCommandEvent& event ) override;
|
* @return True if successful.
|
||||||
|
*/
|
||||||
|
bool saveWorkbook( const wxString& aPath );
|
||||||
|
|
||||||
void menuExit( wxCommandEvent& event ) override
|
/**
|
||||||
{
|
* @brief Returns X axis for a given simulation type.
|
||||||
Close();
|
*/
|
||||||
}
|
SIM_PLOT_TYPE GetXAxisType( SIM_TYPE aType ) const;
|
||||||
|
|
||||||
void menuSaveImage( wxCommandEvent& event ) override;
|
// Menu handlers
|
||||||
void menuSaveCsv( wxCommandEvent& event ) override;
|
void menuNewPlot( wxCommandEvent& aEvent ) override;
|
||||||
void menuZoomIn( wxCommandEvent& event ) override;
|
void menuOpenWorkbook( wxCommandEvent& event ) override;
|
||||||
void menuZoomOut( wxCommandEvent& event ) override;
|
void menuSaveWorkbook( wxCommandEvent& event ) override;
|
||||||
void menuZoomFit( wxCommandEvent& event ) override;
|
|
||||||
void menuShowGrid( wxCommandEvent& event ) override;
|
|
||||||
void menuShowGridUpdate( wxUpdateUIEvent& event ) override;
|
|
||||||
void menuShowLegend( wxCommandEvent& event ) override;
|
|
||||||
void menuShowLegendUpdate( wxUpdateUIEvent& event ) override;
|
|
||||||
//void menuShowCoords( wxCommandEvent& event ) override;
|
|
||||||
//void menuShowCoordsUpdate( wxUpdateUIEvent& event ) override;
|
|
||||||
|
|
||||||
// Event handlers
|
void menuExit( wxCommandEvent& event ) override
|
||||||
void onPlotChanged( wxAuiNotebookEvent& event ) override;
|
{
|
||||||
void onPlotClose( wxAuiNotebookEvent& event ) override;
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
void onSignalDblClick( wxCommandEvent& event ) override;
|
void menuSaveImage( wxCommandEvent& event ) override;
|
||||||
void onSignalRClick( wxMouseEvent& event ) override;
|
void menuSaveCsv( wxCommandEvent& event ) override;
|
||||||
|
void menuZoomIn( wxCommandEvent& event ) override;
|
||||||
|
void menuZoomOut( wxCommandEvent& event ) override;
|
||||||
|
void menuZoomFit( wxCommandEvent& event ) override;
|
||||||
|
void menuShowGrid( wxCommandEvent& event ) override;
|
||||||
|
void menuShowGridUpdate( wxUpdateUIEvent& event ) override;
|
||||||
|
void menuShowLegend( wxCommandEvent& event ) override;
|
||||||
|
void menuShowLegendUpdate( wxUpdateUIEvent& event ) override;
|
||||||
|
|
||||||
void onSimulate( wxCommandEvent& event );
|
// Event handlers
|
||||||
void onSettings( wxCommandEvent& event );
|
void onPlotChanged( wxAuiNotebookEvent& event ) override;
|
||||||
void onAddSignal( wxCommandEvent& event );
|
void onPlotClose( wxAuiNotebookEvent& event ) override;
|
||||||
void onProbe( wxCommandEvent& event );
|
|
||||||
void onTune( wxCommandEvent& event );
|
|
||||||
|
|
||||||
void onClose( wxCloseEvent& aEvent );
|
void onSignalDblClick( wxCommandEvent& event ) override;
|
||||||
|
void onSignalRClick( wxMouseEvent& event ) override;
|
||||||
|
|
||||||
void onCursorUpdate( wxCommandEvent& aEvent );
|
void onSimulate( wxCommandEvent& event );
|
||||||
void onSimUpdate( wxCommandEvent& aEvent );
|
void onSettings( wxCommandEvent& event );
|
||||||
void onSimReport( wxCommandEvent& aEvent );
|
void onAddSignal( wxCommandEvent& event );
|
||||||
void onSimStarted( wxCommandEvent& aEvent );
|
void onProbe( wxCommandEvent& event );
|
||||||
void onSimFinished( wxCommandEvent& aEvent );
|
void onTune( wxCommandEvent& event );
|
||||||
|
|
||||||
wxToolBarToolBase* m_toolSimulate;
|
void onClose( wxCloseEvent& aEvent );
|
||||||
wxToolBarToolBase* m_toolAddSignals;
|
|
||||||
wxToolBarToolBase* m_toolProbe;
|
|
||||||
wxToolBarToolBase* m_toolTune;
|
|
||||||
wxToolBarToolBase* m_toolSettings;
|
|
||||||
|
|
||||||
SCH_EDIT_FRAME* m_schematicFrame;
|
void onCursorUpdate( wxCommandEvent& aEvent );
|
||||||
std::unique_ptr<NETLIST_EXPORTER_PSPICE_SIM> m_exporter;
|
void onSimUpdate( wxCommandEvent& aEvent );
|
||||||
std::unique_ptr<SPICE_SIMULATOR> m_simulator;
|
void onSimReport( wxCommandEvent& aEvent );
|
||||||
|
void onSimStarted( wxCommandEvent& aEvent );
|
||||||
|
void onSimFinished( wxCommandEvent& aEvent );
|
||||||
|
|
||||||
typedef std::map<wxString, TRACE_DESC> TRACE_MAP;
|
// Toolbar buttons
|
||||||
|
wxToolBarToolBase* m_toolSimulate;
|
||||||
|
wxToolBarToolBase* m_toolAddSignals;
|
||||||
|
wxToolBarToolBase* m_toolProbe;
|
||||||
|
wxToolBarToolBase* m_toolTune;
|
||||||
|
wxToolBarToolBase* m_toolSettings;
|
||||||
|
|
||||||
struct PLOT_INFO
|
SCH_EDIT_FRAME* m_schematicFrame;
|
||||||
{
|
std::unique_ptr<NETLIST_EXPORTER_PSPICE_SIM> m_exporter;
|
||||||
///> Map of the traces displayed on the plot
|
std::unique_ptr<SPICE_SIMULATOR> m_simulator;
|
||||||
TRACE_MAP m_traces;
|
|
||||||
|
|
||||||
///> Spice directive used to execute the simulation
|
typedef std::map<wxString, TRACE_DESC> TRACE_MAP;
|
||||||
wxString m_simCommand;
|
|
||||||
};
|
|
||||||
|
|
||||||
///> Map of plot panels and associated data
|
struct PLOT_INFO
|
||||||
std::map<SIM_PLOT_PANEL*, PLOT_INFO> m_plots;
|
{
|
||||||
|
///> Map of the traces displayed on the plot
|
||||||
|
TRACE_MAP m_traces;
|
||||||
|
|
||||||
///> List of currently displayed tuners
|
///> Spice directive used to execute the simulation
|
||||||
std::list<TUNER_SLIDER*> m_tuners;
|
wxString m_simCommand;
|
||||||
|
};
|
||||||
|
|
||||||
// Trick to preserve settings between runs
|
///> Map of plot panels and associated data
|
||||||
DIALOG_SIM_SETTINGS m_settingsDlg;
|
std::map<SIM_PLOT_PANEL*, PLOT_INFO> m_plots;
|
||||||
|
|
||||||
// Right click context menu for signals in the listbox
|
///> List of currently displayed tuners
|
||||||
class SIGNAL_CONTEXT_MENU : public wxMenu
|
std::list<TUNER_SLIDER*> m_tuners;
|
||||||
{
|
|
||||||
public:
|
|
||||||
SIGNAL_CONTEXT_MENU( const wxString& aSignal, SIM_PLOT_FRAME* aPlotFrame );
|
|
||||||
|
|
||||||
private:
|
// Trick to preserve settings between runs
|
||||||
void onMenuEvent( wxMenuEvent& aEvent );
|
DIALOG_SIM_SETTINGS m_settingsDlg;
|
||||||
|
|
||||||
const wxString& m_signal;
|
// Right click context menu for signals in the listbox
|
||||||
SIM_PLOT_FRAME* m_plotFrame;
|
class SIGNAL_CONTEXT_MENU : public wxMenu
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SIGNAL_CONTEXT_MENU( const wxString& aSignal, SIM_PLOT_FRAME* aPlotFrame );
|
||||||
|
|
||||||
enum SIGNAL_CONTEXT_MENU_EVENTS
|
private:
|
||||||
{
|
void onMenuEvent( wxMenuEvent& aEvent );
|
||||||
HIDE_SIGNAL,
|
|
||||||
SHOW_CURSOR,
|
|
||||||
HIDE_CURSOR
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
///> Panel that was used as the most recent one for simulations
|
const wxString& m_signal;
|
||||||
SIM_PLOT_PANEL* m_lastSimPlot;
|
SIM_PLOT_FRAME* m_plotFrame;
|
||||||
|
|
||||||
|
enum SIGNAL_CONTEXT_MENU_EVENTS
|
||||||
|
{
|
||||||
|
HIDE_SIGNAL,
|
||||||
|
SHOW_CURSOR,
|
||||||
|
HIDE_CURSOR
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
///> Panel that was used as the most recent one for simulations
|
||||||
|
SIM_PLOT_PANEL* m_lastSimPlot;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
|
|
|
@ -28,80 +28,88 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
static wxString formatFloat (double x, int nDigits)
|
static wxString formatFloat( double x, int nDigits )
|
||||||
{
|
{
|
||||||
wxString rv, fmt;
|
wxString rv, fmt;
|
||||||
|
|
||||||
if(nDigits)
|
if( nDigits )
|
||||||
{
|
{
|
||||||
fmt = wxT("%.0Nf");
|
fmt = wxT( "%.0Nf" );
|
||||||
fmt[3] = '0' + nDigits;
|
fmt[3] = '0' + nDigits;
|
||||||
} else {
|
}
|
||||||
fmt = wxT("%.0f");
|
else
|
||||||
|
{
|
||||||
|
fmt = wxT( "%.0f" );
|
||||||
}
|
}
|
||||||
|
|
||||||
rv.Printf(fmt, x);
|
rv.Printf( fmt, x );
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void getSISuffix ( double x, const wxString& unit, int& power, wxString& suffix )
|
|
||||||
|
static void getSISuffix( double x, const wxString& unit, int& power, wxString& suffix )
|
||||||
{
|
{
|
||||||
const int n_powers = 11;
|
const int n_powers = 11;
|
||||||
const struct {
|
|
||||||
|
const struct
|
||||||
|
{
|
||||||
double exponent;
|
double exponent;
|
||||||
char suffix;
|
char suffix;
|
||||||
} powers[] = {
|
} powers[] =
|
||||||
{-18,'a'},
|
{
|
||||||
{-15,'f'},
|
{ -18, 'a' },
|
||||||
{-12,'p'},
|
{ -15, 'f' },
|
||||||
{-9,'n'},
|
{ -12, 'p' },
|
||||||
{-6,'u'},
|
{ -9, 'n' },
|
||||||
{-3,'m'},
|
{ -6, 'u' },
|
||||||
{0, 0},
|
{ -3, 'm' },
|
||||||
{3, 'k'},
|
{ 0, 0 },
|
||||||
{6, 'M'},
|
{ 3, 'k' },
|
||||||
{9, 'G'},
|
{ 6, 'M' },
|
||||||
{12, 'T'},
|
{ 9, 'G' },
|
||||||
{15, 'P'}
|
{ 12, 'T' },
|
||||||
|
{ 14, 'P' }
|
||||||
};
|
};
|
||||||
|
|
||||||
power = 0;
|
power = 0;
|
||||||
suffix = unit;
|
suffix = unit;
|
||||||
|
|
||||||
if (x == 0.0)
|
if( x == 0.0 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for ( int i = 0; i <n_powers - 1;i++)
|
for( int i = 0; i < n_powers - 1; i++ )
|
||||||
{
|
{
|
||||||
double r_cur = pow(10, powers[i].exponent);
|
double r_cur = pow( 10, powers[i].exponent );
|
||||||
|
|
||||||
if( fabs(x) >= r_cur && fabs(x) < r_cur * 1000.0 )
|
if( fabs( x ) >= r_cur && fabs( x ) < r_cur * 1000.0 )
|
||||||
{
|
{
|
||||||
power = powers[i].exponent;
|
power = powers[i].exponent;
|
||||||
if ( powers[i].suffix )
|
|
||||||
suffix = wxString(powers[i].suffix) + unit;
|
if( powers[i].suffix )
|
||||||
|
suffix = wxString( powers[i].suffix ) + unit;
|
||||||
else
|
else
|
||||||
suffix = unit;
|
suffix = unit;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int countDecimalDigits ( double x, int maxDigits )
|
|
||||||
|
static int countDecimalDigits( double x, int maxDigits )
|
||||||
{
|
{
|
||||||
int64_t k = (int) ( ( x - floor(x)) * pow ( 10.0, (double) maxDigits ));
|
int64_t k = (int)( ( x - floor( x ) ) * pow( 10.0, (double) maxDigits ) );
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
while(k && ((k % 10LL) == 0LL || (k % 10LL) == 9LL))
|
while( k && ( ( k % 10LL ) == 0LL || ( k % 10LL ) == 9LL ) )
|
||||||
{
|
{
|
||||||
k /= 10LL;
|
k /= 10LL;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
|
|
||||||
while (k != 0LL)
|
while( k != 0LL )
|
||||||
{
|
{
|
||||||
n++;
|
n++;
|
||||||
k /= 10LL;
|
k /= 10LL;
|
||||||
|
@ -111,64 +119,66 @@ static int countDecimalDigits ( double x, int maxDigits )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void formatSILabels( mpScaleBase *scale, const wxString& aUnit, int nDigits )
|
static void formatSILabels( mpScaleBase* scale, const wxString& aUnit, int nDigits )
|
||||||
{
|
{
|
||||||
double maxVis = scale->AbsVisibleMaxValue();
|
double maxVis = scale->AbsVisibleMaxValue();
|
||||||
|
|
||||||
wxString suffix;
|
wxString suffix;
|
||||||
int power, digits = 0;
|
int power, digits = 0;
|
||||||
|
|
||||||
getSISuffix( maxVis, aUnit, power, suffix);
|
getSISuffix( maxVis, aUnit, power, suffix );
|
||||||
|
|
||||||
double sf = pow(10.0, power);
|
double sf = pow( 10.0, power );
|
||||||
|
|
||||||
for ( auto &l : scale->TickLabels() )
|
for( auto &l : scale->TickLabels() )
|
||||||
{
|
{
|
||||||
int k = countDecimalDigits( l.pos / sf, nDigits );
|
int k = countDecimalDigits( l.pos / sf, nDigits );
|
||||||
|
|
||||||
digits = std::max(digits, k);
|
digits = std::max( digits, k );
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( auto &l : scale->TickLabels() )
|
for( auto &l : scale->TickLabels() )
|
||||||
{
|
{
|
||||||
l.label = formatFloat ( l.pos / sf, digits ) + suffix;
|
l.label = formatFloat ( l.pos / sf, digits ) + suffix;
|
||||||
l.visible = true;
|
l.visible = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class FREQUENCY_LOG_SCALE : public mpScaleXLog
|
class FREQUENCY_LOG_SCALE : public mpScaleXLog
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FREQUENCY_LOG_SCALE(wxString name, int flags) :
|
FREQUENCY_LOG_SCALE( wxString name, int flags ) :
|
||||||
mpScaleXLog( name, flags ) {};
|
mpScaleXLog( name, flags ) {};
|
||||||
|
|
||||||
void formatLabels()
|
void formatLabels()
|
||||||
{
|
{
|
||||||
const wxString unit = wxT("Hz");
|
const wxString unit = wxT( "Hz" );
|
||||||
wxString suffix;
|
wxString suffix;
|
||||||
int power;
|
int power;
|
||||||
|
|
||||||
for ( auto &l : TickLabels() )
|
for( auto &l : TickLabels() )
|
||||||
{
|
{
|
||||||
getSISuffix( l.pos, unit, power, suffix);
|
getSISuffix( l.pos, unit, power, suffix );
|
||||||
double sf = pow(10.0, power);
|
double sf = pow( 10.0, power );
|
||||||
int k = countDecimalDigits( l.pos / sf, 3 );
|
int k = countDecimalDigits( l.pos / sf, 3 );
|
||||||
|
|
||||||
l.label = formatFloat ( l.pos / sf, k ) + suffix;
|
l.label = formatFloat( l.pos / sf, k ) + suffix;
|
||||||
l.visible = true;
|
l.visible = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class FREQUENCY_LIN_SCALE : public mpScaleX
|
class FREQUENCY_LIN_SCALE : public mpScaleX
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FREQUENCY_LIN_SCALE(wxString name, int flags) :
|
FREQUENCY_LIN_SCALE( wxString name, int flags ) :
|
||||||
mpScaleX( name, flags, false , 0 ) {};
|
mpScaleX( name, flags, false , 0 ) {};
|
||||||
|
|
||||||
void formatLabels()
|
void formatLabels()
|
||||||
{
|
{
|
||||||
formatSILabels( this, wxT("Hz"), 3 );
|
formatSILabels( this, wxT( "Hz" ), 3 );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -176,74 +186,78 @@ public:
|
||||||
class TIME_SCALE : public mpScaleX
|
class TIME_SCALE : public mpScaleX
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TIME_SCALE(wxString name, int flags) :
|
TIME_SCALE( wxString name, int flags ) :
|
||||||
mpScaleX ( name, flags, false, 0) {};
|
mpScaleX( name, flags, false, 0 ) {};
|
||||||
|
|
||||||
void formatLabels()
|
void formatLabels()
|
||||||
{
|
{
|
||||||
formatSILabels( this, wxT("s"), 3 );
|
formatSILabels( this, wxT( "s" ), 3 );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class VOLTAGE_SCALE_X : public mpScaleX
|
class VOLTAGE_SCALE_X : public mpScaleX
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VOLTAGE_SCALE_X(wxString name, int flags) :
|
VOLTAGE_SCALE_X( wxString name, int flags ) :
|
||||||
mpScaleX ( name, flags, false, 0 ) {};
|
mpScaleX( name, flags, false, 0 ) {};
|
||||||
|
|
||||||
void formatLabels()
|
void formatLabels()
|
||||||
{
|
{
|
||||||
formatSILabels( this, wxT("V"), 3 );
|
formatSILabels( this, wxT( "V" ), 3 );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class GAIN_SCALE : public mpScaleY
|
class GAIN_SCALE : public mpScaleY
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GAIN_SCALE( wxString name, int flags ) :
|
GAIN_SCALE( wxString name, int flags ) :
|
||||||
mpScaleY ( name, flags, false) {};
|
mpScaleY( name, flags, false ) {};
|
||||||
|
|
||||||
void formatLabels()
|
void formatLabels()
|
||||||
{
|
{
|
||||||
formatSILabels( this, wxT("dB"), 3 );
|
formatSILabels( this, wxT( "dB" ), 3 );
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class PHASE_SCALE : public mpScaleY
|
class PHASE_SCALE : public mpScaleY
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PHASE_SCALE(wxString name, int flags) :
|
PHASE_SCALE( wxString name, int flags ) :
|
||||||
mpScaleY ( name, flags, false ) {};
|
mpScaleY( name, flags, false ) {};
|
||||||
|
|
||||||
void formatLabels()
|
void formatLabels()
|
||||||
{
|
{
|
||||||
formatSILabels( this, wxT("\u00B0"), 3 );
|
formatSILabels( this, wxT( "\u00B0" ), 3 ); // degree sign
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class VOLTAGE_SCALE_Y : public mpScaleY
|
class VOLTAGE_SCALE_Y : public mpScaleY
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VOLTAGE_SCALE_Y(wxString name, int flags) :
|
VOLTAGE_SCALE_Y( wxString name, int flags ) :
|
||||||
mpScaleY ( name, flags, false ) {};
|
mpScaleY( name, flags, false ) {};
|
||||||
|
|
||||||
void formatLabels()
|
void formatLabels()
|
||||||
{
|
{
|
||||||
formatSILabels( this, wxT("V"), 3 );
|
formatSILabels( this, wxT( "V" ), 3 );
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class CURRENT_SCALE : public mpScaleY
|
class CURRENT_SCALE : public mpScaleY
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CURRENT_SCALE(wxString name, int flags ) :
|
CURRENT_SCALE( wxString name, int flags ) :
|
||||||
mpScaleY ( name, flags, false ) {};
|
mpScaleY( name, flags, false ) {};
|
||||||
|
|
||||||
void formatLabels()
|
void formatLabels()
|
||||||
{
|
{
|
||||||
formatSILabels( this, wxT("A"), 3 );
|
formatSILabels( this, wxT( "A" ), 3 );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -366,7 +380,7 @@ SIM_PLOT_PANEL::SIM_PLOT_PANEL( SIM_TYPE aType, wxWindow* parent, wxWindowID id,
|
||||||
m_axis_x = new FREQUENCY_LOG_SCALE( wxT( "Frequency" ), mpALIGN_BOTTOM );
|
m_axis_x = new FREQUENCY_LOG_SCALE( wxT( "Frequency" ), mpALIGN_BOTTOM );
|
||||||
m_axis_y1 = new GAIN_SCALE( wxT( "Gain" ), mpALIGN_LEFT );
|
m_axis_y1 = new GAIN_SCALE( wxT( "Gain" ), mpALIGN_LEFT );
|
||||||
m_axis_y2 = new PHASE_SCALE( wxT( "Phase" ), mpALIGN_RIGHT );
|
m_axis_y2 = new PHASE_SCALE( wxT( "Phase" ), mpALIGN_RIGHT );
|
||||||
m_axis_y2->SetMasterScale(m_axis_y1);
|
m_axis_y2->SetMasterScale( m_axis_y1 );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ST_DC:
|
case ST_DC:
|
||||||
|
@ -383,7 +397,7 @@ SIM_PLOT_PANEL::SIM_PLOT_PANEL( SIM_TYPE aType, wxWindow* parent, wxWindowID id,
|
||||||
m_axis_x = new TIME_SCALE( wxT( "Time" ), mpALIGN_BOTTOM );
|
m_axis_x = new TIME_SCALE( wxT( "Time" ), mpALIGN_BOTTOM );
|
||||||
m_axis_y1 = new VOLTAGE_SCALE_Y( wxT( "Voltage" ), mpALIGN_LEFT );
|
m_axis_y1 = new VOLTAGE_SCALE_Y( wxT( "Voltage" ), mpALIGN_LEFT );
|
||||||
m_axis_y2 = new CURRENT_SCALE( wxT( "Current" ), mpALIGN_RIGHT );
|
m_axis_y2 = new CURRENT_SCALE( wxT( "Current" ), mpALIGN_RIGHT );
|
||||||
m_axis_y2->SetMasterScale(m_axis_y1);
|
m_axis_y2->SetMasterScale( m_axis_y1 );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -416,9 +430,9 @@ SIM_PLOT_PANEL::SIM_PLOT_PANEL( SIM_TYPE aType, wxWindow* parent, wxWindowID id,
|
||||||
m_legend = new mpInfoLegend( wxRect( 0, 40, 200, 40 ), wxTRANSPARENT_BRUSH );
|
m_legend = new mpInfoLegend( wxRect( 0, 40, 200, 40 ), wxTRANSPARENT_BRUSH );
|
||||||
AddLayer( m_legend );
|
AddLayer( m_legend );
|
||||||
m_topLevel.push_back( m_legend );
|
m_topLevel.push_back( m_legend );
|
||||||
SetColourTheme(*wxBLACK, *wxWHITE, grey);
|
SetColourTheme( *wxBLACK, *wxWHITE, grey );
|
||||||
|
|
||||||
EnableDoubleBuffer(true);
|
EnableDoubleBuffer( true );
|
||||||
UpdateAll();
|
UpdateAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,20 +469,20 @@ bool SIM_PLOT_PANEL::AddTrace( const wxString& aName, int aPoints,
|
||||||
|
|
||||||
if( addedNewEntry )
|
if( addedNewEntry )
|
||||||
{
|
{
|
||||||
if ( m_type == ST_TRANSIENT )
|
if( m_type == ST_TRANSIENT )
|
||||||
{
|
{
|
||||||
bool hasVoltageTraces = false;
|
bool hasVoltageTraces = false;
|
||||||
|
|
||||||
for( auto t : m_traces )
|
for( auto t : m_traces )
|
||||||
{
|
{
|
||||||
if ( ! (t.second->GetFlags() & SPT_CURRENT ) )
|
if( !( t.second->GetFlags() & SPT_CURRENT ) )
|
||||||
{
|
{
|
||||||
hasVoltageTraces = true;
|
hasVoltageTraces = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !hasVoltageTraces )
|
if( !hasVoltageTraces )
|
||||||
m_axis_y2->SetMasterScale( nullptr );
|
m_axis_y2->SetMasterScale( nullptr );
|
||||||
else
|
else
|
||||||
m_axis_y2->SetMasterScale( m_axis_y1 );
|
m_axis_y2->SetMasterScale( m_axis_y1 );
|
||||||
|
@ -499,12 +513,12 @@ bool SIM_PLOT_PANEL::AddTrace( const wxString& aName, int aPoints,
|
||||||
{
|
{
|
||||||
if( aFlags & SPT_AC_PHASE )
|
if( aFlags & SPT_AC_PHASE )
|
||||||
{
|
{
|
||||||
for(int i = 0; i < aPoints; i++ )
|
for( int i = 0; i < aPoints; i++ )
|
||||||
tmp[i] = tmp[i] * 180.0 / M_PI; // convert to degrees
|
tmp[i] = tmp[i] * 180.0 / M_PI; // convert to degrees
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for(int i = 0; i < aPoints; i++ )
|
for( int i = 0; i < aPoints; i++ )
|
||||||
tmp[i] = 20 * log( tmp[i] ) / log( 10.0 ); // convert to dB
|
tmp[i] = 20 * log( tmp[i] ) / log( 10.0 ); // convert to dB
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -553,6 +567,7 @@ void SIM_PLOT_PANEL::DeleteAllTraces()
|
||||||
DeleteTrace( t.first );
|
DeleteTrace( t.first );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_colorIdx = 0;
|
||||||
m_traces.clear();
|
m_traces.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
|
|
||||||
class TRACE;
|
class TRACE;
|
||||||
|
|
||||||
|
///> Cursor attached to a trace to follow its values:
|
||||||
class CURSOR : public mpInfoLayer
|
class CURSOR : public mpInfoLayer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -86,14 +87,18 @@ class TRACE : public mpFXYVector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TRACE( const wxString& aName ) :
|
TRACE( const wxString& aName ) :
|
||||||
mpFXYVector( aName ), m_cursor( nullptr ), m_flags(0)
|
mpFXYVector( aName ), m_cursor( nullptr ), m_flags( 0 )
|
||||||
{
|
{
|
||||||
SetContinuity( true );
|
SetContinuity( true );
|
||||||
SetDrawOutsideMargins( false );
|
SetDrawOutsideMargins( false );
|
||||||
ShowName( false );
|
ShowName( false );
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Assigns new data set for the trace. aX and aY need to have the same length.
|
||||||
|
* @param aX are the X axis values.
|
||||||
|
* @param aY are the Y axis values.
|
||||||
|
*/
|
||||||
void SetData( const std::vector<double>& aX, const std::vector<double>& aY ) override
|
void SetData( const std::vector<double>& aX, const std::vector<double>& aY ) override
|
||||||
{
|
{
|
||||||
if( m_cursor )
|
if( m_cursor )
|
||||||
|
@ -127,7 +132,7 @@ public:
|
||||||
return m_cursor;
|
return m_cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFlags ( int aFlags )
|
void SetFlags( int aFlags )
|
||||||
{
|
{
|
||||||
m_flags = aFlags;
|
m_flags = aFlags;
|
||||||
}
|
}
|
||||||
|
@ -222,26 +227,20 @@ public:
|
||||||
return m_legend->IsVisible();
|
return m_legend->IsVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowCoords( bool aEnable )
|
///> Returns true if the trace has cursor shown.
|
||||||
{
|
|
||||||
m_coords->SetVisible( aEnable );
|
|
||||||
UpdateAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsCoordsShown() const
|
|
||||||
{
|
|
||||||
return m_coords->IsVisible();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HasCursorEnabled( const wxString& aName ) const;
|
bool HasCursorEnabled( const wxString& aName ) const;
|
||||||
|
|
||||||
|
///> Toggles cursor for a particular trace.
|
||||||
void EnableCursor( const wxString& aName, bool aEnable );
|
void EnableCursor( const wxString& aName, bool aEnable );
|
||||||
|
|
||||||
|
///> Resets scale ranges to fit the current traces
|
||||||
void ResetScales();
|
void ResetScales();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
///> Returns a new color from the palette
|
||||||
wxColour generateColor();
|
wxColour generateColor();
|
||||||
|
|
||||||
|
// Color index to get a new color from the palette
|
||||||
unsigned int m_colorIdx;
|
unsigned int m_colorIdx;
|
||||||
|
|
||||||
// Traces to be plotted
|
// Traces to be plotted
|
||||||
|
@ -251,7 +250,6 @@ private:
|
||||||
mpScaleY* m_axis_y1;
|
mpScaleY* m_axis_y1;
|
||||||
mpScaleY* m_axis_y2;
|
mpScaleY* m_axis_y2;
|
||||||
mpInfoLegend* m_legend;
|
mpInfoLegend* m_legend;
|
||||||
mpInfoCoords* m_coords;
|
|
||||||
|
|
||||||
std::vector<mpLayer*> m_topLevel;
|
std::vector<mpLayer*> m_topLevel;
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ enum SIM_PLOT_TYPE {
|
||||||
SPT_AC_PHASE = 0x04,
|
SPT_AC_PHASE = 0x04,
|
||||||
SPT_AC_MAG = 0x08,
|
SPT_AC_MAG = 0x08,
|
||||||
|
|
||||||
|
// X axis
|
||||||
SPT_TIME = 0x10,
|
SPT_TIME = 0x10,
|
||||||
SPT_LIN_FREQUENCY = 0x20,
|
SPT_LIN_FREQUENCY = 0x20,
|
||||||
SPT_LOG_FREQUENCY = 0x20,
|
SPT_LOG_FREQUENCY = 0x20,
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
#include <schframe.h>
|
|
||||||
|
|
||||||
void SCH_EDIT_FRAME::OnSimulationRun( wxCommandEvent& event )
|
|
||||||
{}
|
|
||||||
|
|
||||||
void SCH_EDIT_FRAME::OnSimulationStop( wxCommandEvent& event )
|
|
||||||
{}
|
|
||||||
|
|
||||||
void SCH_EDIT_FRAME::OnSimulationAddProbe( wxCommandEvent& event )
|
|
||||||
{}
|
|
||||||
|
|
|
@ -41,31 +41,91 @@ public:
|
||||||
SPICE_SIMULATOR() : m_reporter( NULL ) {}
|
SPICE_SIMULATOR() : m_reporter( NULL ) {}
|
||||||
virtual ~SPICE_SIMULATOR() {}
|
virtual ~SPICE_SIMULATOR() {}
|
||||||
|
|
||||||
|
///> Creates a simulator instance of particular type (currently only ngspice is handled)
|
||||||
static SPICE_SIMULATOR* CreateInstance( const std::string& aName );
|
static SPICE_SIMULATOR* CreateInstance( const std::string& aName );
|
||||||
|
|
||||||
|
///> Intializes the simulator
|
||||||
virtual void Init() = 0;
|
virtual void Init() = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief Loads a netlist for the simulation.
|
||||||
|
* @return True in case of success, false otherwise.
|
||||||
|
*/
|
||||||
virtual bool LoadNetlist( const std::string& aNetlist ) = 0;
|
virtual bool LoadNetlist( const std::string& aNetlist ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Executes the simulation with currently loaded netlist.
|
||||||
|
* @return True in case of success, false otherwise.
|
||||||
|
*/
|
||||||
virtual bool Run() = 0;
|
virtual bool Run() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Halts the simulation.
|
||||||
|
* @return True in case of success, false otherwise.
|
||||||
|
*/
|
||||||
virtual bool Stop() = 0;
|
virtual bool Stop() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if simulation is running at the moment.
|
||||||
|
* @return True if simulation is currently executed.
|
||||||
|
*/
|
||||||
virtual bool IsRunning() = 0;
|
virtual bool IsRunning() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Executes a Spice command as if it was typed into console.
|
||||||
|
* @param aCmd is the command to be issued.
|
||||||
|
*/
|
||||||
virtual bool Command( const std::string& aCmd ) = 0;
|
virtual bool Command( const std::string& aCmd ) = 0;
|
||||||
|
|
||||||
///> Returns X axis name for a given simulation type
|
///> Returns X axis name for a given simulation type
|
||||||
virtual std::string GetXAxis( SIM_TYPE aType ) const = 0;
|
virtual std::string GetXAxis( SIM_TYPE aType ) const = 0;
|
||||||
|
|
||||||
|
///> Sets a SPICE_REPORTER object to receive the simulation log.
|
||||||
virtual void SetReporter( SPICE_REPORTER* aReporter )
|
virtual void SetReporter( SPICE_REPORTER* aReporter )
|
||||||
{
|
{
|
||||||
m_reporter = aReporter;
|
m_reporter = aReporter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a requested vector with complex values. If the vector is real, then
|
||||||
|
* the imaginary part is set to 0 in all values.
|
||||||
|
* @param aName is the vector named in Spice convention (e.g. V(3), I(R1)).
|
||||||
|
* @return Requested vector. It might be empty if there is no vector with requested name.
|
||||||
|
*/
|
||||||
virtual std::vector<COMPLEX> GetPlot( const std::string& aName, int aMaxLen = -1 ) = 0;
|
virtual std::vector<COMPLEX> GetPlot( const std::string& aName, int aMaxLen = -1 ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a requested vector with real values. If the vector is complex, then
|
||||||
|
* the real part is returned.
|
||||||
|
* @param aName is the vector named in Spice convention (e.g. V(3), I(R1)).
|
||||||
|
* @return Requested vector. It might be empty if there is no vector with requested name.
|
||||||
|
*/
|
||||||
virtual std::vector<double> GetRealPlot( const std::string& aName, int aMaxLen = -1 ) = 0;
|
virtual std::vector<double> GetRealPlot( const std::string& aName, int aMaxLen = -1 ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a requested vector with imaginary values. If the vector is complex, then
|
||||||
|
* the imaginary part is returned. If the vector is reql, then only zeroes are returned.
|
||||||
|
* @param aName is the vector named in Spice convention (e.g. V(3), I(R1)).
|
||||||
|
* @return Requested vector. It might be empty if there is no vector with requested name.
|
||||||
|
*/
|
||||||
virtual std::vector<double> GetImagPlot( const std::string& aName, int aMaxLen = -1 ) = 0;
|
virtual std::vector<double> GetImagPlot( const std::string& aName, int aMaxLen = -1 ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a requested vector with magnitude values.
|
||||||
|
* @param aName is the vector named in Spice convention (e.g. V(3), I(R1)).
|
||||||
|
* @return Requested vector. It might be empty if there is no vector with requested name.
|
||||||
|
*/
|
||||||
virtual std::vector<double> GetMagPlot( const std::string& aName, int aMaxLen = -1 ) = 0;
|
virtual std::vector<double> GetMagPlot( const std::string& aName, int aMaxLen = -1 ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a requested vector with phase values.
|
||||||
|
* @param aName is the vector named in Spice convention (e.g. V(3), I(R1)).
|
||||||
|
* @return Requested vector. It might be empty if there is no vector with requested name.
|
||||||
|
*/
|
||||||
virtual std::vector<double> GetPhasePlot( const std::string& aName, int aMaxLen = -1 ) = 0;
|
virtual std::vector<double> GetPhasePlot( const std::string& aName, int aMaxLen = -1 ) = 0;
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
///> Reporter object to receive simulation log
|
||||||
SPICE_REPORTER* m_reporter;
|
SPICE_REPORTER* m_reporter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -221,13 +221,13 @@ SPICE_VALUE SPICE_VALUE::operator/( const SPICE_VALUE& aOther ) const
|
||||||
|
|
||||||
void SPICE_VALUE::stripZeros( wxString& aString )
|
void SPICE_VALUE::stripZeros( wxString& aString )
|
||||||
{
|
{
|
||||||
if ( aString.Find(',') >= 0 || aString.Find('.') >= 0 )
|
if ( aString.Find( ',' ) >= 0 || aString.Find( '.' ) >= 0 )
|
||||||
{
|
{
|
||||||
while( aString.EndsWith( '0' ) )
|
while( aString.EndsWith( '0' ) )
|
||||||
aString.RemoveLast();
|
aString.RemoveLast();
|
||||||
|
|
||||||
if( aString.EndsWith( '.' ) || aString.EndsWith( ',' ) )
|
if( aString.EndsWith( '.' ) || aString.EndsWith( ',' ) )
|
||||||
aString.RemoveLast();
|
aString.RemoveLast();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///> Parses the string to create a Spice value (e.g. 100n)
|
||||||
SPICE_VALUE( const wxString& aString );
|
SPICE_VALUE( const wxString& aString );
|
||||||
|
|
||||||
SPICE_VALUE( int aInt, UNIT_PREFIX aPrefix = PFX_NONE )
|
SPICE_VALUE( int aInt, UNIT_PREFIX aPrefix = PFX_NONE )
|
||||||
|
@ -65,19 +66,35 @@ public:
|
||||||
Normalize();
|
Normalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Normalizes the value. The unit prefix is picked so the base is (0.001 <= base < 1000).
|
||||||
|
*/
|
||||||
void Normalize();
|
void Normalize();
|
||||||
|
|
||||||
double ToDouble() const;
|
double ToDouble() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns string value as when converting double to string (e.g. 123456.789).
|
||||||
|
*/
|
||||||
wxString ToString() const;
|
wxString ToString() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns string value in Spice format (e.g. 123.3456789k).
|
||||||
|
*/
|
||||||
wxString ToSpiceString() const;
|
wxString ToSpiceString() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns either a normal string or Spice format string, depending on the original
|
||||||
|
* value format.
|
||||||
|
*/
|
||||||
wxString ToOrigString() const
|
wxString ToOrigString() const
|
||||||
{
|
{
|
||||||
return m_spiceStr ? ToSpiceString() : ToString();
|
return m_spiceStr ? ToSpiceString() : ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the object was initiated with a Spice formatted string value.
|
||||||
|
*/
|
||||||
bool IsSpiceString() const
|
bool IsSpiceString() const
|
||||||
{
|
{
|
||||||
return m_spiceStr;
|
return m_spiceStr;
|
||||||
|
@ -120,6 +137,7 @@ private:
|
||||||
///> Was the value defined using the Spice notation?
|
///> Was the value defined using the Spice notation?
|
||||||
bool m_spiceStr;
|
bool m_spiceStr;
|
||||||
|
|
||||||
|
///> Removes redundant zeros from the end of a string.
|
||||||
static void stripZeros( wxString& aString );
|
static void stripZeros( wxString& aString );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -141,6 +159,7 @@ public:
|
||||||
bool Validate( wxWindow* aParent ) override;
|
bool Validate( wxWindow* aParent ) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
///> Is it valid to get an empty value?
|
||||||
bool m_emptyAllowed;
|
bool m_emptyAllowed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue