2005-08-01 06:08:52 +00:00
|
|
|
/***************************************************************************
|
|
|
|
matchdialog.cpp
|
|
|
|
-----------------
|
|
|
|
begin : Fri Jul 22 2005
|
|
|
|
copyright : (C) 2005 by Michael Margraf
|
|
|
|
email : michael.margraf@alumni.tu-berlin.de
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
2013-06-01 12:33:02 +02:00
|
|
|
|
2005-08-01 06:08:52 +00:00
|
|
|
#include "matchdialog.h"
|
2006-03-28 06:10:52 +00:00
|
|
|
#include "main.h"
|
2005-08-01 06:08:52 +00:00
|
|
|
#include "qucs.h"
|
|
|
|
#include "element.h"
|
|
|
|
#include "../components/capacitor.h"
|
|
|
|
#include "../components/inductor.h"
|
|
|
|
#include "../components/ground.h"
|
2014-11-12 03:42:14 +08:00
|
|
|
#include "misc.h"
|
2005-08-01 06:08:52 +00:00
|
|
|
|
2013-06-01 12:33:02 +02:00
|
|
|
#include <QLabel>
|
|
|
|
#include <QHBoxLayout>
|
|
|
|
#include <QVBoxLayout>
|
|
|
|
#include <QLineEdit>
|
|
|
|
#include <QComboBox>
|
|
|
|
#include <QCheckBox>
|
|
|
|
#include <QValidator>
|
|
|
|
#include <QPushButton>
|
|
|
|
#include <QMessageBox>
|
|
|
|
#include <QApplication>
|
|
|
|
#include <QClipboard>
|
|
|
|
#include <QGroupBox>
|
2005-08-01 06:08:52 +00:00
|
|
|
|
2015-01-09 13:53:16 +01:00
|
|
|
#include <cmath>
|
2014-11-04 13:57:06 +08:00
|
|
|
|
2005-08-01 06:08:52 +00:00
|
|
|
|
2005-09-12 12:01:40 +00:00
|
|
|
MatchDialog::MatchDialog(QWidget *parent)
|
2014-11-26 17:54:17 +01:00
|
|
|
: QDialog(parent)
|
2005-08-01 06:08:52 +00:00
|
|
|
{
|
2013-06-01 12:33:02 +02:00
|
|
|
setWindowTitle(tr("Create Matching Circuit"));
|
2005-08-01 06:08:52 +00:00
|
|
|
DoubleVal = new QDoubleValidator(this);
|
|
|
|
|
2013-06-01 12:33:02 +02:00
|
|
|
all = new QVBoxLayout(this);
|
2005-09-12 12:01:40 +00:00
|
|
|
|
2013-06-01 12:33:02 +02:00
|
|
|
TwoCheck = new QCheckBox(tr("calculate two-port matching"));
|
2005-09-12 12:01:40 +00:00
|
|
|
all->addWidget(TwoCheck);
|
|
|
|
TwoCheck->setChecked(true);
|
|
|
|
connect(TwoCheck, SIGNAL(toggled(bool)), SLOT(slotSetTwoPort(bool)));
|
|
|
|
|
2005-08-01 06:08:52 +00:00
|
|
|
// ...........................................................
|
2013-06-01 12:33:02 +02:00
|
|
|
QGroupBox *ImpBox = new QGroupBox(tr("Reference Impedance"));
|
2005-09-12 12:01:40 +00:00
|
|
|
all->addWidget(ImpBox);
|
2013-06-01 12:33:02 +02:00
|
|
|
QHBoxLayout *ImpLayout = new QHBoxLayout();
|
|
|
|
Port1Label = new QLabel(tr("Port 1"));
|
|
|
|
Ref1Edit = new QLineEdit("50");
|
2005-09-12 12:01:40 +00:00
|
|
|
Ref1Edit->setValidator(DoubleVal);
|
2013-06-01 12:33:02 +02:00
|
|
|
Ohm1Label = new QLabel(tr("ohms"));
|
2005-09-12 12:01:40 +00:00
|
|
|
connect(Ref1Edit, SIGNAL(textChanged(const QString&)),
|
|
|
|
SLOT(slotImpedanceChanged(const QString&)));
|
2013-06-01 12:33:02 +02:00
|
|
|
Port2Label = new QLabel(tr("Port 2"));
|
|
|
|
Ref2Edit = new QLineEdit("50");
|
2005-09-12 12:01:40 +00:00
|
|
|
Ref2Edit->setValidator(DoubleVal);
|
2013-06-01 12:33:02 +02:00
|
|
|
Ohm2Label = new QLabel(tr("ohms"));
|
|
|
|
ImpLayout->addWidget(Port1Label);
|
|
|
|
ImpLayout->addWidget(Ref1Edit);
|
|
|
|
ImpLayout->addWidget(Ohm1Label);
|
|
|
|
ImpLayout->addSpacing(50);
|
|
|
|
ImpLayout->addWidget(Port2Label);
|
|
|
|
ImpLayout->addWidget(Ref2Edit);
|
|
|
|
ImpLayout->addWidget(Ohm2Label);
|
|
|
|
ImpBox->setLayout(ImpLayout);
|
2005-09-12 12:01:40 +00:00
|
|
|
|
|
|
|
// ...........................................................
|
2013-06-01 12:33:02 +02:00
|
|
|
QGroupBox *SParBox = new QGroupBox(tr("S Parameter"));
|
2005-09-12 12:01:40 +00:00
|
|
|
all->addWidget(SParBox);
|
2013-06-01 12:33:02 +02:00
|
|
|
QVBoxLayout *SParLayout = new QVBoxLayout();
|
|
|
|
SParBox->setLayout(SParLayout);
|
2005-09-12 12:01:40 +00:00
|
|
|
|
2013-06-01 12:33:02 +02:00
|
|
|
QHBoxLayout *h1 = new QHBoxLayout();
|
2005-09-12 12:01:40 +00:00
|
|
|
h1->setSpacing(3);
|
2013-06-01 12:33:02 +02:00
|
|
|
FormatLabel = new QLabel(tr("Input format"));
|
|
|
|
h1->addWidget(FormatLabel);
|
|
|
|
FormatCombo = new QComboBox();
|
|
|
|
h1->addWidget(FormatCombo);
|
2005-09-12 12:01:40 +00:00
|
|
|
FormatCombo->insertItem(tr("real/imag"));
|
|
|
|
FormatCombo->insertItem(tr("mag/deg"));
|
|
|
|
connect(FormatCombo, SIGNAL(activated(int)), SLOT(slotChangeMode(int)));
|
2013-06-01 12:33:02 +02:00
|
|
|
h1->addStretch(5);
|
|
|
|
SParLayout->addLayout(h1);
|
2005-09-12 12:01:40 +00:00
|
|
|
|
2013-06-01 12:33:02 +02:00
|
|
|
QHBoxLayout *h3 = new QHBoxLayout();
|
2005-09-12 12:01:40 +00:00
|
|
|
h3->setSpacing(3);
|
2013-06-01 12:33:02 +02:00
|
|
|
QVBoxLayout *VBox1 = new QVBoxLayout();
|
|
|
|
h3->addLayout(VBox1);
|
|
|
|
S11Label = new QLabel(tr("S11"));
|
|
|
|
S21Label = new QLabel(tr("S21"));
|
|
|
|
VBox1->addWidget(S11Label);
|
|
|
|
VBox1->addWidget(S21Label);
|
|
|
|
QVBoxLayout *VBox2 = new QVBoxLayout();
|
|
|
|
h3->addLayout(VBox2);
|
|
|
|
S11magEdit = new QLineEdit("0.5");
|
2005-09-12 12:01:40 +00:00
|
|
|
S11magEdit->setValidator(DoubleVal);
|
2013-06-01 12:33:02 +02:00
|
|
|
S21magEdit = new QLineEdit("0.5");
|
2005-09-12 12:01:40 +00:00
|
|
|
S21magEdit->setValidator(DoubleVal);
|
2013-06-01 12:33:02 +02:00
|
|
|
VBox2->addWidget(S11magEdit);
|
|
|
|
VBox2->addWidget(S21magEdit);
|
|
|
|
QVBoxLayout *VBox3 = new QVBoxLayout();
|
|
|
|
h3->addLayout(VBox3);
|
|
|
|
S11sLabel = new QLabel("+j");
|
|
|
|
S21sLabel = new QLabel("+j");
|
|
|
|
VBox3->addWidget(S11sLabel);
|
|
|
|
VBox3->addWidget(S21sLabel);
|
|
|
|
QVBoxLayout *VBox4 = new QVBoxLayout();
|
|
|
|
h3->addLayout(VBox4);
|
|
|
|
S11degEdit = new QLineEdit("0");
|
2005-09-12 12:01:40 +00:00
|
|
|
S11degEdit->setValidator(DoubleVal);
|
2013-06-01 12:33:02 +02:00
|
|
|
S21degEdit = new QLineEdit("0");
|
2005-09-12 12:01:40 +00:00
|
|
|
S21degEdit->setValidator(DoubleVal);
|
2013-06-01 12:33:02 +02:00
|
|
|
VBox4->addWidget(S11degEdit);
|
|
|
|
VBox4->addWidget(S21degEdit);
|
|
|
|
QVBoxLayout *VBox5 = new QVBoxLayout();
|
|
|
|
h3->addLayout(VBox5);
|
|
|
|
S11uLabel = new QLabel(" ");
|
|
|
|
S21uLabel = new QLabel(" ");
|
|
|
|
VBox5->addWidget(S11uLabel);
|
|
|
|
VBox5->addWidget(S21uLabel);
|
|
|
|
h3->addStretch(5);
|
|
|
|
QVBoxLayout *VBox6 = new QVBoxLayout();
|
|
|
|
h3->addLayout(VBox6);
|
|
|
|
S12Label = new QLabel(tr("S12"));
|
|
|
|
S22Label = new QLabel(tr("S22"));
|
|
|
|
VBox6->addWidget(S12Label);
|
|
|
|
VBox6->addWidget(S22Label);
|
|
|
|
QVBoxLayout *VBox7 = new QVBoxLayout();
|
|
|
|
h3->addLayout(VBox7);
|
|
|
|
S12magEdit = new QLineEdit("0");
|
2005-09-12 12:01:40 +00:00
|
|
|
S12magEdit->setValidator(DoubleVal);
|
2013-06-01 12:33:02 +02:00
|
|
|
S22magEdit = new QLineEdit("0.5");
|
2005-09-12 12:01:40 +00:00
|
|
|
S22magEdit->setValidator(DoubleVal);
|
2013-06-01 12:33:02 +02:00
|
|
|
VBox7->addWidget(S12magEdit);
|
|
|
|
VBox7->addWidget(S22magEdit);
|
|
|
|
QVBoxLayout *VBox8 = new QVBoxLayout();
|
|
|
|
h3->addLayout(VBox8);
|
|
|
|
S12sLabel = new QLabel("+j");
|
|
|
|
S22sLabel = new QLabel("+j");
|
|
|
|
VBox8->addWidget(S12sLabel);
|
|
|
|
VBox8->addWidget(S22sLabel);
|
|
|
|
QVBoxLayout *VBox9 = new QVBoxLayout();
|
|
|
|
h3->addLayout(VBox9);
|
|
|
|
S12degEdit = new QLineEdit("0");
|
2005-09-12 12:01:40 +00:00
|
|
|
S12degEdit->setValidator(DoubleVal);
|
2013-06-01 12:33:02 +02:00
|
|
|
S22degEdit = new QLineEdit("0");
|
2005-09-12 12:01:40 +00:00
|
|
|
S22degEdit->setValidator(DoubleVal);
|
2013-06-01 12:33:02 +02:00
|
|
|
VBox9->addWidget(S12degEdit);
|
|
|
|
VBox9->addWidget(S22degEdit);
|
|
|
|
QVBoxLayout *VBox0 = new QVBoxLayout();
|
|
|
|
h3->addLayout(VBox0);
|
|
|
|
S12uLabel = new QLabel(" ");
|
|
|
|
S22uLabel = new QLabel(" ");
|
|
|
|
VBox0->addWidget(S12uLabel);
|
|
|
|
VBox0->addWidget(S22uLabel);
|
|
|
|
SParLayout->addLayout(h3);
|
2005-09-12 12:01:40 +00:00
|
|
|
|
|
|
|
connect(S21magEdit, SIGNAL(textChanged(const QString&)),
|
|
|
|
SLOT(slotImpedanceChanged(const QString&)));
|
|
|
|
connect(S21degEdit, SIGNAL(textChanged(const QString&)),
|
|
|
|
SLOT(slotImpedanceChanged(const QString&)));
|
|
|
|
connect(S11magEdit, SIGNAL(textChanged(const QString&)),
|
|
|
|
SLOT(slotReflexionChanged(const QString&)));
|
|
|
|
connect(S11degEdit, SIGNAL(textChanged(const QString&)),
|
|
|
|
SLOT(slotReflexionChanged(const QString&)));
|
|
|
|
|
|
|
|
|
2013-06-01 12:33:02 +02:00
|
|
|
QHBoxLayout *h2 = new QHBoxLayout();
|
2005-09-12 12:01:40 +00:00
|
|
|
h2->setSpacing(3);
|
2013-06-01 12:33:02 +02:00
|
|
|
FrequencyLabel = new QLabel(tr("Frequency:"));
|
|
|
|
FrequencyEdit = new QLineEdit();
|
2005-08-01 06:08:52 +00:00
|
|
|
FrequencyEdit->setValidator(DoubleVal);
|
2013-06-01 12:33:02 +02:00
|
|
|
h2->addWidget(FrequencyLabel);
|
|
|
|
h2->addWidget(FrequencyEdit);
|
|
|
|
UnitCombo = new QComboBox();
|
2005-08-01 06:08:52 +00:00
|
|
|
UnitCombo->insertItem("Hz");
|
|
|
|
UnitCombo->insertItem("kHz");
|
|
|
|
UnitCombo->insertItem("MHz");
|
|
|
|
UnitCombo->insertItem("GHz");
|
2013-06-01 12:33:02 +02:00
|
|
|
h2->addWidget(UnitCombo);
|
|
|
|
h2->addStretch(5);
|
|
|
|
SParLayout->addLayout(h2);
|
2005-08-01 06:08:52 +00:00
|
|
|
|
|
|
|
// ...........................................................
|
2013-06-01 12:33:02 +02:00
|
|
|
QHBoxLayout *h0 = new QHBoxLayout();
|
2005-08-01 06:08:52 +00:00
|
|
|
h0->setSpacing(5);
|
2013-06-01 12:33:02 +02:00
|
|
|
all->addLayout(h0);
|
|
|
|
h0->addStretch(5);
|
|
|
|
QPushButton *buttCreate = new QPushButton(tr("Create"));
|
|
|
|
QPushButton *buttCancel = new QPushButton(tr("Cancel"));
|
|
|
|
h0->addWidget(buttCreate);
|
|
|
|
h0->addWidget(buttCancel);
|
|
|
|
connect(buttCreate, SIGNAL(clicked()), SLOT(slotButtCreate()));
|
|
|
|
connect(buttCancel, SIGNAL(clicked()), SLOT(reject()));
|
2005-09-12 12:01:40 +00:00
|
|
|
|
2013-06-01 12:33:02 +02:00
|
|
|
slotReflexionChanged(""); // calculate impedance
|
2005-09-12 12:01:40 +00:00
|
|
|
setFrequency(1e9); // set 1GHz
|
|
|
|
resize(520, 100);
|
2005-08-01 06:08:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MatchDialog::~MatchDialog()
|
|
|
|
{
|
|
|
|
delete all;
|
|
|
|
delete DoubleVal;
|
|
|
|
}
|
|
|
|
|
2005-09-12 12:01:40 +00:00
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void MatchDialog::setFrequency(double Freq_)
|
|
|
|
{
|
|
|
|
int Expo = int(log10(Freq_) / 3.0);
|
|
|
|
if(Expo < 0) Expo = 0;
|
|
|
|
else if(Expo > 3) Expo = 3;
|
|
|
|
UnitCombo->setCurrentItem(Expo);
|
|
|
|
Freq_ /= pow(10.0, double(3*Expo));
|
|
|
|
FrequencyEdit->setText(QString::number(Freq_));
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
// Is called when the checkbox for two-port matching changes.
|
|
|
|
void MatchDialog::slotSetTwoPort(bool on)
|
|
|
|
{
|
|
|
|
if(on) { // two-port matching ?
|
|
|
|
S11Label->setText(tr("S11"));
|
|
|
|
S21Label->setText(tr("S21"));
|
|
|
|
S12magEdit->setEnabled(true);
|
|
|
|
S22magEdit->setEnabled(true);
|
|
|
|
S12degEdit->setEnabled(true);
|
|
|
|
S22degEdit->setEnabled(true);
|
|
|
|
S12Label->setEnabled(true);
|
|
|
|
S22Label->setEnabled(true);
|
|
|
|
S12sLabel->setEnabled(true);
|
|
|
|
S22sLabel->setEnabled(true);
|
|
|
|
S12degEdit->setEnabled(true);
|
|
|
|
S22degEdit->setEnabled(true);
|
|
|
|
S12uLabel->setEnabled(true);
|
|
|
|
S22uLabel->setEnabled(true);
|
|
|
|
Port2Label->setEnabled(true);
|
|
|
|
Ref2Edit->setEnabled(true);
|
|
|
|
Ohm2Label->setEnabled(true);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
S11Label->setText(tr("Reflexion Coefficient"));
|
|
|
|
S21Label->setText(tr("Impedance (ohms)"));
|
|
|
|
S12magEdit->setEnabled(false);
|
|
|
|
S22magEdit->setEnabled(false);
|
|
|
|
S12degEdit->setEnabled(false);
|
|
|
|
S22degEdit->setEnabled(false);
|
|
|
|
S12Label->setEnabled(false);
|
|
|
|
S22Label->setEnabled(false);
|
|
|
|
S12sLabel->setEnabled(false);
|
|
|
|
S22sLabel->setEnabled(false);
|
|
|
|
S12degEdit->setEnabled(false);
|
|
|
|
S22degEdit->setEnabled(false);
|
|
|
|
S12uLabel->setEnabled(false);
|
|
|
|
S22uLabel->setEnabled(false);
|
|
|
|
Port2Label->setEnabled(false);
|
|
|
|
Ref2Edit->setEnabled(false);
|
|
|
|
Ohm2Label->setEnabled(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
// Is called when the combobox changes between mag/deg and real/imag.
|
|
|
|
void MatchDialog::slotChangeMode(int Index)
|
|
|
|
{
|
|
|
|
if(Index) { // polar ?
|
|
|
|
S11sLabel->setText("/");
|
|
|
|
S12sLabel->setText("/");
|
|
|
|
S21sLabel->setText("/");
|
|
|
|
S22sLabel->setText("/");
|
2013-06-01 12:33:02 +02:00
|
|
|
S11uLabel->setText(QString::fromUtf8("°"));
|
|
|
|
S12uLabel->setText(QString::fromUtf8("°"));
|
|
|
|
S21uLabel->setText(QString::fromUtf8("°"));
|
|
|
|
S22uLabel->setText(QString::fromUtf8("°"));
|
2005-09-12 12:01:40 +00:00
|
|
|
|
|
|
|
double Real = S11magEdit->text().toDouble();
|
|
|
|
double Imag = S11degEdit->text().toDouble();
|
|
|
|
c2p(Real, Imag);
|
|
|
|
S11magEdit->setText(QString::number(Real));
|
|
|
|
S11degEdit->setText(QString::number(Imag));
|
|
|
|
|
|
|
|
Real = S12magEdit->text().toDouble();
|
|
|
|
Imag = S12degEdit->text().toDouble();
|
|
|
|
c2p(Real, Imag);
|
|
|
|
S12magEdit->setText(QString::number(Real));
|
|
|
|
S12degEdit->setText(QString::number(Imag));
|
|
|
|
|
|
|
|
Real = S21magEdit->text().toDouble();
|
|
|
|
Imag = S21degEdit->text().toDouble();
|
|
|
|
c2p(Real, Imag);
|
|
|
|
S21magEdit->setText(QString::number(Real));
|
|
|
|
S21degEdit->setText(QString::number(Imag));
|
|
|
|
|
|
|
|
Real = S22magEdit->text().toDouble();
|
|
|
|
Imag = S22degEdit->text().toDouble();
|
|
|
|
c2p(Real, Imag);
|
|
|
|
S22magEdit->setText(QString::number(Real));
|
|
|
|
S22degEdit->setText(QString::number(Imag));
|
|
|
|
}
|
|
|
|
else { // cartesian
|
|
|
|
S11sLabel->setText("+j");
|
|
|
|
S12sLabel->setText("+j");
|
|
|
|
S21sLabel->setText("+j");
|
|
|
|
S22sLabel->setText("+j");
|
|
|
|
S11uLabel->setText(" ");
|
|
|
|
S12uLabel->setText(" ");
|
|
|
|
S21uLabel->setText(" ");
|
|
|
|
S22uLabel->setText(" ");
|
|
|
|
|
|
|
|
double Mag = S11magEdit->text().toDouble();
|
|
|
|
double Phase = S11degEdit->text().toDouble();
|
|
|
|
p2c(Mag, Phase);
|
|
|
|
S11magEdit->setText(QString::number(Mag));
|
|
|
|
S11degEdit->setText(QString::number(Phase));
|
|
|
|
|
|
|
|
Mag = S12magEdit->text().toDouble();
|
|
|
|
Phase = S12degEdit->text().toDouble();
|
|
|
|
p2c(Mag, Phase);
|
|
|
|
S12magEdit->setText(QString::number(Mag));
|
|
|
|
S12degEdit->setText(QString::number(Phase));
|
|
|
|
|
|
|
|
Mag = S21magEdit->text().toDouble();
|
|
|
|
Phase = S21degEdit->text().toDouble();
|
|
|
|
p2c(Mag, Phase);
|
|
|
|
S21magEdit->setText(QString::number(Mag));
|
|
|
|
S21degEdit->setText(QString::number(Phase));
|
|
|
|
|
|
|
|
Mag = S22magEdit->text().toDouble();
|
|
|
|
Phase = S22degEdit->text().toDouble();
|
|
|
|
p2c(Mag, Phase);
|
|
|
|
S22magEdit->setText(QString::number(Mag));
|
|
|
|
S22degEdit->setText(QString::number(Phase));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-08-01 06:08:52 +00:00
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
// Is called if the user changed the impedance. -> The reflexion
|
|
|
|
// coefficient is calculated.
|
|
|
|
void MatchDialog::slotImpedanceChanged(const QString&)
|
|
|
|
{
|
2005-09-12 12:01:40 +00:00
|
|
|
if(TwoCheck->isChecked()) return;
|
|
|
|
|
|
|
|
double Z0 = Ref1Edit->text().toDouble();
|
|
|
|
double Real = S21magEdit->text().toDouble();
|
|
|
|
double Imag = S21degEdit->text().toDouble();
|
2005-08-01 06:08:52 +00:00
|
|
|
z2r(Real, Imag, Z0);
|
2005-09-12 12:01:40 +00:00
|
|
|
S11magEdit->blockSignals(true); // do not call "changed-slot"
|
|
|
|
S11magEdit->setText(QString::number(Real));
|
|
|
|
S11magEdit->blockSignals(false);
|
|
|
|
S11degEdit->blockSignals(true); // do not call "changed-slot"
|
|
|
|
S11degEdit->setText(QString::number(Imag));
|
|
|
|
S11degEdit->blockSignals(false);
|
2005-08-01 06:08:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
// Is called if the user changed the reflexion coefficient. -> The impedance
|
|
|
|
// is calculated.
|
|
|
|
void MatchDialog::slotReflexionChanged(const QString&)
|
|
|
|
{
|
2005-09-12 12:01:40 +00:00
|
|
|
if(TwoCheck->isChecked()) return;
|
|
|
|
|
|
|
|
double Z0 = Ref1Edit->text().toDouble();
|
|
|
|
double Real = S11magEdit->text().toDouble();
|
|
|
|
double Imag = S11degEdit->text().toDouble();
|
2005-08-01 06:08:52 +00:00
|
|
|
r2z(Real, Imag, Z0);
|
2005-09-12 12:01:40 +00:00
|
|
|
S21magEdit->blockSignals(true); // do not call "changed-slot"
|
|
|
|
S21magEdit->setText(QString::number(Real));
|
|
|
|
S21magEdit->blockSignals(false);
|
|
|
|
S21degEdit->blockSignals(true); // do not call "changed-slot"
|
|
|
|
S21degEdit->setText(QString::number(Imag));
|
|
|
|
S21degEdit->blockSignals(false);
|
2005-08-01 06:08:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
// Is called if the "Create"-button is pressed.
|
|
|
|
void MatchDialog::slotButtCreate()
|
|
|
|
{
|
2005-09-12 12:01:40 +00:00
|
|
|
double Z1 = Ref1Edit->text().toDouble();
|
|
|
|
double Z2 = Ref2Edit->text().toDouble();
|
2005-08-01 06:08:52 +00:00
|
|
|
double Freq = FrequencyEdit->text().toDouble() *
|
|
|
|
pow(10.0, 3.0*double(UnitCombo->currentItem()));
|
|
|
|
|
2005-09-12 12:01:40 +00:00
|
|
|
double S11real = S11magEdit->text().toDouble();
|
|
|
|
double S11imag = S11degEdit->text().toDouble();
|
|
|
|
double S12real = S12magEdit->text().toDouble();
|
|
|
|
double S12imag = S12degEdit->text().toDouble();
|
|
|
|
double S21real = S21magEdit->text().toDouble();
|
|
|
|
double S21imag = S21degEdit->text().toDouble();
|
|
|
|
double S22real = S22magEdit->text().toDouble();
|
|
|
|
double S22imag = S22degEdit->text().toDouble();
|
|
|
|
if(FormatCombo->currentItem()) { // are they polar ?
|
|
|
|
p2c(S11real, S11imag);
|
|
|
|
p2c(S12real, S12imag);
|
|
|
|
p2c(S21real, S21imag);
|
|
|
|
p2c(S22real, S22imag);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(TwoCheck->isChecked()) { // two-port matching ?
|
|
|
|
// determinante of S-parameter matrix
|
|
|
|
double DetReal = S11real*S22real - S11imag*S22imag
|
|
|
|
- S12real*S21real + S12imag*S21imag;
|
|
|
|
double DetImag = S11real*S22imag + S11imag*S22real
|
|
|
|
- S12real*S21imag - S12imag*S21real;
|
|
|
|
|
|
|
|
if(!MatchDialog::calc2PortMatch(S11real, S11imag, S22real, S22imag,
|
|
|
|
DetReal, DetImag, Z1, Z2, Freq))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if(!calcMatchingCircuit(S11real, S11imag, Z1, Freq))
|
|
|
|
return;
|
2005-08-01 06:08:52 +00:00
|
|
|
|
2006-03-28 06:10:52 +00:00
|
|
|
QucsMain->slotEditPaste(true);
|
2005-08-01 06:08:52 +00:00
|
|
|
accept();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-09-12 12:01:40 +00:00
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
// transform real/imag into mag/deg (cartesian to polar)
|
|
|
|
void MatchDialog::c2p(double& Real, double& Imag)
|
|
|
|
{
|
|
|
|
double Real_ = Real;
|
|
|
|
Real = sqrt(Real*Real + Imag*Imag); // magnitude
|
|
|
|
Imag = 180.0/M_PI * atan2(Imag, Real_); // phase in degree
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
// transform mag/deg into real/imag (polar to cartesian)
|
|
|
|
void MatchDialog::p2c(double& Real, double& Imag)
|
|
|
|
{
|
|
|
|
double Real_ = Real;
|
|
|
|
Real = Real_ * cos(Imag * M_PI/180.0); // real part
|
|
|
|
Imag = Real_ * sin(Imag * M_PI/180.0); // imaginary part
|
|
|
|
}
|
|
|
|
|
2005-08-01 06:08:52 +00:00
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
// transform reflexion coefficient into impedance
|
|
|
|
void MatchDialog::r2z(double& Real, double& Imag, double Z0)
|
|
|
|
{
|
|
|
|
double tmp = Z0 / ((1.0-Real)*(1.0-Real) + Imag*Imag);
|
|
|
|
Real = (1.0 - Real*Real - Imag*Imag) * tmp;
|
|
|
|
Imag *= 2.0 * tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
// transform impedance into reflexion coefficient
|
|
|
|
void MatchDialog::z2r(double& Real, double& Imag, double Z0)
|
|
|
|
{
|
|
|
|
double tmp = (Real+Z0)*(Real+Z0) + Imag*Imag;
|
|
|
|
Real = (Real*Real + Imag*Imag - Z0*Z0) / tmp;
|
|
|
|
Imag *= 2.0 * Z0 / tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------
|
2005-08-15 06:04:52 +00:00
|
|
|
// Calculate matching circuit. Returns string like "sp:1nH:5pF"
|
|
|
|
QString MatchDialog::calcMatching(double r_real, double r_imag,
|
|
|
|
double Z0, double Freq)
|
2005-08-01 06:08:52 +00:00
|
|
|
{
|
|
|
|
double Zreal = r_real, Zimag = r_imag;
|
|
|
|
r2z(Zreal, Zimag, Z0);
|
|
|
|
|
2005-08-15 06:04:52 +00:00
|
|
|
if (Zreal < 0.0) {
|
|
|
|
if (Zreal < -1e-13) {
|
|
|
|
QMessageBox::critical(0, tr("Error"),
|
|
|
|
tr("Real part of impedance must be greater zero,\nbut is %1 !").arg(Zreal));
|
|
|
|
return QString(""); // matching not possible
|
|
|
|
}
|
|
|
|
|
2005-09-12 12:01:40 +00:00
|
|
|
// In high-Q circuits, Zreal often becomes somewhat about -1e-16
|
2005-08-15 06:04:52 +00:00
|
|
|
// because of numerical inaccuracy.
|
|
|
|
Zreal = 0.0;
|
2005-08-01 06:08:52 +00:00
|
|
|
}
|
|
|
|
|
2005-08-15 06:04:52 +00:00
|
|
|
|
|
|
|
double X1, X2, Omega = 2.0 * M_PI * Freq;
|
|
|
|
QString Str;
|
|
|
|
if(r_real < 0) {
|
|
|
|
// ...................................................
|
|
|
|
// first serial than parallel component (possible if Zreal <= Z0)
|
|
|
|
Str = "sp";
|
|
|
|
X1 = sqrt(Zreal * (Z0 - Zreal));
|
|
|
|
if (Zimag < 0.0) X1 *= -1.0; // always use shortest matching path
|
|
|
|
X1 -= Zimag;
|
|
|
|
|
|
|
|
// parallel component
|
|
|
|
X2 = (Zimag + X1) / (Zreal*Zreal + (Zimag + X1)*(Zimag + X1));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
Str = "ps";
|
|
|
|
X1 = Zreal + Zimag*Zimag / Zreal - Z0;
|
|
|
|
// ...................................................
|
|
|
|
// first parallel than serial component (possible if X >= 0.0)
|
|
|
|
X1 = sqrt(Z0 * X1);
|
|
|
|
if (Zimag > 0.0) X1 *= -1.0; // always use shortest matching path
|
|
|
|
|
|
|
|
// parallel component
|
|
|
|
X2 = Zimag / (Zreal*Zreal + Zimag*Zimag) + X1 / (Z0*Z0 + X1*X1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// serial component
|
|
|
|
if (X1 < 0.0) // capacitance ?
|
|
|
|
Str += ':' + num2str(-1.0 / Omega / X1) + 'F';
|
|
|
|
else // inductance
|
|
|
|
Str += ':' + num2str(X1 / Omega) + 'H';
|
|
|
|
|
|
|
|
// parallel component
|
|
|
|
if (X2 < 0.0) // inductance ?
|
|
|
|
Str += ':' + num2str(-1.0 / Omega / X2) + 'H';
|
|
|
|
else // capacitance
|
|
|
|
Str += ':' + num2str(X2 / Omega) + 'F';
|
|
|
|
|
|
|
|
return Str;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
bool MatchDialog::calcMatchingCircuit(double r_real, double r_imag,
|
|
|
|
double Z0, double Freq)
|
|
|
|
{
|
2005-08-01 06:08:52 +00:00
|
|
|
QString Schematic =
|
|
|
|
"<Qucs Schematic " PACKAGE_VERSION ">\n"
|
|
|
|
"<Components>\n";
|
|
|
|
|
|
|
|
|
2005-08-15 06:04:52 +00:00
|
|
|
QString Str = calcMatching(r_real, r_imag, Z0, Freq);
|
|
|
|
if(Str.isEmpty()) return false;
|
|
|
|
|
|
|
|
if(Str.section(':', 0,0) == "sp") {
|
|
|
|
// ...................................................
|
|
|
|
// first serial than parallel component
|
|
|
|
|
|
|
|
if(Str.section(':', 1,1).right(1) == "F")
|
2005-08-01 06:08:52 +00:00
|
|
|
Schematic += "<C C1";
|
2005-08-15 06:04:52 +00:00
|
|
|
else
|
2005-08-01 06:08:52 +00:00
|
|
|
Schematic += "<L L1";
|
2005-08-15 06:04:52 +00:00
|
|
|
Schematic += " 1 100 10 -26 10 0 0 \"" + Str.section(':', 1,1) + "\" 1>\n";
|
2005-08-01 06:08:52 +00:00
|
|
|
|
2005-08-15 06:04:52 +00:00
|
|
|
if(Str.section(':', 2,2).right(1) == "F")
|
2005-08-01 06:08:52 +00:00
|
|
|
Schematic += "<C C2";
|
2005-08-15 06:04:52 +00:00
|
|
|
else
|
|
|
|
Schematic += "<L L2";
|
|
|
|
Schematic += " 1 30 80 17 -26 0 1 \"" + Str.section(':', 2,2) + "\" 1>\n";
|
2005-08-01 06:08:52 +00:00
|
|
|
|
|
|
|
Schematic +=
|
|
|
|
"<GND * 1 30 110 0 0 0 0>\n"
|
|
|
|
"</Components>\n"
|
|
|
|
"<Wires>\n"
|
|
|
|
"<10 10 30 10 \"\" 0 0 0 \"\">\n"
|
|
|
|
"<30 10 70 10 \"\" 0 0 0 \"\">\n"
|
|
|
|
"<30 10 30 50 \"\" 0 0 0 \"\">\n";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// ...................................................
|
|
|
|
// first parallel than serial component
|
2005-08-15 06:04:52 +00:00
|
|
|
|
|
|
|
if(Str.section(':', 1,1).right(1) == "F")
|
2005-08-01 06:08:52 +00:00
|
|
|
Schematic += "<C C1";
|
2005-08-15 06:04:52 +00:00
|
|
|
else
|
2005-08-01 06:08:52 +00:00
|
|
|
Schematic += "<L L1";
|
2005-09-12 12:01:40 +00:00
|
|
|
Schematic += " 1 50 10 -26 10 0 0 \"" + Str.section(':', 1,1) + "\" 1>\n";
|
2005-08-01 06:08:52 +00:00
|
|
|
|
2005-08-15 06:04:52 +00:00
|
|
|
if(Str.section(':', 2,2).right(1) == "F")
|
2005-08-01 06:08:52 +00:00
|
|
|
Schematic += "<C C2";
|
2005-08-15 06:04:52 +00:00
|
|
|
else
|
|
|
|
Schematic += "<L L2";
|
2005-09-12 12:01:40 +00:00
|
|
|
Schematic += " 1 130 70 17 -26 0 1 \"" + Str.section(':', 2,2) + "\" 1>\n";
|
2005-08-01 06:08:52 +00:00
|
|
|
|
|
|
|
Schematic +=
|
2005-09-12 12:01:40 +00:00
|
|
|
"<GND * 1 130 100 0 0 0 0>\n"
|
2005-08-01 06:08:52 +00:00
|
|
|
"</Components>\n"
|
|
|
|
"<Wires>\n"
|
2005-09-12 12:01:40 +00:00
|
|
|
"<130 10 130 40 \"\" 0 0 0 \"\">\n"
|
|
|
|
"<130 10 150 10 \"\" 0 0 0 \"\">\n"
|
|
|
|
"<80 10 130 10 \"\" 0 0 0 \"\">\n";
|
2005-08-01 06:08:52 +00:00
|
|
|
}
|
|
|
|
|
2005-09-12 12:01:40 +00:00
|
|
|
Schematic += QString(
|
2005-08-01 06:08:52 +00:00
|
|
|
"</Wires>\n"
|
|
|
|
"<Diagrams>\n"
|
|
|
|
"</Diagrams>\n"
|
|
|
|
"<Paintings>\n"
|
2005-09-12 12:01:40 +00:00
|
|
|
" <Text -20 -10 12 #000000 0 \"%1 Ohm\">\n"
|
|
|
|
" <Text 120 -10 12 #000000 0 \"device\">\n"
|
|
|
|
"</Paintings>\n").arg(Z0);
|
2005-08-01 06:08:52 +00:00
|
|
|
|
|
|
|
QApplication::clipboard()->setText(Schematic, QClipboard::Clipboard);
|
2005-08-15 06:04:52 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
// Fundamental calculations for concurrent 2-port matching.
|
|
|
|
QString MatchDialog::calcBiMatch(double S11real, double S11imag,
|
|
|
|
double S22real, double S22imag, double DetReal, double DetImag,
|
|
|
|
double Z0, double Freq)
|
|
|
|
{
|
|
|
|
double B = 1.0 + S11real*S11real + S11imag*S11imag
|
|
|
|
- S22real*S22real - S22imag*S22imag
|
|
|
|
- DetReal*DetReal - DetImag*DetImag;
|
|
|
|
double Creal = S11real - S22real*DetReal - S22imag*DetImag;
|
|
|
|
double Cimag = S22real*DetImag - S11imag - S22imag*DetReal;
|
|
|
|
double Cmag = 2.0 * (Creal*Creal + Cimag*Cimag);
|
|
|
|
Creal /= Cmag;
|
|
|
|
Cimag /= Cmag;
|
|
|
|
|
|
|
|
double Rreal = B*B - 2.0*Cmag;
|
|
|
|
double Rimag;
|
|
|
|
if(Rreal < 0.0) {
|
|
|
|
Rimag = Cimag * B - Creal * sqrt(-Rreal);
|
|
|
|
Rreal = Creal * B + Cimag * sqrt(-Rreal);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Rreal = B - sqrt(Rreal);
|
|
|
|
Rimag = Cimag * Rreal;
|
|
|
|
Rreal *= Creal;
|
|
|
|
}
|
|
|
|
|
|
|
|
return calcMatching(Rreal, -Rimag, Z0, Freq);
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
bool MatchDialog::calc2PortMatch(double S11real, double S11imag,
|
|
|
|
double S22real, double S22imag, double DetReal, double DetImag,
|
2005-09-12 12:01:40 +00:00
|
|
|
double Z1, double Z2, double Freq)
|
2005-08-15 06:04:52 +00:00
|
|
|
{
|
|
|
|
QString Input = calcBiMatch(S11real, S11imag, S22real, S22imag,
|
2005-09-12 12:01:40 +00:00
|
|
|
DetReal, DetImag, Z1, Freq);
|
2005-08-15 06:04:52 +00:00
|
|
|
if(Input.isEmpty()) return false;
|
|
|
|
|
|
|
|
QString Output = calcBiMatch(S22real, S22imag, S11real, S11imag,
|
2005-09-12 12:01:40 +00:00
|
|
|
DetReal, DetImag, Z2, Freq);
|
2005-08-15 06:04:52 +00:00
|
|
|
if(Output.isEmpty()) return false;
|
|
|
|
|
|
|
|
QString Schematic =
|
|
|
|
"<Qucs Schematic " PACKAGE_VERSION ">\n"
|
|
|
|
"<Components>\n";
|
|
|
|
|
|
|
|
|
|
|
|
// ...................................................
|
|
|
|
// create input circuit
|
|
|
|
if(Input.section(':', 0,0) == "sp") {
|
|
|
|
// first serial than parallel component
|
|
|
|
|
|
|
|
if(Input.section(':', 1,1).right(1) == "F")
|
|
|
|
Schematic += "<C C1";
|
|
|
|
else
|
|
|
|
Schematic += "<L L1";
|
|
|
|
Schematic += " 1 -50 10 -26 10 0 0 \"" + Input.section(':', 1,1) + "\" 1>\n";
|
|
|
|
|
|
|
|
if(Input.section(':', 2,2).right(1) == "F")
|
|
|
|
Schematic += "<C C2";
|
|
|
|
else
|
|
|
|
Schematic += "<L L2";
|
|
|
|
Schematic += " 1 -120 80 17 -26 0 1 \"" + Input.section(':', 2,2) + "\" 1>\n";
|
|
|
|
|
|
|
|
Schematic += "<GND * 1 -120 110 0 0 0 0>\n";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// first parallel than serial component
|
|
|
|
|
|
|
|
if(Input.section(':', 1,1).right(1) == "F")
|
|
|
|
Schematic += "<C C1";
|
|
|
|
else
|
|
|
|
Schematic += "<L L1";
|
|
|
|
Schematic += " 1 -140 10 -26 10 0 0 \"" + Input.section(':', 1,1) + "\" 1>\n";
|
|
|
|
|
|
|
|
if(Input.section(':', 2,2).right(1) == "F")
|
|
|
|
Schematic += "<C C2";
|
|
|
|
else
|
|
|
|
Schematic += "<L L2";
|
|
|
|
Schematic += " 1 -60 70 17 -26 0 1 \"" + Input.section(':', 2,2) + "\" 1>\n";
|
|
|
|
|
|
|
|
Schematic += "<GND * 1 -60 100 0 0 0 0>\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ...................................................
|
|
|
|
// create output circuit
|
|
|
|
if(Output.section(':', 0,0) == "sp") {
|
|
|
|
// first serial than parallel component
|
|
|
|
|
|
|
|
if(Output.section(':', 1,1).right(1) == "F")
|
|
|
|
Schematic += "<C C1";
|
|
|
|
else
|
|
|
|
Schematic += "<L L1";
|
|
|
|
Schematic += " 1 50 10 -26 10 0 0 \"" + Output.section(':', 1,1) + "\" 1>\n";
|
|
|
|
|
|
|
|
if(Output.section(':', 2,2).right(1) == "F")
|
|
|
|
Schematic += "<C C2";
|
|
|
|
else
|
|
|
|
Schematic += "<L L2";
|
|
|
|
Schematic += " 1 120 80 17 -26 0 1 \"" + Output.section(':', 2,2) + "\" 1>\n";
|
|
|
|
|
|
|
|
Schematic += "<GND * 1 120 110 0 0 0 0>\n";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// ...................................................
|
|
|
|
// first parallel than serial component
|
|
|
|
|
|
|
|
if(Output.section(':', 1,1).right(1) == "F")
|
|
|
|
Schematic += "<C C1";
|
|
|
|
else
|
|
|
|
Schematic += "<L L1";
|
|
|
|
Schematic += " 1 140 10 -26 10 0 0 \"" + Output.section(':', 1,1) + "\" 1>\n";
|
|
|
|
|
|
|
|
if(Output.section(':', 2,2).right(1) == "F")
|
|
|
|
Schematic += "<C C2";
|
|
|
|
else
|
|
|
|
Schematic += "<L L2";
|
|
|
|
Schematic += " 1 60 70 17 -26 0 1 \"" + Output.section(':', 2,2) + "\" 1>\n";
|
|
|
|
|
|
|
|
Schematic += "<GND * 1 60 100 0 0 0 0>\n";
|
|
|
|
}
|
|
|
|
Schematic += "</Components>\n"
|
|
|
|
"<Wires>\n";
|
|
|
|
|
|
|
|
|
|
|
|
// ...................................................
|
|
|
|
// create wires for input circuit
|
|
|
|
if(Input.section(':', 0,0) == "sp") // first serial than parallel component
|
|
|
|
Schematic +=
|
|
|
|
"<-140 10 -120 10 \"\" 0 0 0 \"\">\n"
|
|
|
|
"<-120 10 -80 10 \"\" 0 0 0 \"\">\n"
|
|
|
|
"<-120 10 -120 50 \"\" 0 0 0 \"\">\n";
|
|
|
|
else // first parallel than serial component
|
|
|
|
Schematic +=
|
|
|
|
"<-60 10 -60 40 \"\" 0 0 0 \"\">\n"
|
|
|
|
"<-60 10 -40 10 \"\" 0 0 0 \"\">\n"
|
|
|
|
"<-110 10 -60 10 \"\" 0 0 0 \"\">\n";
|
|
|
|
|
|
|
|
|
|
|
|
// ...................................................
|
|
|
|
// create wires for output circuit
|
|
|
|
if(Output.section(':', 0,0) == "sp") // first serial than parallel component
|
|
|
|
Schematic +=
|
|
|
|
"<140 10 120 10 \"\" 0 0 0 \"\">\n"
|
|
|
|
"<120 10 80 10 \"\" 0 0 0 \"\">\n"
|
|
|
|
"<120 10 120 50 \"\" 0 0 0 \"\">\n";
|
|
|
|
else // first parallel than serial component
|
|
|
|
Schematic +=
|
|
|
|
"<60 10 60 40 \"\" 0 0 0 \"\">\n"
|
|
|
|
"<60 10 40 10 \"\" 0 0 0 \"\">\n"
|
|
|
|
"<110 10 60 10 \"\" 0 0 0 \"\">\n";
|
|
|
|
|
|
|
|
Schematic +=
|
|
|
|
"</Wires>\n"
|
|
|
|
"<Diagrams>\n"
|
|
|
|
"</Diagrams>\n"
|
|
|
|
"<Paintings>\n"
|
2005-09-12 12:01:40 +00:00
|
|
|
" <Text -200 -10 12 #000000 0 \"Port 1\">\n"
|
|
|
|
" <Text -20 -10 12 #000000 0 \"device\">\n"
|
|
|
|
" <Text 160 -10 12 #000000 0 \"Port 2\">\n"
|
2005-08-15 06:04:52 +00:00
|
|
|
"</Paintings>\n";
|
|
|
|
|
|
|
|
QApplication::clipboard()->setText(Schematic, QClipboard::Clipboard);
|
|
|
|
return true;
|
2005-08-01 06:08:52 +00:00
|
|
|
}
|