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:
Robert Larice 2012-12-17 20:58:41 +01:00 committed by rlar
parent 53ae036b6d
commit ec1ab0af88
8 changed files with 204 additions and 41 deletions

12
src/include/uisrc.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef FOO_H_INCLUDED
#define FOO_H_INCLUDED
struct pwl_state
{
double *arr;
int len;
int position;
int bpoint;
};
#endif

View File

@ -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")
};

View File

@ -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

View File

@ -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);

View File

@ -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 */

View File

@ -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

View File

@ -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);

View File

@ -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 {