Skip to content

Commit

Permalink
SCPI commands for saving/loading calibration files
Browse files Browse the repository at this point in the history
  • Loading branch information
jankae committed Oct 12, 2021
1 parent e4106fe commit 09366d7
Show file tree
Hide file tree
Showing 15 changed files with 110 additions and 36 deletions.
Binary file modified Documentation/UserManual/ProgrammingGuide.pdf
Binary file not shown.
12 changes: 12 additions & 0 deletions Documentation/UserManual/ProgrammingGuide.tex
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,18 @@ \subsubsection{VNA:CALibration:MEASure}
\subsubsection{VNA:CALibration:BUSY}
\query{Queries whether a calibration measurement is ongoing}{VNA:CALibration:BUSY?}{None}{TRUE or FALSE}

\subsubsection{VNA:CALibration:SAVE}
\event{Saves the active calibration to a file}{VNA:CALibration:SAVE}{<filename>}
Important points when saving/loading calibration files through SCPI commands:
\begin{itemize}
\item Filenames must be either absolute or relative to the location of the GUI application.
\item SCPI parsing implicitly capitalizes all commands, the file will be saved using only uppercase letters. Similarly, it is not possible to load a file whose filename contains lowercase characters.
\item If the LibreVNA-GUI (and thus also the SCPI server) is running on a different machine than the SCPI client, the calibration files will be saved/loaded from the machine that runs the GUI.
\end{itemize}

\subsubsection{VNA:CALibration:LOAD}
\query{Loads a calibration file}{VNA:CALibration:LOAD?}{<filename>}{TRUE or FALSE}

\subsection{Signal Generator Commands}
These commands change or query signal generator settings. Although most of them are available regardless of the current device mode, they usually only have an effect once the generator mode is active.

Expand Down
6 changes: 2 additions & 4 deletions Software/PC_Application/Calibration/amplitudecaldialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ AmplitudeCalDialog::AmplitudeCalDialog(Device *dev, QWidget *parent) :
file >> j;
for(auto point : j) {
if(!point.contains("Frequency") || !point.contains("Port1") || !point.contains("Port2")) {
QMessageBox::warning(this, "Error loading file", "Failed to parse calibration point");
InformationBox::ShowError("Error loading file", "Failed to parse calibration point");
return;
}
CorrectionPoint p;
Expand Down Expand Up @@ -425,9 +425,7 @@ void AmplitudeCalDialog::ReceivedMeasurement(Protocol::SpectrumAnalyzerResult re
bool AmplitudeCalDialog::ConfirmActionIfEdited()
{
if(edited) {
auto reply = QMessageBox::question(this, "Confirm action", "Some points have been edited but not saved in the device yet. If you continue, all changes will be lost (unless they are already saved to a file). Do you want to continue?",
QMessageBox::Yes|QMessageBox::No);
return reply == QMessageBox::Yes;
return InformationBox::AskQuestion("Confirm action", "Some points have been edited but not saved in the device yet. If you continue, all changes will be lost (unless they are already saved to a file). Do you want to continue?", true);
} else {
// not edited yet, nothing to confirm
return true;
Expand Down
26 changes: 21 additions & 5 deletions Software/PC_Application/Calibration/calibration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "unit.h"
#include <QDebug>
#include "Tools/parameters.h"
#include "CustomWidgets/informationbox.h"

using namespace std;

Expand Down Expand Up @@ -127,7 +128,7 @@ bool Calibration::constructErrorTerms(Calibration::Type type)
+ "The measured calibration data covers " + Unit::ToString(minFreq, "Hz", " kMG", 4) + " to " + Unit::ToString(maxFreq, "Hz", " kMG", 4)
+ ", however the calibration kit is only valid from " + Unit::ToString(kit_minFreq, "Hz", " kMG", 4) + " to " + Unit::ToString(kit_maxFreq, "Hz", " kMG", 4) + ".\n\n"
+ "Please adjust the calibration kit or the span and take the calibration measurements again.";
QMessageBox::critical(nullptr, "Unable to perform calibration", msg);
InformationBox::ShowError("Unable to perform calibration", msg);
qWarning() << msg;
return false;
}
Expand Down Expand Up @@ -732,6 +733,13 @@ bool Calibration::openFromFile(QString filename)
return false;
}
}

// force correct file ending
if(filename.toLower().endsWith(".cal")) {
filename.chop(4);
filename += ".cal";
}

qDebug() << "Attempting to open calibration from file" << filename;

// reset all data before loading new calibration
Expand All @@ -749,16 +757,24 @@ bool Calibration::openFromFile(QString filename)
try {
kit = Calkit::fromFile(calkit_file);
} catch (runtime_error e) {
QMessageBox::warning(nullptr, "Missing calibration kit", "The calibration kit file associated with the selected calibration could not be parsed. The calibration might not be accurate. (" + QString(e.what()) + ")");
InformationBox::ShowError("Missing calibration kit", "The calibration kit file associated with the selected calibration could not be parsed. The calibration might not be accurate. (" + QString(e.what()) + ")");
qWarning() << "Parsing of calibration kit failed while opening calibration file: " << e.what();
}

ifstream file;

file.open(filename.toStdString());
if(!file.good()) {
QString msg = "Unable to open file: "+filename;
InformationBox::ShowError("Error", msg);
qWarning() << msg;
return false;
}

try {
file >> *this;
} catch(runtime_error e) {
QMessageBox::warning(nullptr, "File parsing error", e.what());
} catch(exception e) {
InformationBox::ShowError("File parsing error", e.what());
qWarning() << "Calibration file parsing failed: " << e.what();
return false;
}
Expand All @@ -778,7 +794,7 @@ bool Calibration::saveToFile(QString filename)
}
}

