From eeeb3e0a9a0d51dbd2b53dee5a7284fecdc58a00 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 11 Aug 2016 14:42:17 +0200 Subject: [PATCH] Simulator code formatting and clean up --- eeschema/sim/netlist_exporter_pspice_sim.cpp | 3 - eeschema/sim/netlist_exporter_pspice_sim.h | 25 +- eeschema/sim/ngspice.cpp | 12 +- eeschema/sim/ngspice.h | 41 ++- eeschema/sim/sim_plot_frame.cpp | 37 +-- eeschema/sim/sim_plot_frame.h | 328 ++++++++++--------- eeschema/sim/sim_plot_panel.cpp | 161 ++++----- eeschema/sim/sim_plot_panel.h | 38 +-- eeschema/sim/sim_types.h | 1 + eeschema/sim/simulate.h | 11 - eeschema/sim/spice_simulator.h | 62 +++- eeschema/sim/spice_value.cpp | 4 +- eeschema/sim/spice_value.h | 19 ++ 13 files changed, 443 insertions(+), 299 deletions(-) delete mode 100644 eeschema/sim/simulate.h diff --git a/eeschema/sim/netlist_exporter_pspice_sim.cpp b/eeschema/sim/netlist_exporter_pspice_sim.cpp index 1e5ca02435..516618e8c7 100644 --- a/eeschema/sim/netlist_exporter_pspice_sim.cpp +++ b/eeschema/sim/netlist_exporter_pspice_sim.cpp @@ -44,8 +44,6 @@ wxString NETLIST_EXPORTER_PSPICE_SIM::GetSpiceVector( const wxString& aName, SIM return wxString::Format( "V(%d)", it->second ); } - - /// @todo check is Lower() is required else if( aType & SPT_CURRENT ) { 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 aFormatter->Print( 0, "%s\n", (const char*) m_simCommand.c_str() ); } - } diff --git a/eeschema/sim/netlist_exporter_pspice_sim.h b/eeschema/sim/netlist_exporter_pspice_sim.h index 6cd76c81d7..78e03fb5c7 100644 --- a/eeschema/sim/netlist_exporter_pspice_sim.h +++ b/eeschema/sim/netlist_exporter_pspice_sim.h @@ -64,30 +64,53 @@ public: */ static const std::vector& GetCurrents( SPICE_PRIMITIVE aPrimitive ); + /** + * @brief Overrides the simulation command directive. + */ void SetSimCommand( const wxString& aCmd ) { m_simCommand = aCmd; } + /** + * @brief Returns the simulation command directive. + */ const wxString& GetSimCommand() const { return m_simCommand; } + /** + * @brief Clears the simulation command directive. + */ void ClearSimCommand() { 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(); + /** + * @brief Returns simulation command directives placed in schematic sheets (if any). + */ wxString GetSheetSimCommand(); + /** + * @brief Determines if a directive is a simulation command. + */ static bool IsSimCommand( const wxString& aCmd ) { return CommandToSimType( aCmd ) != ST_UNKNOWN; } + /** + * @brief Returns simulation type basing on a simulation command directive. + */ static SIM_TYPE CommandToSimType( const wxString& aCmd ); protected: @@ -95,7 +118,7 @@ protected: private: - ///> Overridden simulation command + ///> Custom simulation command (has priority over the schematic sheet simulation commands) wxString m_simCommand; }; diff --git a/eeschema/sim/ngspice.cpp b/eeschema/sim/ngspice.cpp index dacc729e08..54a5c8ffc4 100644 --- a/eeschema/sim/ngspice.cpp +++ b/eeschema/sim/ngspice.cpp @@ -52,7 +52,6 @@ NGSPICE::NGSPICE() m_ngSpice_AllPlots = (ngSpice_AllPlots) m_dll->GetSymbol( "ngSpice_AllPlots" ); m_ngSpice_AllVecs = (ngSpice_AllVecs) m_dll->GetSymbol( "ngSpice_AllVecs" ); m_ngSpice_Running = (ngSpice_Running) m_dll->GetSymbol( "ngSpice_running" ); - } @@ -243,7 +242,7 @@ bool NGSPICE::LoadNetlist( const string& aNetlist ) bool NGSPICE::Run() { setlocale( LC_ALL, "C" ); - bool rv = Command( "bg_run" ); + bool rv = Command( "bg_run" ); // bg_* commands execute in a separate thread setlocale( LC_ALL, "" ); return rv; } @@ -252,7 +251,7 @@ bool NGSPICE::Run() bool NGSPICE::Stop() { setlocale( LC_ALL, "C" ); - bool rv = Command( "bg_halt" ); + bool rv = Command( "bg_halt" ); // bg_* commands execute in a separate thread setlocale( LC_ALL, "" ); return rv; } @@ -301,10 +300,11 @@ string NGSPICE::GetXAxis( SIM_TYPE aType ) const 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); - return 0; + //printf("stat %d immed %d quit %d\n", status, !!immediate, !!exit_upon_quit); + return 0; } diff --git a/eeschema/sim/ngspice.h b/eeschema/sim/ngspice.h index ca5d1fca87..5fa3f9c7ce 100644 --- a/eeschema/sim/ngspice.h +++ b/eeschema/sim/ngspice.h @@ -36,32 +36,54 @@ public: NGSPICE(); virtual ~NGSPICE(); + ///> @copydoc SPICE_SIMULATOR::Init() void Init() override; + + ///> @copydoc SPICE_SIMULATOR::LoadNetlist() bool LoadNetlist( const std::string& aNetlist ) override; + + ///> @copydoc SPICE_SIMULATOR::Run() bool Run() override; + + ///> @copydoc SPICE_SIMULATOR::Stop() bool Stop() override; + + ///> @copydoc SPICE_SIMULATOR::IsRunning() bool IsRunning() override; + + ///> @copydoc SPICE_SIMULATOR::Command() bool Command( const std::string& aCmd ) override; + + ///> @copydoc SPICE_SIMULATOR::GetXAxis() std::string GetXAxis( SIM_TYPE aType ) const override; + ///> @copydoc SPICE_SIMULATOR::GetPlot() std::vector GetPlot( const std::string& aName, int aMaxLen = -1 ) override; + + ///> @copydoc SPICE_SIMULATOR::GetRealPlot() std::vector GetRealPlot( const std::string& aName, int aMaxLen = -1 ) override; + + ///> @copydoc SPICE_SIMULATOR::GetImagPlot() std::vector GetImagPlot( const std::string& aName, int aMaxLen = -1 ) override; + + ///> @copydoc SPICE_SIMULATOR::GetMagPlot() std::vector GetMagPlot( const std::string& aName, int aMaxLen = -1 ) override; + + ///> @copydoc SPICE_SIMULATOR::GetPhasePlot() std::vector GetPhasePlot( const std::string& aName, int aMaxLen = -1 ) override; private: + // ngspice library functions typedef void (*ngSpice_Init)( SendChar*, SendStat*, ControlledExit*, 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 - 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); - + ///> Handles to DLL functions ngSpice_Init m_ngSpice_Init; ngSpice_Circ m_ngSpice_Circ; ngSpice_Command m_ngSpice_Command; @@ -72,10 +94,11 @@ private: wxDynamicLibrary* m_dll; + // Callback functions static int cbSendChar( 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 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(); }; diff --git a/eeschema/sim/sim_plot_frame.cpp b/eeschema/sim/sim_plot_frame.cpp index dc92a9f7a3..c693195b71 100644 --- a/eeschema/sim/sim_plot_frame.cpp +++ b/eeschema/sim/sim_plot_frame.cpp @@ -45,6 +45,7 @@ SIM_PLOT_TYPE operator|( SIM_PLOT_TYPE aFirst, SIM_PLOT_TYPE aSecond ) return (SIM_PLOT_TYPE) res; } + class SIM_THREAD_REPORTER : public SPICE_REPORTER { 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_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 ); - m_toolAddSignals = m_toolBar->AddTool( ID_SIM_ADD_SIGNALS, _("Add Signals"), 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 ); + // Toolbar buttons + m_toolSimulate = m_toolBar->AddTool( ID_SIM_RUN, _( "Run/Stop Simulation" ), + KiBitmap( sim_run_xpm ), _( "Run Simulation" ), wxITEM_NORMAL ); + m_toolAddSignals = m_toolBar->AddTool( ID_SIM_ADD_SIGNALS, _( "Add Signals" ), + 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_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_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::onAddSignal, this, m_addSignals->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() ); m_toolBar->Realize(); - m_plotNotebook->SetPageText(0, _("Welcome!") ); + m_plotNotebook->SetPageText( 0, _( "Welcome!" ) ); } @@ -180,8 +188,6 @@ void SIM_PLOT_FRAME::StartSimulation() updateTuners(); applyTuners(); m_simulator->Run(); - - Layout(); } @@ -746,21 +752,6 @@ void SIM_PLOT_FRAME::menuShowLegendUpdate( wxUpdateUIEvent& event ) 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 ) { diff --git a/eeschema/sim/sim_plot_frame.h b/eeschema/sim/sim_plot_frame.h index adae18328d..03cf5dc9d1 100644 --- a/eeschema/sim/sim_plot_frame.h +++ b/eeschema/sim/sim_plot_frame.h @@ -27,7 +27,8 @@ #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_types.h" @@ -49,7 +50,7 @@ class NETLIST_EXPORTER_PSPICE_SIM; class SIM_PLOT_PANEL; class TUNER_SLIDER; -/// @todo description +///> Trace descriptor class class TRACE_DESC { public: @@ -102,191 +103,218 @@ private: /** Implementing SIM_PLOT_FRAME_BASE */ class SIM_PLOT_FRAME : public SIM_PLOT_FRAME_BASE { - public: - /** Constructor */ - SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent ); - ~SIM_PLOT_FRAME(); +public: + /** Constructor */ + SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent ); + ~SIM_PLOT_FRAME(); - void StartSimulation(); - void StopSimulation(); - bool IsSimulationRunning(); + void StartSimulation(); + void StopSimulation(); + bool IsSimulationRunning(); - /** - * @brief Creates a new plot panel for a given simulation type and adds it to the main - * notebook. - * @param aSimType is requested simulation type. - * @return The new plot panel. - */ - SIM_PLOT_PANEL* NewPlotPanel( SIM_TYPE aSimType ); + /** + * @brief Creates a new plot panel for a given simulation type and adds it to the main + * notebook. + * @param aSimType is requested simulation type. + * @return The new plot panel. + */ + 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 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 Removes an existing tuner. + * @param aTuner is the tuner to be removed. + * @param aErase decides whether the tuner should be also removed from the tuners list. + * Otherwise it is removed only from the SIM_PLOT_FRAME pane. + */ + void RemoveTuner( TUNER_SLIDER* aTuner, bool aErase = true ); - /** - * @brief Removes a plot with a specific title. - * @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). - */ - void removePlot( const wxString& aPlotName, bool aErase = true ); + /** + * @brief Returns the currently opened plot panel (or NULL if there is none). + */ + SIM_PLOT_PANEL* CurrentPlot() const; - 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 - * the plot, it will be added. - * @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 Removes a plot with a specific title. + * @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). + */ + void removePlot( const wxString& aPlotName, bool aErase = true ); - /** - * @brief Updates the list of currently plotted signals. - */ - void updateSignalList(); + /** + * @brief Reloads the current schematic for the netlist exporter. + */ + void updateNetlistExporter(); - /** - * @brief Updates the cursor values list. - */ - void updateCursors(); + /** + * @brief Updates plot in a particular SIM_PLOT_PANEL. If the panel does not contain + * the plot, it will be added. + * @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. - * Decisions are based on the current NETLIST_EXPORTER data. - */ - void updateTuners(); + /** + * @brief Updates the list of currently plotted signals. + */ + void updateSignalList(); - /** - * @brief Applies component values specified using tunder sliders to the current netlist. - */ - void applyTuners(); + /** + * @brief Updates the cursor values list. + */ + void updateCursors(); - /** - * @brief Loads plot settings from a file. - * @param aPath is the file name. - * @return True if successful. - */ - bool loadWorkbook( const wxString& aPath ); + /** + * @brief Filters out tuners for components that do not exist anymore. + * Decisions are based on the current NETLIST_EXPORTER data. + */ + void updateTuners(); - /** - * @brief Saves plot settings to a file. - * @param aPath is the file name. - * @return True if successful. - */ - bool saveWorkbook( const wxString& aPath ); + /** + * @brief Applies component values specified using tunder sliders to the current netlist. + */ + void applyTuners(); - 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; - void menuOpenWorkbook( wxCommandEvent& event ) override; - void menuSaveWorkbook( wxCommandEvent& event ) override; + /** + * @brief Saves plot settings to a file. + * @param aPath is the file name. + * @return True if successful. + */ + bool saveWorkbook( const wxString& aPath ); - void menuExit( wxCommandEvent& event ) override - { - Close(); - } + /** + * @brief Returns X axis for a given simulation type. + */ + SIM_PLOT_TYPE GetXAxisType( SIM_TYPE aType ) const; - void menuSaveImage( wxCommandEvent& 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 menuShowCoords( wxCommandEvent& event ) override; - //void menuShowCoordsUpdate( wxUpdateUIEvent& event ) override; + // Menu handlers + void menuNewPlot( wxCommandEvent& aEvent ) override; + void menuOpenWorkbook( wxCommandEvent& event ) override; + void menuSaveWorkbook( wxCommandEvent& event ) override; - // Event handlers - void onPlotChanged( wxAuiNotebookEvent& event ) override; - void onPlotClose( wxAuiNotebookEvent& event ) override; + void menuExit( wxCommandEvent& event ) override + { + Close(); + } - void onSignalDblClick( wxCommandEvent& event ) override; - void onSignalRClick( wxMouseEvent& event ) override; + void menuSaveImage( wxCommandEvent& 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 ); - void onSettings( wxCommandEvent& event ); - void onAddSignal( wxCommandEvent& event ); - void onProbe( wxCommandEvent& event ); - void onTune( wxCommandEvent& event ); + // Event handlers + void onPlotChanged( wxAuiNotebookEvent& event ) override; + void onPlotClose( wxAuiNotebookEvent& event ) override; - void onClose( wxCloseEvent& aEvent ); + void onSignalDblClick( wxCommandEvent& event ) override; + void onSignalRClick( wxMouseEvent& event ) override; - void onCursorUpdate( wxCommandEvent& aEvent ); - void onSimUpdate( wxCommandEvent& aEvent ); - void onSimReport( wxCommandEvent& aEvent ); - void onSimStarted( wxCommandEvent& aEvent ); - void onSimFinished( wxCommandEvent& aEvent ); + void onSimulate( wxCommandEvent& event ); + void onSettings( wxCommandEvent& event ); + void onAddSignal( wxCommandEvent& event ); + void onProbe( wxCommandEvent& event ); + void onTune( wxCommandEvent& event ); - wxToolBarToolBase* m_toolSimulate; - wxToolBarToolBase* m_toolAddSignals; - wxToolBarToolBase* m_toolProbe; - wxToolBarToolBase* m_toolTune; - wxToolBarToolBase* m_toolSettings; + void onClose( wxCloseEvent& aEvent ); - SCH_EDIT_FRAME* m_schematicFrame; - std::unique_ptr m_exporter; - std::unique_ptr m_simulator; + void onCursorUpdate( wxCommandEvent& aEvent ); + void onSimUpdate( wxCommandEvent& aEvent ); + void onSimReport( wxCommandEvent& aEvent ); + void onSimStarted( wxCommandEvent& aEvent ); + void onSimFinished( wxCommandEvent& aEvent ); - typedef std::map TRACE_MAP; + // Toolbar buttons + wxToolBarToolBase* m_toolSimulate; + wxToolBarToolBase* m_toolAddSignals; + wxToolBarToolBase* m_toolProbe; + wxToolBarToolBase* m_toolTune; + wxToolBarToolBase* m_toolSettings; - struct PLOT_INFO - { - ///> Map of the traces displayed on the plot - TRACE_MAP m_traces; + SCH_EDIT_FRAME* m_schematicFrame; + std::unique_ptr m_exporter; + std::unique_ptr m_simulator; - ///> Spice directive used to execute the simulation - wxString m_simCommand; - }; + typedef std::map TRACE_MAP; - ///> Map of plot panels and associated data - std::map m_plots; + struct PLOT_INFO + { + ///> Map of the traces displayed on the plot + TRACE_MAP m_traces; - ///> List of currently displayed tuners - std::list m_tuners; + ///> Spice directive used to execute the simulation + wxString m_simCommand; + }; - // Trick to preserve settings between runs - DIALOG_SIM_SETTINGS m_settingsDlg; + ///> Map of plot panels and associated data + std::map m_plots; - // Right click context menu for signals in the listbox - class SIGNAL_CONTEXT_MENU : public wxMenu - { - public: - SIGNAL_CONTEXT_MENU( const wxString& aSignal, SIM_PLOT_FRAME* aPlotFrame ); + ///> List of currently displayed tuners + std::list m_tuners; - private: - void onMenuEvent( wxMenuEvent& aEvent ); + // Trick to preserve settings between runs + DIALOG_SIM_SETTINGS m_settingsDlg; - const wxString& m_signal; - SIM_PLOT_FRAME* m_plotFrame; + // Right click context menu for signals in the listbox + class SIGNAL_CONTEXT_MENU : public wxMenu + { + public: + SIGNAL_CONTEXT_MENU( const wxString& aSignal, SIM_PLOT_FRAME* aPlotFrame ); - enum SIGNAL_CONTEXT_MENU_EVENTS - { - HIDE_SIGNAL, - SHOW_CURSOR, - HIDE_CURSOR - }; - }; + private: + void onMenuEvent( wxMenuEvent& aEvent ); - ///> Panel that was used as the most recent one for simulations - SIM_PLOT_PANEL* m_lastSimPlot; + const wxString& m_signal; + 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 diff --git a/eeschema/sim/sim_plot_panel.cpp b/eeschema/sim/sim_plot_panel.cpp index 4b40753db0..098805fe5d 100644 --- a/eeschema/sim/sim_plot_panel.cpp +++ b/eeschema/sim/sim_plot_panel.cpp @@ -28,80 +28,88 @@ #include #include -static wxString formatFloat (double x, int nDigits) +static wxString formatFloat( double x, int nDigits ) { wxString rv, fmt; - if(nDigits) + if( nDigits ) { - fmt = wxT("%.0Nf"); + fmt = wxT( "%.0Nf" ); fmt[3] = '0' + nDigits; - } else { - fmt = wxT("%.0f"); + } + else + { + fmt = wxT( "%.0f" ); } - rv.Printf(fmt, x); + rv.Printf( fmt, x ); 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 struct { + + const struct + { double exponent; char suffix; - } powers[] = { - {-18,'a'}, - {-15,'f'}, - {-12,'p'}, - {-9,'n'}, - {-6,'u'}, - {-3,'m'}, - {0, 0}, - {3, 'k'}, - {6, 'M'}, - {9, 'G'}, - {12, 'T'}, - {15, 'P'} + } powers[] = + { + { -18, 'a' }, + { -15, 'f' }, + { -12, 'p' }, + { -9, 'n' }, + { -6, 'u' }, + { -3, 'm' }, + { 0, 0 }, + { 3, 'k' }, + { 6, 'M' }, + { 9, 'G' }, + { 12, 'T' }, + { 14, 'P' } }; power = 0; suffix = unit; - if (x == 0.0) + if( x == 0.0 ) return; - for ( int i = 0; i = r_cur && fabs(x) < r_cur * 1000.0 ) + if( fabs( x ) >= r_cur && fabs( x ) < r_cur * 1000.0 ) { 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 suffix = unit; + 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; - while(k && ((k % 10LL) == 0LL || (k % 10LL) == 9LL)) + while( k && ( ( k % 10LL ) == 0LL || ( k % 10LL ) == 9LL ) ) { k /= 10LL; } n = 0; - while (k != 0LL) + while( k != 0LL ) { n++; 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(); wxString suffix; 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 ); - 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.visible = true; } } + class FREQUENCY_LOG_SCALE : public mpScaleXLog { public: - FREQUENCY_LOG_SCALE(wxString name, int flags) : + FREQUENCY_LOG_SCALE( wxString name, int flags ) : mpScaleXLog( name, flags ) {}; void formatLabels() { - const wxString unit = wxT("Hz"); + const wxString unit = wxT( "Hz" ); wxString suffix; int power; - for ( auto &l : TickLabels() ) + for( auto &l : TickLabels() ) { - getSISuffix( l.pos, unit, power, suffix); - double sf = pow(10.0, power); + getSISuffix( l.pos, unit, power, suffix ); + double sf = pow( 10.0, power ); 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; } } }; + class FREQUENCY_LIN_SCALE : public mpScaleX { public: - FREQUENCY_LIN_SCALE(wxString name, int flags) : + FREQUENCY_LIN_SCALE( wxString name, int flags ) : mpScaleX( name, flags, false , 0 ) {}; void formatLabels() { - formatSILabels( this, wxT("Hz"), 3 ); + formatSILabels( this, wxT( "Hz" ), 3 ); } }; @@ -176,74 +186,78 @@ public: class TIME_SCALE : public mpScaleX { public: - TIME_SCALE(wxString name, int flags) : - mpScaleX ( name, flags, false, 0) {}; + TIME_SCALE( wxString name, int flags ) : + mpScaleX( name, flags, false, 0 ) {}; void formatLabels() { - formatSILabels( this, wxT("s"), 3 ); + formatSILabels( this, wxT( "s" ), 3 ); } }; + class VOLTAGE_SCALE_X : public mpScaleX { public: - VOLTAGE_SCALE_X(wxString name, int flags) : - mpScaleX ( name, flags, false, 0 ) {}; + VOLTAGE_SCALE_X( wxString name, int flags ) : + mpScaleX( name, flags, false, 0 ) {}; void formatLabels() { - formatSILabels( this, wxT("V"), 3 ); + formatSILabels( this, wxT( "V" ), 3 ); } }; + class GAIN_SCALE : public mpScaleY { public: GAIN_SCALE( wxString name, int flags ) : - mpScaleY ( name, flags, false) {}; + mpScaleY( name, flags, false ) {}; void formatLabels() { - formatSILabels( this, wxT("dB"), 3 ); + formatSILabels( this, wxT( "dB" ), 3 ); } }; + class PHASE_SCALE : public mpScaleY { public: - PHASE_SCALE(wxString name, int flags) : - mpScaleY ( name, flags, false ) {}; + PHASE_SCALE( wxString name, int flags ) : + mpScaleY( name, flags, false ) {}; void formatLabels() { - formatSILabels( this, wxT("\u00B0"), 3 ); + 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 ) {}; + VOLTAGE_SCALE_Y( wxString name, int flags ) : + mpScaleY( name, flags, false ) {}; void formatLabels() { - formatSILabels( this, wxT("V"), 3 ); + formatSILabels( this, wxT( "V" ), 3 ); } - }; + class CURRENT_SCALE : public mpScaleY { public: - CURRENT_SCALE(wxString name, int flags ) : - mpScaleY ( name, flags, false ) {}; + CURRENT_SCALE( wxString name, int flags ) : + mpScaleY( name, flags, false ) {}; 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_y1 = new GAIN_SCALE( wxT( "Gain" ), mpALIGN_LEFT ); 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; 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_y1 = new VOLTAGE_SCALE_Y( wxT( "Voltage" ), mpALIGN_LEFT ); 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; 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 ); AddLayer( m_legend ); m_topLevel.push_back( m_legend ); - SetColourTheme(*wxBLACK, *wxWHITE, grey); + SetColourTheme( *wxBLACK, *wxWHITE, grey ); - EnableDoubleBuffer(true); + EnableDoubleBuffer( true ); UpdateAll(); } @@ -455,20 +469,20 @@ bool SIM_PLOT_PANEL::AddTrace( const wxString& aName, int aPoints, if( addedNewEntry ) { - if ( m_type == ST_TRANSIENT ) + if( m_type == ST_TRANSIENT ) { bool hasVoltageTraces = false; for( auto t : m_traces ) { - if ( ! (t.second->GetFlags() & SPT_CURRENT ) ) + if( !( t.second->GetFlags() & SPT_CURRENT ) ) { hasVoltageTraces = true; break; } } - if ( !hasVoltageTraces ) + if( !hasVoltageTraces ) m_axis_y2->SetMasterScale( nullptr ); else 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 ) { - 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 } 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 } } @@ -553,6 +567,7 @@ void SIM_PLOT_PANEL::DeleteAllTraces() DeleteTrace( t.first ); } + m_colorIdx = 0; m_traces.clear(); } diff --git a/eeschema/sim/sim_plot_panel.h b/eeschema/sim/sim_plot_panel.h index 6db406a705..873de37935 100644 --- a/eeschema/sim/sim_plot_panel.h +++ b/eeschema/sim/sim_plot_panel.h @@ -32,6 +32,7 @@ class TRACE; +///> Cursor attached to a trace to follow its values: class CURSOR : public mpInfoLayer { public: @@ -86,14 +87,18 @@ class TRACE : public mpFXYVector { public: TRACE( const wxString& aName ) : - mpFXYVector( aName ), m_cursor( nullptr ), m_flags(0) - { - SetContinuity( true ); - SetDrawOutsideMargins( false ); - ShowName( false ); - - } + mpFXYVector( aName ), m_cursor( nullptr ), m_flags( 0 ) + { + SetContinuity( true ); + SetDrawOutsideMargins( 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& aX, const std::vector& aY ) override { if( m_cursor ) @@ -127,7 +132,7 @@ public: return m_cursor; } - void SetFlags ( int aFlags ) + void SetFlags( int aFlags ) { m_flags = aFlags; } @@ -222,26 +227,20 @@ public: return m_legend->IsVisible(); } - void ShowCoords( bool aEnable ) - { - m_coords->SetVisible( aEnable ); - UpdateAll(); - } - - bool IsCoordsShown() const - { - return m_coords->IsVisible(); - } - + ///> Returns true if the trace has cursor shown. bool HasCursorEnabled( const wxString& aName ) const; + ///> Toggles cursor for a particular trace. void EnableCursor( const wxString& aName, bool aEnable ); + ///> Resets scale ranges to fit the current traces void ResetScales(); private: + ///> Returns a new color from the palette wxColour generateColor(); + // Color index to get a new color from the palette unsigned int m_colorIdx; // Traces to be plotted @@ -251,7 +250,6 @@ private: mpScaleY* m_axis_y1; mpScaleY* m_axis_y2; mpInfoLegend* m_legend; - mpInfoCoords* m_coords; std::vector m_topLevel; diff --git a/eeschema/sim/sim_types.h b/eeschema/sim/sim_types.h index ac2ab0beac..fe36f9ac76 100644 --- a/eeschema/sim/sim_types.h +++ b/eeschema/sim/sim_types.h @@ -39,6 +39,7 @@ enum SIM_PLOT_TYPE { SPT_AC_PHASE = 0x04, SPT_AC_MAG = 0x08, + // X axis SPT_TIME = 0x10, SPT_LIN_FREQUENCY = 0x20, SPT_LOG_FREQUENCY = 0x20, diff --git a/eeschema/sim/simulate.h b/eeschema/sim/simulate.h deleted file mode 100644 index 602d4ebcd1..0000000000 --- a/eeschema/sim/simulate.h +++ /dev/null @@ -1,11 +0,0 @@ -#include - -void SCH_EDIT_FRAME::OnSimulationRun( wxCommandEvent& event ) -{} - -void SCH_EDIT_FRAME::OnSimulationStop( wxCommandEvent& event ) -{} - -void SCH_EDIT_FRAME::OnSimulationAddProbe( wxCommandEvent& event ) -{} - diff --git a/eeschema/sim/spice_simulator.h b/eeschema/sim/spice_simulator.h index 1231e042e1..4a44be09d2 100644 --- a/eeschema/sim/spice_simulator.h +++ b/eeschema/sim/spice_simulator.h @@ -41,31 +41,91 @@ public: SPICE_SIMULATOR() : m_reporter( NULL ) {} virtual ~SPICE_SIMULATOR() {} + ///> Creates a simulator instance of particular type (currently only ngspice is handled) static SPICE_SIMULATOR* CreateInstance( const std::string& aName ); + ///> Intializes the simulator 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; + + /** + * @brief Executes the simulation with currently loaded netlist. + * @return True in case of success, false otherwise. + */ virtual bool Run() = 0; + + /** + * @brief Halts the simulation. + * @return True in case of success, false otherwise. + */ virtual bool Stop() = 0; + + /** + * @brief Checks if simulation is running at the moment. + * @return True if simulation is currently executed. + */ 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; ///> Returns X axis name for a given simulation type 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 ) { 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 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 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 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 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 GetPhasePlot( const std::string& aName, int aMaxLen = -1 ) = 0; - protected: + ///> Reporter object to receive simulation log SPICE_REPORTER* m_reporter; }; diff --git a/eeschema/sim/spice_value.cpp b/eeschema/sim/spice_value.cpp index a65875355d..383589779f 100644 --- a/eeschema/sim/spice_value.cpp +++ b/eeschema/sim/spice_value.cpp @@ -221,13 +221,13 @@ SPICE_VALUE SPICE_VALUE::operator/( const SPICE_VALUE& aOther ) const void SPICE_VALUE::stripZeros( wxString& aString ) { - if ( aString.Find(',') >= 0 || aString.Find('.') >= 0 ) + if ( aString.Find( ',' ) >= 0 || aString.Find( '.' ) >= 0 ) { while( aString.EndsWith( '0' ) ) aString.RemoveLast(); if( aString.EndsWith( '.' ) || aString.EndsWith( ',' ) ) - aString.RemoveLast(); + aString.RemoveLast(); } } diff --git a/eeschema/sim/spice_value.h b/eeschema/sim/spice_value.h index c8c01e7848..0ebead1f83 100644 --- a/eeschema/sim/spice_value.h +++ b/eeschema/sim/spice_value.h @@ -51,6 +51,7 @@ public: { } + ///> Parses the string to create a Spice value (e.g. 100n) SPICE_VALUE( const wxString& aString ); SPICE_VALUE( int aInt, UNIT_PREFIX aPrefix = PFX_NONE ) @@ -65,19 +66,35 @@ public: Normalize(); } + /** + * @brief Normalizes the value. The unit prefix is picked so the base is (0.001 <= base < 1000). + */ void Normalize(); double ToDouble() const; + /** + * @brief Returns string value as when converting double to string (e.g. 123456.789). + */ wxString ToString() const; + /** + * @brief Returns string value in Spice format (e.g. 123.3456789k). + */ wxString ToSpiceString() const; + /** + * @brief Returns either a normal string or Spice format string, depending on the original + * value format. + */ wxString ToOrigString() const { return m_spiceStr ? ToSpiceString() : ToString(); } + /** + * Returns true if the object was initiated with a Spice formatted string value. + */ bool IsSpiceString() const { return m_spiceStr; @@ -120,6 +137,7 @@ private: ///> Was the value defined using the Spice notation? bool m_spiceStr; + ///> Removes redundant zeros from the end of a string. static void stripZeros( wxString& aString ); }; @@ -141,6 +159,7 @@ public: bool Validate( wxWindow* aParent ) override; private: + ///> Is it valid to get an empty value? bool m_emptyAllowed; };