From 62939ff882cd249b14e55fd3ce65d0e66550ae02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=A4berich?= Date: Mon, 12 Apr 2021 19:48:19 +0200 Subject: [PATCH] Enforce amplitude cal point limit, SCPI command for reading trace data --- .../Calibration/amplitudecaldialog.cpp | 35 ++- .../Calibration/amplitudecaldialog.h | 4 +- .../PC_Application/Calibration/calkit.cpp | 2 +- .../CustomWidgets/informationbox.cpp | 2 +- Software/PC_Application/Device/device.cpp | 12 +- Software/PC_Application/Device/device.h | 2 +- .../PC_Application/Generator/generator.cpp | 6 +- .../SpectrumAnalyzer/spectrumanalyzer.cpp | 35 +-- .../SpectrumAnalyzer/spectrumanalyzer.h | 2 + .../PC_Application/Traces/tracewidget.cpp | 53 ++++ Software/PC_Application/Traces/tracewidget.h | 4 +- .../PC_Application/Traces/tracexyplot.cpp | 2 +- Software/PC_Application/VNA/vna.cpp | 25 +- Software/PC_Application/VNA/vna.h | 2 + Software/PC_Application/appwindow.cpp | 231 +++++++++++++----- Software/PC_Application/appwindow.h | 1 + Software/PC_Application/main.cpp | 15 +- Software/PC_Application/scpi.cpp | 8 +- Software/PC_Application/scpi.h | 6 +- .../VNA_embedded/Application/AmplitudeCal.cpp | 6 +- Software/VNA_embedded/Application/App.cpp | 5 + 21 files changed, 342 insertions(+), 116 deletions(-) diff --git a/Software/PC_Application/Calibration/amplitudecaldialog.cpp b/Software/PC_Application/Calibration/amplitudecaldialog.cpp index b10f036..26ece2a 100644 --- a/Software/PC_Application/Calibration/amplitudecaldialog.cpp +++ b/Software/PC_Application/Calibration/amplitudecaldialog.cpp @@ -9,6 +9,7 @@ #include #include "json.hpp" #include +#include using namespace std; using namespace nlohmann; @@ -90,7 +91,10 @@ AmplitudeCalDialog::AmplitudeCalDialog(Device *dev, QWidget *parent) : p.port1set = false; p.port2set = false; UpdateAmplitude(p); - AddPoint(p); + if(!AddPoint(p)) { + InformationBox::ShowMessage("Limit reached", "Unable to add all points from file, would not fit into the device"); + break; + } } }); @@ -176,6 +180,7 @@ void AmplitudeCalDialog::setAmplitude(double amplitude, unsigned int point, bool void AmplitudeCalDialog::ReceivedPoint(Protocol::AmplitudeCorrectionPoint p) { +// qDebug() << "Received amplitude calibration point" << p.pointNum << "/" << p.totalPoints; CorrectionPoint c; c.frequency = p.freq * 10.0; c.correctionPort1 = p.port1; @@ -199,7 +204,7 @@ void AmplitudeCalDialog::LoadFromDevice() ui->load->setEnabled(false); dev->SetIdle(); RemoveAllPoints(); - qDebug() << "Asking for amplitude calibration"; +// qDebug() << "Asking for amplitude calibration"; connect(dev, &Device::AmplitudeCorrectionPointReceived, this, &AmplitudeCalDialog::ReceivedPoint); dev->SendCommandWithoutPayload(requestCommand()); edited = false; @@ -219,6 +224,7 @@ void AmplitudeCalDialog::SaveToDevice() info.amplitudePoint.totalPoints = points.size(); info.amplitudePoint.pointNum = i; dev->SendPacket(info); +// qDebug() << "Sent amplitude calibration point" << i << "/" << points.size(); } edited = false; UpdateSaveButton(); @@ -242,8 +248,12 @@ void AmplitudeCalDialog::RemoveAllPoints() UpdateSaveButton(); } -void AmplitudeCalDialog::AddPoint(AmplitudeCalDialog::CorrectionPoint &p) +bool AmplitudeCalDialog::AddPoint(AmplitudeCalDialog::CorrectionPoint &p) { + if (points.size() >= Device::Info().limits_maxAmplitudePoints) { + // already at limit + return false; + } // find position at which this frequency gets inserted auto index = upper_bound(points.begin(), points.end(), p.frequency, [](double value, const CorrectionPoint& p){ return value < p.frequency; @@ -253,9 +263,10 @@ void AmplitudeCalDialog::AddPoint(AmplitudeCalDialog::CorrectionPoint &p) points.insert(index, p); model.endInsertRows(); UpdateSaveButton(); + return true; } -void AmplitudeCalDialog::AddPoint(double frequency) +bool AmplitudeCalDialog::AddPoint(double frequency) { CorrectionPoint newPoint; newPoint.frequency = frequency; @@ -263,8 +274,11 @@ void AmplitudeCalDialog::AddPoint(double frequency) newPoint.correctionPort2 = 0; newPoint.port1set = false; newPoint.port2set = false; - AddPoint(newPoint); - edited = true; + auto success = AddPoint(newPoint); + if (success) { + edited = true; + } + return success; } void AmplitudeCalDialog::AddPointDialog() @@ -296,14 +310,19 @@ void AmplitudeCalDialog::AddPointDialog() RemoveAllPoints(); } if(ui->singlePoint->isChecked()) { - AddPoint(ui->frequency->value()); + if(!AddPoint(ui->frequency->value())) { + InformationBox::ShowMessage("Limit reached", "Can't add any more points, would not fit into the device"); + } } else { double freq_start = ui->startFreq->value(); double freq_stop = ui->stopFreq->value(); unsigned int points = ui->numPoints->value(); double freq_step = (freq_stop - freq_start) / (points - 1); for(unsigned int i=0;isetStandardButtons(QMessageBox::Ok); - msg->exec(); + msg->show(); } file.close(); diff --git a/Software/PC_Application/CustomWidgets/informationbox.cpp b/Software/PC_Application/CustomWidgets/informationbox.cpp index 0713a06..993c7a7 100644 --- a/Software/PC_Application/CustomWidgets/informationbox.cpp +++ b/Software/PC_Application/CustomWidgets/informationbox.cpp @@ -16,7 +16,7 @@ void InformationBox::ShowMessage(QString title, QString message, QString message QSettings s; if(!s.contains(hashToSettingsKey(hash))) { auto box = new InformationBox(title, message, hash, nullptr); - box->exec(); + box->show(); } } diff --git a/Software/PC_Application/Device/device.cpp b/Software/PC_Application/Device/device.cpp index 7f5d6a8..f3a9d26 100644 --- a/Software/PC_Application/Device/device.cpp +++ b/Software/PC_Application/Device/device.cpp @@ -170,7 +170,7 @@ Device::Device(QString serial) if(!m_handle) { QString message = "No device found"; auto msg = new QMessageBox(QMessageBox::Icon::Warning, "Error opening device", message); - msg->exec(); + msg->show(); libusb_exit(m_context); throw std::runtime_error(message.toStdString()); return; @@ -187,7 +187,7 @@ Device::Device(QString serial) message.append("\" Maybe you are already connected to this device?"); qWarning() << message; auto msg = new QMessageBox(QMessageBox::Icon::Warning, "Error opening device", message); - msg->exec(); + msg->show(); libusb_exit(m_context); throw std::runtime_error(message.toStdString()); } @@ -360,7 +360,7 @@ void Device::SearchDevices(std::function "If that is not the case, you can try installing the WinUSB driver using Zadig (https://zadig.akeo.ie/)"); qWarning() << message; auto msg = new QMessageBox(QMessageBox::Icon::Warning, "Error opening device", message); - msg->exec(); + msg->show(); } continue; } @@ -520,6 +520,12 @@ void Device::transmissionFinished(TransmissionResult result) qWarning() << "transmissionFinished with empty transmission queue, stray Ack?"; return; } + if(result == TransmissionResult::Timeout) { + qWarning() << "transmissionFinished with timeout"; + } + if(result == TransmissionResult::Nack) { + qWarning() << "transmissionFinished with NACK"; + } auto t = transmissionQueue.dequeue(); if(t.callback) { t.callback(result); diff --git a/Software/PC_Application/Device/device.h b/Software/PC_Application/Device/device.h index e577f48..8424a95 100644 --- a/Software/PC_Application/Device/device.h +++ b/Software/PC_Application/Device/device.h @@ -57,7 +57,7 @@ public: // connect to a VNA device. If serial is specified only connecting to this device, otherwise to the first one found Device(QString serial = QString()); ~Device(); - bool SendPacket(const Protocol::PacketInfo& packet, std::function cb = nullptr, unsigned int timeout = 200); + bool SendPacket(const Protocol::PacketInfo& packet, std::function cb = nullptr, unsigned int timeout = 500); bool Configure(Protocol::SweepSettings settings, std::function cb = nullptr); bool Configure(Protocol::SpectrumAnalyzerSettings settings); bool SetManual(Protocol::ManualControl manual); diff --git a/Software/PC_Application/Generator/generator.cpp b/Software/PC_Application/Generator/generator.cpp index a868551..b3fc876 100644 --- a/Software/PC_Application/Generator/generator.cpp +++ b/Software/PC_Application/Generator/generator.cpp @@ -66,7 +66,7 @@ void Generator::setupSCPI() central->setFrequency(newval); return ""; } - }, [=]() -> QString { + }, [=](QStringList) -> QString { return QString::number(central->getDeviceStatus().frequency); })); add(new SCPICommand("LVL", [=](QStringList params) -> QString { @@ -81,7 +81,7 @@ void Generator::setupSCPI() central->setLevel(newval); return ""; } - }, [=]() -> QString { + }, [=](QStringList) -> QString { return QString::number(central->getDeviceStatus().cdbm_level / 100.0); })); add(new SCPICommand("PORT", [=](QStringList params) -> QString { @@ -96,7 +96,7 @@ void Generator::setupSCPI() central->setPort(newval); return ""; } - }, [=]() -> QString { + }, [=](QStringList) -> QString { return QString::number(central->getDeviceStatus().activePort); })); } diff --git a/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.cpp b/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.cpp index 5ad890c..2b4c4ec 100644 --- a/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.cpp +++ b/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.cpp @@ -235,7 +235,8 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window) markerModel = new TraceMarkerModel(traceModel, this); auto tracesDock = new QDockWidget("Traces"); - tracesDock->setWidget(new TraceWidgetSA(traceModel, window)); + traceWidget = new TraceWidgetSA(traceModel, window); + tracesDock->setWidget(traceWidget); window->addDockWidget(Qt::LeftDockWidgetArea, tracesDock); docks.insert(tracesDock); @@ -677,7 +678,7 @@ void SpectrumAnalyzer::SetupSCPI() SetSpan(newval); return ""; } - }, [=]() -> QString { + }, [=](QStringList) -> QString { return QString::number(settings.f_stop - settings.f_start); })); scpi_freq->add(new SCPICommand("START", [=](QStringList params) -> QString { @@ -688,7 +689,7 @@ void SpectrumAnalyzer::SetupSCPI() SetStartFreq(newval); return ""; } - }, [=]() -> QString { + }, [=](QStringList) -> QString { return QString::number(settings.f_start); })); scpi_freq->add(new SCPICommand("CENTer", [=](QStringList params) -> QString { @@ -699,7 +700,7 @@ void SpectrumAnalyzer::SetupSCPI() SetCenterFreq(newval); return ""; } - }, [=]() -> QString { + }, [=](QStringList) -> QString { return QString::number((settings.f_start + settings.f_stop)/2); })); scpi_freq->add(new SCPICommand("STOP", [=](QStringList params) -> QString { @@ -710,10 +711,11 @@ void SpectrumAnalyzer::SetupSCPI() SetStopFreq(newval); return ""; } - }, [=]() -> QString { + }, [=](QStringList) -> QString { return QString::number(settings.f_stop); })); scpi_freq->add(new SCPICommand("FULL", [=](QStringList params) -> QString { + Q_UNUSED(params) SetFullSpan(); return ""; }, nullptr)); @@ -727,7 +729,7 @@ void SpectrumAnalyzer::SetupSCPI() SetRBW(newval); return ""; } - }, [=]() -> QString { + }, [=](QStringList) -> QString { return QString::number(settings.RBW); })); scpi_acq->add(new SCPICommand("WINDow", [=](QStringList params) -> QString { @@ -746,7 +748,7 @@ void SpectrumAnalyzer::SetupSCPI() return "INVALID MDOE"; } return ""; - }, [=]() -> QString { + }, [=](QStringList) -> QString { switch((Window) settings.WindowType) { case Window::None: return "NONE"; case Window::Kaiser: return "KAISER"; @@ -773,7 +775,7 @@ void SpectrumAnalyzer::SetupSCPI() return "INVALID MDOE"; } return ""; - }, [=]() -> QString { + }, [=](QStringList) -> QString { switch((Detector) settings.Detector) { case Detector::PPeak: return "+PEAK"; case Detector::NPeak: return "-PEAK"; @@ -791,7 +793,7 @@ void SpectrumAnalyzer::SetupSCPI() SetAveraging(newval); return ""; } - }, [=]() -> QString { + }, [=](QStringList) -> QString { return QString::number(averages); })); scpi_acq->add(new SCPICommand("SIGid", [=](QStringList params) -> QString { @@ -806,7 +808,7 @@ void SpectrumAnalyzer::SetupSCPI() return "ERROR"; } return ""; - }, [=]() -> QString { + }, [=](QStringList) -> QString { return settings.SignalID ? "1" : "0"; })); auto scpi_tg = new SCPINode("TRACKing"); @@ -823,7 +825,7 @@ void SpectrumAnalyzer::SetupSCPI() return "ERROR"; } return ""; - }, [=]() -> QString { + }, [=](QStringList) -> QString { return settings.trackingGenerator ? "1" : "0"; })); scpi_tg->add(new SCPICommand("Port", [=](QStringList params) -> QString { @@ -838,7 +840,7 @@ void SpectrumAnalyzer::SetupSCPI() return "ERROR"; } return ""; - }, [=]() -> QString { + }, [=](QStringList) -> QString { return settings.trackingGeneratorPort ? "2" : "1"; })); scpi_tg->add(new SCPICommand("LVL", [=](QStringList params) -> QString { @@ -853,7 +855,7 @@ void SpectrumAnalyzer::SetupSCPI() SetTGLevel(newval); return ""; } - }, [=]() -> QString { + }, [=](QStringList) -> QString { return QString::number(settings.trackingPower / 100.0); })); scpi_tg->add(new SCPICommand("OFFset", [=](QStringList params) -> QString { @@ -868,7 +870,7 @@ void SpectrumAnalyzer::SetupSCPI() SetTGOffset(newval); return ""; } - }, [=]() -> QString { + }, [=](QStringList) -> QString { return QString::number(settings.trackingGeneratorOffset); })); auto scpi_norm = new SCPINode("NORMalize"); @@ -885,7 +887,7 @@ void SpectrumAnalyzer::SetupSCPI() return "ERROR"; } return ""; - }, [=]() -> QString { + }, [=](QStringList) -> QString { return normalize.active ? "1" : "0"; })); scpi_norm->add(new SCPICommand("MEASure", [=](QStringList params) -> QString { @@ -905,9 +907,10 @@ void SpectrumAnalyzer::SetupSCPI() SetNormalizationLevel(newval); return ""; } - }, [=]() -> QString { + }, [=](QStringList) -> QString { return QString::number(normalize.Level->value()); })); + SCPINode::add(traceWidget); } void SpectrumAnalyzer::UpdateAverageCount() diff --git a/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.h b/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.h index 45a6ea1..0a3a696 100644 --- a/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.h +++ b/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.h @@ -9,6 +9,7 @@ #include #include #include "scpi.h" +#include "Traces/tracewidget.h" class SpectrumAnalyzer : public Mode, public SCPINode { @@ -76,6 +77,7 @@ private: Protocol::SpectrumAnalyzerSettings settings; unsigned int averages; TraceModel traceModel; + TraceWidget *traceWidget; TraceMarkerModel *markerModel; Averaging average; diff --git a/Software/PC_Application/Traces/tracewidget.cpp b/Software/PC_Application/Traces/tracewidget.cpp index f712a20..c065c82 100644 --- a/Software/PC_Application/Traces/tracewidget.cpp +++ b/Software/PC_Application/Traces/tracewidget.cpp @@ -12,6 +12,7 @@ TraceWidget::TraceWidget(TraceModel &model, QWidget *parent) : QWidget(parent), + SCPINode("TRACe"), ui(new Ui::TraceWidget), model(model) { @@ -23,6 +24,7 @@ TraceWidget::TraceWidget(TraceModel &model, QWidget *parent) : connect(ui->bExport, &QPushButton::clicked, this, &TraceWidget::exportDialog); installEventFilter(this); createCount = 0; + SetupSCPI(); } TraceWidget::~TraceWidget() @@ -133,3 +135,54 @@ void TraceWidget::on_view_clicked(const QModelIndex &index) break; } } + +void TraceWidget::SetupSCPI() +{ + auto findTrace = [=](QStringList params) -> Trace* { + if(params.size() < 1) { + return nullptr; + } + // check if trace is specified by number + bool ok; + auto n = params[0].toUInt(&ok); + if(ok) { + // check if enough traces exist + if(n < model.getTraces().size()) { + return model.getTraces()[n]; + } else { + // invalid number + return nullptr; + } + } else { + // trace specified by name + for(auto t : model.getTraces()) { + if(t->name().compare(params[0], Qt::CaseInsensitive) == 0) { + return t; + } + } + // not found + return nullptr; + } + }; + add(new SCPICommand("LIST", nullptr, [=](QStringList){ + QString ret; + for(auto t : model.getTraces()) { + ret += t->name() + ","; + } + ret.chop(1); + return ret; + })); + add(new SCPICommand("DATA", nullptr, [=](QStringList params) -> QString { + auto t = findTrace(params); + if(!t) { + return "ERROR"; + } + QString ret; + for(unsigned int i=0;isize();i++) { + auto d = t->sample(i); + ret += "["+QString::number(d.x)+","+QString::number(d.y.real())+","+QString::number(d.y.imag())+"],"; + } + ret.chop(1); + return ret; + })); +} diff --git a/Software/PC_Application/Traces/tracewidget.h b/Software/PC_Application/Traces/tracewidget.h index aa5f6b5..b6e4ff7 100644 --- a/Software/PC_Application/Traces/tracewidget.h +++ b/Software/PC_Application/Traces/tracewidget.h @@ -3,12 +3,13 @@ #include #include "tracemodel.h" +#include "scpi.h" namespace Ui { class TraceWidget; } -class TraceWidget : public QWidget +class TraceWidget : public QWidget, public SCPINode { Q_OBJECT @@ -26,6 +27,7 @@ protected slots: virtual void importDialog() = 0; protected: + void SetupSCPI(); bool eventFilter(QObject *obj, QEvent *event) override; virtual Trace::LiveParameter defaultParameter() = 0; QPoint dragStartPosition; diff --git a/Software/PC_Application/Traces/tracexyplot.cpp b/Software/PC_Application/Traces/tracexyplot.cpp index 9bc2da8..fc5c95d 100644 --- a/Software/PC_Application/Traces/tracexyplot.cpp +++ b/Software/PC_Application/Traces/tracexyplot.cpp @@ -219,7 +219,7 @@ bool TraceXYPlot::isTDRtype(TraceXYPlot::YAxisType type) void TraceXYPlot::axisSetupDialog() { auto setup = new XYplotAxisDialog(this); - setup->exec(); + setup->show(); } void TraceXYPlot::updateContextMenu() diff --git a/Software/PC_Application/VNA/vna.cpp b/Software/PC_Application/VNA/vna.cpp index fc7ecf8..2badd02 100644 --- a/Software/PC_Application/VNA/vna.cpp +++ b/Software/PC_Application/VNA/vna.cpp @@ -59,8 +59,6 @@ VNA::VNA(AppWindow *window) calDialog.reset(); calEdited = false; - SetupSCPI(); - // Create default traces auto tS11 = new Trace("S11", Qt::yellow); tS11->fromLivedata(Trace::LivedataType::Overwrite, Trace::LiveParameter::S11); @@ -421,7 +419,8 @@ VNA::VNA(AppWindow *window) markerModel = new TraceMarkerModel(traceModel, this); auto tracesDock = new QDockWidget("Traces"); - tracesDock->setWidget(new TraceWidgetVNA(traceModel, cal, deembedding)); + traceWidget = new TraceWidgetVNA(traceModel, cal, deembedding); + tracesDock->setWidget(traceWidget); window->addDockWidget(Qt::LeftDockWidgetArea, tracesDock); docks.insert(tracesDock); @@ -433,6 +432,8 @@ VNA::VNA(AppWindow *window) window->addDockWidget(Qt::BottomDockWidgetArea, markerDock); docks.insert(markerDock); + SetupSCPI(); + // Set initial sweep settings auto pref = Preferences::getInstance(); if(pref.Acquisition.alwaysExciteBothPorts) { @@ -902,7 +903,7 @@ void VNA::SetupSCPI() SetSpan(newval); return ""; } - }, [=]() -> QString { + }, [=](QStringList) -> QString { return QString::number(settings.f_stop - settings.f_start); })); scpi_freq->add(new SCPICommand("START", [=](QStringList params) -> QString { @@ -913,7 +914,7 @@ void VNA::SetupSCPI() SetStartFreq(newval); return ""; } - }, [=]() -> QString { + }, [=](QStringList) -> QString { return QString::number(settings.f_start); })); scpi_freq->add(new SCPICommand("CENTer", [=](QStringList params) -> QString { @@ -924,7 +925,7 @@ void VNA::SetupSCPI() SetCenterFreq(newval); return ""; } - }, [=]() -> QString { + }, [=](QStringList) -> QString { return QString::number((settings.f_start + settings.f_stop)/2); })); scpi_freq->add(new SCPICommand("STOP", [=](QStringList params) -> QString { @@ -935,10 +936,11 @@ void VNA::SetupSCPI() SetStopFreq(newval); return ""; } - }, [=]() -> QString { + }, [=](QStringList) -> QString { return QString::number(settings.f_stop); })); scpi_freq->add(new SCPICommand("FULL", [=](QStringList params) -> QString { + Q_UNUSED(params) SetFullSpan(); return ""; }, nullptr)); @@ -952,7 +954,7 @@ void VNA::SetupSCPI() SetIFBandwidth(newval); return ""; } - }, [=]() -> QString { + }, [=](QStringList) -> QString { return QString::number(settings.if_bandwidth); })); scpi_acq->add(new SCPICommand("POINTS", [=](QStringList params) -> QString { @@ -963,7 +965,7 @@ void VNA::SetupSCPI() SetPoints(newval); return ""; } - }, [=]() -> QString { + }, [=](QStringList) -> QString { return QString::number(settings.points); })); scpi_acq->add(new SCPICommand("AVG", [=](QStringList params) -> QString { @@ -974,7 +976,7 @@ void VNA::SetupSCPI() SetAveraging(newval); return ""; } - }, [=]() -> QString { + }, [=](QStringList) -> QString { return QString::number(averages); })); auto scpi_stim = new SCPINode("STIMulus"); @@ -991,9 +993,10 @@ void VNA::SetupSCPI() SetSourceLevel(newval); return ""; } - }, [=]() -> QString { + }, [=](QStringList) -> QString { return QString::number(settings.cdbm_excitation / 100.0); })); + SCPINode::add(traceWidget); } void VNA::ConstrainAndUpdateFrequencies() diff --git a/Software/PC_Application/VNA/vna.h b/Software/PC_Application/VNA/vna.h index 811cd52..45de702 100644 --- a/Software/PC_Application/VNA/vna.h +++ b/Software/PC_Application/VNA/vna.h @@ -10,6 +10,7 @@ #include #include "Deembedding/deembedding.h" #include "scpi.h" +#include "Traces/tracewidget.h" class VNA : public Mode, public SCPINode { @@ -66,6 +67,7 @@ private: Protocol::SweepSettings settings; unsigned int averages; TraceModel traceModel; + TraceWidget *traceWidget; TraceMarkerModel *markerModel; Averaging average; diff --git a/Software/PC_Application/appwindow.cpp b/Software/PC_Application/appwindow.cpp index 49af003..e6578b0 100644 --- a/Software/PC_Application/appwindow.cpp +++ b/Software/PC_Application/appwindow.cpp @@ -95,60 +95,6 @@ AppWindow::AppWindow(QWidget *parent) StartTCPServer(Preferences::getInstance().General.SCPI.port); } - scpi.add(new SCPICommand("*IDN", nullptr, [=](){ - return "LibreVNA-GUI"; - })); - auto scpi_dev = new SCPINode("DEVice"); - scpi.add(scpi_dev); - scpi_dev->add(new SCPICommand("DISConnect", [=](QStringList params) -> QString { - Q_UNUSED(params) - DisconnectDevice(); - return ""; - }, nullptr)); - scpi_dev->add(new SCPICommand("CONNect", [=](QStringList params) -> QString { - QString serial; - if(params.size() > 0) { - serial = params[0]; - } - if(!ConnectToDevice(serial)) { - return "Device not found"; - } else { - return ""; - } - }, [=]() -> QString { - if(device) { - return device->serial(); - } else { - return "Not connected"; - } - })); - scpi.add(new SCPICommand("MODE", [=](QStringList params) -> QString { - if (params.size() != 1) { - return "ERROR"; - } - if (params[0] == "VNA") { - vna->activate(); - } else if(params[0] == "GEN") { - generator->activate(); - } else if(params[0] == "SA") { - spectrumAnalyzer->activate(); - } else { - return "INVALID MDOE"; - } - return ""; - }, [=]() -> QString { - auto active = Mode::getActiveMode(); - if(active == vna) { - return "VNA"; - } else if(active == generator) { - return "GEN"; - } else if(active == spectrumAnalyzer) { - return "SA"; - } else { - return "ERROR"; - } - })); - ui->setupUi(this); ui->statusbar->addWidget(&lConnectionStatus); auto div1 = new QFrame; @@ -196,10 +142,6 @@ AppWindow::AppWindow(QWidget *parent) generator = new Generator(this); spectrumAnalyzer = new SpectrumAnalyzer(this); - scpi.add(vna); - scpi.add(generator); - scpi.add(spectrumAnalyzer); - // UI connections connect(ui->actionUpdate_Device_List, &QAction::triggered, this, &AppWindow::UpdateDeviceList); connect(ui->actionDisconnect, &QAction::triggered, this, &AppWindow::DisconnectDevice); @@ -242,7 +184,7 @@ AppWindow::AppWindow(QWidget *parent) connect(ui->actionReceiver_Calibration, &QAction::triggered, this, &AppWindow::ReceiverCalibrationDialog); connect(ui->actionPreferences, &QAction::triggered, [=](){ // save previous SCPI settings in case they change - auto p = Preferences::getInstance(); + auto &p = Preferences::getInstance(); auto SCPIenabled = p.General.SCPI.enabled; auto SCPIport = p.General.SCPI.port; p.edit(); @@ -272,6 +214,8 @@ AppWindow::AppWindow(QWidget *parent) restoreGeometry(settings.value("geometry").toByteArray()); } + SetupSCPI(); + // Set default mode vna->activate(); @@ -416,6 +360,174 @@ void AppWindow::CreateToolbars() tb_reference->setObjectName("Reference Toolbar"); } +void AppWindow::SetupSCPI() +{ + scpi.add(new SCPICommand("*IDN", nullptr, [=](QStringList){ + return "LibreVNA-GUI"; + })); + auto scpi_dev = new SCPINode("DEVice"); + scpi.add(scpi_dev); + scpi_dev->add(new SCPICommand("DISConnect", [=](QStringList params) -> QString { + Q_UNUSED(params) + DisconnectDevice(); + return ""; + }, nullptr)); + scpi_dev->add(new SCPICommand("CONNect", [=](QStringList params) -> QString { + QString serial; + if(params.size() > 0) { + serial = params[0]; + } + if(!ConnectToDevice(serial)) { + return "Device not found"; + } else { + return ""; + } + }, [=](QStringList) -> QString { + if(device) { + return device->serial(); + } else { + return "Not connected"; + } + })); + scpi_dev->add(new SCPICommand("LIST", nullptr, [=](QStringList) -> QString { + QString ret; + for(auto d : Device::GetDevices()) { + ret += d + ","; + } + // remove last comma + ret.chop(1); + return ret; + })); + auto scpi_ref = new SCPINode("REFerence"); + scpi_dev->add(scpi_ref); + scpi_ref->add(new SCPICommand("OUT", [=](QStringList params) -> QString { + if(params.size() != 1) { + return "ERROR"; + } else if(params[0] == "0" || params[0] == "OFF") { + toolbars.reference.outFreq->setCurrentIndex(0); + } else if(params[0] == "10") { + toolbars.reference.outFreq->setCurrentIndex(1); + } else if(params[0] == "100") { + toolbars.reference.outFreq->setCurrentIndex(2); + } else { + return "ERROR"; + } + return ""; + }, [=](QStringList) -> QString { + switch(toolbars.reference.outFreq->currentIndex()) { + case 0: return "OFF"; + case 1: return "10"; + case 2: return "100"; + default: return "ERROR"; + } + })); + scpi_ref->add(new SCPICommand("IN", [=](QStringList params) -> QString { + if(params.size() != 1) { + return "ERROR"; + } else if(params[0] == "INT") { + toolbars.reference.type->setCurrentIndex(0); + } else if(params[0] == "EXT") { + toolbars.reference.type->setCurrentIndex(1); + } else if(params[0] == "AUTO") { + toolbars.reference.type->setCurrentIndex(2); + } else { + return "ERROR"; + } + return ""; + }, [=](QStringList) -> QString { + switch(Device::Info().extRefInUse) { + case 0: return "INT"; + case 1: return "EXT"; + default: return "ERROR"; + } + })); + scpi.add(new SCPICommand("MODE", [=](QStringList params) -> QString { + if (params.size() != 1) { + return "ERROR"; + } + if (params[0] == "VNA") { + vna->activate(); + } else if(params[0] == "GEN") { + generator->activate(); + } else if(params[0] == "SA") { + spectrumAnalyzer->activate(); + } else { + return "INVALID MDOE"; + } + return ""; + }, [=](QStringList) -> QString { + auto active = Mode::getActiveMode(); + if(active == vna) { + return "VNA"; + } else if(active == generator) { + return "GEN"; + } else if(active == spectrumAnalyzer) { + return "SA"; + } else { + return "ERROR"; + } + })); + auto scpi_status = new SCPINode("STAtus"); + scpi_dev->add(scpi_status); + scpi_status->add(new SCPICommand("UNLOcked", nullptr, [=](QStringList){ + bool locked = Device::Info().source_locked && Device::Info().LO1_locked; + return locked ? "0" : "1"; + })); + scpi_status->add(new SCPICommand("ADCOVERload", nullptr, [=](QStringList){ + return Device::Info().ADC_overload ? "1" : "0"; + })); + scpi_status->add(new SCPICommand("UNLEVel", nullptr, [=](QStringList){ + return Device::Info().unlevel ? "1" : "0"; + })); + auto scpi_info = new SCPINode("INFo"); + scpi_dev->add(scpi_info); + scpi_info->add(new SCPICommand("FWREVision", nullptr, [=](QStringList){ + return QString::number(Device::Info().FW_major)+"."+QString::number(Device::Info().FW_minor)+"."+QString::number(Device::Info().FW_patch); + })); + scpi_info->add(new SCPICommand("HWREVision", nullptr, [=](QStringList){ + return QString(Device::Info().HW_Revision); + })); + scpi_info->add(new SCPICommand("TEMPeratures", nullptr, [=](QStringList){ + return QString::number(Device::Info().temp_source)+"/"+QString::number(Device::Info().temp_LO1)+"/"+QString::number(Device::Info().temp_MCU); + })); + auto scpi_limits = new SCPINode("LIMits"); + scpi_info->add(scpi_limits); + scpi_limits->add(new SCPICommand("MINFrequency", nullptr, [=](QStringList){ + return QString::number(Device::Info().limits_minFreq); + })); + scpi_limits->add(new SCPICommand("MAXFrequency", nullptr, [=](QStringList){ + return QString::number(Device::Info().limits_maxFreq); + })); + scpi_limits->add(new SCPICommand("MINIFBW", nullptr, [=](QStringList){ + return QString::number(Device::Info().limits_minIFBW); + })); + scpi_limits->add(new SCPICommand("MAXIFBW", nullptr, [=](QStringList){ + return QString::number(Device::Info().limits_maxIFBW); + })); + scpi_limits->add(new SCPICommand("MAXPoints", nullptr, [=](QStringList){ + return QString::number(Device::Info().limits_maxPoints); + })); + scpi_limits->add(new SCPICommand("MINPOWer", nullptr, [=](QStringList){ + return QString::number(Device::Info().limits_cdbm_min / 100.0); + })); + scpi_limits->add(new SCPICommand("MAXPOWer", nullptr, [=](QStringList){ + return QString::number(Device::Info().limits_cdbm_max / 100.0); + })); + scpi_limits->add(new SCPICommand("MINRBW", nullptr, [=](QStringList){ + return QString::number(Device::Info().limits_minRBW); + })); + scpi_limits->add(new SCPICommand("MAXRBW", nullptr, [=](QStringList){ + return QString::number(Device::Info().limits_maxRBW); + })); + scpi_limits->add(new SCPICommand("MAXHARMonicfrequency", nullptr, [=](QStringList){ + return QString::number(Device::Info().limits_maxFreqHarmonic); + })); + + scpi.add(vna); + scpi.add(generator); + scpi.add(spectrumAnalyzer); +} + void AppWindow::StartTCPServer(int port) { server = new TCPServer(port); @@ -426,6 +538,7 @@ void AppWindow::StartTCPServer(int port) void AppWindow::StopTCPServer() { delete server; + server = nullptr; } int AppWindow::UpdateDeviceList() diff --git a/Software/PC_Application/appwindow.h b/Software/PC_Application/appwindow.h index a196838..ba37a56 100644 --- a/Software/PC_Application/appwindow.h +++ b/Software/PC_Application/appwindow.h @@ -58,6 +58,7 @@ private slots: private: void DeviceConnectionLost(); void CreateToolbars(); + void SetupSCPI(); void StartTCPServer(int port); void StopTCPServer(); diff --git a/Software/PC_Application/main.cpp b/Software/PC_Application/main.cpp index 2e47473..680c030 100644 --- a/Software/PC_Application/main.cpp +++ b/Software/PC_Application/main.cpp @@ -20,7 +20,20 @@ void sig_handler(int s) { } int main(int argc, char *argv[]) { - app = new QApplication(argc, argv); + // Hack: set platform to offscreen if no-gui option specified, this prevents any dialogs from showing up + char *argv_ext[argc+2]; + for(int i=0;i("-platform"); + argv_ext[argc+1] = const_cast("offscreen"); + argc+=2; + break; + } + } + app = new QApplication(argc, argv_ext); window = new AppWindow; signal(SIGINT, sig_handler); app->exec(); diff --git a/Software/PC_Application/scpi.cpp b/Software/PC_Application/scpi.cpp index 150837f..552de78 100644 --- a/Software/PC_Application/scpi.cpp +++ b/Software/PC_Application/scpi.cpp @@ -5,7 +5,7 @@ SCPI::SCPI() : SCPINode("") { lastNode = this; - add(new SCPICommand("*LST", nullptr, [=](){ + add(new SCPICommand("*LST", nullptr, [=](QStringList){ QString list; createCommandList("", list); return list.trimmed(); @@ -130,7 +130,7 @@ QString SCPINode::parse(QString cmd, SCPINode* &lastNode) // save current node in case of non-root for the next command lastNode = this; if(isQuery) { - return c->query(); + return c->query(params); } else { return c->execute(params); } @@ -150,11 +150,11 @@ QString SCPICommand::execute(QStringList params) } } -QString SCPICommand::query() +QString SCPICommand::query(QStringList params) { if(fn_query == nullptr) { return "ERROR"; } else { - return fn_query(); + return fn_query(params); } } diff --git a/Software/PC_Application/scpi.h b/Software/PC_Application/scpi.h index c32ed9f..a20baa9 100644 --- a/Software/PC_Application/scpi.h +++ b/Software/PC_Application/scpi.h @@ -8,20 +8,20 @@ class SCPICommand { public: - SCPICommand(QString name, std::function cmd, std::function query) : + SCPICommand(QString name, std::function cmd, std::function query) : _name(name), fn_cmd(cmd), fn_query(query){} QString execute(QStringList params); - QString query(); + QString query(QStringList params); QString name() {return _name;} bool queryable() { return fn_query != nullptr;}; bool executable() { return fn_cmd != nullptr;}; private: const QString _name; std::function fn_cmd; - std::function fn_query; + std::function fn_query; }; class SCPINode { diff --git a/Software/VNA_embedded/Application/AmplitudeCal.cpp b/Software/VNA_embedded/Application/AmplitudeCal.cpp index c6984f7..2b1a1a3 100644 --- a/Software/VNA_embedded/Application/AmplitudeCal.cpp +++ b/Software/VNA_embedded/Application/AmplitudeCal.cpp @@ -34,6 +34,10 @@ bool AmplitudeCal::Load() { LOG_WARN("Invalid version in flash, expected %u, got %u", version, cal.version); SetDefault(); return false; + } else if(cal.Source.usedPoints == 0 || cal.Receiver.usedPoints == 0){ + LOG_WARN("Empty amplitude calibration, resetting to default"); + SetDefault(); + return false; } else { LOG_INFO("Loaded from flash"); return true; @@ -128,7 +132,7 @@ static void addPoint(CorrectionTable& table, const Protocol::AmplitudeCorrection table.freq[p.pointNum] = p.freq; table.port1Correction[p.pointNum] = p.port1; table.port2Correction[p.pointNum] = p.port2; - if(p.pointNum == p.totalPoints - 1) { + if(p.pointNum == p.totalPoints - 1 || p.pointNum == AmplitudeCal::maxPoints - 1) { // this was the last point, update used points and save table.usedPoints = p.totalPoints; LOG_INFO("Last point received, saving to flash"); diff --git a/Software/VNA_embedded/Application/App.cpp b/Software/VNA_embedded/Application/App.cpp index 91025e5..a38af87 100644 --- a/Software/VNA_embedded/Application/App.cpp +++ b/Software/VNA_embedded/Application/App.cpp @@ -142,6 +142,7 @@ void App_Start() { Communication::SendWithoutPayload(Protocol::PacketType::Ack); break; case Protocol::PacketType::RequestDeviceInfo: + Communication::SendWithoutPayload(Protocol::PacketType::Ack); Protocol::PacketInfo p; p.type = Protocol::PacketType::DeviceInfo; HW::fillDeviceInfo(&p.info); @@ -189,16 +190,20 @@ void App_Start() { break; #endif case Protocol::PacketType::RequestSourceCal: + Communication::SendWithoutPayload(Protocol::PacketType::Ack); AmplitudeCal::SendSource(); break; case Protocol::PacketType::RequestReceiverCal: + Communication::SendWithoutPayload(Protocol::PacketType::Ack); AmplitudeCal::SendReceiver(); break; case Protocol::PacketType::SourceCalPoint: AmplitudeCal::AddSourcePoint(recv_packet.amplitudePoint); + Communication::SendWithoutPayload(Protocol::PacketType::Ack); break; case Protocol::PacketType::ReceiverCalPoint: AmplitudeCal::AddReceiverPoint(recv_packet.amplitudePoint); + Communication::SendWithoutPayload(Protocol::PacketType::Ack); break; default: // this packet type is not supported