ADDED user-defined signals.

This commit is contained in:
Jeff Young 2023-02-21 09:06:02 +00:00
parent ae0cf19923
commit 6fcb95b24e
19 changed files with 1163 additions and 116 deletions

View File

@ -60,8 +60,10 @@ wxSize GRID_CELL_ESCAPED_TEXT_RENDERER::GetBestSize( wxGrid & aGrid, wxGridCellA
//-------- GRID_CELL_STC_EDITOR -----------------------------------------------------------------
//
GRID_CELL_STC_EDITOR::GRID_CELL_STC_EDITOR( std::function<void( wxStyledTextEvent&,
GRID_CELL_STC_EDITOR::GRID_CELL_STC_EDITOR( bool aIgnoreCase,
std::function<void( wxStyledTextEvent&,
SCINTILLA_TRICKS* )> aOnChar ) :
m_ignoreCase( aIgnoreCase ),
m_onChar( aOnChar )
{ }
@ -79,6 +81,7 @@ void GRID_CELL_STC_EDITOR::Create( wxWindow* aParent, wxWindowID aId, wxEvtHandl
stc_ctrl()->SetMarginWidth( 1, 0 ); // Line-number margin
stc_ctrl()->SetEOLMode( wxSTC_EOL_LF );
stc_ctrl()->AutoCompSetMaxWidth( 25 );
stc_ctrl()->AutoCompSetIgnoreCase( m_ignoreCase );
stc_ctrl()->UsePopUp( 0 );
// A hack which causes Scintilla to auto-size the text editor canvas

View File

@ -351,6 +351,8 @@ if( KICAD_SPICE )
dialogs/dialog_sim_format_value_base.cpp
dialogs/dialog_sim_model.cpp
dialogs/dialog_sim_model_base.cpp
dialogs/dialog_user_defined_signals.cpp
dialogs/dialog_user_defined_signals_base.cpp
tools/simulator_control.cpp
sim/ngspice_circuit_model.cpp
sim/ngspice.cpp

View File

@ -0,0 +1,226 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <scintilla_tricks.h>
#include <widgets/std_bitmap_button.h>
#include <widgets/grid_text_helpers.h>
#include <grid_tricks.h>
#include <dialogs/html_message_box.h>
#include <../sim/sim_plot_frame.h>
#include <dialog_user_defined_signals.h>
DIALOG_USER_DEFINED_SIGNALS::DIALOG_USER_DEFINED_SIGNALS( SIM_PLOT_FRAME* aParent,
std::vector<wxString>* aSignals ) :
DIALOG_USER_DEFINED_SIGNALS_BASE( aParent ),
m_frame( aParent ),
m_signals( aSignals ),
m_helpWindow( nullptr )
{
m_grid->PushEventHandler( new GRID_TRICKS( m_grid ) );
for( const wxString& signal : *m_signals )
addGridRow( signal );
m_addButton->SetBitmap( KiBitmap( BITMAPS::small_plus ) );
m_deleteButton->SetBitmap( KiBitmap( BITMAPS::small_trash ) );
SetupStandardButtons();
Layout();
// Now all widgets have the size fixed, call FinishDialogSettings
finishDialogSettings();
}
DIALOG_USER_DEFINED_SIGNALS::~DIALOG_USER_DEFINED_SIGNALS()
{
// Delete the GRID_TRICKS.
m_grid->PopEventHandler( true );
if( m_helpWindow )
m_helpWindow->Destroy();
}
bool DIALOG_USER_DEFINED_SIGNALS::TransferDataToWindow()
{
if( !wxDialog::TransferDataToWindow() )
return false;
return true;
}
void DIALOG_USER_DEFINED_SIGNALS::addGridRow( const wxString& aText )
{
int row = m_grid->GetNumberRows();
m_grid->AppendRows();
m_grid->SetCellValue( row, 0, aText );
wxGridCellAttr* attr = new wxGridCellAttr;
attr->SetEditor( new GRID_CELL_STC_EDITOR( true,
[this]( wxStyledTextEvent& aEvent, SCINTILLA_TRICKS* aScintillaTricks )
{
onScintillaCharAdded( aEvent, aScintillaTricks );
} ) );
m_grid->SetAttr( row, 0, attr );
}
void DIALOG_USER_DEFINED_SIGNALS::onAddSignal( wxCommandEvent& event )
{
if( !m_grid->CommitPendingChanges() )
return;
addGridRow( wxEmptyString );
m_grid->MakeCellVisible( m_grid->GetNumberRows() - 1, 0 );
m_grid->SetGridCursor( m_grid->GetNumberRows() - 1, 0 );
m_grid->EnableCellEditControl( true );
m_grid->ShowCellEditControl();
}
void DIALOG_USER_DEFINED_SIGNALS::onDeleteSignal( wxCommandEvent& event )
{
int curRow = m_grid->GetGridCursorRow();
if( curRow < 0 || m_grid->GetNumberRows() <= curRow )
return;
m_grid->CommitPendingChanges( true /* silent mode; we don't care if it's valid */ );
m_grid->DeleteRows( curRow, 1 );
m_grid->MakeCellVisible( std::max( 0, curRow-1 ), m_grid->GetGridCursorCol() );
m_grid->SetGridCursor( std::max( 0, curRow-1 ), m_grid->GetGridCursorCol() );
}
void DIALOG_USER_DEFINED_SIGNALS::onScintillaCharAdded( wxStyledTextEvent &aEvent,
SCINTILLA_TRICKS* aTricks )
{
wxStyledTextCtrl* textCtrl = aTricks->Scintilla();
wxArrayString tokens;
for( const wxString& signal : m_frame->Signals() )
tokens.push_back( signal );
tokens.push_back( wxS( "sqrt(x)" ) );
tokens.push_back( wxS( "sin(x)" ) );
tokens.push_back( wxS( "cos(x)" ) );
tokens.push_back( wxS( "tan(x)" ) );
tokens.push_back( wxS( "sinh(x)" ) );
tokens.push_back( wxS( "cosh(x)" ) );
tokens.push_back( wxS( "tanh(x)" ) );
tokens.push_back( wxS( "asin(x)" ) );
tokens.push_back( wxS( "acos(x)" ) );
tokens.push_back( wxS( "atan(x)" ) );
tokens.push_back( wxS( "asinh(x)" ) );
tokens.push_back( wxS( "acosh(x)" ) );
tokens.push_back( wxS( "atanh(x)" ) );
tokens.push_back( wxS( "arctan(x)" ) );
tokens.push_back( wxS( "exp(x)" ) );
tokens.push_back( wxS( "ln(x)" ) );
tokens.push_back( wxS( "log(x)" ) );
tokens.push_back( wxS( "abs(x)" ) );
tokens.push_back( wxS( "nint(x)" ) );
tokens.push_back( wxS( "int(x)" ) );
tokens.push_back( wxS( "floor(x)" ) );
tokens.push_back( wxS( "ceil(x)" ) );
tokens.push_back( wxS( "pow(x,y)" ) );
tokens.push_back( wxS( "pwr(x,y)" ) );
tokens.push_back( wxS( "min(x,y)" ) );
tokens.push_back( wxS( "max(x,y)" ) );
tokens.push_back( wxS( "sgn(x)" ) );
tokens.push_back( wxS( "ternary_fcn(x,y,z)" ) );
tokens.push_back( wxS( "gauss(nom,rvar,sigma)" ) );
tokens.push_back( wxS( "agauss(nom,avar,sigma)" ) );
tokens.push_back( wxS( "unif(nom,rvar)" ) );
tokens.push_back( wxS( "aunif(nom,avar)" ) );
tokens.push_back( wxS( "limit(nom,avar)" ) );
int text_pos = textCtrl->GetCurrentPos();
int start = textCtrl->WordStartPosition( text_pos, true );
int parenCount = 0;
for( start = text_pos - 1; start > 0; start-- )
{
wxUniChar c = textCtrl->GetCharAt( start );
if( c == '(' )
{
if( parenCount )
{
start += 1;
break;
}
else
{
parenCount++;
}
}
else if( wxIsalpha( c ) && parenCount )
{
break;
}
else if( !wxIsalnum( c ) && c != '/' )
{
start += 1;
break;
}
}
wxString partial = textCtrl->GetRange( start, text_pos );
aTricks->DoAutocomplete( partial, tokens );
textCtrl->SetFocus();
}
bool DIALOG_USER_DEFINED_SIGNALS::TransferDataFromWindow()
{
if( !wxDialog::TransferDataFromWindow() )
return false;
if( !m_grid->CommitPendingChanges() )
return false;
m_signals->clear();
for( int ii = 0; ii < m_grid->GetNumberRows(); ++ii )
m_signals->push_back( m_grid->GetCellValue( ii, 0 ) );
return true;
}
void DIALOG_USER_DEFINED_SIGNALS::OnFormattingHelp( wxHyperlinkEvent& aEvent )
{
m_helpWindow = SCH_TEXT::ShowSyntaxHelp( this );
}

View File

@ -0,0 +1,61 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef DIALOG_USER_DEFINED_SIGNALS_H
#define DIALOG_USER_DEFINED_SIGNALS_H
#include <dialog_user_defined_signals_base.h>
class SIM_PLOT_FRAME;
class SCINTILLA_TRICKS;
class HTML_MESSAGE_BOX;
class DIALOG_USER_DEFINED_SIGNALS : public DIALOG_USER_DEFINED_SIGNALS_BASE
{
public:
DIALOG_USER_DEFINED_SIGNALS( SIM_PLOT_FRAME* parent, std::vector<wxString>* aSignals );
~DIALOG_USER_DEFINED_SIGNALS();
private:
void addGridRow( const wxString& aValue );
void onAddSignal( wxCommandEvent& event ) override;
void onDeleteSignal( wxCommandEvent& event ) override;
void onScintillaCharAdded( wxStyledTextEvent &aEvent, SCINTILLA_TRICKS* aTricks );
void OnFormattingHelp( wxHyperlinkEvent& aEvent ) override;
bool TransferDataToWindow() override;
bool TransferDataFromWindow() override;
private:
SIM_PLOT_FRAME* m_frame;
std::vector<wxString>* m_signals;
HTML_MESSAGE_BOX* m_helpWindow;
};
#endif // DIALOG_USER_DEFINED_SIGNALS_H

View File

@ -0,0 +1,114 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "widgets/std_bitmap_button.h"
#include "widgets/wx_grid.h"
#include "widgets/wx_infobar.h"
#include "dialog_user_defined_signals_base.h"
///////////////////////////////////////////////////////////////////////////
DIALOG_USER_DEFINED_SIGNALS_BASE::DIALOG_USER_DEFINED_SIGNALS_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
wxBoxSizer* bMainSizer;
bMainSizer = new wxBoxSizer( wxVERTICAL );
m_infoBar = new WX_INFOBAR( this );
m_infoBar->SetShowHideEffects( wxSHOW_EFFECT_NONE, wxSHOW_EFFECT_NONE );
m_infoBar->SetEffectDuration( 500 );
m_infoBar->Hide();
bMainSizer->Add( m_infoBar, 0, wxEXPAND|wxBOTTOM, 5 );
m_grid = new WX_GRID( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
// Grid
m_grid->CreateGrid( 0, 1 );
m_grid->EnableEditing( true );
m_grid->EnableGridLines( true );
m_grid->EnableDragGridSize( false );
m_grid->SetMargins( 0, 0 );
// Columns
m_grid->SetColSize( 0, 400 );
m_grid->EnableDragColMove( false );
m_grid->EnableDragColSize( true );
m_grid->SetColLabelSize( 0 );
m_grid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
// Rows
m_grid->EnableDragRowSize( false );
m_grid->SetRowLabelSize( 0 );
m_grid->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
// Label Appearance
// Cell Defaults
m_grid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
m_grid->SetMinSize( wxSize( -1,120 ) );
bMainSizer->Add( m_grid, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 10 );
bButtonSize = new wxBoxSizer( wxHORIZONTAL );
m_addButton = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
m_addButton->SetToolTip( _("Add field") );
bButtonSize->Add( m_addButton, 0, wxTOP|wxRIGHT, 5 );
bButtonSize->Add( 20, 0, 0, wxEXPAND, 5 );
m_deleteButton = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
m_deleteButton->SetToolTip( _("Delete field") );
bButtonSize->Add( m_deleteButton, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
bButtonSize->Add( 0, 0, 1, wxEXPAND, 5 );
m_syntaxHelp = new wxHyperlinkCtrl( this, wxID_ANY, _("Syntax help"), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
m_syntaxHelp->SetToolTip( _("Show syntax help window") );
bButtonSize->Add( m_syntaxHelp, 0, wxTOP|wxRIGHT, 4 );
bMainSizer->Add( bButtonSize, 0, wxEXPAND|wxRIGHT|wxLEFT, 10 );
m_sdbSizer1 = new wxStdDialogButtonSizer();
m_sdbSizer1OK = new wxButton( this, wxID_OK );
m_sdbSizer1->AddButton( m_sdbSizer1OK );
m_sdbSizer1Cancel = new wxButton( this, wxID_CANCEL );
m_sdbSizer1->AddButton( m_sdbSizer1Cancel );
m_sdbSizer1->Realize();
bMainSizer->Add( m_sdbSizer1, 0, wxALL|wxEXPAND, 5 );
this->SetSizer( bMainSizer );
this->Layout();
bMainSizer->Fit( this );
// Connect Events
m_grid->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_USER_DEFINED_SIGNALS_BASE::onGridCellClick ), NULL, this );
m_addButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_USER_DEFINED_SIGNALS_BASE::onAddSignal ), NULL, this );
m_deleteButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_USER_DEFINED_SIGNALS_BASE::onDeleteSignal ), NULL, this );
m_syntaxHelp->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( DIALOG_USER_DEFINED_SIGNALS_BASE::OnFormattingHelp ), NULL, this );
}
DIALOG_USER_DEFINED_SIGNALS_BASE::~DIALOG_USER_DEFINED_SIGNALS_BASE()
{
// Disconnect Events
m_grid->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_USER_DEFINED_SIGNALS_BASE::onGridCellClick ), NULL, this );
m_addButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_USER_DEFINED_SIGNALS_BASE::onAddSignal ), NULL, this );
m_deleteButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_USER_DEFINED_SIGNALS_BASE::onDeleteSignal ), NULL, this );
m_syntaxHelp->Disconnect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( DIALOG_USER_DEFINED_SIGNALS_BASE::OnFormattingHelp ), NULL, this );
}

