diff --git a/Documentation/UserManual/ProgrammingGuide.pdf b/Documentation/UserManual/ProgrammingGuide.pdf index f7e7546..97b6444 100644 Binary files a/Documentation/UserManual/ProgrammingGuide.pdf and b/Documentation/UserManual/ProgrammingGuide.pdf differ diff --git a/Documentation/UserManual/ProgrammingGuide.tex b/Documentation/UserManual/ProgrammingGuide.tex index ded2d15..3f4b66b 100644 --- a/Documentation/UserManual/ProgrammingGuide.tex +++ b/Documentation/UserManual/ProgrammingGuide.tex @@ -251,6 +251,22 @@ This section contains general device commands, available regardless of the curre VNA \end{example} +\subsubsection{DEVice:SETUP:SAVE} +\event{Saves the GUI setup to a file}{DEVice:SETUP:SAVE}{} +Important points when saving/loading setup files through SCPI commands: +\begin{itemize} +\item Filenames must be either absolute or relative to the location of the GUI application. +\item If the LibreVNA-GUI (and thus also the SCPI server) is running on a different machine than the SCPI client, the setup files will be saved/loaded from the machine that runs the GUI. +\item If no (or a wrong) file ending is specified, ``.setup'' is automatically added to the filename. +\end{itemize} + +\subsubsection{DEVice:SETUP:LOAD} +\query{Loads a setup file}{DEVice:SETUP:LOAD?}{}{TRUE or FALSE} +\begin{itemize} +\item Filenames must be either absolute or relative to the location of the GUI application. +\item The filename must include the file ending ``.setup''. +\end{itemize} + \subsubsection{DEVice:REFerence:OUT} \event{Sets the reference output frequency}{DEVice:REFerence:OUT }{ in MHz, either 0 (disabled), 10 or 100} \query{Queries the reference output frequency}{DEVice:REFerence:OUT?}{None}{Output frequency in MHz} @@ -563,7 +579,6 @@ Any number of measurements can be specified (by their number). These measurement 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} diff --git a/Software/PC_Application/LibreVNA-GUI/appwindow.cpp b/Software/PC_Application/LibreVNA-GUI/appwindow.cpp index 946b722..720ceef 100644 --- a/Software/PC_Application/LibreVNA-GUI/appwindow.cpp +++ b/Software/PC_Application/LibreVNA-GUI/appwindow.cpp @@ -521,6 +521,27 @@ void AppWindow::SetupSCPI() ret.chop(1); return ret; })); + auto scpi_setup = new SCPINode("SETUP"); + scpi_dev->add(scpi_setup); + scpi_setup->add(new SCPICommand("SAVE", [=](QStringList params) -> QString { + if(params.size() != 1) { + // no filename given + return SCPI::getResultName(SCPI::Result::Error); + } + SaveSetup(params[0]); + return SCPI::getResultName(SCPI::Result::Empty); + }, nullptr, false)); + scpi_setup->add(new SCPICommand("LOAD", nullptr, [=](QStringList params) -> QString { + if(params.size() != 1) { + // no filename given + return SCPI::getResultName(SCPI::Result::False); + } + if(!LoadSetup(params[0])) { + // some error when loading the setup file + return SCPI::getResultName(SCPI::Result::False); + } + return SCPI::getResultName(SCPI::Result::True); + }, false)); auto scpi_ref = new SCPINode("REFerence"); scpi_dev->add(scpi_ref); scpi_ref->add(new SCPICommand("OUT", [=](QStringList params) -> QString { @@ -1185,13 +1206,13 @@ nlohmann::json AppWindow::SaveSetup() return j; } -void AppWindow::LoadSetup(QString filename) +bool AppWindow::LoadSetup(QString filename) { ifstream file; file.open(filename.toStdString()); if(!file.is_open()) { qWarning() << "Unable to open file:" << filename; - return; + return false; } nlohmann::json j; try { @@ -1200,12 +1221,13 @@ void AppWindow::LoadSetup(QString filename) InformationBox::ShowError("Error", "Failed to parse the setup file (" + QString(e.what()) + ")"); qWarning() << "Parsing of setup file failed: " << e.what(); file.close(); - return; + return false; } file.close(); LoadSetup(j); QFileInfo fi(filename); lSetupName.setText("Setup: "+fi.fileName()); + return true; } void AppWindow::LoadSetup(nlohmann::json j) diff --git a/Software/PC_Application/LibreVNA-GUI/appwindow.h b/Software/PC_Application/LibreVNA-GUI/appwindow.h index 1db476a..e47376e 100644 --- a/Software/PC_Application/LibreVNA-GUI/appwindow.h +++ b/Software/PC_Application/LibreVNA-GUI/appwindow.h @@ -68,7 +68,7 @@ private slots: void DeviceFlagsUpdated(); void DeviceInfoUpdated(); void SaveSetup(QString filename); - void LoadSetup(QString filename); + bool LoadSetup(QString filename); private: nlohmann::json SaveSetup(); void LoadSetup(nlohmann::json j); diff --git a/Software/PC_Application/LibreVNA-GUI/scpi.cpp b/Software/PC_Application/LibreVNA-GUI/scpi.cpp index cc78f69..4684033 100644 --- a/Software/PC_Application/LibreVNA-GUI/scpi.cpp +++ b/Software/PC_Application/LibreVNA-GUI/scpi.cpp @@ -105,7 +105,6 @@ void SCPI::input(QString line) if(cmd[0] == ':') { cmd.remove(0, 1); } - cmd = cmd.toUpper(); auto response = lastNode->parse(cmd, lastNode); emit output(response); } @@ -274,7 +273,7 @@ QString SCPINode::parse(QString cmd, SCPINode* &lastNode) // have not reached a leaf, find next subnode auto subnode = cmd.left(splitPos); for(auto n : subnodes) { - if(SCPI::match(n->name, subnode)) { + if(SCPI::match(n->name, subnode.toUpper())) { // pass on to next level return n->parse(cmd.right(cmd.size() - splitPos - 1), lastNode); } @@ -292,9 +291,14 @@ QString SCPINode::parse(QString cmd, SCPINode* &lastNode) cmd.chop(1); } for(auto c : commands) { - if(SCPI::match(c->name(), cmd)) { + if(SCPI::match(c->name(), cmd.toUpper())) { // save current node in case of non-root for the next command lastNode = this; + if(c->convertToUppercase()) { + for(auto &p : params) { + p = p.toUpper(); + } + } if(isQuery) { return c->query(params); } else { diff --git a/Software/PC_Application/LibreVNA-GUI/scpi.h b/Software/PC_Application/LibreVNA-GUI/scpi.h index 8a7f37d..f56f92e 100644 --- a/Software/PC_Application/LibreVNA-GUI/scpi.h +++ b/Software/PC_Application/LibreVNA-GUI/scpi.h @@ -8,20 +8,23 @@ class SCPICommand { public: - SCPICommand(QString name, std::function cmd, std::function query) : + SCPICommand(QString name, std::function cmd, std::function query, bool convertToUppercase = true) : _name(name), fn_cmd(cmd), - fn_query(query){} + fn_query(query), + argAlwaysUppercase(convertToUppercase){} QString execute(QStringList params); QString query(QStringList params); QString name() {return _name;} bool queryable() { return fn_query != nullptr;} bool executable() { return fn_cmd != nullptr;} + bool convertToUppercase() { return argAlwaysUppercase;} private: const QString _name; std::function fn_cmd; std::function fn_query; + bool argAlwaysUppercase; }; class SCPINode {