Add a new code model pswitch, behaviour directly compatible

to PSPICE (rounded corner at cntl_on)
This commit is contained in:
Holger Vogt 2020-10-03 10:20:28 +02:00
parent fdc143ce16
commit 1f6c4d6338
4 changed files with 350 additions and 0 deletions

View File

@ -9,3 +9,4 @@ potentiometer
zener
memristor
sidiode
pswitch

View File

@ -0,0 +1,262 @@
/*.......1.........2.........3.........4.........5.........6.........7.........8
================================================================================
FILE pswitch/cfunc.mod
3-Clause BSD
Copyright 2020 The ngspice team
AUTHORS
27 September 2020 Holger Vogt
MODIFICATIONS
SUMMARY
This file contains the functional description of the pswitch
code model.
INTERFACES
FILE ROUTINE CALLED
CMmacros.h cm_message_send();
REFERENCED FILES
Inputs from and outputs to ARGS structure.
NON-STANDARD FEATURES
NONE
===============================================================================*/
/*=== INCLUDE FILES ====================*/
#include <math.h>
/*=== CONSTANTS ========================*/
/*=== MACROS ===========================*/
/*=== LOCAL VARIABLES & TYPEDEFS =======*/
typedef struct {
double logmean; /* log-mean of resistor values */
double logratio; /* log-ratio of resistor values */
double cntl_mean; /* mean of control values */
double cntl_diff; /* diff of control values */
double intermediate; /* intermediate value used to calculate
the resistance of the switch when the
controlling voltage is between cntl_on
and cntl_of */
double c1; /* some constants */
double c2;
double c3;
} Local_Data_t;
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
static void
cm_pswitch_callback(ARGS, Mif_Callback_Reason_t reason)
{
switch (reason) {
case MIF_CB_DESTROY: {
Local_Data_t *loc = STATIC_VAR (locdata);
free(loc);
break;
}
}
}
/*==============================================================================
FUNCTION cm_pswitch()
AUTHORS
27 September 2020 Holger Vogt
MODIFICATIONS
SUMMARY
This function implements the pswitch code model.
INTERFACES
FILE ROUTINE CALLED
CMmacros.h cm_message_send();
RETURNED VALUE
Returns inputs and outputs via ARGS structure.
GLOBAL VARIABLES
NONE
NON-STANDARD FEATURES
NONE
==============================================================================*/
/*=== CM_PSWITCH ROUTINE ===*/
void cm_pswitch(ARGS) /* structure holding parms,
inputs, outputs, etc. */
{
double cntl_on; /* voltage above which switch come on */
double cntl_off; /* voltage below the switch has resistance roff */
double r_on; /* on resistance */
double r_off; /* off resistance */
double logmean; /* log-mean of resistor values */
double logratio; /* log-ratio of resistor values */
double cntl_mean; /* mean of control values */
double cntl_diff; /* diff of control values */
double intermediate; /* intermediate value used to calculate
the resistance of the switch when the
controlling voltage is between cntl_on
and cntl_of */
double r; /* value of the resistance of the switch */
double pi_pvout; /* partial of the output wrt input */
double pi_pcntl; /* partial of the output wrt control input */
Mif_Complex_t ac_gain;
char *cntl_error = "\n*****ERROR*****\nPSWITCH: CONTROL voltage delta less than 1.0e-12\n";
Local_Data_t *loc; /* Pointer to local static data, not to be included
in the state vector */
/* Retrieve frequently used parameters... */
cntl_on = PARAM(cntl_on);
cntl_off = PARAM(cntl_off);
r_on = PARAM(r_on);
r_off = PARAM(r_off);
if( r_on < 1.0e-3 ) r_on = 1.0e-3; /* Set minimum 'ON' resistance */
if( (fabs(cntl_on - cntl_off) < 1.0e-12) ) {
cm_message_send(cntl_error);
return;
}
if(INIT == 1) { /* first time through, allocate memory, set static parameters */
/*** allocate static storage for *loc ***/
STATIC_VAR (locdata) = calloc (1 , sizeof ( Local_Data_t ));
loc = STATIC_VAR (locdata);
if ( PARAM(log) == MIF_TRUE ) { /* Logarithmic Variation in 'R' */
loc->logmean = log(sqrt(r_on * r_off));
loc->logratio = log(r_on / r_off);
loc->cntl_mean = (cntl_on + cntl_off) / 2.;
loc->cntl_diff = cntl_on - cntl_off;
loc->intermediate = loc->logratio / loc->cntl_diff;
loc->c1 = 1.5 * loc->logratio / loc->cntl_diff;
loc->c3 = 2. * loc->logratio / pow(loc->cntl_diff, 3);
loc->c2 = 3 * loc->c3;
} else {
loc->cntl_diff = cntl_on - cntl_off;
loc->intermediate = (r_on - r_off) / (cntl_on - cntl_off);
}
}
loc = STATIC_VAR (locdata);
if ( PARAM(log) == MIF_TRUE ) { /* Logarithmic Variation in 'R' */
logmean = loc->logmean;
logratio = loc->logratio;
cntl_mean = loc->cntl_mean;
cntl_diff = loc->cntl_diff;
intermediate = loc->intermediate;
double inmean = INPUT(cntl_in) - cntl_mean;
if (cntl_on >= cntl_off) {
if (INPUT(cntl_in) >= cntl_on) {
r = r_on;
}
else if (INPUT(cntl_in) <= cntl_off) {
r = r_off;
}
else {
r = exp(logmean + 3 * logratio * inmean / (2 * cntl_diff) - loc->c3 * pow(inmean, 3));
if(r<r_on) r=r_on;/* minimum resistance limiter */
}
} else {
if (INPUT(cntl_in) <= cntl_on) {
r = r_on;
}
else if (INPUT(cntl_in) >= cntl_off) {
r = r_off;
}
else {
r = exp(logmean + 3 * logratio * inmean / (2 * cntl_diff) - loc->c3 * pow(inmean, 3));
// r = exp(logmean + 3 * logratio * (INPUT(cntl_in) - cntl_mean) / (2 * cntl_diff) - 2 * logratio * pow((INPUT(cntl_in) - cntl_mean), 3) / pow(cntl_diff, 3));
if(r<r_on) r=r_on;/* minimum resistance limiter */
}
}
pi_pcntl = INPUT(out) / r * (loc->c2 * inmean * inmean - loc->c1 * INPUT(cntl_in));
pi_pvout = 1.0 / r;
}
else { /* Linear Variation in 'R' */
intermediate = loc->intermediate;
cntl_diff = loc->cntl_diff;
r = INPUT(cntl_in) * intermediate + ((r_off*cntl_on -
r_on*cntl_off) / cntl_diff);
if(r<=1.0e-9) r=1.0e-9;/* minimum resistance limiter */
pi_pvout = 1.0 / r;
pi_pcntl = -intermediate * INPUT(out) / (r*r);
}
if(ANALYSIS != MIF_AC) { /* Output DC & Transient Values */
OUTPUT(out) = INPUT(out) / r;
// PARTIAL(out,out) = pi_pvout;
// PARTIAL(out,cntl_in) = pi_pcntl;
cm_analog_auto_partial();
/* Note that the minus signs are required because current is positive
flowing INTO rather than OUT OF a component node. */
}
else { /* Output AC Gain Values */
ac_gain.real = -pi_pvout; /* See comment on minus signs above... */
ac_gain.imag= 0.0;
AC_GAIN(out,out) = ac_gain;
ac_gain.real = -pi_pcntl;
ac_gain.imag= 0.0;
AC_GAIN(out,cntl_in) = ac_gain;
}
}