View File

@ -0,0 +1,477 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<wxFormBuilder_Project>
<FileVersion major="1" minor="16" />
<object class="Project" expanded="1">
<property name="class_decoration"></property>
<property name="code_generation">C++</property>
<property name="disconnect_events">1</property>
<property name="disconnect_mode">source_name</property>
<property name="disconnect_php_events">0</property>
<property name="disconnect_python_events">0</property>
<property name="embedded_files_path">res</property>
<property name="encoding">UTF-8</property>
<property name="event_generation">connect</property>
<property name="file">dialog_user_defined_signals_base</property>
<property name="first_id">1000</property>
<property name="help_provider">none</property>
<property name="image_path_wrapper_function_name"></property>
<property name="indent_with_spaces"></property>
<property name="internationalize">1</property>
<property name="name">dialog_user_defined_signals_base</property>
<property name="namespace"></property>
<property name="path">.</property>
<property name="precompiled_header"></property>
<property name="relative_path">1</property>
<property name="skip_lua_events">1</property>
<property name="skip_php_events">1</property>
<property name="skip_python_events">1</property>
<property name="ui_table">UI</property>
<property name="use_array_enum">0</property>
<property name="use_enum">1</property>
<property name="use_microsoft_bom">0</property>
<object class="Dialog" expanded="1">
<property name="aui_managed">0</property>
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
<property name="bg"></property>
<property name="center"></property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="enabled">1</property>
<property name="event_handler">impl_virtual</property>
<property name="extra_style"></property>
<property name="fg"></property>
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size"></property>
<property name="name">DIALOG_USER_DEFINED_SIGNALS_BASE</property>
<property name="pos"></property>
<property name="size">-1,-1</property>
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
<property name="title">User-defined Signals</property>
<property name="tooltip"></property>
<property name="two_step_creation">0</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bMainSizer</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxBOTTOM</property>
<property name="proportion">0</property>
<object class="wxInfoBar" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="duration">500</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">1</property>
<property name="hide_effect">wxSHOW_EFFECT_NONE</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_infoBar</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="show_effect">wxSHOW_EFFECT_NONE</property>
<property name="size"></property>
<property name="subclass">WX_INFOBAR; widgets/wx_infobar.h; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">10</property>
<property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxGrid" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="autosize_cols">0</property>
<property name="autosize_rows">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="cell_bg"></property>
<property name="cell_font"></property>
<property name="cell_horiz_alignment">wxALIGN_LEFT</property>
<property name="cell_text"></property>
<property name="cell_vert_alignment">wxALIGN_TOP</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="col_label_horiz_alignment">wxALIGN_CENTER</property>
<property name="col_label_size">0</property>
<property name="col_label_values"></property>
<property name="col_label_vert_alignment">wxALIGN_CENTER</property>
<property name="cols">1</property>
<property name="column_sizes">400</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_col_move">0</property>
<property name="drag_col_size">1</property>
<property name="drag_grid_size">0</property>
<property name="drag_row_size">0</property>
<property name="editing">1</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="grid_line_color"></property>
<property name="grid_lines">1</property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label_bg"></property>
<property name="label_font"></property>
<property name="label_text"></property>
<property name="margin_height">0</property>
<property name="margin_width">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size">-1,120</property>
<property name="moveable">1</property>
<property name="name">m_grid</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="row_label_horiz_alignment">wxALIGN_CENTER</property>
<property name="row_label_size">0</property>
<property name="row_label_values"></property>
<property name="row_label_vert_alignment">wxALIGN_CENTER</property>
<property name="row_sizes"></property>
<property name="rows">0</property>
<property name="show">1</property>
<property name="size"></property>
<property name="subclass">WX_GRID; widgets/wx_grid.h; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnGridCellLeftClick">onGridCellClick</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">10</property>
<property name="flag">wxEXPAND|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bButtonSize</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">protected</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxTOP|wxRIGHT</property>
<property name="proportion">0</property>
<object class="wxBitmapButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="auth_needed">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="bitmap"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="current"></property>
<property name="default">0</property>
<property name="default_pane">0</property>
<property name="disabled"></property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="focus"></property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Add Field</property>
<property name="margins"></property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size">-1,-1</property>
<property name="moveable">1</property>
<property name="name">m_addButton</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="position"></property>
<property name="pressed"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Add field</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnButtonClick">onAddSignal</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">0</property>
<object class="spacer" expanded="1">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">20</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxTOP|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxBitmapButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="auth_needed">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="bitmap"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="current"></property>
<property name="default">0</property>
<property name="default_pane">0</property>
<property name="disabled"></property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="focus"></property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Delete Field</property>
<property name="margins"></property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size">-1,-1</property>
<property name="moveable">1</property>
<property name="name">m_deleteButton</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="position"></property>
<property name="pressed"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Delete field</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnButtonClick">onDeleteSignal</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="spacer" expanded="1">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
<object class="sizeritem" expanded="0">
<property name="border">4</property>
<property name="flag">wxTOP|wxRIGHT</property>
<property name="proportion">0</property>
<object class="wxHyperlinkCtrl" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="hover_color"></property>
<property name="id">wxID_ANY</property>
<property name="label">Syntax help</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_syntaxHelp</property>
<property name="normal_color"></property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxHL_DEFAULT_STYLE</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Show syntax help window</property>
<property name="url"></property>
<property name="visited_color"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnHyperlink">OnFormattingHelp</event>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxStdDialogButtonSizer" expanded="1">
<property name="Apply">0</property>
<property name="Cancel">1</property>
<property name="ContextHelp">0</property>
<property name="Help">0</property>
<property name="No">0</property>
<property name="OK">1</property>
<property name="Save">0</property>
<property name="Yes">0</property>
<property name="minimum_size"></property>
<property name="name">m_sdbSizer1</property>
<property name="permission">protected</property>
</object>
</object>
</object>
</object>
</object>
</wxFormBuilder_Project>

