mirror of
https://github.com/jankae/LibreVNA.git
synced 2026-04-04 14:07:30 +00:00
Merge branch 'master' of github.com:jankae/LibreVNA
This commit is contained in:
commit
ea6fdac2a4
49 changed files with 637 additions and 348 deletions
|
|
@ -282,7 +282,7 @@ QString Marker::readableData(Format f)
|
|||
return Unit::ToString(data.real(), "", " ", 5) + "+"+Unit::ToString(data.imag(), "", " ", 5)+"j";
|
||||
case Format::Impedance: {
|
||||
auto step = parentTrace->sample(parentTrace->index(position), true).y.real();
|
||||
auto impedance = Util::SparamToImpedance(step).real();
|
||||
auto impedance = Util::SparamToImpedance(step, trace()->getReferenceImpedance()).real();
|
||||
return Unit::ToString(impedance, "Ω", "m kM", 3);
|
||||
}
|
||||
break;
|
||||
|
|
@ -301,8 +301,8 @@ QString Marker::readableData(Format f)
|
|||
case Format::Impedance: {
|
||||
auto step = parentTrace->sample(parentTrace->index(position), true).y.real();
|
||||
auto stepDelta = delta->parentTrace->sample(delta->parentTrace->index(delta->position), true).y.real();
|
||||
auto impedance = Util::SparamToImpedance(step).real();
|
||||
auto impedanceDelta = Util::SparamToImpedance(stepDelta).real();
|
||||
auto impedance = Util::SparamToImpedance(step, trace()->getReferenceImpedance()).real();
|
||||
auto impedanceDelta = Util::SparamToImpedance(stepDelta, trace()->getReferenceImpedance()).real();
|
||||
return "Δ:"+Unit::ToString(impedance - impedanceDelta, "Ω", "m kM", 3);
|
||||
}
|
||||
break;
|
||||
|
|
@ -340,13 +340,13 @@ 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 = Util::SparamToImpedance(data);
|
||||
auto delta_impedance = Util::SparamToImpedance(delta->data);
|
||||
auto impedance = Util::SparamToImpedance(data, trace()->getReferenceImpedance());
|
||||
auto delta_impedance = Util::SparamToImpedance(delta->data, trace()->getReferenceImpedance());
|
||||
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::SeriesR: return "Δ:"+Unit::ToString(Util::SparamToResistance(data, trace()->getReferenceImpedance()) - Util::SparamToResistance(delta->data, trace()->getReferenceImpedance()), "Ω", "m kM", 4);
|
||||
case Format::Capacitance: return "Δ:"+Unit::ToString(Util::SparamToCapacitance(data, position, trace()->getReferenceImpedance()) - Util::SparamToCapacitance(delta->data, delta->position, trace()->getReferenceImpedance()), "F", "pnum ", 4);
|
||||
case Format::Inductance: return "Δ:"+Unit::ToString(Util::SparamToInductance(data, position, trace()->getReferenceImpedance()) - Util::SparamToInductance(delta->data, delta->position, trace()->getReferenceImpedance()), "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";
|
||||
|
|
@ -368,9 +368,9 @@ QString Marker::readableData(Format f)
|
|||
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::SeriesR: return Unit::ToString(Util::SparamToResistance(data, trace()->getReferenceImpedance()), "Ω", "m kM", 4);
|
||||
case Format::Capacitance: return Unit::ToString(Util::SparamToCapacitance(data, position, trace()->getReferenceImpedance()), "F", "pnum ", 4);
|
||||
case Format::Inductance: return Unit::ToString(Util::SparamToInductance(data, position, trace()->getReferenceImpedance()), "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: {
|
||||
|
|
@ -409,7 +409,7 @@ QString Marker::readableData(Format f)
|
|||
}
|
||||
break;
|
||||
case Format::Impedance: {
|
||||
auto impedance = Util::SparamToImpedance(data);
|
||||
auto impedance = Util::SparamToImpedance(data, trace()->getReferenceImpedance());
|
||||
return Unit::ToString(impedance.real(), "Ω", "m k", 5) + "+"+Unit::ToString(impedance.imag(), "Ω", "m k", 5)+"j";
|
||||
}
|
||||
case Format::CenterBandwidth:
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>856</width>
|
||||
<height>259</height>
|
||||
<width>881</width>
|
||||
<height>334</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
|
@ -16,11 +16,11 @@
|
|||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="0,0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,1">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
|
|
@ -72,6 +72,25 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="title">
|
||||
<string>Reference Impedance</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<item row="0" column="1">
|
||||
<widget class="SIUnitEdit" name="impedance"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Impedance:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ Trace::Trace(QString name, QColor color, LiveParameter live)
|
|||
_liveParam(live),
|
||||
vFactor(0.66),
|
||||
reflection(true),
|
||||
reference_impedance(50.0),
|
||||
visible(true),
|
||||
paused(false),
|
||||
createdFromFile(false),
|
||||
|
|
@ -61,7 +62,7 @@ void Trace::clear() {
|
|||
emit outputSamplesChanged(0, 0);
|
||||
}
|
||||
|
||||
void Trace::addData(const Trace::Data& d, DataType domain) {
|
||||
void Trace::addData(const Trace::Data& d, DataType domain, double reference_impedance) {
|
||||
if(this->domain != domain) {
|
||||
clear();
|
||||
this->domain = domain;
|
||||
|
|
@ -100,6 +101,10 @@ void Trace::addData(const Trace::Data& d, DataType domain) {
|
|||
// insert at this position
|
||||
data.insert(lower, d);
|
||||
}
|
||||
if(this->reference_impedance != reference_impedance) {
|
||||
this->reference_impedance = reference_impedance;
|
||||
emit typeChanged(this);
|
||||
}
|
||||
success();
|
||||
emit outputSamplesChanged(index, index + 1);
|
||||
}
|
||||
|
|
@ -154,6 +159,7 @@ void Trace::fillFromTouchstone(Touchstone &t, unsigned int parameter)
|
|||
reflection = false;
|
||||
}
|
||||
createdFromFile = true;
|
||||
reference_impedance = t.getReferenceImpedance();
|
||||
emit typeChanged(this);
|
||||
emit outputSamplesChanged(0, data.size());
|
||||
}
|
||||
|
|
@ -233,7 +239,7 @@ QString Trace::fillFromCSV(CSV &csv, unsigned int parameter)
|
|||
return traceName;
|
||||
}
|
||||
|
||||
void Trace::fillFromDatapoints(Trace &S11, Trace &S12, Trace &S21, Trace &S22, const std::vector<Protocol::Datapoint> &data)
|
||||
void Trace::fillFromDatapoints(Trace &S11, Trace &S12, Trace &S21, Trace &S22, const std::vector<VNAData> &data)
|
||||
{
|
||||
S11.clear();
|
||||
S12.clear();
|
||||
|
|
@ -242,13 +248,13 @@ void Trace::fillFromDatapoints(Trace &S11, Trace &S12, Trace &S21, Trace &S22, c
|
|||
for(auto d : data) {
|
||||
Trace::Data td;
|
||||
td.x = d.frequency;
|
||||
td.y = complex<double>(d.real_S11, d.imag_S11);
|
||||
td.y = d.S.m11;
|
||||
S11.addData(td, DataType::Frequency);
|
||||
td.y = complex<double>(d.real_S12, d.imag_S12);
|
||||
td.y = d.S.m12;
|
||||
S12.addData(td, DataType::Frequency);
|
||||
td.y = complex<double>(d.real_S21, d.imag_S21);
|
||||
td.y = d.S.m21;
|
||||
S21.addData(td, DataType::Frequency);
|
||||
td.y = complex<double>(d.real_S22, d.imag_S22);
|
||||
td.y = d.S.m22;
|
||||
S22.addData(td, DataType::Frequency);
|
||||
}
|
||||
}
|
||||
|
|
@ -287,6 +293,11 @@ void Trace::removeMarker(Marker *m)
|
|||
emit markerRemoved(m);
|
||||
}
|
||||
|
||||
double Trace::getReferenceImpedance() const
|
||||
{
|
||||
return reference_impedance;
|
||||
}
|
||||
|
||||
const std::vector<Trace::MathInfo>& Trace::getMathOperations() const
|
||||
{
|
||||
return mathOps;
|
||||
|
|
@ -474,12 +485,13 @@ std::vector<Trace *> Trace::createFromCSV(CSV &csv)
|
|||
return traces;
|
||||
}
|
||||
|
||||
std::vector<Protocol::Datapoint> Trace::assembleDatapoints(const Trace &S11, const Trace &S12, const Trace &S21, const Trace &S22)
|
||||
std::vector<VNAData> Trace::assembleDatapoints(const Trace &S11, const Trace &S12, const Trace &S21, const Trace &S22)
|
||||
{
|
||||
vector<Protocol::Datapoint> ret;
|
||||
vector<VNAData> ret;
|
||||
|
||||
// Sanity check traces
|
||||
unsigned int samples = S11.size();
|
||||
auto impedance = S11.getReferenceImpedance();
|
||||
vector<const Trace*> traces;
|
||||
traces.push_back(&S11);
|
||||
traces.push_back(&S12);
|
||||
|
|
@ -491,6 +503,10 @@ std::vector<Protocol::Datapoint> Trace::assembleDatapoints(const Trace &S11, con
|
|||
qWarning() << "Selected traces do not have the same size";
|
||||
return ret;
|
||||
}
|
||||
if(t->getReferenceImpedance() != impedance) {
|
||||
qWarning() << "Selected traces do not have the same reference impedance";
|
||||
return ret;
|
||||
}
|
||||
if(t->outputType() != Trace::DataType::Frequency) {
|
||||
qWarning() << "Selected trace not in frequency domain";
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@
|
|||
#include "csv.h"
|
||||
#include "Device/device.h"
|
||||
#include "Math/tracemath.h"
|
||||
#include "Tools/parameters.h"
|
||||
#include "tracemodel.h"
|
||||
#include "VNA/vnadata.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <complex>
|
||||
|
|
@ -41,15 +44,14 @@ public:
|
|||
Invalid,
|
||||
};
|
||||
|
||||
|
||||
void clear();
|
||||
void addData(const Data& d, DataType domain);
|
||||
void addData(const Data& d, DataType domain, double reference_impedance = 50.0);
|
||||
void addData(const Data& d, const Protocol::SpectrumAnalyzerSettings& s);
|
||||
void setName(QString name);
|
||||
void setVelocityFactor(double v);
|
||||
void fillFromTouchstone(Touchstone &t, unsigned int parameter);
|
||||
QString fillFromCSV(CSV &csv, unsigned int parameter); // returns the suggested trace name (not yet set in member data)
|
||||
static void fillFromDatapoints(Trace &S11, Trace &S12, Trace &S21, Trace &S22, const std::vector<Protocol::Datapoint> &data);
|
||||
static void fillFromDatapoints(Trace &S11, Trace &S12, Trace &S21, Trace &S22, const std::vector<VNAData> &data);
|
||||
void fromLivedata(LivedataType type, LiveParameter param);
|
||||
QString name() { return _name; };
|
||||
QColor color() { return _color; };
|
||||
|
|
@ -134,7 +136,7 @@ public:
|
|||
|
||||
// Assembles datapoints as received from the VNA from four S parameter traces. Requires that all traces are in the frequency domain,
|
||||
// have the same number of samples and their samples must be at the same frequencies across all traces
|
||||
static std::vector<Protocol::Datapoint> assembleDatapoints(const Trace &S11, const Trace &S12, const Trace &S21, const Trace &S22);
|
||||
static std::vector<VNAData> assembleDatapoints(const Trace &S11, const Trace &S12, const Trace &S21, const Trace &S22);
|
||||
|
||||
static LiveParameter ParameterFromString(QString s);
|
||||
static QString ParameterToString(LiveParameter p);
|
||||
|
|
@ -144,6 +146,8 @@ public:
|
|||
static LivedataType TypeFromString(QString s);
|
||||
static QString TypeToString(LivedataType t);
|
||||
|
||||
double getReferenceImpedance() const;
|
||||
|
||||
public slots:
|
||||
void setVisible(bool visible);
|
||||
void setColor(QColor color);
|
||||
|
|
@ -174,6 +178,7 @@ private:
|
|||
bool paused;
|
||||
bool createdFromFile;
|
||||
bool calibration;
|
||||
double reference_impedance;
|
||||
DataType domain;
|
||||
QString filename;
|
||||
unsigned int fileParameter;
|
||||
|
|
|
|||
|
|
@ -81,6 +81,11 @@ static void createLogarithmicTicks(vector<double>& ticks, double start, double s
|
|||
} while(div <= stop);
|
||||
}
|
||||
|
||||
YAxis::YAxis()
|
||||
{
|
||||
type = Type::Magnitude;
|
||||
}
|
||||
|
||||
double YAxis::sampleToCoordinate(Trace::Data data, Trace *t, unsigned int sample)
|
||||
{
|
||||
switch(type) {
|
||||
|
|
@ -104,11 +109,11 @@ double YAxis::sampleToCoordinate(Trace::Data data, Trace *t, unsigned int sample
|
|||
case YAxis::Type::Imaginary:
|
||||
return data.y.imag();
|
||||
case YAxis::Type::SeriesR:
|
||||
return Util::SparamToResistance(data.y);
|
||||
return Util::SparamToResistance(data.y, t->getReferenceImpedance());
|
||||
case YAxis::Type::Reactance:
|
||||
return Util::SparamToImpedance(data.y).imag();
|
||||
return Util::SparamToImpedance(data.y, t->getReferenceImpedance()).imag();
|
||||
case YAxis::Type::Capacitance:
|
||||
return Util::SparamToCapacitance(data.y, data.x);
|
||||
return Util::SparamToCapacitance(data.y, data.x, t->getReferenceImpedance());
|
||||
case YAxis::Type::Inductance:
|
||||
return Util::SparamToInductance(data.y, data.x);
|
||||
case YAxis::Type::QualityFactor:
|
||||
|
|
@ -159,7 +164,7 @@ double YAxis::sampleToCoordinate(Trace::Data data, Trace *t, unsigned int sample
|
|||
}
|
||||
double step = t->sample(sample, true).y.real();
|
||||
if(abs(step) < 1.0) {
|
||||
return Util::SparamToImpedance(step).real();
|
||||
return Util::SparamToImpedance(step, t->getReferenceImpedance()).real();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -246,7 +251,7 @@ QString YAxis::Unit(Type type, TraceModel::DataSource source)
|
|||
case Type::Reactance: return "Ω";
|
||||
case Type::Capacitance: return "F";
|
||||
case Type::Inductance: return "H";
|
||||
case Type::Last: return "";
|
||||
default: return "";
|
||||
}
|
||||
} else if(source == TraceModel::DataSource::SA) {
|
||||
switch(type) {
|
||||
|
|
@ -280,7 +285,7 @@ QString YAxis::Prefixes(Type type, TraceModel::DataSource source)
|
|||
case Type::Reactance: return "m kM";
|
||||
case Type::Capacitance: return "pnum ";
|
||||
case Type::Inductance: return "pnum ";
|
||||
case Type::Last: return " ";
|
||||
default: return " ";
|
||||
}
|
||||
} else if(source == TraceModel::DataSource::SA) {
|
||||
switch(type) {
|
||||
|
|
@ -358,8 +363,14 @@ bool Axis::getLog() const
|
|||
return log;
|
||||
}
|
||||
|
||||
XAxis::XAxis()
|
||||
{
|
||||
type = Type::Frequency;
|
||||
}
|
||||
|
||||
double XAxis::sampleToCoordinate(Trace::Data data, Trace *t, unsigned int sample)
|
||||
{
|
||||
Q_UNUSED(sample)
|
||||
switch(type) {
|
||||
case Type::Distance:
|
||||
if(!t) {
|
||||
|
|
@ -430,6 +441,16 @@ XAxis::Type XAxis::getType() const
|
|||
return type;
|
||||
}
|
||||
|
||||
Axis::Axis()
|
||||
{
|
||||
log = false;
|
||||
autorange = true;
|
||||
rangeMin = -1.0;
|
||||
rangeMax = 1.0;
|
||||
rangeDiv = 1.0;
|
||||
ticks.clear();
|
||||
}
|
||||
|
||||
double Axis::transform(double value, double to_low, double to_high)
|
||||
{
|
||||
return Util::Scale(value, rangeMin, rangeMax, to_low, to_high, log);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
class Axis {
|
||||
public:
|
||||
Axis();
|
||||
virtual double sampleToCoordinate(Trace::Data data, Trace *t = nullptr, unsigned int sample = 0) = 0;
|
||||
double transform(double value, double to_low, double to_high);
|
||||
double inverseTransform(double value, double to_low, double to_high);
|
||||
|
|
@ -55,6 +56,7 @@ public:
|
|||
Impedance,
|
||||
Last,
|
||||
};
|
||||
YAxis();
|
||||
double sampleToCoordinate(Trace::Data data, Trace *t = nullptr, unsigned int sample = 0) override;
|
||||
void set(Type type, bool log, bool autorange, double min, double max, double div);
|
||||
static QString TypeToName(Type type);
|
||||
|
|
@ -80,6 +82,7 @@ public:
|
|||
Power,
|
||||
Last,
|
||||
};
|
||||
XAxis();
|
||||
double sampleToCoordinate(Trace::Data data, Trace *t = nullptr, unsigned int sample = 0) override;
|
||||
void set(Type type, bool log, bool autorange, double min, double max, double div);
|
||||
static QString TypeToName(Type type);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ TraceEditDialog::TraceEditDialog(Trace &t, QWidget *parent) :
|
|||
ui->name->setText(t.name());
|
||||
ui->color->setColor(trace.color());
|
||||
ui->vFactor->setValue(t.velocityFactor());
|
||||
ui->impedance->setUnit("Ω");
|
||||
ui->impedance->setPrecision(3);
|
||||
ui->impedance->setValue(t.getReferenceImpedance());
|
||||
|
||||
connect(ui->bLive, &QPushButton::clicked, [=](bool live) {
|
||||
if(live) {
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1038</width>
|
||||
<height>365</height>
|
||||
<width>931</width>
|
||||
<height>392</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5" stretch="0,1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6" stretch="0,1">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
|
|
@ -112,6 +112,24 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Reference impedance:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="SIUnitEdit" name="impedance">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stack">
|
||||
<property name="currentIndex">
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ void TraceModel::clearLiveData()
|
|||
}
|
||||
}
|
||||
|
||||
void TraceModel::addVNAData(const Protocol::Datapoint &d, TraceMath::DataType datatype)
|
||||
void TraceModel::addVNAData(const VNAData& d, TraceMath::DataType datatype)
|
||||
{
|
||||
source = DataSource::VNA;
|
||||
for(auto t : traces) {
|
||||
|
|
@ -225,15 +225,15 @@ void TraceModel::addVNAData(const Protocol::Datapoint &d, TraceMath::DataType da
|
|||
return;
|
||||
}
|
||||
switch(t->liveParameter()) {
|
||||
case Trace::LiveParameter::S11: td.y = complex<double>(d.real_S11, d.imag_S11); break;
|
||||
case Trace::LiveParameter::S12: td.y = complex<double>(d.real_S12, d.imag_S12); break;
|
||||
case Trace::LiveParameter::S21: td.y = complex<double>(d.real_S21, d.imag_S21); break;
|
||||
case Trace::LiveParameter::S22: td.y = complex<double>(d.real_S22, d.imag_S22); break;
|
||||
case Trace::LiveParameter::S11: td.y = d.S.m11; break;
|
||||
case Trace::LiveParameter::S12: td.y = d.S.m12; break;
|
||||
case Trace::LiveParameter::S21: td.y = d.S.m21; break;
|
||||
case Trace::LiveParameter::S22: td.y = d.S.m22; break;
|
||||
default:
|
||||
// not a VNA trace, skip
|
||||
continue;
|
||||
}
|
||||
t->addData(td, datatype);
|
||||
t->addData(td, datatype, d.reference_impedance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "Device/device.h"
|
||||
#include "savable.h"
|
||||
#include "trace.h"
|
||||
#include "VNA/vnadata.h"
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <vector>
|
||||
|
|
@ -64,7 +65,7 @@ signals:
|
|||
|
||||
public slots:
|
||||
void clearLiveData();
|
||||
void addVNAData(const Protocol::Datapoint& d, TraceMath::DataType datatype);
|
||||
void addVNAData(const VNAData& d, TraceMath::DataType datatype);
|
||||
void addSAData(const Protocol::SpectrumAnalyzerResult& d, const Protocol::SpectrumAnalyzerSettings& settings);
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -460,6 +460,12 @@ void TracePlot::checkIfStillSupported(Trace *t)
|
|||
if(!configureForTrace(t)) {
|
||||
enableTrace(t, false);
|
||||
}
|
||||
// remove non-supported traces after graph has been adjusted
|
||||
for(auto t : activeTraces()) {
|
||||
if(!supported(t)) {
|
||||
enableTrace(t, false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "QFileDialog"
|
||||
#include "Util/util.h"
|
||||
#include "appwindow.h"
|
||||
#include "CustomWidgets/informationbox.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <array>
|
||||
|
|
@ -20,7 +21,9 @@ TraceSmithChart::TraceSmithChart(TraceModel &model, QWidget *parent)
|
|||
: TracePlot(model, parent)
|
||||
{
|
||||
limitToSpan = true;
|
||||
limitToEdge = true;
|
||||
edgeReflection = 1.0;
|
||||
Z0 = 50.0;
|
||||
initializeTraceInfo();
|
||||
}
|
||||
|
||||
|
|
@ -30,6 +33,7 @@ nlohmann::json TraceSmithChart::toJSON()
|
|||
j["limit_to_span"] = limitToSpan;
|
||||
j["limit_to_edge"] = limitToEdge;
|
||||
j["edge_reflection"] = edgeReflection;
|
||||
j["Z0"] = Z0;
|
||||
nlohmann::json jtraces;
|
||||
for(auto t : traces) {
|
||||
if(t.second) {
|
||||
|
|
@ -50,6 +54,7 @@ void TraceSmithChart::fromJSON(nlohmann::json j)
|
|||
limitToSpan = j.value("limit_to_span", true);
|
||||
limitToEdge = j.value("limit_to_edge", false);
|
||||
edgeReflection = j.value("edge_reflection", 1.0);
|
||||
Z0 = j.value("Z0", 50.0);
|
||||
for(unsigned int hash : j["traces"]) {
|
||||
// attempt to find the traces with this hash
|
||||
bool found = false;
|
||||
|
|
@ -106,6 +111,10 @@ void TraceSmithChart::axisSetupDialog()
|
|||
ui->zoomReflection->setValue(edgeReflection);
|
||||
ui->zoomFactor->setValue(1.0/edgeReflection);
|
||||
|
||||
ui->impedance->setUnit("Ω");
|
||||
ui->impedance->setPrecision(3);
|
||||
ui->impedance->setValue(Z0);
|
||||
|
||||
auto model = new SmithChartContantLineModel(*this);
|
||||
ui->lineTable->setModel(model);
|
||||
ui->lineTable->setItemDelegateForColumn(SmithChartContantLineModel::ColIndexType, new SmithChartTypeDelegate);
|
||||
|
|
@ -124,6 +133,15 @@ void TraceSmithChart::axisSetupDialog()
|
|||
edgeReflection = ui->zoomReflection->value();
|
||||
ui->zoomFactor->setValueQuiet(1.0 / edgeReflection);
|
||||
});
|
||||
connect(ui->impedance, &SIUnitEdit::valueChanged, [=](){
|
||||
Z0 = ui->impedance->value();
|
||||
for(auto t : traces) {
|
||||
if(t.second) {
|
||||
checkIfStillSupported(t.first);
|
||||
}
|
||||
}
|
||||
ui->impedance->setValueQuiet(Z0);
|
||||
});
|
||||
connect(ui->lineTable, &QTableView::clicked, [=](const QModelIndex &index){
|
||||
if(index.column() == SmithChartContantLineModel::ColIndexColor) {
|
||||
auto line = &constantLines[index.row()];
|
||||
|
|
@ -181,8 +199,7 @@ QPoint TraceSmithChart::dataToPixel(Trace::Data d)
|
|||
if(d.x < sweep_fmin || d.x > sweep_fmax) {
|
||||
return QPoint();
|
||||
}
|
||||
return dataToPixel(d.y);
|
||||
}
|
||||
return dataToPixel(d.y);}
|
||||
|
||||
std::complex<double> TraceSmithChart::pixelToData(QPoint p)
|
||||
{
|
||||
|
|
@ -264,6 +281,20 @@ bool TraceSmithChart::markerVisible(double x)
|
|||
}
|
||||
}
|
||||
|
||||
bool TraceSmithChart::configureForTrace(Trace *t)
|
||||
{
|
||||
if(dropSupported(t)) {
|
||||
Z0 = t->getReferenceImpedance();
|
||||
for(auto t : traces) {
|
||||
if(t.second && t.first->getReferenceImpedance() != Z0) {
|
||||
enableTrace(t.first, false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TraceSmithChart::draw(QPainter &p) {
|
||||
auto pref = Preferences::getInstance();
|
||||
|
||||
|
|
@ -305,7 +336,7 @@ void TraceSmithChart::draw(QPainter &p) {
|
|||
p.drawLine(dataToPixel(complex<double>(edgeReflection,0)),dataToPixel(complex<double>(-edgeReflection,0)));
|
||||
constexpr std::array<double, 5> impedanceLines = {10, 25, 50, 100, 250};
|
||||
for(auto z : impedanceLines) {
|
||||
z /= Preferences::getInstance().Acquisition.refImp;
|
||||
z /= Z0;
|
||||
auto radius = 1.0/z;
|
||||
drawArc(SmithChartArc(QPointF(1.0, radius), radius, 0, 2*M_PI));
|
||||
drawArc(SmithChartArc(QPointF(1.0, -radius), radius, 0, 2*M_PI));
|
||||
|
|
@ -316,7 +347,7 @@ void TraceSmithChart::draw(QPainter &p) {
|
|||
pen = QPen(line.getColor(), pref.Graphs.lineWidth);
|
||||
pen.setCosmetic(true);
|
||||
p.setPen(pen);
|
||||
for(auto arc : line.getArcs()) {
|
||||
for(auto arc : line.getArcs(Z0)) {
|
||||
drawArc(arc);
|
||||
}
|
||||
}
|
||||
|
|
@ -396,11 +427,40 @@ void TraceSmithChart::draw(QPainter &p) {
|
|||
}
|
||||
}
|
||||
|
||||
void TraceSmithChart::traceDropped(Trace *t, QPoint position)
|
||||
{
|
||||
if(!supported(t) && dropSupported(t)) {
|
||||
// needs to switch to a different domain for the graph
|
||||
if(!InformationBox::AskQuestion("Reference impedance change", "You dropped a trace that is not supported with the currently selected reference impedance."
|
||||
" Do you want to remove all traces and change the graph to the correct reference imppedance?", true, "ReferenceImpedanceChangeRequest")) {
|
||||
// user declined to change domain, to not add change impedance
|
||||
return;
|
||||
}
|
||||
// attempt to configure for this trace
|
||||
configureForTrace(t);
|
||||
}
|
||||
TracePlot::traceDropped(t, position);
|
||||
}
|
||||
|
||||
bool TraceSmithChart::dropSupported(Trace *t)
|
||||
{
|
||||
if(!t->isReflection()) {
|
||||
return false;
|
||||
}
|
||||
switch(t->outputType()) {
|
||||
case Trace::DataType::Frequency:
|
||||
case Trace::DataType::Power:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
QString TraceSmithChart::mouseText(QPoint pos)
|
||||
{
|
||||
auto data = pixelToData(pos);
|
||||
if(abs(data) <= edgeReflection) {
|
||||
data = Preferences::getInstance().Acquisition.refImp * (1.0 + data) / (1.0 - data);
|
||||
data = Z0 * (1.0 + data) / (1.0 - data);
|
||||
auto ret = Unit::ToString(data.real(), "", " ", 3);
|
||||
if(data.imag() >= 0) {
|
||||
ret += "+";
|
||||
|
|
@ -477,16 +537,10 @@ void TraceSmithChart::updateContextMenu()
|
|||
|
||||
bool TraceSmithChart::supported(Trace *t)
|
||||
{
|
||||
if(!t->isReflection()) {
|
||||
return false;
|
||||
}
|
||||
switch(t->outputType()) {
|
||||
case Trace::DataType::Frequency:
|
||||
case Trace::DataType::Power:
|
||||
return true;
|
||||
default:
|
||||
if(t->getReferenceImpedance() != Z0) {
|
||||
return false;
|
||||
}
|
||||
return dropSupported(t);
|
||||
}
|
||||
|
||||
SmithChartArc::SmithChartArc(QPointF center, double radius, double startAngle, double spanAngle)
|
||||
|
|
@ -570,9 +624,8 @@ SmithChartConstantLine::SmithChartConstantLine()
|
|||
color = Qt::darkRed;
|
||||
}
|
||||
|
||||
std::vector<SmithChartArc> SmithChartConstantLine::getArcs()
|
||||
std::vector<SmithChartArc> SmithChartConstantLine::getArcs(double Z0)
|
||||
{
|
||||
double Z0 = Preferences::getInstance().Acquisition.refImp;
|
||||
std::vector<SmithChartArc> arcs;
|
||||
switch(type) {
|
||||
case Type::VSWR:
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public:
|
|||
};
|
||||
|
||||
SmithChartConstantLine();
|
||||
std::vector<SmithChartArc> getArcs();
|
||||
std::vector<SmithChartArc> getArcs(double Z0);
|
||||
QColor getColor() const;
|
||||
void setColor(const QColor &value);
|
||||
|
||||
|
|
@ -126,13 +126,17 @@ protected:
|
|||
virtual bool markerVisible(double x);
|
||||
|
||||
//void paintEvent(QPaintEvent *event) override;
|
||||
virtual bool configureForTrace(Trace *t);
|
||||
virtual void updateContextMenu() override;
|
||||
bool supported(Trace *t) override;
|
||||
virtual void draw(QPainter& painter) override;
|
||||
virtual void traceDropped(Trace *t, QPoint position) override;
|
||||
virtual bool dropSupported(Trace *t) override;
|
||||
QString mouseText(QPoint pos) override;
|
||||
bool limitToSpan;
|
||||
bool limitToEdge;
|
||||
double edgeReflection; // magnitude of reflection coefficient at the edge of the smith chart (zoom factor)
|
||||
double Z0;
|
||||
QTransform transform;
|
||||
std::vector<SmithChartConstantLine> constantLines;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ void TraceTouchstoneExport::on_buttonBox_accepted()
|
|||
if(filename.length() > 0) {
|
||||
auto ports = ui->sbPorts->value();
|
||||
auto t = Touchstone(ports);
|
||||
t.setReferenceImpedance(referenceImpedance);
|
||||
// add trace points to touchstone
|
||||
for(unsigned int s=0;s<points;s++) {
|
||||
Touchstone::Datapoint tData;
|
||||
|
|
@ -165,6 +166,7 @@ void TraceTouchstoneExport::selectionChanged(QComboBox *w)
|
|||
// the first trace has been selected, extract frequency info
|
||||
Trace *t = qvariant_cast<Trace*>(w->itemData(w->currentIndex()));
|
||||
points = t->size();
|
||||
referenceImpedance = t->getReferenceImpedance();
|
||||
ui->points->setText(QString::number(points));
|
||||
if(points > 0) {
|
||||
lowerFreq = t->minX();
|
||||
|
|
@ -179,7 +181,7 @@ void TraceTouchstoneExport::selectionChanged(QComboBox *w)
|
|||
for(auto c : v1) {
|
||||
for(int i=1;i<c->count();i++) {
|
||||
Trace *t = qvariant_cast<Trace*>(c->itemData(i));
|
||||
if(t->size() != points || (points > 0 && (t->minX() != lowerFreq || t->maxX() != upperFreq))) {
|
||||
if(t->getReferenceImpedance() != referenceImpedance || t->size() != points || (points > 0 && (t->minX() != lowerFreq || t->maxX() != upperFreq))) {
|
||||
// this trace is not available anymore
|
||||
c->removeItem(i);
|
||||
// decrement to check the next index in the next loop iteration
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ private:
|
|||
unsigned int ports;
|
||||
unsigned int points;
|
||||
double lowerFreq, upperFreq;
|
||||
double referenceImpedance;
|
||||
bool freqsSet;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,11 @@ TraceWaterfall::TraceWaterfall(TraceModel &model, QWidget *parent)
|
|||
keepDataBeyondPlotSize(false),
|
||||
maxDataSweeps(500)
|
||||
{
|
||||
plotAreaTop = 0;
|
||||
plotAreaLeft = 0;
|
||||
plotAreaWidth = 0;
|
||||
plotAreaBottom = 0;
|
||||
|
||||
xAxis.set(XAxis::Type::Frequency, false, true, 0, 6000000000, 500000000);
|
||||
yAxis.set(YAxis::Type::Magnitude, false, true, -1, 1, 1);
|
||||
initializeTraceInfo();
|
||||
|
|
@ -478,7 +483,7 @@ double TraceWaterfall::nearestTracePoint(Trace *t, QPoint pixel, double *distanc
|
|||
QString TraceWaterfall::mouseText(QPoint pos)
|
||||
{
|
||||
QString ret;
|
||||
if(QRect(plotAreaLeft, 0, plotAreaWidth + 1, plotAreaBottom).contains(pos)) {
|
||||
if(QRect(plotAreaLeft, plotAreaTop, plotAreaWidth + 1, plotAreaBottom).contains(pos)) {
|
||||
double x = xAxis.inverseTransform(pos.x(), plotAreaLeft, plotAreaLeft + plotAreaWidth);
|
||||
int significantDigits = floor(log10(abs(xAxis.getRangeMax()))) - floor(log10((abs(xAxis.getRangeMax() - xAxis.getRangeMin())) / 1000.0)) + 1;
|
||||
ret += Unit::ToString(x, xAxis.Unit(), "fpnum kMG", significantDigits) + "\n";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue