basic working wrapper

This commit is contained in:
Jan Käberich 2022-08-05 12:20:41 +02:00
parent a530cea085
commit 90ac9c57e1
25 changed files with 260 additions and 214 deletions

View File

@ -211,6 +211,7 @@ Device::Device(QString serial)
transmissionActive = false; transmissionActive = false;
// got a new connection, request info // got a new connection, request info
SendCommandWithoutPayload(Protocol::PacketType::RequestDeviceInfo); SendCommandWithoutPayload(Protocol::PacketType::RequestDeviceInfo);
SendCommandWithoutPayload(Protocol::PacketType::RequestDeviceStatus);
} }
Device::~Device() Device::~Device()

View File

@ -12,13 +12,13 @@
#include <QQueue> #include <QQueue>
#include <QTimer> #include <QTimer>
Q_DECLARE_METATYPE(Protocol::Datapoint); Q_DECLARE_METATYPE(Protocol::Datapoint)
Q_DECLARE_METATYPE(Protocol::ManualStatusV1); Q_DECLARE_METATYPE(Protocol::ManualStatusV1)
Q_DECLARE_METATYPE(Protocol::SpectrumAnalyzerResult); Q_DECLARE_METATYPE(Protocol::SpectrumAnalyzerResult)
Q_DECLARE_METATYPE(Protocol::AmplitudeCorrectionPoint); Q_DECLARE_METATYPE(Protocol::AmplitudeCorrectionPoint)
class USBInBuffer : public QObject { class USBInBuffer : public QObject {
Q_OBJECT; Q_OBJECT
public: public:
USBInBuffer(libusb_device_handle *handle, unsigned char endpoint, int buffer_size); USBInBuffer(libusb_device_handle *handle, unsigned char endpoint, int buffer_size);
~USBInBuffer(); ~USBInBuffer();

View File

@ -108,6 +108,7 @@ static constexpr VirtualDevice::Info defaultInfo = {
.supportsVNAmode = true, .supportsVNAmode = true,
.supportsSAmode = true, .supportsSAmode = true,
.supportsSGmode = true, .supportsSGmode = true,
.supportsExtRef = true,
.Limits = { .Limits = {
.minFreq = 0, .minFreq = 0,
.maxFreq = 6000000000, .maxFreq = 6000000000,
@ -127,22 +128,24 @@ static const VirtualDevice::Status defaultStatus = {
.overload = false, .overload = false,
.unlocked = false, .unlocked = false,
.unlevel = false, .unlevel = false,
.extRef = false,
}; };
VirtualDevice::VirtualDevice(QString serial) VirtualDevice::VirtualDevice(QString serial)
: QObject(), : QObject(),
info{} info{},
status{}
{ {
isCompound = false; isCompound = false;
zerospan = false; zerospan = false;
auto dev = new Device(serial); auto dev = new Device(serial);
devices.push_back(dev); devices.push_back(dev);
if(!isCompoundDevice()) { if(!isCompoundDevice()) {
// just acting as a wrapper for device, pass on signals // just acting as a wrapper for device, pass on signals
connect(dev, &Device::ConnectionLost, this, &VirtualDevice::ConnectionLost); connect(dev, &Device::ConnectionLost, this, &VirtualDevice::ConnectionLost);
connect(dev, &Device::DeviceInfoUpdated, [&](){ connect(dev, &Device::DeviceInfoUpdated, [&](){
auto i = dev->Info(); auto i = devices[0]->Info();
info.ProtocolVersion = i.ProtocolVersion; info.ProtocolVersion = i.ProtocolVersion;
info.FW_major = i.FW_major; info.FW_major = i.FW_major;
info.FW_minor = i.FW_minor; info.FW_minor = i.FW_minor;
@ -153,11 +156,12 @@ VirtualDevice::VirtualDevice(QString serial)
info.supportsVNAmode = true; info.supportsVNAmode = true;
info.supportsSAmode = true; info.supportsSAmode = true;
info.supportsSGmode = true; info.supportsSGmode = true;
info.supportsExtRef = true;
info.Limits.minFreq = i.limits_minFreq; info.Limits.minFreq = i.limits_minFreq;
info.Limits.maxFreq = i.limits_maxFreq; info.Limits.maxFreq = i.limits_maxFreq;
info.Limits.maxFreqHarmonic = i.limits_maxFreqHarmonic; info.Limits.maxFreqHarmonic = i.limits_maxFreqHarmonic;
info.Limits.minIFBW = i.limits_minIFBW; info.Limits.minIFBW = i.limits_minIFBW;
info.Limits.maxIFBW = i.limits_minIFBW; info.Limits.maxIFBW = i.limits_maxIFBW;
info.Limits.maxPoints = i.limits_maxPoints; info.Limits.maxPoints = i.limits_maxPoints;
info.Limits.mindBm = (double) i.limits_cdbm_min / 100; info.Limits.mindBm = (double) i.limits_cdbm_min / 100;
info.Limits.maxdBm = (double) i.limits_cdbm_max / 100; info.Limits.maxdBm = (double) i.limits_cdbm_max / 100;
@ -167,10 +171,11 @@ VirtualDevice::VirtualDevice(QString serial)
}); });
connect(dev, &Device::LogLineReceived, this, &VirtualDevice::LogLineReceived); connect(dev, &Device::LogLineReceived, this, &VirtualDevice::LogLineReceived);
connect(dev, &Device::DeviceStatusUpdated, [&](){ connect(dev, &Device::DeviceStatusUpdated, [&](){
status.statusString = dev->getLastDeviceInfoString(); status.statusString = devices[0]->getLastDeviceInfoString();
status.overload = dev->StatusV1().ADC_overload; status.overload = devices[0]->StatusV1().ADC_overload;
status.unlevel = dev->StatusV1().unlevel; status.unlevel = devices[0]->StatusV1().unlevel;
status.unlocked = !dev->StatusV1().LO1_locked || !dev->StatusV1().source_locked; status.unlocked = !devices[0]->StatusV1().LO1_locked || !devices[0]->StatusV1().source_locked;
status.extRef = devices[0]->StatusV1().extRefInUse;
emit StatusUpdated(status); emit StatusUpdated(status);
}); });
connect(dev, &Device::NeedsFirmwareUpdate, this, &VirtualDevice::NeedsFirmwareUpdate); connect(dev, &Device::NeedsFirmwareUpdate, this, &VirtualDevice::NeedsFirmwareUpdate);
@ -217,6 +222,13 @@ VirtualDevice::~VirtualDevice()
} }
} }
void VirtualDevice::RegisterTypes()
{
qRegisterMetaType<VirtualDevice::Status>("Status");
qRegisterMetaType<VirtualDevice::VNAMeasurement>("VNAMeasurement");
qRegisterMetaType<VirtualDevice::SAMeasurement>("SAMeasurement");
}
bool VirtualDevice::isCompoundDevice() const bool VirtualDevice::isCompoundDevice() const
{ {
return isCompound; return isCompound;
@ -267,8 +279,8 @@ const VirtualDevice::Status &VirtualDevice::getStatus(VirtualDevice *vdev)
QStringList VirtualDevice::availableVNAMeasurements() QStringList VirtualDevice::availableVNAMeasurements()
{ {
QStringList ret; QStringList ret;
for(int i=1;i<info.ports;i++) { for(int i=1;i<=info.ports;i++) {
for(int j=1;j<info.ports;i++) { for(int j=1;j<=info.ports;j++) {
ret.push_back("S"+QString::number(i)+QString::number(j)); ret.push_back("S"+QString::number(i)+QString::number(j));
} }
} }
@ -280,6 +292,9 @@ bool VirtualDevice::setVNA(const VirtualDevice::VNASettings &s, std::function<vo
if(!info.supportsVNAmode) { if(!info.supportsVNAmode) {
return false; return false;
} }
if(s.excitedPorts.size() == 0) {
return setIdle(cb);
}
zerospan = (s.freqStart == s.freqStop) && (s.dBmStart == s.dBmStop); zerospan = (s.freqStart == s.freqStop) && (s.dBmStart == s.dBmStop);
auto pref = Preferences::getInstance(); auto pref = Preferences::getInstance();
if(!isCompoundDevice()) { if(!isCompoundDevice()) {
@ -293,7 +308,7 @@ bool VirtualDevice::setVNA(const VirtualDevice::VNASettings &s, std::function<vo
sd.excitePort1 = find(s.excitedPorts.begin(), s.excitedPorts.end(), 1) != s.excitedPorts.end() ? 1 : 0; sd.excitePort1 = find(s.excitedPorts.begin(), s.excitedPorts.end(), 1) != s.excitedPorts.end() ? 1 : 0;
sd.excitePort2 = find(s.excitedPorts.begin(), s.excitedPorts.end(), 2) != s.excitedPorts.end() ? 1 : 0; sd.excitePort2 = find(s.excitedPorts.begin(), s.excitedPorts.end(), 2) != s.excitedPorts.end() ? 1 : 0;
sd.suppressPeaks = pref.Acquisition.suppressPeaks ? 1 : 0; sd.suppressPeaks = pref.Acquisition.suppressPeaks ? 1 : 0;
sd.fixedPowerSetting = pref.Acquisition.adjustPowerLevel ? 0 : 1; sd.fixedPowerSetting = pref.Acquisition.adjustPowerLevel || s.dBmStart != s.dBmStop ? 0 : 1;
sd.logSweep = s.logSweep ? 1 : 0; sd.logSweep = s.logSweep ? 1 : 0;
return devices[0]->Configure(sd, [=](Device::TransmissionResult r){ return devices[0]->Configure(sd, [=](Device::TransmissionResult r){
if(cb) { if(cb) {
@ -303,7 +318,7 @@ bool VirtualDevice::setVNA(const VirtualDevice::VNASettings &s, std::function<vo
} else { } else {
// TODO // TODO
return false; return false;
} }
} }
QString VirtualDevice::serial() QString VirtualDevice::serial()
@ -319,7 +334,7 @@ QString VirtualDevice::serial()
QStringList VirtualDevice::availableSAMeasurements() QStringList VirtualDevice::availableSAMeasurements()
{ {
QStringList ret; QStringList ret;
for(int i=1;i<info.ports;i++) { for(int i=1;i<=info.ports;i++) {
ret.push_back("PORT"+QString::number(i)); ret.push_back("PORT"+QString::number(i));
} }
return ret; return ret;
@ -394,9 +409,10 @@ bool VirtualDevice::setSG(const SGSettings &s)
bool VirtualDevice::setIdle(std::function<void (bool)> cb) bool VirtualDevice::setIdle(std::function<void (bool)> cb)
{ {
auto success = true;
results.clear(); results.clear();
for(auto dev : devices) { for(auto dev : devices) {
dev->SetIdle([&](Device::TransmissionResult r){ success &= dev->SetIdle([=](Device::TransmissionResult r){
if(cb) { if(cb) {
results[dev] = r; results[dev] = r;
if(results.size() == devices.size()) { if(results.size() == devices.size()) {
@ -413,6 +429,7 @@ bool VirtualDevice::setIdle(std::function<void (bool)> cb)
} }
}); });
} }
return success;
} }
QStringList VirtualDevice::availableExtRefInSettings() QStringList VirtualDevice::availableExtRefInSettings()
@ -451,6 +468,7 @@ bool VirtualDevice::setExtRef(QString option_in, QString option_out)
p.type = Protocol::PacketType::Reference; p.type = Protocol::PacketType::Reference;
switch(refIn) { switch(refIn) {
case Reference::TypeIn::Internal: case Reference::TypeIn::Internal:
case Reference::TypeIn::None:
p.reference.UseExternalRef = 0; p.reference.UseExternalRef = 0;
p.reference.AutomaticSwitch = 0; p.reference.AutomaticSwitch = 0;
break; break;
@ -464,6 +482,7 @@ bool VirtualDevice::setExtRef(QString option_in, QString option_out)
break; break;
} }
switch(refOut) { switch(refOut) {
case Reference::OutFreq::None:
case Reference::OutFreq::Off: p.reference.ExtRefOuputFreq = 0; break; case Reference::OutFreq::Off: p.reference.ExtRefOuputFreq = 0; break;
case Reference::OutFreq::MHZ10: p.reference.ExtRefOuputFreq = 10000000; break; case Reference::OutFreq::MHZ10: p.reference.ExtRefOuputFreq = 10000000; break;
case Reference::OutFreq::MHZ100: p.reference.ExtRefOuputFreq = 100000000; break; case Reference::OutFreq::MHZ100: p.reference.ExtRefOuputFreq = 100000000; break;

View File

@ -32,7 +32,7 @@ public:
struct { struct {
double minFreq, maxFreq, maxFreqHarmonic; double minFreq, maxFreq, maxFreqHarmonic;
double minIFBW, maxIFBW; double minIFBW, maxIFBW;
int maxPoints; unsigned int maxPoints;
double mindBm; double mindBm;
double maxdBm; double maxdBm;
double minRBW, maxRBW; double minRBW, maxRBW;
@ -45,8 +45,11 @@ public:
bool overload; bool overload;
bool unlocked; bool unlocked;
bool unlevel; bool unlevel;
bool extRef;
}; };
static void RegisterTypes();
bool isCompoundDevice() const; bool isCompoundDevice() const;
Device *getDevice(); Device *getDevice();
std::vector<Device*> getDevices(); std::vector<Device*> getDevices();
@ -66,7 +69,7 @@ public:
}; };
class VNAMeasurement { class VNAMeasurement {
public: public:
int pointNum; unsigned int pointNum;
double Z0; double Z0;
union { union {
struct { struct {
@ -160,11 +163,11 @@ public:
static VirtualDevice* getConnected(); static VirtualDevice* getConnected();
signals: signals:
void VNAmeasurementReceived(const VNAMeasurement &m); void VNAmeasurementReceived(VNAMeasurement m);
void SAmeasurementReceived(const SAMeasurement &m); void SAmeasurementReceived(SAMeasurement m);
void ConnectionLost(); void ConnectionLost();
void InfoUpdated(); void InfoUpdated();
void StatusUpdated(const Status &status); void StatusUpdated(Status status);
void LogLineReceived(QString line); void LogLineReceived(QString line);
void NeedsFirmwareUpdate(int usedProtocol, int requiredProtocol); void NeedsFirmwareUpdate(int usedProtocol, int requiredProtocol);
private: private:
@ -178,4 +181,8 @@ private:
std::map<Device*, Device::TransmissionResult> results; std::map<Device*, Device::TransmissionResult> results;
}; };
Q_DECLARE_METATYPE(VirtualDevice::Status)
Q_DECLARE_METATYPE(VirtualDevice::VNAMeasurement)
Q_DECLARE_METATYPE(VirtualDevice::SAMeasurement)
#endif // VIRTUALDEVICE_H #endif // VIRTUALDEVICE_H

View File

@ -7,6 +7,7 @@
class Generator : public Mode class Generator : public Mode
{ {
Q_OBJECT
public: public:
Generator(AppWindow *window, QString name = "Signal Generator"); Generator(AppWindow *window, QString name = "Signal Generator");
void deactivate() override; void deactivate() override;

View File

@ -1,7 +1,7 @@
#ifndef SIGNALGENERATOR_H #ifndef SIGNALGENERATOR_H
#define SIGNALGENERATOR_H #define SIGNALGENERATOR_H
#include "Device/virtualdevice.h".h" #include "Device/virtualdevice.h"
#include "savable.h" #include "savable.h"
#include <QWidget> #include <QWidget>

View File

@ -14,7 +14,7 @@
#include "Tools/impedancematchdialog.h" #include "Tools/impedancematchdialog.h"
#include "Calibration/calibrationtracedialog.h" #include "Calibration/calibrationtracedialog.h"
#include "ui_main.h" #include "ui_main.h"
#include "Device/virtualdevice.h".h" #include "Device/virtualdevice.h"
#include "preferences.h" #include "preferences.h"
#include "Generator/signalgenwidget.h" #include "Generator/signalgenwidget.h"
@ -438,7 +438,7 @@ void SpectrumAnalyzer::fromJSON(nlohmann::json j)
using namespace std; using namespace std;
void SpectrumAnalyzer::NewDatapoint(const VirtualDevice::SAMeasurement &m) void SpectrumAnalyzer::NewDatapoint(VirtualDevice::SAMeasurement m)
{ {
if(isActive != true) { if(isActive != true) {
return; return;
@ -511,7 +511,7 @@ void SpectrumAnalyzer::NewDatapoint(const VirtualDevice::SAMeasurement &m)
UpdateAverageCount(); UpdateAverageCount();
markerModel->updateMarkers(); markerModel->updateMarkers();
} }
static unsigned int lastPoint = 0; static int lastPoint = 0;
if(m_avg.pointNum > 0 && m_avg.pointNum != lastPoint + 1) { if(m_avg.pointNum > 0 && m_avg.pointNum != lastPoint + 1) {
qWarning() << "Got point" << m_avg.pointNum << "but last received point was" << lastPoint << "("<<(m_avg.pointNum-lastPoint-1)<<"missed points)"; qWarning() << "Got point" << m_avg.pointNum << "but last received point was" << lastPoint << "("<<(m_avg.pointNum-lastPoint-1)<<"missed points)";
} }

View File

@ -39,7 +39,7 @@ private:
static VirtualDevice::SASettings::Detector DetectorFromString(QString s); static VirtualDevice::SASettings::Detector DetectorFromString(QString s);
private slots: private slots:
void NewDatapoint(const VirtualDevice::SAMeasurement &m); void NewDatapoint(VirtualDevice::SAMeasurement m);
// Sweep control // Sweep control
void SetStartFreq(double freq); void SetStartFreq(double freq);
void SetStopFreq(double freq); void SetStopFreq(double freq);

View File

@ -81,7 +81,7 @@ void Trace::addData(const Trace::Data& d, DataType domain, double reference_impe
} }
if(index >= 0) { if(index >= 0) {
// index position specified // index position specified
if(data.size() <= index) { if(data.size() <= (unsigned int) index) {
data.resize(index + 1); data.resize(index + 1);
} }
data[index] = d; data[index] = d;
@ -189,7 +189,6 @@ QString Trace::fillFromCSV(CSV &csv, unsigned int parameter)
int traceNum = -1; int traceNum = -1;
unsigned int i=1; unsigned int i=1;
QString lastTraceName = ""; QString lastTraceName = "";
bool hasImagValues;
std::map<YAxis::Type, int> columnMapping; std::map<YAxis::Type, int> columnMapping;
for(;i<csv.columns();i++) { for(;i<csv.columns();i++) {
auto header = csv.getHeader(i); auto header = csv.getHeader(i);
@ -202,13 +201,13 @@ QString Trace::fillFromCSV(CSV &csv, unsigned int parameter)
auto yaxistype = header.right(header.size() - splitIndex - 1); auto yaxistype = header.right(header.size() - splitIndex - 1);
if(traceName != lastTraceName) { if(traceName != lastTraceName) {
traceNum++; traceNum++;
if(traceNum > parameter) { if(traceNum > (int) parameter) {
// got all columns for the trace we are interested in // got all columns for the trace we are interested in
break; break;
} }
lastTraceName = traceName; lastTraceName = traceName;
} }
if(traceNum == parameter) { if(traceNum == (int) parameter) {
// this is the trace we are looking for, get axistype and add to mapping // this is the trace we are looking for, get axistype and add to mapping
// handle legacy column naming, translate to new naming // handle legacy column naming, translate to new naming
@ -221,7 +220,7 @@ QString Trace::fillFromCSV(CSV &csv, unsigned int parameter)
columnMapping[YAxis::TypeFromName(yaxistype)] = i; columnMapping[YAxis::TypeFromName(yaxistype)] = i;
} }
} }
if(traceNum < parameter) { if(traceNum < (int) parameter) {
throw runtime_error("Not enough traces in CSV file"); throw runtime_error("Not enough traces in CSV file");
} }
if(columnMapping.size() == 0) { if(columnMapping.size() == 0) {
@ -330,6 +329,7 @@ void Trace::removeMarker(Marker *m)
void Trace::markerVisibilityChanged(Marker *m) void Trace::markerVisibilityChanged(Marker *m)
{ {
Q_UNUSED(m);
// trigger replot by pretending that trace visibility also changed // trigger replot by pretending that trace visibility also changed
emit visibilityChanged(this); emit visibilityChanged(this);
} }
@ -711,6 +711,11 @@ nlohmann::json Trace::toJSON()
j["sources"] = jsources; j["sources"] = jsources;
} }
break; break;
case Source::Calibration:
// Skip for now, TODO?
break;
case Source::Last:
break;
} }
j["velocityFactor"] = vFactor; j["velocityFactor"] = vFactor;
j["reflection"] = reflection; j["reflection"] = reflection;

View File

@ -31,6 +31,7 @@ TraceCSVExport::TraceCSVExport(TraceModel &traceModel, QWidget *parent) :
auto domain = t->outputType(); auto domain = t->outputType();
auto Xaxis = XAxis::Type::Last; auto Xaxis = XAxis::Type::Last;
switch(domain) { switch(domain) {
case Trace::DataType::Invalid:
case Trace::DataType::Frequency: Xaxis = XAxis::Type::Frequency; break; case Trace::DataType::Frequency: Xaxis = XAxis::Type::Frequency; break;
case Trace::DataType::Power: Xaxis = XAxis::Type::Power; break; case Trace::DataType::Power: Xaxis = XAxis::Type::Power; break;
case Trace::DataType::Time: Xaxis = XAxis::Type::Time; break; case Trace::DataType::Time: Xaxis = XAxis::Type::Time; break;
@ -109,7 +110,7 @@ void TraceCSVExport::on_buttonBox_accepted()
std::vector<YAxis::Type> TraceCSVExport::getSelectedYAxisTypes() std::vector<YAxis::Type> TraceCSVExport::getSelectedYAxisTypes()
{ {
std::vector<YAxis::Type> ret; std::vector<YAxis::Type> ret;
for(unsigned int i=0;i<ui->listColumns->count();i++) { for(int i=0;i<ui->listColumns->count();i++) {
auto item = ui->listColumns->item(i); auto item = ui->listColumns->item(i);
if(item->checkState() == Qt::Checked) { if(item->checkState() == Qt::Checked) {
auto type = YAxis::TypeFromName(item->text()); auto type = YAxis::TypeFromName(item->text());

View File

@ -107,7 +107,6 @@ TraceEditDialog::TraceEditDialog(Trace &t, QWidget *parent) :
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
} else { } else {
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
auto touchstone = ui->touchstoneImport->getTouchstone();
} }
if(!(ui->touchstoneImport->getFilename().endsWith(".csv"))) { if(!(ui->touchstoneImport->getFilename().endsWith(".csv"))) {
// switch to touchstone import dialog // switch to touchstone import dialog
@ -125,6 +124,7 @@ TraceEditDialog::TraceEditDialog(Trace &t, QWidget *parent) :
VNAtrace = Trace::isVNAParameter(t.liveParameter()); VNAtrace = Trace::isVNAParameter(t.liveParameter());
if(VirtualDevice::getConnected()) { if(VirtualDevice::getConnected()) {
qDebug() << VirtualDevice::getConnected();
if(VNAtrace) { if(VNAtrace) {
ui->CLiveParam->addItems(VirtualDevice::getConnected()->availableVNAMeasurements()); ui->CLiveParam->addItems(VirtualDevice::getConnected()->availableVNAMeasurements());
} else { } else {
@ -132,6 +132,9 @@ TraceEditDialog::TraceEditDialog(Trace &t, QWidget *parent) :
} }
} }
if(ui->CLiveParam->findText(t.liveParameter()) < 0) {
ui->CLiveParam->addItem(t.liveParameter());
}
ui->CLiveParam->setCurrentText(t.liveParameter()); ui->CLiveParam->setCurrentText(t.liveParameter());
connect(ui->touchstoneImport, &TouchstoneImport::statusChanged, updateTouchstoneFileStatus); connect(ui->touchstoneImport, &TouchstoneImport::statusChanged, updateTouchstoneFileStatus);

View File

@ -70,7 +70,7 @@ void TraceModel::togglePause(unsigned int index)
traces[index]->pause(); traces[index]->pause();
} }
emit dataChanged(createIndex(index, ColIndexPlayPause), createIndex(index, ColIndexPlayPause)); emit dataChanged(createIndex(index, ColIndexPlayPause), createIndex(index, ColIndexPlayPause));
emit requiredExcitation(PortExcitationRequired(1), PortExcitationRequired(2)); emit requiredExcitation();
} }
} }
@ -252,7 +252,7 @@ void TraceModel::addSAData(const VirtualDevice::SAMeasurement& d, const VirtualD
if (t->getSource() == Trace::Source::Live && !t->isPaused()) { if (t->getSource() == Trace::Source::Live && !t->isPaused()) {
int index = -1; int index = -1;
Trace::Data td; Trace::Data td;
if(settings.f_start == settings.f_stop) { if(settings.freqStart == settings.freqStop) {
// in zerospan mode, insert data by index // in zerospan mode, insert data by index
index = d.pointNum; index = d.pointNum;
td.x = (double) d.us / 1000000.0; td.x = (double) d.us / 1000000.0;

View File

@ -59,7 +59,7 @@ signals:
void SpanChanged(double fmin, double fmax); void SpanChanged(double fmin, double fmax);
void traceAdded(Trace *t); void traceAdded(Trace *t);
void traceRemoved(Trace *t); void traceRemoved(Trace *t);
void requiredExcitation(bool excitePort1, bool excitePort2); void requiredExcitation();
void traceNameChanged(Trace *t); void traceNameChanged(Trace *t);
public slots: public slots:

View File

@ -133,18 +133,12 @@ bool TraceWaterfall::configureForTrace(Trace *t)
xAxis.set(XAxis::Type::Frequency, false, true, 0, 1, 0.1); xAxis.set(XAxis::Type::Frequency, false, true, 0, 1, 0.1);
yAxis.set(YAxis::Type::Magnitude, false, true, 0, 1, 1.0); yAxis.set(YAxis::Type::Magnitude, false, true, 0, 1, 1.0);
break; break;
// case Trace::DataType::Time:
// xAxis.set(XAxis::Type::Time, false, true, 0, 1, 0.1);
// yAxis.set(YAxis::Type::ImpulseMag, false, true, 0, 1, 1.0);
// break;
case Trace::DataType::Power: case Trace::DataType::Power:
xAxis.set(XAxis::Type::Power, false, true, 0, 1, 0.1); xAxis.set(XAxis::Type::Power, false, true, 0, 1, 0.1);
yAxis.set(YAxis::Type::Magnitude, false, true, 0, 1, 1.0); yAxis.set(YAxis::Type::Magnitude, false, true, 0, 1, 1.0);
break; break;
// case Trace::DataType::TimeZeroSpan: case Trace::DataType::Time:
// xAxis.set(XAxis::Type::Power, false, true, 0, 1, 0.1); case Trace::DataType::TimeZeroSpan:
// yAxis.set(YAxis::Type::Magnitude, false, true, 0, 1, 1.0);
// break;
case Trace::DataType::Invalid: case Trace::DataType::Invalid:
// unable to add // unable to add
return false; return false;

View File

@ -211,6 +211,7 @@ void TraceWidget::SetupSCPI()
auto d = t->sample(i); auto d = t->sample(i);
int precision = 0; int precision = 0;
switch(t->outputType()) { switch(t->outputType()) {
case Trace::DataType::Invalid:
case Trace::DataType::Frequency: precision = 0; break; case Trace::DataType::Frequency: precision = 0; break;
case Trace::DataType::Time: precision = 12; break; case Trace::DataType::Time: precision = 12; break;
case Trace::DataType::Power: precision = 3; break; case Trace::DataType::Power: precision = 3; break;

View File

@ -72,16 +72,16 @@ VNA::VNA(AppWindow *window, QString name)
// Create default traces // Create default traces
auto tS11 = new Trace("S11", Qt::yellow); auto tS11 = new Trace("S11", Qt::yellow);
tS11->fromLivedata(Trace::LivedataType::Overwrite, Trace::LiveParameter::S11); tS11->fromLivedata(Trace::LivedataType::Overwrite, "S11");
traceModel.addTrace(tS11); traceModel.addTrace(tS11);
auto tS12 = new Trace("S12", Qt::blue); auto tS12 = new Trace("S12", Qt::blue);
tS12->fromLivedata(Trace::LivedataType::Overwrite, Trace::LiveParameter::S12); tS12->fromLivedata(Trace::LivedataType::Overwrite, "S12");
traceModel.addTrace(tS12); traceModel.addTrace(tS12);
auto tS21 = new Trace("S21", Qt::green); auto tS21 = new Trace("S21", Qt::green);
tS21->fromLivedata(Trace::LivedataType::Overwrite, Trace::LiveParameter::S21); tS21->fromLivedata(Trace::LivedataType::Overwrite, "S21");
traceModel.addTrace(tS21); traceModel.addTrace(tS21);
auto tS22 = new Trace("S22", Qt::red); auto tS22 = new Trace("S22", Qt::red);
tS22->fromLivedata(Trace::LivedataType::Overwrite, Trace::LiveParameter::S22); tS22->fromLivedata(Trace::LivedataType::Overwrite, "S22");
traceModel.addTrace(tS22); traceModel.addTrace(tS22);
auto tracesmith1 = new TraceSmithChart(traceModel); auto tracesmith1 = new TraceSmithChart(traceModel);
@ -675,7 +675,7 @@ void VNA::deactivate()
void VNA::initializeDevice() void VNA::initializeDevice()
{ {
defaultCalMenu->setEnabled(true); defaultCalMenu->setEnabled(true);
connect(window->getDevice(), &Device::DatapointReceived, this, &VNA::NewDatapoint, Qt::UniqueConnection); connect(window->getDevice(), &VirtualDevice::VNAmeasurementReceived, this, &VNA::NewDatapoint, Qt::UniqueConnection);
// Check if default calibration exists and attempt to load it // Check if default calibration exists and attempt to load it
QSettings s; QSettings s;
auto key = "DefaultCalibration"+window->getDevice()->serial(); auto key = "DefaultCalibration"+window->getDevice()->serial();
@ -799,7 +799,7 @@ void VNA::fromJSON(nlohmann::json j)
using namespace std; using namespace std;
void VNA::NewDatapoint(Protocol::Datapoint d) void VNA::NewDatapoint(VirtualDevice::VNAMeasurement m)
{ {
if(isActive != true) { if(isActive != true) {
// ignore // ignore
@ -814,54 +814,54 @@ void VNA::NewDatapoint(Protocol::Datapoint d)
if(singleSweep && average.getLevel() == averages) { if(singleSweep && average.getLevel() == averages) {
changingSettings = true; changingSettings = true;
// single sweep finished // single sweep finished
window->getDevice()->SetIdle([=](Device::TransmissionResult){ window->getDevice()->setIdle([=](bool){
changingSettings = false; changingSettings = false;
}); });
} }
auto m_avg = m;
bool needsSegmentUpdate = false; bool needsSegmentUpdate = false;
if (settings.segments > 1) { if (settings.segments > 1) {
// using multiple segments, adjust pointNum // using multiple segments, adjust pointNum
auto pointsPerSegment = ceil((double) settings.npoints / settings.segments); auto pointsPerSegment = ceil((double) settings.npoints / settings.segments);
if (d.pointNum == pointsPerSegment - 1) { if (m_avg.pointNum == pointsPerSegment - 1) {
needsSegmentUpdate = true; needsSegmentUpdate = true;
} }
d.pointNum += pointsPerSegment * settings.activeSegment; m_avg.pointNum += pointsPerSegment * settings.activeSegment;
if(d.pointNum == settings.npoints - 1) { if(m_avg.pointNum == settings.npoints - 1) {
needsSegmentUpdate = true; needsSegmentUpdate = true;
} }
} }
if(d.pointNum >= settings.npoints) { if(m_avg.pointNum >= settings.npoints) {
qWarning() << "Ignoring point with too large point number (" << d.pointNum << ")"; qWarning() << "Ignoring point with too large point number (" << m.pointNum << ")";
return; return;
} }
auto vd = VNAData(d); m_avg = average.process(m_avg);
vd = average.process(vd);
if(calMeasuring) { if(calMeasuring) {
if(average.currentSweep() == averages) { if(average.currentSweep() == averages) {
// this is the last averaging sweep, use values for calibration // this is the last averaging sweep, use values for calibration
if(!calWaitFirst || vd.pointNum == 0) { if(!calWaitFirst || m_avg.pointNum == 0) {
calWaitFirst = false; calWaitFirst = false;
cal.addMeasurements(calMeasurements, vd); cal.addMeasurements(calMeasurements, m_avg);
if(vd.pointNum == settings.npoints - 1) { if(m_avg.pointNum == settings.npoints - 1) {
calMeasuring = false; calMeasuring = false;
emit CalibrationMeasurementsComplete(calMeasurements); emit CalibrationMeasurementsComplete(calMeasurements);
} }
} }
} }
int percentage = (((average.currentSweep() - 1) * 100) + (vd.pointNum + 1) * 100 / settings.npoints) / averages; int percentage = (((average.currentSweep() - 1) * 100) + (m_avg.pointNum + 1) * 100 / settings.npoints) / averages;
calDialog.setValue(percentage); calDialog.setValue(percentage);
} }
if(calValid) { if(calValid) {
cal.correctMeasurement(vd); cal.correctMeasurement(m_avg);
} }
if(deembedding_active) { if(deembedding_active) {
deembedding.Deembed(vd); deembedding.Deembed(m_avg);
} }
TraceMath::DataType type; TraceMath::DataType type;
@ -869,11 +869,11 @@ void VNA::NewDatapoint(Protocol::Datapoint d)
type = TraceMath::DataType::TimeZeroSpan; type = TraceMath::DataType::TimeZeroSpan;
// keep track of first point time // keep track of first point time
if(vd.pointNum == 0) { if(m_avg.pointNum == 0) {
settings.firstPointTime = vd.time; settings.firstPointTime = m_avg.us;
vd.time = 0; m_avg.us = 0;
} else { } else {
vd.time -= settings.firstPointTime; m_avg.us -= settings.firstPointTime;
} }
} else { } else {
switch(settings.sweepType) { switch(settings.sweepType) {
@ -887,17 +887,17 @@ void VNA::NewDatapoint(Protocol::Datapoint d)
} }
} }
traceModel.addVNAData(vd, type); traceModel.addVNAData(m_avg, type);
emit dataChanged(); emit dataChanged();
if(vd.pointNum == settings.npoints - 1) { if(m_avg.pointNum == settings.npoints - 1) {
UpdateAverageCount(); UpdateAverageCount();
markerModel->updateMarkers(); markerModel->updateMarkers();
} }
static unsigned int lastPoint = 0; static unsigned int lastPoint = 0;
if(vd.pointNum > 0 && vd.pointNum != lastPoint + 1) { if(m_avg.pointNum > 0 && m_avg.pointNum != lastPoint + 1) {
qWarning() << "Got point" << vd.pointNum << "but last received point was" << lastPoint << "("<<(vd.pointNum-lastPoint-1)<<"missed points)"; qWarning() << "Got point" << m_avg.pointNum << "but last received point was" << lastPoint << "("<<(m_avg.pointNum-lastPoint-1)<<"missed points)";
} }
lastPoint = vd.pointNum; lastPoint = m_avg.pointNum;
if (needsSegmentUpdate) { if (needsSegmentUpdate) {
changingSettings = true; changingSettings = true;
@ -915,24 +915,26 @@ void VNA::UpdateAverageCount()
lAverages->setText(QString::number(average.getLevel()) + "/"); lAverages->setText(QString::number(average.getLevel()) + "/");
} }
void VNA::SettingsChanged(bool resetTraces, std::function<void (Device::TransmissionResult)> cb) void VNA::SettingsChanged(bool resetTraces, std::function<void (bool)> cb)
{ {
if (resetTraces) { if (resetTraces) {
settings.activeSegment = 0; settings.activeSegment = 0;
} }
changingSettings = true; changingSettings = true;
// assemble VNA protocol settings // assemble VNA protocol settings
Protocol::SweepSettings s = {}; VirtualDevice::VNASettings s = {};
s.suppressPeaks = Preferences::getInstance().Acquisition.suppressPeaks ? 1 : 0; s.IFBW = settings.bandwidth;
if(Preferences::getInstance().Acquisition.alwaysExciteBothPorts) { if(Preferences::getInstance().Acquisition.alwaysExciteBothPorts) {
s.excitePort1 = 1; for(int i=1;i<=VirtualDevice::getInfo(window->getDevice()).ports;i++) {
s.excitePort2 = 1; s.excitedPorts.push_back(i);
}
} else { } else {
s.excitePort1 = traceModel.PortExcitationRequired(1); for(int i=1;i<=VirtualDevice::getInfo(window->getDevice()).ports;i++) {
s.excitePort2 = traceModel.PortExcitationRequired(2); if(traceModel.PortExcitationRequired(i))
s.excitedPorts.push_back(i);
}
} }
settings.excitingPort1 = s.excitePort1; settings.excitedPorts = s.excitedPorts;
settings.excitingPort2 = s.excitePort2;
double start = settings.sweepType == SweepType::Frequency ? settings.Freq.start : settings.Power.start; double start = settings.sweepType == SweepType::Frequency ? settings.Freq.start : settings.Power.start;
double stop = settings.sweepType == SweepType::Frequency ? settings.Freq.stop : settings.Power.stop; double stop = settings.sweepType == SweepType::Frequency ? settings.Freq.stop : settings.Power.stop;
@ -941,8 +943,8 @@ void VNA::SettingsChanged(bool resetTraces, std::function<void (Device::Transmis
if (settings.segments > 1) { if (settings.segments > 1) {
// more than one segment, adjust start/stop // more than one segment, adjust start/stop
npoints = ceil((double) settings.npoints / settings.segments); npoints = ceil((double) settings.npoints / settings.segments);
int segmentStartPoint = npoints * settings.activeSegment; unsigned int segmentStartPoint = npoints * settings.activeSegment;
int segmentStopPoint = segmentStartPoint + npoints - 1; unsigned int segmentStopPoint = segmentStartPoint + npoints - 1;
if(segmentStopPoint >= settings.npoints) { if(segmentStopPoint >= settings.npoints) {
segmentStopPoint = settings.npoints - 1; segmentStopPoint = settings.npoints - 1;
npoints = settings.npoints - segmentStartPoint; npoints = settings.npoints - segmentStartPoint;
@ -954,44 +956,34 @@ void VNA::SettingsChanged(bool resetTraces, std::function<void (Device::Transmis
} }
if(settings.sweepType == SweepType::Frequency) { if(settings.sweepType == SweepType::Frequency) {
s.fixedPowerSetting = Preferences::getInstance().Acquisition.adjustPowerLevel ? 0 : 1; s.freqStart = start;
s.f_start = start; s.freqStop = stop;
s.f_stop = stop;
s.points = npoints; s.points = npoints;
s.if_bandwidth = settings.bandwidth; s.dBmStart = settings.Freq.excitation_power;
s.cdbm_excitation_start = settings.Freq.excitation_power * 100; s.dBmStop = settings.Freq.excitation_power;
s.cdbm_excitation_stop = settings.Freq.excitation_power * 100;
s.logSweep = settings.Freq.logSweep; s.logSweep = settings.Freq.logSweep;
} else if(settings.sweepType == SweepType::Power) { } else if(settings.sweepType == SweepType::Power) {
s.fixedPowerSetting = 0; s.freqStart = settings.Power.frequency;
s.f_start = settings.Power.frequency; s.freqStop = settings.Power.frequency;
s.f_stop = settings.Power.frequency;
s.points = npoints; s.points = npoints;
s.if_bandwidth = settings.bandwidth; s.dBmStart = start;
s.cdbm_excitation_start = start * 100; s.dBmStop = stop;
s.cdbm_excitation_stop = stop * 100;
s.logSweep = false; s.logSweep = false;
} }
if(window->getDevice() && isActive) { if(window->getDevice() && isActive) {
if(s.excitePort1 == 0 && s.excitePort2 == 0) { window->getDevice()->setVNA(s, [=](bool res){
// no signal at either port, just set the device to idle // device received command, reset traces now
window->getDevice()->SetIdle(); if (resetTraces) {
average.reset(settings.npoints);
traceModel.clearLiveData();
UpdateAverageCount();
UpdateCalWidget();
}
if(cb) {
cb(res);
}
changingSettings = false; changingSettings = false;
} else { });
window->getDevice()->Configure(s, [=](Device::TransmissionResult res){
// device received command, reset traces now
if (resetTraces) {
average.reset(settings.npoints);
traceModel.clearLiveData();
UpdateAverageCount();
UpdateCalWidget();
}
if(cb) {
cb(res);
}
changingSettings = false;
});
}
} }
} }
@ -1034,14 +1026,14 @@ void VNA::SetStopFreq(double freq)
void VNA::SetCenterFreq(double freq) void VNA::SetCenterFreq(double freq)
{ {
auto old_span = settings.Freq.stop - settings.Freq.start; auto old_span = settings.Freq.stop - settings.Freq.start;
if (freq - old_span / 2 <= Device::Info(window->getDevice()).limits_minFreq) { if (freq - old_span / 2 <= VirtualDevice::getInfo(window->getDevice()).Limits.minFreq) {
// would shift start frequency below minimum // would shift start frequency below minimum
settings.Freq.start = 0; settings.Freq.start = 0;
settings.Freq.stop = 2 * freq; settings.Freq.stop = 2 * freq;
} else if(freq + old_span / 2 >= Device::Info(window->getDevice()).limits_maxFreq) { } else if(freq + old_span / 2 >= VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq) {
// would shift stop frequency above maximum // would shift stop frequency above maximum
settings.Freq.start = 2 * freq - Device::Info(window->getDevice()).limits_maxFreq; settings.Freq.start = 2 * freq - VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq;
settings.Freq.stop = Device::Info(window->getDevice()).limits_maxFreq; settings.Freq.stop = VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq;
} else { } else {
settings.Freq.start = freq - old_span / 2; settings.Freq.start = freq - old_span / 2;
settings.Freq.stop = freq + old_span / 2; settings.Freq.stop = freq + old_span / 2;
@ -1051,12 +1043,12 @@ void VNA::SetCenterFreq(double freq)
void VNA::SetSpan(double span) void VNA::SetSpan(double span)
{ {
auto maxFreq = Preferences::getInstance().Acquisition.harmonicMixing ? Device::Info(window->getDevice()).limits_maxFreqHarmonic : Device::Info(window->getDevice()).limits_maxFreq; auto maxFreq = Preferences::getInstance().Acquisition.harmonicMixing ? VirtualDevice::getInfo(window->getDevice()).Limits.maxFreqHarmonic : VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq;
auto old_center = (settings.Freq.start + settings.Freq.stop) / 2; auto old_center = (settings.Freq.start + settings.Freq.stop) / 2;
if(old_center < Device::Info(window->getDevice()).limits_minFreq + span / 2) { if(old_center < VirtualDevice::getInfo(window->getDevice()).Limits.minFreq + span / 2) {
// would shift start frequency below minimum // would shift start frequency below minimum
settings.Freq.start = Device::Info(window->getDevice()).limits_minFreq; settings.Freq.start = VirtualDevice::getInfo(window->getDevice()).Limits.minFreq;
settings.Freq.stop = Device::Info(window->getDevice()).limits_minFreq + span; settings.Freq.stop = VirtualDevice::getInfo(window->getDevice()).Limits.minFreq + span;
} else if(old_center > maxFreq - span / 2) { } else if(old_center > maxFreq - span / 2) {
// would shift stop frequency above maximum // would shift stop frequency above maximum
settings.Freq.start = maxFreq - span; settings.Freq.start = maxFreq - span;
@ -1070,8 +1062,8 @@ void VNA::SetSpan(double span)
void VNA::SetFullSpan() void VNA::SetFullSpan()
{ {
settings.Freq.start = Device::Info(window->getDevice()).limits_minFreq; settings.Freq.start = VirtualDevice::getInfo(window->getDevice()).Limits.minFreq;
settings.Freq.stop = Device::Info(window->getDevice()).limits_maxFreq; settings.Freq.stop = VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq;
ConstrainAndUpdateFrequencies(); ConstrainAndUpdateFrequencies();
} }
@ -1116,10 +1108,10 @@ void VNA::SetLogSweep(bool log)
void VNA::SetSourceLevel(double level) void VNA::SetSourceLevel(double level)
{ {
if(level > Device::Info(window->getDevice()).limits_cdbm_max / 100.0) { if(level > VirtualDevice::getInfo(window->getDevice()).Limits.maxdBm) {
level = Device::Info(window->getDevice()).limits_cdbm_max / 100.0; level = VirtualDevice::getInfo(window->getDevice()).Limits.maxdBm;
} else if(level < Device::Info(window->getDevice()).limits_cdbm_min / 100.0) { } else if(level < VirtualDevice::getInfo(window->getDevice()).Limits.mindBm) {
level = Device::Info(window->getDevice()).limits_cdbm_min / 100.0; level = VirtualDevice::getInfo(window->getDevice()).Limits.mindBm;
} }
emit sourceLevelChanged(level); emit sourceLevelChanged(level);
settings.Freq.excitation_power = level; settings.Freq.excitation_power = level;
@ -1149,15 +1141,15 @@ void VNA::SetPowerSweepFrequency(double freq)
void VNA::SetPoints(unsigned int points) void VNA::SetPoints(unsigned int points)
{ {
unsigned int maxPoints = Preferences::getInstance().Acquisition.allowSegmentedSweep ? UINT16_MAX : Device::Info(window->getDevice()).limits_maxPoints; unsigned int maxPoints = Preferences::getInstance().Acquisition.allowSegmentedSweep ? UINT16_MAX : VirtualDevice::getInfo(window->getDevice()).Limits.maxPoints;
if(points > maxPoints) { if(points > maxPoints) {
points = maxPoints; points = maxPoints;
} else if (points < 2) { } else if (points < 2) {
points = 2; points = 2;
} }
if (points > Device::Info(window->getDevice()).limits_maxPoints) { if (points > VirtualDevice::getInfo(window->getDevice()).Limits.maxPoints) {
// needs segmented sweep // needs segmented sweep
settings.segments = ceil((double) points / Device::Info(window->getDevice()).limits_maxPoints); settings.segments = ceil((double) points / VirtualDevice::getInfo(window->getDevice()).Limits.maxPoints);
settings.activeSegment = 0; settings.activeSegment = 0;
} else { } else {
// can fit all points into one segment // can fit all points into one segment
@ -1171,10 +1163,10 @@ void VNA::SetPoints(unsigned int points)
void VNA::SetIFBandwidth(double bandwidth) void VNA::SetIFBandwidth(double bandwidth)
{ {
if(bandwidth > Device::Info(window->getDevice()).limits_maxIFBW) { if(bandwidth > VirtualDevice::getInfo(window->getDevice()).Limits.maxIFBW) {
bandwidth = Device::Info(window->getDevice()).limits_maxIFBW; bandwidth = VirtualDevice::getInfo(window->getDevice()).Limits.maxIFBW;
} else if(bandwidth < Device::Info(window->getDevice()).limits_minIFBW) { } else if(bandwidth < VirtualDevice::getInfo(window->getDevice()).Limits.minIFBW) {
bandwidth = Device::Info(window->getDevice()).limits_minIFBW; bandwidth = VirtualDevice::getInfo(window->getDevice()).Limits.minIFBW;
} }
settings.bandwidth = bandwidth; settings.bandwidth = bandwidth;
emit IFBandwidthChanged(settings.bandwidth); emit IFBandwidthChanged(settings.bandwidth);
@ -1189,18 +1181,18 @@ void VNA::SetAveraging(unsigned int averages)
SettingsChanged(); SettingsChanged();
} }
void VNA::ExcitationRequired(bool port1, bool port2) void VNA::ExcitationRequired()
{ {
if(Preferences::getInstance().Acquisition.alwaysExciteBothPorts) { if(!Preferences::getInstance().Acquisition.alwaysExciteBothPorts) {
port1 = true; for(int i=1;i<VirtualDevice::getInfo(window->getDevice()).ports;i++) {
port2 = true; auto required = traceModel.PortExcitationRequired(i);
} auto set = find(settings.excitedPorts.begin(), settings.excitedPorts.end(), i) != settings.excitedPorts.end();
// check if settings actually changed if(required != set) {
if(settings.excitingPort1 != port1 // Required port excitation changed
|| settings.excitingPort2 != port2) { SettingsChanged();
settings.excitingPort1 = port1; break;
settings.excitingPort2 = port2; }
SettingsChanged(); }
} }
} }
@ -1274,7 +1266,7 @@ void VNA::StartCalibrationMeasurements(std::set<Calibration::Measurement> m)
cal.clearMeasurements(calMeasurements); cal.clearMeasurements(calMeasurements);
}); });
// Trigger sweep to start from beginning // Trigger sweep to start from beginning
SettingsChanged(true, [=](Device::TransmissionResult){ SettingsChanged(true, [=](bool){
// enable calibration measurement only in transmission callback (prevents accidental sampling of data which was still being processed) // enable calibration measurement only in transmission callback (prevents accidental sampling of data which was still being processed)
calMeasuring = true; calMeasuring = true;
}); });
@ -1541,9 +1533,9 @@ void VNA::ConstrainAndUpdateFrequencies()
auto pref = Preferences::getInstance(); auto pref = Preferences::getInstance();
double maxFreq; double maxFreq;
if(pref.Acquisition.harmonicMixing) { if(pref.Acquisition.harmonicMixing) {
maxFreq = Device::Info(window->getDevice()).limits_maxFreqHarmonic; maxFreq = VirtualDevice::getInfo(window->getDevice()).Limits.maxFreqHarmonic;
} else { } else {
maxFreq = Device::Info(window->getDevice()).limits_maxFreq; maxFreq = VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq;
} }
if(settings.Freq.stop > maxFreq) { if(settings.Freq.stop > maxFreq) {
settings.Freq.stop = maxFreq; settings.Freq.stop = maxFreq;
@ -1551,8 +1543,8 @@ void VNA::ConstrainAndUpdateFrequencies()
if(settings.Freq.start > settings.Freq.stop) { if(settings.Freq.start > settings.Freq.stop) {
settings.Freq.start = settings.Freq.stop; settings.Freq.start = settings.Freq.stop;
} }
if(settings.Freq.start < Device::Info(window->getDevice()).limits_minFreq) { if(settings.Freq.start < VirtualDevice::getInfo(window->getDevice()).Limits.minFreq) {
settings.Freq.start = Device::Info(window->getDevice()).limits_minFreq; settings.Freq.start = VirtualDevice::getInfo(window->getDevice()).Limits.minFreq;
} }
settings.zerospan = (settings.sweepType == SweepType::Frequency && settings.Freq.start == settings.Freq.stop) settings.zerospan = (settings.sweepType == SweepType::Frequency && settings.Freq.start == settings.Freq.stop)
|| (settings.sweepType == SweepType::Power && settings.Power.start == settings.Power.stop); || (settings.sweepType == SweepType::Power && settings.Power.start == settings.Power.stop);
@ -1607,7 +1599,7 @@ void VNA::StoreSweepSettings()
void VNA::StopSweep() void VNA::StopSweep()
{ {
if(window->getDevice()) { if(window->getDevice()) {
window->getDevice()->SetIdle(); window->getDevice()->setIdle();
} }
} }

View File

@ -48,7 +48,7 @@ public:
: sweepType(SweepType::Frequency) : sweepType(SweepType::Frequency)
, Freq({.start=1000000, .stop=6000000000, .excitation_power=-10, .logSweep=false}) , Freq({.start=1000000, .stop=6000000000, .excitation_power=-10, .logSweep=false})
, Power({.start=-40, .stop=-10, .frequency=1000000000}) , Power({.start=-40, .stop=-10, .frequency=1000000000})
, npoints(501), bandwidth(1000), excitingPort1(true), excitingPort2(true) , npoints(501), bandwidth(1000)
, segments(1), activeSegment(0){} , segments(1), activeSegment(0){}
SweepType sweepType; SweepType sweepType;
struct { struct {
@ -62,10 +62,9 @@ public:
double stop; double stop;
double frequency; double frequency;
} Power; } Power;
int npoints; unsigned int npoints;
double bandwidth; double bandwidth;
bool excitingPort1; std::vector<int> excitedPorts;
bool excitingPort2;
// if the number of points is higher than supported by the hardware, the sweep has to be segmented into multiple parts // if the number of points is higher than supported by the hardware, the sweep has to be segmented into multiple parts
int segments; int segments;
int activeSegment; int activeSegment;
@ -77,7 +76,7 @@ public slots:
bool LoadCalibration(QString filename); bool LoadCalibration(QString filename);
private slots: private slots:
void NewDatapoint(Protocol::Datapoint d); void NewDatapoint(VirtualDevice::VNAMeasurement m);
void StartImpedanceMatching(); void StartImpedanceMatching();
// Sweep control // Sweep control
void SetSweepType(SweepType sw); void SetSweepType(SweepType sw);
@ -101,7 +100,7 @@ private slots:
void SetPoints(unsigned int points); void SetPoints(unsigned int points);
void SetIFBandwidth(double bandwidth); void SetIFBandwidth(double bandwidth);
void SetAveraging(unsigned int averages); void SetAveraging(unsigned int averages);
void ExcitationRequired(bool port1, bool port2); void ExcitationRequired();
// Calibration // Calibration
void DisableCalibration(bool force = false); void DisableCalibration(bool force = false);
void ApplyCalibration(Calibration::Type type); void ApplyCalibration(Calibration::Type type);
@ -115,7 +114,7 @@ private:
bool CalibrationMeasurementActive() { return calWaitFirst || calMeasuring; } bool CalibrationMeasurementActive() { return calWaitFirst || calMeasuring; }
void SetupSCPI(); void SetupSCPI();
void UpdateAverageCount(); void UpdateAverageCount();
void SettingsChanged(bool resetTraces = true, std::function<void (Device::TransmissionResult)> cb = nullptr); void SettingsChanged(bool resetTraces = true, std::function<void(bool)> cb = nullptr);
void ConstrainAndUpdateFrequencies(); void ConstrainAndUpdateFrequencies();
void LoadSweepSettings(); void LoadSweepSettings();
void StoreSweepSettings(); void StoreSweepSettings();

View File

@ -325,6 +325,7 @@ bool AppWindow::ConnectToDevice(QString serial)
qDebug() << "Attempting to connect to device..."; qDebug() << "Attempting to connect to device...";
vdevice = new VirtualDevice(serial); vdevice = new VirtualDevice(serial);
UpdateStatusBar(AppWindow::DeviceStatusBar::Connected); UpdateStatusBar(AppWindow::DeviceStatusBar::Connected);
connect(vdevice, &VirtualDevice::InfoUpdated, this, &AppWindow::DeviceInfoUpdated);
connect(vdevice, &VirtualDevice::LogLineReceived, &deviceLog, &DeviceLog::addLine); connect(vdevice, &VirtualDevice::LogLineReceived, &deviceLog, &DeviceLog::addLine);
connect(vdevice, &VirtualDevice::ConnectionLost, this, &AppWindow::DeviceConnectionLost); connect(vdevice, &VirtualDevice::ConnectionLost, this, &AppWindow::DeviceConnectionLost);
connect(vdevice, &VirtualDevice::StatusUpdated, this, &AppWindow::DeviceStatusUpdated); connect(vdevice, &VirtualDevice::StatusUpdated, this, &AppWindow::DeviceStatusUpdated);
@ -339,11 +340,6 @@ bool AppWindow::ConnectToDevice(QString serial)
} }
UpdateAcquisitionFrequencies(); UpdateAcquisitionFrequencies();
if (modeHandler->getActiveMode()) {
modeHandler->getActiveMode()->initializeDevice();
}
UpdateReferenceToolbar();
UpdateReference();
for(auto d : deviceActionGroup->actions()) { for(auto d : deviceActionGroup->actions()) {
if(d->text() == vdevice->serial()) { if(d->text() == vdevice->serial()) {
@ -453,49 +449,59 @@ void AppWindow::SetupSCPI()
if(params.size() != 1) { if(params.size() != 1) {
return SCPI::getResultName(SCPI::Result::Error); return SCPI::getResultName(SCPI::Result::Error);
} else if(params[0] == "0" || params[0] == "OFF") { } else if(params[0] == "0" || params[0] == "OFF") {
int index = toolbars.reference.outFreq->findData((int)Reference::OutFreq::Off); int index = toolbars.reference.outFreq->findText("Off");
toolbars.reference.outFreq->setCurrentIndex(index); if(index >= 0) {
} else if(params[0] == "10") { toolbars.reference.outFreq->setCurrentIndex(index);
int index = toolbars.reference.outFreq->findData((int)Reference::OutFreq::MHZ10); } else {
toolbars.reference.outFreq->setCurrentIndex(index); return SCPI::getResultName(SCPI::Result::Error);
} else if(params[0] == "100") { }
int index = toolbars.reference.outFreq->findData((int)Reference::OutFreq::MHZ100);
toolbars.reference.outFreq->setCurrentIndex(index);
} else { } else {
return SCPI::getResultName(SCPI::Result::Error); bool isInt;
params[0].toInt(&isInt);
if(isInt) {
params[0].append(" MHz");
int index = toolbars.reference.outFreq->findText(params[0]);
if(index >= 0) {
toolbars.reference.outFreq->setCurrentIndex(index);
} else {
return SCPI::getResultName(SCPI::Result::Error);
}
} else {
return SCPI::getResultName(SCPI::Result::Error);
}
} }
return SCPI::getResultName(SCPI::Result::Empty); return SCPI::getResultName(SCPI::Result::Empty);
}, [=](QStringList) -> QString { }, [=](QStringList) -> QString {
Reference::OutFreq f = static_cast<Reference::OutFreq>(toolbars.reference.outFreq->currentData().toInt()); auto fOutString = toolbars.reference.outFreq->currentText().toUpper();
switch(f) { if(fOutString.endsWith(" MHZ")) {
case Reference::OutFreq::Off: return "OFF"; fOutString.chop(4);
case Reference::OutFreq::MHZ10: return "10"; }
case Reference::OutFreq::MHZ100: return "100"; if(fOutString.isEmpty()) {
default: return SCPI::getResultName(SCPI::Result::Error); return SCPI::getResultName(SCPI::Result::Error);
} else {
return fOutString;
} }
})); }));
scpi_ref->add(new SCPICommand("IN", [=](QStringList params) -> QString { scpi_ref->add(new SCPICommand("IN", [=](QStringList params) -> QString {
if(params.size() != 1) { // reference settings translation
map<QString, QString> translation {
make_pair("INT", "Internal"),
make_pair("EXT", "External"),
make_pair("AUTO", "Auto"),
};
if(params.size() != 1 || translation.count(params[0]) == 0) {
return SCPI::getResultName(SCPI::Result::Error); return SCPI::getResultName(SCPI::Result::Error);
} else if(params[0] == "INT") {
int index = toolbars.reference.type->findData((int)Reference::TypeIn::Internal);
toolbars.reference.type->setCurrentIndex(index);
} else if(params[0] == "EXT") {
int index = toolbars.reference.type->findData((int)Reference::TypeIn::External);
toolbars.reference.type->setCurrentIndex(index);
} else if(params[0] == "AUTO") {
int index = toolbars.reference.type->findData((int)Reference::TypeIn::Auto);
toolbars.reference.type->setCurrentIndex(index);
} else { } else {
return SCPI::getResultName(SCPI::Result::Error); int index = toolbars.reference.type->findText(translation[params[0]]);
if(index >= 0) {
toolbars.reference.type->setCurrentIndex(index);
} else {
return SCPI::getResultName(SCPI::Result::Error);
}
} }
return SCPI::getResultName(SCPI::Result::Empty); return SCPI::getResultName(SCPI::Result::Empty);
}, [=](QStringList) -> QString { }, [=](QStringList) -> QString {
switch(Device::StatusV1(getDevice()).extRefInUse) { return VirtualDevice::getStatus(getDevice()).extRef ? "EXT" : "INT";
case 0: return "INT";
case 1: return "EXT";
default: return SCPI::getResultName(SCPI::Result::Error);
}
})); }));
scpi_dev->add(new SCPICommand("MODE", [=](QStringList params) -> QString { scpi_dev->add(new SCPICommand("MODE", [=](QStringList params) -> QString {
if (params.size() != 1) { if (params.size() != 1) {
@ -525,6 +531,7 @@ void AppWindow::SetupSCPI()
case Mode::Type::VNA: return "VNA"; case Mode::Type::VNA: return "VNA";
case Mode::Type::SG: return "SG"; case Mode::Type::SG: return "SG";
case Mode::Type::SA: return "SA"; case Mode::Type::SA: return "SA";
case Mode::Type::Last: return SCPI::getResultName(SCPI::Result::Error);
} }
} }
return SCPI::getResultName(SCPI::Result::Error); return SCPI::getResultName(SCPI::Result::Error);
@ -903,6 +910,9 @@ void AppWindow::UpdateReferenceToolbar()
if(!vdevice || !vdevice->getInfo().supportsExtRef) { if(!vdevice || !vdevice->getInfo().supportsExtRef) {
toolbars.reference.type->setEnabled(false); toolbars.reference.type->setEnabled(false);
toolbars.reference.outFreq->setEnabled(false); toolbars.reference.outFreq->setEnabled(false);
} else {
toolbars.reference.type->setEnabled(true);
toolbars.reference.outFreq->setEnabled(true);
} }
// save current setting // save current setting
auto refInBuf = toolbars.reference.type->currentText(); auto refInBuf = toolbars.reference.type->currentText();
@ -913,7 +923,7 @@ void AppWindow::UpdateReferenceToolbar()
} }
toolbars.reference.outFreq->clear(); toolbars.reference.outFreq->clear();
for(auto out : vdevice->availableExtRefOutSettings()) { for(auto out : vdevice->availableExtRefOutSettings()) {
toolbars.reference.outFreq->addItem(in); toolbars.reference.outFreq->addItem(out);
} }
// restore previous setting if still available // restore previous setting if still available
if(toolbars.reference.type->findText(refInBuf) >= 0) { if(toolbars.reference.type->findText(refInBuf) >= 0) {
@ -982,7 +992,7 @@ void AppWindow::DeviceNeedsUpdate(int reported, int expected)
} }
} }
void AppWindow::DeviceStatusUpdated(VirtualDevice::Status &status) void AppWindow::DeviceStatusUpdated(VirtualDevice::Status status)
{ {
lDeviceInfo.setText(status.statusString); lDeviceInfo.setText(status.statusString);
lADCOverload.setVisible(status.overload); lADCOverload.setVisible(status.overload);
@ -990,6 +1000,15 @@ void AppWindow::DeviceStatusUpdated(VirtualDevice::Status &status)
lUnlock.setVisible(status.unlocked); lUnlock.setVisible(status.unlocked);
} }
void AppWindow::DeviceInfoUpdated()
{
if (modeHandler->getActiveMode()) {
modeHandler->getActiveMode()->initializeDevice();
}
UpdateReferenceToolbar();
UpdateReference();
}
void AppWindow::SourceCalibrationDialog() void AppWindow::SourceCalibrationDialog()
{ {
if(!vdevice || vdevice->isCompoundDevice()) { if(!vdevice || vdevice->isCompoundDevice()) {

View File

@ -1,7 +1,7 @@
#ifndef APPWINDOW_H #ifndef APPWINDOW_H
#define APPWINDOW_H #define APPWINDOW_H
#include "Device/virtualdevice.h".h" #include "Device/virtualdevice.h"
#include "Traces/traceplot.h" #include "Traces/traceplot.h"
#include "Calibration/calibration.h" #include "Calibration/calibration.h"
#include "Traces/tracemodel.h" #include "Traces/tracemodel.h"
@ -67,7 +67,8 @@ private slots:
void UpdateAcquisitionFrequencies(); void UpdateAcquisitionFrequencies();
void StartFirmwareUpdateDialog(); void StartFirmwareUpdateDialog();
void DeviceNeedsUpdate(int reported, int expected); void DeviceNeedsUpdate(int reported, int expected);
void DeviceStatusUpdated(VirtualDevice::Status &status); void DeviceStatusUpdated(VirtualDevice::Status status);
void DeviceInfoUpdated();
void SourceCalibrationDialog(); void SourceCalibrationDialog();
void ReceiverCalibrationDialog(); void ReceiverCalibrationDialog();
void FrequencyCalibrationDialog(); void FrequencyCalibrationDialog();

View File

@ -88,7 +88,7 @@ void Averaging::setMode(const Mode &value)
mode = value; mode = value;
} }
void Averaging::process(int pointNum, std::vector<std::complex<double>> &data) void Averaging::process(unsigned int pointNum, std::vector<std::complex<double>> &data)
{ {
if(data.size() != numMeasurements) { if(data.size() != numMeasurements) {
numMeasurements = data.size(); numMeasurements = data.size();
@ -119,12 +119,12 @@ void Averaging::process(int pointNum, std::vector<std::complex<double>> &data)
// calculate average // calculate average
complex<double> sum[numMeasurements]; complex<double> sum[numMeasurements];
for(auto s : *deque) { for(auto s : *deque) {
for(int i=0;i<numMeasurements;i++) { for(unsigned int i=0;i<numMeasurements;i++) {
sum[i] += s[i]; sum[i] += s[i];
} }
} }
for(auto s : sum) { for(auto s : sum) {
averagedResults.push_back(abs(s / (double) (deque->size()))); averagedResults.push_back(s / (double) (deque->size()));
} }
} }
break; break;

View File

@ -30,11 +30,11 @@ public:
void setMode(const Mode &value); void setMode(const Mode &value);
private: private:
void process(int pointNum, std::vector<std::complex<double> > &data); void process(unsigned int pointNum, std::vector<std::complex<double> > &data);
std::vector<std::deque<std::vector<std::complex<double>>>> avg; std::vector<std::deque<std::vector<std::complex<double>>>> avg;
int maxPoints; int maxPoints;
int numMeasurements; unsigned int numMeasurements;
unsigned int averages; unsigned int averages;
Mode mode; Mode mode;
}; };

View File

@ -1,6 +1,7 @@
#include "appwindow.h" #include "appwindow.h"
#include <QtWidgets/QApplication> #include <QtWidgets/QApplication>
#include "Device/device.h" #include "Device/device.h"
#include "Device/virtualdevice.h"
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
#include <signal.h> #include <signal.h>
#endif #endif
@ -20,6 +21,9 @@ int main(int argc, char *argv[]) {
qSetMessagePattern("%{time process}: [%{type}] %{message}"); qSetMessagePattern("%{time process}: [%{type}] %{message}");
Device::RegisterTypes();
VirtualDevice::RegisterTypes();
app = new QApplication(argc, argv); app = new QApplication(argc, argv);
QCoreApplication::setOrganizationName("LibreVNA"); QCoreApplication::setOrganizationName("LibreVNA");
QCoreApplication::setApplicationName("LibreVNA-GUI"); QCoreApplication::setApplicationName("LibreVNA-GUI");
@ -27,8 +31,6 @@ int main(int argc, char *argv[]) {
QCoreApplication::setApplicationVersion(window->getAppVersion() + "-" + QCoreApplication::setApplicationVersion(window->getAppVersion() + "-" +
window->getAppGitHash().left(9)); window->getAppGitHash().left(9));
Device::RegisterTypes();
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
signal(SIGINT, tryExitGracefully); signal(SIGINT, tryExitGracefully);
#endif #endif

View File

@ -18,8 +18,8 @@
Mode::Mode(AppWindow *window, QString name, QString SCPIname) Mode::Mode(AppWindow *window, QString name, QString SCPIname)
: QObject(window), : QObject(window),
SCPINode(SCPIname), SCPINode(SCPIname),
window(window),
isActive(false), isActive(false),
window(window),
name(name), name(name),
central(nullptr) central(nullptr)
{ {

View File

@ -28,7 +28,7 @@ public:
Mode(AppWindow *window, QString name, QString SCPIname); Mode(AppWindow *window, QString name, QString SCPIname);
~Mode(); ~Mode();
virtual void shutdown(){}; // called when the application is about to exit virtual void shutdown(){} // called when the application is about to exit
QString getName() const; QString getName() const;
void setName(const QString &value); void setName(const QString &value);
void updateGraphColors(); void updateGraphColors();
@ -37,7 +37,7 @@ public:
virtual Type getType() = 0; virtual Type getType() = 0;
virtual void initializeDevice() = 0; virtual void initializeDevice() = 0;
virtual void deviceDisconnected(){}; virtual void deviceDisconnected(){}
virtual void saveSreenshot(); virtual void saveSreenshot();

View File

@ -85,6 +85,7 @@ QString SCPI::getResultName(SCPI::Result r)
case Result::Empty: case Result::Empty:
return ""; return "";
case Result::Error: case Result::Error:
default:
return "ERROR"; return "ERROR";
case Result::False: case Result::False:
return "FALSE"; return "FALSE";