diff --git a/src/xspice/icm/xtradev/pswitch/cfunc.mod b/src/xspice/icm/xtradev/pswitch/cfunc.mod index f00a0d8ba..a2f644ba9 100644 --- a/src/xspice/icm/xtradev/pswitch/cfunc.mod +++ b/src/xspice/icm/xtradev/pswitch/cfunc.mod @@ -139,6 +139,7 @@ void cm_pswitch(ARGS) /* structure holding parms, double cntl_off; /* voltage below the switch has resistance roff */ double r_on; /* on resistance */ double r_off; /* off resistance */ + double r_cntl_in; /* input resistance for control terminal */ double logmean; /* log-mean of resistor values */ double logratio; /* log-ratio of resistor values */ double cntl_mean; /* mean of control values */ @@ -153,7 +154,7 @@ void cm_pswitch(ARGS) /* structure holding parms, 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 */ @@ -165,15 +166,19 @@ void cm_pswitch(ARGS) /* structure holding parms, cntl_off = PARAM(cntl_off); r_on = PARAM(r_on); r_off = PARAM(r_off); + r_cntl_in = PARAM(r_cntl_in); - if( r_on < 1.0e-3 ) r_on = 1.0e-3; /* Set minimum 'ON' resistance */ + r_on = (r_on < 1.0e-3) ? 1.0e-3 : r_on; /* Set minimum 'ON' resistance */ + r_off = (r_off > 1.0e12) ? 1.0e12 : r_off; /* Set maximum 'OFF' 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 */ + char *cntl_error = "\n*****ERROR*****\nPSWITCH: CONTROL voltage delta less than 1.0e-12\n"; + + if( (fabs(cntl_on - cntl_off) < 1.0e-12) ) { + cm_message_send(cntl_error); + return; + } CALLBACK = cm_pswitch_callback; @@ -182,13 +187,24 @@ void cm_pswitch(ARGS) /* structure holding parms, loc = STATIC_VAR (locdata); if ( PARAM(log) == MIF_TRUE ) { /* Logarithmic Variation in 'R' */ + if (cntl_on > cntl_off) + { + cntl_on = 1; + cntl_off = 0; + } + else + { + cntl_on = 0; + cntl_off = 1; + } + 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_mean = 0.5; 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->c3 = 2. * loc->logratio / (loc->cntl_diff * loc->cntl_diff * loc->cntl_diff); //pow(loc->cntl_diff, 3); loc->c2 = 3 * loc->c3; } else { loc->cntl_diff = cntl_on - cntl_off; @@ -204,37 +220,42 @@ void cm_pswitch(ARGS) /* structure holding parms, 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) { + double inmean;// = INPUT(cntl_in) - cntl_mean; + int outOfLimit = 0; + if (cntl_on > cntl_off) { + inmean = ((INPUT(cntl_in) - PARAM(cntl_off)) / (PARAM(cntl_on) - PARAM(cntl_off))) - cntl_mean; + if (INPUT(cntl_in) > cntl_on) { r = r_on; + outOfLimit = 1; } - else if (INPUT(cntl_in) <= cntl_off) { + else if (INPUT(cntl_in) < cntl_off) { r = r_off; + outOfLimit = 1; } else { - r = exp(logmean + 3 * logratio * inmean / (2 * cntl_diff) - loc->c3 * pow(inmean, 3)); + r = exp(logmean + loc->c1 * inmean - loc->c3 * inmean * inmean * inmean); if(r= cntl_off) { + else if (INPUT(cntl_in) > cntl_off) { r = r_off; + outOfLimit = 1; } 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)); + r = exp(logmean + loc->c1 * inmean - loc->c3 * inmean * inmean * inmean); if(rc2 * inmean * inmean - loc->c1); - if(r == r_on) - pi_pcntl = 0; - if(r == r_off) + if(1 == outOfLimit){ pi_pcntl = 0; + } pi_pvout = 1.0 / r; } @@ -249,10 +270,14 @@ void cm_pswitch(ARGS) /* structure holding parms, } 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(); + OUTPUT(out) = INPUT(out) / r; + OUTPUT(cntl_in) = INPUT(cntl_in) / r_cntl_in; +// PARTIAL(out,out) = pi_pvout; +// PARTIAL(out,cntl_in) = pi_pcntl; +// PARTIAL(cntl_in,cntl_in) = 1 / r_cntl_in; +// PARTIAL(cntl_in,out) = 0; /* cntl input resistance is +// independent to out port */ + cm_analog_auto_partial(); /* Note that the minus signs are required because current is positive flowing INTO rather than OUT OF a component node. */ diff --git a/src/xspice/icm/xtradev/pswitch/ifspec.ifs b/src/xspice/icm/xtradev/pswitch/ifspec.ifs index 29a285d6f..33e95d5e8 100644 --- a/src/xspice/icm/xtradev/pswitch/ifspec.ifs +++ b/src/xspice/icm/xtradev/pswitch/ifspec.ifs @@ -30,11 +30,11 @@ 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: - - +Direction: inout inout +Default_Type: gd gd +Allowed_Types: [g,gd] [gd] +Vector: no no +Vector_Bounds: - - Null_Allowed: no no @@ -66,14 +66,14 @@ 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 +Parameter_Name: r_on r_cntl_in +Description: "on resistance" "input resistance for control terminal" +Data_Type: real real +Default_Value: 1.0 1.0e12 +Limits: - - +Vector: no no +Vector_Bounds: - - +Null_Allowed: yes yes STATIC_VAR_TABLE: