diff --git a/common/widgets/mathplot.cpp b/common/widgets/mathplot.cpp index 4622c7239b..f26ac7fab6 100644 --- a/common/widgets/mathplot.cpp +++ b/common/widgets/mathplot.cpp @@ -2980,10 +2980,10 @@ void mpFXYVector::SetData( const std::vector& xs, const std::vector +{ +public: + TIME_SCALE( const wxString& name, const wxString& unit, int flags ) : + LIN_SCALE( name, unit, flags ) + {}; + + void ExtendDataRange( double minV, double maxV ) override + { + if( !m_rangeSet ) + { + m_minV = 0; + m_maxV = 0; + m_rangeSet = true; + } + else + { + if( minV < m_minV ) + m_minV -= abs( maxV - minV ); + + if( maxV > m_maxV ) + m_maxV += abs( maxV - minV ); + } + } +}; + + template class LOG_SCALE : public parent { @@ -511,7 +538,7 @@ void SIM_PLOT_PANEL::updateAxes( int aNewTraceType ) case ST_TRANSIENT: if( !m_axis_x ) { - m_axis_x = new LIN_SCALE( wxEmptyString, wxT( "s" ), mpALIGN_BOTTOM ); + m_axis_x = new TIME_SCALE( wxEmptyString, wxT( "s" ), mpALIGN_BOTTOM ); m_axis_x->SetNameAlign( mpALIGN_BOTTOM ); m_plotWin->AddLayer( m_axis_x ); @@ -793,7 +820,7 @@ void SIM_PLOT_PANEL::DeleteTrace( TRACE* aTrace ) } m_plotWin->DelLayer( aTrace, true, true ); - ResetScales(); + ResetScales( false ); } @@ -843,9 +870,9 @@ void SIM_PLOT_PANEL::EnableCursor( const wxString& aVectorName, int aType, int a } -void SIM_PLOT_PANEL::ResetScales() +void SIM_PLOT_PANEL::ResetScales( bool aIncludeX ) { - if( m_axis_x ) + if( m_axis_x && aIncludeX ) m_axis_x->ResetDataRange(); if( m_axis_y1 ) diff --git a/eeschema/sim/sim_plot_panel.h b/eeschema/sim/sim_plot_panel.h index 3813809543..6c353181aa 100644 --- a/eeschema/sim/sim_plot_panel.h +++ b/eeschema/sim/sim_plot_panel.h @@ -300,7 +300,7 @@ public: const wxString& aSignalName ); ///< Reset scale ranges to fit the current traces. - void ResetScales(); + void ResetScales( bool aIncludeX ); ///< Update trace line style void UpdateTraceStyle( TRACE* trace ); diff --git a/eeschema/sim/simulator_frame.cpp b/eeschema/sim/simulator_frame.cpp index 3dcc2921f7..513b60e9d6 100644 --- a/eeschema/sim/simulator_frame.cpp +++ b/eeschema/sim/simulator_frame.cpp @@ -741,7 +741,7 @@ void SIMULATOR_FRAME::onSimFinished( wxCommandEvent& aEvent ) m_simFinished = true; - m_panel->OnSimFinished(); + m_panel->OnSimRefresh( true ); m_schematicFrame->RefreshOperatingPointDisplay(); m_schematicFrame->GetCanvas()->Refresh(); @@ -765,8 +765,8 @@ void SIMULATOR_FRAME::onSimUpdate( wxCommandEvent& aEvent ) if( m_panel->GetCurrentPlotWindow() != m_lastSimPlot ) { - // We need to rerun simulation, as the simulator currently stores - // results for another plot + // We need to rerun simulation, as the simulator currently stores results for another + // plot StartSimulation(); } else diff --git a/eeschema/sim/simulator_panel.cpp b/eeschema/sim/simulator_panel.cpp index 2bb2e38056..9fd7a4b9ff 100644 --- a/eeschema/sim/simulator_panel.cpp +++ b/eeschema/sim/simulator_panel.cpp @@ -402,6 +402,10 @@ private: }; +#define ID_SIM_REFRESH 10207 +#define REFRESH_INTERVAL 50 // 20 frames/second. + + SIMULATOR_PANEL::SIMULATOR_PANEL( SIMULATOR_FRAME* aSimulatorFrame, SCH_EDIT_FRAME* aSchematicFrame ) : SIMULATOR_PANEL_BASE( aSimulatorFrame ), @@ -409,7 +413,8 @@ SIMULATOR_PANEL::SIMULATOR_PANEL( SIMULATOR_FRAME* aSimulatorFrame, m_simulatorFrame( aSimulatorFrame ), m_schematicFrame( aSchematicFrame ), m_darkMode( true ), - m_plotNumber( 0 ) + m_plotNumber( 0 ), + m_refreshTimer( this, ID_SIM_REFRESH ) { // Get the previous size and position of windows: LoadSettings( m_schematicFrame->eeconfig() ); @@ -456,6 +461,16 @@ SIMULATOR_PANEL::SIMULATOR_PANEL( SIMULATOR_FRAME* aSimulatorFrame, Bind( EVT_SIM_CURSOR_UPDATE, &SIMULATOR_PANEL::onPlotCursorUpdate, this ); Bind( EVT_WORKBOOK_MODIFIED, &SIMULATOR_PANEL::onNotebookModified, this ); + Bind( wxEVT_TIMER, + [&]( wxTimerEvent& aEvent ) + { + OnSimRefresh( false ); + + if( m_simulatorFrame->GetSimulator()->IsRunning() ) + m_refreshTimer.Start( REFRESH_INTERVAL, wxTIMER_ONE_SHOT ); + }, + m_refreshTimer.GetId() ); + #ifndef wxHAS_NATIVE_TABART // Default non-native tab art has ugly gradients we don't want m_plotNotebook->SetArtProvider( new wxAuiSimpleTabArt() ); @@ -1373,7 +1388,7 @@ void SIMULATOR_PANEL::SetUserDefinedSignals( const std::map& aNew void SIMULATOR_PANEL::updateTrace( const wxString& aVectorName, int aTraceType, - SIM_PLOT_PANEL* aPlotPanel ) + SIM_PLOT_PANEL* aPlotPanel ) { SIM_TYPE simType = NGSPICE_CIRCUIT_MODEL::CommandToSimType( aPlotPanel->GetSimCommand() ); @@ -1402,31 +1417,28 @@ void SIMULATOR_PANEL::updateTrace( const wxString& aVectorName, int aTraceType, std::vector data_x; std::vector data_y; - if( m_simulatorFrame->SimFinished() ) + data_x = simulator()->GetMagPlot( (const char*) xAxisName.c_str() ); + + switch( simType ) { - data_x = simulator()->GetMagPlot( (const char*) xAxisName.c_str() ); - - switch( simType ) - { - case ST_AC: - if( aTraceType & SPT_AC_MAG ) - data_y = simulator()->GetMagPlot( (const char*) simVectorName.c_str() ); - else if( aTraceType & SPT_AC_PHASE ) - data_y = simulator()->GetPhasePlot( (const char*) simVectorName.c_str() ); - else - wxFAIL_MSG( wxT( "Plot type missing AC_PHASE or AC_MAG bit" ) ); - - break; - - case ST_NOISE: - case ST_DC: - case ST_TRANSIENT: + case ST_AC: + if( aTraceType & SPT_AC_MAG ) data_y = simulator()->GetMagPlot( (const char*) simVectorName.c_str() ); - break; + else if( aTraceType & SPT_AC_PHASE ) + data_y = simulator()->GetPhasePlot( (const char*) simVectorName.c_str() ); + else + wxFAIL_MSG( wxT( "Plot type missing AC_PHASE or AC_MAG bit" ) ); - default: - wxFAIL_MSG( wxT( "Unhandled plot type" ) ); - } + break; + + case ST_NOISE: + case ST_DC: + case ST_TRANSIENT: + data_y = simulator()->GetMagPlot( (const char*) simVectorName.c_str() ); + break; + + default: + wxFAIL_MSG( wxT( "Unhandled plot type" ) ); } unsigned int size = data_x.size(); @@ -2316,11 +2328,15 @@ void SIMULATOR_PANEL::onPlotCursorUpdate( wxCommandEvent& aEvent ) void SIMULATOR_PANEL::OnSimUpdate() { - // Incremental update + if( SIM_PLOT_PANEL* plotPanel = dynamic_cast( GetCurrentPlotWindow() ) ) + plotPanel->ResetScales( true ); + m_simConsole->Clear(); // Do not export netlist, it is already stored in the simulator applyTuners(); + + m_refreshTimer.Start( REFRESH_INTERVAL, wxTIMER_ONE_SHOT ); } @@ -2331,7 +2347,7 @@ void SIMULATOR_PANEL::OnSimReport( const wxString& aMsg ) } -void SIMULATOR_PANEL::OnSimFinished() +void SIMULATOR_PANEL::OnSimRefresh( bool aFinal ) { SIM_TYPE simType = circuitModel()->GetSimType(); SIM_PLOT_PANEL_BASE* plotPanelWindow = GetCurrentPlotWindow(); @@ -2397,7 +2413,10 @@ void SIMULATOR_PANEL::OnSimFinished() updateSignalsGrid(); plotPanel->GetPlotWin()->UpdateAll(); - plotPanel->ResetScales(); + + if( aFinal ) + plotPanel->ResetScales( true ); + plotPanel->GetPlotWin()->Fit(); } else if( simType == ST_OP ) diff --git a/eeschema/sim/simulator_panel.h b/eeschema/sim/simulator_panel.h index ab094234a1..546ffeeb87 100644 --- a/eeschema/sim/simulator_panel.h +++ b/eeschema/sim/simulator_panel.h @@ -228,7 +228,7 @@ public: void OnSimUpdate(); void OnSimReport( const wxString& aMsg ); - void OnSimFinished(); + void OnSimRefresh( bool aFinal ); private: /** @@ -331,6 +331,7 @@ private: int m_splitterTuneValuesSashPosition; bool m_darkMode; unsigned int m_plotNumber; + wxTimer m_refreshTimer; }; #endif // SIMULATOR_PANEL_H diff --git a/include/widgets/mathplot.h b/include/widgets/mathplot.h index d2d54b1c55..19650b0151 100644 --- a/include/widgets/mathplot.h +++ b/include/widgets/mathplot.h @@ -748,7 +748,7 @@ public: maxV = m_maxV; } - void ExtendDataRange( double minV, double maxV ) + virtual void ExtendDataRange( double minV, double maxV ) { if( !m_rangeSet ) { @@ -771,7 +771,7 @@ public: void ResetDataRange() { - m_rangeSet = 0; + m_rangeSet = false; } double AbsMaxValue() const