ADDED operating point text variables for labels and symbols.

ADDED formatting for cursors and operationg points

Also fixes a bunch of bugs to make the new cursors work with .ac sims.

Fixes https://gitlab.com/kicad/code/kicad/issues/11253

Fixes https://gitlab.com/kicad/code/kicad/issues/6965
This commit is contained in:
Jeff Young 2023-02-05 20:47:27 +00:00
parent b3ffbd6258
commit 2a5bb71fbd
30 changed files with 1422 additions and 129 deletions

View File

@ -289,11 +289,11 @@ void GRID_TRICKS::getSelectedArea()
}
void GRID_TRICKS::onGridCellRightClick( wxGridEvent& )
void GRID_TRICKS::onGridCellRightClick( wxGridEvent& aEvent )
{
wxMenu menu;
showPopupMenu( menu );
showPopupMenu( menu, aEvent );
}
@ -320,7 +320,7 @@ void GRID_TRICKS::onGridLabelRightClick( wxGridEvent& )
}
void GRID_TRICKS::showPopupMenu( wxMenu& menu )
void GRID_TRICKS::showPopupMenu( wxMenu& menu, wxGridEvent& aEvent )
{
menu.Append( GRIDTRICKS_ID_CUT, _( "Cut" ) + "\tCtrl+X",
_( "Clear selected cells placing original contents on clipboard" ) );

View File

@ -24,7 +24,7 @@ LIB_TABLE_GRID_TRICKS::LIB_TABLE_GRID_TRICKS( WX_GRID* aGrid ) : GRID_TRICKS( aG
{
}
void LIB_TABLE_GRID_TRICKS::showPopupMenu( wxMenu& menu )
void LIB_TABLE_GRID_TRICKS::showPopupMenu( wxMenu& menu, wxGridEvent& aEvent )
{
bool showActivate = false;
bool showDeactivate = false;
@ -33,13 +33,9 @@ void LIB_TABLE_GRID_TRICKS::showPopupMenu( wxMenu& menu )
for( int row = m_sel_row_start; row < m_sel_row_start + m_sel_row_count; ++row )
{
if( tbl->GetValueAsBool( row, 0 ) )
{
showDeactivate = true;
}
else
{
showActivate = true;
}
if( showActivate && showDeactivate )
break;
@ -47,24 +43,25 @@ void LIB_TABLE_GRID_TRICKS::showPopupMenu( wxMenu& menu )
if( showActivate )
menu.Append( LIB_TABLE_GRID_TRICKS_ACTIVATE_SELECTED, _( "Activate selected" ) );
if( showDeactivate )
menu.Append( LIB_TABLE_GRID_TRICKS_DEACTIVATE_SELECTED, _( "Deactivate selected" ) );
menu.AppendSeparator();
GRID_TRICKS::showPopupMenu( menu );
GRID_TRICKS::showPopupMenu( menu, aEvent );
}
void LIB_TABLE_GRID_TRICKS::doPopupSelection( wxCommandEvent& event )
{
int menu_id = event.GetId();
if( menu_id == LIB_TABLE_GRID_TRICKS_ACTIVATE_SELECTED
|| menu_id == LIB_TABLE_GRID_TRICKS_DEACTIVATE_SELECTED )
{
LIB_TABLE_GRID* tbl = (LIB_TABLE_GRID*) m_grid->GetTable();
for( int row = m_sel_row_start; row < m_sel_row_start + m_sel_row_count; ++row )
{
tbl->SetValueAsBool( row, 0, menu_id == LIB_TABLE_GRID_TRICKS_ACTIVATE_SELECTED );
}
}
else
{

View File

@ -347,6 +347,8 @@ if( KICAD_SPICE )
${EESCHEMA_SRCS}
dialogs/dialog_sim_command.cpp
dialogs/dialog_sim_command_base.cpp
dialogs/dialog_sim_format_value.cpp
dialogs/dialog_sim_format_value_base.cpp
dialogs/dialog_sim_model.cpp
dialogs/dialog_sim_model_base.cpp
tools/simulator_control.cpp

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.com
* Copyright (C) 2016 Wayne Stambaugh, stambaughw@gmail.com
* Copyright (C) 2004-2022 KiCad Developers, see AITHORS.txt for contributors.
* Copyright (C) 2004-2023 KiCad Developers, see AITHORS.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
@ -35,6 +35,7 @@
#include <sch_edit_frame.h>
#include <ee_collectors.h>
#include <sch_symbol.h>
#include <sch_label.h>
#include <lib_field.h>
#include <template_fieldnames.h>
#include <symbol_library.h>
@ -44,6 +45,8 @@
#include <sch_text.h>
#include <scintilla_tricks.h>
#include <wildcards_and_files_ext.h>
#include <sim/sim_model.h>
#include <sim/sim_lib_mgr.h>
DIALOG_FIELD_PROPERTIES::DIALOG_FIELD_PROPERTIES( SCH_BASE_FRAME* aParent, const wxString& aTitle,
@ -584,32 +587,52 @@ void DIALOG_SCH_FIELD_PROPERTIES::onScintillaCharAdded( wxStyledTextEvent &aEven
{
partial = m_StyledTextCtrl->GetRange( start, pos );
wxString ref = m_StyledTextCtrl->GetRange( refStart, start - 1 );
SCH_SHEET_LIST sheets = editFrame->Schematic().GetSheets();
SCH_REFERENCE_LIST refs;
SCH_SYMBOL* refSymbol = nullptr;
wxString ref = m_StyledTextCtrl->GetRange( refStart, start - 1 );
sheets.GetSymbols( refs );
for( size_t jj = 0; jj < refs.GetCount(); jj++ )
if( ref == wxS( "OP" ) )
{
if( refs[ jj ].GetSymbol()->GetRef( &refs[ jj ].GetSheetPath(), true ) == ref )
// SPICE operating points use ':' syntax for ports
SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( m_field->GetParent() );
SCH_SHEET_PATH& sheet = editFrame->Schematic().CurrentSheet();
if( symbol )
{
refSymbol = refs[ jj ].GetSymbol();
break;
SIM_LIB_MGR mgr( &Prj() );
SIM_MODEL& model = mgr.CreateModel( &sheet, *symbol ).model;
for( const std::string& pin : model.GetPinNames() )
autocompleteTokens.push_back( pin );
}
}
else
{
SCH_SHEET_LIST sheets = editFrame->Schematic().GetSheets();
SCH_REFERENCE_LIST refs;
SCH_SYMBOL* refSymbol = nullptr;
if( refSymbol )
refSymbol->GetContextualTextVars( &autocompleteTokens );
sheets.GetSymbols( refs );
for( size_t jj = 0; jj < refs.GetCount(); jj++ )
{
if( refs[ jj ].GetSymbol()->GetRef( &refs[ jj ].GetSheetPath(), true ) == ref )
{
refSymbol = refs[ jj ].GetSymbol();
break;
}
}
if( refSymbol )
refSymbol->GetContextualTextVars( &autocompleteTokens );
}
}
}
else if( textVarRef( start ) )
{
partial = m_StyledTextCtrl->GetTextRange( start, pos );
SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( m_field->GetParent() );
SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( m_field->GetParent() );
SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( m_field->GetParent() );
SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( m_field->GetParent() );
SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( m_field->GetParent() );
if( symbol )
{
@ -624,6 +647,9 @@ void DIALOG_SCH_FIELD_PROPERTIES::onScintillaCharAdded( wxStyledTextEvent &aEven
if( sheet )
sheet->GetContextualTextVars( &autocompleteTokens );
if( label )
label->GetContextualTextVars( &autocompleteTokens );
for( std::pair<wxString, wxString> entry : Prj().GetTextVars() )
autocompleteTokens.push_back( entry.first );
}

View File

@ -0,0 +1,97 @@
/*
* 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 3
* 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:
* https://www.gnu.org/licenses/gpl-3.0.html
* or you may search the http://www.gnu.org website for the version 3 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <dialog_sim_format_value.h>
#include "sim/spice_value.h"
DIALOG_SIM_FORMAT_VALUE::DIALOG_SIM_FORMAT_VALUE( wxWindow* aParent, int* aPrecision,
wxString* aRange ) :
DIALOG_SIM_FORMAT_VALUE_BASE( aParent ),
m_precision( aPrecision ),
m_range( aRange )
{
m_units = aRange->Right( 1 );
if( m_units == wxS( "V" ) )
{
SetTitle( wxString::Format( GetTitle(), _( "Voltage" ) ) );
}
else if( m_units == wxS( "A" ) )
{
SetTitle( wxString::Format( GetTitle(), _( "Current" ) ) );
}
else if( m_units == wxS( "s" ) )
{
SetTitle( wxString::Format( GetTitle(), _( "Time" ) ) );
}
else if( aRange->Right( 2 ) == wxS( "Hz" ) )
{
m_units = aRange->Right( 2 );
SetTitle( wxString::Format( GetTitle(), _( "Frequency" ) ) );
}
else if( aRange->Right( 3 ) == wxS( "dBV" ) )
{
m_units = aRange->Right( 3 );
SetTitle( wxString::Format( GetTitle(), _( "Gain" ) ) );
}
else if( m_units == wxS( "°" ) )
{
SetTitle( wxString::Format( GetTitle(), _( "Phase" ) ) );
}
else
{
if( aRange->GetChar( 0 ) == '~' )
m_units = aRange->Right( aRange->Length() - 1 );
else if( SPICE_VALUE::ParseSIPrefix( aRange->GetChar( 0 ) ) != SPICE_VALUE::PFX_NONE )
m_units = aRange->Right( aRange->Length() - 1 );
else
m_units = *aRange;
SetTitle( wxString::Format( GetTitle(), _( "Value" ) ) );
}
m_precisionCtrl->SetValue( *aPrecision );
for( int ii = 1; ii < (int) m_rangeCtrl->GetCount(); ++ii )
m_rangeCtrl->SetString( ii, m_rangeCtrl->GetString( ii ) + m_units );
if( aRange->GetChar( 0 ) == '~' )
m_rangeCtrl->SetSelection( 0 );
else
m_rangeCtrl->SetStringSelection( *aRange );
}
bool DIALOG_SIM_FORMAT_VALUE::TransferDataFromWindow()
{
*m_precision = m_precisionCtrl->GetValue();
if( m_rangeCtrl->GetSelection() == 0 )
*m_range = wxS( "~" ) + m_units;
else
*m_range = m_rangeCtrl->GetStringSelection();
return true;
}

View File

@ -0,0 +1,44 @@
/*
* 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 3
* 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:
* https://www.gnu.org/licenses/gpl-3.0.html
* or you may search the http://www.gnu.org website for the version 3 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef DIALOG_SIM_FORMAT_VALUE_H
#define DIALOG_SIM_FORMAT_VALUE_H
#include <dialog_sim_format_value_base.h>
class DIALOG_SIM_FORMAT_VALUE : public DIALOG_SIM_FORMAT_VALUE_BASE
{
public:
DIALOG_SIM_FORMAT_VALUE( wxWindow* aParent, int* aPrecision, wxString* aRange );
private:
bool TransferDataFromWindow() override;
private:
int* m_precision;
wxString* m_range;
wxString m_units;
};
#endif /* DIALOG_SIM_FORMAT_VALUE_H */

View File

@ -0,0 +1,76 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "dialog_sim_format_value_base.h"
///////////////////////////////////////////////////////////////////////////
DIALOG_SIM_FORMAT_VALUE_BASE::DIALOG_SIM_FORMAT_VALUE_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( wxSize( -1,-1 ), wxDefaultSize );
wxBoxSizer* bMainSizer;
bMainSizer = new wxBoxSizer( wxVERTICAL );
wxFlexGridSizer* fgSizer;
fgSizer = new wxFlexGridSizer( 3, 2, 8, 0 );
fgSizer->AddGrowableCol( 1 );
fgSizer->SetFlexibleDirection( wxBOTH );
fgSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
m_precisionLabel = new wxStaticText( this, wxID_ANY, _("Significant digits:"), wxDefaultPosition, wxDefaultSize, 0 );
m_precisionLabel->Wrap( -1 );
fgSizer->Add( m_precisionLabel, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
m_precisionCtrl = new wxSpinCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, 10, 3 );
fgSizer->Add( m_precisionCtrl, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT|wxLEFT, 5 );
m_rangeLabel = new wxStaticText( this, wxID_ANY, _("Range:"), wxDefaultPosition, wxDefaultSize, 0 );
m_rangeLabel->Wrap( -1 );
fgSizer->Add( m_rangeLabel, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
wxString m_rangeCtrlChoices[] = { _("auto"), _("f"), _("p"), _("n"), _("u"), _("m"), wxEmptyString, _("K"), _("M"), _("G"), _("T"), _("P") };
int m_rangeCtrlNChoices = sizeof( m_rangeCtrlChoices ) / sizeof( wxString );
m_rangeCtrl = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_rangeCtrlNChoices, m_rangeCtrlChoices, 0 );
m_rangeCtrl->SetSelection( 0 );
fgSizer->Add( m_rangeCtrl, 0, wxEXPAND|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 );
fgSizer->Add( 0, 0, 1, wxEXPAND, 5 );
bMainSizer->Add( fgSizer, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 10 );
wxBoxSizer* bBottomSizer;
bBottomSizer = new wxBoxSizer( wxHORIZONTAL );
bBottomSizer->Add( 50, 0, 1, wxEXPAND, 5 );
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();
bBottomSizer->Add( m_sdbSizer1, 0, wxEXPAND|wxALL, 5 );
bMainSizer->Add( bBottomSizer, 0, wxEXPAND, 5 );
this->SetSizer( bMainSizer );
this->Layout();
bMainSizer->Fit( this );
this->Centre( wxBOTH );
}
DIALOG_SIM_FORMAT_VALUE_BASE::~DIALOG_SIM_FORMAT_VALUE_BASE()
{
}

View File

@ -0,0 +1,382 @@
<?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_sim_format_value_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_SIM_FORMAT_VALUE_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">0</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">wxBOTH</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">-1,-1</property>
<property name="name">DIALOG_SIM_FORMAT_VALUE_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; forward_declare</property>
<property name="title">Format %s</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">10</property>
<property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxFlexGridSizer" expanded="1">
<property name="cols">2</property>
<property name="flexible_direction">wxBOTH</property>
<property name="growablecols">1</property>
<property name="growablerows"></property>
<property name="hgap">0</property>
<property name="minimum_size"></property>
<property name="name">fgSizer</property>
<property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
<property name="permission">none</property>
<property name="rows">3</property>
<property name="vgap">8</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxStaticText" 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="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="id">wxID_ANY</property>
<property name="label">Significant digits:</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"></property>
<property name="moveable">1</property>
<property name="name">m_precisionLabel</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"></property>
<property name="subclass">; ; 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>
<property name="wrap">-1</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxSpinCtrl" 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="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="id">wxID_ANY</property>
<property name="initial">3</property>
<property name="max">10</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min">1</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_precisionCtrl</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">wxSP_ARROW_KEYS</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="value"></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">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxStaticText" 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="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="id">wxID_ANY</property>
<property name="label">Range:</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"></property>
<property name="moveable">1</property>
<property name="name">m_rangeLabel</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"></property>
<property name="subclass">; ; 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>
<property name="wrap">-1</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL</property>
<property name="proportion">0</property>
<object class="wxChoice" 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="choices">&quot;auto&quot; &quot;f&quot; &quot;p&quot; &quot;n&quot; &quot;u&quot; &quot;m&quot; &quot;&quot; &quot;K&quot; &quot;M&quot; &quot;G&quot; &quot;T&quot; &quot;P&quot;</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="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_rangeCtrl</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="selection">0</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></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>
</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>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bBottomSizer</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property>
<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">50</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxALL</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>
</object>
</object>
</wxFormBuilder_Project>

View File

@ -0,0 +1,52 @@
///////////////////////////////////////////////////////////////////////////
// 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>
#include "dialog_shim.h"
#include <wx/string.h>
#include <wx/stattext.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/spinctrl.h>
#include <wx/choice.h>
#include <wx/sizer.h>
#include <wx/button.h>
#include <wx/dialog.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class DIALOG_SIM_FORMAT_VALUE_BASE
///////////////////////////////////////////////////////////////////////////////
class DIALOG_SIM_FORMAT_VALUE_BASE : public DIALOG_SHIM
{
private:
protected:
wxStaticText* m_precisionLabel;
wxSpinCtrl* m_precisionCtrl;
wxStaticText* m_rangeLabel;
wxChoice* m_rangeCtrl;
wxStdDialogButtonSizer* m_sdbSizer1;
wxButton* m_sdbSizer1OK;
wxButton* m_sdbSizer1Cancel;
public:
DIALOG_SIM_FORMAT_VALUE_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Format %s"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~DIALOG_SIM_FORMAT_VALUE_BASE();
};

View File

@ -79,7 +79,7 @@ public:
{}
protected:
void showPopupMenu( wxMenu& menu ) override
void showPopupMenu( wxMenu& menu, wxGridEvent& aEvent ) override
{
if( m_grid->GetGridCursorCol() == FOOTPRINT_FIELD )
{
@ -94,7 +94,7 @@ protected:
menu.AppendSeparator();
}
GRID_TRICKS::showPopupMenu( menu );
GRID_TRICKS::showPopupMenu( menu, aEvent );
}
void doPopupSelection( wxCommandEvent& event ) override

View File

@ -856,7 +856,7 @@ template class FIELDS_GRID_TABLE<SCH_FIELD>;
template class FIELDS_GRID_TABLE<LIB_FIELD>;
void FIELDS_GRID_TRICKS::showPopupMenu( wxMenu& menu )
void FIELDS_GRID_TRICKS::showPopupMenu( wxMenu& menu, wxGridEvent& aEvent )
{
if( m_grid->GetGridCursorRow() == FOOTPRINT_FIELD && m_grid->GetGridCursorCol() == FDC_VALUE )
{
@ -871,7 +871,7 @@ void FIELDS_GRID_TRICKS::showPopupMenu( wxMenu& menu )
menu.AppendSeparator();
}
GRID_TRICKS::showPopupMenu( menu );
GRID_TRICKS::showPopupMenu( menu, aEvent );
}

View File

@ -44,7 +44,7 @@ public:
{}
protected:
virtual void showPopupMenu( wxMenu& menu ) override;
virtual void showPopupMenu( wxMenu& menu, wxGridEvent& aEvent ) override;
virtual void doPopupSelection( wxCommandEvent& event ) override;
DIALOG_SHIM* m_dlg;
};

View File

@ -1256,6 +1256,45 @@ void SCH_EDIT_FRAME::PrintPage( const RENDER_SETTINGS* aSettings )
}
void SCH_EDIT_FRAME::RefreshOperatingPointDisplay()
{
GetCanvas()->GetView()->UpdateAllItemsConditionally(
[&]( KIGFX::VIEW_ITEM* aItem ) -> int
{
int flags = 0;
if( SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItem ) )
{
item->RunOnChildren(
[&flags]( SCH_ITEM* aChild )
{
EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aChild );
if( text && text->HasTextVars() )
{
text->ClearRenderCache();
text->ClearBoundingBoxCache();
flags |= KIGFX::GEOMETRY | KIGFX::REPAINT;
}
} );
EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aItem );
if( text && text->HasTextVars() )
{
text->ClearRenderCache();
text->ClearBoundingBoxCache();
flags |= KIGFX::GEOMETRY | KIGFX::REPAINT;
}
}
return flags;
} );
GetCanvas()->ForceRefresh();
}
void SCH_EDIT_FRAME::AutoRotateItem( SCH_SCREEN* aScreen, SCH_ITEM* aItem )
{
if( aItem->IsType( { SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T } ) )

View File

@ -187,6 +187,11 @@ public:
void KiwayMailIn( KIWAY_EXPRESS& aEvent ) override;
/**
* Refresh the display of any operating points. Called after a .op simulation completes.
*/
void RefreshOperatingPointDisplay();
/**
* Automatically set the rotation of an item (if the item supports it)
*/

View File

@ -479,11 +479,50 @@ void SCH_LABEL_BASE::GetIntersheetRefs( std::vector<std::pair<wxString, wxString
}
void SCH_LABEL_BASE::GetContextualTextVars( wxArrayString* aVars ) const
{
for( const SCH_FIELD& field : m_fields )
aVars->push_back( field.GetCanonicalName().Upper() );
aVars->push_back( wxT( "OP" ) );
aVars->push_back( wxT( "CONNECTION_TYPE" ) );
aVars->push_back( wxT( "SHORT_NET_NAME" ) );
aVars->push_back( wxT( "NET_NAME" ) );
aVars->push_back( wxT( "NET_CLASS" ) );
}
bool SCH_LABEL_BASE::ResolveTextVar( wxString* token, int aDepth ) const
{
static wxRegEx operatingPoint( wxT( "^"
"OP"
"(.([0-9])?([a-zA-Z]*))?"
"$" ) );
if( !Schematic() )
return false;
if( operatingPoint.Matches( *token ) )
{
int precision = 3;
wxString precisionStr( operatingPoint.GetMatch( *token, 2 ) );
wxString range( operatingPoint.GetMatch( *token, 3 ) );
if( !precisionStr.IsEmpty() )
precision = precisionStr[0] - '0';
if( range.IsEmpty() )
range = wxS( "~V" );
const SCH_CONNECTION* connection = Connection();
*token = wxS( "?" );
if( connection )
*token = Schematic()->GetOperatingPoint( connection->Name( false ), precision, range );
return true;
}
if( token->Contains( ':' ) )
{
if( Schematic()->ResolveCrossReference( token, aDepth + 1 ) )
@ -528,11 +567,11 @@ bool SCH_LABEL_BASE::ResolveTextVar( wxString* token, int aDepth ) const
return true;
}
for( size_t i = 0; i < m_fields.size(); ++i )
for( const SCH_FIELD& field : m_fields)
{
if( token->IsSameAs( m_fields[i].GetName() ) )
if( token->IsSameAs( field.GetName() ) )
{
*token = m_fields[i].GetShownText( aDepth + 1 );
*token = field.GetShownText( aDepth + 1 );
return true;
}
}

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-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
@ -126,6 +126,16 @@ public:
*/
void GetIntersheetRefs( std::vector<std::pair<wxString, wxString>>* pages );
/**
* Return the list of system text vars & fields for this label.
*/
void GetContextualTextVars( wxArrayString* aVars ) const;
/**
* Resolve any references to system tokens supported by the label.
*
* @param aDepth a counter to limit recursion and circular references.
*/
virtual bool ResolveTextVar( wxString* token, int aDepth ) const;
wxString GetShownText( int aDepth = 0, bool aAllowExtraText = true ) const override;

View File

@ -1117,6 +1117,7 @@ void SCH_SYMBOL::GetContextualTextVars( wxArrayString* aVars ) const
for( size_t i = MANDATORY_FIELDS; i < m_fields.size(); ++i )
aVars->push_back( m_fields[i].GetName() );
aVars->push_back( wxT( "OP" ) );
aVars->push_back( wxT( "FOOTPRINT_LIBRARY" ) );
aVars->push_back( wxT( "FOOTPRINT_NAME" ) );
aVars->push_back( wxT( "UNIT" ) );
@ -1132,12 +1133,38 @@ void SCH_SYMBOL::GetContextualTextVars( wxArrayString* aVars ) const
bool SCH_SYMBOL::ResolveTextVar( wxString* token, int aDepth ) const
{
static wxRegEx operatingPoint( wxT( "^"
"OP"
"(:[a-zA-Z]*)?" // port
"(.([0-9])?([a-zA-Z]*))?" // format
"$" ) );
SCHEMATIC* schematic = Schematic();
// SCH_SYMOL object has no context outside a schematic.
if( !schematic )
return false;
if( operatingPoint.Matches( *token ) )
{
wxString port( operatingPoint.GetMatch( *token, 1 ) );
wxString precisionStr( operatingPoint.GetMatch( *token, 3 ) );
wxString range( operatingPoint.GetMatch( *token, 4 ) );
wxString signal = GetRef( &schematic->CurrentSheet() ) + port;
int precision = 3;
if( !precisionStr.IsEmpty() )
precision = precisionStr[0] - '0';
if( range.IsEmpty() )
range = wxS( "~A" );
*token = Schematic()->GetOperatingPoint( signal.Lower(), precision, range );
return true;
}
if( token->Contains( ':' ) )
{
if( schematic->ResolveCrossReference( token, aDepth + 1 ) )

View File

@ -31,6 +31,7 @@
#include <sch_screen.h>
#include <sim/spice_settings.h>
#include <sch_label.h>
#include <sim/spice_value.h>
SCHEMATIC::SCHEMATIC( PROJECT* aPrj ) :
EDA_ITEM( nullptr, SCHEMATIC_T ),
@ -625,6 +626,20 @@ void SCHEMATIC::RecomputeIntersheetRefs( const std::function<void( SCH_GLOBALLAB
}
wxString SCHEMATIC::GetOperatingPoint( const wxString& aNetName, int aPrecision,
const wxString& aRange )
{
auto it = m_operatingPoints.find( aNetName );
if( it != m_operatingPoints.end() )
return SPICE_VALUE( it->second ).ToString( aPrecision, aRange );
else if( m_operatingPoints.empty() )
return wxS( "--" );
else
return wxS( "?" );
}
void SCHEMATIC::FixupJunctions()
{
for( const SCH_SHEET_PATH& sheet : GetSheets() )

View File

@ -204,6 +204,24 @@ public:
*/
void RecomputeIntersheetRefs( const std::function<void( SCH_GLOBALLABEL* )>& aItemCallback );
/**
* Clear operating points from a .op simulation.
*/
void ClearOperatingPoints()
{
m_operatingPoints.clear();
}
/**
* Set operating points from a .op simulation. Called after the simulation completes.
*/
void SetOperatingPoint( const wxString& aSignal, double aValue )
{
m_operatingPoints[ aSignal ] = aValue;
}
wxString GetOperatingPoint( const wxString& aNetName, int aPrecision, const wxString& aRange );
/**
* Add junctions to this schematic where required. This function is needed for some plugins
* (e.g. Legacy and Cadstar) in order to retain connectivity after loading.
@ -243,6 +261,11 @@ private:
* Properties for text variable substitution (and perhaps other uses in future).
*/
std::map<wxString, wxString> m_properties;
/**
* Simulation operating points for text variable substitution.
*/
std::map<wxString, double> m_operatingPoints;
};
#endif

View File

@ -33,17 +33,24 @@
SIM_TRACE_TYPE NGSPICE_CIRCUIT_MODEL::VectorToSignal( const std::string& aVector,
wxString& aSignal ) const
{
using namespace std;
static wxString BRANCH( wxS( "#branch" ) );
// See ngspice manual chapt. 31.1 "Accessing internal device parameters"
wxRegEx internalDevParameter( "^@(\\w*[\\.\\w+]*)\\[(\\w*)\\]$", wxRE_ADVANCED );
static wxRegEx internalDevParameter( wxS( "^@(\\w*[\\.\\w+]*)\\[(\\w*)\\]$" ), wxRE_ADVANCED );
wxString vector( aVector );
if( !internalDevParameter.Matches( vector ) )
{
// any text is a node name, which returns voltage
aSignal = wxT( "V(" ) + aVector + wxT( ")" );
return SPT_VOLTAGE;
if( vector.EndsWith( BRANCH ) )
{
aSignal = wxT( "I(" ) + vector.Left( vector.Length() - BRANCH.Length() ) + wxT( ")" );
return SPT_CURRENT;
}
else
{
aSignal = wxT( "V(" ) + vector + wxT( ")" );
return SPT_VOLTAGE;
}
}
else
{

View File

@ -56,7 +56,7 @@
#include "sim_plot_panel.h"
#include "spice_simulator.h"
#include "spice_reporter.h"
#include <menus_helpers.h>
#include <dialog_sim_format_value.h>
#include <eeschema_settings.h>
#include <memory>
@ -129,6 +129,73 @@ enum CURSORS_GRID_COLUMNS
};
enum
{
MYID_FORMAT_VALUE = GRIDTRICKS_FIRST_CLIENT_ID
};
class CURSORS_GRID_TRICKS : public GRID_TRICKS
{
public:
CURSORS_GRID_TRICKS( SIM_PLOT_FRAME* aParent, WX_GRID* aGrid ) :
GRID_TRICKS( aGrid ),
m_parent( aParent )
{}
protected:
void showPopupMenu( wxMenu& menu, wxGridEvent& aEvent ) override;
void doPopupSelection( wxCommandEvent& event ) override;
protected:
SIM_PLOT_FRAME* m_parent;
int m_menuRow;
int m_menuCol;
};
void CURSORS_GRID_TRICKS::showPopupMenu( wxMenu& menu, wxGridEvent& aEvent )
{
m_menuRow = aEvent.GetRow();
m_menuCol = aEvent.GetCol();
if( m_menuCol == COL_CURSOR_X || m_menuCol == COL_CURSOR_Y )
{
wxString msg = m_grid->GetColLabelValue( m_menuCol );
menu.Append( MYID_FORMAT_VALUE, wxString::Format( _( "Format..." ), msg ),
wxString::Format( _( "Specify %s precision and range" ), msg.Lower() ) );
menu.AppendSeparator();
}
GRID_TRICKS::showPopupMenu( menu, aEvent );
}
void CURSORS_GRID_TRICKS::doPopupSelection( wxCommandEvent& event )
{
if( event.GetId() == MYID_FORMAT_VALUE )
{
int cursorId = m_menuRow;
int cursorAxis = m_menuCol - COL_CURSOR_X;
int precision = m_parent->GetCursorPrecision( cursorId, cursorAxis );
wxString range = m_parent->GetCursorRange( cursorId, cursorAxis );
DIALOG_SIM_FORMAT_VALUE formatDialog( m_parent, &precision, &range );
if( formatDialog.ShowModal() == wxID_OK )
{
m_parent->SetCursorPrecision( cursorId, cursorAxis, precision );
m_parent->SetCursorRange( cursorId, cursorAxis, range );
}
}
else
{
GRID_TRICKS::doPopupSelection( event );
}
}
SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
SIM_PLOT_FRAME_BASE( aParent ),
m_lastSimPlot( nullptr ),
@ -180,7 +247,15 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
attr->SetReadOnly();
m_cursorsGrid->SetColAttr( COL_CURSOR_Y, attr );
m_cursorsGrid->PushEventHandler( new GRID_TRICKS( m_cursorsGrid ) );
m_cursorsGrid->PushEventHandler( new CURSORS_GRID_TRICKS( this, m_cursorsGrid ) );
for( int cursorId = 0; cursorId < 3; ++cursorId )
{
m_cursorPrecision[ cursorId ][ 0 ] = 3;
m_cursorRange[ cursorId ][ 0 ] = wxS( "~s" );
m_cursorPrecision[ cursorId ][ 1 ] = 3;
m_cursorRange[ cursorId ][ 1 ] = wxS( "~V" );
}
// Prepare the color list to plot traces
SIM_PLOT_COLORS::FillDefaultColorList( m_darkMode );
@ -438,6 +513,9 @@ void SIM_PLOT_FRAME::rebuildSignalsGrid( wxString aFilter )
{
m_signalsGrid->ClearRows();
if( !GetCurrentPlot() )
return;
if( aFilter.IsEmpty() )
aFilter = wxS( "*" );
@ -567,6 +645,8 @@ void SIM_PLOT_FRAME::StartSimulation( const wxString& aSimCommand )
unconnected.Replace( '(', '_' ); // Convert to SPICE markup
m_signals.clear();
auto simType = m_circuitModel->GetSimType();
// Add voltages
for( const std::string& net : m_circuitModel->GetNets() )
{
@ -574,11 +654,19 @@ void SIM_PLOT_FRAME::StartSimulation( const wxString& aSimCommand )
wxString netname = UnescapeString( net );
if( netname != "GND" && netname != "0" && !netname.StartsWith( unconnected ) )
m_signals.push_back( wxString::Format( "V(%s)", netname ) );
{
if( simType == ST_AC )
{
m_signals.push_back( wxString::Format( _( "V(%s) (gain)" ), netname ) );
m_signals.push_back( wxString::Format( _( "V(%s) (phase)" ), netname ) );
}
else
{
m_signals.push_back( wxString::Format( "V(%s)", netname ) );
}
}
}
auto simType = m_circuitModel->GetSimType();
// Add currents
if( simType == ST_TRANSIENT || simType == ST_DC )
{
@ -666,15 +754,33 @@ void SIM_PLOT_FRAME::onSignalsGridCellChanged( wxGridEvent& aEvent )
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[0];
int traceType = SPT_UNKNOWN;
if( firstChar == 'V' || firstChar == 'v' )
addTrace( signalName, SPT_VOLTAGE );
traceType = SPT_VOLTAGE;
else if( firstChar == 'I' || firstChar == 'i' )
addTrace( signalName, SPT_CURRENT );
traceType = SPT_CURRENT;
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 );
}
if( !GetCurrentPlot()->GetTrace( signalName ) )
@ -955,7 +1061,7 @@ bool SIM_PLOT_FRAME::updateTrace( const wxString& aName, SIM_TRACE_TYPE aType,
wxString traceTitle = aName;
if( aType & SPT_AC_MAG )
traceTitle += _( " (mag)" );
traceTitle += _( " (gain)" );
else if( aType & SPT_AC_PHASE )
traceTitle += _( " (phase)" );
@ -1605,17 +1711,6 @@ void SIM_PLOT_FRAME::onCursorUpdate( wxCommandEvent& event )
else
m_cursorsGrid->SetColLabelValue( COL_CURSOR_Y, labelY1 + wxT( " / " ) + labelY2 );
auto getUnitsY =
[&]( TRACE* aTrace ) -> wxString
{
if( aTrace->GetType() == SPT_VOLTAGE )
return wxS( "V" );
else if( aTrace->GetType() == SPT_CURRENT )
return wxS( "A" );
else
return wxEmptyString;
};
// Update cursor values
wxString unitsX = plotPanel->GetUnitsX();
CURSOR* cursor1 = nullptr;
@ -1623,7 +1718,32 @@ void SIM_PLOT_FRAME::onCursorUpdate( wxCommandEvent& event )
CURSOR* cursor2 = nullptr;
wxString unitsY2;
#define SET_CELL( r, c, v ) m_cursorsGrid->SetCellValue( r, c, v )
auto getUnitsY =
[&]( TRACE* aTrace ) -> wxString
{
if( ( aTrace->GetType() & SPT_AC_PHASE ) || ( aTrace->GetType() & SPT_CURRENT ) )
return plotPanel->GetUnitsY2();
else
return plotPanel->GetUnitsY1();
};
auto updateRangeUnits =
[]( wxString* aRange, const wxString& aUnits )
{
if( aRange->GetChar( 0 ) == '~' )
*aRange = aRange->Left( 1 ) + aUnits;
else if( SPICE_VALUE::ParseSIPrefix( aRange->GetChar( 0 ) ) != SPICE_VALUE::PFX_NONE )
*aRange = aRange->Left( 1 ) + aUnits;
else
*aRange = aUnits;
};
auto formatValue =
[this]( double aValue, int aCursorId, int aCol ) -> wxString
{
return SPICE_VALUE( aValue ).ToString( m_cursorPrecision[ aCursorId ][ aCol ],
m_cursorRange[ aCursorId ][ aCol ] );
};
for( const auto& [name, trace] : plotPanel->GetTraces() )
{
@ -1635,12 +1755,14 @@ void SIM_PLOT_FRAME::onCursorUpdate( wxCommandEvent& event )
wxRealPoint coords = cursor->GetCoords();
int row = m_cursorsGrid->GetNumberRows();
m_cursorsGrid->AppendRows( 1 );
SET_CELL( row, COL_CURSOR_NAME, wxS( "1" ) );
SET_CELL( row, COL_CURSOR_SIGNAL, cursor->GetName() );
SET_CELL( row, COL_CURSOR_X, SPICE_VALUE( coords.x ).ToSpiceString() + unitsX );
SET_CELL( row, COL_CURSOR_Y, SPICE_VALUE( coords.y ).ToSpiceString() + unitsY1 );
updateRangeUnits( &m_cursorRange[0][0], unitsX );
updateRangeUnits( &m_cursorRange[0][1], unitsY1 );
m_cursorsGrid->AppendRows( 1 );
m_cursorsGrid->SetCellValue( row, COL_CURSOR_NAME, wxS( "1" ) );
m_cursorsGrid->SetCellValue( row, COL_CURSOR_SIGNAL, cursor->GetName() );
m_cursorsGrid->SetCellValue( row, COL_CURSOR_X, formatValue( coords.x, 0, 0 ) );
m_cursorsGrid->SetCellValue( row, COL_CURSOR_Y, formatValue( coords.y, 0, 1 ) );
break;
}
}
@ -1655,38 +1777,37 @@ void SIM_PLOT_FRAME::onCursorUpdate( wxCommandEvent& event )
wxRealPoint coords = cursor->GetCoords();
int row = m_cursorsGrid->GetNumberRows();
m_cursorsGrid->AppendRows( 1 );
SET_CELL( row, COL_CURSOR_NAME, wxS( "2" ) );
SET_CELL( row, COL_CURSOR_SIGNAL, cursor->GetName() );
SET_CELL( row, COL_CURSOR_X, SPICE_VALUE( coords.x ).ToSpiceString() + unitsX );
SET_CELL( row, COL_CURSOR_Y, SPICE_VALUE( coords.y ).ToSpiceString() + unitsY2 );
updateRangeUnits( &m_cursorRange[1][0], unitsX );
updateRangeUnits( &m_cursorRange[1][1], unitsY2 );
m_cursorsGrid->AppendRows( 1 );
m_cursorsGrid->SetCellValue( row, COL_CURSOR_NAME, wxS( "2" ) );
m_cursorsGrid->SetCellValue( row, COL_CURSOR_SIGNAL, cursor->GetName() );
m_cursorsGrid->SetCellValue( row, COL_CURSOR_X, formatValue( coords.x, 1, 0 ) );
m_cursorsGrid->SetCellValue( row, COL_CURSOR_Y, formatValue( coords.y, 1, 1 ) );
break;
}
}
if( cursor1 && cursor2 && unitsY1 == unitsY2 )
{
const wxRealPoint coords = cursor2->GetCoords() - cursor1->GetCoords();
wxRealPoint coords = cursor2->GetCoords() - cursor1->GetCoords();
wxString signal;
updateRangeUnits( &m_cursorRange[2][0], unitsX );
updateRangeUnits( &m_cursorRange[2][1], unitsY1 );
if( cursor1->GetName() == cursor2->GetName() )
signal = wxString::Format( wxS( "%s[2 - 1]" ), cursor2->GetName() );
else
signal = wxString::Format( wxS( "%s - %s" ), cursor2->GetName(), cursor1->GetName() );
m_cursorsGrid->AppendRows( 1 );
SET_CELL( 2, COL_CURSOR_NAME, _( "Diff" ) );
if( cursor1->GetName() == cursor2->GetName() )
{
SET_CELL( 2, COL_CURSOR_SIGNAL, wxString::Format( wxS( "%s[2 - 1]" ),
cursor2->GetName() ) );
}
else
{
SET_CELL( 2, COL_CURSOR_SIGNAL, wxString::Format( wxS( "%s - %s" ),
cursor2->GetName(),
cursor1->GetName() ) );
}
SET_CELL( 2, COL_CURSOR_X, SPICE_VALUE( coords.x ).ToSpiceString() + unitsX );
SET_CELL( 2, COL_CURSOR_Y, SPICE_VALUE( coords.y ).ToSpiceString() + unitsY1 );
m_cursorsGrid->SetCellValue( 2, COL_CURSOR_NAME, _( "Diff" ) );
m_cursorsGrid->SetCellValue( 2, COL_CURSOR_SIGNAL, signal );
m_cursorsGrid->SetCellValue( 2, COL_CURSOR_X, formatValue( coords.x, 2, 0 ) );
m_cursorsGrid->SetCellValue( 2, COL_CURSOR_Y, formatValue( coords.y, 2, 1 ) );
}
#undef SET_CELL
}
@ -1847,6 +1968,9 @@ void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent )
}
else if( simType == ST_OP )
{
SCHEMATIC& schematic = m_schematicFrame->Schematic();
schematic.ClearOperatingPoints();
m_simConsole->AppendText( _( "\n\nSimulation results:\n\n" ) );
m_simConsole->SetInsertionPointEnd();
@ -1857,23 +1981,28 @@ void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent )
if( val_list.size() == 0 ) // The list of values can be empty!
continue;
double val = val_list.at( 0 );
wxString outLine, signal;
wxString value = SPICE_VALUE( val_list.at( 0 ) ).ToSpiceString();
wxString msg;
wxString signal;
SIM_TRACE_TYPE type = m_circuitModel->VectorToSignal( vec, signal );
const size_t tab = 25; //characters
size_t padding = ( signal.length() < tab ) ? ( tab - signal.length() ) : 1;
outLine.Printf( wxT( "%s%s" ),
( signal + wxT( ":" ) ).Pad( padding, wxUniChar( ' ' ) ),
SPICE_VALUE( val ).ToSpiceString() );
value.Append( type == SPT_CURRENT ? wxS( "A" ) : wxS( "V" ) );
outLine.Append( type == SPT_CURRENT ? wxT( "A\n" ) : wxT( "V\n" ) );
msg.Printf( wxT( "%s%s\n" ),
( signal + wxT( ":" ) ).Pad( padding, wxUniChar( ' ' ) ),
value );
m_simConsole->AppendText( outLine );
m_simConsole->AppendText( msg );
m_simConsole->SetInsertionPointEnd();
// @todo display calculated values on the schematic
if( signal.StartsWith( wxS( "V(" ) ) || signal.StartsWith( wxS( "I(" ) ) )
signal = signal.SubString( 2, signal.Length() - 2 );
schematic.SetOperatingPoint( signal, val_list.at( 0 ) );
m_schematicFrame->RefreshOperatingPointDisplay();
}
}

View File

@ -94,6 +94,41 @@ public:
*/
void AddCurrentPlot( const wxString& aDeviceName );
/**
* Get/Set the number of decimal places to show in a cursor value.
* @param aValueCol 0 indicates the X value column; 1 the Y value.
*/
int GetCursorPrecision( int aCursorId, int aValueCol ) const
{
return m_cursorPrecision[ aCursorId ][ aValueCol ];
}
void SetCursorPrecision( int aCursorId, int aValueCol, int aPrecision )
{
m_cursorPrecision[ aCursorId ][ aValueCol ] = aPrecision;
wxCommandEvent dummy;
onCursorUpdate( dummy );
}
/**
* Get/Set the range of a cursor value.
* @param aValueCol 0 indicates the X value column; 1 the Y value.
* @param aScale "~" + unit indicates automatic; the rest are SI prefix + unit.
*/
wxString GetCursorRange( int aCursorId, int aValueCol ) const
{
return m_cursorRange[ aCursorId ][ aValueCol ];
}
void SetCursorRange( int aCursorId, int aValueCol, const wxString& aRange )
{
m_cursorRange[ aCursorId ][ aValueCol ] = aRange;
wxCommandEvent dummy;
onCursorUpdate( dummy );
}
/**
* Add a tuner for a symbol.
*/
@ -313,6 +348,9 @@ private:
bool m_darkMode;
unsigned int m_plotNumber;
bool m_simFinished;
int m_cursorPrecision[3][2];
wxString m_cursorRange[3][2];
};
// Commands

