mirror of
https://github.com/jankae/LibreVNA.git
synced 2026-04-04 22:17:31 +00:00
Add temperature and manual control SCPI commands
This commit is contained in:
parent
f2b01f71c4
commit
e8482783f7
13 changed files with 785 additions and 357 deletions
|
|
@ -116,25 +116,33 @@ LibreVNADriver::LibreVNADriver()
|
|||
hardwareVersion = 0;
|
||||
protocolVersion = 0;
|
||||
setSynchronization(Synchronization::Disabled, false);
|
||||
manualControlDialog = nullptr;
|
||||
|
||||
auto manual = new QAction("Manual Control");
|
||||
connect(manual, &QAction::triggered, this, [=](){
|
||||
QDialog *d = nullptr;
|
||||
// Add driver specific actions
|
||||
|
||||
auto startManualControl = [=](){
|
||||
manualControlDialog = nullptr;
|
||||
switch(hardwareVersion) {
|
||||
case 1:
|
||||
d = new ManualControlDialogV1(*this);
|
||||
manualControlDialog = new ManualControlDialogV1(*this);
|
||||
break;
|
||||
case 0xFE:
|
||||
d = new ManualControlDialogVFE(*this);
|
||||
manualControlDialog = new ManualControlDialogVFE(*this);
|
||||
break;
|
||||
case 0xFF:
|
||||
d = new ManualControlDialogVFF(*this);
|
||||
manualControlDialog = new ManualControlDialogVFF(*this);
|
||||
break;
|
||||
}
|
||||
if(d) {
|
||||
d->show();
|
||||
if(manualControlDialog) {
|
||||
manualControlDialog->show();
|
||||
connect(manualControlDialog, &QDialog::finished, this, [=](){
|
||||
manualControlDialog = nullptr;
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
auto manual = new QAction("Manual Control");
|
||||
connect(manual, &QAction::triggered, this, startManualControl);
|
||||
specificActions.push_back(manual);
|
||||
|
||||
auto config = new QAction("Configuration");
|
||||
|
|
@ -199,6 +207,50 @@ LibreVNADriver::LibreVNADriver()
|
|||
d->show();
|
||||
});
|
||||
specificActions.push_back(log);
|
||||
|
||||
// Create driver specific commands
|
||||
specificSCPIcommands.push_back(new SCPICommand("DEVice:INFo:TEMPeratures", nullptr, [=](QStringList) -> QString {
|
||||
if(!connected) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
return QString::number(lastStatus.V1.temp_source)+"/"+QString::number(lastStatus.V1.temp_LO1)+"/"+QString::number(lastStatus.V1.temp_MCU);
|
||||
}));
|
||||
|
||||
specificSCPIcommands.push_back(new SCPICommand("DEVice:UPDATE", [=](QStringList params) -> QString {
|
||||
if(!connected) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
if(params.size() != 1) {
|
||||
// no file given
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
auto ret = updateFirmware(params[0]);
|
||||
if(!ret) {
|
||||
// update failed
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
} else {
|
||||
// update succeeded
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}
|
||||
}, nullptr, false));
|
||||
|
||||
specificSCPIcommands.push_back(new SCPICommand("MANual:STArt", [=](QStringList) -> QString {
|
||||
if(!manualControlDialog) {
|
||||
startManualControl();
|
||||
if(!manualControlDialog) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
}
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, nullptr));
|
||||
|
||||
specificSCPIcommands.push_back(new SCPICommand("MANual:STOp", [=](QStringList) -> QString {
|
||||
if(manualControlDialog) {
|
||||
delete manualControlDialog;
|
||||
manualControlDialog = nullptr;
|
||||
}
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, nullptr));
|
||||
}
|
||||
|
||||
std::set<DeviceDriver::Flag> LibreVNADriver::getFlags()
|
||||
|
|
|
|||
|
|
@ -222,6 +222,8 @@ protected:
|
|||
double SARBWLimitForDFT;
|
||||
bool VNASuppressInvalidPeaks;
|
||||
bool VNAAdjustPowerLevel;
|
||||
|
||||
QDialog *manualControlDialog;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(Protocol::PacketInfo)
|
||||
|
|
|
|||
|
|
@ -186,11 +186,204 @@ ManualControlDialogV1::ManualControlDialogV1(LibreVNADriver &dev, QWidget *paren
|
|||
connect(ui->Samples, qOverload<int>(&QSpinBox::valueChanged), [=](double) { UpdateDevice(); });
|
||||
connect(ui->cbWindow, qOverload<int>(&QComboBox::activated), [=](int) { UpdateDevice(); });
|
||||
|
||||
// Create the SCPI commands
|
||||
|
||||
auto addBooleanManualSetting = [=](QString cmd, void(ManualControlDialogV1::*set)(bool), bool(ManualControlDialogV1::*get)(void)) {
|
||||
commands.push_back(new SCPICommand(cmd, [=](QStringList params) -> QString {
|
||||
bool enable;
|
||||
if(!SCPI::paramToBool(params, 0, enable)) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
auto set_fn = std::bind(set, this, std::placeholders::_1);
|
||||
set_fn(enable);
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, [=](QStringList) -> QString {
|
||||
auto get_fn = std::bind(get, this);
|
||||
return get_fn() ? SCPI::getResultName(SCPI::Result::True) : SCPI::getResultName(SCPI::Result::False);
|
||||
}));
|
||||
};
|
||||
|
||||
auto addDoubleManualSetting = [=](QString cmd, void(ManualControlDialogV1::*set)(double), double(ManualControlDialogV1::*get)(void)) {
|
||||
commands.push_back(new SCPICommand(cmd, [=](QStringList params) -> QString {
|
||||
double value;
|
||||
if(!SCPI::paramToDouble(params, 0, value)) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
auto set_fn = std::bind(set, this, std::placeholders::_1);
|
||||
set_fn(value);
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, [=](QStringList) -> QString {
|
||||
auto get_fn = std::bind(get, this);
|
||||
return QString::number(get_fn());
|
||||
}));
|
||||
};
|
||||
auto addIntegerManualSetting = [=](QString cmd, void(ManualControlDialogV1::*set)(int), int(ManualControlDialogV1::*get)(void)) {
|
||||
commands.push_back(new SCPICommand(cmd, [=](QStringList params) -> QString {
|
||||
double value;
|
||||
if(!SCPI::paramToDouble(params, 0, value)) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
auto set_fn = std::bind(set, this, std::placeholders::_1);
|
||||
set_fn(value);
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, [=](QStringList) -> QString {
|
||||
auto get_fn = std::bind(get, this);
|
||||
return QString::number(get_fn());
|
||||
}));
|
||||
};
|
||||
auto addIntegerManualSettingWithReturnValue = [=](QString cmd, bool(ManualControlDialogV1::*set)(int), int(ManualControlDialogV1::*get)(void)) {
|
||||
commands.push_back(new SCPICommand(cmd, [=](QStringList params) -> QString {
|
||||
double value;
|
||||
if(!SCPI::paramToDouble(params, 0, value)) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
auto set_fn = std::bind(set, this, std::placeholders::_1);
|
||||
if(set_fn(value)) {
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
} else {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
}, [=](QStringList) -> QString {
|
||||
auto get_fn = std::bind(get, this);
|
||||
return QString::number(get_fn());
|
||||
}));
|
||||
};
|
||||
auto addIntegerManualQuery = [=](QString cmd, int(ManualControlDialogV1::*get)(void)) {
|
||||
commands.push_back(new SCPICommand(cmd, nullptr, [=](QStringList) -> QString {
|
||||
auto get_fn = std::bind(get, this);
|
||||
return QString::number(get_fn());
|
||||
}));
|
||||
};
|
||||
auto addDoubleManualQuery = [=](QString cmd, double(ManualControlDialogV1::*get)(void)) {
|
||||
commands.push_back(new SCPICommand(cmd, nullptr, [=](QStringList) -> QString {
|
||||
auto get_fn = std::bind(get, this);
|
||||
return QString::number(get_fn());
|
||||
}));
|
||||
};
|
||||
auto addBooleanManualQuery = [=](QString cmd, bool(ManualControlDialogV1::*get)(void)) {
|
||||
commands.push_back(new SCPICommand(cmd, nullptr, [=](QStringList) -> QString {
|
||||
auto get_fn = std::bind(get, this);
|
||||
return get_fn() ? SCPI::getResultName(SCPI::Result::True) : SCPI::getResultName(SCPI::Result::False);
|
||||
}));
|
||||
};
|
||||
auto addComplexManualQuery = [=](QString cmd, std::complex<double>(ManualControlDialogV1::*get)(void)) {
|
||||
commands.push_back(new SCPICommand(cmd, nullptr, [=](QStringList) -> QString {
|
||||
auto get_fn = std::bind(get, this);
|
||||
auto res = get_fn();
|
||||
return QString::number(res.real())+","+QString::number(res.imag());
|
||||
}));
|
||||
};
|
||||
|
||||
addBooleanManualSetting("MANual:HSRC_CE", &ManualControlDialogV1::setHighSourceChipEnable, &ManualControlDialogV1::getHighSourceChipEnable);
|
||||
addBooleanManualSetting("MANual:HSRC_RFEN", &ManualControlDialogV1::setHighSourceRFEnable, &ManualControlDialogV1::getHighSourceRFEnable);
|
||||
addBooleanManualQuery("MANual:HSRC_LOCKed", &ManualControlDialogV1::getHighSourceLocked);
|
||||
addIntegerManualSettingWithReturnValue("MANual:HSRC_PWR", &ManualControlDialogV1::setHighSourcePower, &ManualControlDialogV1::getHighSourcePower);
|
||||
addDoubleManualSetting("MANual:HSRC_FREQ", &ManualControlDialogV1::setHighSourceFrequency, &ManualControlDialogV1::getHighSourceFrequency);
|
||||
commands.push_back(new SCPICommand("MANual:HSRC_LPF", [=](QStringList params) -> QString {
|
||||
long value;
|
||||
if(!SCPI::paramToLong(params, 0, value)) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
switch(value) {
|
||||
case 947:
|
||||
setHighSourceLPF(ManualControlDialogV1::LPF::M947);
|
||||
break;
|
||||
case 1880:
|
||||
setHighSourceLPF(ManualControlDialogV1::LPF::M1880);
|
||||
break;
|
||||
case 3500:
|
||||
setHighSourceLPF(ManualControlDialogV1::LPF::M3500);
|
||||
break;
|
||||
case 0:
|
||||
setHighSourceLPF(ManualControlDialogV1::LPF::None);
|
||||
break;
|
||||
default:
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, [=](QStringList) -> QString {
|
||||
auto lpf = getHighSourceLPF();
|
||||
switch(lpf) {
|
||||
case ManualControlDialogV1::LPF::M947: return "947";
|
||||
case ManualControlDialogV1::LPF::M1880: return "1880";
|
||||
case ManualControlDialogV1::LPF::M3500: return "3500";
|
||||
case ManualControlDialogV1::LPF::None: return "0";
|
||||
default: return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
}));
|
||||
addBooleanManualSetting("MANual:LSRC_EN", &ManualControlDialogV1::setLowSourceEnable, &ManualControlDialogV1::getLowSourceEnable);
|
||||
addIntegerManualSettingWithReturnValue("MANual:LSRC_PWR", &ManualControlDialogV1::setLowSourcePower, &ManualControlDialogV1::getLowSourcePower);
|
||||
addDoubleManualSetting("MANual:LSRC_FREQ", &ManualControlDialogV1::setLowSourceFrequency, &ManualControlDialogV1::getLowSourceFrequency);
|
||||
addBooleanManualSetting("MANual:BAND_SW", &ManualControlDialogV1::setHighband, &ManualControlDialogV1::getHighband);
|
||||
addDoubleManualSetting("MANual:ATTenuator", &ManualControlDialogV1::setAttenuator, &ManualControlDialogV1::getAttenuator);
|
||||
addBooleanManualSetting("MANual:AMP_EN", &ManualControlDialogV1::setAmplifierEnable, &ManualControlDialogV1::getAmplifierEnable);
|
||||
addIntegerManualSettingWithReturnValue("MANual:PORT_SW", &ManualControlDialogV1::setPortSwitch, &ManualControlDialogV1::getPortSwitch);
|
||||
addBooleanManualSetting("MANual:LO1_CE", &ManualControlDialogV1::setLO1ChipEnable, &ManualControlDialogV1::getLO1ChipEnable);
|
||||
addBooleanManualSetting("MANual:LO1_RFEN", &ManualControlDialogV1::setLO1RFEnable, &ManualControlDialogV1::getLO1RFEnable);
|
||||
addBooleanManualQuery("MANual:LO1_LOCKed", &ManualControlDialogV1::getLO1Locked);
|
||||
addDoubleManualSetting("MANual:LO1_FREQ", &ManualControlDialogV1::setLO1Frequency, &ManualControlDialogV1::getLO1Frequency);
|
||||
addDoubleManualSetting("MANual:IF1_FREQ", &ManualControlDialogV1::setIF1Frequency, &ManualControlDialogV1::getIF1Frequency);
|
||||
addBooleanManualSetting("MANual:LO2_EN", &ManualControlDialogV1::setLO2Enable, &ManualControlDialogV1::getLO2Enable);
|
||||
addDoubleManualSetting("MANual:LO2_FREQ", &ManualControlDialogV1::setLO2Frequency, &ManualControlDialogV1::getLO2Frequency);
|
||||
addDoubleManualSetting("MANual:IF2_FREQ", &ManualControlDialogV1::setIF2Frequency, &ManualControlDialogV1::getIF2Frequency);
|
||||
addBooleanManualSetting("MANual:PORT1_EN", &ManualControlDialogV1::setPort1Enable, &ManualControlDialogV1::getPort1Enable);
|
||||
addBooleanManualSetting("MANual:PORT2_EN", &ManualControlDialogV1::setPort2Enable, &ManualControlDialogV1::getPort2Enable);
|
||||
addBooleanManualSetting("MANual:REF_EN", &ManualControlDialogV1::setRefEnable, &ManualControlDialogV1::getRefEnable);
|
||||
addIntegerManualSetting("MANual:SAMPLES", &ManualControlDialogV1::setNumSamples, &ManualControlDialogV1::getNumSamples);
|
||||
commands.push_back(new SCPICommand("MANual:WINdow", [=](QStringList params) -> QString {
|
||||
if(params.size() < 1) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
if (params[0] == "NONE") {
|
||||
setWindow(ManualControlDialogV1::Window::None);
|
||||
} else if(params[0] == "KAISER") {
|
||||
setWindow(ManualControlDialogV1::Window::Kaiser);
|
||||
} else if(params[0] == "HANN") {
|
||||
setWindow(ManualControlDialogV1::Window::Hann);
|
||||
} else if(params[0] == "FLATTOP") {
|
||||
setWindow(ManualControlDialogV1::Window::FlatTop);
|
||||
} else {
|
||||
return "INVALID WINDOW";
|
||||
}
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, [=](QStringList) -> QString {
|
||||
switch((ManualControlDialogV1::Window) getWindow()) {
|
||||
case ManualControlDialogV1::Window::None: return "NONE";
|
||||
case ManualControlDialogV1::Window::Kaiser: return "KAISER";
|
||||
case ManualControlDialogV1::Window::Hann: return "HANN";
|
||||
case ManualControlDialogV1::Window::FlatTop: return "FLATTOP";
|
||||
default: return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
}));
|
||||
addIntegerManualQuery("MANual:PORT1_MIN", &ManualControlDialogV1::getPort1MinADC);
|
||||
addIntegerManualQuery("MANual:PORT1_MAX", &ManualControlDialogV1::getPort1MaxADC);
|
||||
addDoubleManualQuery("MANual:PORT1_MAG", &ManualControlDialogV1::getPort1Magnitude);
|
||||
addDoubleManualQuery("MANual:PORT1_PHAse", &ManualControlDialogV1::getPort1Phase);
|
||||
addComplexManualQuery("MANual:PORT1_REFerenced", &ManualControlDialogV1::getPort1Referenced);
|
||||
|
||||
addIntegerManualQuery("MANual:PORT2_MIN", &ManualControlDialogV1::getPort2MinADC);
|
||||
addIntegerManualQuery("MANual:PORT2_MAX", &ManualControlDialogV1::getPort2MaxADC);
|
||||
addDoubleManualQuery("MANual:PORT2_MAG", &ManualControlDialogV1::getPort2Magnitude);
|
||||
addDoubleManualQuery("MANual:PORT2_PHAse", &ManualControlDialogV1::getPort2Phase);
|
||||
addComplexManualQuery("MANual:PORT2_REFerenced", &ManualControlDialogV1::getPort2Referenced);
|
||||
|
||||
addIntegerManualQuery("MANual:REF_MIN", &ManualControlDialogV1::getRefMinADC);
|
||||
addIntegerManualQuery("MANual:REF_MAX", &ManualControlDialogV1::getRefMaxADC);
|
||||
addDoubleManualQuery("MANual:REF_MAG", &ManualControlDialogV1::getRefMagnitude);
|
||||
addDoubleManualQuery("MANual:REF_PHAse", &ManualControlDialogV1::getRefPhase);
|
||||
|
||||
for(auto c : commands) {
|
||||
emit dev.addSCPICommand(c);
|
||||
}
|
||||
|
||||
UpdateDevice();
|
||||
}
|
||||
|
||||
ManualControlDialogV1::~ManualControlDialogV1()
|
||||
{
|
||||
for(auto c : commands) {
|
||||
emit dev.removeSCPICommand(c);
|
||||
}
|
||||
emit dev.releaseControl();
|
||||
delete ui;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,6 +111,8 @@ private:
|
|||
LibreVNADriver &dev;
|
||||
std::complex<double> port1referenced;
|
||||
std::complex<double> port2referenced;
|
||||
|
||||
std::vector<SCPICommand*> commands;
|
||||
};
|
||||
|
||||
#endif // MANUALCONTROLDIALOGV1_H
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<class>ManualControlDialogV1</class>
|
||||
<widget class="QDialog" name="ManualControlDialogV1">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::ApplicationModal</enum>
|
||||
<enum>Qt::WindowModality::ApplicationModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
|
|
@ -520,16 +520,16 @@
|
|||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="Samples">
|
||||
<property name="minimum">
|
||||
<number>128</number>
|
||||
<number>16</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>130944</number>
|
||||
<number>131072</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>128</number>
|
||||
<number>16</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>130944</number>
|
||||
<number>131072</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "Tools/parameters.h"
|
||||
#include "savable.h"
|
||||
#include "scpi.h"
|
||||
|
||||
#include <set>
|
||||
#include <complex>
|
||||
|
|
@ -231,6 +232,24 @@ public:
|
|||
*/
|
||||
std::vector<QAction*> driverSpecificActions() {return specificActions;}
|
||||
|
||||
/**
|
||||
* @brief Return driver specific SCPI commands
|
||||
*
|
||||
* The returned commands will be added to the :DEV SCPI node
|
||||
*
|
||||
* @return List of SCPI commands
|
||||
*/
|
||||
std::vector<SCPICommand*> driverSpecificSCPICommands() {return specificSCPIcommands;}
|
||||
|
||||
/**
|
||||
* @brief Return driver specific SCPI nodes
|
||||
*
|
||||
* The returned nodes (which may contain further nodes/commands) will be added to the :DEV SCPI node
|
||||
*
|
||||
* @return List of SCPI nodes
|
||||
*/
|
||||
std::vector<SCPINode*> driverSpecificSCPINodes() {return specificSCPInodes;}
|
||||
|
||||
class VNASettings {
|
||||
public:
|
||||
// Start/stop frequency. Both values will be identical for power sweeps and zero span
|
||||
|
|
@ -486,6 +505,41 @@ signals:
|
|||
*/
|
||||
void releaseControl();
|
||||
|
||||
/**
|
||||
* @brief Emit this to temporarily add a new SCPI command to the root node.
|
||||
*
|
||||
* Before deleting the command, removeSCPICommand must be emitted.
|
||||
* When the device is disconnected, all added commands will be automatically removed.
|
||||
*
|
||||
* @param cmd Command to add
|
||||
*/
|
||||
void addSCPICommand(SCPICommand *cmd);
|
||||
|
||||
/**
|
||||
* @brief Emit this to remove a temporarily added SCPI command.
|
||||
*
|
||||
* @param cmd Command to remove
|
||||
*/
|
||||
void removeSCPICommand(SCPICommand *cmd);
|
||||
|
||||
/**
|
||||
* @brief Emit this to temporarily add a new SCPI node to the root node.
|
||||
*
|
||||
* Before deleting the node, removeSCPINode must be emitted.
|
||||
* When the device is disconnected, all added nodes will be automatically removed.
|
||||
*
|
||||
* @param node Node to add
|
||||
*/
|
||||
void addSCPINode(SCPINode *node);
|
||||
|
||||
/**
|
||||
* @brief Emit this to remove a temporarily added SCPI node.
|
||||
*
|
||||
* @param node Node to remove
|
||||
*/
|
||||
void removeSCPINode(SCPINode *node);
|
||||
|
||||
|
||||
public:
|
||||
bool connectDevice(QString serial, bool isIndepedentDriver = false);
|
||||
void disconnectDevice();
|
||||
|
|
@ -494,9 +548,29 @@ public:
|
|||
static unsigned int SApoints();
|
||||
|
||||
protected:
|
||||
// Each driver implementation may add specific actionsm, settings or commands. All of these must
|
||||
// be created in the constructor and added to the following vectors:
|
||||
|
||||
// A list of actions specific to the driver. They will show up in the device menu
|
||||
std::vector<QAction*> specificActions;
|
||||
|
||||
// A list of settings specific to the driver. They will be stored/recalled as part of the preferences.
|
||||
// If a setting should be user-changeable in the preferences, createSettingsWidget() must include some
|
||||
// widget to modify that setting
|
||||
std::vector<Savable::SettingDescription> specificSettings;
|
||||
|
||||
// A list of SCPI commands. They will be available at the root node whenever the device driver is in use.
|
||||
// Avoid name collisions with commands/nodes already implemented in appwindow.cpp.
|
||||
// Use this for commands that will be available whenever the device is connected. For commands that are
|
||||
// not always available, use the addSCPICommand and removeSCPICommand signals.
|
||||
std::vector<SCPICommand*> specificSCPIcommands;
|
||||
|
||||
// A list of SCPI nodes. They will be available at the root node whenever the device driver is in use.
|
||||
// Avoid name collisions with commands/nodes already implemented in appwindow.cpp
|
||||
// Use this for nodes that will be available whenever the device is connected. For nodes that are
|
||||
// not always available, use the addSCPINode and removeSCPINode signals.
|
||||
std::vector<SCPINode*> specificSCPInodes;
|
||||
|
||||
private:
|
||||
static DeviceDriver *activeDriver;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -354,6 +354,28 @@ bool AppWindow::ConnectToDevice(QString serial, DeviceDriver *driver)
|
|||
lastActiveMode = modeHandler->getActiveMode();
|
||||
modeHandler->deactivate(lastActiveMode);
|
||||
});
|
||||
connect(d, &DeviceDriver::addSCPICommand, this, [=](SCPICommand *cmd){
|
||||
temporaryDeviceCommands.push_back(cmd);
|
||||
scpi.add(cmd);
|
||||
});
|
||||
connect(d, &DeviceDriver::removeSCPICommand, this, [=](SCPICommand *cmd){
|
||||
auto it = std::find(temporaryDeviceCommands.begin(), temporaryDeviceCommands.end(), cmd);
|
||||
if(it != temporaryDeviceCommands.end()) {
|
||||
temporaryDeviceCommands.erase(it);
|
||||
}
|
||||
scpi.remove(cmd);
|
||||
});
|
||||
connect(d, &DeviceDriver::addSCPINode, this, [=](SCPINode *node){
|
||||
temporaryDeviceNodes.push_back(node);
|
||||
scpi.add(node);
|
||||
});
|
||||
connect(d, &DeviceDriver::removeSCPINode, this, [=](SCPINode *node){
|
||||
auto it = std::find(temporaryDeviceNodes.begin(), temporaryDeviceNodes.end(), node);
|
||||
if(it != temporaryDeviceNodes.end()) {
|
||||
temporaryDeviceNodes.erase(it);
|
||||
}
|
||||
scpi.remove(node);
|
||||
});
|
||||
|
||||
if(d->connectDevice(serial)) {
|
||||
device = d;
|
||||
|
|
@ -386,15 +408,16 @@ bool AppWindow::ConnectToDevice(QString serial, DeviceDriver *driver)
|
|||
for(auto a : device->driverSpecificActions()) {
|
||||
ui->menuDevice->insertAction(before, a);
|
||||
}
|
||||
// if(!vdevice->isCompoundDevice()) {
|
||||
// ui->actionManual_Control->setEnabled(true);
|
||||
// ui->actionFirmware_Update->setEnabled(true);
|
||||
// ui->actionSource_Calibration->setEnabled(true);
|
||||
// ui->actionReceiver_Calibration->setEnabled(true);
|
||||
// ui->actionFrequency_Calibration->setEnabled(true);
|
||||
// }
|
||||
ui->actionPreset->setEnabled(true);
|
||||
|
||||
// Add SCPI nodes/commands
|
||||
for(auto n : device->driverSpecificSCPINodes()) {
|
||||
scpi.add(n);
|
||||
}
|
||||
for(auto c : device->driverSpecificSCPICommands()) {
|
||||
scpi.add(c);
|
||||
}
|
||||
|
||||
DeviceEntry e;
|
||||
e.serial = device->getSerial();
|
||||
e.driver = device;
|
||||
|
|
@ -407,12 +430,6 @@ bool AppWindow::ConnectToDevice(QString serial, DeviceDriver *driver)
|
|||
}
|
||||
}
|
||||
|
||||
// vdevice->initialize();
|
||||
|
||||
// UpdateAcquisitionFrequencies();
|
||||
// if (modeHandler->getActiveMode()) {
|
||||
// modeHandler->getActiveMode()->initializeDevice();
|
||||
// }
|
||||
return true;
|
||||
} catch (const runtime_error &e) {
|
||||
qWarning() << "Failed to connect:" << e.what();
|
||||
|
|
@ -425,9 +442,28 @@ bool AppWindow::ConnectToDevice(QString serial, DeviceDriver *driver)
|
|||
void AppWindow::DisconnectDevice()
|
||||
{
|
||||
if(device) {
|
||||
// remove menu entries
|
||||
for(auto a : device->driverSpecificActions()) {
|
||||
ui->menuDevice->removeAction(a);
|
||||
}
|
||||
// remove SCPI nodes/commands
|
||||
for(auto n : device->driverSpecificSCPINodes()) {
|
||||
scpi.remove(n);
|
||||
}
|
||||
for(auto c : device->driverSpecificSCPICommands()) {
|
||||
scpi.remove(c);
|
||||
}
|
||||
|
||||
// Remove all temporary SCPI nodes/commands
|
||||
for(auto n : temporaryDeviceNodes) {
|
||||
scpi.remove(n);
|
||||
}
|
||||
temporaryDeviceNodes.clear();
|
||||
for(auto c : temporaryDeviceCommands) {
|
||||
scpi.remove(c);
|
||||
}
|
||||
temporaryDeviceCommands.clear();
|
||||
|
||||
device->disconnectDevice();
|
||||
disconnect(device, nullptr, &deviceLog, nullptr);
|
||||
disconnect(device, nullptr, this, nullptr);
|
||||
|
|
@ -515,26 +551,6 @@ void AppWindow::SetupSCPI()
|
|||
return "Not connected";
|
||||
}
|
||||
}));
|
||||
scpi_dev->add(new SCPICommand("UPDATE", [=](QStringList params) -> QString {
|
||||
if(params.size() != 1) {
|
||||
// no file given
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
if(!device) {
|
||||
// not connected to any device
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
scpi.setOperationPending(true);
|
||||
auto ret = device->updateFirmware(params[0]);
|
||||
scpi.setOperationPending(false);
|
||||
if(!ret) {
|
||||
// update failed
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
} else {
|
||||
// update succeeded
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}
|
||||
}, nullptr, false));
|
||||
scpi_dev->add(new SCPICommand("LIST", nullptr, [=](QStringList) -> QString {
|
||||
QString ret;
|
||||
UpdateDeviceList();
|
||||
|
|
@ -728,32 +744,6 @@ void AppWindow::SetupSCPI()
|
|||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
}));
|
||||
// scpi_info->add(new SCPICommand("TEMPeratures", nullptr, [=](QStringList){
|
||||
// if(!vdevice) {
|
||||
// return QString("0/0/0");
|
||||
// } else if(vdevice->isCompoundDevice()) {
|
||||
// // show highest temperature of all devices
|
||||
// int maxTempSource = 0;
|
||||
// int maxTempLO = 0;
|
||||
// int maxTempMCU = 0;
|
||||
// for(auto dev : vdevice->getDevices()) {
|
||||
// auto status = dev->StatusV1();
|
||||
// if(status.temp_source > maxTempSource) {
|
||||
// maxTempSource = status.temp_source;
|
||||
// }
|
||||
// if(status.temp_LO1 > maxTempLO) {
|
||||
// maxTempLO = status.temp_LO1;
|
||||
// }
|
||||
// if(status.temp_MCU > maxTempMCU) {
|
||||
// maxTempMCU = status.temp_MCU;
|
||||
// }
|
||||
// }
|
||||
// return QString::number(maxTempSource)+"/"+QString::number(maxTempLO)+"/"+QString::number(maxTempMCU);
|
||||
// } else {
|
||||
// auto dev = vdevice->getDevice();
|
||||
// return QString::number(dev->StatusV1().temp_source)+"/"+QString::number(dev->StatusV1().temp_LO1)+"/"+QString::number(dev->StatusV1().temp_MCU);
|
||||
// }
|
||||
// }));
|
||||
auto scpi_limits = new SCPINode("LIMits");
|
||||
scpi_info->add(scpi_limits);
|
||||
scpi_limits->add(new SCPICommand("MINFrequency", nullptr, [=](QStringList){
|
||||
|
|
@ -786,234 +776,6 @@ void AppWindow::SetupSCPI()
|
|||
scpi_limits->add(new SCPICommand("MAXHARMonicfrequency", nullptr, [=](QStringList){
|
||||
return QString::number(DeviceDriver::getInfo(getDevice()).Limits.VNA.maxFreq);
|
||||
}));
|
||||
|
||||
// TODO
|
||||
// auto scpi_manual = new SCPINode("MANual");
|
||||
// scpi_manual->add(new SCPICommand("STArt",[=](QStringList) -> QString {
|
||||
//// StartManualControl();
|
||||
// return SCPI::getResultName(SCPI::Result::Empty);
|
||||
// }, nullptr));
|
||||
// scpi_manual->add(new SCPICommand("STOp",[=](QStringList) -> QString {
|
||||
// manual->close();
|
||||
// delete manual;
|
||||
// return SCPI::getResultName(SCPI::Result::Empty);
|
||||
// }, nullptr));
|
||||
//
|
||||
// auto addBooleanManualSetting = [=](QString cmd, void(ManualControlDialog::*set)(bool), bool(ManualControlDialog::*get)(void)) {
|
||||
// scpi_manual->add(new SCPICommand(cmd, [=](QStringList params) -> QString {
|
||||
// bool enable;
|
||||
// if(!manual || !SCPI::paramToBool(params, 0, enable)) {
|
||||
// return SCPI::getResultName(SCPI::Result::Error);
|
||||
// }
|
||||
// auto set_fn = std::bind(set, manual, std::placeholders::_1);
|
||||
// set_fn(enable);
|
||||
// return SCPI::getResultName(SCPI::Result::Empty);
|
||||
// }, [=](QStringList) -> QString {
|
||||
// if(!manual) {
|
||||
// return SCPI::getResultName(SCPI::Result::Error);
|
||||
// }
|
||||
// auto get_fn = std::bind(get, manual);
|
||||
// return get_fn() ? SCPI::getResultName(SCPI::Result::True) : SCPI::getResultName(SCPI::Result::False);
|
||||
// }));
|
||||
// };
|
||||
|
||||
// auto addDoubleManualSetting = [=](QString cmd, void(ManualControlDialog::*set)(double), double(ManualControlDialog::*get)(void)) {
|
||||
// scpi_manual->add(new SCPICommand(cmd, [=](QStringList params) -> QString {
|
||||
// double value;
|
||||
// if(!manual || !SCPI::paramToDouble(params, 0, value)) {
|
||||
// return SCPI::getResultName(SCPI::Result::Error);
|
||||
// }
|
||||
// auto set_fn = std::bind(set, manual, std::placeholders::_1);
|
||||
// set_fn(value);
|
||||
// return SCPI::getResultName(SCPI::Result::Empty);
|
||||
// }, [=](QStringList) -> QString {
|
||||
// if(!manual) {
|
||||
// return SCPI::getResultName(SCPI::Result::Error);
|
||||
// }
|
||||
// auto get_fn = std::bind(get, manual);
|
||||
// return QString::number(get_fn());
|
||||
// }));
|
||||
// };
|
||||
// auto addIntegerManualSetting = [=](QString cmd, void(ManualControlDialog::*set)(int), int(ManualControlDialog::*get)(void)) {
|
||||
// scpi_manual->add(new SCPICommand(cmd, [=](QStringList params) -> QString {
|
||||
// double value;
|
||||
// if(!manual || !SCPI::paramToDouble(params, 0, value)) {
|
||||
// return SCPI::getResultName(SCPI::Result::Error);
|
||||
// }
|
||||
// auto set_fn = std::bind(set, manual, std::placeholders::_1);
|
||||
// set_fn(value);
|
||||
// return SCPI::getResultName(SCPI::Result::Empty);
|
||||
// }, [=](QStringList) -> QString {
|
||||
// if(!manual) {
|
||||
// return SCPI::getResultName(SCPI::Result::Error);
|
||||
// }
|
||||
// auto get_fn = std::bind(get, manual);
|
||||
// return QString::number(get_fn());
|
||||
// }));
|
||||
// };
|
||||
// auto addIntegerManualSettingWithReturnValue = [=](QString cmd, bool(ManualControlDialog::*set)(int), int(ManualControlDialog::*get)(void)) {
|
||||
// scpi_manual->add(new SCPICommand(cmd, [=](QStringList params) -> QString {
|
||||
// double value;
|
||||
// if(!manual || !SCPI::paramToDouble(params, 0, value)) {
|
||||
// return SCPI::getResultName(SCPI::Result::Error);
|
||||
// }
|
||||
// auto set_fn = std::bind(set, manual, std::placeholders::_1);
|
||||
// if(set_fn(value)) {
|
||||
// return SCPI::getResultName(SCPI::Result::Empty);
|
||||
// } else {
|
||||
// return SCPI::getResultName(SCPI::Result::Error);
|
||||
// }
|
||||
// }, [=](QStringList) -> QString {
|
||||
// if(!manual) {
|
||||
// return SCPI::getResultName(SCPI::Result::Error);
|
||||
// }
|
||||
// auto get_fn = std::bind(get, manual);
|
||||
// return QString::number(get_fn());
|
||||
// }));
|
||||
// };
|
||||
// auto addIntegerManualQuery = [=](QString cmd, int(ManualControlDialog::*get)(void)) {
|
||||
// scpi_manual->add(new SCPICommand(cmd, nullptr, [=](QStringList) -> QString {
|
||||
// if(!manual) {
|
||||
// return SCPI::getResultName(SCPI::Result::Error);
|
||||
// }
|
||||
// auto get_fn = std::bind(get, manual);
|
||||
// return QString::number(get_fn());
|
||||
// }));
|
||||
// };
|
||||
// auto addDoubleManualQuery = [=](QString cmd, double(ManualControlDialog::*get)(void)) {
|
||||
// scpi_manual->add(new SCPICommand(cmd, nullptr, [=](QStringList) -> QString {
|
||||
// if(!manual) {
|
||||
// return SCPI::getResultName(SCPI::Result::Error);
|
||||
// }
|
||||
// auto get_fn = std::bind(get, manual);
|
||||
// return QString::number(get_fn());
|
||||
// }));
|
||||
// };
|
||||
// auto addBooleanManualQuery = [=](QString cmd, bool(ManualControlDialog::*get)(void)) {
|
||||
// scpi_manual->add(new SCPICommand(cmd, nullptr, [=](QStringList) -> QString {
|
||||
// if(!manual) {
|
||||
// return SCPI::getResultName(SCPI::Result::Error);
|
||||
// }
|
||||
// auto get_fn = std::bind(get, manual);
|
||||
// return get_fn() ? SCPI::getResultName(SCPI::Result::True) : SCPI::getResultName(SCPI::Result::False);
|
||||
// }));
|
||||
// };
|
||||
// auto addComplexManualQuery = [=](QString cmd, std::complex<double>(ManualControlDialog::*get)(void)) {
|
||||
// scpi_manual->add(new SCPICommand(cmd, nullptr, [=](QStringList) -> QString {
|
||||
// if(!manual) {
|
||||
// return SCPI::getResultName(SCPI::Result::Error);
|
||||
// }
|
||||
// auto get_fn = std::bind(get, manual);
|
||||
// auto res = get_fn();
|
||||
// return QString::number(res.real())+","+QString::number(res.imag());
|
||||
// }));
|
||||
// };
|
||||
|
||||
// addBooleanManualSetting("HSRC_CE", &ManualControlDialog::setHighSourceChipEnable, &ManualControlDialog::getHighSourceChipEnable);
|
||||
// addBooleanManualSetting("HSRC_RFEN", &ManualControlDialog::setHighSourceRFEnable, &ManualControlDialog::getHighSourceRFEnable);
|
||||
// addBooleanManualQuery("HSRC_LOCKed", &ManualControlDialog::getHighSourceLocked);
|
||||
// addIntegerManualSettingWithReturnValue("HSRC_PWR", &ManualControlDialog::setHighSourcePower, &ManualControlDialog::getHighSourcePower);
|
||||
// addDoubleManualSetting("HSRC_FREQ", &ManualControlDialog::setHighSourceFrequency, &ManualControlDialog::getHighSourceFrequency);
|
||||
// scpi_manual->add(new SCPICommand("HSRC_LPF", [=](QStringList params) -> QString {
|
||||
// long value;
|
||||
// if(!manual || !SCPI::paramToLong(params, 0, value)) {
|
||||
// return SCPI::getResultName(SCPI::Result::Error);
|
||||
// }
|
||||
// switch(value) {
|
||||
// case 947:
|
||||
// manual->setHighSourceLPF(ManualControlDialog::LPF::M947);
|
||||
// break;
|
||||
// case 1880:
|
||||
// manual->setHighSourceLPF(ManualControlDialog::LPF::M1880);
|
||||
// break;
|
||||
// case 3500:
|
||||
// manual->setHighSourceLPF(ManualControlDialog::LPF::M3500);
|
||||
// break;
|
||||
// case 0:
|
||||
// manual->setHighSourceLPF(ManualControlDialog::LPF::None);
|
||||
// break;
|
||||
// default:
|
||||
// return SCPI::getResultName(SCPI::Result::Error);
|
||||
// }
|
||||
// return SCPI::getResultName(SCPI::Result::Empty);
|
||||
// }, [=](QStringList) -> QString {
|
||||
// if(!manual) {
|
||||
// return SCPI::getResultName(SCPI::Result::Error);
|
||||
// }
|
||||
// auto lpf = manual->getHighSourceLPF();
|
||||
// switch(lpf) {
|
||||
// case ManualControlDialog::LPF::M947: return "947";
|
||||
// case ManualControlDialog::LPF::M1880: return "1880";
|
||||
// case ManualControlDialog::LPF::M3500: return "3500";
|
||||
// case ManualControlDialog::LPF::None: return "0";
|
||||
// default: return SCPI::getResultName(SCPI::Result::Error);
|
||||
// }
|
||||
// }));
|
||||
// addBooleanManualSetting("LSRC_EN", &ManualControlDialog::setLowSourceEnable, &ManualControlDialog::getLowSourceEnable);
|
||||
// addIntegerManualSettingWithReturnValue("LSRC_PWR", &ManualControlDialog::setLowSourcePower, &ManualControlDialog::getLowSourcePower);
|
||||
// addDoubleManualSetting("LSRC_FREQ", &ManualControlDialog::setLowSourceFrequency, &ManualControlDialog::getLowSourceFrequency);
|
||||
// addBooleanManualSetting("BAND_SW", &ManualControlDialog::setHighband, &ManualControlDialog::getHighband);
|
||||
// addDoubleManualSetting("ATTenuator", &ManualControlDialog::setAttenuator, &ManualControlDialog::getAttenuator);
|
||||
// addBooleanManualSetting("AMP_EN", &ManualControlDialog::setAmplifierEnable, &ManualControlDialog::getAmplifierEnable);
|
||||
// addIntegerManualSettingWithReturnValue("PORT_SW", &ManualControlDialog::setPortSwitch, &ManualControlDialog::getPortSwitch);
|
||||
// addBooleanManualSetting("LO1_CE", &ManualControlDialog::setLO1ChipEnable, &ManualControlDialog::getLO1ChipEnable);
|
||||
// addBooleanManualSetting("LO1_RFEN", &ManualControlDialog::setLO1RFEnable, &ManualControlDialog::getLO1RFEnable);
|
||||
// addBooleanManualQuery("LO1_LOCKed", &ManualControlDialog::getLO1Locked);
|
||||
// addDoubleManualSetting("LO1_FREQ", &ManualControlDialog::setLO1Frequency, &ManualControlDialog::getLO1Frequency);
|
||||
// addDoubleManualSetting("IF1_FREQ", &ManualControlDialog::setIF1Frequency, &ManualControlDialog::getIF1Frequency);
|
||||
// addBooleanManualSetting("LO2_EN", &ManualControlDialog::setLO2Enable, &ManualControlDialog::getLO2Enable);
|
||||
// addDoubleManualSetting("LO2_FREQ", &ManualControlDialog::setLO2Frequency, &ManualControlDialog::getLO2Frequency);
|
||||
// addDoubleManualSetting("IF2_FREQ", &ManualControlDialog::setIF2Frequency, &ManualControlDialog::getIF2Frequency);
|
||||
// addBooleanManualSetting("PORT1_EN", &ManualControlDialog::setPort1Enable, &ManualControlDialog::getPort1Enable);
|
||||
// addBooleanManualSetting("PORT2_EN", &ManualControlDialog::setPort2Enable, &ManualControlDialog::getPort2Enable);
|
||||
// addBooleanManualSetting("REF_EN", &ManualControlDialog::setRefEnable, &ManualControlDialog::getRefEnable);
|
||||
// addIntegerManualSetting("SAMPLES", &ManualControlDialog::setNumSamples, &ManualControlDialog::getNumSamples);
|
||||
// scpi_manual->add(new SCPICommand("WINdow", [=](QStringList params) -> QString {
|
||||
// if(!manual || params.size() < 1) {
|
||||
// return SCPI::getResultName(SCPI::Result::Error);
|
||||
// }
|
||||
// if (params[0] == "NONE") {
|
||||
// manual->setWindow(ManualControlDialog::Window::None);
|
||||
// } else if(params[0] == "KAISER") {
|
||||
// manual->setWindow(ManualControlDialog::Window::Kaiser);
|
||||
// } else if(params[0] == "HANN") {
|
||||
// manual->setWindow(ManualControlDialog::Window::Hann);
|
||||
// } else if(params[0] == "FLATTOP") {
|
||||
// manual->setWindow(ManualControlDialog::Window::FlatTop);
|
||||
// } else {
|
||||
// return "INVALID WINDOW";
|
||||
// }
|
||||
// return SCPI::getResultName(SCPI::Result::Empty);
|
||||
// }, [=](QStringList) -> QString {
|
||||
// if(!manual) {
|
||||
// return SCPI::getResultName(SCPI::Result::Error);
|
||||
// }
|
||||
// switch((ManualControlDialog::Window) manual->getWindow()) {
|
||||
// case ManualControlDialog::Window::None: return "NONE";
|
||||
// case ManualControlDialog::Window::Kaiser: return "KAISER";
|
||||
// case ManualControlDialog::Window::Hann: return "HANN";
|
||||
// case ManualControlDialog::Window::FlatTop: return "FLATTOP";
|
||||
// default: return SCPI::getResultName(SCPI::Result::Error);
|
||||
// }
|
||||
// }));
|
||||
// addIntegerManualQuery("PORT1_MIN", &ManualControlDialog::getPort1MinADC);
|
||||
// addIntegerManualQuery("PORT1_MAX", &ManualControlDialog::getPort1MaxADC);
|
||||
// addDoubleManualQuery("PORT1_MAG", &ManualControlDialog::getPort1Magnitude);
|
||||
// addDoubleManualQuery("PORT1_PHAse", &ManualControlDialog::getPort1Phase);
|
||||
// addComplexManualQuery("PORT1_REFerenced", &ManualControlDialog::getPort1Referenced);
|
||||
|
||||
// addIntegerManualQuery("PORT2_MIN", &ManualControlDialog::getPort2MinADC);
|
||||
// addIntegerManualQuery("PORT2_MAX", &ManualControlDialog::getPort2MaxADC);
|
||||
// addDoubleManualQuery("PORT2_MAG", &ManualControlDialog::getPort2Magnitude);
|
||||
// addDoubleManualQuery("PORT2_PHAse", &ManualControlDialog::getPort2Phase);
|
||||
// addComplexManualQuery("PORT2_REFerenced", &ManualControlDialog::getPort2Referenced);
|
||||
|
||||
// addIntegerManualQuery("REF_MIN", &ManualControlDialog::getRefMinADC);
|
||||
// addIntegerManualQuery("REF_MAX", &ManualControlDialog::getRefMaxADC);
|
||||
// addDoubleManualQuery("REF_MAG", &ManualControlDialog::getRefMagnitude);
|
||||
// addDoubleManualQuery("REF_PHAse", &ManualControlDialog::getRefPhase);
|
||||
|
||||
// scpi.add(scpi_manual);
|
||||
}
|
||||
|
||||
void AppWindow::StartTCPServer(int port)
|
||||
|
|
|
|||
|
|
@ -159,6 +159,8 @@ private:
|
|||
QCommandLineParser parser;
|
||||
|
||||
SCPI scpi;
|
||||
std::vector<SCPICommand*> temporaryDeviceCommands;
|
||||
std::vector<SCPINode*> temporaryDeviceNodes;
|
||||
TCPServer *server;
|
||||
StreamingServer *streamVNARawData;
|
||||
StreamingServer *streamVNACalibratedData;
|
||||
|
|
|
|||
|
|
@ -285,39 +285,6 @@ SCPINode::~SCPINode()
|
|||
}
|
||||
}
|
||||
|
||||
bool SCPINode::add(SCPINode *node)
|
||||
{
|
||||
if(nameCollision(node->name)) {
|
||||
qWarning() << "Unable to add SCPI node, name collision: " << node->name;
|
||||
return false;
|
||||
}
|
||||
subnodes.push_back(node);
|
||||
node->parent = this;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SCPINode::remove(SCPINode *node)
|
||||
{
|
||||
auto it = std::find(subnodes.begin(), subnodes.end(), node);
|
||||
if(it != subnodes.end()) {
|
||||
subnodes.erase(it);
|
||||
node->parent = nullptr;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SCPINode::add(SCPICommand *cmd)
|
||||
{
|
||||
if(nameCollision(cmd->name())) {
|
||||
qWarning() << "Unable to add SCPI command, name collision: " << cmd->name();
|
||||
return false;
|
||||
}
|
||||
commands.push_back(cmd);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SCPINode::addDoubleParameter(QString name, double ¶m, bool gettable, bool settable, std::function<void(void)> setCallback)
|
||||
{
|
||||
auto cmd = settable ? [¶m, setCallback](QStringList params) -> QString {
|
||||
|
|
@ -441,14 +408,118 @@ void SCPINode::createCommandList(QString prefix, QString &list)
|
|||
{
|
||||
for(auto c : commands) {
|
||||
if(c->queryable()) {
|
||||
list += prefix + c->name() + "?\n";
|
||||
list += prefix + c->leafName() + "?\n";
|
||||
}
|
||||
if(c->executable()) {
|
||||
list += prefix + c->name() + '\n';
|
||||
list += prefix + c->leafName() + '\n';
|
||||
}
|
||||
}
|
||||
for(auto n : subnodes) {
|
||||
n->createCommandList(prefix + n->name + ":", list);
|
||||
n->createCommandList(prefix + n->leafName() + ":", list);
|
||||
}
|
||||
}
|
||||
|
||||
SCPINode *SCPINode::findSubnode(QString name)
|
||||
{
|
||||
for(auto n : subnodes) {
|
||||
if(n->name == name) {
|
||||
return n;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool SCPINode::addInternal(SCPINode *node, int depth)
|
||||
{
|
||||
QStringList parts = node->name.split(":");
|
||||
if(depth == parts.size()-1) {
|
||||
// add to this node
|
||||
if(nameCollision(parts[depth])) {
|
||||
qWarning() << "Unable to add SCPI node, name collision: " << node->name;
|
||||
return false;
|
||||
}
|
||||
subnodes.push_back(node);
|
||||
node->parent = this;
|
||||
return true;
|
||||
} else {
|
||||
// add to subnode
|
||||
auto subNode = findSubnode(parts[depth]);
|
||||
if(!subNode) {
|
||||
// does not exist, create first
|
||||
subNode = new SCPINode(parts[depth]);
|
||||
add(subNode);
|
||||
}
|
||||
return subNode->addInternal(node, depth+1);
|
||||
}
|
||||
}
|
||||
|
||||
bool SCPINode::removeInternal(SCPINode *node, int depth)
|
||||
{
|
||||
QStringList parts = node->name.split(":");
|
||||
if(depth == parts.size()-1) {
|
||||
// remove from this node
|
||||
auto it = std::find(subnodes.begin(), subnodes.end(), node);
|
||||
if(it != subnodes.end()) {
|
||||
subnodes.erase(it);
|
||||
node->parent = nullptr;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// remove from subnode
|
||||
auto subNode = findSubnode(parts[depth]);
|
||||
if(!subNode) {
|
||||
// does not exist
|
||||
return false;
|
||||
}
|
||||
return subNode->removeInternal(node, depth+1);
|
||||
}
|
||||
}
|
||||
|
||||
bool SCPINode::addInternal(SCPICommand *cmd, int depth)
|
||||
{
|
||||
QStringList parts = cmd->name().split(":");
|
||||
if(depth == parts.size()-1) {
|
||||
// add to this node
|
||||
if(nameCollision(parts[depth])) {
|
||||
qWarning() << "Unable to add SCPI command, name collision: " << cmd->name();
|
||||
return false;
|
||||
}
|
||||
commands.push_back(cmd);
|
||||
return true;
|
||||
} else {
|
||||
// add to subnode
|
||||
auto subNode = findSubnode(parts[depth]);
|
||||
if(!subNode) {
|
||||
// does not exist, create first
|
||||
subNode = new SCPINode(parts[depth]);
|
||||
add(subNode);
|
||||
}
|
||||
return subNode->addInternal(cmd, depth+1);
|
||||
}
|
||||
}
|
||||
|
||||
bool SCPINode::removeInternal(SCPICommand *cmd, int depth)
|
||||
{
|
||||
QStringList parts = cmd->name().split(":");
|
||||
if(depth == parts.size()-1) {
|
||||
// remove from this node
|
||||
auto it = std::find(commands.begin(), commands.end(), cmd);
|
||||
if(it != commands.end()) {
|
||||
commands.erase(it);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// remove from subnode
|
||||
auto subNode = findSubnode(parts[depth]);
|
||||
if(!subNode) {
|
||||
// does not exist
|
||||
return false;
|
||||
}
|
||||
return subNode->removeInternal(cmd, depth+1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -463,7 +534,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.toUpper())) {
|
||||
if(SCPI::match(n->leafName(), subnode.toUpper())) {
|
||||
// pass on to next level
|
||||
return n->parse(cmd.right(cmd.size() - splitPos - 1), lastNode);
|
||||
}
|
||||
|
|
@ -481,7 +552,7 @@ QString SCPINode::parse(QString cmd, SCPINode* &lastNode)
|
|||
cmd.chop(1);
|
||||
}
|
||||
for(auto c : commands) {
|
||||
if(SCPI::match(c->name(), cmd.toUpper())) {
|
||||
if(SCPI::match(c->leafName(), cmd.toUpper())) {
|
||||
// save current node in case of non-root for the next command
|
||||
lastNode = this;
|
||||
if(c->convertToUppercase()) {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ public:
|
|||
bool queryable() { return fn_query != nullptr;}
|
||||
bool executable() { return fn_cmd != nullptr;}
|
||||
bool convertToUppercase() { return argAlwaysUppercase;}
|
||||
QString leafName() {return _name.split(":").back();}
|
||||
private:
|
||||
const QString _name;
|
||||
std::function<QString(QStringList)> fn_cmd;
|
||||
|
|
@ -35,15 +36,17 @@ public:
|
|||
name(name), parent(nullptr), operationPending(false){}
|
||||
virtual ~SCPINode();
|
||||
|
||||
bool add(SCPINode *node);
|
||||
bool remove(SCPINode *node);
|
||||
bool add(SCPICommand *cmd);
|
||||
bool add(SCPINode *node) {return addInternal(node, 0);}
|
||||
bool remove(SCPINode *node) {return removeInternal(node, 0);}
|
||||
bool add(SCPICommand *cmd) {return addInternal(cmd, 0);}
|
||||
bool remove(SCPICommand *cmd) {return removeInternal(cmd, 0);}
|
||||
|
||||
bool addDoubleParameter(QString name, double ¶m, bool gettable = true, bool settable = true, std::function<void(void)> setCallback = nullptr);
|
||||
bool addUnsignedIntParameter(QString name, unsigned int ¶m, bool gettable = true, bool settable = true, std::function<void(void)> setCallback = nullptr);
|
||||
bool addBoolParameter(QString name, bool ¶m, bool gettable = true, bool settable = true, std::function<void(void)> setCallback = nullptr);
|
||||
|
||||
bool changeName(QString newname);
|
||||
QString leafName() {return name.split(":").back();}
|
||||
|
||||
void setOperationPending(bool pending);
|
||||
|
||||
|
|
@ -54,6 +57,11 @@ private:
|
|||
QString parse(QString cmd, SCPINode* &lastNode);
|
||||
bool nameCollision(QString name);
|
||||
void createCommandList(QString prefix, QString &list);
|
||||
SCPINode *findSubnode(QString name);
|
||||
bool addInternal(SCPINode *node, int depth);
|
||||
bool removeInternal(SCPINode *node, int depth);
|
||||
bool addInternal(SCPICommand *cmd, int depth);
|
||||
bool removeInternal(SCPICommand *cmd, int depth);
|
||||
QString name;
|
||||
std::vector<SCPINode*> subnodes;
|
||||
std::vector<SCPICommand*> commands;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue