Qucs-GUI
0.0.19
|
00001 /*************************************************************************** 00002 matchdialog.cpp 00003 ----------------- 00004 begin : Fri Jul 22 2005 00005 copyright : (C) 2005 by Michael Margraf 00006 email : michael.margraf@alumni.tu-berlin.de 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00018 #ifdef HAVE_CONFIG_H 00019 # include <config.h> 00020 #endif 00021 00022 #include "matchdialog.h" 00023 #include "main.h" 00024 #include "qucs.h" 00025 #include "element.h" 00026 #include "../components/capacitor.h" 00027 #include "../components/inductor.h" 00028 #include "../components/ground.h" 00029 #include "misc.h" 00030 00031 #include <QLabel> 00032 #include <QHBoxLayout> 00033 #include <QVBoxLayout> 00034 #include <QLineEdit> 00035 #include <QComboBox> 00036 #include <QCheckBox> 00037 #include <QValidator> 00038 #include <QPushButton> 00039 #include <QMessageBox> 00040 #include <QApplication> 00041 #include <QClipboard> 00042 #include <QGroupBox> 00043 00044 #include <cmath> 00045 00046 00047 MatchDialog::MatchDialog(QWidget *parent) 00048 : QDialog(parent) 00049 { 00050 setWindowTitle(tr("Create Matching Circuit")); 00051 DoubleVal = new QDoubleValidator(this); 00052 00053 all = new QVBoxLayout(this); 00054 00055 TwoCheck = new QCheckBox(tr("calculate two-port matching")); 00056 all->addWidget(TwoCheck); 00057 TwoCheck->setChecked(true); 00058 connect(TwoCheck, SIGNAL(toggled(bool)), SLOT(slotSetTwoPort(bool))); 00059 00060 // ........................................................... 00061 QGroupBox *ImpBox = new QGroupBox(tr("Reference Impedance")); 00062 all->addWidget(ImpBox); 00063 QHBoxLayout *ImpLayout = new QHBoxLayout(); 00064 Port1Label = new QLabel(tr("Port 1")); 00065 Ref1Edit = new QLineEdit("50"); 00066 Ref1Edit->setValidator(DoubleVal); 00067 Ohm1Label = new QLabel(tr("ohms")); 00068 connect(Ref1Edit, SIGNAL(textChanged(const QString&)), 00069 SLOT(slotImpedanceChanged(const QString&))); 00070 Port2Label = new QLabel(tr("Port 2")); 00071 Ref2Edit = new QLineEdit("50"); 00072 Ref2Edit->setValidator(DoubleVal); 00073 Ohm2Label = new QLabel(tr("ohms")); 00074 ImpLayout->addWidget(Port1Label); 00075 ImpLayout->addWidget(Ref1Edit); 00076 ImpLayout->addWidget(Ohm1Label); 00077 ImpLayout->addSpacing(50); 00078 ImpLayout->addWidget(Port2Label); 00079 ImpLayout->addWidget(Ref2Edit); 00080 ImpLayout->addWidget(Ohm2Label); 00081 ImpBox->setLayout(ImpLayout); 00082 00083 // ........................................................... 00084 QGroupBox *SParBox = new QGroupBox(tr("S Parameter")); 00085 all->addWidget(SParBox); 00086 QVBoxLayout *SParLayout = new QVBoxLayout(); 00087 SParBox->setLayout(SParLayout); 00088 00089 QHBoxLayout *h1 = new QHBoxLayout(); 00090 h1->setSpacing(3); 00091 FormatLabel = new QLabel(tr("Input format")); 00092 h1->addWidget(FormatLabel); 00093 FormatCombo = new QComboBox(); 00094 h1->addWidget(FormatCombo); 00095 FormatCombo->insertItem(tr("real/imag")); 00096 FormatCombo->insertItem(tr("mag/deg")); 00097 connect(FormatCombo, SIGNAL(activated(int)), SLOT(slotChangeMode(int))); 00098 h1->addStretch(5); 00099 SParLayout->addLayout(h1); 00100 00101 QHBoxLayout *h3 = new QHBoxLayout(); 00102 h3->setSpacing(3); 00103 QVBoxLayout *VBox1 = new QVBoxLayout(); 00104 h3->addLayout(VBox1); 00105 S11Label = new QLabel(tr("S11")); 00106 S21Label = new QLabel(tr("S21")); 00107 VBox1->addWidget(S11Label); 00108 VBox1->addWidget(S21Label); 00109 QVBoxLayout *VBox2 = new QVBoxLayout(); 00110 h3->addLayout(VBox2); 00111 S11magEdit = new QLineEdit("0.5"); 00112 S11magEdit->setValidator(DoubleVal); 00113 S21magEdit = new QLineEdit("0.5"); 00114 S21magEdit->setValidator(DoubleVal); 00115 VBox2->addWidget(S11magEdit); 00116 VBox2->addWidget(S21magEdit); 00117 QVBoxLayout *VBox3 = new QVBoxLayout(); 00118 h3->addLayout(VBox3); 00119 S11sLabel = new QLabel("+j"); 00120 S21sLabel = new QLabel("+j"); 00121 VBox3->addWidget(S11sLabel); 00122 VBox3->addWidget(S21sLabel); 00123 QVBoxLayout *VBox4 = new QVBoxLayout(); 00124 h3->addLayout(VBox4); 00125 S11degEdit = new QLineEdit("0"); 00126 S11degEdit->setValidator(DoubleVal); 00127 S21degEdit = new QLineEdit("0"); 00128 S21degEdit->setValidator(DoubleVal); 00129 VBox4->addWidget(S11degEdit); 00130 VBox4->addWidget(S21degEdit); 00131 QVBoxLayout *VBox5 = new QVBoxLayout(); 00132 h3->addLayout(VBox5); 00133 S11uLabel = new QLabel(" "); 00134 S21uLabel = new QLabel(" "); 00135 VBox5->addWidget(S11uLabel); 00136 VBox5->addWidget(S21uLabel); 00137 h3->addStretch(5); 00138 QVBoxLayout *VBox6 = new QVBoxLayout(); 00139 h3->addLayout(VBox6); 00140 S12Label = new QLabel(tr("S12")); 00141 S22Label = new QLabel(tr("S22")); 00142 VBox6->addWidget(S12Label); 00143 VBox6->addWidget(S22Label); 00144 QVBoxLayout *VBox7 = new QVBoxLayout(); 00145 h3->addLayout(VBox7); 00146 S12magEdit = new QLineEdit("0"); 00147 S12magEdit->setValidator(DoubleVal); 00148 S22magEdit = new QLineEdit("0.5"); 00149 S22magEdit->setValidator(DoubleVal); 00150 VBox7->addWidget(S12magEdit); 00151 VBox7->addWidget(S22magEdit); 00152 QVBoxLayout *VBox8 = new QVBoxLayout(); 00153 h3->addLayout(VBox8); 00154 S12sLabel = new QLabel("+j"); 00155 S22sLabel = new QLabel("+j"); 00156 VBox8->addWidget(S12sLabel); 00157 VBox8->addWidget(S22sLabel); 00158 QVBoxLayout *VBox9 = new QVBoxLayout(); 00159 h3->addLayout(VBox9); 00160 S12degEdit = new QLineEdit("0"); 00161 S12degEdit->setValidator(DoubleVal); 00162 S22degEdit = new QLineEdit("0"); 00163 S22degEdit->setValidator(DoubleVal); 00164 VBox9->addWidget(S12degEdit); 00165 VBox9->addWidget(S22degEdit); 00166 QVBoxLayout *VBox0 = new QVBoxLayout(); 00167 h3->addLayout(VBox0); 00168 S12uLabel = new QLabel(" "); 00169 S22uLabel = new QLabel(" "); 00170 VBox0->addWidget(S12uLabel); 00171 VBox0->addWidget(S22uLabel); 00172 SParLayout->addLayout(h3); 00173 00174 connect(S21magEdit, SIGNAL(textChanged(const QString&)), 00175 SLOT(slotImpedanceChanged(const QString&))); 00176 connect(S21degEdit, SIGNAL(textChanged(const QString&)), 00177 SLOT(slotImpedanceChanged(const QString&))); 00178 connect(S11magEdit, SIGNAL(textChanged(const QString&)), 00179 SLOT(slotReflexionChanged(const QString&))); 00180 connect(S11degEdit, SIGNAL(textChanged(const QString&)), 00181 SLOT(slotReflexionChanged(const QString&))); 00182 00183 00184 QHBoxLayout *h2 = new QHBoxLayout(); 00185 h2->setSpacing(3); 00186 FrequencyLabel = new QLabel(tr("Frequency:")); 00187 FrequencyEdit = new QLineEdit(); 00188 FrequencyEdit->setValidator(DoubleVal); 00189 h2->addWidget(FrequencyLabel); 00190 h2->addWidget(FrequencyEdit); 00191 UnitCombo = new QComboBox(); 00192 UnitCombo->insertItem("Hz"); 00193 UnitCombo->insertItem("kHz"); 00194 UnitCombo->insertItem("MHz"); 00195 UnitCombo->insertItem("GHz"); 00196 h2->addWidget(UnitCombo); 00197 h2->addStretch(5); 00198 SParLayout->addLayout(h2); 00199 00200 // ........................................................... 00201 QHBoxLayout *h0 = new QHBoxLayout(); 00202 h0->setSpacing(5); 00203 all->addLayout(h0); 00204 h0->addStretch(5); 00205 QPushButton *buttCreate = new QPushButton(tr("Create")); 00206 QPushButton *buttCancel = new QPushButton(tr("Cancel")); 00207 h0->addWidget(buttCreate); 00208 h0->addWidget(buttCancel); 00209 connect(buttCreate, SIGNAL(clicked()), SLOT(slotButtCreate())); 00210 connect(buttCancel, SIGNAL(clicked()), SLOT(reject())); 00211 00212 slotReflexionChanged(""); // calculate impedance 00213 setFrequency(1e9); // set 1GHz 00214 resize(520, 100); 00215 } 00216 00217 MatchDialog::~MatchDialog() 00218 { 00219 delete all; 00220 delete DoubleVal; 00221 } 00222 00223 // ----------------------------------------------------------------------- 00224 void MatchDialog::setFrequency(double Freq_) 00225 { 00226 int Expo = int(log10(Freq_) / 3.0); 00227 if(Expo < 0) Expo = 0; 00228 else if(Expo > 3) Expo = 3; 00229 UnitCombo->setCurrentItem(Expo); 00230 Freq_ /= pow(10.0, double(3*Expo)); 00231 FrequencyEdit->setText(QString::number(Freq_)); 00232 } 00233 00234 // ----------------------------------------------------------------------- 00235 // Is called when the checkbox for two-port matching changes. 00236 void MatchDialog::slotSetTwoPort(bool on) 00237 { 00238 if(on) { // two-port matching ? 00239 S11Label->setText(tr("S11")); 00240 S21Label->setText(tr("S21")); 00241 S12magEdit->setEnabled(true); 00242 S22magEdit->setEnabled(true); 00243 S12degEdit->setEnabled(true); 00244 S22degEdit->setEnabled(true); 00245 S12Label->setEnabled(true); 00246 S22Label->setEnabled(true); 00247 S12sLabel->setEnabled(true); 00248 S22sLabel->setEnabled(true); 00249 S12degEdit->setEnabled(true); 00250 S22degEdit->setEnabled(true); 00251 S12uLabel->setEnabled(true); 00252 S22uLabel->setEnabled(true); 00253 Port2Label->setEnabled(true); 00254 Ref2Edit->setEnabled(true); 00255 Ohm2Label->setEnabled(true); 00256 } 00257 else { 00258 S11Label->setText(tr("Reflexion Coefficient")); 00259 S21Label->setText(tr("Impedance (ohms)")); 00260 S12magEdit->setEnabled(false); 00261 S22magEdit->setEnabled(false); 00262 S12degEdit->setEnabled(false); 00263 S22degEdit->setEnabled(false); 00264 S12Label->setEnabled(false); 00265 S22Label->setEnabled(false); 00266 S12sLabel->setEnabled(false); 00267 S22sLabel->setEnabled(false); 00268 S12degEdit->setEnabled(false); 00269 S22degEdit->setEnabled(false); 00270 S12uLabel->setEnabled(false); 00271 S22uLabel->setEnabled(false); 00272 Port2Label->setEnabled(false); 00273 Ref2Edit->setEnabled(false); 00274 Ohm2Label->setEnabled(false); 00275 } 00276 } 00277 00278 // ----------------------------------------------------------------------- 00279 // Is called when the combobox changes between mag/deg and real/imag. 00280 void MatchDialog::slotChangeMode(int Index) 00281 { 00282 if(Index) { // polar ? 00283 S11sLabel->setText("/"); 00284 S12sLabel->setText("/"); 00285 S21sLabel->setText("/"); 00286 S22sLabel->setText("/"); 00287 S11uLabel->setText(QString::fromUtf8("°")); 00288 S12uLabel->setText(QString::fromUtf8("°")); 00289 S21uLabel->setText(QString::fromUtf8("°")); 00290 S22uLabel->setText(QString::fromUtf8("°")); 00291 00292 double Real = S11magEdit->text().toDouble(); 00293 double Imag = S11degEdit->text().toDouble(); 00294 c2p(Real, Imag); 00295 S11magEdit->setText(QString::number(Real)); 00296 S11degEdit->setText(QString::number(Imag)); 00297 00298 Real = S12magEdit->text().toDouble(); 00299 Imag = S12degEdit->text().toDouble(); 00300 c2p(Real, Imag); 00301 S12magEdit->setText(QString::number(Real)); 00302 S12degEdit->setText(QString::number(Imag)); 00303 00304 Real = S21magEdit->text().toDouble(); 00305 Imag = S21degEdit->text().toDouble(); 00306 c2p(Real, Imag); 00307 S21magEdit->setText(QString::number(Real)); 00308 S21degEdit->setText(QString::number(Imag)); 00309 00310 Real = S22magEdit->text().toDouble(); 00311 Imag = S22degEdit->text().toDouble(); 00312 c2p(Real, Imag); 00313 S22magEdit->setText(QString::number(Real)); 00314 S22degEdit->setText(QString::number(Imag)); 00315 } 00316 else { // cartesian 00317 S11sLabel->setText("+j"); 00318 S12sLabel->setText("+j"); 00319 S21sLabel->setText("+j"); 00320 S22sLabel->setText("+j"); 00321 S11uLabel->setText(" "); 00322 S12uLabel->setText(" "); 00323 S21uLabel->setText(" "); 00324 S22uLabel->setText(" "); 00325 00326 double Mag = S11magEdit->text().toDouble(); 00327 double Phase = S11degEdit->text().toDouble(); 00328 p2c(Mag, Phase); 00329 S11magEdit->setText(QString::number(Mag)); 00330 S11degEdit->setText(QString::number(Phase)); 00331 00332 Mag = S12magEdit->text().toDouble(); 00333 Phase = S12degEdit->text().toDouble(); 00334 p2c(Mag, Phase); 00335 S12magEdit->setText(QString::number(Mag)); 00336 S12degEdit->setText(QString::number(Phase)); 00337 00338 Mag = S21magEdit->text().toDouble(); 00339 Phase = S21degEdit->text().toDouble(); 00340 p2c(Mag, Phase); 00341 S21magEdit->setText(QString::number(Mag)); 00342 S21degEdit->setText(QString::number(Phase)); 00343 00344 Mag = S22magEdit->text().toDouble(); 00345 Phase = S22degEdit->text().toDouble(); 00346 p2c(Mag, Phase); 00347 S22magEdit->setText(QString::number(Mag)); 00348 S22degEdit->setText(QString::number(Phase)); 00349 } 00350 } 00351 00352 // ----------------------------------------------------------------------- 00353 // Is called if the user changed the impedance. -> The reflexion 00354 // coefficient is calculated. 00355 void MatchDialog::slotImpedanceChanged(const QString&) 00356 { 00357 if(TwoCheck->isChecked()) return; 00358 00359 double Z0 = Ref1Edit->text().toDouble(); 00360 double Real = S21magEdit->text().toDouble(); 00361 double Imag = S21degEdit->text().toDouble(); 00362 z2r(Real, Imag, Z0); 00363 S11magEdit->blockSignals(true); // do not call "changed-slot" 00364 S11magEdit->setText(QString::number(Real)); 00365 S11magEdit->blockSignals(false); 00366 S11degEdit->blockSignals(true); // do not call "changed-slot" 00367 S11degEdit->setText(QString::number(Imag)); 00368 S11degEdit->blockSignals(false); 00369 } 00370 00371 // ----------------------------------------------------------------------- 00372 // Is called if the user changed the reflexion coefficient. -> The impedance 00373 // is calculated. 00374 void MatchDialog::slotReflexionChanged(const QString&) 00375 { 00376 if(TwoCheck->isChecked()) return; 00377 00378 double Z0 = Ref1Edit->text().toDouble(); 00379 double Real = S11magEdit->text().toDouble(); 00380 double Imag = S11degEdit->text().toDouble(); 00381 r2z(Real, Imag, Z0); 00382 S21magEdit->blockSignals(true); // do not call "changed-slot" 00383 S21magEdit->setText(QString::number(Real)); 00384 S21magEdit->blockSignals(false); 00385 S21degEdit->blockSignals(true); // do not call "changed-slot" 00386 S21degEdit->setText(QString::number(Imag)); 00387 S21degEdit->blockSignals(false); 00388 } 00389 00390 // ----------------------------------------------------------------------- 00391 // Is called if the "Create"-button is pressed. 00392 void MatchDialog::slotButtCreate() 00393 { 00394 double Z1 = Ref1Edit->text().toDouble(); 00395 double Z2 = Ref2Edit->text().toDouble(); 00396 double Freq = FrequencyEdit->text().toDouble() * 00397 pow(10.0, 3.0*double(UnitCombo->currentItem())); 00398 00399 double S11real = S11magEdit->text().toDouble(); 00400 double S11imag = S11degEdit->text().toDouble(); 00401 double S12real = S12magEdit->text().toDouble(); 00402 double S12imag = S12degEdit->text().toDouble(); 00403 double S21real = S21magEdit->text().toDouble(); 00404 double S21imag = S21degEdit->text().toDouble(); 00405 double S22real = S22magEdit->text().toDouble(); 00406 double S22imag = S22degEdit->text().toDouble(); 00407 if(FormatCombo->currentItem()) { // are they polar ? 00408 p2c(S11real, S11imag); 00409 p2c(S12real, S12imag); 00410 p2c(S21real, S21imag); 00411 p2c(S22real, S22imag); 00412 } 00413 00414 if(TwoCheck->isChecked()) { // two-port matching ? 00415 // determinante of S-parameter matrix 00416 double DetReal = S11real*S22real - S11imag*S22imag 00417 - S12real*S21real + S12imag*S21imag; 00418 double DetImag = S11real*S22imag + S11imag*S22real 00419 - S12real*S21imag - S12imag*S21real; 00420 00421 if(!MatchDialog::calc2PortMatch(S11real, S11imag, S22real, S22imag, 00422 DetReal, DetImag, Z1, Z2, Freq)) 00423 return; 00424 } 00425 else 00426 if(!calcMatchingCircuit(S11real, S11imag, Z1, Freq)) 00427 return; 00428 00429 QucsMain->slotEditPaste(true); 00430 accept(); 00431 } 00432 00433 00434 // ----------------------------------------------------------------------- 00435 // transform real/imag into mag/deg (cartesian to polar) 00436 void MatchDialog::c2p(double& Real, double& Imag) 00437 { 00438 double Real_ = Real; 00439 Real = sqrt(Real*Real + Imag*Imag); // magnitude 00440 Imag = 180.0/pi * atan2(Imag, Real_); // phase in degree 00441 } 00442 00443 // ----------------------------------------------------------------------- 00444 // transform mag/deg into real/imag (polar to cartesian) 00445 void MatchDialog::p2c(double& Real, double& Imag) 00446 { 00447 double Real_ = Real; 00448 Real = Real_ * cos(Imag * pi/180.0); // real part 00449 Imag = Real_ * sin(Imag * pi/180.0); // imaginary part 00450 } 00451 00452 // ----------------------------------------------------------------------- 00453 // transform reflexion coefficient into impedance 00454 void MatchDialog::r2z(double& Real, double& Imag, double Z0) 00455 { 00456 double tmp = Z0 / ((1.0-Real)*(1.0-Real) + Imag*Imag); 00457 Real = (1.0 - Real*Real - Imag*Imag) * tmp; 00458 Imag *= 2.0 * tmp; 00459 } 00460 00461 // ----------------------------------------------------------------------- 00462 // transform impedance into reflexion coefficient 00463 void MatchDialog::z2r(double& Real, double& Imag, double Z0) 00464 { 00465 double tmp = (Real+Z0)*(Real+Z0) + Imag*Imag; 00466 Real = (Real*Real + Imag*Imag - Z0*Z0) / tmp; 00467 Imag *= 2.0 * Z0 / tmp; 00468 } 00469 00470 // ----------------------------------------------------------------------- 00471 // Calculate matching circuit. Returns string like "sp:1nH:5pF" 00472 QString MatchDialog::calcMatching(double r_real, double r_imag, 00473 double Z0, double Freq) 00474 { 00475 double Zreal = r_real, Zimag = r_imag; 00476 r2z(Zreal, Zimag, Z0); 00477 00478 if (Zreal < 0.0) { 00479 if (Zreal < -1e-13) { 00480 QMessageBox::critical(0, tr("Error"), 00481 tr("Real part of impedance must be greater zero,\nbut is %1 !").arg(Zreal)); 00482 return QString(""); // matching not possible 00483 } 00484 00485 // In high-Q circuits, Zreal often becomes somewhat about -1e-16 00486 // because of numerical inaccuracy. 00487 Zreal = 0.0; 00488 } 00489 00490 00491 double X1, X2, Omega = 2.0 * pi * Freq; 00492 QString Str; 00493 if(r_real < 0) { 00494 // ................................................... 00495 // first serial than parallel component (possible if Zreal <= Z0) 00496 Str = "sp"; 00497 X1 = sqrt(Zreal * (Z0 - Zreal)); 00498 if (Zimag < 0.0) X1 *= -1.0; // always use shortest matching path 00499 X1 -= Zimag; 00500 00501 // parallel component 00502 X2 = (Zimag + X1) / (Zreal*Zreal + (Zimag + X1)*(Zimag + X1)); 00503 } 00504 else { 00505 00506 Str = "ps"; 00507 X1 = Zreal + Zimag*Zimag / Zreal - Z0; 00508 // ................................................... 00509 // first parallel than serial component (possible if X >= 0.0) 00510 X1 = sqrt(Z0 * X1); 00511 if (Zimag > 0.0) X1 *= -1.0; // always use shortest matching path 00512 00513 // parallel component 00514 X2 = Zimag / (Zreal*Zreal + Zimag*Zimag) + X1 / (Z0*Z0 + X1*X1); 00515 } 00516 00517 00518 // serial component 00519 if (X1 < 0.0) // capacitance ? 00520 Str += ':' + misc::num2str(-1.0 / Omega / X1) + 'F'; 00521 else // inductance 00522 Str += ':' + misc::num2str(X1 / Omega) + 'H'; 00523 00524 // parallel component 00525 if (X2 < 0.0) // inductance ? 00526 Str += ':' + misc::num2str(-1.0 / Omega / X2) + 'H'; 00527 else // capacitance 00528 Str += ':' + misc::num2str(X2 / Omega) + 'F'; 00529 00530 return Str; 00531 } 00532 00533 // ----------------------------------------------------------------------- 00534 bool MatchDialog::calcMatchingCircuit(double r_real, double r_imag, 00535 double Z0, double Freq) 00536 { 00537 QString Schematic = 00538 "<Qucs Schematic " PACKAGE_VERSION ">\n" 00539 "<Components>\n"; 00540 00541 00542 QString Str = calcMatching(r_real, r_imag, Z0, Freq); 00543 if(Str.isEmpty()) return false; 00544 00545 if(Str.section(':', 0,0) == "sp") { 00546 // ................................................... 00547 // first serial than parallel component 00548 00549 if(Str.section(':', 1,1).right(1) == "F") 00550 Schematic += "<C C1"; 00551 else 00552 Schematic += "<L L1"; 00553 Schematic += " 1 100 10 -26 10 0 0 \"" + Str.section(':', 1,1) + "\" 1>\n"; 00554 00555 if(Str.section(':', 2,2).right(1) == "F") 00556 Schematic += "<C C2"; 00557 else 00558 Schematic += "<L L2"; 00559 Schematic += " 1 30 80 17 -26 0 1 \"" + Str.section(':', 2,2) + "\" 1>\n"; 00560 00561 Schematic += 00562 "<GND * 1 30 110 0 0 0 0>\n" 00563 "</Components>\n" 00564 "<Wires>\n" 00565 "<10 10 30 10 \"\" 0 0 0 \"\">\n" 00566 "<30 10 70 10 \"\" 0 0 0 \"\">\n" 00567 "<30 10 30 50 \"\" 0 0 0 \"\">\n"; 00568 } 00569 else { 00570 // ................................................... 00571 // first parallel than serial component 00572 00573 if(Str.section(':', 1,1).right(1) == "F") 00574 Schematic += "<C C1"; 00575 else 00576 Schematic += "<L L1"; 00577 Schematic += " 1 50 10 -26 10 0 0 \"" + Str.section(':', 1,1) + "\" 1>\n"; 00578 00579 if(Str.section(':', 2,2).right(1) == "F") 00580 Schematic += "<C C2"; 00581 else 00582 Schematic += "<L L2"; 00583 Schematic += " 1 130 70 17 -26 0 1 \"" + Str.section(':', 2,2) + "\" 1>\n"; 00584 00585 Schematic += 00586 "<GND * 1 130 100 0 0 0 0>\n" 00587 "</Components>\n" 00588 "<Wires>\n" 00589 "<130 10 130 40 \"\" 0 0 0 \"\">\n" 00590 "<130 10 150 10 \"\" 0 0 0 \"\">\n" 00591 "<80 10 130 10 \"\" 0 0 0 \"\">\n"; 00592 } 00593 00594 Schematic += QString( 00595 "</Wires>\n" 00596 "<Diagrams>\n" 00597 "</Diagrams>\n" 00598 "<Paintings>\n" 00599 " <Text -20 -10 12 #000000 0 \"%1 Ohm\">\n" 00600 " <Text 120 -10 12 #000000 0 \"device\">\n" 00601 "</Paintings>\n").arg(Z0); 00602 00603 QApplication::clipboard()->setText(Schematic, QClipboard::Clipboard); 00604 return true; 00605 } 00606 00607 // ----------------------------------------------------------------------- 00608 // Fundamental calculations for concurrent 2-port matching. 00609 QString MatchDialog::calcBiMatch(double S11real, double S11imag, 00610 double S22real, double S22imag, double DetReal, double DetImag, 00611 double Z0, double Freq) 00612 { 00613 double B = 1.0 + S11real*S11real + S11imag*S11imag 00614 - S22real*S22real - S22imag*S22imag 00615 - DetReal*DetReal - DetImag*DetImag; 00616 double Creal = S11real - S22real*DetReal - S22imag*DetImag; 00617 double Cimag = S22real*DetImag - S11imag - S22imag*DetReal; 00618 double Cmag = 2.0 * (Creal*Creal + Cimag*Cimag); 00619 Creal /= Cmag; 00620 Cimag /= Cmag; 00621 00622 double Rreal = B*B - 2.0*Cmag; 00623 double Rimag; 00624 if(Rreal < 0.0) { 00625 Rimag = Cimag * B - Creal * sqrt(-Rreal); 00626 Rreal = Creal * B + Cimag * sqrt(-Rreal); 00627 } 00628 else { 00629 Rreal = B - sqrt(Rreal); 00630 Rimag = Cimag * Rreal; 00631 Rreal *= Creal; 00632 } 00633 00634 return calcMatching(Rreal, -Rimag, Z0, Freq); 00635 } 00636 00637 // ----------------------------------------------------------------------- 00638 bool MatchDialog::calc2PortMatch(double S11real, double S11imag, 00639 double S22real, double S22imag, double DetReal, double DetImag, 00640 double Z1, double Z2, double Freq) 00641 { 00642 QString Input = calcBiMatch(S11real, S11imag, S22real, S22imag, 00643 DetReal, DetImag, Z1, Freq); 00644 if(Input.isEmpty()) return false; 00645 00646 QString Output = calcBiMatch(S22real, S22imag, S11real, S11imag, 00647 DetReal, DetImag, Z2, Freq); 00648 if(Output.isEmpty()) return false; 00649 00650 QString Schematic = 00651 "<Qucs Schematic " PACKAGE_VERSION ">\n" 00652 "<Components>\n"; 00653 00654 00655 // ................................................... 00656 // create input circuit 00657 if(Input.section(':', 0,0) == "sp") { 00658 // first serial than parallel component 00659 00660 if(Input.section(':', 1,1).right(1) == "F") 00661 Schematic += "<C C1"; 00662 else 00663 Schematic += "<L L1"; 00664 Schematic += " 1 -50 10 -26 10 0 0 \"" + Input.section(':', 1,1) + "\" 1>\n"; 00665 00666 if(Input.section(':', 2,2).right(1) == "F") 00667 Schematic += "<C C2"; 00668 else 00669 Schematic += "<L L2"; 00670 Schematic += " 1 -120 80 17 -26 0 1 \"" + Input.section(':', 2,2) + "\" 1>\n"; 00671 00672 Schematic += "<GND * 1 -120 110 0 0 0 0>\n"; 00673 } 00674 else { 00675 // first parallel than serial component 00676 00677 if(Input.section(':', 1,1).right(1) == "F") 00678 Schematic += "<C C1"; 00679 else 00680 Schematic += "<L L1"; 00681 Schematic += " 1 -140 10 -26 10 0 0 \"" + Input.section(':', 1,1) + "\" 1>\n"; 00682 00683 if(Input.section(':', 2,2).right(1) == "F") 00684 Schematic += "<C C2"; 00685 else 00686 Schematic += "<L L2"; 00687 Schematic += " 1 -60 70 17 -26 0 1 \"" + Input.section(':', 2,2) + "\" 1>\n"; 00688 00689 Schematic += "<GND * 1 -60 100 0 0 0 0>\n"; 00690 } 00691 00692 00693 // ................................................... 00694 // create output circuit 00695 if(Output.section(':', 0,0) == "sp") { 00696 // first serial than parallel component 00697 00698 if(Output.section(':', 1,1).right(1) == "F") 00699 Schematic += "<C C1"; 00700 else 00701 Schematic += "<L L1"; 00702 Schematic += " 1 50 10 -26 10 0 0 \"" + Output.section(':', 1,1) + "\" 1>\n"; 00703 00704 if(Output.section(':', 2,2).right(1) == "F") 00705 Schematic += "<C C2"; 00706 else 00707 Schematic += "<L L2"; 00708 Schematic += " 1 120 80 17 -26 0 1 \"" + Output.section(':', 2,2) + "\" 1>\n"; 00709 00710 Schematic += "<GND * 1 120 110 0 0 0 0>\n"; 00711 } 00712 else { 00713 // ................................................... 00714 // first parallel than serial component 00715 00716 if(Output.section(':', 1,1).right(1) == "F") 00717 Schematic += "<C C1"; 00718 else 00719 Schematic += "<L L1"; 00720 Schematic += " 1 140 10 -26 10 0 0 \"" + Output.section(':', 1,1) + "\" 1>\n"; 00721 00722 if(Output.section(':', 2,2).right(1) == "F") 00723 Schematic += "<C C2"; 00724 else 00725 Schematic += "<L L2"; 00726 Schematic += " 1 60 70 17 -26 0 1 \"" + Output.section(':', 2,2) + "\" 1>\n"; 00727 00728 Schematic += "<GND * 1 60 100 0 0 0 0>\n"; 00729 } 00730 Schematic += "</Components>\n" 00731 "<Wires>\n"; 00732 00733 00734 // ................................................... 00735 // create wires for input circuit 00736 if(Input.section(':', 0,0) == "sp") // first serial than parallel component 00737 Schematic += 00738 "<-140 10 -120 10 \"\" 0 0 0 \"\">\n" 00739 "<-120 10 -80 10 \"\" 0 0 0 \"\">\n" 00740 "<-120 10 -120 50 \"\" 0 0 0 \"\">\n"; 00741 else // first parallel than serial component 00742 Schematic += 00743 "<-60 10 -60 40 \"\" 0 0 0 \"\">\n" 00744 "<-60 10 -40 10 \"\" 0 0 0 \"\">\n" 00745 "<-110 10 -60 10 \"\" 0 0 0 \"\">\n"; 00746 00747 00748 // ................................................... 00749 // create wires for output circuit 00750 if(Output.section(':', 0,0) == "sp") // first serial than parallel component 00751 Schematic += 00752 "<140 10 120 10 \"\" 0 0 0 \"\">\n" 00753 "<120 10 80 10 \"\" 0 0 0 \"\">\n" 00754 "<120 10 120 50 \"\" 0 0 0 \"\">\n"; 00755 else // first parallel than serial component 00756 Schematic += 00757 "<60 10 60 40 \"\" 0 0 0 \"\">\n" 00758 "<60 10 40 10 \"\" 0 0 0 \"\">\n" 00759 "<110 10 60 10 \"\" 0 0 0 \"\">\n"; 00760 00761 Schematic += 00762 "</Wires>\n" 00763 "<Diagrams>\n" 00764 "</Diagrams>\n" 00765 "<Paintings>\n" 00766 " <Text -200 -10 12 #000000 0 \"Port 1\">\n" 00767 " <Text -20 -10 12 #000000 0 \"device\">\n" 00768 " <Text 160 -10 12 #000000 0 \"Port 2\">\n" 00769 "</Paintings>\n"; 00770 00771 QApplication::clipboard()->setText(Schematic, QClipboard::Clipboard); 00772 return true; 00773 }