View File

@ -427,6 +427,28 @@ wxString SIM_PLOT_PANEL::GetUnitsX() const
}
wxString SIM_PLOT_PANEL::GetUnitsY1() const
{
LIN_SCALE<mpScaleY>* linScale = dynamic_cast<LIN_SCALE<mpScaleY>*>( m_axis_y1 );
if( linScale )
return linScale->GetUnits();
else
return wxEmptyString;
}
wxString SIM_PLOT_PANEL::GetUnitsY2() const
{
LIN_SCALE<mpScaleY>* linScale = dynamic_cast<LIN_SCALE<mpScaleY>*>( m_axis_y2 );
if( linScale )
return linScale->GetUnits();
else
return wxEmptyString;
}
void SIM_PLOT_PANEL::updateAxes()
{
bool skipAddToView = false;

View File

@ -220,6 +220,8 @@ public:
}
wxString GetUnitsX() const;
wxString GetUnitsY1() const;
wxString GetUnitsY2() const;
bool TraceShown( const wxString& aName ) const
{

View File

@ -23,6 +23,7 @@
*/
#include "spice_value.h"
#include "math/util.h"
#include <stdexcept>
#include <cmath>
@ -34,6 +35,7 @@
#include <ki_exception.h>
#include <locale_io.h>
SPICE_VALUE::SPICE_VALUE( const wxString& aString )
{
char buf[8] = { 0, };
@ -107,20 +109,56 @@ void SPICE_VALUE::Normalize()
}
wxString prefix( SPICE_VALUE::UNIT_PREFIX aPrefix )
wxString spice_prefix( SPICE_VALUE::UNIT_PREFIX aPrefix )
{
switch( aPrefix )
{
case SPICE_VALUE::PFX_FEMTO: return wxT( "f" );
case SPICE_VALUE::PFX_PICO: return wxT( "p" );
case SPICE_VALUE::PFX_NANO: return wxT( "n" );
case SPICE_VALUE::PFX_MICRO: return wxT( "u" );
case SPICE_VALUE::PFX_MILI: return wxT( "m" );
case SPICE_VALUE::PFX_NONE: return wxEmptyString;
case SPICE_VALUE::PFX_KILO: return wxT( "k" );
case SPICE_VALUE::PFX_MEGA: return wxT( "Meg" );
case SPICE_VALUE::PFX_GIGA: return wxT( "G" );
case SPICE_VALUE::PFX_TERA: return wxT( "T" );
case SPICE_VALUE::PFX_FEMTO: return wxT( "f" );
case SPICE_VALUE::PFX_PICO: return wxT( "p" );
case SPICE_VALUE::PFX_NANO: return wxT( "n" );
case SPICE_VALUE::PFX_MICRO: return wxT( "u" );
case SPICE_VALUE::PFX_MILI: return wxT( "m" );
case SPICE_VALUE::PFX_NONE: return wxEmptyString;
case SPICE_VALUE::PFX_KILO: return wxT( "k" );
case SPICE_VALUE::PFX_MEGA: return wxT( "Meg" );
case SPICE_VALUE::PFX_GIGA: return wxT( "G" );
case SPICE_VALUE::PFX_TERA: return wxT( "T" );
}
}
wxString si_prefix( SPICE_VALUE::UNIT_PREFIX aPrefix )
{
switch( aPrefix )
{
case SPICE_VALUE::PFX_FEMTO: return wxT( "f" );
case SPICE_VALUE::PFX_PICO: return wxT( "p" );
case SPICE_VALUE::PFX_NANO: return wxT( "n" );
case SPICE_VALUE::PFX_MICRO: return wxT( "u" );
case SPICE_VALUE::PFX_MILI: return wxT( "m" );
case SPICE_VALUE::PFX_NONE: return wxEmptyString;
case SPICE_VALUE::PFX_KILO: return wxT( "K" );
case SPICE_VALUE::PFX_MEGA: return wxT( "M" );
case SPICE_VALUE::PFX_GIGA: return wxT( "G" );
case SPICE_VALUE::PFX_TERA: return wxT( "T" );
}
}
SPICE_VALUE::UNIT_PREFIX SPICE_VALUE::ParseSIPrefix( wxChar c )
{
switch( c )
{
case 'f': return SPICE_VALUE::PFX_FEMTO;
case 'p': return SPICE_VALUE::PFX_PICO;
case 'n': return SPICE_VALUE::PFX_NANO;
case 'u': return SPICE_VALUE::PFX_MICRO;
case 'm': return SPICE_VALUE::PFX_MILI;
case 'K': return SPICE_VALUE::PFX_KILO;
case 'M': return SPICE_VALUE::PFX_MEGA;
case 'G': return SPICE_VALUE::PFX_GIGA;
case 'T': return SPICE_VALUE::PFX_TERA;
default: return SPICE_VALUE::PFX_NONE;
}
}
@ -129,7 +167,7 @@ double SPICE_VALUE::ToNormalizedDouble( wxString* aPrefix )
{
Normalize();
*aPrefix = prefix( m_prefix );
*aPrefix = spice_prefix( m_prefix );
return m_base;
}
@ -153,11 +191,52 @@ wxString SPICE_VALUE::ToString() const
}
wxString SPICE_VALUE::ToString( int aPrecision, const wxString& aRange )
{
wxString range( aRange );
if( range.StartsWith( wxS( "~" ) ) )
{
Normalize();
range = si_prefix( m_prefix ) + range.Right( range.Length() - 1 );
}
else
{
SPICE_VALUE::UNIT_PREFIX rangePrefix = ParseSIPrefix( aRange[0] );
m_base = m_base * std::pow( 10, m_prefix - rangePrefix );
m_prefix = rangePrefix;
}
double mantissa = m_base;
int scale = 0;
while( std::fabs( mantissa ) >= 10.0 )
{
mantissa *= 0.1;
scale += 1;
}
while( mantissa != 0.0 && std::fabs( mantissa ) < 1.0 )
{
mantissa *= 10;
scale -= 1;
}
mantissa = KiROUND( mantissa * std::pow( 10, aPrecision - 1 ) );
mantissa *= std::pow( 10, scale - aPrecision + 1 );
wxString res = wxString::FromCDouble( mantissa );
StripZeros( res );
return res + range;
}
wxString SPICE_VALUE::ToSpiceString() const
{
wxString res = wxString::FromCDouble( m_base );
StripZeros( res );
res += prefix( m_prefix );
res += spice_prefix( m_prefix );
return res;
}

