282 lines
9.9 KiB
C++
282 lines
9.9 KiB
C++
#include "impedancematchdialog.h"
|
|
|
|
#include "ui_impedancematchdialog.h"
|
|
#include "Tools/eseries.h"
|
|
#include "Util/util.h"
|
|
#include "preferences.h"
|
|
|
|
using namespace std;
|
|
|
|
ImpedanceMatchDialog::ImpedanceMatchDialog(MarkerModel &model, Marker *marker, QWidget *parent) :
|
|
QDialog(parent),
|
|
ui(new Ui::ImpedanceMatchDialog)
|
|
{
|
|
ui->setupUi(this);
|
|
|
|
Z0 = 50.0;
|
|
|
|
// set SI units and prefixes
|
|
ui->zReal->setUnit("Ohm");
|
|
ui->zImag->setUnit("Ohm");
|
|
ui->zFreq->setUnit("Hz");
|
|
ui->zFreq->setPrefixes(" kMG");
|
|
|
|
ui->mImag->setUnit("Ohm");
|
|
ui->mReal->setUnit("Ohm");
|
|
ui->mLoss->setUnit("db");
|
|
|
|
ui->lValue->setUnit("H");
|
|
ui->lValue->setPrefixes("pnum ");
|
|
ui->cValue->setUnit("F");
|
|
ui->cValue->setPrefixes("pnum ");
|
|
|
|
connect(ui->zFreq, &SIUnitEdit::valueChanged, this, &ImpedanceMatchDialog::calculateMatch);
|
|
connect(ui->zImag, &SIUnitEdit::valueChanged, this, &ImpedanceMatchDialog::calculateMatch);
|
|
connect(ui->zReal, &SIUnitEdit::valueChanged, this, &ImpedanceMatchDialog::calculateMatch);
|
|
connect(ui->zGroup, qOverload<int>(&QButtonGroup::idClicked), this, &ImpedanceMatchDialog::calculateMatch);
|
|
connect(ui->cMatchType, qOverload<int>(&QComboBox::currentIndexChanged), this, &ImpedanceMatchDialog::calculateMatch);
|
|
connect(ui->lGroup, qOverload<int>(&QButtonGroup::idClicked), this, &ImpedanceMatchDialog::calculateMatch);
|
|
connect(ui->cGroup, qOverload<int>(&QButtonGroup::idClicked), this, &ImpedanceMatchDialog::calculateMatch);
|
|
connect(ui->zGroup, qOverload<int>(&QButtonGroup::idClicked), this, &ImpedanceMatchDialog::calculateMatch);
|
|
|
|
// populate marker options
|
|
auto markers = model.getMarkers();
|
|
for(auto m : markers) {
|
|
if(!m->trace()->isReflection()) {
|
|
// matching only possible for reflections
|
|
continue;
|
|
}
|
|
ui->cSource->addItem("From Marker "+QString::number(m->getNumber()), QVariant::fromValue<Marker*>(m));
|
|
if(m == marker) {
|
|
// select the last index, e.i. the just created marker
|
|
ui->cSource->setCurrentIndex(ui->cSource->count()-1);
|
|
}
|
|
}
|
|
}
|
|
|
|
ImpedanceMatchDialog::~ImpedanceMatchDialog()
|
|
{
|
|
delete ui;
|
|
}
|
|
|
|
void ImpedanceMatchDialog::on_cSource_currentIndexChanged(int index)
|
|
{
|
|
ui->rbSeries->setEnabled(index == 0);
|
|
ui->rbParallel->setEnabled(index == 0);
|
|
ui->zReal->setEnabled(index == 0);
|
|
ui->zImag->setEnabled(index == 0);
|
|
ui->zFreq->setEnabled(index == 0);
|
|
if(index > 0) {
|
|
auto m = qvariant_cast<Marker*>(ui->cSource->itemData(index));
|
|
ui->rbSeries->setChecked(true);
|
|
auto data = m->getData();
|
|
Z0 = m->getTrace()->getReferenceImpedance();
|
|
auto reflection = Z0 * (1.0 + data) / (1.0 - data);
|
|
ui->zReal->setValue(reflection.real());
|
|
ui->zImag->setValue(reflection.imag());
|
|
ui->zFreq->setValue(m->getPosition());
|
|
} else {
|
|
Z0 = 50.0;
|
|
}
|
|
}
|
|
|
|
void ImpedanceMatchDialog::calculateMatch()
|
|
{
|
|
try {
|
|
double freq = ui->zFreq->value();
|
|
complex<double> Z;
|
|
if(ui->rbSeries->isChecked()) {
|
|
Z.real(ui->zReal->value());
|
|
Z.imag(ui->zImag->value());
|
|
} else {
|
|
auto real = complex<double>(ui->zReal->value(), 0.0);
|
|
auto imag = complex<double>(0.0, ui->zImag->value());
|
|
// calculate parallel impedance
|
|
Z = real * imag / (real + imag);
|
|
}
|
|
bool seriesC = ui->cMatchType->currentIndex() == 0 ? true : false;
|
|
// equations taken from http://www.ittc.ku.edu/~jstiles/723/handouts/section_5_1_Matching_with_Lumped_Elements_package.pdf
|
|
double B, X;
|
|
if(Z.real() > Z0) {
|
|
B = sqrt(Z.real()/Z0)*sqrt(norm(Z)-Z0*Z.real());
|
|
if (seriesC) {
|
|
B = -B;
|
|
}
|
|
B += Z.imag();
|
|
B /= norm(Z);
|
|
X = 1/B + Z.imag()*Z0/Z.real()-Z0/(B*Z.real());
|
|
} else {
|
|
B = sqrt((Z0-Z.real())/Z.real())/Z0;
|
|
X = sqrt(Z.real()*(Z0-Z.real()));
|
|
if (seriesC) {
|
|
B = -B;
|
|
X = -X;
|
|
}
|
|
X -= Z.imag();
|
|
}
|
|
// convert X and B to inductor and capacitor
|
|
bool twoCs = false;
|
|
bool twoLs = false;
|
|
double L = 0, C = 0, C2 = 0, L2 = 0;
|
|
if(X >= 0) {
|
|
L = X/(2*M_PI*freq);
|
|
if(B > 0) {
|
|
C = B/(2*M_PI*freq);
|
|
} else {
|
|
L2 = X/(2*M_PI*freq);
|
|
L = -1/(B*2*M_PI*freq);
|
|
twoLs = true;
|
|
}
|
|
} else {
|
|
C = -1/(X*2*M_PI*freq);
|
|
if(B < 0) {
|
|
L = -1/(B*2*M_PI*freq);
|
|
} else {
|
|
C2 = B/(2*M_PI*freq);
|
|
twoCs = true;
|
|
}
|
|
}
|
|
|
|
ESeries::Series Lseries;
|
|
if(ui->lE6->isChecked()) {
|
|
Lseries = ESeries::Series::E6;
|
|
} else if(ui->lE12->isChecked()) {
|
|
Lseries = ESeries::Series::E12;
|
|
} else if(ui->lE24->isChecked()) {
|
|
Lseries = ESeries::Series::E24;
|
|
} else if(ui->lE48->isChecked()) {
|
|
Lseries = ESeries::Series::E48;
|
|
} else if(ui->lE96->isChecked()) {
|
|
Lseries = ESeries::Series::E96;
|
|
} else {
|
|
Lseries = ESeries::Series::Ideal;
|
|
}
|
|
ESeries::Series Cseries;
|
|
if(ui->cE6->isChecked()) {
|
|
Cseries = ESeries::Series::E6;
|
|
} else if(ui->cE12->isChecked()) {
|
|
Cseries = ESeries::Series::E12;
|
|
} else if(ui->cE24->isChecked()) {
|
|
Cseries = ESeries::Series::E24;
|
|
} else if(ui->cE48->isChecked()) {
|
|
Cseries = ESeries::Series::E48;
|
|
} else if(ui->cE96->isChecked()) {
|
|
Cseries = ESeries::Series::E96;
|
|
} else {
|
|
Cseries = ESeries::Series::Ideal;
|
|
}
|
|
|
|
L = ESeries::ToESeries(L, Lseries);
|
|
C = ESeries::ToESeries(C, Cseries);
|
|
L2 = ESeries::ToESeries(L2, Lseries);
|
|
C2 = ESeries::ToESeries(C2, Cseries);
|
|
|
|
if(twoCs) {
|
|
for(auto b : ui->lGroup->buttons()) {
|
|
b->setEnabled(false);
|
|
}
|
|
for(auto b : ui->cGroup->buttons()) {
|
|
b->setEnabled(true);
|
|
}
|
|
ui->lL->setText("C1:");
|
|
ui->lC->setText("C2:");
|
|
ui->lValue->setUnit("F");
|
|
ui->cValue->setUnit("F");
|
|
ui->lValue->setValue(C2);
|
|
ui->cValue->setValue(C);
|
|
} else if(twoLs) {
|
|
for(auto b : ui->cGroup->buttons()) {
|
|
b->setEnabled(false);
|
|
}
|
|
for(auto b : ui->lGroup->buttons()) {
|
|
b->setEnabled(true);
|
|
}
|
|
ui->lC->setText("L2:");
|
|
ui->lL->setText("L1:");
|
|
ui->cValue->setUnit("H");
|
|
ui->lValue->setUnit("H");
|
|
ui->cValue->setValue(L2);
|
|
ui->lValue->setValue(L);
|
|
} else {
|
|
for(auto b : ui->cGroup->buttons()) {
|
|
b->setEnabled(true);
|
|
}
|
|
for(auto b : ui->lGroup->buttons()) {
|
|
b->setEnabled(true);
|
|
}
|
|
ui->lC->setText("C:");
|
|
ui->lL->setText("L:");
|
|
ui->lValue->setUnit("H");
|
|
ui->cValue->setUnit("F");
|
|
ui->lValue->setValue(L);
|
|
ui->cValue->setValue(C);
|
|
}
|
|
// calculate actual matched impedance
|
|
complex<double> Zmatched;
|
|
complex<double> Zp, Zs;
|
|
if(seriesC) {
|
|
if(twoLs) {
|
|
Zs = complex<double>(0, 2*M_PI*freq*L2);
|
|
Zp = complex<double>(0, 2*M_PI*freq*L);
|
|
} else if(twoCs) {
|
|
Zs = complex<double>(0, -1/(2*M_PI*freq*C2));
|
|
Zp = complex<double>(0, -1/(2*M_PI*freq*C));
|
|
} else {
|
|
Zs = complex<double>(0, -1/(2*M_PI*freq*C));
|
|
Zp = complex<double>(0, 2*M_PI*freq*L);
|
|
}
|
|
} else {
|
|
if(twoCs) {
|
|
Zs = complex<double>(0, -1/(2*M_PI*freq*C));
|
|
Zp = complex<double>(0, -1/(2*M_PI*freq*C2));
|
|
} else if(twoLs){
|
|
Zs = complex<double>(0, 2*M_PI*freq*L);
|
|
Zp = complex<double>(0, 2*M_PI*freq*L2);
|
|
} else {
|
|
Zs = complex<double>(0, 2*M_PI*freq*L);
|
|
Zp = complex<double>(0, -1/(2*M_PI*freq*C));
|
|
}
|
|
}
|
|
if(Z.real() > Z0) {
|
|
Zmatched = Z*Zp/(Z+Zp) + Zs;
|
|
} else {
|
|
Zmatched = Zp*(Z+Zs)/(Zp+Z+Zs);
|
|
}
|
|
ui->mReal->setValue(Zmatched.real());
|
|
ui->mImag->setValue(Zmatched.imag());
|
|
double reflection = abs((Zmatched-Z0)/(Zmatched+Z0));
|
|
auto loss = Util::SparamTodB(reflection);
|
|
ui->mLoss->setValue(loss);
|
|
|
|
// set correct image
|
|
if(Z.real() > Z0) {
|
|
if(X >= 0 && B >= 0) {
|
|
ui->Image->setPixmap(QPixmap(":/icons/sLpC_small.png"));
|
|
} else if(X < 0 && B < 0) {
|
|
ui->Image->setPixmap(QPixmap(":/icons/sCpL_small.png"));
|
|
} else if(X >= 0 && B < 0) {
|
|
ui->Image->setPixmap(QPixmap(":/icons/sCpC_small.png"));
|
|
} else {
|
|
ui->Image->setPixmap(QPixmap(":/icons/sLpL_small.png"));
|
|
}
|
|
} else {
|
|
if(X >= 0 && B >= 0) {
|
|
ui->Image->setPixmap(QPixmap(":/icons/pCsL_small.png"));
|
|
} else if(X < 0 && B < 0) {
|
|
ui->Image->setPixmap(QPixmap(":/icons/pLsC_small.png"));
|
|
} else if(X >= 0 && B < 0) {
|
|
ui->Image->setPixmap(QPixmap(":/icons/pLsL_small.png"));
|
|
} else {
|
|
ui->Image->setPixmap(QPixmap(":/icons/pCsC_small.png"));
|
|
}
|
|
}
|
|
} catch (exception &e){
|
|
// something went wrong, probably caused by (intermediate) invalid input, such as f=0Hz
|
|
ui->lValue->setValue(nan(""));
|
|
ui->cValue->setValue(nan(""));
|
|
ui->mReal->setValue(nan(""));
|
|
ui->mImag->setValue(nan(""));
|
|
ui->mLoss->setValue(nan(""));
|
|
}
|
|
}
|