My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
matchdialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  matchdialog.cpp
3  -----------------
4  begin : Fri Jul 22 2005
5  copyright : (C) 2005 by Michael Margraf
6  email : michael.margraf@alumni.tu-berlin.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 
22 #include "matchdialog.h"
23 #include "main.h"
24 #include "qucs.h"
25 #include "element.h"
26 #include "../components/capacitor.h"
27 #include "../components/inductor.h"
28 #include "../components/ground.h"
29 
30 #include <qlabel.h>
31 #include <qlayout.h>
32 #include <qhbox.h>
33 #include <qvbox.h>
34 #include <qlineedit.h>
35 #include <qcombobox.h>
36 #include <qcheckbox.h>
37 #include <qvalidator.h>
38 #include <qpushbutton.h>
39 #include <qmessagebox.h>
40 #include <qapplication.h>
41 #include <qclipboard.h>
42 #include <qhgroupbox.h>
43 #include <qvgroupbox.h>
44 
45 
46 MatchDialog::MatchDialog(QWidget *parent)
47  : QDialog(parent, 0, TRUE, Qt::WDestructiveClose)
48 {
49  setCaption(tr("Create Matching Circuit"));
50  DoubleVal = new QDoubleValidator(this);
51 
52  all = new QVBoxLayout(this, 3,3);
53 
54  TwoCheck = new QCheckBox(tr("calculate two-port matching"), this);
55  all->addWidget(TwoCheck);
56  TwoCheck->setChecked(true);
57  connect(TwoCheck, SIGNAL(toggled(bool)), SLOT(slotSetTwoPort(bool)));
58 
59  // ...........................................................
60  QHGroupBox *ImpBox = new QHGroupBox(tr("Reference Impedance"), this);
61  all->addWidget(ImpBox);
62  Port1Label = new QLabel(tr("Port 1"), ImpBox);
63  Ref1Edit = new QLineEdit("50", ImpBox);
64  Ref1Edit->setValidator(DoubleVal);
65  Ohm1Label = new QLabel(tr("ohms"), ImpBox);
66  connect(Ref1Edit, SIGNAL(textChanged(const QString&)),
67  SLOT(slotImpedanceChanged(const QString&)));
68  ImpBox->addSpace(50); // placeholder
69  Port2Label = new QLabel(tr("Port 2"), ImpBox);
70  Ref2Edit = new QLineEdit("50", ImpBox);
71  Ref2Edit->setValidator(DoubleVal);
72  Ohm2Label = new QLabel(tr("ohms"), ImpBox);
73 
74 
75  // ...........................................................
76  QVGroupBox *SParBox = new QVGroupBox(tr("S Parameter"), this);
77  all->addWidget(SParBox);
78 
79  QHBox *h1 = new QHBox(SParBox);
80  h1->setSpacing(3);
81  FormatLabel = new QLabel(tr("Input format"), h1);
82  FormatCombo = new QComboBox(h1);
83  FormatCombo->insertItem(tr("real/imag"));
84  FormatCombo->insertItem(tr("mag/deg"));
85  connect(FormatCombo, SIGNAL(activated(int)), SLOT(slotChangeMode(int)));
86  QWidget *place1 = new QWidget(h1); // stretchable placeholder
87  h1->setStretchFactor(place1, 5);
88 
89  QHBox *h3 = new QHBox(SParBox);
90  h3->setSpacing(3);
91  QVBox *VBox1 = new QVBox(h3);
92  S11Label = new QLabel(tr("S11"), VBox1);
93  S21Label = new QLabel(tr("S21"), VBox1);
94  QVBox *VBox2 = new QVBox(h3);
95  S11magEdit = new QLineEdit("0.5", VBox2);
96  S11magEdit->setValidator(DoubleVal);
97  S21magEdit = new QLineEdit("0.5", VBox2);
98  S21magEdit->setValidator(DoubleVal);
99  QVBox *VBox3 = new QVBox(h3);
100  S11sLabel = new QLabel("+j", VBox3);
101  S21sLabel = new QLabel("+j", VBox3);
102  QVBox *VBox4 = new QVBox(h3);
103  S11degEdit = new QLineEdit("0", VBox4);
104  S11degEdit->setValidator(DoubleVal);
105  S21degEdit = new QLineEdit("0", VBox4);
106  S21degEdit->setValidator(DoubleVal);
107  QVBox *VBox5 = new QVBox(h3);
108  S11uLabel = new QLabel(" ", VBox5);
109  S21uLabel = new QLabel(" ", VBox5);
110  QWidget *place4 = new QWidget(h3); // stretchable placeholder
111  h3->setStretchFactor(place4, 5);
112  QVBox *VBox6 = new QVBox(h3);
113  S12Label = new QLabel(tr("S12"), VBox6);
114  S22Label = new QLabel(tr("S22"), VBox6);
115  QVBox *VBox7 = new QVBox(h3);
116  S12magEdit = new QLineEdit("0", VBox7);
117  S12magEdit->setValidator(DoubleVal);
118  S22magEdit = new QLineEdit("0.5", VBox7);
119  S22magEdit->setValidator(DoubleVal);
120  QVBox *VBox8 = new QVBox(h3);
121  S12sLabel = new QLabel("+j", VBox8);
122  S22sLabel = new QLabel("+j", VBox8);
123  QVBox *VBox9 = new QVBox(h3);
124  S12degEdit = new QLineEdit("0", VBox9);
125  S12degEdit->setValidator(DoubleVal);
126  S22degEdit = new QLineEdit("0", VBox9);
127  S22degEdit->setValidator(DoubleVal);
128  QVBox *VBox0 = new QVBox(h3);
129  S12uLabel = new QLabel(" ", VBox0);
130  S22uLabel = new QLabel(" ", VBox0);
131 
132  connect(S21magEdit, SIGNAL(textChanged(const QString&)),
133  SLOT(slotImpedanceChanged(const QString&)));
134  connect(S21degEdit, SIGNAL(textChanged(const QString&)),
135  SLOT(slotImpedanceChanged(const QString&)));
136  connect(S11magEdit, SIGNAL(textChanged(const QString&)),
137  SLOT(slotReflexionChanged(const QString&)));
138  connect(S11degEdit, SIGNAL(textChanged(const QString&)),
139  SLOT(slotReflexionChanged(const QString&)));
140 
141 
142  QHBox *h2 = new QHBox(SParBox);
143  h2->setSpacing(3);
144  FrequencyLabel = new QLabel(tr("Frequency:"), h2);
145  FrequencyEdit = new QLineEdit(h2);
146  FrequencyEdit->setValidator(DoubleVal);
147  UnitCombo = new QComboBox(h2);
148  UnitCombo->insertItem("Hz");
149  UnitCombo->insertItem("kHz");
150  UnitCombo->insertItem("MHz");
151  UnitCombo->insertItem("GHz");
152  QWidget *place2 = new QWidget(h2); // stretchable placeholder
153  h2->setStretchFactor(place2, 5);
154 
155  // ...........................................................
156  QHBox *h0 = new QHBox(this);
157  h0->setSpacing(5);
158  all->addWidget(h0);
159  QWidget *place3 = new QWidget(h0); // stretchable placeholder
160  h0->setStretchFactor(place3, 5);
161  connect(new QPushButton(tr("Create"),h0), SIGNAL(clicked()),
162  SLOT(slotButtCreate()));
163  connect(new QPushButton(tr("Cancel"),h0), SIGNAL(clicked()),
164  SLOT(reject()));
165 
166 
167 // slotReflexionChanged(""); // calculate impedance
168  setFrequency(1e9); // set 1GHz
169  resize(520, 100);
170 }
171 
173 {
174  delete all;
175  delete DoubleVal;
176 }
177 
178 // -----------------------------------------------------------------------
179 void MatchDialog::setFrequency(double Freq_)
180 {
181  int Expo = int(log10(Freq_) / 3.0);
182  if(Expo < 0) Expo = 0;
183  else if(Expo > 3) Expo = 3;
184  UnitCombo->setCurrentItem(Expo);
185  Freq_ /= pow(10.0, double(3*Expo));
186  FrequencyEdit->setText(QString::number(Freq_));
187 }
188 
189 // -----------------------------------------------------------------------
190 // Is called when the checkbox for two-port matching changes.
192 {
193  if(on) { // two-port matching ?
194  S11Label->setText(tr("S11"));
195  S21Label->setText(tr("S21"));
196  S12magEdit->setEnabled(true);
197  S22magEdit->setEnabled(true);
198  S12degEdit->setEnabled(true);
199  S22degEdit->setEnabled(true);
200  S12Label->setEnabled(true);
201  S22Label->setEnabled(true);
202  S12sLabel->setEnabled(true);
203  S22sLabel->setEnabled(true);
204  S12degEdit->setEnabled(true);
205  S22degEdit->setEnabled(true);
206  S12uLabel->setEnabled(true);
207  S22uLabel->setEnabled(true);
208  Port2Label->setEnabled(true);
209  Ref2Edit->setEnabled(true);
210  Ohm2Label->setEnabled(true);
211  }
212  else {
213  S11Label->setText(tr("Reflexion Coefficient"));
214  S21Label->setText(tr("Impedance (ohms)"));
215  S12magEdit->setEnabled(false);
216  S22magEdit->setEnabled(false);
217  S12degEdit->setEnabled(false);
218  S22degEdit->setEnabled(false);
219  S12Label->setEnabled(false);
220  S22Label->setEnabled(false);
221  S12sLabel->setEnabled(false);
222  S22sLabel->setEnabled(false);
223  S12degEdit->setEnabled(false);
224  S22degEdit->setEnabled(false);
225  S12uLabel->setEnabled(false);
226  S22uLabel->setEnabled(false);
227  Port2Label->setEnabled(false);
228  Ref2Edit->setEnabled(false);
229  Ohm2Label->setEnabled(false);
230  }
231 }
232 
233 // -----------------------------------------------------------------------
234 // Is called when the combobox changes between mag/deg and real/imag.
236 {
237  if(Index) { // polar ?
238  S11sLabel->setText("/");
239  S12sLabel->setText("/");
240  S21sLabel->setText("/");
241  S22sLabel->setText("/");
242  S11uLabel->setText("°");
243  S12uLabel->setText("°");
244  S21uLabel->setText("°");
245  S22uLabel->setText("°");
246 
247  double Real = S11magEdit->text().toDouble();
248  double Imag = S11degEdit->text().toDouble();
249  c2p(Real, Imag);
250  S11magEdit->setText(QString::number(Real));
251  S11degEdit->setText(QString::number(Imag));
252 
253  Real = S12magEdit->text().toDouble();
254  Imag = S12degEdit->text().toDouble();
255  c2p(Real, Imag);
256  S12magEdit->setText(QString::number(Real));
257  S12degEdit->setText(QString::number(Imag));
258 
259  Real = S21magEdit->text().toDouble();
260  Imag = S21degEdit->text().toDouble();
261  c2p(Real, Imag);
262  S21magEdit->setText(QString::number(Real));
263  S21degEdit->setText(QString::number(Imag));
264 
265  Real = S22magEdit->text().toDouble();
266  Imag = S22degEdit->text().toDouble();
267  c2p(Real, Imag);
268  S22magEdit->setText(QString::number(Real));
269  S22degEdit->setText(QString::number(Imag));
270  }
271  else { // cartesian
272  S11sLabel->setText("+j");
273  S12sLabel->setText("+j");
274  S21sLabel->setText("+j");
275  S22sLabel->setText("+j");
276  S11uLabel->setText(" ");
277  S12uLabel->setText(" ");
278  S21uLabel->setText(" ");
279  S22uLabel->setText(" ");
280 
281  double Mag = S11magEdit->text().toDouble();
282  double Phase = S11degEdit->text().toDouble();
283  p2c(Mag, Phase);
284  S11magEdit->setText(QString::number(Mag));
285  S11degEdit->setText(QString::number(Phase));
286 
287  Mag = S12magEdit->text().toDouble();
288  Phase = S12degEdit->text().toDouble();
289  p2c(Mag, Phase);
290  S12magEdit->setText(QString::number(Mag));
291  S12degEdit->setText(QString::number(Phase));
292 
293  Mag = S21magEdit->text().toDouble();
294  Phase = S21degEdit->text().toDouble();
295  p2c(Mag, Phase);
296  S21magEdit->setText(QString::number(Mag));
297  S21degEdit->setText(QString::number(Phase));
298 
299  Mag = S22magEdit->text().toDouble();
300  Phase = S22degEdit->text().toDouble();
301  p2c(Mag, Phase);
302  S22magEdit->setText(QString::number(Mag));
303  S22degEdit->setText(QString::number(Phase));
304  }
305 }
306 
307 // -----------------------------------------------------------------------
308 // Is called if the user changed the impedance. -> The reflexion
309 // coefficient is calculated.
311 {
312  if(TwoCheck->isChecked()) return;
313 
314  double Z0 = Ref1Edit->text().toDouble();
315  double Real = S21magEdit->text().toDouble();
316  double Imag = S21degEdit->text().toDouble();
317  z2r(Real, Imag, Z0);
318  S11magEdit->blockSignals(true); // do not call "changed-slot"
319  S11magEdit->setText(QString::number(Real));
320  S11magEdit->blockSignals(false);
321  S11degEdit->blockSignals(true); // do not call "changed-slot"
322  S11degEdit->setText(QString::number(Imag));
323  S11degEdit->blockSignals(false);
324 }
325 
326 // -----------------------------------------------------------------------
327 // Is called if the user changed the reflexion coefficient. -> The impedance
328 // is calculated.
330 {
331  if(TwoCheck->isChecked()) return;
332 
333  double Z0 = Ref1Edit->text().toDouble();
334  double Real = S11magEdit->text().toDouble();
335  double Imag = S11degEdit->text().toDouble();
336  r2z(Real, Imag, Z0);
337  S21magEdit->blockSignals(true); // do not call "changed-slot"
338  S21magEdit->setText(QString::number(Real));
339  S21magEdit->blockSignals(false);
340  S21degEdit->blockSignals(true); // do not call "changed-slot"
341  S21degEdit->setText(QString::number(Imag));
342  S21degEdit->blockSignals(false);
343 }
344 
345 // -----------------------------------------------------------------------
346 // Is called if the "Create"-button is pressed.
348 {
349  double Z1 = Ref1Edit->text().toDouble();
350  double Z2 = Ref2Edit->text().toDouble();
351  double Freq = FrequencyEdit->text().toDouble() *
352  pow(10.0, 3.0*double(UnitCombo->currentItem()));
353 
354  double S11real = S11magEdit->text().toDouble();
355  double S11imag = S11degEdit->text().toDouble();
356  double S12real = S12magEdit->text().toDouble();
357  double S12imag = S12degEdit->text().toDouble();
358  double S21real = S21magEdit->text().toDouble();
359  double S21imag = S21degEdit->text().toDouble();
360  double S22real = S22magEdit->text().toDouble();
361  double S22imag = S22degEdit->text().toDouble();
362  if(FormatCombo->currentItem()) { // are they polar ?
363  p2c(S11real, S11imag);
364  p2c(S12real, S12imag);
365  p2c(S21real, S21imag);
366  p2c(S22real, S22imag);
367  }
368 
369  if(TwoCheck->isChecked()) { // two-port matching ?
370  // determinante of S-parameter matrix
371  double DetReal = S11real*S22real - S11imag*S22imag
372  - S12real*S21real + S12imag*S21imag;
373  double DetImag = S11real*S22imag + S11imag*S22real
374  - S12real*S21imag - S12imag*S21real;
375 
376  if(!MatchDialog::calc2PortMatch(S11real, S11imag, S22real, S22imag,
377  DetReal, DetImag, Z1, Z2, Freq))
378  return;
379  }
380  else
381  if(!calcMatchingCircuit(S11real, S11imag, Z1, Freq))
382  return;
383 
384  QucsMain->slotEditPaste(true);
385  accept();
386 }
387 
388 
389 // -----------------------------------------------------------------------
390 // transform real/imag into mag/deg (cartesian to polar)
391 void MatchDialog::c2p(double& Real, double& Imag)
392 {
393  double Real_ = Real;
394  Real = sqrt(Real*Real + Imag*Imag); // magnitude
395  Imag = 180.0/M_PI * atan2(Imag, Real_); // phase in degree
396 }
397 
398 // -----------------------------------------------------------------------
399 // transform mag/deg into real/imag (polar to cartesian)
400 void MatchDialog::p2c(double& Real, double& Imag)
401 {
402  double Real_ = Real;
403  Real = Real_ * cos(Imag * M_PI/180.0); // real part
404  Imag = Real_ * sin(Imag * M_PI/180.0); // imaginary part
405 }
406 
407 // -----------------------------------------------------------------------
408 // transform reflexion coefficient into impedance
409 void MatchDialog::r2z(double& Real, double& Imag, double Z0)
410 {
411  double tmp = Z0 / ((1.0-Real)*(1.0-Real) + Imag*Imag);
412  Real = (1.0 - Real*Real - Imag*Imag) * tmp;
413  Imag *= 2.0 * tmp;
414 }
415 
416 // -----------------------------------------------------------------------
417 // transform impedance into reflexion coefficient
418 void MatchDialog::z2r(double& Real, double& Imag, double Z0)
419 {
420  double tmp = (Real+Z0)*(Real+Z0) + Imag*Imag;
421  Real = (Real*Real + Imag*Imag - Z0*Z0) / tmp;
422  Imag *= 2.0 * Z0 / tmp;
423 }
424 
425 // -----------------------------------------------------------------------
426 // Calculate matching circuit. Returns string like "sp:1nH:5pF"
427 QString MatchDialog::calcMatching(double r_real, double r_imag,
428  double Z0, double Freq)
429 {
430  double Zreal = r_real, Zimag = r_imag;
431  r2z(Zreal, Zimag, Z0);
432 
433  if (Zreal < 0.0) {
434  if (Zreal < -1e-13) {
435  QMessageBox::critical(0, tr("Error"),
436  tr("Real part of impedance must be greater zero,\nbut is %1 !").arg(Zreal));
437  return QString(""); // matching not possible
438  }
439 
440  // In high-Q circuits, Zreal often becomes somewhat about -1e-16
441  // because of numerical inaccuracy.
442  Zreal = 0.0;
443  }
444 
445 
446  double X1, X2, Omega = 2.0 * M_PI * Freq;
447  QString Str;
448  if(r_real < 0) {
449  // ...................................................
450  // first serial than parallel component (possible if Zreal <= Z0)
451  Str = "sp";
452  X1 = sqrt(Zreal * (Z0 - Zreal));
453  if (Zimag < 0.0) X1 *= -1.0; // always use shortest matching path
454  X1 -= Zimag;
455 
456  // parallel component
457  X2 = (Zimag + X1) / (Zreal*Zreal + (Zimag + X1)*(Zimag + X1));
458  }
459  else {
460 
461  Str = "ps";
462  X1 = Zreal + Zimag*Zimag / Zreal - Z0;
463  // ...................................................
464  // first parallel than serial component (possible if X >= 0.0)
465  X1 = sqrt(Z0 * X1);
466  if (Zimag > 0.0) X1 *= -1.0; // always use shortest matching path
467 
468  // parallel component
469  X2 = Zimag / (Zreal*Zreal + Zimag*Zimag) + X1 / (Z0*Z0 + X1*X1);
470  }
471 
472 
473  // serial component
474  if (X1 < 0.0) // capacitance ?
475  Str += ':' + num2str(-1.0 / Omega / X1) + 'F';
476  else // inductance
477  Str += ':' + num2str(X1 / Omega) + 'H';
478 
479  // parallel component
480  if (X2 < 0.0) // inductance ?
481  Str += ':' + num2str(-1.0 / Omega / X2) + 'H';
482  else // capacitance
483  Str += ':' + num2str(X2 / Omega) + 'F';
484 
485  return Str;
486 }
487 
488 // -----------------------------------------------------------------------
489 bool MatchDialog::calcMatchingCircuit(double r_real, double r_imag,
490  double Z0, double Freq)
491 {
492  QString Schematic =
493  "<Qucs Schematic " PACKAGE_VERSION ">\n"
494  "<Components>\n";
495 
496 
497  QString Str = calcMatching(r_real, r_imag, Z0, Freq);
498  if(Str.isEmpty()) return false;
499 
500  if(Str.section(':', 0,0) == "sp") {
501  // ...................................................
502  // first serial than parallel component
503 
504  if(Str.section(':', 1,1).right(1) == "F")
505  Schematic += "<C C1";
506  else
507  Schematic += "<L L1";
508  Schematic += " 1 100 10 -26 10 0 0 \"" + Str.section(':', 1,1) + "\" 1>\n";
509 
510  if(Str.section(':', 2,2).right(1) == "F")
511  Schematic += "<C C2";
512  else
513  Schematic += "<L L2";
514  Schematic += " 1 30 80 17 -26 0 1 \"" + Str.section(':', 2,2) + "\" 1>\n";
515 
516  Schematic +=
517  "<GND * 1 30 110 0 0 0 0>\n"
518  "</Components>\n"
519  "<Wires>\n"
520  "<10 10 30 10 \"\" 0 0 0 \"\">\n"
521  "<30 10 70 10 \"\" 0 0 0 \"\">\n"
522  "<30 10 30 50 \"\" 0 0 0 \"\">\n";
523  }
524  else {
525  // ...................................................
526  // first parallel than serial component
527 
528  if(Str.section(':', 1,1).right(1) == "F")
529  Schematic += "<C C1";
530  else
531  Schematic += "<L L1";
532  Schematic += " 1 50 10 -26 10 0 0 \"" + Str.section(':', 1,1) + "\" 1>\n";
533 
534  if(Str.section(':', 2,2).right(1) == "F")
535  Schematic += "<C C2";
536  else
537  Schematic += "<L L2";
538  Schematic += " 1 130 70 17 -26 0 1 \"" + Str.section(':', 2,2) + "\" 1>\n";
539 
540  Schematic +=
541  "<GND * 1 130 100 0 0 0 0>\n"
542  "</Components>\n"
543  "<Wires>\n"
544  "<130 10 130 40 \"\" 0 0 0 \"\">\n"
545  "<130 10 150 10 \"\" 0 0 0 \"\">\n"
546  "<80 10 130 10 \"\" 0 0 0 \"\">\n";
547  }
548 
549  Schematic += QString(
550  "</Wires>\n"
551  "<Diagrams>\n"
552  "</Diagrams>\n"
553  "<Paintings>\n"
554  " <Text -20 -10 12 #000000 0 \"%1 Ohm\">\n"
555  " <Text 120 -10 12 #000000 0 \"device\">\n"
556  "</Paintings>\n").arg(Z0);
557 
558  QApplication::clipboard()->setText(Schematic, QClipboard::Clipboard);
559  return true;
560 }
561 
562 // -----------------------------------------------------------------------
563 // Fundamental calculations for concurrent 2-port matching.
564 QString MatchDialog::calcBiMatch(double S11real, double S11imag,
565  double S22real, double S22imag, double DetReal, double DetImag,
566  double Z0, double Freq)
567 {
568  double B = 1.0 + S11real*S11real + S11imag*S11imag
569  - S22real*S22real - S22imag*S22imag
570  - DetReal*DetReal - DetImag*DetImag;
571  double Creal = S11real - S22real*DetReal - S22imag*DetImag;
572  double Cimag = S22real*DetImag - S11imag - S22imag*DetReal;
573  double Cmag = 2.0 * (Creal*Creal + Cimag*Cimag);
574  Creal /= Cmag;
575  Cimag /= Cmag;
576 
577  double Rreal = B*B - 2.0*Cmag;
578  double Rimag;
579  if(Rreal < 0.0) {
580  Rimag = Cimag * B - Creal * sqrt(-Rreal);
581  Rreal = Creal * B + Cimag * sqrt(-Rreal);
582  }
583  else {
584  Rreal = B - sqrt(Rreal);
585  Rimag = Cimag * Rreal;
586  Rreal *= Creal;
587  }
588 
589  return calcMatching(Rreal, -Rimag, Z0, Freq);
590 }
591 
592 // -----------------------------------------------------------------------
593 bool MatchDialog::calc2PortMatch(double S11real, double S11imag,
594  double S22real, double S22imag, double DetReal, double DetImag,
595  double Z1, double Z2, double Freq)
596 {
597  QString Input = calcBiMatch(S11real, S11imag, S22real, S22imag,
598  DetReal, DetImag, Z1, Freq);
599  if(Input.isEmpty()) return false;
600 
601  QString Output = calcBiMatch(S22real, S22imag, S11real, S11imag,
602  DetReal, DetImag, Z2, Freq);
603  if(Output.isEmpty()) return false;
604 
605  QString Schematic =
606  "<Qucs Schematic " PACKAGE_VERSION ">\n"
607  "<Components>\n";
608 
609 
610  // ...................................................
611  // create input circuit
612  if(Input.section(':', 0,0) == "sp") {
613  // first serial than parallel component
614 
615  if(Input.section(':', 1,1).right(1) == "F")
616  Schematic += "<C C1";
617  else
618  Schematic += "<L L1";
619  Schematic += " 1 -50 10 -26 10 0 0 \"" + Input.section(':', 1,1) + "\" 1>\n";
620 
621  if(Input.section(':', 2,2).right(1) == "F")
622  Schematic += "<C C2";
623  else
624  Schematic += "<L L2";
625  Schematic += " 1 -120 80 17 -26 0 1 \"" + Input.section(':', 2,2) + "\" 1>\n";
626 
627  Schematic += "<GND * 1 -120 110 0 0 0 0>\n";
628  }
629  else {
630  // first parallel than serial component
631 
632  if(Input.section(':', 1,1).right(1) == "F")
633  Schematic += "<C C1";
634  else
635  Schematic += "<L L1";
636  Schematic += " 1 -140 10 -26 10 0 0 \"" + Input.section(':', 1,1) + "\" 1>\n";
637 
638  if(Input.section(':', 2,2).right(1) == "F")
639  Schematic += "<C C2";
640  else
641  Schematic += "<L L2";
642  Schematic += " 1 -60 70 17 -26 0 1 \"" + Input.section(':', 2,2) + "\" 1>\n";
643 
644  Schematic += "<GND * 1 -60 100 0 0 0 0>\n";
645  }
646 
647 
648  // ...................................................
649  // create output circuit
650  if(Output.section(':', 0,0) == "sp") {
651  // first serial than parallel component
652 
653  if(Output.section(':', 1,1).right(1) == "F")
654  Schematic += "<C C1";
655  else
656  Schematic += "<L L1";
657  Schematic += " 1 50 10 -26 10 0 0 \"" + Output.section(':', 1,1) + "\" 1>\n";
658 
659  if(Output.section(':', 2,2).right(1) == "F")
660  Schematic += "<C C2";
661  else
662  Schematic += "<L L2";
663  Schematic += " 1 120 80 17 -26 0 1 \"" + Output.section(':', 2,2) + "\" 1>\n";
664 
665  Schematic += "<GND * 1 120 110 0 0 0 0>\n";
666  }
667  else {
668  // ...................................................
669  // first parallel than serial component
670 
671  if(Output.section(':', 1,1).right(1) == "F")
672  Schematic += "<C C1";
673  else
674  Schematic += "<L L1";
675  Schematic += " 1 140 10 -26 10 0 0 \"" + Output.section(':', 1,1) + "\" 1>\n";
676 
677  if(Output.section(':', 2,2).right(1) == "F")
678  Schematic += "<C C2";
679  else
680  Schematic += "<L L2";
681  Schematic += " 1 60 70 17 -26 0 1 \"" + Output.section(':', 2,2) + "\" 1>\n";
682 
683  Schematic += "<GND * 1 60 100 0 0 0 0>\n";
684  }
685  Schematic += "</Components>\n"
686  "<Wires>\n";
687 
688 
689  // ...................................................
690  // create wires for input circuit
691  if(Input.section(':', 0,0) == "sp") // first serial than parallel component
692  Schematic +=
693  "<-140 10 -120 10 \"\" 0 0 0 \"\">\n"
694  "<-120 10 -80 10 \"\" 0 0 0 \"\">\n"
695  "<-120 10 -120 50 \"\" 0 0 0 \"\">\n";
696  else // first parallel than serial component
697  Schematic +=
698  "<-60 10 -60 40 \"\" 0 0 0 \"\">\n"
699  "<-60 10 -40 10 \"\" 0 0 0 \"\">\n"
700  "<-110 10 -60 10 \"\" 0 0 0 \"\">\n";
701 
702 
703  // ...................................................
704  // create wires for output circuit
705  if(Output.section(':', 0,0) == "sp") // first serial than parallel component
706  Schematic +=
707  "<140 10 120 10 \"\" 0 0 0 \"\">\n"
708  "<120 10 80 10 \"\" 0 0 0 \"\">\n"
709  "<120 10 120 50 \"\" 0 0 0 \"\">\n";
710  else // first parallel than serial component
711  Schematic +=
712  "<60 10 60 40 \"\" 0 0 0 \"\">\n"
713  "<60 10 40 10 \"\" 0 0 0 \"\">\n"
714  "<110 10 60 10 \"\" 0 0 0 \"\">\n";
715 
716  Schematic +=
717  "</Wires>\n"
718  "<Diagrams>\n"
719  "</Diagrams>\n"
720  "<Paintings>\n"
721  " <Text -200 -10 12 #000000 0 \"Port 1\">\n"
722  " <Text -20 -10 12 #000000 0 \"device\">\n"
723  " <Text 160 -10 12 #000000 0 \"Port 2\">\n"
724  "</Paintings>\n";
725 
726  QApplication::clipboard()->setText(Schematic, QClipboard::Clipboard);
727  return true;
728 }