LibreVNA/Software/PC_Application/LibreVNA-GUI/scpi.h

140 lines
4.2 KiB
C
Raw Normal View History

2022-10-01 17:10:44 +02:00
#ifndef SCPI_H
#define SCPI_H
#include <QString>
#include <QObject>
2024-12-02 14:02:34 +01:00
#include <QSemaphore>
2022-10-01 17:10:44 +02:00
#include <vector>
#include <functional>
class SCPICommand {
public:
SCPICommand(QString name, std::function<QString(QStringList)> cmd, std::function<QString(QStringList)> query, bool convertToUppercase = true) :
2022-10-01 17:10:44 +02:00
_name(name),
fn_cmd(cmd),
fn_query(query),
argAlwaysUppercase(convertToUppercase){}
2022-10-01 17:10:44 +02:00
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;}
QString leafName() {return _name.split(":").back();}
2022-10-01 17:10:44 +02:00
private:
const QString _name;
std::function<QString(QStringList)> fn_cmd;
std::function<QString(QStringList)> fn_query;
bool argAlwaysUppercase;
2022-10-01 17:10:44 +02:00
};
class SCPINode {
friend class SCPI;
public:
SCPINode(QString name) :
2024-04-07 14:11:04 +02:00
name(name), parent(nullptr), operationPending(false){}
2022-12-15 00:00:15 +01:00
virtual ~SCPINode();
2022-10-01 17:10:44 +02:00
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);}
2022-10-01 17:10:44 +02:00
bool addDoubleParameter(QString name, double &param, bool gettable = true, bool settable = true, std::function<void(void)> setCallback = nullptr);
bool addUnsignedIntParameter(QString name, unsigned int &param, bool gettable = true, bool settable = true, std::function<void(void)> setCallback = nullptr);
bool addBoolParameter(QString name, bool &param, bool gettable = true, bool settable = true, std::function<void(void)> setCallback = nullptr);
bool addStringParameter(QString name, QString &param, bool gettable = true, bool settable = true, std::function<void(void)> setCallback = nullptr);
2022-12-12 17:39:17 +01:00
bool changeName(QString newname);
QString leafName() {return name.split(":").back();}
2022-12-12 17:39:17 +01:00
2024-04-07 14:11:04 +02:00
void setOperationPending(bool pending);
protected:
2024-04-07 14:11:04 +02:00
bool isOperationPending();
2022-10-01 17:10:44 +02:00
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);
2022-12-12 17:39:17 +01:00
QString name;
2022-10-01 17:10:44 +02:00
std::vector<SCPINode*> subnodes;
std::vector<SCPICommand*> commands;
SCPINode *parent;
2024-04-07 14:11:04 +02:00
bool operationPending;
2022-10-01 17:10:44 +02:00
};
class SCPI : public QObject, public SCPINode
{
Q_OBJECT
public:
SCPI();
static bool match(QString s1, QString s2);
static QString alternateName(QString name);
static bool paramToDouble(QStringList params, int index, double &dest);
static bool paramToULongLong(QStringList params, int index, unsigned long long &dest);
static bool paramToLong(QStringList params, int index, long &dest);
static bool paramToBool(QStringList params, int index, bool &dest);
enum class Result {
Empty,
Error,
2024-04-07 14:22:57 +02:00
CmdError,
QueryError,
ExecError,
2022-10-01 17:10:44 +02:00
False,
True
};
static QString getResultName(SCPI::Result r);
2024-04-07 14:11:04 +02:00
// call whenever a subnode completes an operation
void someOperationCompleted();
2022-10-01 17:10:44 +02:00
public slots:
void input(QString line);
2024-04-07 14:11:04 +02:00
void process();
2022-10-01 17:10:44 +02:00
signals:
void output(QString line);
2024-04-07 14:11:04 +02:00
private:
enum class Flag {
OPC = 0x01, // Operation complete
RQC = 0x02, // device wants to become the controller (of the bus)
QYE = 0x04, // query error
DDE = 0x08, // device-dependent error
EXE = 0x10, // execution error
CME = 0x20, // command error
URQ = 0x40, // user request
PON = 0x80, // power on
};
void setFlag(Flag flag);
void clearFlag(Flag flag);
bool getFlag(Flag flag);
2024-04-07 14:39:27 +02:00
unsigned int SESR;
unsigned int ESE;
2024-04-07 14:11:04 +02:00
bool OCAS;
bool OPCsetBitScheduled;
2024-04-07 14:11:04 +02:00
bool OPCQueryScheduled;
bool WAIexecuting;
QList<QString> cmdQueue;
2024-12-02 12:10:13 +01:00
bool processing;
2024-12-02 14:02:34 +01:00
QSemaphore semQueue;
QSemaphore semProcessing;
2022-10-01 17:10:44 +02:00
};
#endif // SCPI_H