View File

@ -82,6 +82,13 @@ public:
*/
wxString ToString() const;
/**
* Return string value with a particular precision and range.
* @param aPrecision number of significant digits
* @param aRange "~" + unit for autorage; otherwise SI prefix + unit
*/
wxString ToString( int aPrecision, const wxString& aRange );
/**
* Return string value in Spice format (e.g. 123.3456789k).
*/
@ -137,6 +144,8 @@ public:
///< Remove redundant zeros from the end of a string.
static void StripZeros( wxString& aString );
static UNIT_PREFIX ParseSIPrefix( wxChar c );
private:
double m_base;
UNIT_PREFIX m_prefix;

View File

@ -107,7 +107,7 @@ protected:
void onGridMotion( wxMouseEvent& event );
virtual bool handleDoubleClick( wxGridEvent& aEvent );
virtual void showPopupMenu( wxMenu& menu );
virtual void showPopupMenu( wxMenu& menu, wxGridEvent& aEvent );
virtual void doPopupSelection( wxCommandEvent& event );
bool toggleCell( int aRow, int aCol, bool aPreserveSelection = false );

View File

@ -30,6 +30,6 @@ class LIB_TABLE_GRID_TRICKS : public GRID_TRICKS
public:
explicit LIB_TABLE_GRID_TRICKS( WX_GRID* aGrid );
void showPopupMenu( wxMenu& menu ) override;
void showPopupMenu( wxMenu& menu, wxGridEvent& aEvent ) override;
void doPopupSelection( wxCommandEvent& event ) override;
};

