SPICE: Add support for transmission lines
This commit is contained in:
parent
2dbc89e5f2
commit
58e167013d
|
@ -252,21 +252,25 @@ bool DIALOG_SPICE_MODEL::TransferDataFromWindow()
|
|||
// Passive
|
||||
if( page == m_passive )
|
||||
{
|
||||
if( !m_disabled->GetValue() && !m_passive->Validate() )
|
||||
return false;
|
||||
|
||||
switch( m_pasType->GetSelection() )
|
||||
{
|
||||
case 0: m_fieldsTmp[SF_PRIMITIVE] = (char) SP_RESISTOR; break;
|
||||
case 1: m_fieldsTmp[SF_PRIMITIVE] = (char) SP_CAPACITOR; break;
|
||||
case 2: m_fieldsTmp[SF_PRIMITIVE] = (char) SP_INDUCTOR; break;
|
||||
|
||||
default:
|
||||
wxASSERT_MSG( false, "Unhandled passive type" );
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
bool checkValue = m_fieldsTmp[SF_PRIMITIVE] == (char) SP_RESISTOR
|
||||
|| m_fieldsTmp[SF_PRIMITIVE] == (char) SP_CAPACITOR
|
||||
|| m_fieldsTmp[SF_PRIMITIVE] == (char) SP_INDUCTOR;
|
||||
|
||||
if( checkValue && !m_disabled->GetValue() && !m_passive->Validate() )
|
||||
return false;
|
||||
|
||||
m_fieldsTmp[SF_MODEL] = m_pasValue->GetValue();
|
||||
}
|
||||
else if( page == m_model ) // Model
|
||||
|
@ -294,6 +298,34 @@ bool DIALOG_SPICE_MODEL::TransferDataFromWindow()
|
|||
m_fieldsTmp[SF_PRIMITIVE] = (char)( m_pwrType->GetSelection() ? SP_ISOURCE : SP_VSOURCE );
|
||||
m_fieldsTmp[SF_MODEL] = model;
|
||||
}
|
||||
else if( page == m_tline )
|
||||
{
|
||||
wxWindow* subpage = m_tlineNotebook->GetCurrentPage();
|
||||
wxString model;
|
||||
|
||||
if( subpage == m_tlineLossless )
|
||||
{
|
||||
m_fieldsTmp[SF_PRIMITIVE] = (char) SP_TLINE;
|
||||
|
||||
if( !generateTlineLossless( model ) )
|
||||
return false;
|
||||
|
||||
m_fieldsTmp[SF_MODEL] = model;
|
||||
}
|
||||
else if( subpage == m_tlineLossy )
|
||||
{
|
||||
m_fieldsTmp[SF_PRIMITIVE] = (char) SP_TLINE_LOSSY;
|
||||
|
||||
if( !generateTlineLossy( model ) )
|
||||
return false;
|
||||
|
||||
m_fieldsTmp[SF_MODEL] = model;
|
||||
}
|
||||
else
|
||||
{
|
||||
wxASSERT_MSG( false, "Unhandled transmission line type" );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wxASSERT_MSG( false, "Unhandled model type" );
|
||||
|
@ -388,13 +420,26 @@ bool DIALOG_SPICE_MODEL::TransferDataToWindow()
|
|||
case SP_CAPACITOR:
|
||||
case SP_INDUCTOR:
|
||||
m_notebook->SetSelection( m_notebook->FindPage( m_passive ) );
|
||||
m_pasType->SetSelection( primitive == SP_RESISTOR ? 0
|
||||
: primitive == SP_CAPACITOR ? 1
|
||||
: primitive == SP_INDUCTOR ? 2
|
||||
: -1 );
|
||||
m_pasType->SetSelection( primitive == SP_RESISTOR ? 0
|
||||
: primitive == SP_CAPACITOR ? 1
|
||||
: primitive == SP_INDUCTOR ? 2
|
||||
: -1 );
|
||||
m_pasValue->SetValue( m_fieldsTmp[SF_MODEL] );
|
||||
break;
|
||||
case SP_TLINE:
|
||||
m_notebook->SetSelection( m_notebook->FindPage( m_tline ) );
|
||||
m_tlineNotebook->SetSelection( m_tlineNotebook->FindPage( m_tlineLossless ) );
|
||||
|
||||
if( !parseLosslessTline( m_fieldsTmp[SF_MODEL] ) )
|
||||
return false;
|
||||
break;
|
||||
case SP_TLINE_LOSSY:
|
||||
m_notebook->SetSelection( m_notebook->FindPage( m_tline ) );
|
||||
m_tlineNotebook->SetSelection( m_tlineNotebook->FindPage( m_tlineLossy ) );
|
||||
|
||||
if( !parseLossyTline( m_fieldsTmp[SF_MODEL] ) )
|
||||
return false;
|
||||
break;
|
||||
case SP_DIODE:
|
||||
case SP_BJT:
|
||||
case SP_MOSFET:
|
||||
|
@ -480,6 +525,88 @@ void DIALOG_SPICE_MODEL::showPinOrderNote( int aModelType )
|
|||
m_stInfoNote->SetLabel( msg );
|
||||
}
|
||||
|
||||
bool DIALOG_SPICE_MODEL::parseLosslessTline( const wxString& aModel )
|
||||
{
|
||||
if( aModel.IsEmpty() )
|
||||
return false;
|
||||
|
||||
wxStringTokenizer tokenizer( aModel, " " );
|
||||
|
||||
while( tokenizer.HasMoreTokens() )
|
||||
{
|
||||
// Get the next token now, so if any of the branches catches an exception, try to
|
||||
// process it in another branch
|
||||
wxString tkn = tokenizer.GetNextToken().Lower();
|
||||
|
||||
if( tkn.SubString( 0, 2 ) == "z0=" )
|
||||
{
|
||||
m_tlineLosslessImpedance->SetValue( tkn.AfterFirst( wxUniChar( '=' ) ) );
|
||||
}
|
||||
else if( tkn.SubString( 0, 2 ) == "td=" )
|
||||
{
|
||||
m_tlineLosslessDelay->SetValue( tkn.AfterFirst( wxUniChar( '=' ) ) );
|
||||
m_tlineLosslessDelayMode->SetSelection( 0 );
|
||||
}
|
||||
else if( tkn.SubString( 0, 1 ) == "f=" )
|
||||
{
|
||||
m_tlineLosslessFrequency->SetValue( tkn.AfterFirst( wxUniChar( '=' ) ) );
|
||||
m_tlineLosslessDelayMode->SetSelection( 1 );
|
||||
}
|
||||
else if( tkn.SubString( 0, 2 ) == "nl=" )
|
||||
{
|
||||
m_tlineLosslessWavelength->SetValue( tkn.AfterFirst( wxUniChar( '=' ) ) );
|
||||
m_tlineLosslessDelayMode->SetSelection( 1 );
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DIALOG_SPICE_MODEL::parseLossyTline( const wxString& aModel )
|
||||
{
|
||||
if( aModel.IsEmpty() )
|
||||
return false;
|
||||
|
||||
wxStringTokenizer tokenizer( aModel, " " );
|
||||
|
||||
wxString extraParam = "";
|
||||
|
||||
while( tokenizer.HasMoreTokens() )
|
||||
{
|
||||
// Get the next token now, so if any of the branches catches an exception, try to
|
||||
// process it in another branch
|
||||
wxString tkn = tokenizer.GetNextToken().Lower();
|
||||
|
||||
if( tkn.SubString( 0, 1 ) == "r=" )
|
||||
{
|
||||
m_tlineLossyR->SetValue( tkn.AfterFirst( wxUniChar( '=' ) ) );
|
||||
}
|
||||
else if( tkn.SubString( 0, 1 ) == "l=" )
|
||||
{
|
||||
m_tlineLossyL->SetValue( tkn.AfterFirst( wxUniChar( '=' ) ) );
|
||||
}
|
||||
else if( tkn.SubString( 0, 1 ) == "c=" )
|
||||
{
|
||||
m_tlineLossyC->SetValue( tkn.AfterFirst( wxUniChar( '=' ) ) );
|
||||
}
|
||||
else if( tkn.SubString( 0, 1 ) == "g=" )
|
||||
{
|
||||
m_tlineLossyG->SetValue( tkn.AfterFirst( wxUniChar( '=' ) ) );
|
||||
}
|
||||
else if( tkn.SubString( 0, 3 ) == "len=" )
|
||||
{
|
||||
m_tlineLossyLen->SetValue( tkn.AfterFirst( wxUniChar( '=' ) ) );
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
extraParam += tkn + " ";
|
||||
}
|
||||
}
|
||||
m_tlineLossyParams->SetValue( extraParam );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DIALOG_SPICE_MODEL::parsePowerSource( const wxString& aModel )
|
||||
{
|
||||
|
@ -661,6 +788,139 @@ bool DIALOG_SPICE_MODEL::parsePowerSource( const wxString& aModel )
|
|||
}
|
||||
|
||||
|
||||
bool DIALOG_SPICE_MODEL::generateTlineLossless( wxString& aTarget )
|
||||
{
|
||||
wxString result = "";
|
||||
|
||||
try
|
||||
{
|
||||
if( !empty( m_tlineLosslessImpedance ) )
|
||||
result += wxString::Format(
|
||||
"Z0=%s ", SPICE_VALUE( m_tlineLosslessImpedance->GetValue() ).ToSpiceString() );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
DisplayError( this, _( "Invalid Impedance value" ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if( m_tlineLosslessDelayMode->GetSelection() == 0 )
|
||||
{
|
||||
try
|
||||
{
|
||||
if( !empty( m_tlineLosslessDelay ) )
|
||||
result += wxString::Format(
|
||||
"TD=%s ", SPICE_VALUE( m_tlineLosslessDelay->GetValue() ).ToSpiceString() );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
DisplayError( this, _( "Invalid delay value" ) );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if( m_tlineLosslessDelayMode->GetSelection() == 1 )
|
||||
{
|
||||
try
|
||||
{
|
||||
if( !empty( m_tlineLosslessFrequency ) )
|
||||
result += wxString::Format(
|
||||
"F=%s ",
|
||||
SPICE_VALUE( m_tlineLosslessFrequency->GetValue() ).ToSpiceString() );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
DisplayError( this, _( "Invalid frequency value" ) );
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
if( !empty( m_tlineLosslessWavelength ) )
|
||||
result += wxString::Format(
|
||||
"NL=%s ",
|
||||
SPICE_VALUE( m_tlineLosslessWavelength->GetValue() ).ToSpiceString() );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
DisplayError( this, _( "Invalid length in wavelength value" ) );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
aTarget += result;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DIALOG_SPICE_MODEL::generateTlineLossy( wxString& aTarget )
|
||||
{
|
||||
wxString result;
|
||||
|
||||
try
|
||||
{
|
||||
if( !empty( m_tlineLossyR ) )
|
||||
result += wxString::Format( "r=%s ",
|
||||
SPICE_VALUE( m_tlineLossyR->GetValue() ).ToSpiceString() );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
DisplayError( this, _( "Invalid resistance value" ) );
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
if( !empty( m_tlineLossyC ) )
|
||||
result += wxString::Format( "c=%s ",
|
||||
SPICE_VALUE( m_tlineLossyC->GetValue() ).ToSpiceString() );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
DisplayError( this, _( "Invalid capacitance value" ) );
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
if( !empty( m_tlineLossyL ) )
|
||||
result += wxString::Format( "l=%s ",
|
||||
SPICE_VALUE( m_tlineLossyL->GetValue() ).ToSpiceString() );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
DisplayError( this, _( "Invalid inductance value" ) );
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
if( !empty( m_tlineLossyG ) )
|
||||
result += wxString::Format( "g=%s ",
|
||||
SPICE_VALUE( m_tlineLossyG->GetValue() ).ToSpiceString() );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
DisplayError( this, _( "Invalid conductance value" ) );
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
if( !empty( m_tlineLossyLen ) )
|
||||
result += wxString::Format(
|
||||
"len=%s ", SPICE_VALUE( m_tlineLossyLen->GetValue() ).ToSpiceString() );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
DisplayError( this, _( "Invalid length value" ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
result += m_tlineLossyParams->GetValue();
|
||||
|
||||
aTarget += result;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DIALOG_SPICE_MODEL::generatePowerSource( wxString& aTarget )
|
||||
{
|
||||
wxString acdc, trans;
|
||||
|
|
|
@ -55,6 +55,23 @@ private:
|
|||
*/
|
||||
bool parsePowerSource( const wxString& aModel );
|
||||
|
||||
/**
|
||||
* Parse a string describing a lossless transmission line, so appropriate settings are checked in the dialog.
|
||||
*
|
||||
* @param aModel contains the string to be parse (e.g. "Z0=50 td=10n")
|
||||
* @return True if the input string was parsed without errors.
|
||||
*/
|
||||
bool parseLosslessTline( const wxString& aModel );
|
||||
|
||||
/**
|
||||
* Parse a string describing a lossy transmission line, so appropriate settings are checked in the dialog.
|
||||
*
|
||||
* @param aModel contains the string to be parse (e.g. "R=50 C=10 LEN=1")
|
||||
* @return True if the input string was parsed without errors.
|
||||
*/
|
||||
bool parseLossyTline( const wxString& aModel );
|
||||
|
||||
|
||||
/**
|
||||
* Generate a string to describe power source parameters, basing on the current selection.
|
||||
*
|
||||
|
@ -65,6 +82,26 @@ private:
|
|||
*/
|
||||
bool generatePowerSource( wxString& aTarget );
|
||||
|
||||
/**
|
||||
* Generate a string to describe a transmission line model, basing on the current selection.
|
||||
*
|
||||
* If there are missing fields, it will not modify the target string.
|
||||
*
|
||||
* @param aTarget is the destination for the generated string.
|
||||
* @return True if the string was saved successfully.
|
||||
*/
|
||||
bool generateTlineLossless( wxString& aTarget );
|
||||
|
||||
/**
|
||||
* Generate a string to describe a transmission line model, basing on the current selection.
|
||||
*
|
||||
* If there are missing fields, it will not modify the target string.
|
||||
*
|
||||
* @param aTarget is the destination for the generated string.
|
||||
* @return True if the string was saved successfully.
|
||||
*/
|
||||
bool generateTlineLossy( wxString& aTarget );
|
||||
|
||||
/**
|
||||
* Load a list of components (.model and .subckt) from a spice library file and add them to
|
||||
* a combo box.
|
||||
|
|
|
@ -928,6 +928,187 @@ DIALOG_SPICE_MODEL_BASE::DIALOG_SPICE_MODEL_BASE( wxWindow* parent, wxWindowID i
|
|||
m_power->Layout();
|
||||
bSizer4->Fit( m_power );
|
||||
m_notebook->AddPage( m_power, _("Source"), false );
|
||||
m_tline = new wxPanel( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
m_tline->SetMinSize( wxSize( 650,-1 ) );
|
||||
|
||||
wxBoxSizer* bSizer42;
|
||||
bSizer42 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxStaticBoxSizer* sbSizer31;
|
||||
sbSizer31 = new wxStaticBoxSizer( new wxStaticBox( m_tline, wxID_ANY, _("Line model") ), wxVERTICAL );
|
||||
|
||||
m_tlineNotebook = new wxNotebook( sbSizer31->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_tlineLossless = new wxPanel( m_tlineNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
wxFlexGridSizer* fgSizer131;
|
||||
fgSizer131 = new wxFlexGridSizer( 0, 1, 0, 0 );
|
||||
fgSizer131->AddGrowableCol( 1 );
|
||||
fgSizer131->SetFlexibleDirection( wxBOTH );
|
||||
fgSizer131->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
wxFlexGridSizer* fgSizer1311;
|
||||
fgSizer1311 = new wxFlexGridSizer( 4, 3, 0, 0 );
|
||||
fgSizer1311->AddGrowableCol( 1 );
|
||||
fgSizer1311->SetFlexibleDirection( wxBOTH );
|
||||
fgSizer1311->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_staticText2671111 = new wxStaticText( m_tlineLossless, wxID_ANY, _("Characteristic impedance"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText2671111->Wrap( -1 );
|
||||
fgSizer1311->Add( m_staticText2671111, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
m_tlineLosslessImpedance = new wxTextCtrl( m_tlineLossless, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer1311->Add( m_tlineLosslessImpedance, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_staticText26211111 = new wxStaticText( m_tlineLossless, wxID_ANY, _("ohm"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText26211111->Wrap( -1 );
|
||||
fgSizer1311->Add( m_staticText26211111, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
m_staticText26711111 = new wxStaticText( m_tlineLossless, wxID_ANY, _("Propagation delay"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText26711111->Wrap( -1 );
|
||||
fgSizer1311->Add( m_staticText26711111, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
m_tlineLosslessDelay = new wxTextCtrl( m_tlineLossless, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer1311->Add( m_tlineLosslessDelay, 0, wxALL, 5 );
|
||||
|
||||
m_staticText262111111 = new wxStaticText( m_tlineLossless, wxID_ANY, _("s"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText262111111->Wrap( -1 );
|
||||
fgSizer1311->Add( m_staticText262111111, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
m_staticText267111111 = new wxStaticText( m_tlineLossless, wxID_ANY, _("Frequency"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText267111111->Wrap( -1 );
|
||||
fgSizer1311->Add( m_staticText267111111, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
m_tlineLosslessFrequency = new wxTextCtrl( m_tlineLossless, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer1311->Add( m_tlineLosslessFrequency, 1, wxALL, 5 );
|
||||
|
||||
m_staticText2621111111 = new wxStaticText( m_tlineLossless, wxID_ANY, _("Hz"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText2621111111->Wrap( -1 );
|
||||
fgSizer1311->Add( m_staticText2621111111, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
m_staticText2671111111 = new wxStaticText( m_tlineLossless, wxID_ANY, _("Length in wavelength"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText2671111111->Wrap( -1 );
|
||||
fgSizer1311->Add( m_staticText2671111111, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
m_tlineLosslessWavelength = new wxTextCtrl( m_tlineLossless, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer1311->Add( m_tlineLosslessWavelength, 1, wxALL, 5 );
|
||||
|
||||
|
||||
fgSizer1311->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
fgSizer131->Add( fgSizer1311, 100, wxEXPAND, 5 );
|
||||
|
||||
wxString m_tlineLosslessDelayModeChoices[] = { _("Use time delay"), _("Use frequency and number of wavelength") };
|
||||
int m_tlineLosslessDelayModeNChoices = sizeof( m_tlineLosslessDelayModeChoices ) / sizeof( wxString );
|
||||
m_tlineLosslessDelayMode = new wxRadioBox( m_tlineLossless, wxID_ANY, _("Delay / Electrical length"), wxDefaultPosition, wxDefaultSize, m_tlineLosslessDelayModeNChoices, m_tlineLosslessDelayModeChoices, 1, wxRA_SPECIFY_COLS );
|
||||
m_tlineLosslessDelayMode->SetSelection( 0 );
|
||||
fgSizer131->Add( m_tlineLosslessDelayMode, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_tlineLossless->SetSizer( fgSizer131 );
|
||||
m_tlineLossless->Layout();
|
||||
fgSizer131->Fit( m_tlineLossless );
|
||||
m_tlineNotebook->AddPage( m_tlineLossless, _("Lossless"), true );
|
||||
m_tlineLossy = new wxPanel( m_tlineNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
wxFlexGridSizer* fgSizer1312;
|
||||
fgSizer1312 = new wxFlexGridSizer( 0, 1, 0, 0 );
|
||||
fgSizer1312->AddGrowableCol( 1 );
|
||||
fgSizer1312->SetFlexibleDirection( wxBOTH );
|
||||
fgSizer1312->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
wxFlexGridSizer* fgSizer13111;
|
||||
fgSizer13111 = new wxFlexGridSizer( 0, 3, 0, 0 );
|
||||
fgSizer13111->AddGrowableCol( 1 );
|
||||
fgSizer13111->SetFlexibleDirection( wxBOTH );
|
||||
fgSizer13111->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_staticText26711112 = new wxStaticText( m_tlineLossy, wxID_ANY, _("Resistance per unit length"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText26711112->Wrap( -1 );
|
||||
fgSizer13111->Add( m_staticText26711112, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
m_tlineLossyR = new wxTextCtrl( m_tlineLossy, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer13111->Add( m_tlineLossyR, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_staticText262111112 = new wxStaticText( m_tlineLossy, wxID_ANY, _("ohm / unit"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText262111112->Wrap( -1 );
|
||||
fgSizer13111->Add( m_staticText262111112, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
m_staticText267111112 = new wxStaticText( m_tlineLossy, wxID_ANY, _("Inductance per unit length"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText267111112->Wrap( -1 );
|
||||
fgSizer13111->Add( m_staticText267111112, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
m_tlineLossyL = new wxTextCtrl( m_tlineLossy, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer13111->Add( m_tlineLossyL, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_staticText2621111112 = new wxStaticText( m_tlineLossy, wxID_ANY, _("henry / unit"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText2621111112->Wrap( -1 );
|
||||
fgSizer13111->Add( m_staticText2621111112, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
m_staticText2671111112 = new wxStaticText( m_tlineLossy, wxID_ANY, _("Capacitance per unit length"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText2671111112->Wrap( -1 );
|
||||
fgSizer13111->Add( m_staticText2671111112, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
m_tlineLossyC = new wxTextCtrl( m_tlineLossy, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer13111->Add( m_tlineLossyC, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_staticText26211111111 = new wxStaticText( m_tlineLossy, wxID_ANY, _("farad / unit"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText26211111111->Wrap( -1 );
|
||||
fgSizer13111->Add( m_staticText26211111111, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
m_staticText26711111111 = new wxStaticText( m_tlineLossy, wxID_ANY, _("Conductance per unit length"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText26711111111->Wrap( -1 );
|
||||
fgSizer13111->Add( m_staticText26711111111, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
m_tlineLossyG = new wxTextCtrl( m_tlineLossy, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer13111->Add( m_tlineLossyG, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_staticText262111111111 = new wxStaticText( m_tlineLossy, wxID_ANY, _("siemens / unit"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText262111111111->Wrap( -1 );
|
||||
fgSizer13111->Add( m_staticText262111111111, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
m_staticText267111111111 = new wxStaticText( m_tlineLossy, wxID_ANY, _("Length"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText267111111111->Wrap( -1 );
|
||||
fgSizer13111->Add( m_staticText267111111111, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
m_tlineLossyLen = new wxTextCtrl( m_tlineLossy, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer13111->Add( m_tlineLossyLen, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_staticText262111111112 = new wxStaticText( m_tlineLossy, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText262111111112->Wrap( -1 );
|
||||
fgSizer13111->Add( m_staticText262111111112, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
m_staticText2671111111111 = new wxStaticText( m_tlineLossy, wxID_ANY, _("Extra parameters"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText2671111111111->Wrap( -1 );
|
||||
fgSizer13111->Add( m_staticText2671111111111, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
m_tlineLossyParams = new wxTextCtrl( m_tlineLossy, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer13111->Add( m_tlineLossyParams, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
fgSizer1312->Add( fgSizer13111, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_staticline21 = new wxStaticLine( m_tlineLossy, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
fgSizer1312->Add( m_staticline21, 0, wxEXPAND | wxALL, 5 );
|
||||
|
||||
m_staticText1812 = new wxStaticText( m_tlineLossy, wxID_ANY, _("The following types of lines have been implemented so far:\n\n- RLC\n- RC\n- LC\n- RG\n\nAny other combination will yield erroneous results and should not be tried."), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText1812->Wrap( -1 );
|
||||
fgSizer1312->Add( m_staticText1812, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_tlineLossy->SetSizer( fgSizer1312 );
|
||||
m_tlineLossy->Layout();
|
||||
fgSizer1312->Fit( m_tlineLossy );
|
||||
m_tlineNotebook->AddPage( m_tlineLossy, _("Lossy"), false );
|
||||
|
||||
sbSizer31->Add( m_tlineNotebook, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
|
||||
bSizer42->Add( sbSizer31, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_tline->SetSizer( bSizer42 );
|
||||
m_tline->Layout();
|
||||
bSizer42->Fit( m_tline );
|
||||
m_notebook->AddPage( m_tline, _("Transmission Line"), true );
|
||||
|
||||
bSizer1->Add( m_notebook, 1, wxEXPAND | wxALL, 5 );
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -230,6 +230,41 @@ class DIALOG_SPICE_MODEL_BASE : public DIALOG_SHIM
|
|||
wxTextCtrl* m_rnParam2;
|
||||
wxPanel* m_pwrExtData;
|
||||
wxRadioBox* m_pwrType;
|
||||
wxPanel* m_tline;
|
||||
wxNotebook* m_tlineNotebook;
|
||||
wxPanel* m_tlineLossless;
|
||||
wxStaticText* m_staticText2671111;
|
||||
wxTextCtrl* m_tlineLosslessImpedance;
|
||||
wxStaticText* m_staticText26211111;
|
||||
wxStaticText* m_staticText26711111;
|
||||
wxTextCtrl* m_tlineLosslessDelay;
|
||||
wxStaticText* m_staticText262111111;
|
||||
wxStaticText* m_staticText267111111;
|
||||
wxTextCtrl* m_tlineLosslessFrequency;
|
||||
wxStaticText* m_staticText2621111111;
|
||||
wxStaticText* m_staticText2671111111;
|
||||
wxTextCtrl* m_tlineLosslessWavelength;
|
||||
wxRadioBox* m_tlineLosslessDelayMode;
|
||||
wxPanel* m_tlineLossy;
|
||||
wxStaticText* m_staticText26711112;
|
||||
wxTextCtrl* m_tlineLossyR;
|
||||
wxStaticText* m_staticText262111112;
|
||||
wxStaticText* m_staticText267111112;
|
||||
wxTextCtrl* m_tlineLossyL;
|
||||
wxStaticText* m_staticText2621111112;
|
||||
wxStaticText* m_staticText2671111112;
|
||||
wxTextCtrl* m_tlineLossyC;
|
||||
wxStaticText* m_staticText26211111111;
|
||||
wxStaticText* m_staticText26711111111;
|
||||
wxTextCtrl* m_tlineLossyG;
|
||||
wxStaticText* m_staticText262111111111;
|
||||
wxStaticText* m_staticText267111111111;
|
||||
wxTextCtrl* m_tlineLossyLen;
|
||||
wxStaticText* m_staticText262111111112;
|
||||
wxStaticText* m_staticText2671111111111;
|
||||
wxTextCtrl* m_tlineLossyParams;
|
||||
wxStaticLine* m_staticline21;
|
||||
wxStaticText* m_staticText1812;
|
||||
wxStaticLine* m_staticline2;
|
||||
wxCheckBox* m_disabled;
|
||||
wxCheckBox* m_nodeSeqCheck;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <build_version.h>
|
||||
#include <confirm.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <search_stack.h>
|
||||
|
||||
|
@ -296,6 +297,18 @@ wxString NETLIST_EXPORTER_PSPICE::GetSpiceFieldDefVal( SPICE_FIELD aField, SCH_S
|
|||
}
|
||||
}
|
||||
|
||||
wxString modelLine( wxString aName, wxString aParams )
|
||||
{
|
||||
wxString result;
|
||||
result = aName;
|
||||
result += "\n.model ";
|
||||
result += aName;
|
||||
result += " ";
|
||||
result += aParams;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool NETLIST_EXPORTER_PSPICE::ProcessNetlist( unsigned aCtl )
|
||||
{
|
||||
|
@ -304,7 +317,10 @@ bool NETLIST_EXPORTER_PSPICE::ProcessNetlist( unsigned aCtl )
|
|||
std::set<wxString> refNames; // Set of reference names, to check for duplication
|
||||
|
||||
m_netMap.clear();
|
||||
m_netMap["GND"] = 0; // 0 is reserved for "GND"
|
||||
|
||||
int refNet = 0;
|
||||
const char* refNetString = "0";
|
||||
m_netMap["GND"] = refNet; // 0 is reserved for "GND"
|
||||
int netIdx = 1;
|
||||
|
||||
m_libraries.clear();
|
||||
|
@ -392,7 +408,53 @@ bool NETLIST_EXPORTER_PSPICE::ProcessNetlist( unsigned aCtl )
|
|||
}
|
||||
}
|
||||
|
||||
//Special case because we have a GUI to set a model.
|
||||
if( spiceItem.m_primitive == SP_TLINE_LOSSY )
|
||||
{
|
||||
spiceItem.m_model =
|
||||
modelLine( "LTRA_" + spiceItem.m_refName, "LTRA " + spiceItem.m_model );
|
||||
}
|
||||
|
||||
m_spiceItems.push_back( spiceItem );
|
||||
|
||||
|
||||
//Special case for lossline transmission lines ( TXXXX )
|
||||
//From the ngspice doc:
|
||||
// This element models only one propagating mode.
|
||||
// If all four nodes are distinct in the actual circuit, then two modes may be excited.
|
||||
// To simulate such a situation, two transmission-line elements are required.
|
||||
|
||||
// This is apparently also needed for lossy lines
|
||||
|
||||
if( spiceItem.m_primitive == SP_TLINE || spiceItem.m_primitive == SP_TLINE_LOSSY )
|
||||
{
|
||||
std::vector<wxString> pins = spiceItem.m_pins;
|
||||
std::vector<wxString> pins2 = pins;
|
||||
|
||||
|
||||
if( pins.size() == 4 ) // A transmission line as 4 pins in ngspice
|
||||
{
|
||||
std::sort( pins2.begin(), pins2.end(),
|
||||
[]( wxString& a, wxString& b ) -> bool
|
||||
{
|
||||
return a.Cmp( b ) < 0;
|
||||
} );
|
||||
bool has_duplicate =
|
||||
std::adjacent_find( pins2.begin(), pins2.end() ) != pins2.end();
|
||||
|
||||
if( !has_duplicate )
|
||||
{
|
||||
SPICE_ITEM spiceItem2 = spiceItem;
|
||||
spiceItem2.m_refName += "_kicad_pair";
|
||||
spiceItem2.m_pins.at( 0 ) = pins.at( 1 );
|
||||
spiceItem2.m_pins.at( 1 ) = refNetString;
|
||||
spiceItem2.m_pins.at( 2 ) = pins.at( 3 );
|
||||
spiceItem2.m_pins.at( 3 ) = refNetString;
|
||||
|
||||
m_spiceItems.push_back( spiceItem2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,8 @@ enum SPICE_PRIMITIVE {
|
|||
SP_RESISTOR = 'R',
|
||||
SP_CAPACITOR = 'C',
|
||||
SP_INDUCTOR = 'L',
|
||||
SP_TLINE = 'T',
|
||||
SP_TLINE_LOSSY = 'O',
|
||||
SP_DIODE = 'D',
|
||||
SP_BJT = 'Q',
|
||||
SP_MOSFET = 'M',
|
||||
|
|
Loading…
Reference in New Issue