View File

@ -0,0 +1,68 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#pragma once
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/intl.h>
class STD_BITMAP_BUTTON;
class WX_GRID;
class WX_INFOBAR;
#include "dialog_shim.h"
#include <wx/infobar.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/string.h>
#include <wx/grid.h>
#include <wx/bmpbuttn.h>
#include <wx/bitmap.h>
#include <wx/image.h>
#include <wx/icon.h>
#include <wx/button.h>
#include <wx/hyperlink.h>
#include <wx/sizer.h>
#include <wx/dialog.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class DIALOG_USER_DEFINED_SIGNALS_BASE
///////////////////////////////////////////////////////////////////////////////
class DIALOG_USER_DEFINED_SIGNALS_BASE : public DIALOG_SHIM
{
private:
protected:
WX_INFOBAR* m_infoBar;
WX_GRID* m_grid;
wxBoxSizer* bButtonSize;
STD_BITMAP_BUTTON* m_addButton;
STD_BITMAP_BUTTON* m_deleteButton;
wxHyperlinkCtrl* m_syntaxHelp;
wxStdDialogButtonSizer* m_sdbSizer1;
wxButton* m_sdbSizer1OK;
wxButton* m_sdbSizer1Cancel;
// Virtual event handlers, override them in your derived class
virtual void onGridCellClick( wxGridEvent& event ) { event.Skip(); }
virtual void onAddSignal( wxCommandEvent& event ) { event.Skip(); }
virtual void onDeleteSignal( wxCommandEvent& event ) { event.Skip(); }
virtual void OnFormattingHelp( wxHyperlinkEvent& event ) { event.Skip(); }
public:
DIALOG_USER_DEFINED_SIGNALS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("User-defined Signals"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~DIALOG_USER_DEFINED_SIGNALS_BASE();
};

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016-2022 CERN
* Copyright (C) 2018-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2018-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Maciej Suminski <maciej.suminski@cern.ch>
@ -567,7 +567,9 @@ void NGSPICE::init_dll()
// Workarounds to avoid hang ups on certain errors
// These commands have to be called, no matter what is in the spinit file
Command( "unset interactive" );
// We have to allow interactive for user-defined signals. Hopefully whatever bug this was
// meant to address has gone away in the last 5 years...
//Command( "unset interactive" );
Command( "set noaskquit" );
Command( "set nomoremode" );

View File

@ -56,6 +56,8 @@
#include "sim_plot_panel.h"
#include "spice_simulator.h"
#include "spice_reporter.h"
#include "core/kicad_algo.h"
#include "fmt/format.h"
#include <dialog_sim_format_value.h>
#include <eeschema_settings.h>
@ -772,16 +774,28 @@ void SIM_PLOT_FRAME::rebuildSignalsList()
unconnected.Replace( '(', '_' ); // Convert to SPICE markup
auto addSignal =
[&]( const wxString& aSignal )
[&]( const wxString& aSignal, const wxString& aSpiceVecName = wxEmptyString )
{
if( simType == ST_AC )
{
m_signals.push_back( wxString::Format( _( "%s (gain)" ), aSignal ) );
m_signals.push_back( wxString::Format( _( "%s (phase)" ), aSignal ) );
wxString gain = _( " (gain)" );
wxString phase = _( " (phase)" );
m_signals.push_back( aSignal + gain );
m_signals.push_back( aSignal + phase );
if( !aSpiceVecName.IsEmpty() )
{
m_userDefinedSignalToSpiceVecName[ aSignal + gain ] = aSpiceVecName + gain;
m_userDefinedSignalToSpiceVecName[ aSignal + phase ] = aSpiceVecName + phase;
}
}
else
{
m_signals.push_back( aSignal );
if( !aSpiceVecName.IsEmpty() )
m_userDefinedSignalToSpiceVecName[ aSignal ] = aSpiceVecName;
}
};
@ -795,6 +809,7 @@ void SIM_PLOT_FRAME::rebuildSignalsList()
if( netname == "GND" || netname == "0" || netname.StartsWith( unconnected ) )
continue;
m_quotedNetnames[ netname ] = wxString::Format( wxS( "\"%s\"" ), netname );
addSignal( wxString::Format( wxS( "V(%s)" ), netname ) );
}
}
@ -838,6 +853,23 @@ void SIM_PLOT_FRAME::rebuildSignalsList()
}
}
// JEY TODO: find and add LET commands
// 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 );
}
}
std::sort( m_signals.begin(), m_signals.end(),
[]( const wxString& lhs, const wxString& rhs )
{
@ -912,9 +944,6 @@ void SIM_PLOT_FRAME::StartSimulation()
if( !LoadSimulator() )
return;
rebuildSignalsList();
rebuildSignalsGrid( m_filter->GetValue() );
std::unique_lock<std::mutex> simulatorLock( m_simulator->GetMutex(), std::try_to_lock );
if( simulatorLock.owns_lock() )
@ -996,6 +1025,17 @@ void updateRangeUnits( wxString* aRange, const wxString& aUnits )
}
wxString SIM_PLOT_FRAME::getTraceName( int aRow )
{
wxString signalName = m_signalsGrid->GetCellValue( aRow, COL_SIGNAL_NAME );
if( alg::contains( m_userDefinedSignals, signalName ) )
signalName = m_userDefinedSignalToSpiceVecName[ signalName ];
return signalName;
}
void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent )
{
if( m_SuppressGridEvents > 0 )
@ -1009,55 +1049,18 @@ void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent )
if( col == COL_SIGNAL_SHOW )
{
if( text == wxS( "1" ) )
{
wxString signalName = m_signalsGrid->GetCellValue( row, COL_SIGNAL_NAME );
wxString baseSignal = signalName;
if( !signalName.IsEmpty() )
{
wxString gainSuffix = _( " (gain)" );
wxString phaseSuffix = _( " (phase)" );
wxUniChar firstChar = signalName.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( signalName.EndsWith( gainSuffix ) )
{
traceType |= SPT_AC_MAG;
baseSignal = signalName.Left( signalName.Length() - gainSuffix.Length() );
}
else if( signalName.EndsWith( phaseSuffix ) )
{
traceType |= SPT_AC_PHASE;
baseSignal = signalName.Left( signalName.Length() - phaseSuffix.Length() );
}
if( traceType != SPT_UNKNOWN )
{
addTrace( baseSignal, (SIM_TRACE_TYPE) traceType );
m_workbookModified = true;
}
}
}
addTrace( getTraceName( row ) );
else
{
removeTrace( m_signalsGrid->GetCellValue( row, COL_SIGNAL_NAME ) );
}
removeTrace( getTraceName( row ) );
// Update enabled/visible states of other controls
updateSignalsGrid();
m_workbookModified = true;
}
else if( col == COL_SIGNAL_COLOR )
{
KIGFX::COLOR4D color( m_signalsGrid->GetCellValue( row, COL_SIGNAL_COLOR ) );
wxString signalName = m_signalsGrid->GetCellValue( row, COL_SIGNAL_NAME );
TRACE* trace = plot->GetTrace( signalName );
TRACE* trace = plot->GetTrace( getTraceName( row ) );
if( trace )
{
@ -1071,10 +1074,9 @@ void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent )
{
for( int ii = 0; ii < m_signalsGrid->GetNumberRows(); ++ii )
{
wxString signalName = m_signalsGrid->GetCellValue( ii, COL_SIGNAL_NAME );
bool enable = ii == row && text == wxS( "1" );
bool enable = ii == row && text == wxS( "1" );
plot->EnableCursor( signalName, col == COL_CURSOR_1 ? 1 : 2, enable );
plot->EnableCursor( getTraceName( ii ), col == COL_CURSOR_1 ? 1 : 2, enable );
m_workbookModified = true;
}
@ -1229,15 +1231,13 @@ void SIM_PLOT_FRAME::updateMeasurement( int aRow )
void SIM_PLOT_FRAME::AddVoltagePlot( const wxString& aNetName )
{
addTrace( aNetName, SPT_VOLTAGE );
m_workbookModified = true;
doAddPlot( aNetName, SPT_VOLTAGE );
}
void SIM_PLOT_FRAME::AddCurrentPlot( const wxString& aDeviceName )
{
addTrace( aDeviceName, SPT_CURRENT );
m_workbookModified = true;
doAddPlot( aDeviceName, SPT_CURRENT );
}
@ -1357,7 +1357,7 @@ const NGSPICE_CIRCUIT_MODEL* SIM_PLOT_FRAME::GetExporter() const
}
void SIM_PLOT_FRAME::addTrace( const wxString& aName, SIM_TRACE_TYPE aType )
void SIM_PLOT_FRAME::doAddPlot( const wxString& aName, SIM_TRACE_TYPE aType )
{
SIM_PLOT_PANEL* plotPanel = GetCurrentPlot();
@ -1398,6 +1398,64 @@ void SIM_PLOT_FRAME::addTrace( const wxString& aName, SIM_TRACE_TYPE aType )
}
updateSignalsGrid();
m_workbookModified = true;
}
void SIM_PLOT_FRAME::SetUserDefinedSignals( const std::vector<wxString>& aNewSignals )
{
for( const wxString& signal : m_userDefinedSignals )
{
if( !alg::contains( aNewSignals, signal ) )
removeTrace( m_userDefinedSignalToSpiceVecName[ signal ] );
}
m_userDefinedSignals = aNewSignals;
if( m_simFinished )
applyUserDefinedSignals();
rebuildSignalsList();
rebuildSignalsGrid( m_filter->GetValue() );
updateSignalsGrid();
m_workbookModified = true;
}
void SIM_PLOT_FRAME::addTrace( const wxString& aSignalName )
{
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 );
}
}
@ -1425,6 +1483,9 @@ void SIM_PLOT_FRAME::updateTrace( const wxString& aName, SIM_TRACE_TYPE aTraceTy
{
SIM_TYPE simType = NGSPICE_CIRCUIT_MODEL::CommandToSimType( aPlotPanel->GetSimCommand() );
aTraceType = (SIM_TRACE_TYPE) ( aTraceType & SPT_Y_AXIS_MASK );
aTraceType = (SIM_TRACE_TYPE) ( aTraceType | getXAxisType( simType ) );
wxString traceTitle = aName;
wxString vectorName = aName;
@ -1538,9 +1599,7 @@ void SIM_PLOT_FRAME::updateSignalsGrid()
for( int row = 0; row < m_signalsGrid->GetNumberRows(); ++row )
{
wxString signal = m_signalsGrid->GetCellValue( row, COL_SIGNAL_NAME );
if( TRACE* trace = plot->GetTrace( signal ) )
if( TRACE* trace = plot->GetTrace( getTraceName( row ) ) )
{
m_signalsGrid->SetCellValue( row, COL_SIGNAL_SHOW, wxS( "1" ) );
@ -1598,6 +1657,27 @@ void SIM_PLOT_FRAME::updateSignalsGrid()
}
void SIM_PLOT_FRAME::applyUserDefinedSignals()
{
auto quoteNetNames =
[&]( wxString aExpression ) -> wxString
{
for( const auto& [netname, quotedNetname] : m_quotedNetnames )
aExpression.Replace( netname, quotedNetname );
return aExpression;
};
for( int ii = 0; ii < (int) m_userDefinedSignals.size(); ++ii )
{
wxString signal = m_userDefinedSignals[ii].Lower();
std::string cmd = "let user{} = {}";
m_simulator->Command( "echo " + fmt::format(cmd, ii, signal.ToStdString() ) );
m_simulator->Command( fmt::format( cmd, ii, quoteNetNames( signal ).ToStdString() ) );
}
}
void SIM_PLOT_FRAME::applyTuners()
{
wxString errors;
@ -1745,33 +1825,6 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath )
return false;
}
if( version <= 2 )
{
long legacyTraceType = traceType;
traceType = 0;
if( legacyTraceType & LEGACY_SPT_VOLTAGE )
traceType |= SPT_VOLTAGE;
if( legacyTraceType & LEGACY_SPT_CURRENT )
traceType |= SPT_CURRENT;
if( legacyTraceType & LEGACY_SPT_AC_PHASE )
traceType |= SPT_AC_PHASE;
if( legacyTraceType & LEGACY_SPT_AC_MAG )
traceType |= SPT_AC_MAG;
if( legacyTraceType & LEGACY_SPT_TIME )
traceType |= SPT_TIME;
if( legacyTraceType & LEGACY_SPT_LIN_FREQUENCY )
traceType |= SPT_LIN_FREQUENCY;
if( legacyTraceType & LEGACY_SPT_SWEEP )
traceType |= SPT_SWEEP;
}
name = file.GetNextLine();
if( name.IsEmpty() )
@ -1784,7 +1837,7 @@ bool SIM_PLOT_FRAME::LoadWorkbook( const wxString& aPath )
param = file.GetNextLine();
addTrace( name, (SIM_TRACE_TYPE) traceType );
addTrace( name );
SIM_PLOT_PANEL* plotPanel = GetCurrentPlot();
TRACE* trace = plotPanel ? plotPanel->GetTrace( name ) : nullptr;
@ -2459,6 +2512,8 @@ void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent )
m_simFinished = true;
applyUserDefinedSignals();
// If there are any signals plotted, update them
if( SIM_PANEL_BASE::IsPlottable( simType ) )
{
@ -2487,6 +2542,8 @@ void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent )
updateTrace( trace.m_name, trace.m_type, plotPanel );
rebuildSignalsGrid( m_filter->GetValue() );
updateSignalsGrid();
plotPanel->GetPlotWin()->UpdateAll();
plotPanel->ResetScales();
}

View File

@ -85,6 +85,11 @@ public:
*/
bool EditSimCommand();
const std::vector<wxString>& Signals() { return m_signals; }
const std::vector<wxString>& UserDefinedSignals() { return m_userDefinedSignals; }
void SetUserDefinedSignals( const std::vector<wxString>& aSignals );
/**
* Add a voltage plot for a given net name.
*
@ -255,7 +260,14 @@ private:
* @param aType describes the type of plot.
* @param aParam is the parameter for the device/net (e.g. I, Id, V).
*/
void addTrace( const wxString& aName, SIM_TRACE_TYPE aType );
void doAddPlot( const wxString& aName, SIM_TRACE_TYPE aType );
void addTrace( const wxString& aSignalName );
/**
* For user-defined traces we have a separate SPICE vector name.
*/
wxString getTraceName( int aRow );
/**
* Remove a plot with a specific title.
@ -302,6 +314,11 @@ private:
*/
void updateMeasurement( int aRow );
/**
* Apply user-defined signals to the SPICE session.
*/
void applyUserDefinedSignals();
/**
* Apply component values specified using tuner sliders to the current netlist.
*/
@ -365,8 +382,15 @@ private:
SIM_THREAD_REPORTER* m_reporter;
std::vector<wxString> m_signals;
std::vector<wxString> m_userDefinedSignals;
std::map<wxString, wxString> m_userDefinedSignalToSpiceVecName;
std::list<TUNER_SLIDER*> m_tuners;
///< SPICE expressions need quoted versions of the netnames since KiCad allows '-' and '/'
///< in netnames.
std::map<wxString, wxString> m_quotedNetnames;
///< Panel that was used as the most recent one for simulations
SIM_PANEL_BASE* m_lastSimPlot;