if(filename.endsWith(".cal")) {
if(filename.toLower().endsWith(".cal")) {
filename.chop(4);
}
auto calibration_file = filename + ".cal";
Expand Down
7 changes: 2 additions & 5 deletions Software/PC_Application/Calibration/calkit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "json.hpp"
#include <QMessageBox>
#include <QDebug>
#include "CustomWidgets/informationbox.h"

using json = nlohmann::json;
using namespace std;
Expand Down Expand Up @@ -171,13 +172,9 @@ Calkit Calkit::fromFile(QString filename)
c.TRL.Line.minFreq = readLine(file).toDouble();
c.TRL.Line.maxFreq = readLine(file).toDouble();

auto msg = new QMessageBox();
msg->setWindowTitle("Loading calkit file");
msg->setText("The file \"" + filename + "\" is stored in a deprecated"
InformationBox::ShowMessage("Loading calkit file", "The file \"" + filename + "\" is stored in a deprecated"
" calibration kit format. Future versions of this application might not support"
" it anymore. Please save the calibration kit to update to the new format");
msg->setStandardButtons(QMessageBox::Ok);
msg->show();
}
file.close();

Expand Down
4 changes: 2 additions & 2 deletions Software/PC_Application/Calibration/calkitdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include <fstream>
#include <touchstone.h>
#include <QtGlobal>
#include <QMessageBox>
#include "CustomWidgets/informationbox.h"

using namespace std;

Expand Down Expand Up @@ -123,7 +123,7 @@ CalkitDialog::CalkitDialog(Calkit &c, QWidget *parent) :
try {
ownKit = Calkit::fromFile(filename);
} catch (runtime_error e) {
QMessageBox::warning(nullptr, "Error", "The calibration kit file could not be parsed (" + QString(e.what()) + ")");
InformationBox::ShowError("Error", "The calibration kit file could not be parsed (" + QString(e.what()) + ")");
qWarning() << "Parsing of calibration kit failed while opening calibration file: " << e.what();
}
updateEntries();
Expand Down
21 changes: 21 additions & 0 deletions Software/PC_Application/CustomWidgets/informationbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,15 @@
#include <QSettings>
#include <QDebug>

bool InformationBox::has_gui = true;

void InformationBox::ShowMessage(QString title, QString message, QString messageID, bool block)
{
if(!has_gui) {
// no gui option active, do not show any messages
return;
}

// check if the user still wants to see this message
unsigned int hash;
if(messageID.isEmpty()) {
Expand All @@ -31,12 +38,21 @@ void InformationBox::ShowMessageBlocking(QString title, QString message, QString

void InformationBox::ShowError(QString title, QString message)
{
if(!has_gui) {
// no gui option active, do not show any messages
return;
}
auto box = new InformationBox(title, message, QMessageBox::Information, 0, nullptr);
box->show();
}

bool InformationBox::AskQuestion(QString title, QString question, bool defaultAnswer, QString messageID)
{
if(!has_gui) {
// no gui option active, do not show any messages
return defaultAnswer;
}

// check if the user still wants to see this message
unsigned int hash;
if(messageID.isEmpty()) {
Expand All @@ -61,6 +77,11 @@ bool InformationBox::AskQuestion(QString title, QString question, bool defaultAn
}
}

void InformationBox::setGUI(bool enable)
{
has_gui = enable;
}

InformationBox::InformationBox(QString title, QString message, Icon icon, unsigned int hash, QWidget *parent)
: QMessageBox(parent),
hash(hash)
Expand Down
3 changes: 3 additions & 0 deletions Software/PC_Application/CustomWidgets/informationbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ class InformationBox : public QMessageBox
static void ShowError(QString title, QString message);
// Display a dialog with yes/no buttons. Returns true if yes is clicked, false otherwise. If the user has selected to never see this message again, defaultAnswer is returned instead
static bool AskQuestion(QString title, QString question, bool defaultAnswer, QString messageID = QString());

static void setGUI(bool enable);
private:
InformationBox(QString title, QString message, QMessageBox::Icon icon, unsigned int hash, QWidget *parent);
~InformationBox();
static QString hashToSettingsKey(unsigned int hash);
unsigned int hash;
static bool has_gui;
};

#endif // INFORMATIONBOX_H
10 changes: 4 additions & 6 deletions Software/PC_Application/Device/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <QString>
#include <QMessageBox>
#include <mutex>
#include "CustomWidgets/informationbox.h"

using namespace std;

Expand Down Expand Up @@ -169,8 +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->show();
InformationBox::ShowError("Error opening device", message);
libusb_exit(m_context);
throw std::runtime_error(message.toStdString());
return;
Expand All @@ -186,8 +186,7 @@ Device::Device(QString serial)
message.append(libusb_strerror((libusb_error) ret));
message.append("\" Maybe you are already connected to this device?");
qWarning() << message;
auto msg = new QMessageBox(QMessageBox::Icon::Warning, "Error opening device", message);
msg->show();
InformationBox::ShowError("Error opening device", message);
libusb_exit(m_context);
throw std::runtime_error(message.toStdString());
}
Expand Down Expand Up @@ -359,8 +358,7 @@ void Device::SearchDevices(std::function<bool (libusb_device_handle *, QString)>
"this device (is another instance of the application already runnning? "
"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->show();
InformationBox::ShowError("Error opening device", message);
}
continue;
}
Expand Down
4 changes: 2 additions & 2 deletions Software/PC_Application/Traces/Math/medianfilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#include "ui_medianfilterdialog.h"
#include "ui_medianexplanationwidget.h"

#include <QMessageBox>
#include "CustomWidgets/informationbox.h"

using namespace Math;
using namespace std;
Expand Down Expand Up @@ -34,7 +34,7 @@ void MedianFilter::edit()

connect(ui->kernelSize, qOverload<int>(&QSpinBox::valueChanged), [=](int newval) {
if((newval & 0x01) == 0) {
QMessageBox::information(d, "Median filter", "Only odd values are allowed for the kernel size");
InformationBox::ShowMessageBlocking("Median filter", "Only odd values are allowed for the kernel size");
newval++;
}
ui->kernelSize->setValue(newval);
Expand Down
4 changes: 1 addition & 3 deletions Software/PC_Application/VNA/Deembedding/portextension.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,10 @@ public slots:

// status variables for automatic measurements
Calkit *kit;
// bool measuring;
bool isPort1;
bool isOpen;
bool isIdeal;
// std::vector<Protocol::Datapoint> measurements;
QMessageBox *msgBox;

Ui::PortExtensionEditDialog *ui;
};

Expand Down
1 change: 0 additions & 1 deletion Software/PC_Application/VNA/Deembedding/twothru.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ private slots:
std::vector<Point> points;
bool measuring2xthru;
bool measuringDUT;
QMessageBox *msgBox;
Ui::TwoThruDialog *ui;
};

Expand Down
31 changes: 30 additions & 1 deletion Software/PC_Application/VNA/vna.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1062,7 +1062,7 @@ void VNA::ApplyCalibration(Calibration::Type type)
DisableCalibration(true);
}
} catch (runtime_error e) {
QMessageBox::critical(window, "Calibration failure", e.what());
InformationBox::ShowError("Calibration failure", e.what());
DisableCalibration(true);
}
} else {
Expand Down Expand Up @@ -1325,6 +1325,35 @@ void VNA::SetupSCPI()
scpi_cal->add(new SCPICommand("BUSy", nullptr, [=](QStringList) -> QString {
return CalibrationMeasurementActive() ? "TRUE" : "FALSE";
}));
scpi_cal->add(new SCPICommand("SAVE", [=](QStringList params) -> QString {
if(params.size() != 1 || !calValid) {
// no filename given or no calibration active
return "ERROR";
}
if(!cal.saveToFile(params[0])) {
// some error when writing the calibration file
return "ERROR";
}
calEdited = false;
return "";
}, nullptr));
scpi_cal->add(new SCPICommand("LOAD", nullptr, [=](QStringList params) -> QString {
if(params.size() != 1) {
// no filename given or no calibration active
return "FALSE";
}
if(!cal.openFromFile(params[0])) {
// some error when loading the calibration file
return "FALSE";
}
if(cal.getType() == Calibration::Type::None) {
DisableCalibration();
} else {
ApplyCalibration(cal.getType());
}
calEdited = false;
return "TRUE";
}));
}

