copy to isrc
fixme some E_BADPARM unterschiede fixme eine noise ist missing fixme einige der vars sollten in die pwl struct
This commit is contained in:
parent
53ae036b6d
commit
ec1ab0af88
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef FOO_H_INCLUDED
|
||||
#define FOO_H_INCLUDED
|
||||
|
||||
struct pwl_state
|
||||
{
|
||||
double *arr;
|
||||
int len;
|
||||
int position;
|
||||
int bpoint;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -40,6 +40,8 @@ IFparm ISRCpTable[] = { /* parameters */
|
|||
OP ("current", ISRC_CURRENT, IF_REAL, "Current in DC or Transient mode"),
|
||||
#endif
|
||||
/* gtri - end - add parameter for current source value */
|
||||
IP ("r", ISRC_R, IF_REAL, "pwl repeat value"),
|
||||
IP ("td", ISRC_TD, IF_REAL, "pwl delay value"),
|
||||
IP ("distof1", ISRC_D_F1, IF_REALVEC,"f1 input for distortion"),
|
||||
IP ("distof2", ISRC_D_F2, IF_REALVEC,"f2 input for distortion")
|
||||
};
|
||||
|
|
|
|||
|
|
@ -165,22 +165,75 @@ ISRCaccept(CKTcircuit *ckt, GENmodel *inModel)
|
|||
break;
|
||||
|
||||
case PWL: {
|
||||
int i;
|
||||
if(ckt->CKTtime < *(here->ISRCcoeffs)) {
|
||||
double td = here->ISRCrdelay;
|
||||
double tp = here->ISRCrperiod;
|
||||
volatile double bp;
|
||||
|
||||
if (ckt->CKTtime < here->ISRCcoeffs [0] + td) {
|
||||
here->nxt = 0;
|
||||
here->rpt = 0;
|
||||
if(ckt->CKTbreak) {
|
||||
error = CKTsetBreak(ckt,*(here->ISRCcoeffs));
|
||||
error = CKTsetBreak(ckt, here->ISRCcoeffs [0] + td);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(i=0;i<(here->ISRCfunctionOrder/2)-1;i++) {
|
||||
if ( ckt->CKTbreak && AlmostEqualUlps(*(here->ISRCcoeffs+2*i), ckt->CKTtime, 3 ) ) {
|
||||
error = CKTsetBreak(ckt, *(here->ISRCcoeffs+2*i+2));
|
||||
if(error) return(error);
|
||||
goto bkptset;
|
||||
|
||||
/* check td + first >= 0 */
|
||||
|
||||
/*
|
||||
* Postition:
|
||||
* nxt = [0, order[
|
||||
* rpt = [0.. [
|
||||
* with
|
||||
* time == arr[nxt] + rpt*period + td
|
||||
*
|
||||
* (fixme, no thats inclusive see above)
|
||||
*
|
||||
* evtl ==order als Ende Kriterium, !!! must
|
||||
*/
|
||||
|
||||
/* (libc) Remainder Functions, `same sign ...' and magnitude ... */
|
||||
|
||||
#if 0
|
||||
if (repeat && (time > tstart))
|
||||
rest = tstart + fmod(time - tstart, period);
|
||||
else
|
||||
rest = time;
|
||||
#endif
|
||||
|
||||
if (!ckt->CKTbreak || here->nxt >= here->ISRCfunctionOrder)
|
||||
break;
|
||||
|
||||
bp = here->ISRCcoeffs[here->nxt] + td + (here->rpt * tp);
|
||||
|
||||
if (!AlmostEqualUlps(bp, ckt->CKTtime, 3))
|
||||
break;
|
||||
|
||||
for (;;) {
|
||||
volatile double t;
|
||||
|
||||
here->nxt += 2;
|
||||
if (here->nxt >= here->ISRCfunctionOrder) {
|
||||
if (!here->ISRCrGiven)
|
||||
break;
|
||||
here->nxt = here->ISRCrBreakpt;
|
||||
here->rpt++;
|
||||
}
|
||||
|
||||
t = here->ISRCcoeffs[here->nxt] + td + (here->rpt * tp);
|
||||
|
||||
/* CKTtime isn't exactly identical to bp, thus ... */
|
||||
if (t <= ckt->CKTtime || t <= bp)
|
||||
continue;
|
||||
|
||||
bp = t;
|
||||
error = CKTsetBreak(ckt, bp);
|
||||
if (error)
|
||||
return(error);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/**** tansient noise routines:
|
||||
INoi2 2 0 DC 0 TRNOISE(10n 0.5n 0 0n) : generate gaussian distributed noise
|
||||
|
|
@ -200,7 +253,7 @@ ISRCaccept(CKTcircuit *ckt, GENmodel *inModel)
|
|||
/* FIXME, dont' want this here, over to aof_get or somesuch */
|
||||
if (ckt->CKTtime == 0.0) {
|
||||
if (ft_ngdebug)
|
||||
printf("VSRC: free fft tables\n");
|
||||
printf("ISRC: free fft tables\n");
|
||||
fftFree();
|
||||
}
|
||||
|
||||
|
|
@ -289,7 +342,6 @@ ISRCaccept(CKTcircuit *ckt, GENmodel *inModel)
|
|||
|
||||
} // switch
|
||||
} // if ... else
|
||||
bkptset: ;
|
||||
} // for
|
||||
} // for
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,12 @@ ISRCask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value, IFvalue *
|
|||
case ISRC_AC_IMAG:
|
||||
value->rValue = here->ISRCacImag;
|
||||
return (OK);
|
||||
case ISRC_R:
|
||||
value->rValue = here->ISRCr;
|
||||
return (OK);
|
||||
case ISRC_TD:
|
||||
value->rValue = here->ISRCrdelay;
|
||||
return (OK);
|
||||
case ISRC_FCN_ORDER:
|
||||
value->rValue = here->ISRCfunctionOrder;
|
||||
return (OK);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ Author: 1985 Thomas L. Quarles
|
|||
#include "ngspice/cktdefs.h"
|
||||
#include "ngspice/gendefs.h"
|
||||
#include "ngspice/complex.h"
|
||||
#include "uisrc.h"
|
||||
|
||||
/*
|
||||
* structures to describe independent current sources
|
||||
|
|
@ -30,6 +31,7 @@ typedef struct sISRCinstance {
|
|||
|
||||
int ISRCfunctionType; /* code number of function type for source */
|
||||
int ISRCfunctionOrder; /* order of the function for the source */
|
||||
int ISRCrBreakpt; /* pwl repeat breakpoint index */
|
||||
double *ISRCcoeffs; /* pointer to array of coefficients */
|
||||
|
||||
double ISRCdcValue; /* DC and TRANSIENT value of source */
|
||||
|
|
@ -47,6 +49,12 @@ typedef struct sISRCinstance {
|
|||
|
||||
struct trnoise_state *ISRCtrnoise_state; /* transient noise */
|
||||
struct trrandom_state *ISRCtrrandom_state; /* transient random source */
|
||||
struct pwl_state *ISRC_state;
|
||||
|
||||
int nxt, rpt;
|
||||
double ISRCr; /* pwl repeat */
|
||||
double ISRCrdelay; /* pwl delay period */
|
||||
double ISRCrperiod;
|
||||
|
||||
/* gtri - begin - add member to hold current source value */
|
||||
#ifdef XSPICE
|
||||
|
|
@ -64,6 +72,7 @@ typedef struct sISRCinstance {
|
|||
unsigned ISRCdGiven :1 ; /* flag to indicate source is a distortion input */
|
||||
unsigned ISRCdF1given :1 ; /* flag to indicate source is an f1 distortion input */
|
||||
unsigned ISRCdF2given :1 ; /* flag to indicate source is an f2 distortion input */
|
||||
unsigned ISRCrGiven :1 ; /* flag to indicate repeating pwl */
|
||||
} ISRCinstance ;
|
||||
|
||||
|
||||
|
|
@ -123,6 +132,8 @@ typedef struct sISRCmodel {
|
|||
/* gtri - end - add define for current source value */
|
||||
#define ISRC_TRNOISE 25
|
||||
#define ISRC_TRRANDOM 26
|
||||
#define ISRC_R 27
|
||||
#define ISRC_TD 28
|
||||
|
||||
/* model parameters */
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,64 @@ Modified: 2000 Alansfixes
|
|||
/* gtri - end - wbk - modify for supply ramping option */
|
||||
#endif
|
||||
|
||||
|
||||
static double
|
||||
pwl_state_get(struct pwl_state *this, double time)
|
||||
{
|
||||
/* fixme, enter mehrmals im sägezahn ...
|
||||
* 1) optimier dafür
|
||||
* 2) stelle sicher, dass das jeweils höchste timestamp zum zug kommt
|
||||
* (allow step antwort *)
|
||||
* invariant bei repeat:
|
||||
* enter time < timof(last-point)
|
||||
* this->position < indexof(last-point) (fixme really ? wenn es nur 2 points sind zB )
|
||||
*/
|
||||
|
||||
for (;;) {
|
||||
|
||||
double t1 = this->arr[this->position + 0];
|
||||
double t2 = this->arr[this->position + 2];
|
||||
|
||||
double v1, v2;
|
||||
|
||||
if (time >= t2) {
|
||||
if (this->position+4 >= this->len)
|
||||
return this->arr[this->len-1];
|
||||
this->position += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (time < t1) {
|
||||
if (this->position == 0)
|
||||
return this->arr[1];
|
||||
this->position = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* invariant: t1 <= time < t2 ==> t1 != t2 */
|
||||
|
||||
v1 = this->arr[this->position + 1];
|
||||
v2 = this->arr[this->position + 3];
|
||||
|
||||
return v1 + ((v2-v1)/(t2-t1)) * (time - t1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pwl_state_init(struct pwl_state *this, ISRCinstance *here)
|
||||
{
|
||||
|
||||
this->len = here->ISRCfunctionOrder;
|
||||
this->arr = here->ISRCcoeffs;
|
||||
this->position = 0;
|
||||
this->bpoint = 0;
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
int
|
||||
ISRCload(GENmodel *inModel, CKTcircuit *ckt)
|
||||
/* actually load the current value into the
|
||||
|
|
@ -289,30 +347,29 @@ ISRCload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
break;
|
||||
|
||||
case PWL: {
|
||||
int i;
|
||||
if(time < *(here->ISRCcoeffs)) {
|
||||
value = *(here->ISRCcoeffs + 1) ;
|
||||
break;
|
||||
|
||||
struct pwl_state *state;
|
||||
|
||||
double td = here->ISRCrdelay;
|
||||
double tp = here->ISRCrperiod;
|
||||
double r = here->ISRCr;
|
||||
|
||||
if (!here->ISRC_state) {
|
||||
here->ISRC_state = TMALLOC(struct pwl_state, 1);
|
||||
pwl_state_init((struct pwl_state *) here->ISRC_state, here);
|
||||
}
|
||||
for(i=0;i<=(here->ISRCfunctionOrder/2)-1;i++) {
|
||||
if((*(here->ISRCcoeffs+2*i)==time)) {
|
||||
value = *(here->ISRCcoeffs+2*i+1);
|
||||
goto loadDone;
|
||||
}
|
||||
if((*(here->ISRCcoeffs+2*i)<time) &&
|
||||
(*(here->ISRCcoeffs+2*(i+1)) >time)) {
|
||||
value = *(here->ISRCcoeffs+2*i+1) +
|
||||
(((time-*(here->ISRCcoeffs+2*i))/
|
||||
(*(here->ISRCcoeffs+2*(i+1)) -
|
||||
*(here->ISRCcoeffs+2*i))) *
|
||||
(*(here->ISRCcoeffs+2*i+3) -
|
||||
*(here->ISRCcoeffs+2*i+1)));
|
||||
goto loadDone;
|
||||
}
|
||||
|
||||
state = (struct pwl_state *) here -> ISRC_state;
|
||||
|
||||
/* fixme repeat value ignored */
|
||||
if (here->ISRCrGiven && time - td - r >= 0) {
|
||||
double t = fmod(time - td - r, tp) + r;
|
||||
value = pwl_state_get(state, t);
|
||||
} else {
|
||||
value = pwl_state_get(state, time - td);
|
||||
}
|
||||
value = *(here->ISRCcoeffs+ here->ISRCfunctionOrder-1) ;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/**** tansient noise routines:
|
||||
INoi2 2 0 DC 0 TRNOISE(10n 0.5n 0 0n) : generate gaussian distributed noise
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ ISRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
|
|||
copy_coeffs(here, value);
|
||||
|
||||
for (i=0; i<(here->ISRCfunctionOrder/2)-1; i++) {
|
||||
/* fixme identical soll erlaubt werden */
|
||||
if (*(here->ISRCcoeffs+2*(i+1))<=*(here->ISRCcoeffs+2*i)) {
|
||||
fprintf(stderr, "Warning : current source %s",
|
||||
here->ISRCname);
|
||||
|
|
@ -114,6 +115,36 @@ ISRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
|
|||
|
||||
break;
|
||||
|
||||
case ISRC_TD:
|
||||
here->ISRCrdelay = value->rValue;
|
||||
break;
|
||||
|
||||
case ISRC_R: {
|
||||
double end_time;
|
||||
here->ISRCr = value->rValue;
|
||||
here->ISRCrGiven = TRUE;
|
||||
|
||||
for ( i = 0; i < here->ISRCfunctionOrder; i += 2 ) {
|
||||
here->ISRCrBreakpt = i;
|
||||
if ( here->ISRCr == *(here->ISRCcoeffs+i) ) break;
|
||||
}
|
||||
|
||||
end_time = *(here->ISRCcoeffs + here->ISRCfunctionOrder-2);
|
||||
/* actually ok, würde stationaer bedeuten ... und ist so gut wie no repeat */
|
||||
if ( here->ISRCr > end_time ) {
|
||||
fprintf(stderr, "ERROR: repeat start time value %g for pwl voltage source must be smaller than final time point given!\n", here->ISRCr );
|
||||
return ( E_PARMVAL );
|
||||
}
|
||||
|
||||
if ( here->ISRCr != *(here->ISRCcoeffs+here->ISRCrBreakpt) ) {
|
||||
fprintf(stderr, "ERROR: repeat start time value %g for pwl voltage source does not match any time point given!\n", here->ISRCr );
|
||||
return ( E_PARMVAL );
|
||||
}
|
||||
|
||||
here ->ISRCrperiod = end_time - here->ISRCcoeffs[here->ISRCrBreakpt];
|
||||
}
|
||||
break;
|
||||
|
||||
case ISRC_SFFM:
|
||||
if(value->v.numValue < 2)
|
||||
return(E_BADPARM);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ Author: 1985 Thomas L. Quarles
|
|||
#include "ngspice/cktdefs.h"
|
||||
#include "ngspice/gendefs.h"
|
||||
#include "ngspice/complex.h"
|
||||
#include "uisrc.h"
|
||||
|
||||
struct trnoise_state;
|
||||
|
||||
|
|
@ -81,15 +82,6 @@ typedef struct sVSRCinstance {
|
|||
} VSRCinstance ;
|
||||
|
||||
|
||||
struct pwl_state
|
||||
{
|
||||
double *arr;
|
||||
int len;
|
||||
int position;
|
||||
int bpoint;
|
||||
};
|
||||
|
||||
|
||||
/* per model data */
|
||||
|
||||
typedef struct sVSRCmodel {
|
||||
|
|
|
|||
Loading…
Reference in New Issue