Merge branch 'master' of github.com:jankae/LibreVNA

This commit is contained in:
Jan Käberich 2022-03-28 22:07:20 +02:00
commit ea6fdac2a4
49 changed files with 637 additions and 348 deletions

View file

@ -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:

View file

@ -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">

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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) {

View file

@ -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">

View file

@ -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);
}
}
}

View file

@ -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:

View file

@ -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;
}

View file

@ -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:

View file

@ -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;
};

View file

@ -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

View file

@ -34,6 +34,7 @@ private:
unsigned int ports;
unsigned int points;
double lowerFreq, upperFreq;
double referenceImpedance;
bool freqsSet;
};

View file

@ -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";