View File

@ -0,0 +1,83 @@
/*.......1.........2.........3.........4.........5.........6.........7.........8
================================================================================
3-Clause BSD
Copyright 2020 The ngspice team
AUTHORS
27 September 2020 Holger Vogt
SUMMARY
This file contains the interface specification file for the
analog pswitch code model.
===============================================================================*/
NAME_TABLE:
C_Function_Name: cm_pswitch
Spice_Model_Name: pswitch
Description: "analog PSPICE compatible switch"
PORT_TABLE:
Port_Name: cntl_in out
Description: "input" "resistive output"
Direction: in inout
Default_Type: v gd
Allowed_Types: [v,vd,i,id,vnam] [gd]
Vector: no no
Vector_Bounds: - -
Null_Allowed: no no
PARAMETER_TABLE:
Parameter_Name: cntl_off cntl_on
Description: "control 'off' val" "control 'on' val"
Data_Type: real real
Default_Value: 0.0 1.0
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: log r_off
Description: "Log-linear switch" "off resistance"
Data_Type: boolean real
Default_Value: TRUE 1.0e12
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: r_on
Description: "on resistance"
Data_Type: real
Default_Value: 1.0
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: yes
STATIC_VAR_TABLE:
Static_Var_Name: locdata
Description: "local static data"
Data_Type: pointer

View File

@ -220,6 +220,8 @@
<AdditionalIncludeDirectories>..\..\src\xspice\%(RelativeDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<ClCompile Include="icm\xtradev\core\core-ifspec.c" />
<ClCompile Include="icm\xtradev\pswitch\pswitch-cfunc.c" />
<ClCompile Include="icm\xtradev\pswitch\pswitch-ifspec.c" />
<ClCompile Include="icm\xtradev\sidiode\sidiode-cfunc.c" />
<ClCompile Include="icm\xtradev\sidiode\sidiode-ifspec.c" />
<ClCompile Include="icm\xtradev\inductor\inductor-cfunc.c">
@ -257,6 +259,8 @@
<None Include="..\..\src\xspice\icm\xtradev\cmeter\ifspec.ifs" />
<None Include="..\..\src\xspice\icm\xtradev\core\cfunc.mod" />
<None Include="..\..\src\xspice\icm\xtradev\core\ifspec.ifs" />
<None Include="..\..\src\xspice\icm\xtradev\pswitch\cfunc.mod" />
<None Include="..\..\src\xspice\icm\xtradev\pswitch\ifspec.ifs" />
<None Include="..\..\src\xspice\icm\xtradev\sidiode\cfunc.mod" />
<None Include="..\..\src\xspice\icm\xtradev\sidiode\ifspec.ifs" />
<None Include="..\..\src\xspice\icm\xtradev\inductor\cfunc.mod" />