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.
 
 
 
 
 
 

238 lines
7.7 KiB

/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
Modified: 2000 AlansFixes
**********/
/*
*/
#include "ngspice.h"
#include "vsrcdefs.h"
#include "ifsim.h"
#include "sperror.h"
#include "suffix.h"
#include "1-f-code.h"
static void copy_coeffs(VSRCinstance *here, IFvalue *value)
{
if(here->VSRCcoeffs)
tfree(here->VSRCcoeffs);
here->VSRCcoeffs = TMALLOC(double, value->v.numValue);
here->VSRCfunctionOrder = value->v.numValue;
here->VSRCcoeffsGiven = TRUE;
memcpy(here->VSRCcoeffs, value->v.vec.rVec, value->v.numValue * sizeof(double));
}
/* ARGSUSED */
int
VSRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
{
int i;
VSRCinstance *here = (VSRCinstance *)inst;
NG_IGNORE(select);
switch(param) {
case VSRC_DC:
here->VSRCdcValue = value->rValue;
here->VSRCdcGiven = TRUE;
break;
case VSRC_AC_MAG:
here->VSRCacMag = value->rValue;
here->VSRCacMGiven = TRUE;
here->VSRCacGiven = TRUE;
break;
case VSRC_AC_PHASE:
here->VSRCacPhase = value->rValue;
here->VSRCacPGiven = TRUE;
here->VSRCacGiven = TRUE;
break;
case VSRC_AC:
switch(value->v.numValue) {
case 2:
here->VSRCacPhase = *(value->v.vec.rVec+1);
here->VSRCacPGiven = TRUE;
case 1:
here->VSRCacMag = *(value->v.vec.rVec);
here->VSRCacMGiven = TRUE;
case 0:
here->VSRCacGiven = TRUE;
break;
default:
return(E_BADPARM);
}
break;
case VSRC_PULSE:
here->VSRCfunctionType = PULSE;
here->VSRCfuncTGiven = TRUE;
copy_coeffs(here, value);
break;
case VSRC_SINE:
here->VSRCfunctionType = SINE;
here->VSRCfuncTGiven = TRUE;
copy_coeffs(here, value);
break;
case VSRC_EXP:
here->VSRCfunctionType = EXP;
here->VSRCfuncTGiven = TRUE;
copy_coeffs(here, value);
break;
case VSRC_PWL:
here->VSRCfunctionType = PWL;
here->VSRCfuncTGiven = TRUE;
copy_coeffs(here, value);
for(i=0;i<(here->VSRCfunctionOrder/2)-1;i++) {
if(*(here->VSRCcoeffs+2*(i+1))<=*(here->VSRCcoeffs+2*i)) {
fprintf(stderr, "Warning : voltage source %s",
here->VSRCname);
fprintf(stderr, " has non-increasing PWL time points.\n");
}
}
break;
case VSRC_TD:
here->VSRCrdelay = value->rValue;
break;
case VSRC_R: {
double end_time;
here->VSRCr = value->rValue;
here->VSRCrGiven = TRUE;
for ( i = 0; i < here->VSRCfunctionOrder; i += 2 ) {
here->VSRCrBreakpt = i;
if ( here->VSRCr == *(here->VSRCcoeffs+i) ) break;
}
end_time = *(here->VSRCcoeffs + here->VSRCfunctionOrder-2);
if ( here->VSRCr > end_time ) {
fprintf(stderr, "ERROR: repeat start time value %g for pwl voltage source must be smaller than final time point given!\n", here->VSRCr );
return ( E_PARMVAL );
}
if ( here->VSRCr != *(here->VSRCcoeffs+here->VSRCrBreakpt) ) {
fprintf(stderr, "ERROR: repeat start time value %g for pwl voltage source does not match any time point given!\n", here->VSRCr );
return ( E_PARMVAL );
}
break; }
case VSRC_SFFM:
here->VSRCfunctionType = SFFM;
here->VSRCfuncTGiven = TRUE;
copy_coeffs(here, value);
break;
case VSRC_AM:
if(value->v.numValue <2) return(E_BADPARM);
here->VSRCfunctionType = AM;
here->VSRCfuncTGiven = TRUE;
copy_coeffs(here, value);
break;
case VSRC_D_F1:
here->VSRCdF1given = TRUE;
here->VSRCdGiven = TRUE;
switch(value->v.numValue) {
case 2:
here->VSRCdF1phase = *(value->v.vec.rVec+1);
here->VSRCdF1mag = *(value->v.vec.rVec);
break;
case 1:
here->VSRCdF1mag = *(value->v.vec.rVec);
here->VSRCdF1phase = 0.0;
break;
case 0:
here->VSRCdF1mag = 1.0;
here->VSRCdF1phase = 0.0;
break;
default:
return(E_BADPARM);
}
break;
case VSRC_D_F2:
here->VSRCdF2given = TRUE;
here->VSRCdGiven = TRUE;
switch(value->v.numValue) {
case 2:
here->VSRCdF2phase = *(value->v.vec.rVec+1);
here->VSRCdF2mag = *(value->v.vec.rVec);
break;
case 1:
here->VSRCdF2mag = *(value->v.vec.rVec);
here->VSRCdF2phase = 0.0;
break;
case 0:
here->VSRCdF2mag = 1.0;
here->VSRCdF2phase = 0.0;
break;
default:
return(E_BADPARM);
}
break;
case VSRC_TRNOISE: {
double NA, TS;
double NALPHA = 0.0;
double NAMP = 0.0;
double RTSAM = 0.0;
double RTSCAPT = 0.0;
double RTSEMT = 0.0;
here->VSRCfunctionType = TRNOISE;
here->VSRCfuncTGiven = TRUE;
copy_coeffs(here, value);
NA = here->VSRCcoeffs[0]; // input is rms value
TS = here->VSRCcoeffs[1]; // time step
if (here->VSRCfunctionOrder > 2)
NALPHA = here->VSRCcoeffs[2]; // 1/f exponent
if (here->VSRCfunctionOrder > 3 && NALPHA != 0.0)
NAMP = here->VSRCcoeffs[3]; // 1/f amplitude
if (here->VSRCfunctionOrder > 4)
RTSAM = here->VSRCcoeffs[4]; // RTS amplitude
if (here->VSRCfunctionOrder > 5 && RTSAM != 0.0)
RTSCAPT = here->VSRCcoeffs[5]; // RTS trap capture time
if (here->VSRCfunctionOrder > 6 && RTSAM != 0.0)
RTSEMT = here->VSRCcoeffs[6]; // RTS trap emission time
here->VSRCtrnoise_state =
trnoise_state_init(NA, TS, NALPHA, NAMP, RTSAM, RTSCAPT, RTSEMT);
}
break;
case VSRC_TRRANDOM: {
double TD = 0.0, TS;
int rndtype = 1;
double PARAM1 = 1.0;
double PARAM2 = 0.0;
here->VSRCfunctionType = TRRANDOM;
here->VSRCfuncTGiven = TRUE;
copy_coeffs(here, value);
rndtype = (int)here->VSRCcoeffs[0]; // type of random function
TS = here->VSRCcoeffs[1]; // time step
if (here->VSRCfunctionOrder > 2)
TD = here->VSRCcoeffs[2]; // delay
if (here->VSRCfunctionOrder > 3)
PARAM1 = here->VSRCcoeffs[3]; // first parameter
if (here->VSRCfunctionOrder > 4)
PARAM2 = here->VSRCcoeffs[4]; // second parameter
here->VSRCtrrandom_state =
trrandom_state_init(rndtype, TS, TD, PARAM1, PARAM2);
}
break;
default:
return(E_BADPARM);
}
return(OK);
}