View File

@ -289,7 +289,7 @@ protected:
return false;
}
void showPopupMenu( wxMenu& menu ) override
void showPopupMenu( wxMenu& menu, wxGridEvent& aEvent ) override
{
if( m_grid->GetGridCursorCol() == COL_OPTIONS )
{
@ -297,7 +297,7 @@ protected:
menu.AppendSeparator();
}
LIB_TABLE_GRID_TRICKS::showPopupMenu( menu );
LIB_TABLE_GRID_TRICKS::showPopupMenu( menu, aEvent );
}
void doPopupSelection( wxCommandEvent& event ) override

View File

@ -1,4 +1,4 @@
(kicad_sch (version 20221004) (generator eeschema)
(kicad_sch (version 20230121) (generator eeschema)
(uuid 1982c87f-95a1-4a40-9669-f13cd3c28543)
@ -148,6 +148,83 @@
)
)
)
(symbol "device:Q_NPN_BCE" (pin_numbers hide) (pin_names (offset 0) hide) (in_bom yes) (on_board yes)
(property "Reference" "Q" (at 5.08 1.27 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Value" "Q_NPN_BCE" (at 5.08 -1.27 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Footprint" "" (at 5.08 2.54 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "ki_keywords" "transistor NPN" (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "ki_description" "NPN transistor, base/collector/emitter" (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(symbol "Q_NPN_BCE_0_1"
(polyline
(pts
(xy 0.635 0.635)
(xy 2.54 2.54)
)
(stroke (width 0) (type default))
(fill (type none))
)
(polyline
(pts
(xy 0.635 -0.635)
(xy 2.54 -2.54)
(xy 2.54 -2.54)
)
(stroke (width 0) (type default))
(fill (type none))
)
(polyline
(pts
(xy 0.635 1.905)
(xy 0.635 -1.905)
(xy 0.635 -1.905)
)
(stroke (width 0.508) (type default))
(fill (type none))
)
(polyline
(pts
(xy 1.27 -1.778)
(xy 1.778 -1.27)
(xy 2.286 -2.286)
(xy 1.27 -1.778)
(xy 1.27 -1.778)
)
(stroke (width 0) (type default))
(fill (type outline))
)
(circle (center 1.27 0) (radius 2.8194)
(stroke (width 0.254) (type default))
(fill (type none))
)
)
(symbol "Q_NPN_BCE_1_1"
(pin input line (at -5.08 0 0) (length 5.715)
(name "B" (effects (font (size 1.27 1.27))))
(number "1" (effects (font (size 1.27 1.27))))
)
(pin passive line (at 2.54 5.08 270) (length 2.54)
(name "C" (effects (font (size 1.27 1.27))))
(number "2" (effects (font (size 1.27 1.27))))
)
(pin passive line (at 2.54 -5.08 90) (length 2.54)
(name "E" (effects (font (size 1.27 1.27))))
(number "3" (effects (font (size 1.27 1.27))))
)
)
)
(symbol "power:GND" (power) (pin_names (offset 0)) (in_bom yes) (on_board yes)
(property "Reference" "#PWR" (at 0 -6.35 0)
(effects (font (size 1.27 1.27)) hide)
@ -201,7 +278,7 @@
(stroke (width 0) (type default))
(uuid 04439e70-b428-449c-8252-f1ae41187e35)
)
(wire (pts (xy 127 88.9) (xy 127 127))
(wire (pts (xy 127 88.9) (xy 127 102.87))
(stroke (width 0) (type default))
(uuid 13012609-7ad9-472e-86c6-03fee6bbd1d7)
)
@ -225,6 +302,10 @@
(stroke (width 0) (type default))
(uuid 501f3c0a-9c33-49a4-8f5c-dbfdd1280680)
)
(wire (pts (xy 119.38 88.9) (xy 119.38 107.95))
(stroke (width 0) (type default))
(uuid 5b1973d0-c313-4505-a993-a8a37c4b3509)
)
(wire (pts (xy 127 50.8) (xy 152.4 50.8))
(stroke (width 0) (type default))
(uuid 7b442ca0-947a-4ba5-b5ca-d4993e9d8f1f)
@ -237,6 +318,10 @@
(stroke (width 0) (type default))
(uuid 81216253-8919-43e8-8787-797837904c0c)
)
(wire (pts (xy 127 113.03) (xy 127 127))
(stroke (width 0) (type default))
(uuid 8b2e3ad9-db78-4121-a235-15453979e385)
)
(wire (pts (xy 114.3 50.8) (xy 127 50.8))
(stroke (width 0) (type default))
(uuid 8dfaa691-b0dd-464f-a3c8-e61d80a9e815)
@ -253,6 +338,10 @@
(stroke (width 0) (type default))
(uuid a58e2b02-3d81-4f91-9994-4ab346e73283)
)
(wire (pts (xy 127 88.9) (xy 119.38 88.9))
(stroke (width 0) (type default))
(uuid b45774f9-87b3-422f-9dfe-55a54863fc2e)
)
(wire (pts (xy 152.4 50.8) (xy 152.4 53.34))
(stroke (width 0) (type default))
(uuid b9267405-05c0-4c72-be22-100cadee2870)
@ -292,10 +381,39 @@
(uuid ef8fea74-bc8a-49e2-9bda-219af90153ff)
)
(netclass_flag "" (length 2.54) (shape round) (at 134.62 50.8 0) (fields_autoplaced)
(effects (font (size 1.27 1.27)) (justify left bottom))
(uuid 0267b22e-f0f5-4503-afd3-8b8f8c8a2238)
(property "op" "${OP}" (at 135.3185 48.26 0)
(effects (font (size 1.27 1.27) italic) (justify left))
)
)
(netclass_flag "" (length 2.54) (shape round) (at 158.75 95.25 0) (fields_autoplaced)
(effects (font (size 1.27 1.27)) (justify left bottom))
(uuid 19fb2bcd-aa04-4a99-bf53-4c0d6aba2f25)
(property "op" "${OP.2V}" (at 159.4485 92.71 0)
(effects (font (size 1.27 1.27) italic) (justify left))
)
)
(netclass_flag "" (length 2.54) (shape round) (at 158.75 57.15 0) (fields_autoplaced)
(effects (font (size 1.27 1.27)) (justify left bottom))
(uuid 2ec23ab4-fcb7-40c7-a748-e6a10b2808c5)
(property "op" "${OP.3mV}" (at 159.4485 54.61 0)
(effects (font (size 1.27 1.27) italic) (justify left))
)
)
(netclass_flag "" (length 2.54) (shape round) (at 160.02 133.35 0) (fields_autoplaced)
(effects (font (size 1.27 1.27)) (justify left bottom))
(uuid bb66a009-cad9-4d11-a1ba-1101278f7a49)
(property "op" "${OP}" (at 160.7185 130.81 0)
(effects (font (size 1.27 1.27) italic) (justify left))
)
)
(symbol (lib_id "power:GND") (at 152.4 63.5 0) (unit 1)
(in_bom yes) (on_board yes) (dnp no) (fields_autoplaced)
(uuid 714a5327-723b-4f39-a927-3d5170d8f38b)
(property "Reference" "#PWR?" (at 152.4 69.85 0)
(property "Reference" "#PWR0102" (at 152.4 69.85 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Value" "GND" (at 152.4 68.58 0)
@ -311,7 +429,7 @@
(instances
(project "potentiometers"
(path "/1982c87f-95a1-4a40-9669-f13cd3c28543"
(reference "#PWR?") (unit 1) (value "GND") (footprint "")
(reference "#PWR0102") (unit 1)
)
)
)
@ -347,7 +465,7 @@
(instances
(project "potentiometers"
(path "/1982c87f-95a1-4a40-9669-f13cd3c28543"
(reference "RV3") (unit 1) (value "1k") (footprint "")
(reference "RV3") (unit 1)
)
)
)
@ -380,7 +498,7 @@
(instances
(project "potentiometers"
(path "/1982c87f-95a1-4a40-9669-f13cd3c28543"
(reference "RV1") (unit 1) (value "1k") (footprint "")
(reference "RV1") (unit 1)
)
)
)
@ -389,7 +507,7 @@
(symbol (lib_id "power:GND") (at 152.4 139.7 0) (unit 1)
(in_bom yes) (on_board yes) (dnp no) (fields_autoplaced)
(uuid 97c6566f-c80b-4dd7-b07e-c44615310263)
(property "Reference" "#PWR?" (at 152.4 146.05 0)
(property "Reference" "#PWR0103" (at 152.4 146.05 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Value" "GND" (at 152.4 144.78 0)
@ -405,14 +523,14 @@
(instances
(project "potentiometers"
(path "/1982c87f-95a1-4a40-9669-f13cd3c28543"
(reference "#PWR?") (unit 1) (value "GND") (footprint "")
(reference "#PWR0103") (unit 1)
)
)
)
)
(symbol (lib_id "Simulation_SPICE:VDC") (at 114.3 57.15 0) (unit 1)
(in_bom yes) (on_board yes) (dnp no) (fields_autoplaced)
(in_bom yes) (on_board yes) (dnp no)
(uuid b53e13df-0a0c-4917-99d9-00f4258e8f24)
(property "Reference" "V1" (at 118.11 55.245 0)
(effects (font (size 1.27 1.27)) (justify left))
@ -429,12 +547,20 @@
(property "Sim.Device" "V" (at 114.3 57.15 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "four cats out of five" "${OP}" (at 120.65 63.5 0)
(effects (font (size 1.27 1.27)))
)
(pin "1" (uuid 4553662d-6271-4548-b150-dc1eb8221d40))
(pin "2" (uuid 9ab1f350-5c0f-4459-b0df-abd174706379))
(instances
(project "potentiometers"
(path "/1982c87f-95a1-4a40-9669-f13cd3c28543"
(reference "V1") (unit 1) (value "1") (footprint "")
(reference "V1") (unit 1)
)
)
(project ""
(path "/819ca68d-3774-4cc3-bc37-7f904ecae47c"
(reference "V1") (unit 1)
)
)
)
@ -443,7 +569,7 @@
(symbol (lib_id "power:GND") (at 114.3 63.5 0) (unit 1)
(in_bom yes) (on_board yes) (dnp no) (fields_autoplaced)
(uuid d310f44b-5ee6-401e-97cc-5e407654bb6b)
(property "Reference" "#PWR?" (at 114.3 69.85 0)
(property "Reference" "#PWR0104" (at 114.3 69.85 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Value" "GND" (at 114.3 68.58 0)
@ -459,7 +585,7 @@
(instances
(project "potentiometers"
(path "/1982c87f-95a1-4a40-9669-f13cd3c28543"
(reference "#PWR?") (unit 1) (value "GND") (footprint "")
(reference "#PWR0104") (unit 1)
)
)
)
@ -489,13 +615,21 @@
(property "Sim.Params" "pos=0.3" (at 146.05 99.06 0)
(effects (font (size 1.27 1.27)))
)
(property "four cats out of five" "" (at 152.4 95.25 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid 506d640e-0a3d-4ba3-a5f0-80d908fad32d))
(pin "2" (uuid dc9b9c37-5353-4880-87bb-8fc37017c528))
(pin "3" (uuid db81ec35-ea18-4bf8-aefc-34db5616ae22))
(instances
(project "potentiometers"
(path "/1982c87f-95a1-4a40-9669-f13cd3c28543"
(reference "RV2") (unit 1) (value "1k") (footprint "")
(reference "RV2") (unit 1)
)
)
(project ""
(path "/c77911d6-6148-44b5-abe9-6b8990dcab43"
(reference "RV2") (unit 1)
)
)
)
@ -504,7 +638,7 @@
(symbol (lib_id "power:GND") (at 152.4 101.6 0) (unit 1)
(in_bom yes) (on_board yes) (dnp no) (fields_autoplaced)
(uuid ee756bad-e6db-46d4-99bc-20add3a7dccf)
(property "Reference" "#PWR?" (at 152.4 107.95 0)
(property "Reference" "#PWR0101" (at 152.4 107.95 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Value" "GND" (at 152.4 106.68 0)
@ -520,13 +654,52 @@
(instances
(project "potentiometers"
(path "/1982c87f-95a1-4a40-9669-f13cd3c28543"
(reference "#PWR?") (unit 1) (value "GND") (footprint "")
(reference "#PWR0101") (unit 1)
)
)
)
)
(symbol (lib_id "device:Q_NPN_BCE") (at 124.46 107.95 0) (unit 1)
(in_bom yes) (on_board yes) (dnp no)
(uuid f4b5b14d-00c0-4b07-bfa5-0af01d8fd42f)
(property "Reference" "Q1" (at 129.54 107.315 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Value" "Q_NPN_BCE" (at 129.54 109.855 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Footprint" "" (at 129.54 105.41 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (at 124.46 107.95 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Sim.Device" "NPN" (at 124.46 107.95 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Sim.Type" "VBIC" (at 124.46 107.95 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Sim.Pins" "1=B 2=C 3=E" (at 124.46 107.95 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "e_current" "${OP:E}" (at 132.08 114.3 0)
(effects (font (size 1.27 1.27)))
)
(pin "1" (uuid 7157f3f9-abcb-44d3-a361-1a0eac9a5aa0))
(pin "2" (uuid 8bf73ee2-c883-40ac-98ea-3f05e75843e9))
(pin "3" (uuid bcf9c5d6-03dc-45b4-8d3c-869e0934e038))
(instances
(project "potentiometers"
(path "/1982c87f-95a1-4a40-9669-f13cd3c28543"
(reference "Q1") (unit 1)
)
)
)
)
(sheet_instances
(path "/1982c87f-95a1-4a40-9669-f13cd3c28543" (page "1"))
(path "/" (page "1"))
)
)