void VNA::ConstrainAndUpdateFrequencies()
Expand Down
15 changes: 9 additions & 6 deletions Software/PC_Application/appwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include "Calibration/frequencycaldialog.h"
#include <QDebug>
#include "CustomWidgets/jsonpickerdialog.h"
#include "CustomWidgets/informationbox.h"
#include <QCommandLineParser>
#include "Util/app_common.h"
#include "about.h"
Expand Down Expand Up @@ -181,7 +182,7 @@ AppWindow::AppWindow(QWidget *parent)
try {
file >> j;
} catch (exception &e) {
QMessageBox::warning(nullptr, "Error", "Failed to parse the setup file (" + QString(e.what()) + ")");
InformationBox::ShowError("Error", "Failed to parse the setup file (" + QString(e.what()) + ")");
qWarning() << "Parsing of setup file failed: " << e.what();
}
file.close();
Expand Down Expand Up @@ -252,8 +253,11 @@ AppWindow::AppWindow(QWidget *parent)
ConnectToDevice();
}
if(!parser.isSet("no-gui")) {
InformationBox::setGUI(true);
resize(1280, 800);
show();
} else {
InformationBox::setGUI(false);
}
}

Expand Down Expand Up @@ -357,7 +361,7 @@ void AppWindow::DisconnectDevice()
void AppWindow::DeviceConnectionLost()
{
DisconnectDevice();
QMessageBox::warning(this, "Disconnected", "The USB connection to the device has been lost");
InformationBox::ShowError("Disconnected", "The USB connection to the device has been lost");
UpdateDeviceList();
}

