Calculate additional parameters (R/L/C,...) for markers and traces

This commit is contained in:
Jan Käberich 2021-06-27 23:40:50 +02:00
parent a232be3443
commit e27e594435
18 changed files with 168 additions and 164 deletions

View File

@ -10,6 +10,7 @@
#include "json.hpp"
#include <fstream>
#include <CustomWidgets/informationbox.h>
#include "Util/util.h"
using namespace std;
using namespace nlohmann;
@ -416,7 +417,7 @@ void AmplitudeCalDialog::ReceivedMeasurement(Protocol::SpectrumAnalyzerResult re
if(measured.size() >= averages) {
measured.pop_front();
}
MeasurementResult m = {.port1 = Unit::dB(res.port1), .port2 = Unit::dB(res.port2)};
MeasurementResult m = {.port1 = Util::SparamTodB(res.port1), .port2 = Util::SparamTodB(res.port2)};
measured.push_back(m);
}
}

View File

@ -4,7 +4,7 @@
#include <QDebug>
#include <QButtonGroup>
#include <complex>
#include "unit.h"
#include "Util/util.h"
using namespace std;
@ -207,8 +207,8 @@ void ManualControlDialog::NewStatus(Protocol::ManualStatus status)
auto port1referenced = port1 / ref;
auto port2referenced = port2 / ref;
auto port1db = Unit::dB(port1referenced);
auto port2db = Unit::dB(port2referenced);
auto port1db = Util::SparamTodB(port1referenced);
auto port2db = Util::SparamTodB(port2referenced);
ui->port1referenced->setText(QString::number(port1db, 'f', 1) + "db@" + QString::number(arg(port1referenced)*180/M_PI, 'f', 0) + "°");
ui->port2referenced->setText(QString::number(port2db, 'f', 1) + "db@" + QString::number(arg(port2referenced)*180/M_PI, 'f', 0) + "°");

View File

@ -1,7 +1,7 @@
#include "impedancematchdialog.h"
#include "ui_impedancematchdialog.h"
#include "Tools/eseries.h"
#include "unit.h"
#include "Util/util.h"
using namespace std;
@ -240,7 +240,7 @@ void ImpedanceMatchDialog::calculateMatch()
ui->mReal->setValue(Zmatched.real());
ui->mImag->setValue(Zmatched.imag());
double reflection = abs((Zmatched-Z0)/(Zmatched+Z0));
auto loss = Unit::dB(reflection);
auto loss = Util::SparamTodB(reflection);
ui->mLoss->setValue(loss);
// set correct image

View File

