⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 .#cfunc.c

📁 支持数字元件仿真的SPICE插件
💻 C
字号:
#include "CM.h"#include "oneshot.h"  /* ...generated from IF spec. table..? Contains */                     /* any model-specific defns.      10/10/90 JPM  *//************************************************************************  This model describes a totally analog oneshot.*  After a rising edge is detected, the model will*  output a pulse width specified by the controling *  voltage.*                          HWL 20Mar91****                              ___________________________________*                             /<---pulse width --->              :\*                            / :                  :              : \ *         <---rise_delay--> /  :                  :<-fall_delay->:  \*      ___|________________/   :                  :              :   \____________*         ^                <-->:                  :              :<-->*         Trigger         Risetime                               Falltime**************************************************************************/void cm_oneshot(Mif_Private_t *private)  /* structure holding parms,                                    inputs, outputs, etc.     */{    int i;             /* generic loop counter index                    */	int cntl_size;     /* size of the control array                     */	int pw_size;       /* size of the pulse-width array                 */	int *state;        /* pointer used to store state1 variable         */	int state1;        /* if state1 = 1, then oneshot has                          been triggered.  if state1 = 0, no change     */	int *set;          /* pointer used to store the state of set1       */	int set1;          /* flag used to set/reset the oneshot            */    int trig_pos_edge; /* flag used to define positive or negative                          edge triggering.  1=positive, 0=negative      */    double *x;         /* pointer used to store the control array       */	double *y;         /* pointer used to store the pulse-width array   */	double cntl_input; /* the actual value of the control input         */	double out;        /* value of the output                           */	double output_low; /* output low value                              */	double output_hi;  /* output high value                             */    double pw;         /* actual value of the pulse-width               *//*	double del_out;     value of the delay time between triggering                           and a change in the output                    */	double del_rise;    /* value of the delay time between triggering                           and a change in the output                    */	double del_fall;    /* value of the delay time between the end of the						   pw and a change in the output                */	double *t1;        /* pointer used to store time1                   */	double *t2;        /* pointer used to store time2                   */	double *t3;        /* pointer used to store time3                   */	double *t4;        /* pointer used to store time4                   */	double time1;      /* time at which the output first begins to                           change (trigger + delay)                      */	double time2;      /* time2 = time1 + risetime                      */	double time3;      /* time3 = time2 + pw                            */	double time4;      /* time4 = time3 + falltime                      */	double t_rise;     /* risetime                                      */	double t_fall;     /* falltime                                      */	double *output_old;/* pointer which stores the previous output      */    double *clock;     /* pointer which stores the clock                */	double *old_clock; /* pointer which stores the previous clock       */	double trig_clk;   /* value at which the clock triggers the oneshot */    Mif_Complex_t ac_gain;                                               /**** Retrieve frequently used parameters... ****/    cntl_size = private->param[0]->size;               pw_size = private->param[1]->size;               trig_clk = private->param[2]->element[0].rvalue;    trig_pos_edge = private->param[3]->element[0].bvalue;    output_low = private->param[4]->element[0].rvalue;    output_hi = private->param[5]->element[0].rvalue;    /*del_out = PARAM(delay);*/	del_rise = private->param[7]->element[0].rvalue;	del_fall = private->param[8]->element[0].rvalue;    t_rise = private->param[6]->element[0].rvalue;    t_fall = private->param[9]->element[0].rvalue;    /* set minimum rise and fall_times */	if(t_rise < 1e-12){		t_rise = 1e-12;    }	if(t_fall < 1e-12){		t_fall = 1e-12;    }   /* the control array must be the same size as the pulse-width array */ 	if(cntl_size != pw_size){		cm_send_error_msg(oneshot_array_error);		return; 	}  if(private->circuit.init == 1){  /* first time through, allocate memory */		t1 = cm_alloc(T1,sizeof(double));		t2 = cm_alloc(T2,sizeof(double));		t3 = cm_alloc(T3,sizeof(double));		t4 = cm_alloc(T4,sizeof(double));        set = cm_alloc(SET,sizeof(int));        state = cm_alloc(STATE,sizeof(int));        clock = cm_alloc(CLOCK,sizeof(double));        output_old = cm_alloc(OUTPUT_OLD,sizeof(double));  }   if(private->circuit.anal_type == MIF_DC){    /* for DC, initialize values and set the output = output_low */		t1 = cm_getstore(T1,0);		t2 = cm_getstore(T2,0);		t3 = cm_getstore(T3,0);		t4 = cm_getstore(T4,0);		set = cm_getstore(SET,0);		state = cm_getstore(STATE,0);		output_old = cm_getstore(OUTPUT_OLD,0);		/* initialize time and state values */		*t1 = -1;		*t2 = -1;		*t3 = -1;		*t4 = -1;        *set = 0;        *state = 0;        *output_old = output_low;		private->conn[2]->port[0]->output.rvalue = output_low;		private->conn[2]->port[0]->partial[0].port[0] = 0; 		private->conn[2]->port[0]->partial[1].port[0] = 0;   }else  if(private->circuit.anal_type == MIF_TRAN){/* retrieve previous values, set them equal to the variables    Note that these pointer values are immediately dumped into   other variables because the previous values can't change-    can't rewrite the old values */	t1 = cm_getstore(T1,1);	t2 = cm_getstore(T2,1);	t3 = cm_getstore(T3,1);	t4 = cm_getstore(T4,1);	set = cm_getstore(SET,1);	state = cm_getstore(STATE,1);    clock = cm_getstore(CLOCK,0);    old_clock = cm_getstore(CLOCK,1);    output_old = cm_getstore(OUTPUT_OLD,1);	time1 = *t1;    time2 = *t2;    time3 = *t3;    time4 = *t4;    set1 = *set;    state1 = *state;       /* Allocate storage for breakpoint domain & freq. range values */    x = (double *) calloc(cntl_size, sizeof(double));    if (x == '\0') {        cm_send_error_msg(oneshot_allocation_error);         return;    }    y = (double *) calloc(pw_size, sizeof(double));    if (y == '\0') {        cm_send_error_msg(oneshot_allocation_error);          return;    }    /* Retrieve control and pulse-width values. */           for (i=0; i<cntl_size; i++) {        *(x+i) = private->param[0]->element[i].rvalue;        *(y+i) = private->param[1]->element[i].rvalue;    }                               /* Retrieve cntl_input and clock value. */           cntl_input = private->conn[0]->port[0]->input.rvalue;    *clock = private->conn[1]->port[0]->input.rvalue;    /* Determine segment boundaries within which cntl_input resides */    if (cntl_input <= *x) { /* cntl_input below lowest cntl_voltage */		pw = *y;	    }    else         /*** cntl_input above highest cntl_voltage ***/	        if (cntl_input >= *(x+cntl_size-1)){ 			pw = *(y+cntl_size-1);        } else { /*** cntl_input within bounds of end midpoints...                   must determine position progressively & then                 calculate required output.                    ***/            for (i=0; i<cntl_size-1; i++) {                if ((cntl_input < *(x+i+1)) && (cntl_input >= *(x+i))){             							/* Interpolate to get the correct pulse width value */					pw = ((cntl_input - *(x+i))/(*(x+i+1) - *(x+i)))* 							(*(y+i+1)-*(y+i)) + *(y+i);                 }                 }        }if(trig_pos_edge){  /* for a positive edge trigger */    if(!set1){    /* if set1=0, then look for                      1.  a rising edge trigger                     2.  the clock to be higher than the trigger value */      if((*clock > *old_clock) && (*clock > trig_clk)){        state1 = 1;        set1 = 1;      }	}else            /* look for a neg edge before resetting the trigger */      if((*clock < *old_clock) && (*clock < trig_clk)){        set1 = 0;		      }}else{         /* This stuff belongs to the case where a negative edge			is needed */    if(!set1){      if((*clock < *old_clock) && (*clock < trig_clk)){        state1 = 1;        set1 = 1;      }	}else            /* look for a pos edge before resetting the trigger */    if((*clock > *old_clock) && (*clock > trig_clk)){        set1 = 0;    }}		    if((state1) && (*output_old - output_low < 1e-20)){/* if state1 is 1, and the output is low, then set the time points   and the temporary breakpoints */   	time1 = private->circuit.time + del_rise;    	time2 = time1 + t_rise;    time3 = time2 + pw + del_fall;    time4 = time3 + t_fall;   if((private->circuit.time < time1) || (private->circuit.t[1] == 0)){    	cm_set_temp_bkpt(time1);   }	   cm_set_temp_bkpt(time2);	   cm_set_temp_bkpt(time3);	   cm_set_temp_bkpt(time4);      /* reset the state value */	   state1 = 0;	   private->conn[2]->port[0]->output.rvalue = output_low;   }else{ 	/* state1 = 1, and the output is high,  then just set time3 and time4        and their temporary breakpoints */		 if((state1) && (*output_old - output_hi < 1e-20) && (private->param[10]->element[0].bvalue == MIF_TRUE)){        time3 = private->circuit.time + pw + del_rise + del_fall + t_rise;        time4 = time3 + t_fall;        cm_set_temp_bkpt(time3);        cm_set_temp_bkpt(time4);        private->conn[2]->port[0]->output.rvalue = output_hi;        state1 = 0;      }	  if(private->param[10]->element[0].bvalue==MIF_FALSE){         state1 = 0;      }   }   /*  set the value for the output depending on the current time, and       the values of time1, time2, time3, and time4 */	if((time1 <= private->circuit.time) && (private->circuit.time <= time2)){        private->conn[2]->port[0]->output.rvalue = output_low + ((private->circuit.time - time1)/(time2 - time1))*			(output_hi - output_low); 	}else		if((time2 <= private->circuit.time) && (private->circuit.time <= time3)){        private->conn[2]->port[0]->output.rvalue = output_hi;	}else	if((time3 <= private->circuit.time) && (private->circuit.time <= time4)){			   private->conn[2]->port[0]->output.rvalue = output_hi + ((private->circuit.time - time3)/(time4 - time3))*		(output_low - output_hi);	}else{  	  private->conn[2]->port[0]->output.rvalue = output_low;     }    /* set the variables which need to be stored for the next iteration */	t1 = cm_getstore(T1,0);	t2 = cm_getstore(T2,0);	t3 = cm_getstore(T3,0);	t4 = cm_getstore(T4,0);	set = cm_getstore(SET,0);	state = cm_getstore(STATE,0);	output_old = cm_getstore(OUTPUT_OLD,0);	*t1 = time1;    *t2 = time2;    *t3 = time3;    *t4 = time4;    *set = set1;    *state = state1;    *output_old = private->conn[2]->port[0]->output.rvalue;   	private->conn[2]->port[0]->partial[0].port[0] = 0;    private->conn[2]->port[0]->partial[1].port[0] = 0 ;    } else {                      /* Output AC Gain */  /* This model has no AC capability */        ac_gain.real = 0.0;         ac_gain.imag= 0.0;        private->conn[2]->port[0]->ac_gain[0].port[0] = ac_gain;    }} 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -