new command wrs2p

This commit is contained in:
h_vogt 2010-10-16 12:05:09 +00:00
parent 32c134f481
commit afdf6ee134
8 changed files with 391 additions and 23 deletions

View File

@ -1,3 +1,9 @@
2010-10-15 Holger Vogt
* examples/control_structs/s-param.cir new example
* commands.c, postcoms.h, postcoms.c, rawfile.h, rawfile.c
fteext.h: new command wrs2p, write a s-parameter file
using Touchstone vers. 1 format.
2010-10-15 Holger Vogt
* src/ciderlib/input/output.c : #include "../misc/tilde.h"
* inpcom.c: line 2800ff, allow -.5 token

View File

@ -0,0 +1,116 @@
Test for Scattering Parameters
** Two ports
** Examples: Bipolar, Tschebyschef, RC
.param Rbase=50 Vbias_in=0 Vbias_out=0
*** The two-port circuit:
** port 1: in 0
** port 2: out 0
** Bias on both ports through resistor Rbase (to obtain operating point)
** Example RF Bipolar mrf5711
** VCE 1 V, IE = 5mA
** QXXXXXXX nc nb ne
** model obtained from
** http://141.69.160.32/~krausg/Spice_Model_CD/Vendor%20List/Motorola/Spice/RFBJT/
*.include MRF5711.lib
*XMRF5711 out in e MRF5711
*Ie e 0 5m
*Ce e 0 1
** Example Tschebyschef Low Pass filter
C1 in 0 33.2p
L1 in 2 99.2n
C2 2 0 57.2p
L2 2 out 99.2n
C3 out 0 33.2p
** Example RC
** see
** http://www.allenhollister.com/allen/files/scatteringparameters.pdf
*R2 in out 10
*C1 out int5 30p
*R1 int5 0 10
*** End of circuit
** The following subcircuit to be changed only by an experienced user!
*** Driver and readout
X1 in out S22 S12 S_PARAM
.SUBCKT S_PARAM 22 66 5 7
* Resistors emulate switches with Ron=0.001 and Roff=1e12
* to switch driver to input and readout to output (and vice versa, see below)
RS1 22 2 0.001
RS2 66 6 0.001
RS3 22 6 1e12
RS4 66 2 1e12
*Driver
Vacdc 1 0 DC 'Vbias_in' AC 1 $ ac voltage and dc bias at input (applied through load resistor)
R1 1 2 'Rbase'
E1 3 0 2 0 2 $ amplify in port ac voltage by 2
Vac 3 4 DC 0 AC 1 $ subtract driving ac voltage
R_loop 4 5 0.001
R3 5 0 1 $ ground return for measure node 5
*Readout
E2 7 0 6 0 2 $ amplify out port ac voltage by 2
R4 6 8 'Rbase' $ load resistor at output (ac)
Vdc 8 0 DC 'Vbias_out' AC 0 $ dc bias at output (applied through load resistor)
.ends
** Check the two ac lines below for being equal!
.control
set noaskquit
set filetype=ascii
** measurement for s11 and s21
op
** save bias voltages to vector
let Vdcnew=V(X1.1) $ former Vacdc
let Vacdcnew=v(X1.8) $ former Vdc
*ac lin 20 0.1G 2G $ use for bip transistor
ac lin 100 2.5MEG 250MEG $ use for Tschebyschef
*ac lin 101 1k 10G $ use for RC
** switch input and output
alter R.X1.RS1=1e12
alter R.X1.RS2=1e12
alter R.X1.RS3=0.001
alter R.X1.RS4=0.001
** switch bias voltages between in and out
alter V.X1.Vacdc DC=op1.Vacdcnew
alter V.X1.Vdc DC=op1.Vdcnew
** measurement for s12 and s22
op
*ac lin 20 0.1G 2G $ use for bip transistor
ac lin 100 2.5MEG 250MEG $ use for Tschebyschef
*ac lin 101 1 10G $ use for RC
let s11=ac1.s22
let s21=ac1.s12
settype s-param S11 S21 S22 S12
let S11db = db(s11)
let S12db = db(s12)
let S21db = db(s21)
let S22db = db(s22)
settype decibel S11db S21db S22db S12db
let P11=180*ph(s11)/pi
let P21=180*ph(s21)/pi
let P22=180*ph(S22)/pi
let P12=180*ph(S12)/pi
settype phase P11 P21 P22 P12
let Rbase=@R.X1.R4[Resistance]
settype impedance Rbase
*plot s11db s21db S22db S12db ylimit -50 0 xlog $ used with RC
plot s11db s21db S22db S12db ylimit -0.5 0 $ used with Tschebyschef
plot P11 P21 P22 P12
plot smithgrid S11 S12
*wrdata s3046 mag(S11) P11 mag(S21) P21 mag(S22) P22 mag(S12) P12 $ write simple table
wrs2p s3046.s2p $ write touchstone vers. 1 file s3046.s2p
.endc
.end

