Add tuner support for potentiometer code model
This commit is contained in:
parent
e618ef98e9
commit
f004665df8
|
@ -61,6 +61,36 @@ wxString NETLIST_EXPORTER_PSPICE::GetSpiceDevice( const wxString& aSymbol ) cons
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// most part is identical to above GetSpiceDevice()
|
||||||
|
std::pair<wxString, bool>
|
||||||
|
NETLIST_EXPORTER_PSPICE::GetSpiceTuningCommand( const wxString& aSymbol ) const
|
||||||
|
{
|
||||||
|
const std::list<SPICE_ITEM>& spiceItems = GetSpiceItems();
|
||||||
|
|
||||||
|
auto it = std::find_if( spiceItems.begin(), spiceItems.end(),
|
||||||
|
[&]( const SPICE_ITEM& item )
|
||||||
|
{
|
||||||
|
return item.m_refName == aSymbol;
|
||||||
|
} );
|
||||||
|
|
||||||
|
if( it == spiceItems.end() )
|
||||||
|
return { wxEmptyString, false };
|
||||||
|
|
||||||
|
/// @todo assuming ngspice potentiometer code model
|
||||||
|
/// @todo no ngspice hard coding
|
||||||
|
if( it->m_primitive == SP_CODEMODEL )
|
||||||
|
return { "altermod @" + it->m_model.Lower() + "[position]=", true };
|
||||||
|
|
||||||
|
// Prefix the device type if plain reference would result in a different device type
|
||||||
|
wxString name = it->m_primitive != it->m_refName[0]
|
||||||
|
? wxString( it->m_primitive + it->m_refName )
|
||||||
|
: it->m_refName;
|
||||||
|
|
||||||
|
/// @todo no ngspice hard coding
|
||||||
|
return { "alter @" + name.Lower() + "=", false };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool NETLIST_EXPORTER_PSPICE::WriteNetlist( const wxString& aOutFileName, unsigned aNetlistOptions )
|
bool NETLIST_EXPORTER_PSPICE::WriteNetlist( const wxString& aOutFileName, unsigned aNetlistOptions )
|
||||||
{
|
{
|
||||||
FILE_OUTPUTFORMATTER outputFile( aOutFileName, wxT( "wt" ), '\'' );
|
FILE_OUTPUTFORMATTER outputFile( aOutFileName, wxT( "wt" ), '\'' );
|
||||||
|
|
|
@ -119,6 +119,16 @@ public:
|
||||||
*/
|
*/
|
||||||
wxString GetSpiceDevice( const wxString& aSymbol ) const;
|
wxString GetSpiceDevice( const wxString& aSymbol ) const;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the command to alter a Spice parameter of a schematic symbol.
|
||||||
|
*
|
||||||
|
* @param aSymbol is the symbol reference.
|
||||||
|
* @return Spice command or empty string if there is no such component in the netlist,
|
||||||
|
* and true if it is a code model parameter, false if it is an instance parameter.
|
||||||
|
*/
|
||||||
|
std::pair<wxString, bool> GetSpiceTuningCommand( const wxString& aSymbol ) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write to specified output file
|
* Write to specified output file
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -539,11 +539,11 @@ void SIM_PLOT_FRAME::AddTuner( SCH_SYMBOL* aSymbol )
|
||||||
if( !plotPanel )
|
if( !plotPanel )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// For now limit the tuner tool to RLC components
|
// For now limit the tuner tool to RLC and code model components
|
||||||
char primitiveType = NETLIST_EXPORTER_PSPICE::GetSpiceField( SF_PRIMITIVE, aSymbol, 0 )[0];
|
char primitiveType = NETLIST_EXPORTER_PSPICE::GetSpiceField( SF_PRIMITIVE, aSymbol, 0 )[0];
|
||||||
|
|
||||||
if( primitiveType != SP_RESISTOR && primitiveType != SP_CAPACITOR
|
if( primitiveType != SP_RESISTOR && primitiveType != SP_CAPACITOR
|
||||||
&& primitiveType != SP_INDUCTOR )
|
&& primitiveType != SP_INDUCTOR && primitiveType != SP_CODEMODEL )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const wxString componentName = aSymbol->GetField( REFERENCE_FIELD )->GetText();
|
const wxString componentName = aSymbol->GetField( REFERENCE_FIELD )->GetText();
|
||||||
|
@ -917,11 +917,15 @@ void SIM_PLOT_FRAME::applyTuners()
|
||||||
{
|
{
|
||||||
for( auto& tuner : m_tuners )
|
for( auto& tuner : m_tuners )
|
||||||
{
|
{
|
||||||
/// @todo no ngspice hard coding
|
std::pair<wxString, bool> command = tuner->GetSpiceTuningCommand();
|
||||||
std::string command( "alter @" + tuner->GetSpiceName()
|
const SPICE_VALUE& value = tuner->GetValue();
|
||||||
+ "=" + tuner->GetValue().ToSpiceString() );
|
|
||||||
|
|
||||||
m_simulator->Command( command );
|
// 0 < value < 1 for model parameter to avoid division by zero, etc.
|
||||||
|
command.first += command.second
|
||||||
|
? wxString::FromCDouble( Clamp( 1e-9, value.ToDouble() / 100.0, 1-1e-9 ), 9 )
|
||||||
|
: value.ToSpiceString();
|
||||||
|
|
||||||
|
m_simulator->Command( command.first.ToStdString() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,26 +34,40 @@
|
||||||
TUNER_SLIDER::TUNER_SLIDER( SIM_PLOT_FRAME* aFrame, wxWindow* aParent, SCH_SYMBOL* aSymbol ) :
|
TUNER_SLIDER::TUNER_SLIDER( SIM_PLOT_FRAME* aFrame, wxWindow* aParent, SCH_SYMBOL* aSymbol ) :
|
||||||
TUNER_SLIDER_BASE( aParent ),
|
TUNER_SLIDER_BASE( aParent ),
|
||||||
m_symbol( aSymbol ),
|
m_symbol( aSymbol ),
|
||||||
|
m_fieldId( MANDATORY_FIELD_T::VALUE_FIELD ),
|
||||||
m_min( 0.0 ),
|
m_min( 0.0 ),
|
||||||
m_max( 0.0 ),
|
m_max( 0.0 ),
|
||||||
m_changed( false ),
|
m_value( 0.0 ),
|
||||||
m_frame ( aFrame )
|
m_frame ( aFrame )
|
||||||
{
|
{
|
||||||
const wxString compName = aSymbol->GetField( REFERENCE_FIELD )->GetText();
|
const wxString compName = aSymbol->GetField( REFERENCE_FIELD )->GetText();
|
||||||
m_name->SetLabel( compName );
|
m_name->SetLabel( compName );
|
||||||
|
m_spiceTuningCommand = aFrame->GetExporter()->GetSpiceTuningCommand( compName );
|
||||||
|
|
||||||
if( aSymbol->FindField( NETLIST_EXPORTER_PSPICE::GetSpiceFieldName( SF_MODEL ) ) )
|
if( m_spiceTuningCommand.second )
|
||||||
m_fieldId = aSymbol->FindField( NETLIST_EXPORTER_PSPICE::GetSpiceFieldName( SF_MODEL ) )->GetId();
|
{
|
||||||
|
// model parameter, with fixed %-range and unknown initial value
|
||||||
|
m_min = 0;
|
||||||
|
m_max = 100;
|
||||||
|
m_value = ( m_max - m_min ) / 2.0; // midpoint
|
||||||
|
m_minText->Disable();
|
||||||
|
m_maxText->Disable();
|
||||||
|
m_saveBtn->Disable(); // not an instance parameter that could be updated (invalid m_fieldId)
|
||||||
|
}
|
||||||
else
|
else
|
||||||
m_fieldId = aSymbol->GetField( VALUE_FIELD )->GetId();
|
{
|
||||||
|
// instance parameter
|
||||||
|
if( aSymbol->FindField( NETLIST_EXPORTER_PSPICE::GetSpiceFieldName( SF_MODEL ) ) )
|
||||||
|
m_fieldId = aSymbol->FindField( NETLIST_EXPORTER_PSPICE::GetSpiceFieldName( SF_MODEL ) )->GetId();
|
||||||
|
else
|
||||||
|
m_fieldId = aSymbol->GetField( VALUE_FIELD )->GetId();
|
||||||
|
|
||||||
m_value = SPICE_VALUE( aSymbol->GetFieldById( m_fieldId )->GetText() );
|
m_value = SPICE_VALUE( aSymbol->GetFieldById( m_fieldId )->GetText() );
|
||||||
m_spiceName = aFrame->GetExporter()->GetSpiceDevice( compName ).Lower();
|
m_min = SPICE_VALUE( 0.5 ) * m_value;
|
||||||
|
m_max = SPICE_VALUE( 2.0 ) * m_value;
|
||||||
|
}
|
||||||
|
|
||||||
// Call Set*() methods to update fields and slider
|
// Call Set*() methods to update fields and slider
|
||||||
m_max = SPICE_VALUE( 2.0 ) * m_value;
|
|
||||||
m_min = SPICE_VALUE( 0.5 ) * m_value;
|
|
||||||
|
|
||||||
m_minText->SetValue( m_min.ToOrigString() );
|
m_minText->SetValue( m_min.ToOrigString() );
|
||||||
m_maxText->SetValue( m_max.ToOrigString() );
|
m_maxText->SetValue( m_max.ToOrigString() );
|
||||||
|
|
||||||
|
|
|
@ -49,9 +49,9 @@ public:
|
||||||
return m_name->GetLabel();
|
return m_name->GetLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
const wxString& GetSpiceName() const
|
const std::pair<wxString, bool>& GetSpiceTuningCommand() const
|
||||||
{
|
{
|
||||||
return m_spiceName;
|
return m_spiceTuningCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SPICE_VALUE& GetValue() const
|
const SPICE_VALUE& GetValue() const
|
||||||
|
@ -96,7 +96,7 @@ private:
|
||||||
|
|
||||||
void onSimTimer( wxTimerEvent& event );
|
void onSimTimer( wxTimerEvent& event );
|
||||||
|
|
||||||
wxString m_spiceName;
|
std::pair<wxString, bool> m_spiceTuningCommand;
|
||||||
|
|
||||||
///< Timer that restarts the simulation after the slider value has changed
|
///< Timer that restarts the simulation after the slider value has changed
|
||||||
wxTimer m_simTimer;
|
wxTimer m_simTimer;
|
||||||
|
|
Loading…
Reference in New Issue