@ -12,6 +12,7 @@
#include <QApplication>
#include "preferences.h"
#include "markergroup.h"
#include "Util/util.h"
using namespace std;
@ -110,6 +111,10 @@ QString Marker::formatToString(Marker::Format f)
case Format::RealImag: return "real + imag";
case Format::Impedance: return "Impedance";
case Format::VSWR: return "VSWR";
case Format::SeriesR: return "Resistance";
case Format::Capacitance: return "Capacitance";
case Format::Inductance: return "Inductance";
case Format::QualityFactor: return "Quality Factor";
case Format::TOI: return "Third order intercept";
case Format::AvgTone: return "Average Tone Level";
case Format::AvgModulationProduct: return "Average Modulation Product Level";
@ -175,6 +180,10 @@ std::vector<Marker::Format> Marker::applicableFormats()
if(parentTrace->isReflection()) {
ret.push_back(Format::Impedance);
ret.push_back(Format::VSWR);
ret.push_back(Format::SeriesR);
ret.push_back(Format::Capacitance);
ret.push_back(Format::Inductance);
ret.push_back(Format::QualityFactor);
}
if(!isnan(parentTrace->getNoise(parentTrace->minX()))) {
ret.push_back(Format::Noise);
@ -224,12 +233,12 @@ QString Marker::readableData(Format f)
if(type != Type::Delta) {
switch(f) {
case Format::dB:
return Unit::ToString(Unit::dB(data), "dB", " ", 4);
return Unit::ToString(Util::SparamTodB(data), "dB", " ", 4);
case Format::RealImag:
return Unit::ToString(data.real(), "", " ", 5) + "+"+Unit::ToString(data.imag(), "", " ", 5)+"j";
case Format::Impedance: {
auto step = parentTrace->sample(parentTrace->index(position), Trace::SampleType::TimeStep).y.real();
auto impedance = 50.0 * (1.0 + step) / (1.0 - step);
auto impedance = Util::SparamToImpedance(step).real();
return Unit::ToString(impedance, "Ω", "m kM", 3);
}
break;
@ -242,14 +251,14 @@ QString Marker::readableData(Format f)
}
switch(f) {
case Format::dB:
return "Δ:"+Unit::ToString(Unit::dB(data) - Unit::dB(delta->data), "dB", " ", 4);
return "Δ:"+Unit::ToString(Util::SparamTodB(data) - Util::SparamTodB(delta->data), "dB", " ", 4);
case Format::RealImag:
return "Δ:"+Unit::ToString(data.real() - delta->data.real(), "", " ", 5) + "+"+Unit::ToString(data.imag() - delta->data.real(), "", " ", 5)+"j";
case Format::Impedance: {
auto step = parentTrace->sample(parentTrace->index(position), Trace::SampleType::TimeStep).y.real();
auto stepDelta = delta->parentTrace->sample(delta->parentTrace->index(delta->position), Trace::SampleType::TimeStep).y.real();
auto impedance = 50.0 * (1.0 + step) / (1.0 - step);
auto impedanceDelta = 50.0 * (1.0 + stepDelta) / (1.0 - stepDelta);
auto impedance = Util::SparamToImpedance(step).real();
auto impedanceDelta = Util::SparamToImpedance(stepDelta).real();
return "Δ:"+Unit::ToString(impedance - impedanceDelta, "Ω", "m kM", 3);
}
break;
@ -266,9 +275,9 @@ QString Marker::readableData(Format f)
return "Invalid delta marker";
}
switch(f) {
case Format::dB: return "Δ:"+Unit::ToString(Unit::dB(data) - Unit::dB(delta->data), "dB", " ", 4);
case Format::dB: return "Δ:"+Unit::ToString(Util::SparamTodB(data) - Util::SparamTodB(delta->data), "dB", " ", 4);
case Format::dBAngle: {
QString ret = "Δ:"+Unit::ToString(Unit::dB(data) - Unit::dB(delta->data), "dB", " ", 4) + "/";
QString ret = "Δ:"+Unit::ToString(Util::SparamTodB(data) - Util::SparamTodB(delta->data), "dB", " ", 4) + "/";
auto phase = arg(data)*180/M_PI;
auto deltaphase = arg(delta->data)*180/M_PI;
auto phasediff = phase - deltaphase;
@ -282,10 +291,14 @@ QString Marker::readableData(Format f)
}
case Format::RealImag: return "Δ:"+Unit::ToString(data.real() - delta->data.real(), "", " ", 5) + "+"+Unit::ToString(data.imag() - delta->data.imag(), "", " ", 5)+"j";
case Format::Impedance: {
auto impedance = 50.0 * (1.0 + data) / (1.0 - data);
auto delta_impedance = 50.0 * (1.0 + delta->data) / (1.0 - delta->data);
auto impedance = Util::SparamToImpedance(data);
auto delta_impedance = Util::SparamToImpedance(delta->data);
return "Δ:"+Unit::ToString(impedance.real() - delta_impedance.real(), "Ω", "m k", 5) + "+"+Unit::ToString(impedance.imag() - delta_impedance.imag(), "Ω", "m k", 5)+"j";
}
case Format::SeriesR: return "Δ:"+Unit::ToString(Util::SparamToResistance(data) - Util::SparamToResistance(delta->data), "Ω", "m kM", 4);
case Format::Capacitance: return "Δ:"+Unit::ToString(Util::SparamToCapacitance(data, position) - Util::SparamToCapacitance(delta->data, delta->position), "F", "pnum ", 4);
case Format::Inductance: return "Δ:"+Unit::ToString(Util::SparamToInductance(data, position) - Util::SparamToInductance(delta->data, delta->position), "H", "pnum ", 4);
case Format::QualityFactor: return "ΔQ:" + Unit::ToString(Util::SparamToQualityFactor(data) - Util::SparamToQualityFactor(delta->data), "", " ", 3);
case Format::Noise: return "Δ:"+Unit::ToString(parentTrace->getNoise(position) - delta->parentTrace->getNoise(delta->position), "dbm/Hz", " ", 3);
default: return "Invalid";
}
@ -293,16 +306,20 @@ QString Marker::readableData(Format f)
break;
default:
switch(f) {
case Format::dB: return Unit::ToString(Unit::dB(data), "dB", " ", 4);
case Format::dBAngle: return Unit::ToString(Unit::dB(data), "dB", " ", 4) + "/"+Unit::ToString(arg(data)*180/M_PI, "°", " ", 4);
case Format::dB: return Unit::ToString(Util::SparamTodB(data), "dB", " ", 4);
case Format::dBAngle: return Unit::ToString(Util::SparamTodB(data), "dB", " ", 4) + "/"+Unit::ToString(arg(data)*180/M_PI, "°", " ", 4);
case Format::RealImag: return Unit::ToString(data.real(), "", " ", 5) + "+"+Unit::ToString(data.imag(), "", " ", 5)+"j";
case Format::VSWR:
if(abs(data) < 1.0) {
return "VSWR: "+Unit::ToString(((1+abs(data)) / (1-abs(data))), ":1", " ", 5);
return "VSWR: "+Unit::ToString(Util::SparamToVSWR(data), ":1", " ", 5);
} else {
return "VSWR: NaN";
}
break;
case Format::SeriesR: return Unit::ToString(Util::SparamToResistance(data), "Ω", "m kM", 4);
case Format::Capacitance: return Unit::ToString(Util::SparamToCapacitance(data, position), "F", "pnum ", 4);
case Format::Inductance: return Unit::ToString(Util::SparamToInductance(data, position), "H", "pnum ", 4);
case Format::QualityFactor: return "Q:" + Unit::ToString(Util::SparamToQualityFactor(data), "", " ", 3);
case Format::Noise: return Unit::ToString(parentTrace->getNoise(position), "dbm/Hz", " ", 3);
case Format::TOI: {
auto avgFundamental = (helperMarkers[0]->toDecibel() + helperMarkers[1]->toDecibel()) / 2;
@ -331,7 +348,7 @@ QString Marker::readableData(Format f)
if(parentTrace->isReflection()) {
return "Calculation not possible with reflection measurement";
} else {
return "Ins. Loss:"+Unit::ToString(Unit::dB(data), "dB", " ", 3);
return "Ins. Loss:"+Unit::ToString(Util::SparamTodB(data), "dB", " ", 3);
}
case Format::PhaseNoise: {
auto carrier = toDecibel();
@ -340,7 +357,7 @@ QString Marker::readableData(Format f)
}
break;
case Format::Impedance: {
auto impedance = 50.0 * (1.0 + data) / (1.0 - data);
auto impedance = Util::SparamToImpedance(data);
return Unit::ToString(impedance.real(), "Ω", "m k", 5) + "+"+Unit::ToString(impedance.imag(), "Ω", "m k", 5)+"j";
}
case Format::CenterBandwidth:
@ -853,7 +870,7 @@ void Marker::setType(Marker::Type t)
double Marker::toDecibel()
{
return Unit::dB(data);
return Util::SparamTodB(data);
}
bool Marker::isVisible()
@ -1277,11 +1294,11 @@ void Marker::update()
setPosition(peakFreq);
// find the cutoff frequency
auto index = parentTrace->index(peakFreq);
auto peakAmplitude = Unit::dB(parentTrace->sample(index).y);
auto peakAmplitude = Util::SparamTodB(parentTrace->sample(index).y);
auto cutoff = peakAmplitude + cutoffAmplitude;
int inc = type == Type::Lowpass ? 1 : -1;
while(index >= 0 && index < (int) parentTrace->size()) {
auto amplitude = Unit::dB(parentTrace->sample(index).y);
auto amplitude = Util::SparamTodB(parentTrace->sample(index).y);
if(amplitude <= cutoff) {
break;
}
@ -1307,12 +1324,12 @@ void Marker::update()
setPosition(peakFreq);
// find the cutoff frequencies
auto index = parentTrace->index(peakFreq);
auto peakAmplitude = Unit::dB(parentTrace->sample(index).y);
auto peakAmplitude = Util::SparamTodB(parentTrace->sample(index).y);
auto cutoff = peakAmplitude + cutoffAmplitude;
auto low_index = index;
while(low_index >= 0) {
auto amplitude = Unit::dB(parentTrace->sample(low_index).y);
auto amplitude = Util::SparamTodB(parentTrace->sample(low_index).y);
if(amplitude <= cutoff) {
break;
}
@ -1326,7 +1343,7 @@ void Marker::update()
auto high_index = index;
while(high_index < (int) parentTrace->size()) {
auto amplitude = Unit::dB(parentTrace->sample(high_index).y);
auto amplitude = Util::SparamTodB(parentTrace->sample(high_index).y);
if(amplitude <= cutoff) {
break;
}

View File

@ -27,6 +27,10 @@ public:
RealImag,
Impedance,
VSWR,
SeriesR,
Capacitance,
Inductance,
QualityFactor,
// Noise marker parameters
Noise,
PhaseNoise,

View File

@ -6,7 +6,7 @@
#include <QLabel>
#include <QDebug>
#include "ui_tdrexplanationwidget.h"
#include "unit.h"
#include "Util/util.h"
using namespace Math;
using namespace std;
@ -95,7 +95,7 @@ void TDR::edit()
ui->manualMag->setUnit("dBm");
ui->manualMag->setPrecision(3);
ui->manualMag->setValue(Unit::dB(manualDC));
ui->manualMag->setValue(Util::SparamTodB(manualDC));
ui->manualPhase->setUnit("°");
ui->manualPhase->setPrecision(4);
ui->manualPhase->setValue(180.0/M_PI * arg(manualDC));

View File

@ -7,8 +7,9 @@
#include <QPainter>
#include "Util/util.h"
#include "Traces/fftcomplex.h"
#include "unit.h"
#include "Util/util.h"
#include <QMouseEvent>
#include "unit.h"
Math::TimeGate::TimeGate()
{
@ -345,8 +346,8 @@ void Math::TimeGateGraph::paintEvent(QPaintEvent *event)
auto last = input[i-1];
auto now = input[i];
auto y_last = Unit::dB(last.y);
auto y_now = Unit::dB(now.y);
auto y_last = Util::SparamTodB(last.y);
auto y_now = Util::SparamTodB(now.y);
if(std::isnan(y_last) || std::isnan(y_now) || std::isinf(y_last) || std::isinf(y_now)) {
continue;
@ -366,8 +367,8 @@ void Math::TimeGateGraph::paintEvent(QPaintEvent *event)
auto x_last = input[i-1].x;
auto x_now = input[i].x;
auto f_last = Unit::dB(filter[i-1]);
auto f_now = Unit::dB(filter[i]);
auto f_last = Util::SparamTodB(filter[i-1]);
auto f_now = Util::SparamTodB(filter[i]);
if(std::isnan(f_last) || std::isnan(f_now) || std::isinf(f_last) || std::isinf(f_now)) {
continue;

View File

@ -5,7 +5,7 @@
#include <QScrollBar>
#include <QSettings>
#include <functional>
#include "unit.h"
#include "Util/util.h"
#include "Marker/marker.h"
using namespace std;
@ -871,7 +871,7 @@ std::vector<double> Trace::findPeakFrequencies(unsigned int maxPeaks, double min
double max_dbm = -200.0;
double min_dbm = 200.0;
for(auto d : lastMath->rData()) {
double dbm = Unit::dB(d.y);
double dbm = Util::SparamTodB(d.y);
if((dbm >= max_dbm) && (min_dbm <= dbm - minValley)) {
// potential peak frequency
frequency = d.x;
@ -945,7 +945,7 @@ double Trace::getNoise(double frequency)
return std::numeric_limits<double>::quiet_NaN();
}
// convert to dbm
auto dbm = Unit::dB(lastMath->getInterpolatedSample(frequency).y);
auto dbm = Util::SparamTodB(lastMath->getInterpolatedSample(frequency).y);
// convert to 1Hz bandwidth
dbm -= 10*log10(settings.SA.RBW);
return dbm;

View File

@ -11,6 +11,7 @@
#include <QDebug>
#include <QMenu>
#include "unit.h"
#include "Util/util.h"
TraceWidget::TraceWidget(TraceModel &model, QWidget *parent) :
QWidget(parent),
@ -172,7 +173,7 @@ void TraceWidget::SetupSCPI()
if(std::isnan(d.x)) {
return "NaN";
}
return QString::number(Unit::dB(d.y.real()));
return QString::number(Util::SparamTodB(d.y.real()));
} else {
if(std::isnan(d.x)) {
return "NaN,NaN";

View File

@ -764,13 +764,18 @@ TraceXYPlot::XAxisMode TraceXYPlot::AxisModeFromName(QString name)
QString TraceXYPlot::AxisTypeToName(TraceXYPlot::YAxisType type)
{
switch(type) {
case YAxisType::Magnitude: return "Magnitude"; break;
case YAxisType::Phase: return "Phase"; break;
case YAxisType::VSWR: return "VSWR"; break;
case YAxisType::ImpulseReal: return "Impulse Response (Real)"; break;
case YAxisType::ImpulseMag: return "Impulse Response (Magnitude)"; break;
case YAxisType::Step: return "Step Response"; break;
case YAxisType::Impedance: return "Impedance"; break;
case YAxisType::Disabled: return "Disabled";
case YAxisType::Magnitude: return "Magnitude";
case YAxisType::Phase: return "Phase";
case YAxisType::VSWR: return "VSWR";
case YAxisType::SeriesR: return "Resistance";
case YAxisType::Capacitance: return "Capacitance";
case YAxisType::Inductance: return "Inductance";
case YAxisType::QualityFactor: return "Quality Factor";
case YAxisType::ImpulseReal: return "Impulse Response (Real)";
case YAxisType::ImpulseMag: return "Impulse Response (Magnitude)";
case YAxisType::Step: return "Step Response";
case YAxisType::Impedance: return "Impedance";
default: return "Unknown";
}
}
@ -827,6 +832,10 @@ bool TraceXYPlot::supported(Trace *t, TraceXYPlot::YAxisType type)
case YAxisType::Disabled:
return false;
case YAxisType::VSWR:
case YAxisType::SeriesR:
case YAxisType::Capacitance:
case YAxisType::Inductance:
case YAxisType::QualityFactor:
if(!t->isReflection()) {
return false;
}
@ -863,21 +872,31 @@ QPointF TraceXYPlot::traceToCoordinate(Trace *t, unsigned int sample, TraceXYPlo
}
switch(type) {
case YAxisType::Magnitude:
ret.setY(Unit::dB(data.y));
ret.setY(Util::SparamTodB(data.y));
break;
case YAxisType::Phase:
ret.setY(arg(data.y) * 180.0 / M_PI);
ret.setY(Util::SparamToDegree(data.y));
break;
case YAxisType::VSWR:
if(abs(data.y) < 1.0) {
ret.setY((1+abs(data.y)) / (1-abs(data.y)));
}
ret.setY(Util::SparamToVSWR(data.y));
break;
case YAxisType::SeriesR:
ret.setY(Util::SparamToResistance(data.y));
break;
case YAxisType::Capacitance:
ret.setY(Util::SparamToCapacitance(data.y, data.x));
break;
case YAxisType::Inductance:
ret.setY(Util::SparamToInductance(data.y, data.x));
break;
case YAxisType::QualityFactor:
ret.setY(Util::SparamToQualityFactor(data.y));
break;
case YAxisType::ImpulseReal:
ret.setY(real(data.y));
break;
case YAxisType::ImpulseMag:
ret.setY(Unit::dB(data.y));
ret.setY(Util::SparamTodB(data.y));
break;
case YAxisType::Step:
ret.setY(t->sample(sample, Trace::SampleType::TimeStep).y.real());
@ -885,7 +904,7 @@ QPointF TraceXYPlot::traceToCoordinate(Trace *t, unsigned int sample, TraceXYPlo
case YAxisType::Impedance: {
double step = t->sample(sample, Trace::SampleType::TimeStep).y.real();
if(abs(step) < 1.0) {
ret.setY(50 * (1.0+step) / (1.0-step));
ret.setY(Util::SparamToImpedance(step).real());
}
}
break;

View File

@ -12,16 +12,21 @@ public:
TraceXYPlot(TraceModel &model, QWidget *parent = nullptr);
enum class YAxisType {
Disabled = 0,
Disabled,
// S parameter options
Magnitude = 1,
Phase = 2,
VSWR = 3,
Magnitude,
Phase,
VSWR,
// derived parameter options
SeriesR,
Capacitance,
Inductance,
QualityFactor,
// TDR options
ImpulseReal = 4,
ImpulseMag = 5,
Step = 6,
Impedance = 7,
ImpulseReal,
ImpulseMag,
Step,
Impedance,
Last,
};
static const std::set<YAxisType> YAxisTypes;
@ -62,9 +67,9 @@ private slots:
void updateAxisTicks();
private:
static constexpr int AxisLabelSize = 10;
QString AxisTypeToName(YAxisType type);
QString AxisTypeToName(XAxisType type);
QString AxisModeToName(XAxisMode mode);
static QString AxisTypeToName(YAxisType type);
static QString AxisTypeToName(XAxisType type);
static QString AxisModeToName(XAxisMode mode);
XAxisType XAxisTypeFromName(QString name);
YAxisType YAxisTypeFromName(QString name);
XAxisMode AxisModeFromName(QString name);

View File

@ -10,6 +10,13 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
plot(plot)
{
ui->setupUi(this);
ui->Y1type->clear();
ui->Y2type->clear();
for(int i=0;i<(int) TraceXYPlot::YAxisType::Last;i++) {
ui->Y1type->addItem(TraceXYPlot::AxisTypeToName((TraceXYPlot::YAxisType) i));
ui->Y2type->addItem(TraceXYPlot::AxisTypeToName((TraceXYPlot::YAxisType) i));
}
// Setup GUI connections
connect(ui->Y1type, qOverload<int>(&QComboBox::currentIndexChanged), [this](int index) {
@ -69,7 +76,6 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
connect(ui->XType, qOverload<int>(&QComboBox::currentIndexChanged), this, &XYplotAxisDialog::XAxisTypeChanged);
// Fill initial values
// assume same order in YAxisType enum as in ComboBox items
ui->Y1type->setCurrentIndex((int) plot->YAxis[0].type);
if(plot->YAxis[0].log) {
ui->Y1log->setChecked(true);
@ -175,6 +181,10 @@ std::set<TraceXYPlot::YAxisType> XYplotAxisDialog::supportedYAxis(TraceXYPlot::X
ret.insert(TraceXYPlot::YAxisType::Magnitude);
ret.insert(TraceXYPlot::YAxisType::Phase);
ret.insert(TraceXYPlot::YAxisType::VSWR);
ret.insert(TraceXYPlot::YAxisType::SeriesR);
ret.insert(TraceXYPlot::YAxisType::Capacitance);
ret.insert(TraceXYPlot::YAxisType::Inductance);
ret.insert(TraceXYPlot::YAxisType::QualityFactor);
break;
case TraceXYPlot::XAxisType::Time:
case TraceXYPlot::XAxisType::Distance:

View File

@ -9,7 +9,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>689</width>
<width>773</width>
<height>282</height>
</rect>
</property>
@ -49,48 +49,7 @@
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="Y1type">
<item>
<property name="text">
<string>Disabled</string>
</property>
</item>
<item>
<property name="text">
<string>Magnitude</string>
</property>
</item>
<item>
<property name="text">
<string>Phase</string>
</property>
</item>
<item>
<property name="text">
<string>VSWR</string>
</property>
</item>
<item>
<property name="text">
<string>Impulse Response (real)</string>
</property>
</item>
<item>
<property name="text">
<string>Impulse Response (mag)</string>
</property>
</item>
<item>
<property name="text">
<string>Step Response</string>
</property>
</item>
<item>
<property name="text">
<string>Impedance</string>
</property>
</item>
</widget>
<widget class="QComboBox" name="Y1type"/>
</item>
</layout>
</item>
@ -219,48 +178,7 @@
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="Y2type">
<item>
<property name="text">
<string>Disabled</string>
</property>
</item>
<item>
<property name="text">
<string>Magnitude</string>
</property>
</item>
<item>
<property name="text">
<string>Phase</string>
</property>
</item>
<item>
<property name="text">
<string>VSWR</string>
</property>
</item>
<item>
<property name="text">
<string>Impulse Response (real)</string>
</property>
</item>
<item>
<property name="text">
<string>Impulse Response (mag)</string>
</property>
</item>
<item>
<property name="text">
<string>Step Response</string>
</property>
</item>
<item>
<property name="text">
<string>Impedance</string>
</property>
</item>
</widget>
<widget class="QComboBox" name="Y2type"/>
</item>
</layout>
</item>

View File

@ -1,6 +1,10 @@
#ifndef UTILH_H
#define UTILH_H
#include <complex>
#include <math.h>
#include <limits>
namespace Util {
template<typename T> T Scale(T value, T from_low, T from_high, T to_low, T to_high) {
value -= from_low;
@ -8,6 +12,42 @@ namespace Util {
value += to_low;
return value;
}
static inline double SparamTodB(double d) {
return 20*log10(d);
}
static inline double SparamTodB(std::complex<double> d) {
return SparamTodB(abs(d));
}
static inline double SparamToDegree(std::complex<double> d) {
return (arg(d) * 180.0 / M_PI);
}
static inline double SparamToVSWR(double d) {
if(abs(d) < 1.0) {
return (1+abs(d)) / (1-abs(d));
} else {
return std::numeric_limits<double>::quiet_NaN();
}
}
static inline double SparamToVSWR(std::complex<double> d) {
return SparamToVSWR(abs(d));
}
static inline std::complex<double> SparamToImpedance(std::complex<double> d) {
return 50.0 * (1.0 + d) / (1.0 - d);
}
// all these conversions assume series connection of real and imag part
static inline double SparamToResistance(std::complex<double> d) {
return SparamToImpedance(d).real();
}
static inline double SparamToCapacitance(std::complex<double> d, double freq) {
return -1.0 / (SparamToImpedance(d).imag() * 2.0 * M_PI * freq);
}
static inline double SparamToInductance(std::complex<double> d, double freq) {
return SparamToImpedance(d).imag() / (2.0 * M_PI * freq);
}
static inline double SparamToQualityFactor(std::complex<double> d) {
return abs(d.imag()) / d.real();
}
}
#endif // UTILH_H

View File

@ -3,7 +3,7 @@
#include <QCheckBox>
#include <cmath>
#include <QDebug>
#include "unit.h"
#include "Util/util.h"
using namespace std;
@ -244,7 +244,7 @@ void PortExtension::measurementCompleted(std::vector<Protocol::Datapoint> m)
}
double x = sqrt(p.frequency / m.back().frequency);
double y = Unit::dB(reflection);
double y = Util::SparamTodB(reflection);
att_x.push_back(x);
att_y.push_back(y);
avg_x += x;

View File

@ -6,7 +6,7 @@
#include <cmath>
#include <cctype>
#include <string>
#include "unit.h"
#include "Util/util.h"
using namespace std;
@ -74,7 +74,7 @@ void Touchstone::toFile(string filename, Scale unit, Format format)
out << abs(c) << " " << arg(c) / M_PI * 180.0;
break;
case Format::DBAngle:
out << Unit::dB(c) << " " << arg(c) / M_PI * 180.0;
out << Util::SparamTodB(c) << " " << arg(c) / M_PI * 180.0;
break;
}
};

View File

@ -87,13 +87,3 @@ double Unit::SIPrefixToFactor(char prefix)
default: return 1e0; break;
}
}
double Unit::dB(double d)
{
return 20*log10(d);
}
double Unit::dB(std::complex<double> d)
{
return dB(abs(d));
}

View File

@ -10,8 +10,6 @@ namespace Unit
// prefixed need to be in ascending order (e.g. "m kMG" is okay, whjle "MkG" does not work)
QString ToString(double value, QString unit = QString(), QString prefixes = " ", int precision = 6);
double SIPrefixToFactor(char prefix);
double dB(std::complex<double> d);
double dB(double d);
};
#endif // UNIT_H