diff --git a/eeschema/sim/sim_plot_frame.cpp b/eeschema/sim/sim_plot_frame.cpp index 542c220599..cd542470a4 100644 --- a/eeschema/sim/sim_plot_frame.cpp +++ b/eeschema/sim/sim_plot_frame.cpp @@ -237,42 +237,42 @@ void SIGNALS_GRID_TRICKS::doPopupSelection( wxCommandEvent& event ) if( event.GetId() == MYID_MEASURE_MIN ) { - for( wxString signal : signals ) + for( const wxString& signal : signals ) m_parent->AddMeasurement( wxString::Format( wxS( "MIN %s" ), signal ) ); } else if( event.GetId() == MYID_MEASURE_MAX ) { - for( wxString signal : signals ) + for( const wxString& signal : signals ) m_parent->AddMeasurement( wxString::Format( wxS( "MAX %s" ), signal ) ); } else if( event.GetId() == MYID_MEASURE_AVG ) { - for( wxString signal : signals ) + for( const wxString& signal : signals ) m_parent->AddMeasurement( wxString::Format( wxS( "AVG %s" ), signal ) ); } else if( event.GetId() == MYID_MEASURE_RMS ) { - for( wxString signal : signals ) + for( const wxString& signal : signals ) m_parent->AddMeasurement( wxString::Format( wxS( "RMS %s" ), signal ) ); } else if( event.GetId() == MYID_MEASURE_PP ) { - for( wxString signal : signals ) + for( const wxString& signal : signals ) m_parent->AddMeasurement( wxString::Format( wxS( "PP %s" ), signal ) ); } else if( event.GetId() == MYID_MEASURE_MIN_AT ) { - for( wxString signal : signals ) + for( const wxString& signal : signals ) m_parent->AddMeasurement( wxString::Format( wxS( "MIN_AT %s" ), signal ) ); } else if( event.GetId() == MYID_MEASURE_MAX_AT ) { - for( wxString signal : signals ) + for( const wxString& signal : signals ) m_parent->AddMeasurement( wxString::Format( wxS( "MAX_AT %s" ), signal ) ); } else if( event.GetId() == MYID_MEASURE_INTEGRAL ) { - for( wxString signal : signals ) + for( const wxString& signal : signals ) m_parent->AddMeasurement( wxString::Format( wxS( "INTEG %s" ), signal ) ); } else @@ -963,16 +963,7 @@ void SIM_PLOT_FRAME::rebuildSignalsList() // Add user-defined signals for( int ii = 0; ii < (int) m_userDefinedSignals.size(); ++ii ) { - static wxRegEx regEx( wxS( "(^|[^a-z0-9_])([VIP])\\(" ), wxRE_ICASE ); - const wxString& signal = m_userDefinedSignals[ii]; - - if( regEx.Matches( signal ) ) - { - wxString vecType = regEx.GetMatch( signal, 2 ); - wxString spiceVecName = wxString::Format( wxS( "%s(user%d)" ), vecType, ii ); - - addSignal( signal, spiceVecName ); - } + addSignal( m_userDefinedSignals[ii], wxString::Format( wxS( "user%d" ), ii ) ); } std::sort( m_signals.begin(), m_signals.end(), @@ -1133,12 +1124,6 @@ wxString SIM_PLOT_FRAME::getTraceName( const wxString& aSignalName ) } -wxString SIM_PLOT_FRAME::getTraceName( int aRow ) -{ - return getTraceName( m_signalsGrid->GetCellValue( aRow, COL_SIGNAL_NAME ) ); -} - - /** * AC-small-signal analyses have two traces per signal, so we suffix the names. */ @@ -1165,10 +1150,35 @@ void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent ) if( col == COL_SIGNAL_SHOW ) { + wxString gainSuffix = _( " (gain)" ); + wxString phaseSuffix = _( " (phase)" ); + wxString signal = m_signalsGrid->GetCellValue( row, COL_SIGNAL_NAME ); + wxUniChar firstChar = signal.Upper()[0]; + wxString traceName = getTraceName( signal ); + int traceType = SPT_UNKNOWN; + + if( firstChar == 'V' ) + traceType = SPT_VOLTAGE; + else if( firstChar == 'I' ) + traceType = SPT_CURRENT; + else if( firstChar == 'P' ) + traceType = SPT_POWER; + + if( traceName.EndsWith( gainSuffix ) ) + { + traceType |= SPT_AC_MAG; + traceName = traceName.Left( traceName.Length() - gainSuffix.Length() ); + } + else if( traceName.EndsWith( phaseSuffix ) ) + { + traceType |= SPT_AC_PHASE; + traceName = traceName.Left( traceName.Length() - phaseSuffix.Length() ); + } + if( text == wxS( "1" ) ) - addTrace( getTraceName( row ) ); + addTrace( traceName, (SIM_TRACE_TYPE) traceType ); else - removeTrace( getTraceName( row ) ); + removeTrace( traceName, (SIM_TRACE_TYPE) traceType ); // Update enabled/visible states of other controls updateSignalsGrid(); @@ -1177,7 +1187,8 @@ void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent ) else if( col == COL_SIGNAL_COLOR ) { KIGFX::COLOR4D color( m_signalsGrid->GetCellValue( row, COL_SIGNAL_COLOR ) ); - TRACE* trace = plot->GetTrace( getTraceName( row ) ); + wxString signal = m_signalsGrid->GetCellValue( row, COL_SIGNAL_NAME ); + TRACE* trace = plot->GetTrace( getTraceName( signal ) ); if( trace ) { @@ -1191,9 +1202,11 @@ void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent ) { for( int ii = 0; ii < m_signalsGrid->GetNumberRows(); ++ii ) { - bool enable = ii == row && text == wxS( "1" ); + wxString signal = m_signalsGrid->GetCellValue( ii, COL_SIGNAL_NAME ); + int id = col == COL_CURSOR_1 ? 1 : 2; + bool enable = ii == row && text == wxS( "1" ); - plot->EnableCursor( getTraceName( ii ), col == COL_CURSOR_1 ? 1 : 2, enable ); + plot->EnableCursor( signal, getTraceName( signal ), id, enable ); OnModify(); } @@ -1627,10 +1640,17 @@ void SIM_PLOT_FRAME::doAddPlot( const wxString& aName, SIM_TRACE_TYPE aType ) void SIM_PLOT_FRAME::SetUserDefinedSignals( const std::vector& aNewSignals ) { - for( const wxString& signal : m_userDefinedSignals ) + SIM_PLOT_PANEL* plotPanel = GetCurrentPlot(); + + if( plotPanel ) { - if( !alg::contains( aNewSignals, signal ) ) - removeTrace( m_userDefinedSignalToSpiceVecName[ signal ] ); + for( const wxString& signal : m_userDefinedSignals ) + { + if( !alg::contains( aNewSignals, signal ) ) + plotPanel->DeleteTrace( m_userDefinedSignalToSpiceVecName[ signal ] ); + } + + plotPanel->GetPlotWin()->Fit(); } m_userDefinedSignals = aNewSignals; @@ -1645,59 +1665,27 @@ void SIM_PLOT_FRAME::SetUserDefinedSignals( const std::vector& aNewSig } -void SIM_PLOT_FRAME::addTrace( const wxString& aSignalName ) +void SIM_PLOT_FRAME::addTrace( const wxString& aSignalName, SIM_TRACE_TYPE aTraceType ) { if( aSignalName.IsEmpty() ) return; - wxString baseSignal = aSignalName; - wxString gainSuffix = _( " (gain)" ); - wxString phaseSuffix = _( " (phase)" ); - wxUniChar firstChar = aSignalName.Upper()[0]; - int traceType = SPT_UNKNOWN; - - if( firstChar == 'V' ) - traceType = SPT_VOLTAGE; - else if( firstChar == 'I' ) - traceType = SPT_CURRENT; - else if( firstChar == 'P' ) - traceType = SPT_POWER; - - if( aSignalName.EndsWith( gainSuffix ) ) - { - traceType |= SPT_AC_MAG; - baseSignal = aSignalName.Left( aSignalName.Length() - gainSuffix.Length() ); - } - else if( aSignalName.EndsWith( phaseSuffix ) ) - { - traceType |= SPT_AC_PHASE; - baseSignal = aSignalName.Left( aSignalName.Length() - phaseSuffix.Length() ); - } - - if( traceType != SPT_UNKNOWN ) - { - if( SIM_PLOT_PANEL* plotPanel = GetCurrentPlot() ) - updateTrace( baseSignal, (SIM_TRACE_TYPE) traceType, plotPanel ); - } + if( SIM_PLOT_PANEL* plotPanel = GetCurrentPlot() ) + updateTrace( aSignalName, (SIM_TRACE_TYPE) aTraceType, plotPanel ); } -void SIM_PLOT_FRAME::removeTrace( const wxString& aSignalName ) +void SIM_PLOT_FRAME::removeTrace( const wxString& aSignalName, SIM_TRACE_TYPE aTraceType ) { - SIM_PLOT_PANEL* plotPanel = GetCurrentPlot(); - - if( !plotPanel ) - return; - - wxASSERT( plotPanel->TraceShown( aSignalName ) ); - - if( plotPanel->DeleteTrace( aSignalName ) ) - OnModify(); - - plotPanel->GetPlotWin()->Fit(); + if( SIM_PLOT_PANEL* plotPanel = GetCurrentPlot() ) + { + plotPanel->DeleteTrace( getTraceTitle( aSignalName, aTraceType ) ); + plotPanel->GetPlotWin()->Fit(); + } updateSignalsGrid(); updateCursors(); + OnModify(); } @@ -1817,7 +1805,9 @@ void SIM_PLOT_FRAME::updateSignalsGrid() for( int row = 0; row < m_signalsGrid->GetNumberRows(); ++row ) { - if( TRACE* trace = plot ? plot->GetTrace( getTraceName( row ) ) : nullptr ) + wxString signal = m_signalsGrid->GetCellValue( row, COL_SIGNAL_NAME ); + + if( TRACE* trace = plot ? plot->GetTrace( getTraceName( signal ) ) : nullptr ) { m_signalsGrid->SetCellValue( row, COL_SIGNAL_SHOW, wxS( "1" ) ); @@ -2053,9 +2043,18 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath ) return false; } - param = file.GetNextLine(); + wxString baseName = name; + wxString gainSuffix = _( " (gain)" ); + wxString phaseSuffix = _( " (phase)" ); - addTrace( name ); + if( baseName.EndsWith( gainSuffix ) ) + baseName = baseName.Left( baseName.Length() - gainSuffix.Length() ); + else if( baseName.EndsWith( phaseSuffix ) ) + baseName = baseName.Left( baseName.Length() - phaseSuffix.Length() ); + + addTrace( baseName, (SIM_TRACE_TYPE) traceType ); + + param = file.GetNextLine(); SIM_PLOT_PANEL* plotPanel = GetCurrentPlot(); TRACE* trace = plotPanel ? plotPanel->GetTrace( name ) : nullptr; @@ -2063,17 +2062,16 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath ) if( version >= 4 && trace ) { auto addCursor = - []( int aCursorId, SIM_PLOT_PANEL* aPlotPanel, TRACE* aTrace, double x ) + [&]( int aCursorId, TRACE* aTrace, double x ) { - CURSOR* cursor = new CURSOR( aTrace, aPlotPanel ); - mpWindow* win = aPlotPanel->GetPlotWin(); + CURSOR* cursor = new CURSOR( aTrace, plotPanel ); - cursor->SetName( aTrace->GetName() ); + cursor->SetName( name ); cursor->SetPen( wxPen( aTrace->GetTraceColour() ) ); cursor->SetCoordX( x ); aTrace->SetCursor( aCursorId, cursor ); - win->AddLayer( cursor ); + plotPanel->GetPlotWin()->AddLayer( cursor ); }; wxArrayString items = wxSplit( param, '|' ); @@ -2097,7 +2095,7 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath ) parts[0].AfterFirst( '=' ).ToDouble( &val ); m_cursorFormats[0][0].FromString( parts[1] ); m_cursorFormats[0][1].FromString( parts[2] ); - addCursor( 1, plotPanel, trace, val ); + addCursor( 1, trace, val ); } } else if( item.StartsWith( wxS( "cursor2" ) ) ) @@ -2110,7 +2108,7 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath ) parts[0].AfterFirst( '=' ).ToDouble( &val ); m_cursorFormats[1][0].FromString( parts[1] ); m_cursorFormats[1][1].FromString( parts[2] ); - addCursor( 2, plotPanel, trace, val ); + addCursor( 2, trace, val ); } } else if( item.StartsWith( wxS( "cursorD" ) ) ) @@ -2165,6 +2163,28 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath ) LoadSimulator(); rebuildSignalsList(); + + if( SIM_PLOT_PANEL* plotPanel = GetCurrentPlot() ) + { + for( const auto& [ traceName, trace ] : plotPanel->GetTraces() ) + { + for( int cursorId : { 1, 2 } ) + { + if( CURSOR* cursor = trace->GetCursor( cursorId ) ) + { + for( const auto& [ signalName, vecName ] : m_userDefinedSignalToSpiceVecName ) + { + if( vecName == traceName ) + { + cursor->SetName( signalName ); + break; + } + } + } + } + } + } + rebuildSignalsGrid( m_filter->GetValue() ); updateSignalsGrid(); updateCursors(); @@ -2576,7 +2596,10 @@ void SIM_PLOT_FRAME::updateCursors() auto formatValue = [this]( double aValue, int aCursorId, int aCol ) -> wxString { - return SPICE_VALUE( aValue ).ToString( m_cursorFormats[ aCursorId ][ aCol ] ); + if( !m_simFinished && aCol == 1 ) + return wxS( "--" ); + else + return SPICE_VALUE( aValue ).ToString( m_cursorFormats[ aCursorId ][ aCol ] ); }; for( const auto& [name, trace] : plotPanel->GetTraces() ) @@ -2843,7 +2866,7 @@ void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent ) if( placeholder.m_current ) updateTrace( placeholder.m_name, placeholder.m_type, plotPanel ); else - removeTrace( placeholder.m_name ); + removeTrace( placeholder.m_name, placeholder.m_type ); } rebuildSignalsGrid( m_filter->GetValue() ); @@ -2890,6 +2913,8 @@ void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent ) m_schematicFrame->RefreshOperatingPointDisplay(); + updateCursors(); + for( int row = 0; row < m_measurementsGrid->GetNumberRows(); ++row ) UpdateMeasurement( row ); diff --git a/eeschema/sim/sim_plot_frame.h b/eeschema/sim/sim_plot_frame.h index 43817dc935..dcc96c400b 100644 --- a/eeschema/sim/sim_plot_frame.h +++ b/eeschema/sim/sim_plot_frame.h @@ -262,13 +262,12 @@ private: */ void doAddPlot( const wxString& aName, SIM_TRACE_TYPE aType ); - void addTrace( const wxString& aSignalName ); + void addTrace( const wxString& aSignalName, SIM_TRACE_TYPE aType ); /** * For user-defined traces we have a separate SPICE vector name. */ wxString getTraceName( const wxString& aSignalName ); - wxString getTraceName( int aRow ); /** * AC-small-signal analyses have specific trace titles. Other analyses use the raw signal @@ -279,17 +278,16 @@ private: /** * Remove a plot with a specific title. * - * @param aSignalName is the full plot title (e.g. I(Net-C1-Pad1)). + * @param aName is the SPICE vector name, such as "I(Net-C1-Pad1)". */ - void removeTrace( const wxString& aSignalName ); + void removeTrace( const wxString& aName, SIM_TRACE_TYPE aTraceType ); /** * Update a trace in a particular SIM_PLOT_PANEL. If the panel does not contain the given * trace, then add it. * - * @param aName is the device/net name. + * @param aName is the SPICE vector name, such as "I(Net-C1-Pad1)". * @param aTraceType describes the type of plot. - * @param aParam is the parameter for the device/net (e.g. I, Id, V). * @param aPlotPanel is the panel that should receive the update. */ void updateTrace( const wxString& aName, SIM_TRACE_TYPE aTraceType, SIM_PLOT_PANEL* aPlotPanel ); diff --git a/eeschema/sim/sim_plot_panel.cpp b/eeschema/sim/sim_plot_panel.cpp index ccef8ec6e2..c100d52a00 100644 --- a/eeschema/sim/sim_plot_panel.cpp +++ b/eeschema/sim/sim_plot_panel.cpp @@ -802,9 +802,10 @@ bool SIM_PLOT_PANEL::DeleteTrace( const wxString& aName ) } -void SIM_PLOT_PANEL::EnableCursor( const wxString& aName, int aCursorId, bool aEnable ) +void SIM_PLOT_PANEL::EnableCursor( const wxString& aSignalName, const wxString aTraceName, + int aCursorId, bool aEnable ) { - TRACE* t = GetTrace( aName ); + TRACE* t = GetTrace( aTraceName ); if( t == nullptr || t->HasCursor( aCursorId ) == aEnable ) return; @@ -816,7 +817,7 @@ void SIM_PLOT_PANEL::EnableCursor( const wxString& aName, int aCursorId, bool aE int width = win->GetXScreen() - win->GetMarginLeft() - win->GetMarginRight(); int center = win->GetMarginLeft() + KiROUND( width * ( aCursorId == 1 ? 0.4 : 0.6 ) ); - cursor->SetName( aName ); + cursor->SetName( aSignalName ); cursor->SetX( center ); cursor->SetPen( wxPen( m_colors.GetPlotColor( SIM_PLOT_COLORS::COLOR_SET::CURSOR ) ) ); diff --git a/eeschema/sim/sim_plot_panel.h b/eeschema/sim/sim_plot_panel.h index 3edaad932f..3e2f48e4e5 100644 --- a/eeschema/sim/sim_plot_panel.h +++ b/eeschema/sim/sim_plot_panel.h @@ -282,7 +282,7 @@ public: } ///< Toggle cursor for a particular trace. - void EnableCursor( const wxString& aName, int aCursorId, bool aEnable ); + void EnableCursor( const wxString& aSignalName, const wxString aTraceName, int aCursorId, bool aEnable ); ///< Reset scale ranges to fit the current traces. void ResetScales();