DeviceDriver base class
This commit is contained in:
parent
8aec59f32b
commit
59e30e93c5
429
Software/PC_Application/LibreVNA-GUI/Device/devicedriver.h
Normal file
429
Software/PC_Application/LibreVNA-GUI/Device/devicedriver.h
Normal file
@ -0,0 +1,429 @@
|
|||||||
|
#ifndef DEVICEDRIVER_H
|
||||||
|
#define DEVICEDRIVER_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This file contains the device interface.
|
||||||
|
*
|
||||||
|
* To add support for a new hardware device perform the following steps:
|
||||||
|
* - Derive from this class
|
||||||
|
* - Implement all pure virtual functions
|
||||||
|
* - Implement the virtual functions if the device supports the specific function
|
||||||
|
* - TODO register the driver during application start
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Tools/parameters.h"
|
||||||
|
#include "savable.h"
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
#include <complex>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QAction>
|
||||||
|
|
||||||
|
class DeviceDriver : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
DeviceDriver();
|
||||||
|
virtual ~DeviceDriver();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the driver name. It must be unique across all implemented drivers and is used to identify the driver
|
||||||
|
* @return driver name
|
||||||
|
*/
|
||||||
|
virtual QString getDriverName() = 0;
|
||||||
|
/**
|
||||||
|
* @brief Lists all available devices by their serial numbers
|
||||||
|
* @return Serial numbers of detected devices
|
||||||
|
*/
|
||||||
|
virtual std::set<QString> GetAvailableDevices() = 0;
|
||||||
|
/**
|
||||||
|
* @brief Connects to a device, given by its serial number
|
||||||
|
* @param serial Serial number of device that should be connected to
|
||||||
|
* @return true if connection successful, otherwise false
|
||||||
|
*/
|
||||||
|
virtual bool connectTo(QString serial) = 0;
|
||||||
|
/**
|
||||||
|
* @brief Disconnects from device. Has no effect if no device was connected
|
||||||
|
*/
|
||||||
|
virtual void disconnect() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the serial number of the connected device
|
||||||
|
* @return Serial number of connected device (empty string if no device is connected)
|
||||||
|
*/
|
||||||
|
virtual QString serial() = 0;
|
||||||
|
|
||||||
|
enum class Feature {
|
||||||
|
// VNA features
|
||||||
|
VNA,
|
||||||
|
VNAFrequencySweep,
|
||||||
|
VNAPowerSweep,
|
||||||
|
VNAZeroSpan,
|
||||||
|
VNALogSweep,
|
||||||
|
// Generator features
|
||||||
|
Generator,
|
||||||
|
// Spectrum analyzer features
|
||||||
|
SA,
|
||||||
|
SASignalID,
|
||||||
|
SATrackingGenerator,
|
||||||
|
SATrackingOffset,
|
||||||
|
// External reference
|
||||||
|
ExtRefIn,
|
||||||
|
ExtRefOut,
|
||||||
|
};
|
||||||
|
|
||||||
|
class Info {
|
||||||
|
public:
|
||||||
|
QString firmware_version;
|
||||||
|
QString hardware_version;
|
||||||
|
std::set<Feature> supportedFeatures;
|
||||||
|
struct {
|
||||||
|
struct {
|
||||||
|
// Number of VNA ports
|
||||||
|
unsigned int ports;
|
||||||
|
// Sweep frequency limits in Hz
|
||||||
|
double minFreq, maxFreq;
|
||||||
|
// IF bandwidth limits in Hz
|
||||||
|
double minIFBW, maxIFBW;
|
||||||
|
// Maximum number of points per sweep
|
||||||
|
unsigned int maxPoints;
|
||||||
|
// Stimulus level limits in dBm
|
||||||
|
double mindBm, maxdBm;
|
||||||
|
} VNA;
|
||||||
|
struct {
|
||||||
|
// Number of ports
|
||||||
|
unsigned int ports;
|
||||||
|
// Frequency limits in Hz
|
||||||
|
double minFreq, maxFreq;
|
||||||
|
// Output level limits in dBm
|
||||||
|
double mindBm, maxdBm;
|
||||||
|
} Generator;
|
||||||
|
struct {
|
||||||
|
// Number of ports
|
||||||
|
unsigned int ports;
|
||||||
|
// Sweep frequency limits in Hz
|
||||||
|
double minFreq, maxFreq;
|
||||||
|
// RBW limits in Hz
|
||||||
|
double minRBW, maxRBW;
|
||||||
|
} SA;
|
||||||
|
} Limits;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the device information. This function will be called when a device has been connected. Its return value must be valid
|
||||||
|
* directly after returning from DeviceDriver::connectTo()
|
||||||
|
*
|
||||||
|
* Emit the InfoUpdate() signal whenever the return value of this function changes.
|
||||||
|
*
|
||||||
|
* @return Device information
|
||||||
|
*/
|
||||||
|
virtual Info getInfo() = 0;
|
||||||
|
signals:
|
||||||
|
/**
|
||||||
|
* @brief Emit this signal whenever the device info has been updated
|
||||||
|
*/
|
||||||
|
void InfoUpdated();
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Checks whether a specific feature is supported
|
||||||
|
* @param f Feature to check
|
||||||
|
* @return true if feature is supported, false otherwise
|
||||||
|
*/
|
||||||
|
bool supports(Feature f) { return getInfo().supportedFeatures.count(f);}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status flags
|
||||||
|
*/
|
||||||
|
enum class Flag {
|
||||||
|
// The input is overloaded with a signal that is too large
|
||||||
|
Overload,
|
||||||
|
// A PLL failed to lock
|
||||||
|
Unlocked,
|
||||||
|
// The requested output amplitude can not be reached
|
||||||
|
Unlevel,
|
||||||
|
// The external reference input is in use
|
||||||
|
ExtRef,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a set of all active flags
|
||||||
|
*
|
||||||
|
* There is also a convenience function to check a specific flag, see DeviceDriver::asserted()
|
||||||
|
*
|
||||||
|
* @return Set of active flags
|
||||||
|
*/
|
||||||
|
virtual std::set<Flag> getFlags() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks whether a specific flag is asserted
|
||||||
|
* @param f Flag to check
|
||||||
|
* @return true if flag is asserted, false otherwise
|
||||||
|
*/
|
||||||
|
bool asserted(Flag f) {return getFlags().count(f);}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the device status string. It will be displayed in the status bar of the application
|
||||||
|
*
|
||||||
|
* Emit the StatusUpdated() signal whenever the return value of this function changes
|
||||||
|
*
|
||||||
|
* @return Status string
|
||||||
|
*/
|
||||||
|
virtual QString getStatus() {return "";}
|
||||||
|
signals:
|
||||||
|
/**
|
||||||
|
* @brief Emit this signal whenever the device status has changed (return value of getStatus() has changed)
|
||||||
|
*/
|
||||||
|
void StatusUpdated();
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Returns the driver specific settings
|
||||||
|
*
|
||||||
|
* The settings are returned as a map.
|
||||||
|
* Key: user-readable setting name
|
||||||
|
* Value: SettingDescription, consisting of:
|
||||||
|
* - var: Pointer to the setting variable (should be a private member of the derived class)
|
||||||
|
* - name: Arbitrary string used to persistently store this setting (never visible to the user)
|
||||||
|
* - def: Default value of the setting
|
||||||
|
*
|
||||||
|
* These settings will be persistent across reboots. For each device driver, a section within the preferences
|
||||||
|
* will be created where these settings can be changed.
|
||||||
|
*
|
||||||
|
* @return Map of driver specific settings
|
||||||
|
*/
|
||||||
|
virtual std::map<QString, Savable::SettingDescription> driverSpecificSettings() {return std::map<QString, Savable::SettingDescription>();}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return driver specific actions.
|
||||||
|
*
|
||||||
|
* The returned actions will be appended to the device menu.
|
||||||
|
*
|
||||||
|
* @return List of actions
|
||||||
|
*/
|
||||||
|
virtual std::vector<QAction*> driverSpecificActions() {return std::vector<QAction*>();}
|
||||||
|
|
||||||
|
class VNASettings {
|
||||||
|
public:
|
||||||
|
// Start/stop frequency. Both values will be identical for power sweeps and zero span
|
||||||
|
double freqStart, freqStop;
|
||||||
|
// Start/stop stimulus level. Both values will be identical for frequency sweeps and zero span
|
||||||
|
double dBmStart, dBmStop;
|
||||||
|
// IF bandwidth
|
||||||
|
double IFBW;
|
||||||
|
// Number of points in the sweep
|
||||||
|
int points;
|
||||||
|
// Logarithmic sweep flag, set if sweep should be logarithmic
|
||||||
|
bool logSweep;
|
||||||
|
// List of ports that should be excited during the sweep (port count starts at 1)
|
||||||
|
std::vector<int> excitedPorts;
|
||||||
|
};
|
||||||
|
|
||||||
|
class VNAMeasurement {
|
||||||
|
public:
|
||||||
|
// Number of the point in the sweep (starts at 0)
|
||||||
|
unsigned int pointNum;
|
||||||
|
// Characteristic impedance of the measurement result (typically 50 Ohm)
|
||||||
|
double Z0;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
// for non-zero span
|
||||||
|
// Frequency of the point
|
||||||
|
double frequency;
|
||||||
|
// Stimulus level of the point
|
||||||
|
double dBm;
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
// for zero span
|
||||||
|
// time in us since first datapoint
|
||||||
|
double us;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
// S parameter measurements
|
||||||
|
// Key: S parameter name, e.g. "S11"
|
||||||
|
// Value: complex measurement in real/imag (linear, not in dB)
|
||||||
|
std::map<QString, std::complex<double>> measurements;
|
||||||
|
|
||||||
|
Sparam toSparam(int port1, int port2) const;
|
||||||
|
void fromSparam(Sparam S, int port1, int port2);
|
||||||
|
VNAMeasurement interpolateTo(const VNAMeasurement &to, double a);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Names of available measurements.
|
||||||
|
*
|
||||||
|
* The names must be identical to the names used in the returned VNAMeasurement.
|
||||||
|
* Typically the S parameters, e.g. this function may return {"S11","S12","S21","S22"} but any other names are also allowed.
|
||||||
|
*
|
||||||
|
* @return List of available VNA measurement parameters
|
||||||
|
*/
|
||||||
|
virtual QStringList availableVNAMeasurements() {return {};}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Configures the VNA and starts a sweep
|
||||||
|
* @param s VNA settings
|
||||||
|
* @param cb Callback, must be called after the VNA has been configured
|
||||||
|
* @return true if configuration successful, false otherwise
|
||||||
|
*/
|
||||||
|
virtual bool setVNA(const VNASettings &s, std::function<void(bool)> cb = nullptr) {Q_UNUSED(s) Q_UNUSED(cb) return false;}
|
||||||
|
signals:
|
||||||
|
/**
|
||||||
|
* @brief This signal must be emitted whenever a VNA measurement is complete and should be passed on to the GUI
|
||||||
|
* @param m VNA measurement
|
||||||
|
*/
|
||||||
|
void VNAmeasurementReceived(VNAMeasurement m);
|
||||||
|
|
||||||
|
public:
|
||||||
|
class SASettings {
|
||||||
|
public:
|
||||||
|
enum class Window {
|
||||||
|
None = 0,
|
||||||
|
Kaiser = 1,
|
||||||
|
Hann = 2,
|
||||||
|
FlatTop = 3,
|
||||||
|
Last
|
||||||
|
};
|
||||||
|
enum class Detector {
|
||||||
|
PPeak = 0,
|
||||||
|
NPeak = 1,
|
||||||
|
Sample = 2,
|
||||||
|
Normal = 3,
|
||||||
|
Average = 4,
|
||||||
|
Last
|
||||||
|
};
|
||||||
|
// Start/stop frequency. Both values will be identical for zero span
|
||||||
|
double freqStart, freqStop;
|
||||||
|
// Resolution bandwidth
|
||||||
|
double RBW;
|
||||||
|
// Window type
|
||||||
|
Window window;
|
||||||
|
// Detector type
|
||||||
|
Detector detector;
|
||||||
|
// Tracking generator enable
|
||||||
|
bool trackingGenerator;
|
||||||
|
// Port at which the tracking generator is active. Port count starts at 1
|
||||||
|
int trackingPort;
|
||||||
|
// Offset frequency of the tracking generator
|
||||||
|
double trackingOffset;
|
||||||
|
// Output level of the tracking generator
|
||||||
|
double trackingPower;
|
||||||
|
};
|
||||||
|
class SAMeasurement {
|
||||||
|
public:
|
||||||
|
// Number of point in the sweep
|
||||||
|
int pointNum;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
// for non-zero span
|
||||||
|
double frequency;
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
// for zero span
|
||||||
|
double us; // time in us since first datapoint
|
||||||
|
};
|
||||||
|
};
|
||||||
|
// S parameter measurements
|
||||||
|
// Key: S parameter name, e.g. "PORT1"
|
||||||
|
// Value: measurement in mW (linear, not in dB). A value of 1.0 means 0dBm
|
||||||
|
std::map<QString, double> measurements;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Names of available measurements.
|
||||||
|
*
|
||||||
|
* The names must be identical to the names used in the returned SAMeasurement.
|
||||||
|
* Typically the port names, e.g. this function may return {"PORT1","PORT2"} but any other names are also allowed.
|
||||||
|
*
|
||||||
|
* @return List of available SA measurement parameters
|
||||||
|
*/
|
||||||
|
virtual QStringList availableSAMeasurements() {return {};}
|
||||||
|
/**
|
||||||
|
* @brief Configures the SA and starts a sweep
|
||||||
|
* @param s SA settings
|
||||||
|
* @param cb Callback, must be called after the SA has been configured
|
||||||
|
* @return true if configuration successful, false otherwise
|
||||||
|
*/
|
||||||
|
virtual bool setSA(const SASettings &s, std::function<void(bool)> cb = nullptr) {Q_UNUSED(s) Q_UNUSED(cb) return false;}
|
||||||
|
signals:
|
||||||
|
/**
|
||||||
|
* @brief This signal must be emitted whenever a SA measurement is complete and should be passed on to the GUI
|
||||||
|
* @param m SA measurement
|
||||||
|
*/
|
||||||
|
void SAmeasurementReceived(SAMeasurement m);
|
||||||
|
|
||||||
|
public:
|
||||||
|
class SGSettings {
|
||||||
|
public:
|
||||||
|
// Output frequency
|
||||||
|
double freq;
|
||||||
|
// Output signal level
|
||||||
|
double dBm;
|
||||||
|
// Output port. Port count starts at 1, set to zero to disable all ports
|
||||||
|
int port;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Names of available generator ports.
|
||||||
|
*
|
||||||
|
* Typically the port names, e.g. this function may return {"PORT1","PORT2"} but any other names are also allowed.
|
||||||
|
*
|
||||||
|
* @return List of available SA measurement parameters
|
||||||
|
*/
|
||||||
|
virtual QStringList availableSGPorts() {return {};}
|
||||||
|
/**
|
||||||
|
* @brief Configures the generator
|
||||||
|
* @param s Generator settings
|
||||||
|
* @return true if configuration successful, false otherwise
|
||||||
|
*/
|
||||||
|
virtual bool setSG(const SGSettings &s) {Q_UNUSED(s) return false;}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the device to idle
|
||||||
|
*
|
||||||
|
* Stops all sweeps and signal generation
|
||||||
|
*
|
||||||
|
* @param cb Callback, must be called after the device has stopped all operations
|
||||||
|
* @return true if configuration successful, false otherwise
|
||||||
|
*/
|
||||||
|
virtual bool setIdle(std::function<void(bool)> cb = nullptr) {Q_UNUSED(cb) return false;}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the available options for the external reference input
|
||||||
|
* @return External reference input options
|
||||||
|
*/
|
||||||
|
virtual QStringList availableExtRefInSettings() {return {};}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the available options for the external reference output
|
||||||
|
* @return External reference output options
|
||||||
|
*/
|
||||||
|
virtual QStringList availableExtRefOutSettings() {return {};}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Configures the external reference input/output
|
||||||
|
* @param option_in Reference input option (one of the options returned by availableExtRefInSettings())
|
||||||
|
* @param option_out Reference output option (one of the options returned by availableExtRefOutSettings())
|
||||||
|
* @return true if configuration successful, false otherwise
|
||||||
|
*/
|
||||||
|
virtual bool setExtRef(QString option_in, QString option_out) {Q_UNUSED(option_in) Q_UNUSED(option_out) return false;}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief maximumSupportedPorts Maximum number of supported ports by the GUI. No device driver may report a higher number of ports than this value
|
||||||
|
*/
|
||||||
|
static constexpr unsigned int maximumSupportedPorts = 8;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
/**
|
||||||
|
* @brief Emit this signal when the device connection has been lost unexpectedly
|
||||||
|
*/
|
||||||
|
void ConnectionLost();
|
||||||
|
/**
|
||||||
|
* @brief Emit this signal whenever a debug log line from the device has been received. May be left unused if device does not support debug output
|
||||||
|
* @param line
|
||||||
|
*/
|
||||||
|
void LogLineReceived(QString line);
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(DeviceDriver::VNAMeasurement)
|
||||||
|
Q_DECLARE_METATYPE(DeviceDriver::SAMeasurement)
|
||||||
|
|
||||||
|
#endif // VIRTUALDEVICE_H
|
@ -0,0 +1,6 @@
|
|||||||
|
#include "librevnadriver.h"
|
||||||
|
|
||||||
|
LibreVNADriver::LibreVNADriver()
|
||||||
|
{
|
||||||
|
connected = false;
|
||||||
|
}
|
29
Software/PC_Application/LibreVNA-GUI/Device/librevnadriver.h
Normal file
29
Software/PC_Application/LibreVNA-GUI/Device/librevnadriver.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef LIBREVNADRIVER_H
|
||||||
|
#define LIBREVNADRIVER_H
|
||||||
|
|
||||||
|
#include "devicedriver.h"
|
||||||
|
|
||||||
|
#include "../../VNA_embedded/Application/Communication/Protocol.hpp"
|
||||||
|
|
||||||
|
class LibreVNADriver : public DeviceDriver
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum class TransmissionResult {
|
||||||
|
Ack,
|
||||||
|
Nack,
|
||||||
|
Timeout,
|
||||||
|
InternalError,
|
||||||
|
};
|
||||||
|
Q_ENUM(TransmissionResult)
|
||||||
|
|
||||||
|
LibreVNADriver();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool SendPacket(const Protocol::PacketInfo& packet, std::function<void(TransmissionResult)> cb = nullptr, unsigned int timeout = 500) = 0;
|
||||||
|
virtual void ReceivedData(const uint8_t data, unsigned int len) = 0;
|
||||||
|
|
||||||
|
bool connected;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LIBREVNADRIVER_H
|
@ -26,10 +26,12 @@ HEADERS += \
|
|||||||
Device/compounddevice.h \
|
Device/compounddevice.h \
|
||||||
Device/compounddeviceeditdialog.h \
|
Device/compounddeviceeditdialog.h \
|
||||||
Device/device.h \
|
Device/device.h \
|
||||||
|
Device/devicedriver.h \
|
||||||
Device/devicelog.h \
|
Device/devicelog.h \
|
||||||
Device/deviceusblog.h \
|
Device/deviceusblog.h \
|
||||||
Device/deviceusblogview.h \
|
Device/deviceusblogview.h \
|
||||||
Device/firmwareupdatedialog.h \
|
Device/firmwareupdatedialog.h \
|
||||||
|
Device/librevnadriver.h \
|
||||||
Device/manualcontroldialog.h \
|
Device/manualcontroldialog.h \
|
||||||
Device/virtualdevice.h \
|
Device/virtualdevice.h \
|
||||||
Generator/generator.h \
|
Generator/generator.h \
|
||||||
@ -178,6 +180,7 @@ SOURCES += \
|
|||||||
Device/deviceusblog.cpp \
|
Device/deviceusblog.cpp \
|
||||||
Device/deviceusblogview.cpp \
|
Device/deviceusblogview.cpp \
|
||||||
Device/firmwareupdatedialog.cpp \
|
Device/firmwareupdatedialog.cpp \
|
||||||
|
Device/librevnadriver.cpp \
|
||||||
Device/manualcontroldialog.cpp \
|
Device/manualcontroldialog.cpp \
|
||||||
Device/virtualdevice.cpp \
|
Device/virtualdevice.cpp \
|
||||||
Generator/generator.cpp \
|
Generator/generator.cpp \
|
||||||
|
Loading…
Reference in New Issue
Block a user