Qucs-core
0.0.19
|
00001 /* 00002 * touchstone_producer.cpp - the Touchstone data file producer 00003 * 00004 * Copyright (C) 2007 Stefan Jahn <stefan@lkcc.org> 00005 * 00006 * This is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2, or (at your option) 00009 * any later version. 00010 * 00011 * This software is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this package; see the file COPYING. If not, write to 00018 * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 00019 * Boston, MA 02110-1301, USA. 00020 * 00021 * $Id$ 00022 * 00023 */ 00024 00025 #if HAVE_CONFIG_H 00026 # include <config.h> 00027 #endif 00028 00029 #include <stdio.h> 00030 #include <stdlib.h> 00031 #include <time.h> 00032 #include <ctype.h> 00033 #include <string.h> 00034 00035 #include "touchstone_producer.h" 00036 #include "matrix.h" 00037 #include "matvec.h" 00038 #include "constants.h" 00039 00040 using namespace qucs; 00041 00042 /* Global variables. */ 00043 /* dataset * qucs_data = NULL; -- already defined in CSV producer */ 00044 /* FILE * touchstone_out = NULL; -- already defined in Touchstone lexer */ 00045 00046 struct touchstone_data_t { 00047 char parameter; // type of variable 00048 int ports; // number of S-parameter ports 00049 double resistance; // reference impedance 00050 const char * format; // data format 00051 qucs::vector * vd; // appropriate dependency vector 00052 matvec * mv; // appropriate data matrix vector 00053 qucs::vector * fmin; // minimum noise figure 00054 qucs::vector * sopt; // optimum input refelction for minimum noise figure 00055 qucs::vector * rn; // effective noise resistance 00056 qucs::vector * vf; // dependency vector for noise 00057 } 00058 touchstone_data; 00059 00060 /* Definition of line separator. */ 00061 #ifdef __MINGW32__ 00062 #define touchstone_crlf "\n" 00063 #else 00064 #define touchstone_crlf "\r\n" 00065 #endif 00066 00067 /* The Touchstone noise data printer. */ 00068 void touchstone_print_noise (void) { 00069 if (touchstone_data.vf != NULL && touchstone_data.sopt != NULL && 00070 touchstone_data.rn != NULL && touchstone_data.fmin != NULL) { 00071 // blank line separator 00072 fprintf (touchstone_out, touchstone_crlf); 00073 // noise data 00074 for (int i = 0; i < touchstone_data.vf->getSize (); i++) { 00075 nr_double_t f = real (touchstone_data.vf->get (i)); 00076 fprintf (touchstone_out, "%." "20" "e" 00077 " %+." "20" "e" 00078 " %+." "20" "e" " %+." "20" "e" 00079 " %+." "20" "e" 00080 touchstone_crlf, f, 00081 10.0 * std::log10 (real (touchstone_data.fmin->get (i))), 00082 abs (touchstone_data.sopt->get (i)), 00083 rad2deg (arg (touchstone_data.sopt->get (i))), 00084 real (touchstone_data.rn->get (i)) / 00085 touchstone_data.resistance); 00086 } 00087 } 00088 } 00089 00090 /* The Touchstone data printer. */ 00091 void touchstone_print (void) { 00092 // header line 00093 fprintf (touchstone_out, "# %s %c %s R %g" touchstone_crlf, 00094 "HZ", touchstone_data.parameter, touchstone_data.format, 00095 touchstone_data.resistance); 00096 // one-port file 00097 if (touchstone_data.ports == 1) { 00098 for (int i = 0; i < touchstone_data.vd->getSize (); i++) { 00099 matrix S = touchstone_data.mv->get (i); 00100 nr_double_t f = real (touchstone_data.vd->get (i)); 00101 fprintf (touchstone_out, "%." "20" "e" 00102 " %+." "20" "e" " %+." "20" "e" 00103 touchstone_crlf, f, real (S(0,0)), imag (S(0,0))); 00104 } 00105 } 00106 // two-port file 00107 else if (touchstone_data.ports == 2) { 00108 for (int i = 0; i < touchstone_data.vd->getSize (); i++) { 00109 matrix S = touchstone_data.mv->get (i); 00110 nr_double_t f = real (touchstone_data.vd->get (i)); 00111 fprintf (touchstone_out, "%." "20" "e" 00112 " %+." "20" "e" " %+." "20" "e" 00113 " %+." "20" "e" " %+." "20" "e" 00114 " %+." "20" "e" " %+." "20" "e" 00115 " %+." "20" "e" " %+." "20" "e" 00116 touchstone_crlf, f, 00117 real (S(0,0)), imag (S(0,0)), 00118 real (S(1,0)), imag (S(1,0)), 00119 real (S(0,1)), imag (S(0,1)), 00120 real (S(1,1)), imag (S(1,1))); 00121 } 00122 } 00123 // three-port file 00124 else if (touchstone_data.ports == 3) { 00125 for (int i = 0; i < touchstone_data.vd->getSize (); i++) { 00126 matrix S = touchstone_data.mv->get (i); 00127 nr_double_t f = real (touchstone_data.vd->get (i)); 00128 fprintf (touchstone_out, "%." "20" "e" 00129 " %+." "20" "e" " %+." "20" "e" 00130 " %+." "20" "e" " %+." "20" "e" 00131 " %+." "20" "e" " %+." "20" "e" 00132 touchstone_crlf " %" "20" "s" 00133 " %+." "20" "e" " %+." "20" "e" 00134 " %+." "20" "e" " %+." "20" "e" 00135 " %+." "20" "e" " %+." "20" "e" 00136 touchstone_crlf " %" "20" "s" 00137 " %+." "20" "e" " %+." "20" "e" 00138 " %+." "20" "e" " %+." "20" "e" 00139 " %+." "20" "e" " %+." "20" "e" 00140 touchstone_crlf, 00141 f, 00142 real (S(0,0)), imag (S(0,0)), 00143 real (S(0,1)), imag (S(0,1)), 00144 real (S(0,2)), imag (S(0,2)), " ", 00145 real (S(1,0)), imag (S(1,0)), 00146 real (S(1,1)), imag (S(1,1)), 00147 real (S(1,2)), imag (S(1,2)), " ", 00148 real (S(2,0)), imag (S(2,0)), 00149 real (S(2,1)), imag (S(2,1)), 00150 real (S(2,2)), imag (S(2,2))); 00151 } 00152 } 00153 // four-port and above files 00154 else if (touchstone_data.ports >= 4) { 00155 for (int i = 0; i < touchstone_data.vd->getSize (); i++) { 00156 matrix S = touchstone_data.mv->get (i); 00157 nr_double_t f = real (touchstone_data.vd->get (i)); 00158 int cs = S.getCols (); 00159 int rs = S.getRows (); 00160 fprintf (touchstone_out, "%." "20" "e", f); 00161 for (int r = 0; r < rs; r++) { 00162 if (r >= 1) 00163 fprintf (touchstone_out, " %" "20" "s", " "); 00164 for (int c = 0; c < cs; c++) { 00165 if (c > 1 && (c & 3) == 0) 00166 fprintf (touchstone_out, " %" "20" "s", " "); 00167 fprintf (touchstone_out, " %+." "20" "e" " %+." "20" "e", 00168 real (S(r,c)), imag (S(r,c))); 00169 if ((c > 1 && (c & 3) == 3) || (c == cs - 1)) 00170 fprintf (touchstone_out, touchstone_crlf); 00171 } 00172 } 00173 } 00174 } 00175 } 00176 00177 /* The function finds an appropriate S-parameters or other parameter 00178 type (G, H, Y, Z, etc.) matrix from the given dataset and stores it 00179 into the global Touchstone structure. */ 00180 void touchstone_find_data (dataset * data, const char * name) { 00181 qucs::vector * v; 00182 char * n; 00183 const char * vn; 00184 char * vd = NULL, * vf = NULL; 00185 strlist * deps; 00186 int r, c, rs = -1, cs = -1, s = 0; 00187 00188 // find parameter matrix data and its dimensions 00189 for (v = data->getVariables (); v != NULL; v = (::vector *) v->getNext ()) { 00190 vn = v->getName (); 00191 // requested matrix vector name found? 00192 if (strstr (vn, name) == vn) { 00193 if ((n = matvec::isMatrixVector (vn, r, c)) != NULL) { 00194 if (rs < r) rs = r; 00195 if (cs < c) cs = c; 00196 s = v->getSize (); 00197 free (n); 00198 if ((deps = v->getDependencies ()) != NULL) { 00199 vd = deps->get (0); 00200 } 00201 } 00202 } 00203 // minimum noise figure? 00204 if (!strcmp (vn, "Fmin")) { 00205 touchstone_data.fmin = v; 00206 if ((deps = v->getDependencies ()) != NULL) vf = deps->get (0); 00207 } 00208 // optimal input reflection for minimum noise figure? 00209 else if (!strcmp (vn, "Sopt")) { 00210 touchstone_data.sopt = v; 00211 if ((deps = v->getDependencies ()) != NULL) vf = deps->get (0); 00212 } 00213 // effective noise resitance? 00214 else if (!strcmp (vn, "Rn")) { 00215 touchstone_data.rn = v; 00216 if ((deps = v->getDependencies ()) != NULL) vf = deps->get (0); 00217 } 00218 } 00219 00220 // matrix entries found 00221 if (rs >= 0 && cs >= 0 && vd != NULL) { 00222 int ss = rs > cs ? rs : cs; 00223 // fill in number of ports 00224 touchstone_data.ports = ss + 1; 00225 // create quadratic matrix vector 00226 matvec * mv = new matvec (s, ss + 1, ss + 1); 00227 mv->setName (name); 00228 // fill in matrix vectors 00229 for (v = data->getVariables (); v; v = (::vector *) v->getNext ()) { 00230 vn = v->getName (); 00231 if (strstr (vn, name) == vn) { 00232 if ((n = matvec::isMatrixVector (vn, r, c)) != NULL) { 00233 mv->set (*v, r, c); 00234 free (n); 00235 } 00236 } 00237 } 00238 // store in global structure 00239 touchstone_data.mv = mv; 00240 touchstone_data.parameter = toupper (mv->getName ()[0]); 00241 // look for dependency (frequency) vector 00242 for (v = data->getDependencies (); v; v = (::vector *) v->getNext ()) { 00243 if (vd && !strcmp (v->getName (), vd)) { 00244 touchstone_data.vd = v; 00245 } 00246 if (vf && !strcmp (v->getName (), vf)) { 00247 touchstone_data.vf = v; 00248 } 00249 } 00250 } 00251 } 00252 00253 /* This is the overall Touchstone producer. */ 00254 void touchstone_producer (const char * variable) { 00255 00256 // apply data variable name 00257 if (variable == NULL) { 00258 variable = "S"; 00259 } 00260 00261 // initialize global Touchstone structure 00262 touchstone_data.mv = NULL; 00263 touchstone_data.vd = NULL; 00264 touchstone_data.format = "RI"; 00265 touchstone_data.resistance = 50.0; 00266 touchstone_data.fmin = NULL; 00267 touchstone_data.sopt = NULL; 00268 touchstone_data.rn = NULL; 00269 touchstone_data.vf = NULL; 00270 00271 // look for appropriate matrix data 00272 touchstone_find_data (qucs_data, variable); 00273 00274 // print matrix data if available 00275 if (touchstone_data.mv != NULL) { 00276 touchstone_print (); 00277 delete touchstone_data.mv; 00278 touchstone_print_noise (); 00279 } 00280 else { 00281 fprintf (stderr, "no such data variable `%s' found\n", variable); 00282 } 00283 }