Merge branch 'master' of github.com:jankae/LibreVNA
This commit is contained in:
commit
175cade3da
Binary file not shown.
@ -212,7 +212,9 @@ Some commands are both events and queries, depending on whether the question mar
|
||||
\section{Commands}
|
||||
\subsection{General Commands}
|
||||
\subsubsection{*IDN}
|
||||
\query{Returns the identifications string}{*IDN?}{None}{LibreVNA-GUI}
|
||||
\query{Returns the identifications string}{*IDN?}{None}{LibreVNA,LibreVNA-GUI,dummy\_serial,<software version>}
|
||||
\subsubsection{*OPC}
|
||||
\query{Returns a 1 after every previous command has been handled}{*OPC?}{None}{1}
|
||||
\subsubsection{*LST}
|
||||
\query{Lists all available commands}{*LST?}{None}{List of commands, separated by newline}
|
||||
\subsection{Device Commands}
|
||||
@ -249,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}{<filename>}
|
||||
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?}{<filename>}{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 <freq>}{<freq> in MHz, either 0 (disabled), 10 or 100}
|
||||
\query{Queries the reference output frequency}{DEVice:REFerence:OUT?}{None}{Output frequency in MHz}
|
||||
@ -561,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}
|
||||
|
||||
|
50
Documentation/UserManual/SCPI_Examples/deembedding_test.py
Normal file
50
Documentation/UserManual/SCPI_Examples/deembedding_test.py
Normal file
@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import time
|
||||
from libreVNA import libreVNA
|
||||
|
||||
# Create the control instance
|
||||
vna = libreVNA('localhost', 19542)
|
||||
|
||||
# Quick connection check (should print "LibreVNA-GUI")
|
||||
print(vna.query("*IDN?"))
|
||||
|
||||
vna.cmd(":VNA:DEEMB:CLEAR")
|
||||
vna.cmd(":VNA:DEEMB:NEW PORT_EXTENSION")
|
||||
vna.cmd(":VNA:DEEMB:NEW 2XTHRU")
|
||||
vna.cmd(":VNA:DEEMB:NEW MATCHING_NETWORK")
|
||||
vna.cmd(":VNA:DEEMB:NEW IMPEDANCE_RENORMALIZATION")
|
||||
|
||||
print("Number of total deembedding options:")
|
||||
num_options = int(vna.query(":VNA:DEEMB:NUM?"))
|
||||
print(num_options)
|
||||
|
||||
for i in range(1, num_options+1):
|
||||
option_name = vna.query(":VNA:DEEMB:TYPE? "+str(i))
|
||||
print("Option "+str(i)+": "+option_name)
|
||||
|
||||
# edit port extension
|
||||
vna.cmd(":VNA:DEEMB:1:PORT 2")
|
||||
vna.cmd(":VNA:DEEMB:1:DELAY 0.00002")
|
||||
vna.cmd(":VNA:DEEMB:1:DCLOSS 1")
|
||||
vna.cmd(":VNA:DEEMB:1:LOSS 3")
|
||||
vna.cmd(":VNA:DEEMB:1:FREQUENCY 5000000000")
|
||||
|
||||
vna.cmd(":VNA:DEEMB:3:PORT 3")
|
||||
vna.cmd(":VNA:DEEMB:3:CLEAR")
|
||||
vna.cmd(":VNA:DEEMB:3:ADD FALSE")
|
||||
vna.cmd(":VNA:DEEMB:3:NEW ParallelC")
|
||||
vna.cmd(":VNA:DEEMB:3:NEW SeriesR")
|
||||
vna.cmd(":VNA:DEEMB:3:NEW ParallelL")
|
||||
vna.cmd(":VNA:DEEMB:3:NEW SeriesL")
|
||||
vna.cmd(":VNA:DEEMB:3:NEW touchstone_shunt")
|
||||
|
||||
vna.cmd(":VNA:DEEMB:3:1:VALUE 0.0001")
|
||||
vna.cmd(":VNA:DEEMB:3:2:VALUE 0.00002")
|
||||
vna.cmd(":VNA:DEEMB:3:3:VALUE 0.000003")
|
||||
vna.cmd(":VNA:DEEMB:3:4:VALUE 0.000004")
|
||||
|
||||
vna.cmd(":VNA:DEEMB:3:5:FILE TEST.S2P")
|
||||
|
||||
vna.cmd(":VNA:DEEMB:4:IMPedance 75")
|
||||
|
@ -14,6 +14,7 @@ using USBID = struct {
|
||||
static constexpr USBID IDs[] = {
|
||||
{0x0483, 0x564e},
|
||||
{0x0483, 0x4121},
|
||||
{0x1209, 0x4121},
|
||||
};
|
||||
|
||||
USBInBuffer::USBInBuffer(libusb_device_handle *handle, unsigned char endpoint, int buffer_size) :
|
||||
|
@ -477,7 +477,10 @@ void AppWindow::CreateToolbars()
|
||||
void AppWindow::SetupSCPI()
|
||||
{
|
||||
scpi.add(new SCPICommand("*IDN", nullptr, [=](QStringList){
|
||||
return "LibreVNA-GUI";
|
||||
return "LibreVNA,LibreVNA-GUI,dummy_serial,"+appVersion;
|
||||
}));
|
||||
scpi.add(new SCPICommand("*OPC", nullptr, [=](QStringList){
|
||||
return "1";
|
||||
}));
|
||||
auto scpi_dev = new SCPINode("DEVice");
|
||||
scpi.add(scpi_dev);
|
||||
@ -518,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 {
|
||||
@ -1182,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 {
|
||||
@ -1197,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)
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -8,20 +8,23 @@
|
||||
|
||||
class SCPICommand {
|
||||
public:
|
||||
SCPICommand(QString name, std::function<QString(QStringList)> cmd, std::function<QString(QStringList)> query) :
|
||||
SCPICommand(QString name, std::function<QString(QStringList)> cmd, std::function<QString(QStringList)> 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<QString(QStringList)> fn_cmd;
|
||||
std::function<QString(QStringList)> fn_query;
|
||||
bool argAlwaysUppercase;
|
||||
};
|
||||
|
||||
class SCPINode {
|
||||
|
@ -63,10 +63,10 @@
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define USBD_VID 0x0483
|
||||
#define USBD_VID 0x1209
|
||||
#define USBD_PID_FS 0x4121
|
||||
#define USBD_LANGID_STRING 0x0409
|
||||
#define USBD_MANUFACTURER_STRING "STMicroelectronics"
|
||||
#define USBD_MANUFACTURER_STRING "LibreVNA"
|
||||
#define USBD_PRODUCT_STRING_FS "VNA"
|
||||
#define USBD_CONFIGURATION_STRING_FS "CustomUSBDevice Config"
|
||||
#define USBD_INTERFACE_STRING_FS "CustomUSBDevice Interface"
|
||||
|
Loading…
Reference in New Issue
Block a user