rpn expressions in graphs

This commit is contained in:
Stefan Frederik 2022-02-12 04:55:02 +01:00
parent a24fbc3645
commit defd2a92a7
8 changed files with 298 additions and 154 deletions

View File

@ -629,23 +629,46 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
if(!gr->digital) {
int dset;
int i, j;
double v;
const char *bus_msb = NULL;
int sweep_idx = 0;
double v, start, end;
double min=0.0, max=0.0;
int first = 1;
char *saven, *nptr, *ntok, *node = NULL;;
char *saves, *sptr, *stok, *sweep = NULL, *saven, *nptr, *ntok, *node = NULL;
my_strdup2(1426, &node, get_tok_value(r->prop_ptr,"node",0));
my_strdup2(542, &sweep, get_tok_value(r->prop_ptr,"sweep",0));
nptr = node;
while( (ntok = my_strtok_r(nptr, "\n\t ", "", &saven)) ) {
nptr = NULL;
j = get_raw_index(ntok);
sptr = sweep;
start = (gr->gx1 <= gr->gx2) ? gr->gx1 : gr->gx2;
end = (gr->gx1 <= gr->gx2) ? gr->gx2 : gr->gx1;
while( (ntok = my_strtok_r(nptr, "\n\t ", "\"", &saven)) ) {
stok = my_strtok_r(sptr, " ", "", &saves);
nptr = sptr = NULL;
if(stok && stok[0]) {
sweep_idx = get_raw_index(stok);
if( sweep_idx == -1) sweep_idx = 0;
}
bus_msb = strstr(ntok, ",");
j = -1;
if(!bus_msb && strstr(ntok, " ")) {
j = xctx->graph_nvars;
plot_raw_custom_data(sweep_idx, ntok);
} else {
j = get_raw_index(ntok);
}
if(j >= 0) {
int ofs = 0;
for(dset = 0 ; dset < xctx->graph_datasets; dset++) {
for(i = ofs; i < ofs + xctx->graph_npoints[dset]; i++) {
if(dataset >= 0 && dataset != dset) continue;
if( xctx->graph_values[sweep_idx][i] < start ||
xctx->graph_values[sweep_idx][i] > end) continue;
v = xctx->graph_values[j][i];
if(first || v < min) {min = v; first = 0;}
if(first || v > max) {max = v; first = 0;}
if(first || v < min) min = v;
if(first || v > max) max = v;
first = 0;
}
ofs += xctx->graph_npoints[dset];
}
@ -655,6 +678,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
min = floor_to_n_digits(min, 2);
max = ceil_to_n_digits(max, 2);
my_free(1427, &node);
my_free(573, &sweep);
my_strdup(1422, &r->prop_ptr, subst_token(r->prop_ptr, "y1", dtoa(min)));
my_strdup(1423, &r->prop_ptr, subst_token(r->prop_ptr, "y2", dtoa(max)));
need_redraw = 1;

View File

@ -1654,7 +1654,7 @@ static SPICE_DATA **get_bus_idx_array(const char *ntok, int *n_bits)
int p;
char *ntok_savep, *ntok_ptr, *ntok_copy = NULL;
const char *bit_name;
*n_bits = count_items(ntok, ",") - 1;
*n_bits = count_items(ntok, ",", "") - 1;
idx_arr = my_malloc(1454, (*n_bits) * sizeof(SPICE_DATA *));
p = 0;
my_strdup2(1402, &ntok_copy, ntok);
@ -1750,8 +1750,8 @@ static void draw_graph_bus_points(const char *ntok, int n_bits, SPICE_DATA **idx
}
}
/* wcnt is the nth wave in graph, v is the index in spice raw file */
static void draw_graph_points(int v, int first, int last,
/* wcnt is the nth wave in graph, idx is the index in spice raw file */
static void draw_graph_points(int idx, int first, int last,
XPoint *point, int wave_col, int wcnt, int n_nodes, Graph_ctx *gr)
{
int p;
@ -1761,9 +1761,9 @@ static void draw_graph_points(int v, int first, int last,
double s1;
double s2;
double c, c1;
register SPICE_DATA *gv = xctx->graph_values[v];
register SPICE_DATA *gv = xctx->graph_values[idx];
dbg(1, "draw_graph_points: v=%d, first=%d, last=%d, wcnt=%d\n", v, first, last, wcnt);
dbg(1, "draw_graph_points: idx=%d, first=%d, last=%d, wcnt=%d\n", idx, first, last, wcnt);
digital = gr->digital;
if(digital) {
s1 = DIG_NWAVES; /* 1/DIG_NWAVES waveforms fit in graph if unscaled vertically */
@ -1792,7 +1792,7 @@ static void draw_graph_points(int v, int first, int last,
XDrawLines(display, xctx->save_pixmap, xctx->gc[wave_col], point, poly_npoints, CoordModeOrigin);
}
set_thick_waves(0, wcnt, wave_col, gr);
} else dbg(1, "skipping wave: %s\n", xctx->graph_names[v]);
} else dbg(1, "skipping wave: %s\n", xctx->graph_names[idx]);
}
static void draw_graph_grid(Graph_ctx *gr)
@ -2280,7 +2280,7 @@ int edit_wave_attributes(int what, int i, Graph_ctx *gr)
nptr = node;
cptr = color;
sptr = sweep;
n_nodes = count_items(node, " \t\n");
n_nodes = count_items(node, " \t\n", "\"");
/* process each node given in "node" attribute, get also associated color/sweep var if any */
while( (ntok = my_strtok_r(nptr, "\n\t ", "\"", &saven)) ) {
ctok = my_strtok_r(cptr, " ", "", &savec);
@ -2400,7 +2400,7 @@ void draw_graph(int i, const int flags, Graph_ctx *gr)
nptr = node;
cptr = color;
sptr = sweep;
n_nodes = count_items(node, " \t\n");
n_nodes = count_items(node, " \t\n", "\"");
/* process each node given in "node" attribute, get also associated color/sweep var if any*/
while( (ntok = my_strtok_r(nptr, "\n\t ", "\"", &saven)) ) {
if(strstr(ntok, ",")) {
@ -2420,8 +2420,14 @@ void draw_graph(int i, const int flags, Graph_ctx *gr)
}
}
draw_graph_variables(wcnt, wave_color, n_nodes, sweep_idx, flags, ntok, stok, bus_msb, gr);
/* custom data plot */
idx = -1;
if(xctx->graph_values && !bus_msb && strstr(ntok, " ")) {
idx = xctx->graph_nvars;
plot_raw_custom_data(sweep_idx, ntok);
}
/* quickly find index number of ntok variable to be plotted */
if( (idx = get_raw_index(bus_msb ? bus_msb : ntok)) != -1 ) {
if( idx == xctx->graph_nvars || (idx = get_raw_index(bus_msb ? bus_msb : ntok)) != -1 ) {
int p, dset, ofs;
int poly_npoints;
int first, last;
@ -2434,8 +2440,6 @@ void draw_graph(int i, const int flags, Graph_ctx *gr)
XPoint *point = NULL;
int dataset = gr->dataset;
int digital = gr->digital;
/* <<<< */
/* if(idx == xctx->graph_nvars -1) plot_raw_custom_data(sweep_idx); */
ofs = 0;
start = (gr->gx1 <= gr->gx2) ? gr->gx1 : gr->gx2;
end = (gr->gx1 <= gr->gx2) ? gr->gx2 : gr->gx1;

View File

@ -237,9 +237,9 @@ static void read_binary_block(FILE *fd)
/* read buffer */
tmp = my_calloc(1405, xctx->graph_nvars, (sizeof(double *) ));
/* allocate storage for binary block */
if(!xctx->graph_values) xctx->graph_values = my_calloc(118, xctx->graph_nvars, sizeof(SPICE_DATA *));
for(p = 0 ; p < xctx->graph_nvars; p++) {
/* allocate storage for binary block, add one data column for custom data plots */
if(!xctx->graph_values) xctx->graph_values = my_calloc(118, xctx->graph_nvars + 1, sizeof(SPICE_DATA *));
for(p = 0 ; p <= xctx->graph_nvars; p++) {
my_realloc(372,
&xctx->graph_values[p], (offset + xctx->graph_npoints[xctx->graph_datasets]) * sizeof(SPICE_DATA));
}
@ -389,7 +389,8 @@ void free_rawfile(int dr)
}
if(xctx->graph_values) {
deleted = 1;
for(i = 0 ; i < xctx->graph_nvars; i++) {
/* free also extra column for custom data plots */
for(i = 0 ; i <= xctx->graph_nvars; i++) {
my_free(512, &xctx->graph_values[i]);
}
my_free(528, &xctx->graph_values);
@ -488,12 +489,18 @@ int read_rawfile(const char *f)
int get_raw_index(const char *node)
{
char vnode[300];
char lnode[300];
Int_hashentry *entry;
if(xctx->graph_values) {
entry = int_hash_lookup(xctx->raw_table, node, 0, XLOOKUP);
if(!entry) {
my_snprintf(vnode, S(vnode), "v(%s)", node);
entry = int_hash_lookup(xctx->raw_table, vnode, 0, XLOOKUP);
if(!entry) {
my_strncpy(lnode, vnode, S(lnode));
strtolower(lnode);
entry = int_hash_lookup(xctx->raw_table, lnode, 0, XLOOKUP);
}
}
if(entry) return entry->value;
}
@ -501,35 +508,143 @@ int get_raw_index(const char *node)
}
/* <<<< */
void plot_raw_custom_data(int sweep_idx)
#define PLUS -2
#define MINUS -3
#define MULT -4
#define DIVIS -5
#define POW -6
#define SIN -7
#define COS -8
#define ABS -9
#define SGN -10
#define INTEG -11
#define DERIV -12
#define NUMBER -60
typedef struct {
int i;
double d;
double prev;
} Stack1;
void plot_raw_custom_data(int sweep_idx, const char *ntok)
{
int p, ofs = 0;
/* xctx->graph_datasets */
int idx = xctx->graph_nvars -1;
int dset;
int ret;
char cmd[100];
int i, p, idx, ofs = 0;
int dset, nitems;
const char *n;
char *endptr;
Stack1 stack1[200];
double v, stack2[200];
int stackptr1 = 0, stackptr2 = 0;
SPICE_DATA *y = xctx->graph_values[xctx->graph_nvars]; /* custom plot data column */
SPICE_DATA *x = xctx->graph_values[sweep_idx];
SPICE_DATA *y = xctx->graph_values[idx];
if(!(tcleval("info procs customplot")[0])) return;
nitems = count_items(ntok, " ", "");
dbg(1, "plot_raw_custom_data(), ntok=%s nitems = %d\n", ntok, nitems);
for(i = 1; i <= nitems; i++) {
n = find_nth(ntok, ' ', i);
dbg(1, " plot_raw_custom_data(): n = %s i = %d\n", n, i);
if(!strcmp(n, "+")) stack1[stackptr1++].i = PLUS;
else if(!strcmp(n, "-")) stack1[stackptr1++].i = MINUS;
else if(!strcmp(n, "*")) stack1[stackptr1++].i = MULT;
else if(!strcmp(n, "/")) stack1[stackptr1++].i = DIVIS;
else if(!strcmp(n, "**")) stack1[stackptr1++].i = POW;
else if(!strcmp(n, "sin()")) stack1[stackptr1++].i = SIN;
else if(!strcmp(n, "cos()")) stack1[stackptr1++].i = COS;
else if(!strcmp(n, "abs()")) stack1[stackptr1++].i = ABS;
else if(!strcmp(n, "sgn()")) stack1[stackptr1++].i = SGN;
else if(!strcmp(n, "integ()")) stack1[stackptr1++].i = INTEG;
else if(!strcmp(n, "deriv()")) stack1[stackptr1++].i = DERIV;
else if( (v = strtod(n, &endptr)), !*endptr) {
stack1[stackptr1].i = NUMBER;
stack1[stackptr1++].d = v;
}
else {
idx = get_raw_index(n);
if(idx == -1) {
dbg(1, "plot_raw_custom_data(): no data found: %s\n", n);
return; /* no data found in raw file */
}
stack1[stackptr1].i = idx;
stackptr1++;
}
dbg(1, " plot_raw_custom_data(): stack1= %d\n", stack1[stackptr1 - 1].i);
}
for(dset = 0 ; dset < xctx->graph_datasets; dset++) {
for(p = ofs ; p < ofs + xctx->graph_npoints[dset]; p++) {
my_snprintf(cmd, S(cmd), "customplot %d %g", p, x[p]);
ret = Tcl_GlobalEval(interp, cmd);
if(ret == TCL_OK) {
const char *r = tclresult();
if(r[0]) y[p] = atof(r);
} else {
fprintf(errfp, "plot_raw_custom_data(): evaluation of script: %s failed\n", cmd);
fprintf(errfp, " : %s\n", Tcl_GetStringResult(interp));
Tcl_ResetResult(interp);
y[p] = 0.0;
}
/* y[p] = sin(dset * x[p] * 1e7); */
stackptr2 = 0;
for(i = 0; i < stackptr1; i++) { /* number */
if(stack1[i].i == NUMBER) {
stack2[stackptr2++] = stack1[i].d;
}
else if(stack1[i].i >=0 && stack1[i].i < xctx->graph_allpoints) { /* spice node */
stack2[stackptr2++] = xctx->graph_values[stack1[i].i][p];
}
if(stackptr2 > 1) { /* 2 argument operators */
if(stack1[i].i == PLUS) {
stack2[stackptr2 - 2] = stack2[stackptr2 - 2] + stack2[stackptr2 - 1];
stackptr2--;
}
else if(stack1[i].i == MINUS) {
stack2[stackptr2 - 2] = stack2[stackptr2 - 2] - stack2[stackptr2 - 1];
stackptr2--;
}
else if(stack1[i].i == MULT) {
stack2[stackptr2 - 2] = stack2[stackptr2 - 2] * stack2[stackptr2 - 1];
stackptr2--;
}
else if(stack1[i].i == DIVIS) {
stack2[stackptr2 - 2] = stack2[stackptr2 - 2] / stack2[stackptr2 - 1];
stackptr2--;
}
else if(stack1[i].i == POW) {
stack2[stackptr2 - 2] = pow(stack2[stackptr2 - 2], stack2[stackptr2 - 1]);
stackptr2--;
}
}
if(stackptr2 > 0) { /* 1 argument operators */
if(stack1[i].i == SIN) {
stack2[stackptr2 - 1] = sin(stack2[stackptr2 - 1]);
}
else if(stack1[i].i == COS) {
stack2[stackptr2 - 1] = cos(stack2[stackptr2 - 1]);
}
else if(stack1[i].i == ABS) {
stack2[stackptr2 - 1] = fabs(stack2[stackptr2 - 1]);
}
else if(stack1[i].i == SGN) {
stack2[stackptr2 - 1] = stack2[stackptr2 - 1] > 0.0 ? 1 :
stack2[stackptr2 - 1] < 0.0 ? -1 : 0;
}
else if(stack1[i].i == INTEG) {
double integ = 0;
if( p == ofs ) {
integ = 0;
stack1[i].prev = 0;
} else {
integ = stack1[i].prev + (x[p] - x[p - 1]) * stack2[stackptr2 - 1];
stack1[i].prev = integ;
}
stack2[stackptr2 - 1] = integ;
}
else if(stack1[i].i == DERIV) {
double deriv = 0;
if( p == ofs ) {
deriv = 0;
stack1[i].prev = stack2[stackptr2 - 1];
} else {
deriv = (stack2[stackptr2 - 1] - stack1[i].prev) / (x[p] - x[p - 1]);
stack1[i].prev = stack2[stackptr2 - 1] ;
}
stack2[stackptr2 - 1] = deriv;
}
} /* else if(stackptr2 > 0) */
} /* for(i = 0; i < stackptr1; i++) */
y[p] = stack2[0];
}
ofs += xctx->graph_npoints[dset];
}
}
double get_raw_value(int dataset, int idx, int point)

View File

@ -945,52 +945,24 @@ const char *get_cell_w_ext(const char *str, int no_of_dir)
/* in a string with tokens separated by characters in 'sep'
* count number of tokens. Multiple separators and leading/trailing
* separators are allowed. */
int count_items(const char *s, const char *sep)
int count_items(const char *s, const char *sep, const char *quote)
{
const char *ptr;
int items = 0;
int state = 0; /* 1 if item is being processed */
int c;
int j, nsep = strlen(sep);
int c, q = 0;
ptr = s;
while( (c = *(unsigned char *)ptr++) ) {
for(j = 0; j < nsep; j++) {
if(c == sep[j]) break;
}
if(j >= nsep) { /* not a separator */
if(!state) items++;
state = 1;
} else {
state = 0;
}
}
return items;
}
/* in a string with tokens separated by characters in 'sep'
* count number of tokens. Multiple separators and leading/trailing
* separators are allowed. */
int xcount_items(const char *s, const char *sep)
{
const char *ptr;
char table[1 << 8 * sizeof(unsigned char)];
int items = 0;
int state = 0; /* 1 if item is being processed */
int c;
memset(table, 0, sizeof(table));
ptr = sep;
while( (c = *(unsigned char *)ptr++) ) table[c] = 1;
ptr = s;
while( (c = *(unsigned char *)ptr++) ) {
if(!table[c]) { /* not a separator */
if(strchr(quote, c)) q = !q;
if(q || !strchr(sep, c)) { /* not a separator */
if(!state) items++;
state = 1;
} else {
state = 0;
}
}
dbg(1, "count_items: s=%s, items=%d\n", s, items);
return items;
}
@ -2752,7 +2724,8 @@ const char *find_nth(const char *str, char sep, int n)
if(count==n) {
return ptr;
}
ptr=result+i+1;
while(result[++i] == sep) ;
ptr=result+i;
count++;
}
}

View File

@ -1028,7 +1028,7 @@ extern int get_raw_index(const char *node);
extern void free_rawfile(int dr);
extern int read_rawfile(const char *f);
extern double get_raw_value(int dataset, int idx, int point);
extern void plot_raw_custom_data(int sweep_idx);
extern void plot_raw_custom_data(int sweep_idx, const char *ntok);
extern int schematic_waves_loaded(void);
extern int edit_wave_attributes(int what, int i, Graph_ctx *gr);
extern void draw_graph(int i, int flags, Graph_ctx *gr);
@ -1360,7 +1360,7 @@ extern void select_line(int c, int i, unsigned short select_mode, int fast);
extern void select_polygon(int c, int i, unsigned short select_mode, int fast );
extern const char *net_name(int i, int j, int *mult, int hash_prefix_unnamed_net, int erc);
extern int record_global_node(int what, FILE *fp, char *node);
extern int count_items(const char *s, const char *sep);
extern int count_items(const char *s, const char *sep, const char *quote);
extern int get_unnamed_node(int what, int mult, int node);
extern void node_hash_free(void);
extern void traverse_node_hash();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -22,8 +22,8 @@ B 2 260 -1080 720 -920 {flags=graph
y1 = 0
y2 = 0.93
divy = 5
x1=1.0603e-07
x2=4.34086e-07
x1=1.12193e-07
x2=4.32192e-07
divx=5
subdivx=4
unitx=n
@ -32,18 +32,18 @@ saout"
color="4 5"
}
B 2 260 -1220 720 -1090 {flags=graph
y1 = 0.647719
y2 = 0.652802
y1 = 0.647319
y2 = 0.652563
divy = 5
x1=1.0603e-07
x2=4.34086e-07
x1=1.12193e-07
x2=4.32192e-07
unitx=n
divx=5
subdivx=4
node="plus
minus
\\"plus minus -\\""
color="4 5 8"}
minus"
color="4 5"
dataset=3}
T {CAL} 140 -180 0 1 0.4 0.4 {}
T {EN} 140 -130 0 1 0.4 0.4 {}
T {CALIBRATION