View File

@ -355,7 +355,7 @@ void CURSOR::Plot( wxDC& aDC, mpWindow& aWindow )
bool CURSOR::Inside( const wxPoint& aPoint ) const
{
if( !m_window )
if( !m_window || !m_trace )
return false;
return ( std::abs( (double) aPoint.x -

View File

@ -43,37 +43,24 @@ enum SIM_TYPE
};
///< Possible plot types
enum LEGACY_SIM_TRACE_TYPE
{
// Y axis
LEGACY_SPT_VOLTAGE = 0x01,
LEGACY_SPT_CURRENT = 0x02,
LEGACY_SPT_AC_PHASE = 0x04,
LEGACY_SPT_AC_MAG = 0x08,
// X axis
LEGACY_SPT_TIME = 0x10,
LEGACY_SPT_LIN_FREQUENCY = 0x20,
LEGACY_SPT_SWEEP = 0x40
};
enum SIM_TRACE_TYPE
{
// Y axis
SPT_VOLTAGE = 0x01,
SPT_CURRENT = 0x02,
SPT_AC_PHASE = 0x04,
SPT_AC_MAG = 0x08,
SPT_POWER = 0x10,
SPT_VOLTAGE = 0x0001,
SPT_CURRENT = 0x0002,
SPT_AC_PHASE = 0x0004,
SPT_AC_MAG = 0x0008,
SPT_POWER = 0x0010,
SPT_Y_AXIS_MASK = 0x00FF,
// X axis
SPT_TIME = 0x0100,
SPT_LIN_FREQUENCY = 0x0200,
SPT_LOG_FREQUENCY = 0x0400,
SPT_SWEEP = 0x0800,
SPT_X_AXIS_MASK = 0xFF00,
SPT_UNKNOWN = 0x00
SPT_UNKNOWN = 0x0000
};
#endif /* SIM_TYPES_H */

View File

@ -50,10 +50,10 @@ bool SPICE_SIMULATOR_SETTINGS::operator==( const SPICE_SIMULATOR_SETTINGS &aRhs
NGSPICE_SIMULATOR_SETTINGS::NGSPICE_SIMULATOR_SETTINGS(
JSON_SETTINGS* aParent, const std::string& aPath ) :
SPICE_SIMULATOR_SETTINGS( aParent, aPath ),
m_modelMode( NGSPICE_MODEL_MODE::USER_CONFIG )
m_modelMode( NGSPICE_MODEL_MODE::LT_PSPICE )
{
m_params.emplace_back( new PARAM_ENUM<NGSPICE_MODEL_MODE>( "model_mode", &m_modelMode,
NGSPICE_MODEL_MODE::USER_CONFIG,
NGSPICE_MODEL_MODE::LT_PSPICE,
NGSPICE_MODEL_MODE::USER_CONFIG,
NGSPICE_MODEL_MODE::HSPICE ) );
}

View File

@ -62,6 +62,7 @@ void SIM_PLOT_FRAME::ReCreateHToolbar()
m_toolBar->Add( EE_ACTIONS::simTune );
m_toolBar->AddScaledSeparator( this );
m_toolBar->Add( EE_ACTIONS::editUserDefinedSignals );
m_toolBar->Add( EE_ACTIONS::showNetlist );
// after adding the buttons to the toolbar, must call Realize() to reflect the changes

View File

@ -989,3 +989,9 @@ TOOL_ACTION EE_ACTIONS::showNetlist( "eeschema.Simulation.showNetlist",
_( "Show SPICE Netlist" ), "",
BITMAPS::netlist );
TOOL_ACTION EE_ACTIONS::editUserDefinedSignals( "eeschema.Simulation.editUserDefinedSignals",
AS_GLOBAL, 0, "",
_( "User-defined Signals" ),
_( "Add, edit or delete user-defined simulation signals" ),
BITMAPS::sim_add_signal );

View File

@ -258,6 +258,7 @@ public:
static TOOL_ACTION simCommand;
static TOOL_ACTION runSimulation;
static TOOL_ACTION stopSimulation;
static TOOL_ACTION editUserDefinedSignals;
static TOOL_ACTION showNetlist;
// Net highlighting

View File

@ -36,6 +36,7 @@
#include <tools/ee_actions.h>
#include <tools/simulator_control.h>
#include <scintilla_tricks.h>
#include <dialogs/dialog_user_defined_signals.h>
bool SIMULATOR_CONTROL::Init()
@ -377,6 +378,19 @@ public:
};
int SIMULATOR_CONTROL::EditUserDefinedSignals( const TOOL_EVENT& aEvent )
{
std::vector<wxString> userSignals = m_plotFrame->UserDefinedSignals();
DIALOG_USER_DEFINED_SIGNALS dlg( m_plotFrame, &userSignals );
if( dlg.ShowQuasiModal() == wxID_OK )
m_plotFrame->SetUserDefinedSignals( userSignals );
return 0;
}
int SIMULATOR_CONTROL::ShowNetlist( const TOOL_EVENT& aEvent )
{
if( m_schematicFrame == nullptr || m_simulator == nullptr )
@ -420,5 +434,6 @@ void SIMULATOR_CONTROL::setTransitions()
Go( &SIMULATOR_CONTROL::Probe, EE_ACTIONS::simProbe.MakeEvent() );
Go( &SIMULATOR_CONTROL::Tune, EE_ACTIONS::simTune.MakeEvent() );
Go( &SIMULATOR_CONTROL::EditUserDefinedSignals, EE_ACTIONS::editUserDefinedSignals.MakeEvent() );
Go( &SIMULATOR_CONTROL::ShowNetlist, EE_ACTIONS::showNetlist.MakeEvent() );
}

View File

@ -70,6 +70,7 @@ public:
int Probe( const TOOL_EVENT& aEvent );
int Tune( const TOOL_EVENT& aEvent );
int EditUserDefinedSignals( const TOOL_EVENT& aEvent );
int ShowNetlist( const TOOL_EVENT& aEvent );
private:

View File

@ -47,13 +47,14 @@ public:
class GRID_CELL_STC_EDITOR : public wxGridCellEditor
{
public:
GRID_CELL_STC_EDITOR( std::function<void( wxStyledTextEvent&, SCINTILLA_TRICKS* )> aOnChar );
GRID_CELL_STC_EDITOR( bool aIgnoreCase,
std::function<void( wxStyledTextEvent&, SCINTILLA_TRICKS* )> aOnChar );
void Create( wxWindow* aParent, wxWindowID aId, wxEvtHandler* aEventHandler ) override;
wxGridCellEditor* Clone() const override
{
return new GRID_CELL_STC_EDITOR( m_onChar );
return new GRID_CELL_STC_EDITOR( m_ignoreCase, m_onChar );
}
wxString GetValue() const override;
@ -71,6 +72,7 @@ protected:
protected:
SCINTILLA_TRICKS* m_scintillaTricks;
bool m_ignoreCase;
wxString m_value;
std::function<void( wxStyledTextEvent&, SCINTILLA_TRICKS* )> m_onChar;