Browse Source
Add a new code model pswitch, behaviour directly compatible
Add a new code model pswitch, behaviour directly compatible
to PSPICE (rounded corner at cntl_on)pre-master-46
4 changed files with 350 additions and 0 deletions
-
1src/xspice/icm/xtradev/modpath.lst
-
262src/xspice/icm/xtradev/pswitch/cfunc.mod
-
83src/xspice/icm/xtradev/pswitch/ifspec.ifs
-
4visualc/xspice/xtradev.vcxproj
@ -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; |
|||
} |
|||
} |
|||
|
|||
@ -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 |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue