You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
300 lines
7.9 KiB
300 lines
7.9 KiB
/*.......1.........2.........3.........4.........5.........6.........7.........8
|
|
================================================================================
|
|
|
|
FILE slew/cfunc.mod
|
|
|
|
Public Domain
|
|
|
|
Georgia Tech Research Corporation
|
|
Atlanta, Georgia 30332
|
|
PROJECT A-8503-405
|
|
|
|
|
|
AUTHORS
|
|
|
|
15 Apr 1991 Harry Li
|
|
|
|
|
|
MODIFICATIONS
|
|
|
|
2 Oct 1991 Jeffrey P. Murray
|
|
|
|
|
|
SUMMARY
|
|
|
|
This file contains the model-specific routines used to
|
|
functionally describe the slew (slew rate) code model.
|
|
|
|
|
|
INTERFACES
|
|
|
|
FILE ROUTINE CALLED
|
|
|
|
CM.c void *cm_analog_alloc()
|
|
void *cm_analog_get_ptr()
|
|
|
|
|
|
REFERENCED FILES
|
|
|
|
Inputs from and outputs to ARGS structure.
|
|
|
|
|
|
NON-STANDARD FEATURES
|
|
|
|
NONE
|
|
|
|
===============================================================================*/
|
|
|
|
/*=== INCLUDE FILES ====================*/
|
|
|
|
#include "slew.h"
|
|
|
|
|
|
|
|
/*=== CONSTANTS ========================*/
|
|
|
|
|
|
|
|
|
|
/*=== MACROS ===========================*/
|
|
|
|
|
|
|
|
|
|
/*=== LOCAL VARIABLES & TYPEDEFS =======*/
|
|
|
|
|
|
|
|
|
|
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/
|
|
|
|
|
|
|
|
|
|
|
|
/*==============================================================================
|
|
|
|
FUNCTION void cm_slew()
|
|
|
|
AUTHORS
|
|
|
|
15 Apr 1991 Harry Li
|
|
|
|
|
|
MODIFICATIONS
|
|
|
|
2 Oct 1991 Jeffrey P. Murray
|
|
|
|
SUMMARY
|
|
|
|
This function implements the slew code model.
|
|
|
|
INTERFACES
|
|
|
|
FILE ROUTINE CALLED
|
|
|
|
CM.c void *cm_analog_alloc()
|
|
void *cm_analog_get_ptr()
|
|
|
|
|
|
RETURNED VALUE
|
|
|
|
Returns inputs and outputs via ARGS structure.
|
|
|
|
GLOBAL VARIABLES
|
|
|
|
NONE
|
|
|
|
NON-STANDARD FEATURES
|
|
|
|
NONE
|
|
|
|
==============================================================================*/
|
|
|
|
/*=== CM_SLEW ROUTINE ===*/
|
|
|
|
/****************************************************************
|
|
* *
|
|
* This model describes a single input, single output slew *
|
|
* rate limited block. The user may specify the positive *
|
|
* and negative slew rates. *
|
|
* *
|
|
* Note that the model makes no provision for output high and *
|
|
* low values. That is assumed to be handled by another model. *
|
|
* *
|
|
****************************************************************/
|
|
|
|
void cm_slew(ARGS)
|
|
|
|
{
|
|
double *ins; /* input value */
|
|
double *in_old; /* previous input value */
|
|
double *outs; /* output value */
|
|
double *out_old; /* previous output value */
|
|
double pout_pin; /* partial derivative--output wrt input */
|
|
double delta; /* change in time from previous iteration */
|
|
double slope_rise; /* positive going slew rate */
|
|
double slope_fall; /* negative going slew rate */
|
|
double out_slew; /* "slewed" output value */
|
|
double slope; /* slope of the input wrt time */
|
|
|
|
Mif_Complex_t ac_gain;
|
|
|
|
/** Retrieve frequently used parameters (used by all analyses)... **/
|
|
|
|
if (INIT == 1) {
|
|
|
|
/* First pass...allocate storage for previous state. */
|
|
|
|
cm_analog_alloc(INT1,sizeof(double));
|
|
cm_analog_alloc(INT4,sizeof(double));
|
|
cm_analog_alloc(INT2,sizeof(double));
|
|
cm_analog_alloc(INT3,sizeof(double));
|
|
|
|
}
|
|
|
|
if (ANALYSIS == MIF_DC) {
|
|
|
|
/* DC analysis, get old values */
|
|
|
|
ins= (double *) cm_analog_get_ptr(INT1,0);
|
|
outs= (double *) cm_analog_get_ptr(INT4,0);
|
|
in_old = (double *) cm_analog_get_ptr(INT1,0);
|
|
out_old = (double *) cm_analog_get_ptr(INT4,0);
|
|
|
|
*ins = *in_old = INPUT(in);
|
|
*outs = *out_old = *ins;
|
|
|
|
/*** so, return a zero d/dt value. ***/
|
|
pout_pin = 1.0;
|
|
|
|
OUTPUT(out) = INPUT(in);
|
|
PARTIAL(out,in) = 1;
|
|
|
|
}else
|
|
|
|
if (ANALYSIS == MIF_TRAN) { /**** DC & Transient Analyses ****/
|
|
|
|
/** Retrieve frequently used parameters... **/
|
|
|
|
slope_rise = PARAM(rise_slope);
|
|
slope_fall = PARAM(fall_slope);
|
|
|
|
/* Allocation not necessary...retrieve previous values */
|
|
|
|
ins = (double *) cm_analog_get_ptr(INT1,0); /* Set out pointer to current
|
|
time storage */
|
|
in_old = (double *) cm_analog_get_ptr(INT1,1); /* Set old-output-state pointer */
|
|
outs = (double *) cm_analog_get_ptr(INT4,0);
|
|
out_old = (double *) cm_analog_get_ptr(INT4,1); /* Set old-output-state pointer
|
|
previous time storage */
|
|
|
|
|
|
if ( TIME == 0.0 ) { /*** Test to see if this is the first ***/
|
|
/*** timepoint calculation...if ***/
|
|
|
|
*ins = *in_old = INPUT(in);
|
|
*outs = *out_old = *ins; /* input = output, d/dt = 1 */
|
|
pout_pin = 1.0;
|
|
|
|
}else{
|
|
|
|
/* determine the slope of the input */
|
|
delta = TIME - T(1);
|
|
*ins = INPUT(in);
|
|
slope = (*ins - *in_old)/delta;
|
|
|
|
if(slope >= 0){
|
|
|
|
out_slew = *out_old + slope_rise*delta;
|
|
|
|
if(*ins < (*out_old - slope_fall*delta)){
|
|
|
|
/* If the input had a negative slope (and the output
|
|
was slewing) and then changed direction to a positive
|
|
slope and the "slewed" response hasn't caught up
|
|
to the input yet (input < slewed output), then
|
|
continue negative slewing until the slewed output
|
|
meets the positive sloping input */
|
|
|
|
*outs = *out_old - slope_fall*delta;
|
|
pout_pin = 0;
|
|
|
|
}else
|
|
|
|
/* Two conditions for slewing, if the slope is greater
|
|
than the positive slew rate, or if the input slope
|
|
is less than the positive slew rate and the slewed output
|
|
is less than the input. This second condition occurs
|
|
if the input levels off and the slewed output hasn't
|
|
caught up to the input yet */
|
|
|
|
if((slope > slope_rise) || ((slope < slope_rise) && (out_slew <= *ins))){
|
|
/* SLEWING ! */
|
|
*outs = out_slew;
|
|
pout_pin = 0;
|
|
|
|
}else{
|
|
/* No slewing, output=input */
|
|
*outs = *ins;
|
|
pout_pin = 1;
|
|
|
|
}
|
|
|
|
}else{ /* this ends the positive slope stuff */
|
|
|
|
out_slew = *out_old - slope_fall*delta;
|
|
|
|
if(*ins > (*out_old + slope_rise*delta)){
|
|
|
|
/* If the input had a positive slope (and the output
|
|
was slewing) and then changed direction to a negative
|
|
slope and the "slewed" response hasn't caught up
|
|
to the input yet (input > slewed output), then
|
|
continue positive slewing until the slewed output
|
|
meets the negative sloping input */
|
|
|
|
*outs = *out_old + slope_rise*delta;
|
|
pout_pin = 0;
|
|
|
|
}else
|
|
|
|
/* Two conditions for slewing, if the negative slope is
|
|
greater than the neg. slew rate, or if the neg. input
|
|
slope is less than the negative slew rate and the
|
|
slewed output is greater than the input. This second
|
|
condition occurs if the input levels off and the
|
|
slewed output hasn't caught up to the input yet */
|
|
|
|
if((-slope > slope_fall) || ((-slope < slope_fall) && (out_slew > *ins))){ /* SLEWING ! */
|
|
*outs = out_slew;
|
|
pout_pin = 0;
|
|
|
|
}else{
|
|
|
|
*outs = *ins;
|
|
pout_pin = 1;
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
}
|
|
/** Output values for DC & Transient **/
|
|
|
|
OUTPUT(out) = *outs;
|
|
PARTIAL(out,in) = pout_pin;
|
|
|
|
|
|
}else{ /**** AC Analysis...output (0.0,s*gain) ****/
|
|
ac_gain.real = 1.0;
|
|
ac_gain.imag= 0;
|
|
AC_GAIN(out,in) = ac_gain;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|