|
|
|
@ -11,6 +11,7 @@ Thomas Sailer |
|
|
|
AUTHORS |
|
|
|
|
|
|
|
20 May 2011 Thomas Sailer |
|
|
|
03 Sep 2012 Holger Vogt |
|
|
|
|
|
|
|
|
|
|
|
MODIFICATIONS |
|
|
|
@ -19,7 +20,8 @@ MODIFICATIONS |
|
|
|
SUMMARY |
|
|
|
|
|
|
|
This file contains the model-specific routines used to |
|
|
|
functionally describe the gain code model. |
|
|
|
functionally describe the file source code model used |
|
|
|
to read an array of analog values per time step from a file. |
|
|
|
|
|
|
|
|
|
|
|
INTERFACES |
|
|
|
@ -55,18 +57,38 @@ NON-STANDARD FEATURES |
|
|
|
/*=== MACROS ===========================*/ |
|
|
|
|
|
|
|
#if defined(__MINGW32__) || defined(_MSC_VER) |
|
|
|
#define DIR_PATHSEP "\\" |
|
|
|
#define DIR_PATHSEP "\\" |
|
|
|
#else |
|
|
|
#define DIR_PATHSEP "/" |
|
|
|
#define DIR_PATHSEP "/" |
|
|
|
#endif |
|
|
|
|
|
|
|
#if defined(_MSC_VER) |
|
|
|
#define strdup _strdup |
|
|
|
#define snprintf _snprintf |
|
|
|
#endif |
|
|
|
|
|
|
|
/*=== LOCAL VARIABLES & TYPEDEFS =======*/ |
|
|
|
|
|
|
|
struct filesource_state { |
|
|
|
FILE *fp; |
|
|
|
long pos; |
|
|
|
unsigned char atend; |
|
|
|
FILE *fp; |
|
|
|
long pos; |
|
|
|
unsigned char atend; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
typedef struct { |
|
|
|
|
|
|
|
double *amplinterval; /* the storage array for the |
|
|
|
amplitude offsets */ |
|
|
|
|
|
|
|
double *timeinterval; /* the storage array for the |
|
|
|
time offset */ |
|
|
|
|
|
|
|
struct filesource_state *state; /* the storage array for the |
|
|
|
filesource status. */ |
|
|
|
|
|
|
|
} Local_Data_t; |
|
|
|
|
|
|
|
|
|
|
|
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ |
|
|
|
|
|
|
|
@ -76,19 +98,19 @@ struct filesource_state { |
|
|
|
|
|
|
|
/*============================================================================== |
|
|
|
|
|
|
|
FUNCTION void cm_gain() |
|
|
|
FUNCTION void cm_filesource() |
|
|
|
|
|
|
|
AUTHORS |
|
|
|
|
|
|
|
2 Oct 1991 Jeffrey P. Murray |
|
|
|
20 May 2011 Thomas Sailer |
|
|
|
|
|
|
|
MODIFICATIONS |
|
|
|
|
|
|
|
NONE |
|
|
|
07 Sept 2012 Holger Vogt |
|
|
|
|
|
|
|
SUMMARY |
|
|
|
|
|
|
|
This function implements the gain code model. |
|
|
|
This function implements the filesource code model. |
|
|
|
|
|
|
|
INTERFACES |
|
|
|
|
|
|
|
@ -117,121 +139,125 @@ NON-STANDARD FEATURES |
|
|
|
|
|
|
|
void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc. */ |
|
|
|
{ |
|
|
|
int size; |
|
|
|
int amplscalesize; |
|
|
|
int amploffssize; |
|
|
|
double *timeinterval; |
|
|
|
double *amplinterval; |
|
|
|
struct filesource_state *state; |
|
|
|
|
|
|
|
if(ANALYSIS == MIF_AC) { |
|
|
|
return; |
|
|
|
} |
|
|
|
size = PORT_SIZE(out); |
|
|
|
if (INIT == 1) { |
|
|
|
/* Allocate storage for internal state */ |
|
|
|
cm_analog_alloc(0, 2 * sizeof(double)); |
|
|
|
cm_analog_alloc(1, size * (int) (2 * sizeof(double))); |
|
|
|
cm_analog_alloc(2, sizeof(struct filesource_state)); |
|
|
|
} |
|
|
|
timeinterval = (double *)cm_analog_get_ptr(0, 0); |
|
|
|
amplinterval = (double *)cm_analog_get_ptr(1, 0); |
|
|
|
state = (struct filesource_state *)cm_analog_get_ptr(2, 0); |
|
|
|
if (INIT == 1) { |
|
|
|
int i; |
|
|
|
timeinterval[0] = timeinterval[1] = PARAM_NULL(timeoffset) ? 0.0 : PARAM(timeoffset); |
|
|
|
for (i = 0; i < size; ++i) |
|
|
|
amplinterval[2 * i] = amplinterval[2 * i + 1] = PARAM_NULL(amploffset) ? 0.0 : PARAM(amploffset[i]); |
|
|
|
state->fp = fopen(PARAM(file), "r"); |
|
|
|
state->pos = 0; |
|
|
|
state->atend = 0; |
|
|
|
if (!state->fp) { |
|
|
|
char *lbuffer, *p; |
|
|
|
int size; |
|
|
|
int amplscalesize; |
|
|
|
int amploffssize; |
|
|
|
|
|
|
|
Local_Data_t *loc; /* Pointer to local static data, not to be included |
|
|
|
in the state vector */ |
|
|
|
|
|
|
|
if(ANALYSIS == MIF_AC) { |
|
|
|
return; |
|
|
|
} |
|
|
|
size = PORT_SIZE(out); |
|
|
|
if (INIT == 1) { |
|
|
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
/*** allocate static storage for *loc ***/ |
|
|
|
STATIC_VAR (locdata) = calloc (1 , sizeof ( Local_Data_t )); |
|
|
|
loc = STATIC_VAR (locdata); |
|
|
|
|
|
|
|
/* Allocate storage for internal state */ |
|
|
|
loc->timeinterval = (double*)calloc(2, sizeof(double)); |
|
|
|
loc->amplinterval = (double*)calloc(2 * size, sizeof(double)); |
|
|
|
loc->state = (struct filesource_state*)malloc(sizeof(struct filesource_state)); |
|
|
|
|
|
|
|
loc->timeinterval[0] = loc->timeinterval[1] = PARAM_NULL(timeoffset) ? 0.0 : PARAM(timeoffset); |
|
|
|
for (i = 0; i < size; ++i) |
|
|
|
loc->amplinterval[2 * i] = loc->amplinterval[2 * i + 1] = PARAM_NULL(amploffset) ? 0.0 : PARAM(amploffset[i]); |
|
|
|
loc->state->fp = fopen(PARAM(file), "r"); |
|
|
|
loc->state->pos = 0; |
|
|
|
loc->state->atend = 0; |
|
|
|
if (!loc->state->fp) { |
|
|
|
char *lbuffer, *p; |
|
|
|
lbuffer = getenv("NGSPICE_INPUT_DIR"); |
|
|
|
if (lbuffer && *lbuffer) { |
|
|
|
p = (char*) malloc(strlen(lbuffer) + strlen(DIR_PATHSEP) + strlen(PARAM(file)) + 1); |
|
|
|
sprintf(p, "%s%s%s", lbuffer, DIR_PATHSEP, PARAM(file)); |
|
|
|
state->fp = fopen(p, "r"); |
|
|
|
loc->state->fp = fopen(p, "r"); |
|
|
|
free(p); |
|
|
|
} |
|
|
|
if (!state->fp) { |
|
|
|
char msg[512]; |
|
|
|
snprintf(msg, sizeof(msg), "cannot open file %s", PARAM(file)); |
|
|
|
cm_message_send(msg); |
|
|
|
state->atend = 1; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
amplscalesize = PARAM_NULL(amplscale) ? 0 : PARAM_SIZE(amplscale); |
|
|
|
amploffssize = PARAM_NULL(amploffset) ? 0 : PARAM_SIZE(amploffset); |
|
|
|
while (TIME >= timeinterval[1] && !state->atend) { |
|
|
|
char line[512]; |
|
|
|
char *cp, *cpdel; |
|
|
|
char *cp2; |
|
|
|
double t; |
|
|
|
int i; |
|
|
|
if (ftell(state->fp) != state->pos) { |
|
|
|
clearerr(state->fp); |
|
|
|
fseek(state->fp, state->pos, SEEK_SET); |
|
|
|
} |
|
|
|
if (!fgets(line, sizeof(line), state->fp)) { |
|
|
|
state->atend = 1; |
|
|
|
break; |
|
|
|
} |
|
|
|
state->pos = ftell(state->fp); |
|
|
|
cpdel = cp = strdup(line); |
|
|
|
while (*cp && isspace(*cp)) |
|
|
|
++cp; |
|
|
|
if (*cp == '#' || *cp == ';') { |
|
|
|
free(cpdel); |
|
|
|
continue; |
|
|
|
} |
|
|
|
t = strtod(cp, &cp2); |
|
|
|
if (cp2 == cp) { |
|
|
|
free(cpdel); |
|
|
|
continue; |
|
|
|
} |
|
|
|
cp = cp2; |
|
|
|
if (!PARAM_NULL(timescale)) |
|
|
|
t *= PARAM(timescale); |
|
|
|
if (!PARAM_NULL(timerelative) && PARAM(timerelative) == MIF_TRUE) |
|
|
|
t += timeinterval[1]; |
|
|
|
else if (!PARAM_NULL(timeoffset)) |
|
|
|
t += PARAM(timeoffset); |
|
|
|
timeinterval[0] = timeinterval[1]; |
|
|
|
timeinterval[1] = t; |
|
|
|
for (i = 0; i < size; ++i) |
|
|
|
amplinterval[2 * i] = amplinterval[2 * i + 1]; |
|
|
|
for (i = 0; i < size; ++i) { |
|
|
|
while (*cp && (isspace(*cp) || *cp == ',')) |
|
|
|
++cp; |
|
|
|
t = strtod(cp, &cp2); |
|
|
|
if (cp2 == cp) |
|
|
|
break; |
|
|
|
cp = cp2; |
|
|
|
if (i < amplscalesize) |
|
|
|
t *= PARAM(amplscale[i]); |
|
|
|
if (i < amploffssize) |
|
|
|
t += PARAM(amploffset[i]); |
|
|
|
amplinterval[2 * i + 1] = t; |
|
|
|
} |
|
|
|
free(cpdel); |
|
|
|
} |
|
|
|
if (TIME < timeinterval[1] && timeinterval[0] < timeinterval[1] && 0.0 <= timeinterval[0]) { |
|
|
|
if (!PARAM_NULL(amplstep) && PARAM(amplstep) == MIF_TRUE) { |
|
|
|
int i; |
|
|
|
for (i = 0; i < size; ++i) |
|
|
|
OUTPUT(out[i]) = amplinterval[2 * i]; |
|
|
|
} else { |
|
|
|
double mul0 = (timeinterval[1] - TIME) / (timeinterval[1] - timeinterval[0]); |
|
|
|
double mul1 = 1.0 - mul0; |
|
|
|
int i; |
|
|
|
for (i = 0; i < size; ++i) |
|
|
|
OUTPUT(out[i]) = mul0 * amplinterval[2 * i] + mul1 * amplinterval[2 * i + 1]; |
|
|
|
} |
|
|
|
} else { |
|
|
|
int i; |
|
|
|
for (i = 0; i < size; ++i) |
|
|
|
OUTPUT(out[i]) = amplinterval[2 * i + 1]; |
|
|
|
} |
|
|
|
if (!loc->state->fp) { |
|
|
|
char msg[512]; |
|
|
|
snprintf(msg, sizeof(msg), "cannot open file %s", PARAM(file)); |
|
|
|
cm_message_send(msg); |
|
|
|
loc->state->atend = 1; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
amplscalesize = PARAM_NULL(amplscale) ? 0 : PARAM_SIZE(amplscale); |
|
|
|
amploffssize = PARAM_NULL(amploffset) ? 0 : PARAM_SIZE(amploffset); |
|
|
|
loc = STATIC_VAR (locdata); |
|
|
|
while (TIME >= loc->timeinterval[1] && !loc->state->atend) { |
|
|
|
char line[512]; |
|
|
|
char *cp, *cpdel; |
|
|
|
char *cp2; |
|
|
|
double t; |
|
|
|
int i; |
|
|
|
if (ftell(loc->state->fp) != loc->state->pos) { |
|
|
|
clearerr(loc->state->fp); |
|
|
|
fseek(loc->state->fp, loc->state->pos, SEEK_SET); |
|
|
|
} |
|
|
|
if (!fgets(line, sizeof(line), loc->state->fp)) { |
|
|
|
loc->state->atend = 1; |
|
|
|
break; |
|
|
|
} |
|
|
|
loc->state->pos = ftell(loc->state->fp); |
|
|
|
cpdel = cp = strdup(line); |
|
|
|
while (*cp && isspace(*cp)) |
|
|
|
++cp; |
|
|
|
if (*cp == '#' || *cp == ';') { |
|
|
|
free(cpdel); |
|
|
|
continue; |
|
|
|
} |
|
|
|
t = strtod(cp, &cp2); |
|
|
|
if (cp2 == cp) { |
|
|
|
free(cpdel); |
|
|
|
continue; |
|
|
|
} |
|
|
|
cp = cp2; |
|
|
|
if (!PARAM_NULL(timescale)) |
|
|
|
t *= PARAM(timescale); |
|
|
|
if (!PARAM_NULL(timerelative) && PARAM(timerelative) == MIF_TRUE) |
|
|
|
t += loc->timeinterval[1]; |
|
|
|
else if (!PARAM_NULL(timeoffset)) |
|
|
|
t += PARAM(timeoffset); |
|
|
|
loc->timeinterval[0] = loc->timeinterval[1]; |
|
|
|
loc->timeinterval[1] = t; |
|
|
|
for (i = 0; i < size; ++i) |
|
|
|
loc->amplinterval[2 * i] = loc->amplinterval[2 * i + 1]; |
|
|
|
for (i = 0; i < size; ++i) { |
|
|
|
while (*cp && (isspace(*cp) || *cp == ',')) |
|
|
|
++cp; |
|
|
|
t = strtod(cp, &cp2); |
|
|
|
if (cp2 == cp) |
|
|
|
break; |
|
|
|
cp = cp2; |
|
|
|
if (i < amplscalesize) |
|
|
|
t *= PARAM(amplscale[i]); |
|
|
|
if (i < amploffssize) |
|
|
|
t += PARAM(amploffset[i]); |
|
|
|
loc->amplinterval[2 * i + 1] = t; |
|
|
|
} |
|
|
|
free(cpdel); |
|
|
|
} |
|
|
|
if (TIME < loc->timeinterval[1] && loc->timeinterval[0] < loc->timeinterval[1] && 0.0 <= loc->timeinterval[0]) { |
|
|
|
if (!PARAM_NULL(amplstep) && PARAM(amplstep) == MIF_TRUE) { |
|
|
|
int i; |
|
|
|
for (i = 0; i < size; ++i) |
|
|
|
OUTPUT(out[i]) = loc->amplinterval[2 * i]; |
|
|
|
} else { |
|
|
|
double mul0 = (loc->timeinterval[1] - TIME) / (loc->timeinterval[1] - loc->timeinterval[0]); |
|
|
|
double mul1 = 1.0 - mul0; |
|
|
|
int i; |
|
|
|
for (i = 0; i < size; ++i) |
|
|
|
OUTPUT(out[i]) = mul0 * loc->amplinterval[2 * i] + mul1 * loc->amplinterval[2 * i + 1]; |
|
|
|
} |
|
|
|
} else { |
|
|
|
int i; |
|
|
|
for (i = 0; i < size; ++i) |
|
|
|
OUTPUT(out[i]) = loc->amplinterval[2 * i + 1]; |
|
|
|
} |
|
|
|
} |