Expand Down Expand Up @@ -885,12 +889,11 @@ void AppWindow::StartFirmwareUpdateDialog()

void AppWindow::DeviceNeedsUpdate(int reported, int expected)
{
auto ret = QMessageBox::warning(this, "Warning",
auto ret = InformationBox::AskQuestion("Warning",
"The device reports a different protocol"
"version (" + QString::number(reported) + ") than expected (" + QString::number(expected) + ").\n"
"A firmware update is strongly recommended. Do you want to update now?",
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
if (ret == QMessageBox::Yes) {
"A firmware update is strongly recommended. Do you want to update now?", false);
if (ret) {
StartFirmwareUpdateDialog();
}
}
Expand Down
2 changes: 1 addition & 1 deletion Software/PC_Application/preferences.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :

// Reset and OK action
connect(ui->buttonBox->button(QDialogButtonBox::RestoreDefaults), &QPushButton::clicked, [=](){
if(QMessageBox::question(this, "Restore defaults?", "Do you really want to set all preferences to their default values?") == QMessageBox::StandardButton::Yes) {
if(InformationBox::AskQuestion("Restore defaults?", "Do you really want to set all preferences to their default values?", true)) {
p->setDefault();
setInitialGUIState();
}
Expand Down

0 comments on commit 09366d7

Please sign in to comment.