View File

@ -71,29 +71,18 @@
/* gtri - end - wbk - add include files */
#endif
/* Information about spice commands (strucct comm). */
/* The name of the command. */
// char *co_comname;
/* The function that handles the command. */
// void (*co_func) (wordlist *wl);
/* These can't be used from nutmeg. */
// bool co_spiceonly;
/* Is this a "major" command? */
// bool co_major;
/* Bitmasks for command completion. */
// long co_cctypes[4];
/* print help message on this environment mask */
// unsigned int co_env;
/* minimum number of arguments required */
// int co_minargs;
/* maximum number of arguments allowed */
// int co_maxargs;
/* The fn that prompts the user. */
// void (*co_argfn) (wordlist *wl, struct comm *command);
/* When these are printed, printf(string, av[0]) .. */
// char *co_help;
/* Bool fields: spiceonly, major */
/* Information about spice commands (struct comm). */
// char *co_comname; /* The name of the command. */
// void (*co_func) (wordlist *wl); /* The function that handles the command. */
// bool co_spiceonly; /* These can't be used from nutmeg. */
// bool co_major; /* Is this a "major" command? */
// long co_cctypes[4]; /* Bitmasks for command completion. */
// unsigned int co_env; /* print help message on this environment mask */
// int co_minargs; /* minimum number of arguments required */
// int co_maxargs; /* maximum number of arguments allowed */
// void (*co_argfn) (wordlist *wl, struct comm *command); /* The fn that prompts the user. */
// char *co_help; /* When these are printed, printf(string, av[0]) .. */
struct comm spcp_coms[] = {
{ "let", com_let, FALSE, TRUE,
@ -189,6 +178,10 @@ struct comm spcp_coms[] = {
{ 1, 041000, 041000, 041000 }, E_DEFHMASK, 2, LOTS,
NULL,
"file plotargs : Send plot data to file." } ,
{ "wrs2p", com_write_sparam, FALSE, TRUE,
{ 1, 041000, 041000, 041000 }, E_DEFHMASK, 0, LOTS,
NULL,
"file : Send s-param data to file." } ,
{ "hardcopy", com_hardcopy, FALSE, TRUE,
{ 1, 041000, 041000, 041000 }, E_DEFHMASK, 0, LOTS,
NULL,
@ -605,6 +598,10 @@ struct comm nutcp_coms[] = {
{ 1, 041000, 041000, 041000 }, E_DEFHMASK, 2, LOTS,
NULL,
"file plotargs : Send plot data to file." } ,
{ "wrs2p", com_write_sparam, FALSE, TRUE,
{ 1, 041000, 041000, 041000 }, E_DEFHMASK, 0, LOTS,
NULL,
"file : Send s-param data to file." } ,
{ "hardcopy", com_hardcopy, FALSE, TRUE,
{ 1, 041000, 041000, 041000 }, E_DEFHMASK, 0, LOTS,
NULL,

View File

@ -524,6 +524,149 @@ com_write(wordlist *wl)
return;
}
/* Write scattering parameters into a file with Touchstone File Format Version 1
with command wrs2p file .
Format info from http://www.eda.org/ibis/touchstone_ver2.0/touchstone_ver2_0.pdf
See example 13 on page 15: Two port, ASCII, real-imaginary
Check if S11, S21, S12, S22 and frequency vectors are available
Check if vector Rbase is available
Call spar_write()
*/
void
com_write_sparam(wordlist *wl)
{
char *file;
char* sbuf[6];
wordlist *wl_sparam;
struct pnode *n;
struct dvec *d, *vecs = NULL, *lv = NULL, *end, *vv, *Rbasevec=NULL;
struct pnode *names;
bool scalefound, appendwrite=FALSE;
struct plot *tpl, newplot;
double Rbaseval;
if (wl) {
file = wl->wl_word;
} else
file = "s_param.s2p";
/* generate wordlist with all vectors required*/
sbuf[0] = "frequency";
sbuf[1] = "S11";
sbuf[2] = "S21";
sbuf[3] = "S12";
sbuf[4] = "S22";
sbuf[5] = NULL;
wl_sparam = wl_build(sbuf);
names = ft_getpnames(wl_sparam, TRUE);
if (names == NULL)
return;
for (n = names; n; n = n->pn_next) {
d = ft_evaluate(n);
if (!d)
return;
if (vecs)
lv->v_link2 = d;
else
vecs = d;
for (lv = d; lv->v_link2; lv = lv->v_link2)
;
}
Rbasevec = vec_get("Rbase");
if (Rbasevec)
Rbaseval = Rbasevec->v_realdata[0];
else {
fprintf(stderr, "Error: No Rbase vector given\n");
return;
}
/* Now we have to write them out plot by plot. */
while (vecs) {
tpl = vecs->v_plot;
tpl->pl_written = TRUE;
end = NULL;
bcopy(tpl, &newplot, sizeof (struct plot));
scalefound = FALSE;
/* Figure out how many vectors are in this plot. Also look
* for the scale, or a copy of it, which may have a different
* name.
*/
for (d = vecs; d; d = d->v_link2) {
if (d->v_plot == tpl) {
vv = vec_copy(d);
/* Note that since we are building a new plot
* we don't want to vec_new this one...
*/
vv->v_name = vec_basename(vv);
if (end)
end->v_next = vv;
else
end = newplot.pl_dvecs = vv;
end = vv;
if (vec_eq(d, tpl->pl_scale)) {
newplot.pl_scale = vv;
scalefound = TRUE;
}
}
}
end->v_next = NULL;
/* Maybe we shouldn't make sure that the default scale is
* present if nobody uses it.
*/
if (!scalefound) {
newplot.pl_scale = vec_copy(tpl->pl_scale);
newplot.pl_scale->v_next = newplot.pl_dvecs;
newplot.pl_dvecs = newplot.pl_scale;
}
/* Now let's go through and make sure that everything that
* has its own scale has it in the plot.
*/
for (;;) {
scalefound = FALSE;
for (d = newplot.pl_dvecs; d; d = d->v_next) {
if (d->v_scale) {
for (vv = newplot.pl_dvecs; vv; vv =
vv->v_next)
if (vec_eq(vv, d->v_scale))
break;
/* We have to grab it... */
vv = vec_copy(d->v_scale);
vv->v_next = newplot.pl_dvecs;
newplot.pl_dvecs = vv;
scalefound = TRUE;
}
}
if (!scalefound)
break;
/* Otherwise loop through again... */
}
spar_write(file, &newplot, Rbaseval);
/* Now throw out the vectors we have written already... */
for (d = vecs, lv = NULL; d; d = d->v_link2)
if (d->v_plot == tpl) {
if (lv) {
lv->v_link2 = d->v_link2;
d = lv;
} else
vecs = d->v_link2;
} else
lv = d;
/* If there are more plots we want them appended... */
appendwrite = TRUE;
}
return;
}
/* If the named vectors have more than 1 dimension, then consider
* to be a collection of one or more matrices. This command transposes
* each named matrix.

View File

@ -11,6 +11,7 @@ void com_unlet(wordlist *wl);
void com_load(wordlist *wl);
void com_print(wordlist *wl);
void com_write(wordlist *wl);
void com_write_sparam(wordlist *wl);
void com_transpose(wordlist *wl);
void com_setscale(wordlist *wl);
void com_display(wordlist *wl);

View File

@ -740,3 +740,105 @@ fixdims(struct dvec *v, char *s)
}
return;
}
/* Write a s-param file according to format Touchstone Vers. 1. */
void
spar_write(char *name, struct plot *pl, double Rbaseval)
{
FILE *fp;
bool realflag = TRUE;
int length, numdims, dims[MAXDIMS];
int i, j, prec;
struct dvec *v, *lv;
/* Why bother printing out an empty plot? */
if (!pl->pl_dvecs) {
fprintf(cp_err, "Error writing s2p: plot is empty, nothing written.\n");
return;
}
if (raw_prec != -1)
prec = raw_prec;
else
prec = 6;
numdims = length = 0;
for (v = pl->pl_dvecs; v; v = v->v_next) {
/* All vectors have to have same length,
only dimension 1 is allowed */
if (length == 0) {length = v->v_length;}
if (length != v->v_length) {
fprintf(stderr,"Error writing s2p: lentgth of vector %s differs from length of vector 'frequency'\n",
v->v_name);
return;
}
if (v->v_numdims != 1) {
fprintf(stderr,"Error writing s2p: Dimension of vector %s greater than 1\n",v->v_name);
return;
}
/* Find the length and dimensions of the longest vector
* in the plot.
* Be paranoid and assume somewhere we may have
* forgotten to set the dimensions of 1-D vectors.
if (v->v_numdims <= 1) {
v->v_numdims = 1;
v->v_dims[0] = v->v_length;
}
if (v->v_length > length) {
length = v->v_length;
numdims = v->v_numdims;
for (j = 0; j < numdims; j++) {
dims[j] = v->v_dims[j];
}
}*/
}
if (!(fp = fopen(name, "w"))) {
perror(name);
return;
}
fprintf(fp, "!2-port S-parameter file\n");
fprintf(fp, "!Title: %s\n", pl->pl_title);
fprintf(fp, "!Generated by ngspice at %s\n", pl->pl_date);
fprintf(fp, "# Hz S RI R %g\n", Rbaseval);
fprintf(fp, "!%-*.5s %-*.5s %-*.5s %-*.5s %-*.5s %-*.5s %-*.5s %-*.5s %-*.5s\n",
prec+8,"freq",
prec+8,"ReS11",prec+8,"ImS11",prec+8,"ReS21",prec+8,"ImS21",
prec+8,"ReS12",prec+8,"ImS12",prec+8,"ReS22",prec+8,"ImS22");
/* Before we write the stuff out, make sure that the scale is the first
* in the list.
*/
for (lv = NULL, v = pl->pl_dvecs; v != pl->pl_scale; v = v->v_next)
lv = v;
if (lv) {
lv->v_next = v->v_next;
v->v_next = pl->pl_dvecs;
pl->pl_dvecs = v;
}
/* print frequency first as real value, the real and imag part of
S11, S21, S12, S22 respectively */
for (i = 0; i < length; i++) {
for (v = pl->pl_dvecs; v; v = v->v_next) {
if (i < v->v_length) {
if (cieq(v->v_name, "frequency"))
fprintf(fp, "% .*e ", prec,
realpart(&v->v_compdata[i]));
else
fprintf(fp, "% .*e % .*e ", prec,
realpart(&v->v_compdata[i]),
prec,
imagpart(&v->v_compdata[i]));
}
}
(void) putc('\n', fp);
}
(void) fclose(fp);
return;
}

View File

@ -7,6 +7,7 @@
#define RAWFILE_H_INCLUDED
void raw_write(char *name, struct plot *pl, bool app, bool binary);
void spar_write(char *name, struct plot *pl, double val);
struct plot * raw_read(char *name);

View File

@ -324,6 +324,7 @@ extern void com_unlet(wordlist *wl);
extern void com_load(wordlist *wl);
extern void com_print(wordlist *wl);
extern void com_write(wordlist *wl);
extern void com_write_sparam(wordlist *wl);
extern void com_destroy(wordlist *wl);
extern void com_splot(wordlist *wl);
extern void com_setscale(wordlist *wl);
@ -332,6 +333,7 @@ extern void com_transpose(wordlist *wl);
/* rawfile.c */
extern int raw_prec;
extern void raw_write(char *name, struct plot *pl, bool app, bool binary);
extern void spar_write(char *name, struct plot *pl, double val);
extern struct plot *raw_read(char *name);
/* meas.c */