WIP: device driver abstraction
This commit is contained in:
parent
59e30e93c5
commit
db6d823e0f
@ -151,7 +151,7 @@ Calibration::Calibration()
|
||||
}
|
||||
bool okay;
|
||||
unsigned int number = params[1].toInt(&okay);
|
||||
if(!okay || number < 1 || number > VirtualDevice::getInfo(VirtualDevice::getConnected()).ports) {
|
||||
if(!okay || number < 1 || number > DeviceDriver::getInfo(DeviceDriver::getActiveDriver()).Limits.VNA.ports) {
|
||||
// invalid port specified
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
@ -168,8 +168,8 @@ Calibration::Calibration()
|
||||
unsigned int port1 = params[1].toInt(&okay1);
|
||||
bool okay2;
|
||||
unsigned int port2 = params[2].toInt(&okay2);
|
||||
if(!okay1 || !okay2 || port1 < 1 || port2 > VirtualDevice::getInfo(VirtualDevice::getConnected()).ports
|
||||
|| port2 < 1 || port2 > VirtualDevice::getInfo(VirtualDevice::getConnected()).ports) {
|
||||
if(!okay1 || !okay2 || port1 < 1 || port2 > DeviceDriver::getInfo(DeviceDriver::getActiveDriver()).Limits.VNA.ports
|
||||
|| port2 < 1 || port2 > DeviceDriver::getInfo(DeviceDriver::getActiveDriver()).Limits.VNA.ports) {
|
||||
// invalid port specified
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
@ -318,7 +318,7 @@ Calibration::Type Calibration::TypeFromString(QString s)
|
||||
return Type::None;
|
||||
}
|
||||
|
||||
void Calibration::correctMeasurement(VirtualDevice::VNAMeasurement &d)
|
||||
void Calibration::correctMeasurement(DeviceDriver::VNAMeasurement &d)
|
||||
{
|
||||
lock_guard<recursive_mutex> guard(access);
|
||||
if(caltype.type == Type::None) {
|
||||
@ -1424,7 +1424,7 @@ void Calibration::fromJSON(nlohmann::json j)
|
||||
throw runtime_error("Measurement "+name.toStdString()+" does not contain any points");
|
||||
}
|
||||
for(auto j_p : j_m["points"]) {
|
||||
VirtualDevice::VNAMeasurement p;
|
||||
DeviceDriver::VNAMeasurement p;
|
||||
p.frequency = j_p.value("frequency", 0.0);
|
||||
p.Z0 = 50.0;
|
||||
p.measurements["S11"] = complex<double>(j_p.value("S11_real", 0.0), j_p.value("S11_imag", 0.0));
|
||||
@ -1557,10 +1557,7 @@ bool Calibration::fromFile(QString filename)
|
||||
|
||||
std::vector<Calibration::CalType> Calibration::getAvailableCalibrations()
|
||||
{
|
||||
unsigned int ports = 2;
|
||||
if(VirtualDevice::getConnected()) {
|
||||
ports = VirtualDevice::getConnected()->getInfo().ports;
|
||||
}
|
||||
unsigned int ports = DeviceDriver::getInfo(DeviceDriver::getActiveDriver()).Limits.VNA.ports;
|
||||
vector<CalType> ret;
|
||||
for(auto t : getTypes()) {
|
||||
CalType cal;
|
||||
@ -1727,14 +1724,15 @@ int Calibration::minimumPorts(Calibration::Type type)
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Calibration::addMeasurements(std::set<CalibrationMeasurement::Base *> m, const VirtualDevice::VNAMeasurement &data)
|
||||
void Calibration::addMeasurements(std::set<CalibrationMeasurement::Base *> m, const DeviceDriver::VNAMeasurement &data)
|
||||
{
|
||||
for(auto meas : m) {
|
||||
meas->addPoint(data);
|
||||
}
|
||||
unsavedChanges = true;
|
||||
if(VirtualDevice::getConnected()) {
|
||||
validDevice = VirtualDevice::getConnected()->serial();
|
||||
// TODO
|
||||
if(DeviceDriver::getActiveDriver()) {
|
||||
validDevice = DeviceDriver::getActiveDriver()->getSerial();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include "Traces/trace.h"
|
||||
#include "scpi.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
class Calibration : public QObject, public Savable, public SCPINode
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -38,7 +40,7 @@ public:
|
||||
static Type TypeFromString(QString s);
|
||||
|
||||
// Applies calculated calibration coefficients to measurement data
|
||||
void correctMeasurement(VirtualDevice::VNAMeasurement &d);
|
||||
void correctMeasurement(DeviceDriver::VNAMeasurement &d);
|
||||
void correctTraces(std::map<QString, Trace*> traceSet);
|
||||
|
||||
// Starts the calibration edit dialog, allowing the user to make/delete measurements
|
||||
@ -68,7 +70,7 @@ public:
|
||||
static int minimumPorts(Type type);
|
||||
|
||||
// Adds a new measurement point (data) to all calibration measurements (m)
|
||||
void addMeasurements(std::set<CalibrationMeasurement::Base*> m, const VirtualDevice::VNAMeasurement &data);
|
||||
void addMeasurements(std::set<CalibrationMeasurement::Base*> m, const DeviceDriver::VNAMeasurement &data);
|
||||
// Deletes all datapoints in the calibration measurements (m)
|
||||
void clearMeasurements(std::set<CalibrationMeasurement::Base*> m);
|
||||
CalType getCaltype() const;
|
||||
|
@ -246,7 +246,7 @@ void CalibrationMeasurement::OnePort::clearPoints()
|
||||
timestamp = QDateTime();
|
||||
}
|
||||
|
||||
void CalibrationMeasurement::OnePort::addPoint(const VirtualDevice::VNAMeasurement &m)
|
||||
void CalibrationMeasurement::OnePort::addPoint(const DeviceDriver::VNAMeasurement &m)
|
||||
{
|
||||
QString measurementName = "S"+QString::number(port)+QString::number(port);
|
||||
if(m.measurements.count(measurementName) > 0) {
|
||||
@ -262,12 +262,12 @@ QWidget *CalibrationMeasurement::OnePort::createSettingsWidget()
|
||||
{
|
||||
auto label = new QLabel("Port:");
|
||||
auto cbPort = new QComboBox();
|
||||
auto dev = VirtualDevice::getConnected();
|
||||
auto dev = DeviceDriver::getActiveDriver();
|
||||
if(dev) {
|
||||
if(port == 0) {
|
||||
setPort(1);
|
||||
}
|
||||
for(unsigned int i=1;i<=dev->getInfo().ports;i++) {
|
||||
for(unsigned int i=1;i<=dev->getInfo().Limits.VNA.ports;i++) {
|
||||
cbPort->addItem(QString::number(i));
|
||||
if(port == i) {
|
||||
cbPort->setCurrentText(QString::number(i));
|
||||
@ -390,7 +390,7 @@ void CalibrationMeasurement::TwoPort::clearPoints()
|
||||
timestamp = QDateTime();
|
||||
}
|
||||
|
||||
void CalibrationMeasurement::TwoPort::addPoint(const VirtualDevice::VNAMeasurement &m)
|
||||
void CalibrationMeasurement::TwoPort::addPoint(const DeviceDriver::VNAMeasurement &m)
|
||||
{
|
||||
Point p;
|
||||
p.frequency = m.frequency;
|
||||
@ -407,7 +407,7 @@ QWidget *CalibrationMeasurement::TwoPort::createSettingsWidget()
|
||||
auto cbPort2 = new QComboBox();
|
||||
auto cbReverse = new QCheckBox("Reversed");
|
||||
cbReverse->setToolTip("Enable this option if the calibration standard is defined with the port order swapped");
|
||||
auto dev = VirtualDevice::getConnected();
|
||||
auto dev = DeviceDriver::getActiveDriver();
|
||||
if(dev) {
|
||||
if(port1 == 0) {
|
||||
setPort1(1);
|
||||
@ -415,7 +415,7 @@ QWidget *CalibrationMeasurement::TwoPort::createSettingsWidget()
|
||||
if(port2 == 0) {
|
||||
setPort2(2);
|
||||
}
|
||||
for(unsigned int i=1;i<=dev->getInfo().ports;i++) {
|
||||
for(unsigned int i=1;i<=dev->getInfo().Limits.VNA.ports;i++) {
|
||||
cbPort1->addItem(QString::number(i));
|
||||
cbPort2->addItem(QString::number(i));
|
||||
if(port1 == i) {
|
||||
@ -603,7 +603,7 @@ void CalibrationMeasurement::Isolation::clearPoints()
|
||||
timestamp = QDateTime();
|
||||
}
|
||||
|
||||
void CalibrationMeasurement::Isolation::addPoint(const VirtualDevice::VNAMeasurement &m)
|
||||
void CalibrationMeasurement::Isolation::addPoint(const DeviceDriver::VNAMeasurement &m)
|
||||
{
|
||||
Point p;
|
||||
p.frequency = m.frequency;
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define CALIBRATIONMEASUREMENT_H
|
||||
|
||||
#include "calstandard.h"
|
||||
#include "Device/virtualdevice.h"
|
||||
#include "Device/devicedriver.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QObject>
|
||||
@ -47,7 +47,7 @@ public:
|
||||
virtual Type getType() = 0;
|
||||
|
||||
virtual void clearPoints() = 0;
|
||||
virtual void addPoint(const VirtualDevice::VNAMeasurement &m) = 0;
|
||||
virtual void addPoint(const DeviceDriver::VNAMeasurement &m) = 0;
|
||||
|
||||
virtual QWidget* createStandardWidget();
|
||||
virtual QWidget* createSettingsWidget() = 0;
|
||||
@ -83,7 +83,7 @@ public:
|
||||
virtual bool readyForCalculation() override {return standard && points.size() > 0;}
|
||||
|
||||
virtual void clearPoints() override;
|
||||
virtual void addPoint(const VirtualDevice::VNAMeasurement &m) override;
|
||||
virtual void addPoint(const DeviceDriver::VNAMeasurement &m) override;
|
||||
|
||||
virtual QWidget* createSettingsWidget() override;
|
||||
|
||||
@ -197,7 +197,7 @@ public:
|
||||
virtual bool readyForCalculation() override {return standard && points.size() > 0;}
|
||||
|
||||
virtual void clearPoints() override;
|
||||
virtual void addPoint(const VirtualDevice::VNAMeasurement &m) override;
|
||||
virtual void addPoint(const DeviceDriver::VNAMeasurement &m) override;
|
||||
|
||||
virtual QWidget* createSettingsWidget() override;
|
||||
|
||||
@ -268,7 +268,7 @@ public:
|
||||
virtual bool readyForCalculation() override {return points.size() > 0;}
|
||||
|
||||
virtual void clearPoints() override;
|
||||
virtual void addPoint(const VirtualDevice::VNAMeasurement &m) override;
|
||||
virtual void addPoint(const DeviceDriver::VNAMeasurement &m) override;
|
||||
|
||||
virtual QWidget* createStandardWidget() override;
|
||||
virtual QWidget* createSettingsWidget() override;
|
||||
|
22
Software/PC_Application/LibreVNA-GUI/Device/devicedriver.cpp
Normal file
22
Software/PC_Application/LibreVNA-GUI/Device/devicedriver.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
#include "devicedriver.h"
|
||||
|
||||
DeviceDriver *DeviceDriver::activeDriver = nullptr;
|
||||
|
||||
bool DeviceDriver::connectDevice(QString serial)
|
||||
{
|
||||
if(activeDriver && activeDriver != this) {
|
||||
activeDriver->disconnect();
|
||||
}
|
||||
if(connectTo(serial)) {
|
||||
activeDriver = this;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceDriver::disconnectDevice()
|
||||
{
|
||||
disconnect();
|
||||
activeDriver = nullptr;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
#ifndef DEVICEDRIVER_H
|
||||
#ifndef DEVICEDRIVER_H
|
||||
#define DEVICEDRIVER_H
|
||||
|
||||
/**
|
||||
@ -24,8 +24,8 @@ class DeviceDriver : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DeviceDriver();
|
||||
virtual ~DeviceDriver();
|
||||
DeviceDriver() {}
|
||||
virtual ~DeviceDriver() {}
|
||||
|
||||
/**
|
||||
* @brief Returns the driver name. It must be unique across all implemented drivers and is used to identify the driver
|
||||
@ -37,22 +37,26 @@ public:
|
||||
* @return Serial numbers of detected devices
|
||||
*/
|
||||
virtual std::set<QString> GetAvailableDevices() = 0;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @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;
|
||||
virtual bool connectTo(QString getSerial) = 0;
|
||||
/**
|
||||
* @brief Disconnects from device. Has no effect if no device was connected
|
||||
*/
|
||||
virtual void disconnect() = 0;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @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;
|
||||
virtual QString getSerial() = 0;
|
||||
|
||||
enum class Feature {
|
||||
// VNA features
|
||||
@ -65,7 +69,6 @@ public:
|
||||
Generator,
|
||||
// Spectrum analyzer features
|
||||
SA,
|
||||
SASignalID,
|
||||
SATrackingGenerator,
|
||||
SATrackingOffset,
|
||||
// External reference
|
||||
@ -75,6 +78,7 @@ public:
|
||||
|
||||
class Info {
|
||||
public:
|
||||
// TODO create constructor with default values
|
||||
QString firmware_version;
|
||||
QString hardware_version;
|
||||
std::set<Feature> supportedFeatures;
|
||||
@ -106,6 +110,8 @@ public:
|
||||
double minFreq, maxFreq;
|
||||
// RBW limits in Hz
|
||||
double minRBW, maxRBW;
|
||||
// Output level limits of the tracking generator in dBm
|
||||
double mindBm, maxdBm;
|
||||
} SA;
|
||||
} Limits;
|
||||
};
|
||||
@ -179,19 +185,16 @@ public:
|
||||
/**
|
||||
* @brief Returns the driver specific settings
|
||||
*
|
||||
* The settings are returned as a map.
|
||||
* Key: user-readable setting name
|
||||
* Value: SettingDescription, consisting of:
|
||||
* The settings are returned as a vector of SettingDescriptions, 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.
|
||||
* These settings will be persistent across reboots.
|
||||
*
|
||||
* @return Map of driver specific settings
|
||||
*/
|
||||
virtual std::map<QString, Savable::SettingDescription> driverSpecificSettings() {return std::map<QString, Savable::SettingDescription>();}
|
||||
virtual std::vector<Savable::SettingDescription> driverSpecificSettings() {return std::vector<Savable::SettingDescription>();}
|
||||
|
||||
/**
|
||||
* @brief Return driver specific actions.
|
||||
@ -343,6 +346,12 @@ public:
|
||||
* @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;}
|
||||
|
||||
/**
|
||||
* @brief Returns the number of points in one spectrum analyzer sweep (as configured by the last setSA() call)
|
||||
* @return Number of points in the sweep
|
||||
*/
|
||||
virtual unsigned int getSApoints() {return 0;}
|
||||
signals:
|
||||
/**
|
||||
* @brief This signal must be emitted whenever a SA measurement is complete and should be passed on to the GUI
|
||||
@ -411,9 +420,19 @@ public:
|
||||
*/
|
||||
static constexpr unsigned int maximumSupportedPorts = 8;
|
||||
|
||||
static Info getInfo(DeviceDriver* driver) {
|
||||
if(driver) {
|
||||
return driver->getInfo();
|
||||
} else {
|
||||
return Info();
|
||||
}
|
||||
}
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief Emit this signal when the device connection has been lost unexpectedly
|
||||
*
|
||||
* The device driver should do nothing else, the disconnect() function will be called from the application after this signal has been emitted.
|
||||
*/
|
||||
void ConnectionLost();
|
||||
/**
|
||||
@ -421,6 +440,14 @@ signals:
|
||||
* @param line
|
||||
*/
|
||||
void LogLineReceived(QString line);
|
||||
|
||||
public:
|
||||
bool connectDevice(QString serial);
|
||||
void disconnectDevice();
|
||||
static DeviceDriver* getActiveDriver() {return activeDriver;}
|
||||
|
||||
private:
|
||||
static DeviceDriver *activeDriver;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(DeviceDriver::VNAMeasurement)
|
||||
|
@ -1,6 +1,312 @@
|
||||
#include "librevnadriver.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
LibreVNADriver::LibreVNADriver()
|
||||
{
|
||||
connected = false;
|
||||
skipOwnPacketHandling = false;
|
||||
SApoints = 0;
|
||||
}
|
||||
|
||||
std::set<DeviceDriver::Flag> LibreVNADriver::getFlags()
|
||||
{
|
||||
std::set<DeviceDriver::Flag> ret;
|
||||
if(lastStatus.extRefInUse) {
|
||||
ret.insert(Flag::ExtRef);
|
||||
}
|
||||
if(!lastStatus.source_locked || !lastStatus.LO1_locked) {
|
||||
ret.insert(Flag::Unlocked);
|
||||
}
|
||||
if(lastStatus.unlevel) {
|
||||
ret.insert(Flag::Unlevel);
|
||||
}
|
||||
if(lastStatus.ADC_overload) {
|
||||
ret.insert(Flag::Overload);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString LibreVNADriver::getStatus()
|
||||
{
|
||||
QString ret;
|
||||
ret.append("HW Rev.");
|
||||
ret.append(info.hardware_version);
|
||||
ret.append(" FW "+info.firmware_version);
|
||||
ret.append(" Temps: "+QString::number(lastStatus.temp_source)+"°C/"+QString::number(lastStatus.temp_LO1)+"°C/"+QString::number(lastStatus.temp_MCU)+"°C");
|
||||
ret.append(" Reference:");
|
||||
if(lastStatus.extRefInUse) {
|
||||
ret.append("External");
|
||||
} else {
|
||||
ret.append("Internal");
|
||||
if(lastStatus.extRefAvailable) {
|
||||
ret.append(" (External available)");
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<Savable::SettingDescription> LibreVNADriver::driverSpecificSettings()
|
||||
{
|
||||
std::vector<Savable::SettingDescription> ret;
|
||||
ret.push_back(Savable::SettingDescription(&captureRawReceiverValues, "captureRawReceiverValues", false));
|
||||
ret.push_back(Savable::SettingDescription(&SASignalID, "signalID", true));
|
||||
ret.push_back(Savable::SettingDescription(&VNASuppressInvalidPeaks, "suppressInvalidPeaks", true));
|
||||
ret.push_back(Savable::SettingDescription(&VNAAdjustPowerLevel, "adjustPowerLevel", false));
|
||||
ret.push_back(Savable::SettingDescription(&SAUseDFT, "useDFT", true));
|
||||
ret.push_back(Savable::SettingDescription(&SARBWLimitForDFT, "RBWlimitDFT", 3000));
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<QAction *> LibreVNADriver::driverSpecificActions()
|
||||
{
|
||||
// TODO
|
||||
return std::vector<QAction*>();
|
||||
}
|
||||
|
||||
QStringList LibreVNADriver::availableVNAMeasurements()
|
||||
{
|
||||
QStringList ret;
|
||||
for(unsigned int i=1;i<=info.Limits.VNA.ports;i++) {
|
||||
for(unsigned int j=1;j<=info.Limits.VNA.ports;j++) {
|
||||
ret.push_back("S"+QString::number(i)+QString::number(j));
|
||||
}
|
||||
}
|
||||
|
||||
if(captureRawReceiverValues) {
|
||||
for(unsigned int i=1;i<=info.Limits.VNA.ports;i++) {
|
||||
for(unsigned int j=0;j<info.Limits.VNA.ports;j++) {
|
||||
ret.push_back("RawPort"+QString::number(i)+"Stage"+QString::number(j));
|
||||
ret.push_back("RawPort"+QString::number(i)+"Stage"+QString::number(j)+"Ref");
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool LibreVNADriver::setVNA(const DeviceDriver::VNASettings &s, std::function<void (bool)> cb)
|
||||
{
|
||||
if(!supports(Feature::VNA)) {
|
||||
return false;
|
||||
}
|
||||
if(s.excitedPorts.size() == 0) {
|
||||
return setIdle(cb);
|
||||
}
|
||||
|
||||
// create port->stage mapping
|
||||
portStageMapping.clear();
|
||||
for(unsigned int i=0;i<s.excitedPorts.size();i++) {
|
||||
portStageMapping[s.excitedPorts[i]] = i;
|
||||
}
|
||||
|
||||
Protocol::PacketInfo p = {};
|
||||
p.type = Protocol::PacketType::SweepSettings;
|
||||
p.settings.f_start = s.freqStart;
|
||||
p.settings.f_stop = s.freqStop;
|
||||
p.settings.points = s.points;
|
||||
p.settings.if_bandwidth = s.IFBW;
|
||||
p.settings.cdbm_excitation_start = s.dBmStart * 100;
|
||||
p.settings.cdbm_excitation_stop = s.dBmStop * 100;
|
||||
p.settings.stages = s.excitedPorts.size() - 1;
|
||||
p.settings.suppressPeaks = VNASuppressInvalidPeaks ? 1 : 0;
|
||||
p.settings.fixedPowerSetting = VNAAdjustPowerLevel || s.dBmStart != s.dBmStop ? 0 : 1;
|
||||
p.settings.logSweep = s.logSweep ? 1 : 0;
|
||||
|
||||
zerospan = (s.freqStart == s.freqStop) && (s.dBmStart == s.dBmStop);
|
||||
p.settings.port1Stage = find(s.excitedPorts.begin(), s.excitedPorts.end(), 0) - s.excitedPorts.begin();
|
||||
p.settings.port2Stage = find(s.excitedPorts.begin(), s.excitedPorts.end(), 1) - s.excitedPorts.begin();
|
||||
p.settings.syncMode = 0;
|
||||
p.settings.syncMaster = 0;
|
||||
|
||||
return SendPacket(p, [=](TransmissionResult r){
|
||||
if(cb) {
|
||||
cb(r == TransmissionResult::Ack);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
QStringList LibreVNADriver::availableSAMeasurements()
|
||||
{
|
||||
QStringList ret;
|
||||
for(unsigned int i=1;i<=info.Limits.SA.ports;i++) {
|
||||
ret.push_back("PORT"+QString::number(i));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool LibreVNADriver::setSA(const DeviceDriver::SASettings &s, std::function<void (bool)> cb)
|
||||
{
|
||||
if(!supports(Feature::SA)) {
|
||||
return false;
|
||||
}
|
||||
zerospan = s.freqStart == s.freqStop;
|
||||
|
||||
Protocol::PacketInfo p = {};
|
||||
p.spectrumSettings.f_start = s.freqStart;
|
||||
p.spectrumSettings.f_stop = s.freqStop;
|
||||
|
||||
constexpr unsigned int maxSApoints = 1001;
|
||||
if(s.freqStop - s.freqStart >= maxSApoints || s.freqStop - s.freqStart <= 0) {
|
||||
SApoints = maxSApoints;
|
||||
} else {
|
||||
SApoints = s.freqStop - s.freqStart + 1;
|
||||
}
|
||||
|
||||
p.spectrumSettings.pointNum = SApoints;
|
||||
p.spectrumSettings.RBW = s.RBW;
|
||||
p.spectrumSettings.WindowType = (int) s.window;
|
||||
p.spectrumSettings.SignalID = SASignalID ? 1 : 0;
|
||||
p.spectrumSettings.Detector = (int) s.detector;
|
||||
p.spectrumSettings.UseDFT = 0;
|
||||
if(!s.trackingGenerator && SAUseDFT && s.RBW <= SARBWLimitForDFT) {
|
||||
p.spectrumSettings.UseDFT = 1;
|
||||
}
|
||||
p.spectrumSettings.applyReceiverCorrection = 1;
|
||||
p.spectrumSettings.trackingGeneratorOffset = s.trackingOffset;
|
||||
p.spectrumSettings.trackingPower = s.trackingPower;
|
||||
|
||||
p.spectrumSettings.trackingGenerator = s.trackingGenerator ? 1 : 0;
|
||||
p.spectrumSettings.trackingGeneratorPort = s.trackingPort;
|
||||
p.spectrumSettings.syncMode = 0;
|
||||
p.spectrumSettings.syncMaster = 0;
|
||||
return SendPacket(p, [=](TransmissionResult r){
|
||||
if(cb) {
|
||||
cb(r == TransmissionResult::Ack);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
QStringList LibreVNADriver::availableSGPorts()
|
||||
{
|
||||
QStringList ret;
|
||||
for(unsigned int i=1;i<info.Limits.Generator.ports;i++) {
|
||||
ret.push_back("PORT"+QString::number(i));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool LibreVNADriver::setSG(const DeviceDriver::SGSettings &s)
|
||||
{
|
||||
Protocol::PacketInfo p = {};
|
||||
p.type = Protocol::PacketType::Generator;
|
||||
p.generator.frequency = s.freq;
|
||||
p.generator.cdbm_level = s.dBm * 100;
|
||||
p.generator.activePort = s.port;
|
||||
p.generator.applyAmplitudeCorrection = true;
|
||||
return SendPacket(p);
|
||||
}
|
||||
|
||||
bool LibreVNADriver::setIdle(std::function<void (bool)> cb)
|
||||
{
|
||||
Protocol::PacketInfo p;
|
||||
p.type = Protocol::PacketType::SetIdle;
|
||||
return SendPacket(p, [=](TransmissionResult res) {
|
||||
if(cb) {
|
||||
cb(res == TransmissionResult::Ack);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void LibreVNADriver::handleReceivedPacket(const Protocol::PacketInfo &packet)
|
||||
{
|
||||
emit passOnReceivedPacket(packet);
|
||||
|
||||
if(skipOwnPacketHandling) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch(packet.type) {
|
||||
case Protocol::PacketType::DeviceInfo:
|
||||
// TODO check protocol version
|
||||
info.firmware_version = QString::number(packet.info.FW_major)+"."+QString::number(packet.info.FW_minor)+"."+QString::number(packet.info.FW_patch);
|
||||
info.hardware_version = QString::number(packet.info.hardware_version)+QString(packet.info.HW_Revision);
|
||||
info.supportedFeatures = {
|
||||
Feature::VNA, Feature::VNAFrequencySweep, Feature::VNALogSweep, Feature::VNAPowerSweep, Feature::VNAZeroSpan,
|
||||
Feature::Generator,
|
||||
Feature::SA, Feature::SATrackingGenerator, Feature::SATrackingOffset,
|
||||
Feature::ExtRefIn, Feature::ExtRefOut,
|
||||
};
|
||||
info.Limits.VNA.ports = 2;
|
||||
info.Limits.VNA.minFreq = packet.info.limits_minFreq;
|
||||
info.Limits.VNA.maxFreq = packet.info.limits_maxFreq; // TODO check if harmonic mixing is enabled
|
||||
info.Limits.VNA.maxPoints = packet.info.limits_maxPoints;
|
||||
info.Limits.VNA.minIFBW = packet.info.limits_minIFBW;
|
||||
info.Limits.VNA.maxIFBW = packet.info.limits_maxIFBW;
|
||||
info.Limits.VNA.mindBm = (double) packet.info.limits_cdbm_min / 100;
|
||||
info.Limits.VNA.maxdBm = (double) packet.info.limits_cdbm_max / 100;
|
||||
|
||||
info.Limits.Generator.ports = 2;
|
||||
info.Limits.Generator.minFreq = packet.info.limits_minFreq;
|
||||
info.Limits.Generator.maxFreq = packet.info.limits_maxFreq;
|
||||
info.Limits.Generator.mindBm = (double) packet.info.limits_cdbm_min / 100;
|
||||
info.Limits.Generator.maxdBm = (double) packet.info.limits_cdbm_max / 100;
|
||||
|
||||
info.Limits.SA.ports = 2;
|
||||
info.Limits.SA.minFreq = packet.info.limits_minFreq;
|
||||
info.Limits.SA.maxFreq = packet.info.limits_maxFreq;
|
||||
info.Limits.SA.minRBW = packet.info.limits_minRBW;
|
||||
info.Limits.SA.maxRBW = packet.info.limits_maxRBW;
|
||||
info.Limits.SA.mindBm = (double) packet.info.limits_cdbm_min / 100;
|
||||
info.Limits.SA.maxdBm = (double) packet.info.limits_cdbm_max / 100;
|
||||
emit InfoUpdated();
|
||||
break;
|
||||
case Protocol::PacketType::DeviceStatusV1:
|
||||
lastStatus = packet.statusV1;
|
||||
emit StatusUpdated();
|
||||
break;
|
||||
case Protocol::PacketType::VNADatapoint: {
|
||||
VNAMeasurement m;
|
||||
Protocol::VNADatapoint<32> *res = packet.VNAdatapoint;
|
||||
m.pointNum = res->pointNum;
|
||||
m.Z0 = 50.0;
|
||||
if(zerospan) {
|
||||
m.us = res->us;
|
||||
} else {
|
||||
m.frequency = res->frequency;
|
||||
m.dBm = (double) res->cdBm / 100;
|
||||
}
|
||||
for(auto map : portStageMapping) {
|
||||
// map.first is the port (starts at zero)
|
||||
// map.second is the stage at which this port had the stimulus (starts at zero)
|
||||
complex<double> ref = res->getValue(map.second, map.first, true);
|
||||
for(unsigned int i=0;i<info.Limits.VNA.ports;i++) {
|
||||
complex<double> input = res->getValue(map.second, i, false);
|
||||
if(!std::isnan(ref.real()) && !std::isnan(input.real())) {
|
||||
// got both required measurements
|
||||
QString name = "S"+QString::number(i+1)+QString::number(map.first+1);
|
||||
m.measurements[name] = input / ref;
|
||||
}
|
||||
if(captureRawReceiverValues) {
|
||||
QString name = "RawPort"+QString::number(i+1)+"Stage"+QString::number(map.first);
|
||||
m.measurements[name] = input;
|
||||
name = "RawPort"+QString::number(i+1)+"Stage"+QString::number(map.first)+"Ref";
|
||||
m.measurements[name] = res->getValue(map.second, i, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
delete res;
|
||||
emit VNAmeasurementReceived(m);
|
||||
}
|
||||
break;
|
||||
case Protocol::PacketType::SpectrumAnalyzerResult: {
|
||||
SAMeasurement m;
|
||||
m.pointNum = packet.spectrumResult.pointNum;
|
||||
if(zerospan) {
|
||||
m.us = packet.spectrumResult.us;
|
||||
} else {
|
||||
m.frequency = packet.spectrumResult.frequency;
|
||||
}
|
||||
m.measurements["PORT1"] = packet.spectrumResult.port1;
|
||||
m.measurements["PORT2"] = packet.spectrumResult.port2;
|
||||
emit SAmeasurementReceived(m);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool LibreVNADriver::sendWithoutPayload(Protocol::PacketType type, std::function<void(TransmissionResult)> cb)
|
||||
{
|
||||
Protocol::PacketInfo p;
|
||||
p.type = type;
|
||||
return SendPacket(p, cb);
|
||||
}
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
#include "../../VNA_embedded/Application/Communication/Protocol.hpp"
|
||||
|
||||
#include <functional>
|
||||
|
||||
class LibreVNADriver : public DeviceDriver
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -19,11 +21,188 @@ public:
|
||||
|
||||
LibreVNADriver();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Returns the serial number of the connected device
|
||||
* @return Serial number of connected device (empty string if no device is connected)
|
||||
*/
|
||||
virtual QString getSerial() override {return serial;}
|
||||
|
||||
/**
|
||||
* @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() override {return info;}
|
||||
|
||||
/**
|
||||
* @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() override;
|
||||
|
||||
/**
|
||||
* @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() override;
|
||||
|
||||
/**
|
||||
* @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::vector<Savable::SettingDescription> driverSpecificSettings() override;
|
||||
|
||||
/**
|
||||
* @brief Return driver specific actions.
|
||||
*
|
||||
* The returned actions will be appended to the device menu.
|
||||
*
|
||||
* @return List of actions
|
||||
*/
|
||||
virtual std::vector<QAction*> driverSpecificActions() override;
|
||||
|
||||
/**
|
||||
* @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() override;
|
||||
|
||||
/**
|
||||
* @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) override;
|
||||
|
||||
/**
|
||||
* @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() override;
|
||||
/**
|
||||
* @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) override;
|
||||
|
||||
/**
|
||||
* @brief Returns the number of points in one spectrum analyzer sweep (as configured by the last setSA() call)
|
||||
* @return Number of points in the sweep
|
||||
*/
|
||||
virtual unsigned int getSApoints() {return SApoints;}
|
||||
|
||||
/**
|
||||
* @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() override;
|
||||
/**
|
||||
* @brief Configures the generator
|
||||
* @param s Generator settings
|
||||
* @return true if configuration successful, false otherwise
|
||||
*/
|
||||
virtual bool setSG(const SGSettings &s) override;
|
||||
|
||||
/**
|
||||
* @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) override;
|
||||
|
||||
/**
|
||||
* @brief Returns the available options for the external reference input
|
||||
* @return External reference input options
|
||||
*/
|
||||
virtual QStringList availableExtRefInSettings() override;
|
||||
|
||||
/**
|
||||
* @brief Returns the available options for the external reference output
|
||||
* @return External reference output options
|
||||
*/
|
||||
virtual QStringList availableExtRefOutSettings() override;
|
||||
|
||||
/**
|
||||
* @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) override;
|
||||
|
||||
public:
|
||||
signals:
|
||||
// Required for the compound device driver
|
||||
void passOnReceivedPacket(const Protocol::PacketInfo& packet);
|
||||
public:
|
||||
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;
|
||||
|
||||
protected:
|
||||
signals:
|
||||
void receivedAnswer(TransmissionResult result);
|
||||
void receivedPacket(const Protocol::PacketInfo& packet);
|
||||
|
||||
protected slots:
|
||||
void handleReceivedPacket(const Protocol::PacketInfo& packet);
|
||||
protected:
|
||||
bool sendWithoutPayload(Protocol::PacketType type, std::function<void(TransmissionResult)> cb = nullptr);
|
||||
|
||||
bool connected;
|
||||
QString serial;
|
||||
Info info;
|
||||
|
||||
Protocol::DeviceStatusV1 lastStatus;
|
||||
|
||||
bool skipOwnPacketHandling;
|
||||
bool zerospan;
|
||||
unsigned int SApoints;
|
||||
|
||||
std::map<int, int> portStageMapping; // maps from excitedPort (count starts at zero) to stage (count starts at zero)
|
||||
|
||||
// Driver specific settings
|
||||
bool captureRawReceiverValues;
|
||||
bool SASignalID;
|
||||
bool SAUseDFT;
|
||||
double SARBWLimitForDFT;
|
||||
bool VNASuppressInvalidPeaks;
|
||||
bool VNAAdjustPowerLevel;
|
||||
};
|
||||
|
||||
#endif // LIBREVNADRIVER_H
|
||||
|
@ -0,0 +1,431 @@
|
||||
#include "librevnausbdriver.h"
|
||||
|
||||
#include "CustomWidgets/informationbox.h"
|
||||
#include "deviceusblog.h"
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
using namespace std;
|
||||
|
||||
using USBID = struct {
|
||||
int VID;
|
||||
int PID;
|
||||
};
|
||||
static constexpr USBID IDs[] = {
|
||||
{0x0483, 0x564e},
|
||||
{0x0483, 0x4121},
|
||||
};
|
||||
|
||||
USBInBuffer::USBInBuffer(libusb_device_handle *handle, unsigned char endpoint, int buffer_size) :
|
||||
buffer_size(buffer_size),
|
||||
received_size(0),
|
||||
inCallback(false),
|
||||
cancelling(false)
|
||||
{
|
||||
buffer = new unsigned char[buffer_size];
|
||||
memset(buffer, 0, buffer_size);
|
||||
transfer = libusb_alloc_transfer(0);
|
||||
libusb_fill_bulk_transfer(transfer, handle, endpoint, buffer, buffer_size, CallbackTrampoline, this, 0);
|
||||
libusb_submit_transfer(transfer);
|
||||
}
|
||||
|
||||
USBInBuffer::~USBInBuffer()
|
||||
{
|
||||
if(transfer) {
|
||||
cancelling = true;
|
||||
libusb_cancel_transfer(transfer);
|
||||
// wait for cancellation to complete
|
||||
mutex mtx;
|
||||
unique_lock<mutex> lck(mtx);
|
||||
using namespace std::chrono_literals;
|
||||
if(cv.wait_for(lck, 100ms) == cv_status::timeout) {
|
||||
qWarning() << "Timed out waiting for mutex acquisition during disconnect";
|
||||
}
|
||||
}
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
void USBInBuffer::removeBytes(int handled_bytes)
|
||||
{
|
||||
if(!inCallback) {
|
||||
throw runtime_error("Removing of bytes is only allowed from within receive callback");
|
||||
}
|
||||
if(handled_bytes >= received_size) {
|
||||
received_size = 0;
|
||||
} else {
|
||||
// not removing all bytes, have to move remaining data to the beginning of the buffer
|
||||
memmove(buffer, &buffer[handled_bytes], received_size - handled_bytes);
|
||||
received_size -= handled_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
int USBInBuffer::getReceived() const
|
||||
{
|
||||
return received_size;
|
||||
}
|
||||
|
||||
void USBInBuffer::Callback(libusb_transfer *transfer)
|
||||
{
|
||||
if(cancelling || (transfer->status == LIBUSB_TRANSFER_CANCELLED)) {
|
||||
// destructor called, do not resubmit
|
||||
libusb_free_transfer(transfer);
|
||||
this->transfer = nullptr;
|
||||
cv.notify_all();
|
||||
return;
|
||||
}
|
||||
switch(transfer->status) {
|
||||
case LIBUSB_TRANSFER_COMPLETED:
|
||||
received_size += transfer->actual_length;
|
||||
inCallback = true;
|
||||
emit DataReceived();
|
||||
inCallback = false;
|
||||
break;
|
||||
case LIBUSB_TRANSFER_NO_DEVICE:
|
||||
qCritical() << "LIBUSB_TRANSFER_NO_DEVICE";
|
||||
libusb_free_transfer(transfer);
|
||||
return;
|
||||
case LIBUSB_TRANSFER_ERROR:
|
||||
case LIBUSB_TRANSFER_OVERFLOW:
|
||||
case LIBUSB_TRANSFER_STALL:
|
||||
qCritical() << "LIBUSB_ERROR" << transfer->status;
|
||||
libusb_free_transfer(transfer);
|
||||
this->transfer = nullptr;
|
||||
emit TransferError();
|
||||
return;
|
||||
break;
|
||||
case LIBUSB_TRANSFER_TIMED_OUT:
|
||||
// nothing to do
|
||||
break;
|
||||
case LIBUSB_TRANSFER_CANCELLED:
|
||||
// already handled before switch-case
|
||||
break;
|
||||
}
|
||||
// Resubmit the transfer
|
||||
transfer->buffer = &buffer[received_size];
|
||||
transfer->length = buffer_size - received_size;
|
||||
libusb_submit_transfer(transfer);
|
||||
}
|
||||
|
||||
void USBInBuffer::CallbackTrampoline(libusb_transfer *transfer)
|
||||
{
|
||||
auto usb = (USBInBuffer*) transfer->user_data;
|
||||
usb->Callback(transfer);
|
||||
}
|
||||
|
||||
uint8_t *USBInBuffer::getBuffer() const
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
|
||||
LibreVNAUSBDriver::LibreVNAUSBDriver()
|
||||
: LibreVNADriver()
|
||||
{
|
||||
connected = false;
|
||||
m_handle = nullptr;
|
||||
m_context = nullptr;
|
||||
dataBuffer = nullptr;
|
||||
logBuffer = nullptr;
|
||||
m_receiveThread = nullptr;
|
||||
}
|
||||
|
||||
QString LibreVNAUSBDriver::getDriverName()
|
||||
{
|
||||
return "LibreVNA/USB";
|
||||
}
|
||||
|
||||
std::set<QString> LibreVNAUSBDriver::GetAvailableDevices()
|
||||
{
|
||||
std::set<QString> serials;
|
||||
|
||||
libusb_context *ctx;
|
||||
libusb_init(&ctx);
|
||||
#if LIBUSB_API_VERSION >= 0x01000106
|
||||
libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO);
|
||||
#endif
|
||||
|
||||
SearchDevices([&serials](libusb_device_handle *, QString serial) -> bool {
|
||||
serials.insert(serial);
|
||||
return true;
|
||||
}, ctx, true);
|
||||
|
||||
libusb_exit(ctx);
|
||||
|
||||
return serials;
|
||||
}
|
||||
|
||||
bool LibreVNAUSBDriver::connectTo(QString serial)
|
||||
{
|
||||
if(connected) {
|
||||
disconnect();
|
||||
}
|
||||
|
||||
// info = defaultInfo;
|
||||
// status = {};
|
||||
|
||||
m_handle = nullptr;
|
||||
// infoValid = false;
|
||||
libusb_init(&m_context);
|
||||
#if LIBUSB_API_VERSION >= 0x01000106
|
||||
libusb_set_option(m_context, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO);
|
||||
#endif
|
||||
|
||||
SearchDevices([=](libusb_device_handle *handle, QString found_serial) -> bool {
|
||||
if(serial.isEmpty() || serial == found_serial) {
|
||||
// accept connection to this device
|
||||
this->serial = found_serial;
|
||||
m_handle = handle;
|
||||
// abort device search
|
||||
return false;
|
||||
} else {
|
||||
// not the requested device, continue search
|
||||
return true;
|
||||
}
|
||||
}, m_context, false);
|
||||
|
||||
if(!m_handle) {
|
||||
QString message = "No device found";
|
||||
InformationBox::ShowError("Error opening device", message);
|
||||
libusb_exit(m_context);
|
||||
throw std::runtime_error(message.toStdString());
|
||||
}
|
||||
|
||||
// Found the correct device, now connect
|
||||
/* claim the interface */
|
||||
int ret = libusb_claim_interface(m_handle, 0);
|
||||
if (ret < 0) {
|
||||
libusb_close(m_handle);
|
||||
/* Failed to open */
|
||||
QString message = "Failed to claim interface: \"";
|
||||
message.append(libusb_strerror((libusb_error) ret));
|
||||
message.append("\" Maybe you are already connected to this device?");
|
||||
qWarning() << message;
|
||||
InformationBox::ShowError("Error opening device", message);
|
||||
libusb_exit(m_context);
|
||||
throw std::runtime_error(message.toStdString());
|
||||
}
|
||||
qInfo() << "USB connection established" << flush;
|
||||
connected = true;
|
||||
m_receiveThread = new std::thread(&LibreVNAUSBDriver::USBHandleThread, this);
|
||||
dataBuffer = new USBInBuffer(m_handle, EP_Data_In_Addr, 65536);
|
||||
logBuffer = new USBInBuffer(m_handle, EP_Log_In_Addr, 65536);
|
||||
connect(dataBuffer, &USBInBuffer::DataReceived, this, &LibreVNAUSBDriver::ReceivedData, Qt::DirectConnection);
|
||||
connect(dataBuffer, &USBInBuffer::TransferError, this, &LibreVNAUSBDriver::ConnectionLost);
|
||||
connect(logBuffer, &USBInBuffer::DataReceived, this, &LibreVNAUSBDriver::ReceivedLog, Qt::DirectConnection);
|
||||
connect(&transmissionTimer, &QTimer::timeout, this, &LibreVNAUSBDriver::transmissionTimeout);
|
||||
connect(this, &LibreVNAUSBDriver::receivedAnswer, this, &LibreVNAUSBDriver::transmissionFinished, Qt::QueuedConnection);
|
||||
connect(this, &LibreVNAUSBDriver::receivedPacket, this, &LibreVNAUSBDriver::handleReceivedPacket, Qt::QueuedConnection);
|
||||
transmissionTimer.setSingleShot(true);
|
||||
transmissionActive = false;
|
||||
|
||||
sendWithoutPayload(Protocol::PacketType::RequestDeviceInfo);
|
||||
sendWithoutPayload(Protocol::PacketType::RequestDeviceStatus);
|
||||
return true;
|
||||
}
|
||||
|
||||
void LibreVNAUSBDriver::disconnect()
|
||||
{
|
||||
if(connected) {
|
||||
setIdle();
|
||||
delete dataBuffer;
|
||||
delete logBuffer;
|
||||
connected = false;
|
||||
serial = "";
|
||||
for (int if_num = 0; if_num < 1; if_num++) {
|
||||
int ret = libusb_release_interface(m_handle, if_num);
|
||||
if (ret < 0) {
|
||||
qCritical() << "Error releasing interface" << libusb_error_name(ret);
|
||||
}
|
||||
}
|
||||
libusb_release_interface(m_handle, 0);
|
||||
libusb_close(m_handle);
|
||||
m_receiveThread->join();
|
||||
libusb_exit(m_context);
|
||||
delete m_receiveThread;
|
||||
m_handle = nullptr;
|
||||
m_context = nullptr;
|
||||
m_receiveThread = nullptr;
|
||||
dataBuffer = nullptr;
|
||||
logBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void LibreVNAUSBDriver::ReceivedData()
|
||||
{
|
||||
Protocol::PacketInfo packet;
|
||||
uint16_t handled_len;
|
||||
// qDebug() << "Received data";
|
||||
do {
|
||||
// qDebug() << "Decoding" << dataBuffer->getReceived() << "Bytes";
|
||||
handled_len = Protocol::DecodeBuffer(dataBuffer->getBuffer(), dataBuffer->getReceived(), &packet);
|
||||
// qDebug() << "Handled" << handled_len << "Bytes, type:" << (int) packet.type;
|
||||
if(handled_len > 0) {
|
||||
auto &log = DeviceUSBLog::getInstance();
|
||||
if(packet.type != Protocol::PacketType::None) {
|
||||
log.addPacket(packet, serial);
|
||||
} else {
|
||||
log.addInvalidBytes(dataBuffer->getBuffer(), handled_len, serial);
|
||||
}
|
||||
}
|
||||
dataBuffer->removeBytes(handled_len);
|
||||
switch(packet.type) {
|
||||
case Protocol::PacketType::Ack:
|
||||
emit receivedAnswer(TransmissionResult::Ack);
|
||||
break;
|
||||
case Protocol::PacketType::Nack:
|
||||
emit receivedAnswer(TransmissionResult::Nack);
|
||||
break;
|
||||
default:
|
||||
// pass on to LibreVNADriver class
|
||||
emit receivedPacket(packet);
|
||||
break;
|
||||
}
|
||||
} while (handled_len > 0);
|
||||
}
|
||||
|
||||
void LibreVNAUSBDriver::ReceivedLog()
|
||||
{
|
||||
uint16_t handled_len;
|
||||
do {
|
||||
handled_len = 0;
|
||||
auto firstLinebreak = (uint8_t*) memchr(logBuffer->getBuffer(), '\n', logBuffer->getReceived());
|
||||
if(firstLinebreak) {
|
||||
handled_len = firstLinebreak - logBuffer->getBuffer();
|
||||
auto line = QString::fromLatin1((const char*) logBuffer->getBuffer(), handled_len - 1);
|
||||
emit LogLineReceived(line);
|
||||
logBuffer->removeBytes(handled_len + 1);
|
||||
}
|
||||
} while(handled_len > 0);
|
||||
}
|
||||
|
||||
void LibreVNAUSBDriver::transmissionFinished(LibreVNADriver::TransmissionResult result)
|
||||
{
|
||||
lock_guard<mutex> lock(transmissionMutex);
|
||||
// remove transmitted packet
|
||||
// qDebug() << "Transmission finsished (" << result << "), queue at " << transmissionQueue.size() << " Outstanding ACKs:"<<outstandingAckCount;
|
||||
if(transmissionQueue.empty()) {
|
||||
qWarning() << "transmissionFinished with empty transmission queue, stray Ack? Result:" << result;
|
||||
return;
|
||||
}
|
||||
auto t = transmissionQueue.dequeue();
|
||||
if(result == TransmissionResult::Timeout) {
|
||||
qWarning() << "transmissionFinished with timeout, packettype:" << (int) t.packet.type << "Device:" << serial;
|
||||
}
|
||||
if(result == TransmissionResult::Nack) {
|
||||
qWarning() << "transmissionFinished with NACK";
|
||||
}
|
||||
if(t.callback) {
|
||||
t.callback(result);
|
||||
}
|
||||
transmissionTimer.stop();
|
||||
bool success = false;
|
||||
while(!transmissionQueue.isEmpty() && !success) {
|
||||
success = startNextTransmission();
|
||||
if(!success) {
|
||||
// failed to send this packet
|
||||
auto t = transmissionQueue.dequeue();
|
||||
if(t.callback) {
|
||||
t.callback(TransmissionResult::InternalError);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(transmissionQueue.isEmpty()) {
|
||||
transmissionActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool LibreVNAUSBDriver::SendPacket(const Protocol::PacketInfo &packet, std::function<void (LibreVNADriver::TransmissionResult)> cb, unsigned int timeout)
|
||||
{
|
||||
Transmission t;
|
||||
t.packet = packet;
|
||||
t.timeout = timeout;
|
||||
t.callback = cb;
|
||||
lock_guard<mutex> lock(transmissionMutex);
|
||||
transmissionQueue.enqueue(t);
|
||||
// qDebug() << "Enqueued packet, queue at " << transmissionQueue.size();
|
||||
if(!transmissionActive) {
|
||||
startNextTransmission();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void LibreVNAUSBDriver::USBHandleThread()
|
||||
{
|
||||
qDebug() << "Receive thread started";
|
||||
while (connected) {
|
||||
libusb_handle_events(m_context);
|
||||
}
|
||||
qDebug() << "Disconnected, receive thread exiting";
|
||||
}
|
||||
|
||||
void LibreVNAUSBDriver::SearchDevices(std::function<bool (libusb_device_handle *, QString)> foundCallback, libusb_context *context, bool ignoreOpenError)
|
||||
{
|
||||
libusb_device **devList;
|
||||
auto ndevices = libusb_get_device_list(context, &devList);
|
||||
|
||||
for (ssize_t idx = 0; idx < ndevices; idx++) {
|
||||
int ret;
|
||||
libusb_device *device = devList[idx];
|
||||
libusb_device_descriptor desc = {};
|
||||
|
||||
ret = libusb_get_device_descriptor(device, &desc);
|
||||
if (ret) {
|
||||
/* some error occured */
|
||||
qCritical() << "Failed to get device descriptor: "
|
||||
<< libusb_strerror((libusb_error) ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool correctID = false;
|
||||
int numIDs = sizeof(IDs)/sizeof(IDs[0]);
|
||||
for(int i=0;i<numIDs;i++) {
|
||||
if(desc.idVendor == IDs[i].VID && desc.idProduct == IDs[i].PID) {
|
||||
correctID = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!correctID) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Try to open the device */
|
||||
libusb_device_handle *handle = nullptr;
|
||||
ret = libusb_open(device, &handle);
|
||||
if (ret) {
|
||||
qDebug() << libusb_strerror((enum libusb_error) ret);
|
||||
/* Failed to open */
|
||||
if(!ignoreOpenError) {
|
||||
QString message = "Found potential device but failed to open usb connection: \"";
|
||||
message.append(libusb_strerror((libusb_error) ret));
|
||||
message.append("\" On Linux this is most likely caused by a missing udev rule. "
|
||||
"On Windows this most likely means that you are already connected to "
|
||||
"this device (is another instance of the application already runnning?)");
|
||||
qWarning() << message;
|
||||
InformationBox::ShowError("Error opening device", message);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
char c_product[256];
|
||||
char c_serial[256];
|
||||
libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber,
|
||||
(unsigned char*) c_serial, sizeof(c_serial));
|
||||
ret = libusb_get_string_descriptor_ascii(handle, desc.iProduct,
|
||||
(unsigned char*) c_product, sizeof(c_product));
|
||||
if (ret > 0) {
|
||||
/* managed to read the product string */
|
||||
QString product(c_product);
|
||||
if (product == "VNA") {
|
||||
// this is a match
|
||||
if(!foundCallback(handle, QString(c_serial))) {
|
||||
// abort search
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qWarning() << "Failed to get product descriptor: "
|
||||
<< libusb_strerror((libusb_error) ret);
|
||||
}
|
||||
libusb_close(handle);
|
||||
}
|
||||
libusb_free_device_list(devList, 1);
|
||||
}
|
113
Software/PC_Application/LibreVNA-GUI/Device/librevnausbdriver.h
Normal file
113
Software/PC_Application/LibreVNA-GUI/Device/librevnausbdriver.h
Normal file
@ -0,0 +1,113 @@
|
||||
#ifndef LIBREVNAUSBDRIVER_H
|
||||
#define LIBREVNAUSBDRIVER_H
|
||||
|
||||
#include "librevnadriver.h"
|
||||
|
||||
#include <libusb-1.0/libusb.h>
|
||||
#include <condition_variable>
|
||||
#include <thread>
|
||||
|
||||
#include <QQueue>
|
||||
#include <QTimer>
|
||||
|
||||
class USBInBuffer : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
USBInBuffer(libusb_device_handle *handle, unsigned char endpoint, int buffer_size);
|
||||
~USBInBuffer();
|
||||
|
||||
void removeBytes(int handled_bytes);
|
||||
int getReceived() const;
|
||||
uint8_t *getBuffer() const;
|
||||
|
||||
signals:
|
||||
void DataReceived();
|
||||
void TransferError();
|
||||
|
||||
private:
|
||||
void Callback(libusb_transfer *transfer);
|
||||
static void LIBUSB_CALL CallbackTrampoline(libusb_transfer *transfer);
|
||||
libusb_transfer *transfer;
|
||||
unsigned char *buffer;
|
||||
int buffer_size;
|
||||
int received_size;
|
||||
bool inCallback;
|
||||
bool cancelling;
|
||||
std::condition_variable cv;
|
||||
};
|
||||
|
||||
class LibreVNAUSBDriver : public LibreVNADriver
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
LibreVNAUSBDriver();
|
||||
|
||||
/**
|
||||
* @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() override;
|
||||
/**
|
||||
* @brief Lists all available devices by their serial numbers
|
||||
* @return Serial numbers of detected devices
|
||||
*/
|
||||
virtual std::set<QString> GetAvailableDevices() override;
|
||||
/**
|
||||
* @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) override;
|
||||
/**
|
||||
* @brief Disconnects from device. Has no effect if no device was connected
|
||||
*/
|
||||
virtual void disconnect() override;
|
||||
|
||||
private slots:
|
||||
void ReceivedData();
|
||||
void ReceivedLog();
|
||||
void transmissionTimeout() {
|
||||
transmissionFinished(TransmissionResult::Timeout);
|
||||
}
|
||||
void transmissionFinished(TransmissionResult result);
|
||||
private:
|
||||
static constexpr int EP_Data_Out_Addr = 0x01;
|
||||
static constexpr int EP_Data_In_Addr = 0x81;
|
||||
static constexpr int EP_Log_In_Addr = 0x82;
|
||||
|
||||
virtual bool SendPacket(const Protocol::PacketInfo& packet, std::function<void(TransmissionResult)> cb = nullptr, unsigned int timeout = 500) override;
|
||||
|
||||
void USBHandleThread();
|
||||
// foundCallback is called for every device that is found. If it returns true the search continues, otherwise it is aborted.
|
||||
// When the search is aborted the last found device is still opened
|
||||
static void SearchDevices(std::function<bool(libusb_device_handle *handle, QString getSerial)> foundCallback, libusb_context *context, bool ignoreOpenError);
|
||||
|
||||
libusb_device_handle *m_handle;
|
||||
libusb_context *m_context;
|
||||
USBInBuffer *dataBuffer;
|
||||
USBInBuffer *logBuffer;
|
||||
|
||||
class Transmission {
|
||||
public:
|
||||
Protocol::PacketInfo packet;
|
||||
unsigned int timeout;
|
||||
std::function<void(TransmissionResult)> callback;
|
||||
};
|
||||
|
||||
std::mutex transmissionMutex;
|
||||
QQueue<Transmission> transmissionQueue;
|
||||
bool startNextTransmission();
|
||||
QTimer transmissionTimer;
|
||||
bool transmissionActive;
|
||||
|
||||
std::thread *m_receiveThread;
|
||||
Protocol::DeviceInfo info;
|
||||
bool infoValid;
|
||||
union {
|
||||
Protocol::DeviceStatusV1 v1;
|
||||
} status;
|
||||
|
||||
std::mutex accessMutex;
|
||||
};
|
||||
|
||||
#endif // LIBREVNAUSBDRIVER_H
|
@ -98,7 +98,7 @@ void Generator::setupSCPI()
|
||||
}));
|
||||
add(new SCPICommand("PORT", [=](QStringList params) -> QString {
|
||||
unsigned long long newval;
|
||||
if(!SCPI::paramToULongLong(params, 0, newval) || newval > VirtualDevice::getInfo(window->getDevice()).ports) {
|
||||
if(!SCPI::paramToULongLong(params, 0, newval) || newval > DeviceDriver::getInfo(window->getDevice()).Limits.Generator.ports) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
} else {
|
||||
central->setPort(newval);
|
||||
|
@ -33,16 +33,16 @@ SignalgeneratorWidget::SignalgeneratorWidget(AppWindow *window, QWidget *parent)
|
||||
ui->steps->setPrecision(0);
|
||||
|
||||
connect(ui->frequency, &SIUnitEdit::valueChanged, [=](double newval) {
|
||||
if(newval < VirtualDevice::getInfo(window->getDevice()).Limits.minFreq) {
|
||||
newval = VirtualDevice::getInfo(window->getDevice()).Limits.minFreq;
|
||||
} else if (newval > VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq) {
|
||||
newval = VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq;
|
||||
if(newval < DeviceDriver::getInfo(window->getDevice()).Limits.Generator.minFreq) {
|
||||
newval = DeviceDriver::getInfo(window->getDevice()).Limits.Generator.minFreq;
|
||||
} else if (newval > DeviceDriver::getInfo(window->getDevice()).Limits.Generator.maxFreq) {
|
||||
newval = DeviceDriver::getInfo(window->getDevice()).Limits.Generator.maxFreq;
|
||||
}
|
||||
ui->frequency->setValueQuiet(newval);
|
||||
if (newval < ui->span->value()/2)
|
||||
ui->span->setValueQuiet(newval/2);
|
||||
if (newval + ui->span->value()/2 > VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq)
|
||||
ui->span->setValueQuiet((VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq - newval)*2);
|
||||
if (newval + ui->span->value()/2 > DeviceDriver::getInfo(window->getDevice()).Limits.Generator.maxFreq)
|
||||
ui->span->setValueQuiet((DeviceDriver::getInfo(window->getDevice()).Limits.Generator.maxFreq - newval)*2);
|
||||
newval = ui->frequency->value() - ui->span->value()/2;
|
||||
ui->current->setValueQuiet(newval);
|
||||
emit SettingsChanged();
|
||||
@ -51,8 +51,8 @@ SignalgeneratorWidget::SignalgeneratorWidget(AppWindow *window, QWidget *parent)
|
||||
connect(ui->span, &SIUnitEdit::valueChanged, [=](double newval) {
|
||||
if(newval < 0 ) {
|
||||
newval = 0;
|
||||
} else if (newval > VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq - VirtualDevice::getInfo(window->getDevice()).Limits.minFreq) {
|
||||
newval = VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq - VirtualDevice::getInfo(window->getDevice()).Limits.minFreq;
|
||||
} else if (newval > DeviceDriver::getInfo(window->getDevice()).Limits.Generator.maxFreq - DeviceDriver::getInfo(window->getDevice()).Limits.Generator.minFreq) {
|
||||
newval = DeviceDriver::getInfo(window->getDevice()).Limits.Generator.maxFreq - DeviceDriver::getInfo(window->getDevice()).Limits.Generator.minFreq;
|
||||
}
|
||||
ui->span->setValueQuiet(newval);
|
||||
|
||||
@ -61,8 +61,8 @@ SignalgeneratorWidget::SignalgeneratorWidget(AppWindow *window, QWidget *parent)
|
||||
ui->frequency->setValueQuiet(ui->span->value()/2);
|
||||
}
|
||||
newF = ui->frequency->value() + ui->span->value()/2;
|
||||
if (newF > VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq) {
|
||||
ui->frequency->setValueQuiet(VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq - ui->span->value()/2);
|
||||
if (newF > DeviceDriver::getInfo(window->getDevice()).Limits.Generator.maxFreq) {
|
||||
ui->frequency->setValueQuiet(DeviceDriver::getInfo(window->getDevice()).Limits.Generator.maxFreq - ui->span->value()/2);
|
||||
}
|
||||
|
||||
newval = ui->frequency->value() - ui->span->value()/2;
|
||||
@ -73,8 +73,8 @@ SignalgeneratorWidget::SignalgeneratorWidget(AppWindow *window, QWidget *parent)
|
||||
connect(ui->current, &SIUnitEdit::valueChanged, [=](double newval) {
|
||||
if(newval < 0 ) {
|
||||
newval = 0;
|
||||
} else if (newval > VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq - VirtualDevice::getInfo(window->getDevice()).Limits.minFreq) {
|
||||
newval = VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq - VirtualDevice::getInfo(window->getDevice()).Limits.minFreq;
|
||||
} else if (newval > DeviceDriver::getInfo(window->getDevice()).Limits.Generator.maxFreq - DeviceDriver::getInfo(window->getDevice()).Limits.Generator.minFreq) {
|
||||
newval = DeviceDriver::getInfo(window->getDevice()).Limits.Generator.maxFreq - DeviceDriver::getInfo(window->getDevice()).Limits.Generator.minFreq;
|
||||
}
|
||||
ui->current->setValueQuiet(newval);
|
||||
emit SettingsChanged();
|
||||
@ -132,9 +132,9 @@ void SignalgeneratorWidget::timerEvent(QTimerEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
VirtualDevice::SGSettings SignalgeneratorWidget::getDeviceStatus()
|
||||
DeviceDriver::SGSettings SignalgeneratorWidget::getDeviceStatus()
|
||||
{
|
||||
VirtualDevice::SGSettings s = {};
|
||||
DeviceDriver::SGSettings s = {};
|
||||
if (ui->EnabledSweep->isChecked())
|
||||
s.freq = ui->current->value();
|
||||
else
|
||||
@ -189,7 +189,7 @@ void SignalgeneratorWidget::deviceInfoUpdated()
|
||||
delete cb;
|
||||
}
|
||||
portCheckboxes.clear();
|
||||
for(unsigned int i=1;i<=VirtualDevice::getInfo(window->getDevice()).ports;i++) {
|
||||
for(unsigned int i=1;i<=DeviceDriver::getInfo(window->getDevice()).Limits.Generator.ports;i++) {
|
||||
auto cb = new QCheckBox("Port "+QString::number(i));
|
||||
ui->portBox->layout()->addWidget(cb);
|
||||
portCheckboxes.push_back(cb);
|
||||
|
@ -18,7 +18,7 @@ public:
|
||||
explicit SignalgeneratorWidget(AppWindow *window, QWidget *parent = nullptr);
|
||||
~SignalgeneratorWidget();
|
||||
|
||||
VirtualDevice::SGSettings getDeviceStatus();
|
||||
DeviceDriver::SGSettings getDeviceStatus();
|
||||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
|
||||
|
@ -32,6 +32,7 @@ HEADERS += \
|
||||
Device/deviceusblogview.h \
|
||||
Device/firmwareupdatedialog.h \
|
||||
Device/librevnadriver.h \
|
||||
Device/librevnausbdriver.h \
|
||||
Device/manualcontroldialog.h \
|
||||
Device/virtualdevice.h \
|
||||
Generator/generator.h \
|
||||
@ -176,11 +177,13 @@ SOURCES += \
|
||||
Device/compounddevice.cpp \
|
||||
Device/compounddeviceeditdialog.cpp \
|
||||
Device/device.cpp \
|
||||
Device/devicedriver.cpp \
|
||||
Device/devicelog.cpp \
|
||||
Device/deviceusblog.cpp \
|
||||
Device/deviceusblogview.cpp \
|
||||
Device/firmwareupdatedialog.cpp \
|
||||
Device/librevnadriver.cpp \
|
||||
Device/librevnausbdriver.cpp \
|
||||
Device/manualcontroldialog.cpp \
|
||||
Device/virtualdevice.cpp \
|
||||
Generator/generator.cpp \
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "Traces/Marker/markerwidget.h"
|
||||
#include "Tools/impedancematchdialog.h"
|
||||
#include "ui_main.h"
|
||||
#include "Device/virtualdevice.h"
|
||||
#include "preferences.h"
|
||||
#include "Generator/signalgenwidget.h"
|
||||
|
||||
@ -191,7 +190,7 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name)
|
||||
cbWindowType->addItem("Flat Top");
|
||||
cbWindowType->setCurrentIndex(1);
|
||||
connect(cbWindowType, qOverload<int>(&QComboBox::currentIndexChanged), [=](int index) {
|
||||
SetWindow((VirtualDevice::SASettings::Window) index);
|
||||
SetWindow((DeviceDriver::SASettings::Window) index);
|
||||
});
|
||||
tb_acq->addWidget(cbWindowType);
|
||||
|
||||
@ -204,7 +203,7 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name)
|
||||
cbDetector->addItem("Average");
|
||||
cbDetector->setCurrentIndex(0);
|
||||
connect(cbDetector, qOverload<int>(&QComboBox::currentIndexChanged), [=](int index) {
|
||||
SetDetector((VirtualDevice::SASettings::Detector) index);
|
||||
SetDetector((DeviceDriver::SASettings::Detector) index);
|
||||
});
|
||||
tb_acq->addWidget(cbDetector);
|
||||
|
||||
@ -219,10 +218,6 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name)
|
||||
connect(this, &SpectrumAnalyzer::averagingChanged, sbAverages, &QSpinBox::setValue);
|
||||
tb_acq->addWidget(sbAverages);
|
||||
|
||||
cbSignalID = new QCheckBox("Signal ID");
|
||||
connect(cbSignalID, &QCheckBox::toggled, this, &SpectrumAnalyzer::SetSignalID);
|
||||
tb_acq->addWidget(cbSignalID);
|
||||
|
||||
window->addToolBar(tb_acq);
|
||||
toolbars.insert(tb_acq);
|
||||
|
||||
@ -321,10 +316,8 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name)
|
||||
ConstrainAndUpdateFrequencies();
|
||||
SetRBW(pref.Startup.SA.RBW);
|
||||
SetAveraging(pref.Startup.SA.averaging);
|
||||
settings.points = 1001;
|
||||
SetWindow((VirtualDevice::SASettings::Window) pref.Startup.SA.window);
|
||||
SetDetector((VirtualDevice::SASettings::Detector) pref.Startup.SA.detector);
|
||||
SetSignalID(pref.Startup.SA.signalID);
|
||||
SetWindow((DeviceDriver::SASettings::Window) pref.Startup.SA.window);
|
||||
SetDetector((DeviceDriver::SASettings::Detector) pref.Startup.SA.detector);
|
||||
}
|
||||
|
||||
finalize(central);
|
||||
@ -338,7 +331,7 @@ void SpectrumAnalyzer::deactivate()
|
||||
|
||||
void SpectrumAnalyzer::initializeDevice()
|
||||
{
|
||||
connect(window->getDevice(), &VirtualDevice::SAmeasurementReceived, this, &SpectrumAnalyzer::NewDatapoint, Qt::UniqueConnection);
|
||||
connect(window->getDevice(), &DeviceDriver::SAmeasurementReceived, this, &SpectrumAnalyzer::NewDatapoint, Qt::UniqueConnection);
|
||||
|
||||
// Configure initial state of device
|
||||
SettingsChanged();
|
||||
@ -361,9 +354,8 @@ nlohmann::json SpectrumAnalyzer::toJSON()
|
||||
sweep["single"] = singleSweep;
|
||||
nlohmann::json acq;
|
||||
acq["RBW"] = settings.RBW;
|
||||
acq["window"] = WindowToString((VirtualDevice::SASettings::Window) settings.window).toStdString();
|
||||
acq["detector"] = DetectorToString((VirtualDevice::SASettings::Detector) settings.detector).toStdString();
|
||||
acq["signal ID"] = settings.signalID ? true : false;
|
||||
acq["window"] = WindowToString((DeviceDriver::SASettings::Window) settings.window).toStdString();
|
||||
acq["detector"] = DetectorToString((DeviceDriver::SASettings::Detector) settings.detector).toStdString();
|
||||
sweep["acquisition"] = acq;
|
||||
nlohmann::json tracking;
|
||||
tracking["enabled"] = settings.trackingGenerator ? true : false;
|
||||
@ -419,18 +411,17 @@ void SpectrumAnalyzer::fromJSON(nlohmann::json j)
|
||||
auto acq = sweep["acquisition"];
|
||||
SetRBW(acq.value("RBW", settings.RBW));
|
||||
auto w = WindowFromString(QString::fromStdString(acq.value("window", "")));
|
||||
if(w == VirtualDevice::SASettings::Window::Last) {
|
||||
if(w == DeviceDriver::SASettings::Window::Last) {
|
||||
// invalid, keep current value
|
||||
w = (VirtualDevice::SASettings::Window) settings.window;
|
||||
w = (DeviceDriver::SASettings::Window) settings.window;
|
||||
}
|
||||
SetWindow(w);
|
||||
auto d = DetectorFromString(QString::fromStdString(acq.value("detector", "")));
|
||||
if(d == VirtualDevice::SASettings::Detector::Last) {
|
||||
if(d == DeviceDriver::SASettings::Detector::Last) {
|
||||
// invalid, keep current value
|
||||
d = (VirtualDevice::SASettings::Detector) settings.detector;
|
||||
d = (DeviceDriver::SASettings::Detector) settings.detector;
|
||||
}
|
||||
SetDetector(d);
|
||||
SetSignalID(acq.value("signal ID", settings.signalID ? true : false));
|
||||
}
|
||||
if(sweep.contains("trackingGenerator")) {
|
||||
auto tracking = sweep["trackingGenerator"];
|
||||
@ -473,8 +464,8 @@ void SpectrumAnalyzer::fromJSON(nlohmann::json j)
|
||||
|
||||
using namespace std;
|
||||
|
||||
void SpectrumAnalyzer::NewDatapoint(VirtualDevice::SAMeasurement m)
|
||||
{
|
||||
void SpectrumAnalyzer::NewDatapoint(DeviceDriver::SAMeasurement m)
|
||||
{
|
||||
if(isActive != true) {
|
||||
return;
|
||||
}
|
||||
@ -488,11 +479,6 @@ void SpectrumAnalyzer::NewDatapoint(VirtualDevice::SAMeasurement m)
|
||||
Stop();
|
||||
}
|
||||
|
||||
if(m.pointNum >= settings.points) {
|
||||
qWarning() << "Ignoring point with too large point number (" << m.pointNum << ")";
|
||||
return;
|
||||
}
|
||||
|
||||
auto m_avg = average.process(m);
|
||||
|
||||
if(settings.freqStart == settings.freqStop) {
|
||||
@ -513,18 +499,18 @@ void SpectrumAnalyzer::NewDatapoint(VirtualDevice::SAMeasurement m)
|
||||
for(auto m : m_avg.measurements) {
|
||||
normalize.portCorrection[m.first].push_back(m.second);
|
||||
}
|
||||
if(m_avg.pointNum == settings.points - 1) {
|
||||
if(m_avg.pointNum == DeviceDriver::getActiveDriver()->getSApoints() - 1) {
|
||||
// this was the last point
|
||||
normalize.measuring = false;
|
||||
normalize.f_start = settings.freqStart;
|
||||
normalize.f_stop = settings.freqStop;
|
||||
normalize.points = settings.points;
|
||||
normalize.points = DeviceDriver::getActiveDriver()->getSApoints();
|
||||
EnableNormalization(true);
|
||||
qDebug() << "Normalization measurement complete";
|
||||
}
|
||||
}
|
||||
}
|
||||
int percentage = (((average.currentSweep() - 1) * 100) + (m_avg.pointNum + 1) * 100 / settings.points) / averages;
|
||||
int percentage = (((average.currentSweep() - 1) * 100) + (m_avg.pointNum + 1) * 100 / DeviceDriver::getActiveDriver()->getSApoints()) / averages;
|
||||
normalize.dialog.setValue(percentage);
|
||||
}
|
||||
|
||||
@ -538,7 +524,7 @@ void SpectrumAnalyzer::NewDatapoint(VirtualDevice::SAMeasurement m)
|
||||
|
||||
traceModel.addSAData(m_avg, settings);
|
||||
emit dataChanged();
|
||||
if(m_avg.pointNum == settings.points - 1) {
|
||||
if(m_avg.pointNum == DeviceDriver::getActiveDriver()->getSApoints() - 1) {
|
||||
UpdateAverageCount();
|
||||
markerModel->updateMarkers();
|
||||
}
|
||||
@ -576,14 +562,14 @@ void SpectrumAnalyzer::SetStopFreq(double freq)
|
||||
void SpectrumAnalyzer::SetCenterFreq(double freq)
|
||||
{
|
||||
auto old_span = settings.freqStop - settings.freqStart;
|
||||
if (freq - old_span / 2 <= VirtualDevice::getInfo(window->getDevice()).Limits.minFreq) {
|
||||
if (freq - old_span / 2 <= DeviceDriver::getInfo(window->getDevice()).Limits.SA.minFreq) {
|
||||
// would shift start frequency below minimum
|
||||
settings.freqStart = 0;
|
||||
settings.freqStop = 2 * freq;
|
||||
} else if(freq + old_span / 2 >= VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq) {
|
||||
} else if(freq + old_span / 2 >= DeviceDriver::getInfo(window->getDevice()).Limits.SA.maxFreq) {
|
||||
// would shift stop frequency above maximum
|
||||
settings.freqStart = 2 * freq - VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq;
|
||||
settings.freqStop = VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq;
|
||||
settings.freqStart = 2 * freq - DeviceDriver::getInfo(window->getDevice()).Limits.SA.maxFreq;
|
||||
settings.freqStop = DeviceDriver::getInfo(window->getDevice()).Limits.SA.maxFreq;
|
||||
} else {
|
||||
settings.freqStart = freq - old_span / 2;
|
||||
settings.freqStop = freq + old_span / 2;
|
||||
@ -594,14 +580,14 @@ void SpectrumAnalyzer::SetCenterFreq(double freq)
|
||||
void SpectrumAnalyzer::SetSpan(double span)
|
||||
{
|
||||
auto old_center = (settings.freqStart + settings.freqStop) / 2;
|
||||
if(old_center < VirtualDevice::getInfo(window->getDevice()).Limits.minFreq + span / 2) {
|
||||
if(old_center < DeviceDriver::getInfo(window->getDevice()).Limits.SA.minFreq + span / 2) {
|
||||
// would shift start frequency below minimum
|
||||
settings.freqStart = VirtualDevice::getInfo(window->getDevice()).Limits.minFreq;
|
||||
settings.freqStop = VirtualDevice::getInfo(window->getDevice()).Limits.minFreq + span;
|
||||
} else if(old_center > VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq - span / 2) {
|
||||
settings.freqStart = DeviceDriver::getInfo(window->getDevice()).Limits.SA.minFreq;
|
||||
settings.freqStop = DeviceDriver::getInfo(window->getDevice()).Limits.SA.minFreq + span;
|
||||
} else if(old_center > DeviceDriver::getInfo(window->getDevice()).Limits.SA.maxFreq - span / 2) {
|
||||
// would shift stop frequency above maximum
|
||||
settings.freqStart = VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq - span;
|
||||
settings.freqStop = VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq;
|
||||
settings.freqStart = DeviceDriver::getInfo(window->getDevice()).Limits.SA.maxFreq - span;
|
||||
settings.freqStop = DeviceDriver::getInfo(window->getDevice()).Limits.SA.maxFreq;
|
||||
} else {
|
||||
settings.freqStart = old_center - span / 2;
|
||||
settings.freqStop = settings.freqStart + span;
|
||||
@ -616,8 +602,8 @@ void SpectrumAnalyzer::SetFullSpan()
|
||||
settings.freqStart = pref.Acquisition.fullSpanStart;
|
||||
settings.freqStop = pref.Acquisition.fullSpanStop;
|
||||
} else {
|
||||
settings.freqStart = VirtualDevice::getInfo(window->getDevice()).Limits.minFreq;
|
||||
settings.freqStop = VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq;
|
||||
settings.freqStart = DeviceDriver::getInfo(window->getDevice()).Limits.SA.minFreq;
|
||||
settings.freqStop = DeviceDriver::getInfo(window->getDevice()).Limits.SA.maxFreq;
|
||||
}
|
||||
ConstrainAndUpdateFrequencies();
|
||||
}
|
||||
@ -664,24 +650,24 @@ void SpectrumAnalyzer::SetSingleSweep(bool single)
|
||||
|
||||
void SpectrumAnalyzer::SetRBW(double bandwidth)
|
||||
{
|
||||
if(bandwidth > VirtualDevice::getInfo(window->getDevice()).Limits.maxRBW) {
|
||||
bandwidth = VirtualDevice::getInfo(window->getDevice()).Limits.maxRBW;
|
||||
} else if(bandwidth < VirtualDevice::getInfo(window->getDevice()).Limits.minRBW) {
|
||||
bandwidth = VirtualDevice::getInfo(window->getDevice()).Limits.minRBW;
|
||||
if(bandwidth > DeviceDriver::getInfo(window->getDevice()).Limits.SA.maxRBW) {
|
||||
bandwidth = DeviceDriver::getInfo(window->getDevice()).Limits.SA.maxRBW;
|
||||
} else if(bandwidth < DeviceDriver::getInfo(window->getDevice()).Limits.SA.minRBW) {
|
||||
bandwidth = DeviceDriver::getInfo(window->getDevice()).Limits.SA.minRBW;
|
||||
}
|
||||
settings.RBW = bandwidth;
|
||||
emit RBWChanged(settings.RBW);
|
||||
SettingsChanged();
|
||||
}
|
||||
|
||||
void SpectrumAnalyzer::SetWindow(VirtualDevice::SASettings::Window w)
|
||||
void SpectrumAnalyzer::SetWindow(DeviceDriver::SASettings::Window w)
|
||||
{
|
||||
settings.window = w;
|
||||
cbWindowType->setCurrentIndex((int) w);
|
||||
SettingsChanged();
|
||||
}
|
||||
|
||||
void SpectrumAnalyzer::SetDetector(VirtualDevice::SASettings::Detector d)
|
||||
void SpectrumAnalyzer::SetDetector(DeviceDriver::SASettings::Detector d)
|
||||
{
|
||||
settings.detector = d;
|
||||
cbDetector->setCurrentIndex((int) d);
|
||||
@ -696,13 +682,6 @@ void SpectrumAnalyzer::SetAveraging(unsigned int averages)
|
||||
SettingsChanged();
|
||||
}
|
||||
|
||||
void SpectrumAnalyzer::SetSignalID(bool enabled)
|
||||
{
|
||||
settings.signalID = enabled ? 1 : 0;
|
||||
cbSignalID->setChecked(enabled);
|
||||
SettingsChanged();
|
||||
}
|
||||
|
||||
void SpectrumAnalyzer::SetTGEnabled(bool enabled)
|
||||
{
|
||||
if(enabled != settings.trackingGenerator) {
|
||||
@ -735,10 +714,10 @@ void SpectrumAnalyzer::SetTGPort(int port)
|
||||
|
||||
void SpectrumAnalyzer::SetTGLevel(double level)
|
||||
{
|
||||
if(level > VirtualDevice::getInfo(window->getDevice()).Limits.maxdBm) {
|
||||
level = VirtualDevice::getInfo(window->getDevice()).Limits.maxdBm;
|
||||
} else if(level < VirtualDevice::getInfo(window->getDevice()).Limits.mindBm) {
|
||||
level = VirtualDevice::getInfo(window->getDevice()).Limits.mindBm;
|
||||
if(level > DeviceDriver::getInfo(window->getDevice()).Limits.SA.maxdBm) {
|
||||
level = DeviceDriver::getInfo(window->getDevice()).Limits.SA.maxdBm;
|
||||
} else if(level < DeviceDriver::getInfo(window->getDevice()).Limits.SA.mindBm) {
|
||||
level = DeviceDriver::getInfo(window->getDevice()).Limits.SA.mindBm;
|
||||
}
|
||||
emit TGLevelChanged(level);
|
||||
settings.trackingPower = level * 100;
|
||||
@ -842,51 +821,47 @@ void SpectrumAnalyzer::ConfigureDevice()
|
||||
{
|
||||
if(running) {
|
||||
changingSettings = true;
|
||||
if(settings.freqStop - settings.freqStart >= 1000 || settings.freqStop - settings.freqStart <= 0) {
|
||||
settings.points = 1001;
|
||||
} else {
|
||||
settings.points = settings.freqStop - settings.freqStart + 1;
|
||||
}
|
||||
|
||||
if(settings.trackingGenerator && settings.freqStop >= 25000000) {
|
||||
// Check point spacing.
|
||||
// The highband PLL used as the tracking generator is not able to reach every frequency exactly. This
|
||||
// could lead to sharp drops in the spectrum at certain frequencies. If the span is wide enough with
|
||||
// respect to the point number, it is ensured that every displayed point has at least one sample with
|
||||
// a reachable PLL frequency in it. Display a warning message if this is not the case with the current
|
||||
// settings.
|
||||
auto pointSpacing = (settings.freqStop - settings.freqStart) / (settings.points - 1);
|
||||
// The frequency resolution of the PLL is frequency dependent (due to PLL divider).
|
||||
// This code assumes some knowledge of the actual hardware and probably should be moved
|
||||
// onto the device at some point
|
||||
double minSpacing = 25000;
|
||||
auto stop = settings.freqStop;
|
||||
while(stop <= 3000000000) {
|
||||
minSpacing /= 2;
|
||||
stop *= 2;
|
||||
}
|
||||
if(pointSpacing < minSpacing) {
|
||||
auto requiredMinSpan = minSpacing * (settings.points - 1);
|
||||
auto message = QString() + "Due to PLL limitations, the tracking generator can not reach every frequency exactly. "
|
||||
"With your current span, this could result in the signal not being detected at some bands. A minimum"
|
||||
" span of " + Unit::ToString(requiredMinSpan, "Hz", " kMG") + " is recommended at this stop frequency.";
|
||||
InformationBox::ShowMessage("Warning", message, "TrackingGeneratorSpanTooSmallWarning");
|
||||
}
|
||||
}
|
||||
|
||||
if(normalize.active) {
|
||||
// check if normalization is still valid
|
||||
if(normalize.f_start != settings.freqStart || normalize.f_stop != settings.freqStop || normalize.points != settings.points) {
|
||||
// normalization was taken at different settings, disable
|
||||
EnableNormalization(false);
|
||||
InformationBox::ShowMessage("Information", "Normalization was disabled because the span has been changed");
|
||||
}
|
||||
}
|
||||
// TODO move into libreVNA driver
|
||||
// if(settings.trackingGenerator && settings.freqStop >= 25000000) {
|
||||
// // Check point spacing.
|
||||
// // The highband PLL used as the tracking generator is not able to reach every frequency exactly. This
|
||||
// // could lead to sharp drops in the spectrum at certain frequencies. If the span is wide enough with
|
||||
// // respect to the point number, it is ensured that every displayed point has at least one sample with
|
||||
// // a reachable PLL frequency in it. Display a warning message if this is not the case with the current
|
||||
// // settings.
|
||||
// auto pointSpacing = (settings.freqStop - settings.freqStart) / (settings.points - 1);
|
||||
// // The frequency resolution of the PLL is frequency dependent (due to PLL divider).
|
||||
// // This code assumes some knowledge of the actual hardware and probably should be moved
|
||||
// // onto the device at some point
|
||||
// double minSpacing = 25000;
|
||||
// auto stop = settings.freqStop;
|
||||
// while(stop <= 3000000000) {
|
||||
// minSpacing /= 2;
|
||||
// stop *= 2;
|
||||
// }
|
||||
// if(pointSpacing < minSpacing) {
|
||||
// auto requiredMinSpan = minSpacing * (settings.points - 1);
|
||||
// auto message = QString() + "Due to PLL limitations, the tracking generator can not reach every frequency exactly. "
|
||||
// "With your current span, this could result in the signal not being detected at some bands. A minimum"
|
||||
// " span of " + Unit::ToString(requiredMinSpan, "Hz", " kMG") + " is recommended at this stop frequency.";
|
||||
// InformationBox::ShowMessage("Warning", message, "TrackingGeneratorSpanTooSmallWarning");
|
||||
// }
|
||||
// }
|
||||
|
||||
if(window->getDevice() && isActive) {
|
||||
window->getDevice()->setSA(settings, [=](bool){
|
||||
// device received command
|
||||
changingSettings = false;
|
||||
|
||||
if(normalize.active) {
|
||||
// check if normalization is still valid
|
||||
if(normalize.f_start != settings.freqStart || normalize.f_stop != settings.freqStop || normalize.points != DeviceDriver::getActiveDriver()->getSApoints()) {
|
||||
// normalization was taken at different settings, disable
|
||||
EnableNormalization(false);
|
||||
InformationBox::ShowMessage("Information", "Normalization was disabled because the span has been changed");
|
||||
}
|
||||
}
|
||||
});
|
||||
emit sweepStarted();
|
||||
} else {
|
||||
@ -894,7 +869,7 @@ void SpectrumAnalyzer::ConfigureDevice()
|
||||
emit sweepStopped();
|
||||
changingSettings = false;
|
||||
}
|
||||
average.reset(settings.points);
|
||||
average.reset(DeviceDriver::getActiveDriver()->getSApoints());
|
||||
UpdateAverageCount();
|
||||
traceModel.clearLiveData();
|
||||
emit traceModel.SpanChanged(settings.freqStart, settings.freqStop);
|
||||
@ -915,7 +890,7 @@ void SpectrumAnalyzer::ConfigureDevice()
|
||||
|
||||
void SpectrumAnalyzer::ResetLiveTraces()
|
||||
{
|
||||
average.reset(settings.points);
|
||||
average.reset(DeviceDriver::getActiveDriver()->getSApoints());
|
||||
traceModel.clearLiveData();
|
||||
UpdateAverageCount();
|
||||
}
|
||||
@ -996,23 +971,23 @@ void SpectrumAnalyzer::SetupSCPI()
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
if (params[0] == "NONE") {
|
||||
SetWindow(VirtualDevice::SASettings::Window::None);
|
||||
SetWindow(DeviceDriver::SASettings::Window::None);
|
||||
} else if(params[0] == "KAISER") {
|
||||
SetWindow(VirtualDevice::SASettings::Window::Kaiser);
|
||||
SetWindow(DeviceDriver::SASettings::Window::Kaiser);
|
||||
} else if(params[0] == "HANN") {
|
||||
SetWindow(VirtualDevice::SASettings::Window::Hann);
|
||||
SetWindow(DeviceDriver::SASettings::Window::Hann);
|
||||
} else if(params[0] == "FLATTOP") {
|
||||
SetWindow(VirtualDevice::SASettings::Window::FlatTop);
|
||||
SetWindow(DeviceDriver::SASettings::Window::FlatTop);
|
||||
} else {
|
||||
return "INVALID WINDOW";
|
||||
}
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, [=](QStringList) -> QString {
|
||||
switch((VirtualDevice::SASettings::Window) settings.window) {
|
||||
case VirtualDevice::SASettings::Window::None: return "NONE";
|
||||
case VirtualDevice::SASettings::Window::Kaiser: return "KAISER";
|
||||
case VirtualDevice::SASettings::Window::Hann: return "HANN";
|
||||
case VirtualDevice::SASettings::Window::FlatTop: return "FLATTOP";
|
||||
switch((DeviceDriver::SASettings::Window) settings.window) {
|
||||
case DeviceDriver::SASettings::Window::None: return "NONE";
|
||||
case DeviceDriver::SASettings::Window::Kaiser: return "KAISER";
|
||||
case DeviceDriver::SASettings::Window::Hann: return "HANN";
|
||||
case DeviceDriver::SASettings::Window::FlatTop: return "FLATTOP";
|
||||
default: return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
}));
|
||||
@ -1021,26 +996,26 @@ void SpectrumAnalyzer::SetupSCPI()
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
if (params[0] == "+PEAK") {
|
||||
SetDetector(VirtualDevice::SASettings::Detector::PPeak);
|
||||
SetDetector(DeviceDriver::SASettings::Detector::PPeak);
|
||||
} else if(params[0] == "-PEAK") {
|
||||
SetDetector(VirtualDevice::SASettings::Detector::NPeak);
|
||||
SetDetector(DeviceDriver::SASettings::Detector::NPeak);
|
||||
} else if(params[0] == "NORMAL") {
|
||||
SetDetector(VirtualDevice::SASettings::Detector::Normal);
|
||||
SetDetector(DeviceDriver::SASettings::Detector::Normal);
|
||||
} else if(params[0] == "SAMPLE") {
|
||||
SetDetector(VirtualDevice::SASettings::Detector::Sample);
|
||||
SetDetector(DeviceDriver::SASettings::Detector::Sample);
|
||||
} else if(params[0] == "AVERAGE") {
|
||||
SetDetector(VirtualDevice::SASettings::Detector::Average);
|
||||
SetDetector(DeviceDriver::SASettings::Detector::Average);
|
||||
} else {
|
||||
return "INVALID MDOE";
|
||||
}
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, [=](QStringList) -> QString {
|
||||
switch((VirtualDevice::SASettings::Detector) settings.detector) {
|
||||
case VirtualDevice::SASettings::Detector::PPeak: return "+PEAK";
|
||||
case VirtualDevice::SASettings::Detector::NPeak: return "-PEAK";
|
||||
case VirtualDevice::SASettings::Detector::Normal: return "NORMAL";
|
||||
case VirtualDevice::SASettings::Detector::Sample: return "SAMPLE";
|
||||
case VirtualDevice::SASettings::Detector::Average: return "AVERAGE";
|
||||
switch((DeviceDriver::SASettings::Detector) settings.detector) {
|
||||
case DeviceDriver::SASettings::Detector::PPeak: return "+PEAK";
|
||||
case DeviceDriver::SASettings::Detector::NPeak: return "-PEAK";
|
||||
case DeviceDriver::SASettings::Detector::Normal: return "NORMAL";
|
||||
case DeviceDriver::SASettings::Detector::Sample: return "SAMPLE";
|
||||
case DeviceDriver::SASettings::Detector::Average: return "AVERAGE";
|
||||
default: return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
}));
|
||||
@ -1064,21 +1039,6 @@ void SpectrumAnalyzer::SetupSCPI()
|
||||
scpi_acq->add(new SCPICommand("LIMit", nullptr, [=](QStringList) -> QString {
|
||||
return tiles->allLimitsPassing() ? "PASS" : "FAIL";
|
||||
}));
|
||||
scpi_acq->add(new SCPICommand("SIGid", [=](QStringList params) -> QString {
|
||||
if (params.size() != 1) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
if(params[0] == "1" || params[0] == "TRUE") {
|
||||
SetSignalID(true);
|
||||
} else if(params[0] == "0" || params[0] == "FALSE") {
|
||||
SetSignalID(false);
|
||||
} else {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, [=](QStringList) -> QString {
|
||||
return settings.signalID ? SCPI::getResultName(SCPI::Result::True) : SCPI::getResultName(SCPI::Result::False);
|
||||
}));
|
||||
scpi_acq->add(new SCPICommand("SINGLE", [=](QStringList params) -> QString {
|
||||
bool single;
|
||||
if(!SCPI::paramToBool(params, 0, single)) {
|
||||
@ -1124,7 +1084,7 @@ void SpectrumAnalyzer::SetupSCPI()
|
||||
unsigned long long newval;
|
||||
if(!SCPI::paramToULongLong(params, 0, newval)) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
} else if(newval > 0 && newval <= VirtualDevice::getInfo(window->getDevice()).ports){
|
||||
} else if(newval > 0 && newval <= DeviceDriver::getInfo(window->getDevice()).Limits.SA.ports){
|
||||
SetTGPort(newval-1);
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
} else {
|
||||
@ -1200,24 +1160,24 @@ void SpectrumAnalyzer::UpdateAverageCount()
|
||||
|
||||
void SpectrumAnalyzer::ConstrainAndUpdateFrequencies()
|
||||
{
|
||||
if(settings.freqStop > VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq) {
|
||||
settings.freqStop = VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq;
|
||||
if(settings.freqStop > DeviceDriver::getInfo(window->getDevice()).Limits.SA.maxFreq) {
|
||||
settings.freqStop = DeviceDriver::getInfo(window->getDevice()).Limits.SA.maxFreq;
|
||||
}
|
||||
if(settings.freqStart > settings.freqStop) {
|
||||
settings.freqStart = settings.freqStop;
|
||||
}
|
||||
if(settings.freqStart < VirtualDevice::getInfo(window->getDevice()).Limits.minFreq) {
|
||||
settings.freqStart = VirtualDevice::getInfo(window->getDevice()).Limits.minFreq;
|
||||
if(settings.freqStart < DeviceDriver::getInfo(window->getDevice()).Limits.SA.minFreq) {
|
||||
settings.freqStart = DeviceDriver::getInfo(window->getDevice()).Limits.SA.minFreq;
|
||||
}
|
||||
|
||||
bool trackingOffset_limited = false;
|
||||
if(settings.freqStop + settings.trackingOffset > VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq) {
|
||||
if(settings.freqStop + settings.trackingOffset > DeviceDriver::getInfo(window->getDevice()).Limits.SA.maxFreq) {
|
||||
trackingOffset_limited = true;
|
||||
settings.trackingOffset = VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq - settings.freqStop;
|
||||
settings.trackingOffset = DeviceDriver::getInfo(window->getDevice()).Limits.SA.maxFreq - settings.freqStop;
|
||||
}
|
||||
if(settings.freqStart + settings.trackingOffset < VirtualDevice::getInfo(window->getDevice()).Limits.minFreq) {
|
||||
if(settings.freqStart + settings.trackingOffset < DeviceDriver::getInfo(window->getDevice()).Limits.SA.minFreq) {
|
||||
trackingOffset_limited = true;
|
||||
settings.trackingOffset = VirtualDevice::getInfo(window->getDevice()).Limits.minFreq - settings.freqStart;
|
||||
settings.trackingOffset = DeviceDriver::getInfo(window->getDevice()).Limits.SA.minFreq - settings.freqStart;
|
||||
}
|
||||
if(trackingOffset_limited) {
|
||||
InformationBox::ShowMessage("Warning", "The selected tracking generator offset is not reachable for all frequencies with the current span. "
|
||||
@ -1239,10 +1199,8 @@ void SpectrumAnalyzer::LoadSweepSettings()
|
||||
settings.freqStop = s.value("SAStop", pref.Startup.SA.stop).toULongLong();
|
||||
ConstrainAndUpdateFrequencies();
|
||||
SetRBW(s.value("SARBW", pref.Startup.SA.RBW).toUInt());
|
||||
settings.points = 1001;
|
||||
SetWindow((VirtualDevice::SASettings::Window) s.value("SAWindow", pref.Startup.SA.window).toInt());
|
||||
SetDetector((VirtualDevice::SASettings::Detector) s.value("SADetector", pref.Startup.SA.detector).toInt());
|
||||
SetSignalID(s.value("SASignalID", pref.Startup.SA.signalID).toBool());
|
||||
SetWindow((DeviceDriver::SASettings::Window) s.value("SAWindow", pref.Startup.SA.window).toInt());
|
||||
SetDetector((DeviceDriver::SASettings::Detector) s.value("SADetector", pref.Startup.SA.detector).toInt());
|
||||
SetAveraging(s.value("SAAveraging", pref.Startup.SA.averaging).toInt());
|
||||
}
|
||||
|
||||
@ -1255,7 +1213,6 @@ void SpectrumAnalyzer::StoreSweepSettings()
|
||||
s.setValue("SAWindow", (int) settings.window);
|
||||
s.setValue("SADetector", (int) settings.detector);
|
||||
s.setValue("SAAveraging", averages);
|
||||
s.setValue("SASignalID", static_cast<bool>(settings.signalID));
|
||||
}
|
||||
|
||||
void SpectrumAnalyzer::createDefaultTracesAndGraphs(int ports)
|
||||
@ -1291,7 +1248,7 @@ void SpectrumAnalyzer::preset()
|
||||
}
|
||||
}
|
||||
// Create default traces
|
||||
createDefaultTracesAndGraphs(VirtualDevice::getInfo(window->getDevice()).ports);
|
||||
createDefaultTracesAndGraphs(DeviceDriver::getInfo(window->getDevice()).Limits.SA.ports);
|
||||
}
|
||||
|
||||
void SpectrumAnalyzer::deviceInfoUpdated()
|
||||
@ -1300,53 +1257,53 @@ void SpectrumAnalyzer::deviceInfoUpdated()
|
||||
ClearNormalization();
|
||||
auto tgPort = cbTrackGenPort->currentIndex();
|
||||
cbTrackGenPort->clear();
|
||||
for(unsigned int i=0;i<VirtualDevice::getInfo(window->getDevice()).ports;i++) {
|
||||
for(unsigned int i=0;i<DeviceDriver::getInfo(window->getDevice()).Limits.SA.ports;i++) {
|
||||
cbTrackGenPort->addItem("Port "+QString::number(i+1));
|
||||
}
|
||||
SetTGPort(tgPort);
|
||||
}
|
||||
|
||||
QString SpectrumAnalyzer::WindowToString(VirtualDevice::SASettings::Window w)
|
||||
QString SpectrumAnalyzer::WindowToString(DeviceDriver::SASettings::Window w)
|
||||
{
|
||||
switch(w) {
|
||||
case VirtualDevice::SASettings::Window::None: return "None";
|
||||
case VirtualDevice::SASettings::Window::Kaiser: return "Kaiser";
|
||||
case VirtualDevice::SASettings::Window::Hann: return "Hann";
|
||||
case VirtualDevice::SASettings::Window::FlatTop: return "FlatTop";
|
||||
case DeviceDriver::SASettings::Window::None: return "None";
|
||||
case DeviceDriver::SASettings::Window::Kaiser: return "Kaiser";
|
||||
case DeviceDriver::SASettings::Window::Hann: return "Hann";
|
||||
case DeviceDriver::SASettings::Window::FlatTop: return "FlatTop";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
VirtualDevice::SASettings::Window SpectrumAnalyzer::WindowFromString(QString s)
|
||||
DeviceDriver::SASettings::Window SpectrumAnalyzer::WindowFromString(QString s)
|
||||
{
|
||||
for(int i=0;i<(int)VirtualDevice::SASettings::Window::Last;i++) {
|
||||
if(WindowToString((VirtualDevice::SASettings::Window) i) == s) {
|
||||
return (VirtualDevice::SASettings::Window) i;
|
||||
for(int i=0;i<(int)DeviceDriver::SASettings::Window::Last;i++) {
|
||||
if(WindowToString((DeviceDriver::SASettings::Window) i) == s) {
|
||||
return (DeviceDriver::SASettings::Window) i;
|
||||
}
|
||||
}
|
||||
// not found
|
||||
return VirtualDevice::SASettings::Window::Last;
|
||||
return DeviceDriver::SASettings::Window::Last;
|
||||
}
|
||||
|
||||
QString SpectrumAnalyzer::DetectorToString(VirtualDevice::SASettings::Detector d)
|
||||
QString SpectrumAnalyzer::DetectorToString(DeviceDriver::SASettings::Detector d)
|
||||
{
|
||||
switch(d) {
|
||||
case VirtualDevice::SASettings::Detector::PPeak: return "+Peak";
|
||||
case VirtualDevice::SASettings::Detector::NPeak: return "-Peak";
|
||||
case VirtualDevice::SASettings::Detector::Sample: return "Sample";
|
||||
case VirtualDevice::SASettings::Detector::Normal: return "Normal";
|
||||
case VirtualDevice::SASettings::Detector::Average: return "Average";
|
||||
case DeviceDriver::SASettings::Detector::PPeak: return "+Peak";
|
||||
case DeviceDriver::SASettings::Detector::NPeak: return "-Peak";
|
||||
case DeviceDriver::SASettings::Detector::Sample: return "Sample";
|
||||
case DeviceDriver::SASettings::Detector::Normal: return "Normal";
|
||||
case DeviceDriver::SASettings::Detector::Average: return "Average";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
VirtualDevice::SASettings::Detector SpectrumAnalyzer::DetectorFromString(QString s)
|
||||
DeviceDriver::SASettings::Detector SpectrumAnalyzer::DetectorFromString(QString s)
|
||||
{
|
||||
for(int i=0;i<(int)VirtualDevice::SASettings::Detector::Last;i++) {
|
||||
if(DetectorToString((VirtualDevice::SASettings::Detector) i) == s) {
|
||||
return (VirtualDevice::SASettings::Detector) i;
|
||||
for(int i=0;i<(int)DeviceDriver::SASettings::Detector::Last;i++) {
|
||||
if(DetectorToString((DeviceDriver::SASettings::Detector) i) == s) {
|
||||
return (DeviceDriver::SASettings::Detector) i;
|
||||
}
|
||||
}
|
||||
// not found
|
||||
return VirtualDevice::SASettings::Detector::Last;
|
||||
return DeviceDriver::SASettings::Detector::Last;
|
||||
}
|
||||
|
@ -38,13 +38,13 @@ public:
|
||||
virtual void deviceInfoUpdated() override;
|
||||
|
||||
private:
|
||||
static QString WindowToString(VirtualDevice::SASettings::Window w);
|
||||
static VirtualDevice::SASettings::Window WindowFromString(QString s);
|
||||
static QString DetectorToString(VirtualDevice::SASettings::Detector d);
|
||||
static VirtualDevice::SASettings::Detector DetectorFromString(QString s);
|
||||
static QString WindowToString(DeviceDriver::SASettings::Window w);
|
||||
static DeviceDriver::SASettings::Window WindowFromString(QString s);
|
||||
static QString DetectorToString(DeviceDriver::SASettings::Detector d);
|
||||
static DeviceDriver::SASettings::Detector DetectorFromString(QString s);
|
||||
|
||||
private slots:
|
||||
void NewDatapoint(VirtualDevice::SAMeasurement m);
|
||||
void NewDatapoint(DeviceDriver::SAMeasurement m);
|
||||
// Sweep control
|
||||
void SetStartFreq(double freq);
|
||||
void SetStopFreq(double freq);
|
||||
@ -57,10 +57,9 @@ private slots:
|
||||
void SetSingleSweep(bool single);
|
||||
// Acquisition control
|
||||
void SetRBW(double bandwidth);
|
||||
void SetWindow(VirtualDevice::SASettings::Window w);
|
||||
void SetDetector(VirtualDevice::SASettings::Detector d);
|
||||
void SetWindow(DeviceDriver::SASettings::Window w);
|
||||
void SetDetector(DeviceDriver::SASettings::Detector d);
|
||||
void SetAveraging(unsigned int averages);
|
||||
void SetSignalID(bool enabled);
|
||||
// TG control
|
||||
void SetTGEnabled(bool enabled);
|
||||
void SetTGPort(int port);
|
||||
@ -87,7 +86,7 @@ private:
|
||||
|
||||
void createDefaultTracesAndGraphs(int ports);
|
||||
|
||||
VirtualDevice::SASettings settings;
|
||||
DeviceDriver::SASettings settings;
|
||||
bool changingSettings;
|
||||
unsigned int averages;
|
||||
bool singleSweep;
|
||||
|
@ -139,7 +139,7 @@ void Trace::addData(const Trace::Data& d, DataType domain, double reference_impe
|
||||
emit outputSamplesChanged(index, index + 1);
|
||||
}
|
||||
|
||||
void Trace::addData(const Trace::Data &d, const VirtualDevice::SASettings &s, int index)
|
||||
void Trace::addData(const Trace::Data &d, const DeviceDriver::SASettings &s, int index)
|
||||
{
|
||||
settings.SA = s;
|
||||
settings.valid = true;
|
||||
@ -303,7 +303,7 @@ QString Trace::fillFromCSV(CSV &csv, unsigned int parameter)
|
||||
return lastTraceName;
|
||||
}
|
||||
|
||||
void Trace::fillFromDatapoints(std::map<QString, Trace *> traceSet, const std::vector<VirtualDevice::VNAMeasurement> &data, bool deembedded)
|
||||
void Trace::fillFromDatapoints(std::map<QString, Trace *> traceSet, const std::vector<DeviceDriver::VNAMeasurement> &data, bool deembedded)
|
||||
{
|
||||
// remove all previous points
|
||||
for(auto m : traceSet) {
|
||||
@ -1001,9 +1001,9 @@ std::vector<Trace *> Trace::createFromCSV(CSV &csv)
|
||||
return traces;
|
||||
}
|
||||
|
||||
std::vector<VirtualDevice::VNAMeasurement> Trace::assembleDatapoints(std::map<QString, Trace *> traceSet)
|
||||
std::vector<DeviceDriver::VNAMeasurement> Trace::assembleDatapoints(std::map<QString, Trace *> traceSet)
|
||||
{
|
||||
vector<VirtualDevice::VNAMeasurement> ret;
|
||||
vector<DeviceDriver::VNAMeasurement> ret;
|
||||
|
||||
// Sanity check traces
|
||||
unsigned int samples = traceSet.begin()->second->size();
|
||||
@ -1041,7 +1041,7 @@ std::vector<VirtualDevice::VNAMeasurement> Trace::assembleDatapoints(std::map<QS
|
||||
|
||||
// Checks passed, assemble datapoints
|
||||
for(unsigned int i=0;i<samples;i++) {
|
||||
VirtualDevice::VNAMeasurement d;
|
||||
DeviceDriver::VNAMeasurement d;
|
||||
for(auto m : traceSet) {
|
||||
QString measurement = m.first;
|
||||
const Trace *t = m.second;
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include "touchstone.h"
|
||||
#include "csv.h"
|
||||
#include "Device/virtualdevice.h"
|
||||
#include "Device/devicedriver.h"
|
||||
#include "Math/tracemath.h"
|
||||
#include "Tools/parameters.h"
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#include <QColor>
|
||||
#include <set>
|
||||
#include <QTime>
|
||||
#include <QTimer>
|
||||
|
||||
class Marker;
|
||||
class TraceModel;
|
||||
@ -44,13 +45,13 @@ public:
|
||||
|
||||
void clear(bool force = false);
|
||||
void addData(const Data& d, DataType domain, double reference_impedance = 50.0, int index = -1);
|
||||
void addData(const Data& d, const VirtualDevice::SASettings &s, int index = -1);
|
||||
void addData(const Data& d, const DeviceDriver::SASettings &s, int index = -1);
|
||||
void addDeembeddingData(const Data& d, int index = -1);
|
||||
void setName(QString name);
|
||||
void setVelocityFactor(double v);
|
||||
void fillFromTouchstone(Touchstone &t, unsigned int parameter);
|
||||
QString fillFromCSV(CSV &csv, unsigned int parameter); // returns the suggested trace name (not yet set in member data)
|
||||
static void fillFromDatapoints(std::map<QString, Trace*> traceSet, const std::vector<VirtualDevice::VNAMeasurement> &data, bool deembedded = false);
|
||||
static void fillFromDatapoints(std::map<QString, Trace*> traceSet, const std::vector<DeviceDriver::VNAMeasurement> &data, bool deembedded = false);
|
||||
void fromLivedata(LivedataType type, QString param);
|
||||
void fromMath();
|
||||
QString name() { return _name; }
|
||||
@ -151,7 +152,7 @@ public:
|
||||
|
||||
// Assembles datapoints as received from the VNA from four S parameter traces. Requires that all traces are in the frequency domain,
|
||||
// have the same number of samples and their samples must be at the same frequencies across all traces
|
||||
static std::vector<VirtualDevice::VNAMeasurement> assembleDatapoints(std::map<QString, Trace *> traceSet);
|
||||
static std::vector<DeviceDriver::VNAMeasurement> assembleDatapoints(std::map<QString, Trace *> traceSet);
|
||||
|
||||
static LivedataType TypeFromString(QString s);
|
||||
static QString TypeToString(LivedataType t);
|
||||
@ -275,7 +276,7 @@ private:
|
||||
std::set<Marker*> markers;
|
||||
struct {
|
||||
union {
|
||||
VirtualDevice::SASettings SA;
|
||||
DeviceDriver::SASettings SA;
|
||||
};
|
||||
bool valid;
|
||||
} settings;
|
||||
|
@ -475,16 +475,16 @@ double XAxis::sampleToCoordinate(Trace::Data data, Trace *t, unsigned int sample
|
||||
void XAxis::set(Type type, bool log, bool autorange, double min, double max, double div)
|
||||
{
|
||||
if(max <= min) {
|
||||
auto info = VirtualDevice::getInfo(VirtualDevice::getConnected());
|
||||
auto info = DeviceDriver::getInfo(DeviceDriver::getActiveDriver());
|
||||
// invalid selection, use default instead
|
||||
switch(type) {
|
||||
case Type::Frequency:
|
||||
min = info.Limits.minFreq;
|
||||
max = info.Limits.maxFreq;
|
||||
min = info.Limits.VNA.minFreq;
|
||||
max = info.Limits.VNA.maxFreq;
|
||||
break;
|
||||
case Type::Power:
|
||||
min = info.Limits.mindBm;
|
||||
max = info.Limits.maxdBm;
|
||||
min = info.Limits.VNA.mindBm;
|
||||
max = info.Limits.VNA.maxdBm;
|
||||
break;
|
||||
case Type::Time:
|
||||
case Type::TimeZeroSpan:
|
||||
|
@ -280,7 +280,7 @@ void TraceModel::clearLiveData()
|
||||
}
|
||||
}
|
||||
|
||||
void TraceModel::addVNAData(const VirtualDevice::VNAMeasurement& d, TraceMath::DataType datatype, bool deembedded)
|
||||
void TraceModel::addVNAData(const DeviceDriver::VNAMeasurement& d, TraceMath::DataType datatype, bool deembedded)
|
||||
{
|
||||
source = DataSource::VNA;
|
||||
lastReceivedData = QDateTime::currentDateTimeUtc();
|
||||
@ -319,7 +319,7 @@ void TraceModel::addVNAData(const VirtualDevice::VNAMeasurement& d, TraceMath::D
|
||||
}
|
||||
}
|
||||
|
||||
void TraceModel::addSAData(const VirtualDevice::SAMeasurement& d, const VirtualDevice::SASettings &settings)
|
||||
void TraceModel::addSAData(const DeviceDriver::SAMeasurement& d, const DeviceDriver::SASettings &settings)
|
||||
{
|
||||
source = DataSource::SA;
|
||||
lastReceivedData = QDateTime::currentDateTimeUtc();
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef TRACEMODEL_H
|
||||
#define TRACEMODEL_H
|
||||
|
||||
#include "Device/device.h"
|
||||
#include "Device/devicedriver.h"
|
||||
#include "savable.h"
|
||||
#include "trace.h"
|
||||
|
||||
@ -71,8 +71,8 @@ signals:
|
||||
|
||||
public slots:
|
||||
void clearLiveData();
|
||||
void addVNAData(const VirtualDevice::VNAMeasurement& d, TraceMath::DataType datatype, bool deembedded);
|
||||
void addSAData(const VirtualDevice::SAMeasurement &d, const VirtualDevice::SASettings &settings);
|
||||
void addVNAData(const DeviceDriver::VNAMeasurement& d, TraceMath::DataType datatype, bool deembedded);
|
||||
void addSAData(const DeviceDriver::SAMeasurement &d, const DeviceDriver::SASettings &settings);
|
||||
|
||||
private:
|
||||
DataSource source;
|
||||
|
@ -126,7 +126,7 @@ Deembedding::Deembedding(TraceModel &tm)
|
||||
}, nullptr));
|
||||
}
|
||||
|
||||
void Deembedding::Deembed(VirtualDevice::VNAMeasurement &d)
|
||||
void Deembedding::Deembed(DeviceDriver::VNAMeasurement &d)
|
||||
{
|
||||
// figure out the point in one sweep based on the incomig pointNums
|
||||
static unsigned lastPointNum;
|
||||
|
@ -22,7 +22,7 @@ public:
|
||||
Deembedding(TraceModel &tm);
|
||||
~Deembedding(){}
|
||||
|
||||
void Deembed(VirtualDevice::VNAMeasurement &d);
|
||||
void Deembed(DeviceDriver::VNAMeasurement &d);
|
||||
void Deembed(std::map<QString, Trace*> traceSet);
|
||||
|
||||
void removeOption(unsigned int index);
|
||||
@ -50,7 +50,7 @@ private:
|
||||
TraceModel &tm;
|
||||
|
||||
bool measuring;
|
||||
std::vector<VirtualDevice::VNAMeasurement> measurements;
|
||||
std::vector<DeviceDriver::VNAMeasurement> measurements;
|
||||
QDialog *measurementDialog;
|
||||
Ui_DeembeddingMeasurementDialog *measurementUI;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define DEEMBEDDINGOPTION_H
|
||||
|
||||
#include "savable.h"
|
||||
#include "Device/device.h"
|
||||
#include "Device/devicedriver.h"
|
||||
#include "Traces/tracemodel.h"
|
||||
#include "scpi.h"
|
||||
|
||||
@ -27,12 +27,12 @@ public:
|
||||
static Type TypeFromString(QString string);
|
||||
|
||||
virtual std::set<unsigned int> getAffectedPorts() = 0;
|
||||
virtual void transformDatapoint(VirtualDevice::VNAMeasurement &p) = 0;
|
||||
virtual void transformDatapoint(DeviceDriver::VNAMeasurement &p) = 0;
|
||||
virtual void edit(){}
|
||||
virtual Type getType() = 0;
|
||||
|
||||
public slots:
|
||||
virtual void measurementCompleted(std::vector<VirtualDevice::VNAMeasurement> m){Q_UNUSED(m)}
|
||||
virtual void measurementCompleted(std::vector<DeviceDriver::VNAMeasurement> m){Q_UNUSED(m)}
|
||||
signals:
|
||||
// Deembedding option may selfdestruct if not applicable with current settings. It should emit this signal before deleting itself
|
||||
void deleted(DeembeddingOption *option);
|
||||
|
@ -28,13 +28,13 @@ ImpedanceRenormalization::ImpedanceRenormalization()
|
||||
std::set<unsigned int> ImpedanceRenormalization::getAffectedPorts()
|
||||
{
|
||||
set<unsigned int> ret;
|
||||
for(unsigned int i=1;i<=VirtualDevice::getInfo(VirtualDevice::getConnected()).ports;i++) {
|
||||
for(unsigned int i=1;i<=DeviceDriver::getInfo(DeviceDriver::getActiveDriver()).Limits.VNA.ports;i++) {
|
||||
ret.insert(i);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ImpedanceRenormalization::transformDatapoint(VirtualDevice::VNAMeasurement &p)
|
||||
void ImpedanceRenormalization::transformDatapoint(DeviceDriver::VNAMeasurement &p)
|
||||
{
|
||||
std::map<QString, std::complex<double>> transformed;
|
||||
int ports = 0;
|
||||
|
@ -14,7 +14,7 @@ public:
|
||||
ImpedanceRenormalization();
|
||||
|
||||
std::set<unsigned int> getAffectedPorts() override;
|
||||
void transformDatapoint(VirtualDevice::VNAMeasurement &p) override;
|
||||
void transformDatapoint(DeviceDriver::VNAMeasurement &p) override;
|
||||
Type getType() override { return Type::ImpedanceRenormalization;}
|
||||
nlohmann::json toJSON() override;
|
||||
void fromJSON(nlohmann::json j) override;
|
||||
|
@ -78,7 +78,7 @@ std::set<unsigned int> MatchingNetwork::getAffectedPorts()
|
||||
return {port};
|
||||
}
|
||||
|
||||
void MatchingNetwork::transformDatapoint(VirtualDevice::VNAMeasurement &p)
|
||||
void MatchingNetwork::transformDatapoint(DeviceDriver::VNAMeasurement &p)
|
||||
{
|
||||
if(matching.count(p.frequency) == 0) {
|
||||
// this point is not calculated yet
|
||||
@ -99,7 +99,7 @@ void MatchingNetwork::transformDatapoint(VirtualDevice::VNAMeasurement &p)
|
||||
}
|
||||
// at this point the map contains the matching network effect
|
||||
auto m = matching[p.frequency];
|
||||
VirtualDevice::VNAMeasurement uncorrected = p;
|
||||
DeviceDriver::VNAMeasurement uncorrected = p;
|
||||
|
||||
auto portReflectionName = "S"+QString::number(port)+QString::number(port);
|
||||
if(!uncorrected.measurements.count(portReflectionName)) {
|
||||
@ -180,7 +180,7 @@ void MatchingNetwork::edit()
|
||||
ui->lDefinedShunt->installEventFilter(this);
|
||||
|
||||
ui->port->setValue(port);
|
||||
ui->port->setMaximum(VirtualDevice::maximumSupportedPorts);
|
||||
ui->port->setMaximum(DeviceDriver::maximumSupportedPorts);
|
||||
|
||||
layout->setContentsMargins(0,0,0,0);
|
||||
layout->setSpacing(0);
|
||||
|
@ -68,7 +68,7 @@ public:
|
||||
// DeembeddingOption interface
|
||||
public:
|
||||
std::set<unsigned int> getAffectedPorts() override;
|
||||
void transformDatapoint(VirtualDevice::VNAMeasurement &p) override;
|
||||
void transformDatapoint(DeviceDriver::VNAMeasurement &p) override;
|
||||
void edit() override;
|
||||
Type getType() override {return Type::MatchingNetwork;}
|
||||
nlohmann::json toJSON() override;
|
||||
|
@ -38,7 +38,7 @@ std::set<unsigned int> PortExtension::getAffectedPorts()
|
||||
return {port};
|
||||
}
|
||||
|
||||
void PortExtension::transformDatapoint(VirtualDevice::VNAMeasurement &d)
|
||||
void PortExtension::transformDatapoint(DeviceDriver::VNAMeasurement &d)
|
||||
{
|
||||
auto phase = -2 * M_PI * ext.delay * d.frequency;
|
||||
auto db_attennuation = ext.DCloss;
|
||||
@ -88,7 +88,7 @@ void PortExtension::edit()
|
||||
ui->Loss->setValue(ext.loss);
|
||||
ui->Frequency->setValue(ext.frequency);
|
||||
ui->port->setValue(port);
|
||||
ui->port->setMaximum(VirtualDevice::maximumSupportedPorts);
|
||||
ui->port->setMaximum(DeviceDriver::maximumSupportedPorts);
|
||||
if(!kit) {
|
||||
ui->calkit->setEnabled(false);
|
||||
}
|
||||
@ -138,7 +138,7 @@ void PortExtension::edit()
|
||||
}
|
||||
}
|
||||
|
||||
void PortExtension::measurementCompleted(std::vector<VirtualDevice::VNAMeasurement> m)
|
||||
void PortExtension::measurementCompleted(std::vector<DeviceDriver::VNAMeasurement> m)
|
||||
{
|
||||
if(m.size() > 0) {
|
||||
double last_phase = 0.0;
|
||||
|
@ -19,14 +19,14 @@ class PortExtension : public DeembeddingOption
|
||||
public:
|
||||
PortExtension();
|
||||
std::set<unsigned int> getAffectedPorts() override;
|
||||
void transformDatapoint(VirtualDevice::VNAMeasurement& d) override;
|
||||
void transformDatapoint(DeviceDriver::VNAMeasurement& d) override;
|
||||
void setCalkit(Calkit *kit);
|
||||
Type getType() override {return Type::PortExtension;}
|
||||
nlohmann::json toJSON() override;
|
||||
void fromJSON(nlohmann::json j) override;
|
||||
public slots:
|
||||
void edit() override;
|
||||
void measurementCompleted(std::vector<VirtualDevice::VNAMeasurement> m) override;
|
||||
void measurementCompleted(std::vector<DeviceDriver::VNAMeasurement> m) override;
|
||||
|
||||
private:
|
||||
void startMeasurement();
|
||||
|
@ -25,7 +25,7 @@ std::set<unsigned int> TwoThru::getAffectedPorts()
|
||||
return {port1, port2};
|
||||
}
|
||||
|
||||
void TwoThru::transformDatapoint(VirtualDevice::VNAMeasurement &p)
|
||||
void TwoThru::transformDatapoint(DeviceDriver::VNAMeasurement &p)
|
||||
{
|
||||
// correct measurement
|
||||
if(points.size() > 0) {
|
||||
@ -109,7 +109,7 @@ void TwoThru::updateGUI()
|
||||
}
|
||||
}
|
||||
|
||||
void TwoThru::measurementCompleted(std::vector<VirtualDevice::VNAMeasurement> m)
|
||||
void TwoThru::measurementCompleted(std::vector<DeviceDriver::VNAMeasurement> m)
|
||||
{
|
||||
if (measuring2xthru) {
|
||||
measurements2xthru = m;
|
||||
@ -136,9 +136,9 @@ void TwoThru::edit()
|
||||
ui->lZ0->setVisible(false);
|
||||
|
||||
ui->port1->setValue(port1);
|
||||
ui->port1->setMaximum(VirtualDevice::maximumSupportedPorts);
|
||||
ui->port1->setMaximum(DeviceDriver::maximumSupportedPorts);
|
||||
ui->port2->setValue(port2);
|
||||
ui->port2->setMaximum(VirtualDevice::maximumSupportedPorts);
|
||||
ui->port2->setMaximum(DeviceDriver::maximumSupportedPorts);
|
||||
|
||||
auto portChanged = [=](){
|
||||
port1 = ui->port1->value();
|
||||
@ -261,7 +261,7 @@ void TwoThru::fromJSON(nlohmann::json j)
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<TwoThru::Point> TwoThru::calculateErrorBoxes(std::vector<VirtualDevice::VNAMeasurement> data_2xthru)
|
||||
std::vector<TwoThru::Point> TwoThru::calculateErrorBoxes(std::vector<DeviceDriver::VNAMeasurement> data_2xthru)
|
||||
{
|
||||
// calculate error boxes, see https://www.freelists.org/post/si-list/IEEE-P370-Opensource-Deembedding-MATLAB-functions
|
||||
// create vectors of S parameters
|
||||
@ -442,7 +442,7 @@ std::vector<TwoThru::Point> TwoThru::calculateErrorBoxes(std::vector<VirtualDevi
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<TwoThru::Point> TwoThru::calculateErrorBoxes(std::vector<VirtualDevice::VNAMeasurement> data_2xthru, std::vector<VirtualDevice::VNAMeasurement> data_fix_dut_fix, double z0)
|
||||
std::vector<TwoThru::Point> TwoThru::calculateErrorBoxes(std::vector<DeviceDriver::VNAMeasurement> data_2xthru, std::vector<DeviceDriver::VNAMeasurement> data_fix_dut_fix, double z0)
|
||||
{
|
||||
vector<Point> ret;
|
||||
|
||||
@ -715,9 +715,9 @@ std::vector<TwoThru::Point> TwoThru::calculateErrorBoxes(std::vector<VirtualDevi
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<VirtualDevice::VNAMeasurement> TwoThru::interpolateEvenFrequencySteps(std::vector<VirtualDevice::VNAMeasurement> input)
|
||||
std::vector<DeviceDriver::VNAMeasurement> TwoThru::interpolateEvenFrequencySteps(std::vector<DeviceDriver::VNAMeasurement> input)
|
||||
{
|
||||
vector<VirtualDevice::VNAMeasurement> ret;
|
||||
vector<DeviceDriver::VNAMeasurement> ret;
|
||||
if(input.size() > 1) {
|
||||
int size = input.size();
|
||||
double freqStep = 0.0;
|
||||
@ -739,8 +739,8 @@ std::vector<VirtualDevice::VNAMeasurement> TwoThru::interpolateEvenFrequencyStep
|
||||
// needs to interpolate
|
||||
double freq = freqStep;
|
||||
while(freq <= input.back().frequency) {
|
||||
VirtualDevice::VNAMeasurement interp;
|
||||
auto it = lower_bound(input.begin(), input.end(), freq, [](const VirtualDevice::VNAMeasurement &lhs, const double f) -> bool {
|
||||
DeviceDriver::VNAMeasurement interp;
|
||||
auto it = lower_bound(input.begin(), input.end(), freq, [](const DeviceDriver::VNAMeasurement &lhs, const double f) -> bool {
|
||||
return lhs.frequency < f;
|
||||
});
|
||||
if(it->frequency == freq) {
|
||||
|
@ -17,7 +17,7 @@ public:
|
||||
TwoThru();
|
||||
|
||||
std::set<unsigned int> getAffectedPorts() override;
|
||||
virtual void transformDatapoint(VirtualDevice::VNAMeasurement& p) override;
|
||||
virtual void transformDatapoint(DeviceDriver::VNAMeasurement& p) override;
|
||||
virtual void edit() override;
|
||||
virtual Type getType() override {return DeembeddingOption::Type::TwoThru;}
|
||||
nlohmann::json toJSON() override;
|
||||
@ -26,19 +26,19 @@ public:
|
||||
private slots:
|
||||
void startMeasurement();
|
||||
void updateGUI();
|
||||
void measurementCompleted(std::vector<VirtualDevice::VNAMeasurement> m) override;
|
||||
void measurementCompleted(std::vector<DeviceDriver::VNAMeasurement> m) override;
|
||||
private:
|
||||
using Point = struct {
|
||||
double freq;
|
||||
Tparam inverseP1, inverseP2;
|
||||
};
|
||||
|
||||
static std::vector<VirtualDevice::VNAMeasurement> interpolateEvenFrequencySteps(std::vector<VirtualDevice::VNAMeasurement> input);
|
||||
std::vector<Point> calculateErrorBoxes(std::vector<VirtualDevice::VNAMeasurement> data_2xthru);
|
||||
std::vector<Point> calculateErrorBoxes(std::vector<VirtualDevice::VNAMeasurement> data_2xthru, std::vector<VirtualDevice::VNAMeasurement> data_fix_dut_fix, double z0);
|
||||
static std::vector<DeviceDriver::VNAMeasurement> interpolateEvenFrequencySteps(std::vector<DeviceDriver::VNAMeasurement> input);
|
||||
std::vector<Point> calculateErrorBoxes(std::vector<DeviceDriver::VNAMeasurement> data_2xthru);
|
||||
std::vector<Point> calculateErrorBoxes(std::vector<DeviceDriver::VNAMeasurement> data_2xthru, std::vector<DeviceDriver::VNAMeasurement> data_fix_dut_fix, double z0);
|
||||
|
||||
std::vector<VirtualDevice::VNAMeasurement> measurements2xthru;
|
||||
std::vector<VirtualDevice::VNAMeasurement> measurementsDUT;
|
||||
std::vector<DeviceDriver::VNAMeasurement> measurements2xthru;
|
||||
std::vector<DeviceDriver::VNAMeasurement> measurementsDUT;
|
||||
double Z0;
|
||||
unsigned int port1, port2;
|
||||
std::vector<Point> points;
|
||||
|
@ -97,7 +97,7 @@ VNA::VNA(AppWindow *window, QString name)
|
||||
|
||||
connect(calLoad, &QAction::triggered, [=](){
|
||||
LoadCalibration();
|
||||
if(window->getDevice() && !cal.validForDevice(window->getDevice()->serial())) {
|
||||
if(window->getDevice() && !cal.validForDevice(window->getDevice()->getSerial())) {
|
||||
InformationBox::ShowMessage("Invalid calibration", "The selected calibration was created for a different device. You can still load it but the resulting "
|
||||
"data likely isn't useful.");
|
||||
}
|
||||
@ -213,7 +213,7 @@ VNA::VNA(AppWindow *window, QString name)
|
||||
|
||||
connect(assignDefaultCal, &QAction::triggered, [=](){
|
||||
if(window->getDevice()) {
|
||||
auto key = "DefaultCalibration"+window->getDevice()->serial();
|
||||
auto key = "DefaultCalibration"+window->getDevice()->getSerial();
|
||||
QSettings settings;
|
||||
auto filename = QFileDialog::getOpenFileName(nullptr, "Load calibration data", settings.value(key).toString(), "Calibration files (*.cal)", nullptr, QFileDialog::DontUseNativeDialog);
|
||||
if(!filename.isEmpty()) {
|
||||
@ -225,7 +225,7 @@ VNA::VNA(AppWindow *window, QString name)
|
||||
});
|
||||
connect(removeDefaultCal, &QAction::triggered, [=](){
|
||||
QSettings settings;
|
||||
settings.remove("DefaultCalibration"+window->getDevice()->serial());
|
||||
settings.remove("DefaultCalibration"+window->getDevice()->getSerial());
|
||||
removeDefaultCal->setEnabled(false);
|
||||
});
|
||||
|
||||
@ -678,10 +678,10 @@ void VNA::deactivate()
|
||||
void VNA::initializeDevice()
|
||||
{
|
||||
defaultCalMenu->setEnabled(true);
|
||||
connect(window->getDevice(), &VirtualDevice::VNAmeasurementReceived, this, &VNA::NewDatapoint, Qt::UniqueConnection);
|
||||
connect(window->getDevice(), &DeviceDriver::VNAmeasurementReceived, this, &VNA::NewDatapoint, Qt::UniqueConnection);
|
||||
// Check if default calibration exists and attempt to load it
|
||||
QSettings s;
|
||||
auto key = "DefaultCalibration"+window->getDevice()->serial();
|
||||
auto key = "DefaultCalibration"+window->getDevice()->getSerial();
|
||||
if (s.contains(key)) {
|
||||
auto filename = s.value(key).toString();
|
||||
qDebug() << "Attempting to load default calibration file " << filename;
|
||||
@ -702,7 +702,7 @@ void VNA::initializeDevice()
|
||||
// Configure initial state of device
|
||||
SettingsChanged();
|
||||
emit deviceInitialized();
|
||||
if(window->getDevice() && !cal.validForDevice(window->getDevice()->serial())) {
|
||||
if(window->getDevice() && !cal.validForDevice(window->getDevice()->getSerial())) {
|
||||
InformationBox::ShowMessage("Invalid calibration", "The current calibration was created for a different device. You can still use it but the resulting "
|
||||
"data likely isn't useful.");
|
||||
}
|
||||
@ -806,7 +806,7 @@ void VNA::fromJSON(nlohmann::json j)
|
||||
|
||||
using namespace std;
|
||||
|
||||
void VNA::NewDatapoint(VirtualDevice::VNAMeasurement m)
|
||||
void VNA::NewDatapoint(DeviceDriver::VNAMeasurement m)
|
||||
{
|
||||
if(isActive != true) {
|
||||
// ignore
|
||||
@ -979,14 +979,14 @@ void VNA::SetStopFreq(double freq)
|
||||
void VNA::SetCenterFreq(double freq)
|
||||
{
|
||||
auto old_span = settings.Freq.stop - settings.Freq.start;
|
||||
if (freq - old_span / 2 <= VirtualDevice::getInfo(window->getDevice()).Limits.minFreq) {
|
||||
if (freq - old_span / 2 <= DeviceDriver::getInfo(window->getDevice()).Limits.VNA.minFreq) {
|
||||
// would shift start frequency below minimum
|
||||
settings.Freq.start = 0;
|
||||
settings.Freq.stop = 2 * freq;
|
||||
} else if(freq + old_span / 2 >= VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq) {
|
||||
} else if(freq + old_span / 2 >= DeviceDriver::getInfo(window->getDevice()).Limits.VNA.maxFreq) {
|
||||
// would shift stop frequency above maximum
|
||||
settings.Freq.start = 2 * freq - VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq;
|
||||
settings.Freq.stop = VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq;
|
||||
settings.Freq.start = 2 * freq - DeviceDriver::getInfo(window->getDevice()).Limits.VNA.maxFreq;
|
||||
settings.Freq.stop = DeviceDriver::getInfo(window->getDevice()).Limits.VNA.maxFreq;
|
||||
} else {
|
||||
settings.Freq.start = freq - old_span / 2;
|
||||
settings.Freq.stop = freq + old_span / 2;
|
||||
@ -996,12 +996,12 @@ void VNA::SetCenterFreq(double freq)
|
||||
|
||||
void VNA::SetSpan(double span)
|
||||
{
|
||||
auto maxFreq = Preferences::getInstance().Acquisition.harmonicMixing ? VirtualDevice::getInfo(window->getDevice()).Limits.maxFreqHarmonic : VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq;
|
||||
auto maxFreq = DeviceDriver::getInfo(window->getDevice()).Limits.VNA.maxFreq;
|
||||
auto old_center = (settings.Freq.start + settings.Freq.stop) / 2;
|
||||
if(old_center < VirtualDevice::getInfo(window->getDevice()).Limits.minFreq + span / 2) {
|
||||
if(old_center < DeviceDriver::getInfo(window->getDevice()).Limits.VNA.minFreq + span / 2) {
|
||||
// would shift start frequency below minimum
|
||||
settings.Freq.start = VirtualDevice::getInfo(window->getDevice()).Limits.minFreq;
|
||||
settings.Freq.stop = VirtualDevice::getInfo(window->getDevice()).Limits.minFreq + span;
|
||||
settings.Freq.start = DeviceDriver::getInfo(window->getDevice()).Limits.VNA.minFreq;
|
||||
settings.Freq.stop = DeviceDriver::getInfo(window->getDevice()).Limits.VNA.minFreq + span;
|
||||
} else if(old_center > maxFreq - span / 2) {
|
||||
// would shift stop frequency above maximum
|
||||
settings.Freq.start = maxFreq - span;
|
||||
@ -1025,8 +1025,8 @@ void VNA::SetFullSpan()
|
||||
settings.Freq.start = pref.Acquisition.fullSpanStart;
|
||||
settings.Freq.stop = pref.Acquisition.fullSpanStop;
|
||||
} else {
|
||||
settings.Freq.start = VirtualDevice::getInfo(window->getDevice()).Limits.minFreq;
|
||||
settings.Freq.stop = VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq;
|
||||
settings.Freq.start = DeviceDriver::getInfo(window->getDevice()).Limits.VNA.minFreq;
|
||||
settings.Freq.stop = DeviceDriver::getInfo(window->getDevice()).Limits.VNA.maxFreq;
|
||||
}
|
||||
}
|
||||
ConstrainAndUpdateFrequencies();
|
||||
@ -1073,10 +1073,10 @@ void VNA::SetLogSweep(bool log)
|
||||
|
||||
void VNA::SetSourceLevel(double level)
|
||||
{
|
||||
if(level > VirtualDevice::getInfo(window->getDevice()).Limits.maxdBm) {
|
||||
level = VirtualDevice::getInfo(window->getDevice()).Limits.maxdBm;
|
||||
} else if(level < VirtualDevice::getInfo(window->getDevice()).Limits.mindBm) {
|
||||
level = VirtualDevice::getInfo(window->getDevice()).Limits.mindBm;
|
||||
if(level > DeviceDriver::getInfo(window->getDevice()).Limits.VNA.maxdBm) {
|
||||
level = DeviceDriver::getInfo(window->getDevice()).Limits.VNA.maxdBm;
|
||||
} else if(level < DeviceDriver::getInfo(window->getDevice()).Limits.VNA.mindBm) {
|
||||
level = DeviceDriver::getInfo(window->getDevice()).Limits.VNA.mindBm;
|
||||
}
|
||||
emit sourceLevelChanged(level);
|
||||
settings.Freq.excitation_power = level;
|
||||
@ -1107,15 +1107,15 @@ void VNA::SetPowerSweepFrequency(double freq)
|
||||
|
||||
void VNA::SetPoints(unsigned int points)
|
||||
{
|
||||
unsigned int maxPoints = Preferences::getInstance().Acquisition.allowSegmentedSweep ? UINT16_MAX : VirtualDevice::getInfo(window->getDevice()).Limits.maxPoints;
|
||||
unsigned int maxPoints = Preferences::getInstance().Acquisition.allowSegmentedSweep ? UINT16_MAX : DeviceDriver::getInfo(window->getDevice()).Limits.VNA.maxPoints;
|
||||
if(points > maxPoints) {
|
||||
points = maxPoints;
|
||||
} else if (points < 2) {
|
||||
points = 2;
|
||||
}
|
||||
if (points > VirtualDevice::getInfo(window->getDevice()).Limits.maxPoints) {
|
||||
if (points > DeviceDriver::getInfo(window->getDevice()).Limits.VNA.maxPoints) {
|
||||
// needs segmented sweep
|
||||
settings.segments = ceil((double) points / VirtualDevice::getInfo(window->getDevice()).Limits.maxPoints);
|
||||
settings.segments = ceil((double) points / DeviceDriver::getInfo(window->getDevice()).Limits.VNA.maxPoints);
|
||||
settings.activeSegment = 0;
|
||||
} else {
|
||||
// can fit all points into one segment
|
||||
@ -1129,10 +1129,10 @@ void VNA::SetPoints(unsigned int points)
|
||||
|
||||
void VNA::SetIFBandwidth(double bandwidth)
|
||||
{
|
||||
if(bandwidth > VirtualDevice::getInfo(window->getDevice()).Limits.maxIFBW) {
|
||||
bandwidth = VirtualDevice::getInfo(window->getDevice()).Limits.maxIFBW;
|
||||
} else if(bandwidth < VirtualDevice::getInfo(window->getDevice()).Limits.minIFBW) {
|
||||
bandwidth = VirtualDevice::getInfo(window->getDevice()).Limits.minIFBW;
|
||||
if(bandwidth > DeviceDriver::getInfo(window->getDevice()).Limits.VNA.maxIFBW) {
|
||||
bandwidth = DeviceDriver::getInfo(window->getDevice()).Limits.VNA.maxIFBW;
|
||||
} else if(bandwidth < DeviceDriver::getInfo(window->getDevice()).Limits.VNA.minIFBW) {
|
||||
bandwidth = DeviceDriver::getInfo(window->getDevice()).Limits.VNA.minIFBW;
|
||||
}
|
||||
settings.bandwidth = bandwidth;
|
||||
emit IFBandwidthChanged(settings.bandwidth);
|
||||
@ -1150,7 +1150,7 @@ void VNA::SetAveraging(unsigned int averages)
|
||||
void VNA::ExcitationRequired()
|
||||
{
|
||||
if(!Preferences::getInstance().Acquisition.alwaysExciteAllPorts) {
|
||||
for(unsigned int i=1;i<VirtualDevice::getInfo(window->getDevice()).ports;i++) {
|
||||
for(unsigned int i=1;i<DeviceDriver::getInfo(window->getDevice()).Limits.VNA.ports;i++) {
|
||||
auto required = traceModel.PortExcitationRequired(i);
|
||||
auto set = find(settings.excitedPorts.begin(), settings.excitedPorts.end(), i) != settings.excitedPorts.end();
|
||||
if(required != set) {
|
||||
@ -1430,21 +1430,14 @@ void VNA::SetupSCPI()
|
||||
|
||||
void VNA::ConstrainAndUpdateFrequencies()
|
||||
{
|
||||
auto& pref = Preferences::getInstance();
|
||||
double maxFreq;
|
||||
if(pref.Acquisition.harmonicMixing) {
|
||||
maxFreq = VirtualDevice::getInfo(window->getDevice()).Limits.maxFreqHarmonic;
|
||||
} else {
|
||||
maxFreq = VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq;
|
||||
}
|
||||
if(settings.Freq.stop > maxFreq) {
|
||||
settings.Freq.stop = maxFreq;
|
||||
if(settings.Freq.stop > DeviceDriver::getInfo(window->getDevice()).Limits.VNA.minFreq) {
|
||||
settings.Freq.stop = DeviceDriver::getInfo(window->getDevice()).Limits.VNA.minFreq;
|
||||
}
|
||||
if(settings.Freq.start > settings.Freq.stop) {
|
||||
settings.Freq.start = settings.Freq.stop;
|
||||
}
|
||||
if(settings.Freq.start < VirtualDevice::getInfo(window->getDevice()).Limits.minFreq) {
|
||||
settings.Freq.start = VirtualDevice::getInfo(window->getDevice()).Limits.minFreq;
|
||||
if(settings.Freq.start < DeviceDriver::getInfo(window->getDevice()).Limits.VNA.minFreq) {
|
||||
settings.Freq.start = DeviceDriver::getInfo(window->getDevice()).Limits.VNA.minFreq;
|
||||
}
|
||||
settings.zerospan = (settings.sweepType == SweepType::Frequency && settings.Freq.start == settings.Freq.stop)
|
||||
|| (settings.sweepType == SweepType::Power && settings.Power.start == settings.Power.stop);
|
||||
@ -1617,7 +1610,7 @@ void VNA::preset()
|
||||
}
|
||||
}
|
||||
// Create default traces
|
||||
createDefaultTracesAndGraphs(VirtualDevice::getInfo(window->getDevice()).ports);
|
||||
createDefaultTracesAndGraphs(DeviceDriver::getInfo(window->getDevice()).Limits.VNA.ports);
|
||||
}
|
||||
|
||||
QString VNA::SweepTypeToString(VNA::SweepType sw)
|
||||
@ -1686,14 +1679,14 @@ void VNA::ConfigureDevice(bool resetTraces, std::function<void(bool)> cb)
|
||||
}
|
||||
changingSettings = true;
|
||||
// assemble VNA protocol settings
|
||||
VirtualDevice::VNASettings s = {};
|
||||
DeviceDriver::VNASettings s = {};
|
||||
s.IFBW = settings.bandwidth;
|
||||
if(Preferences::getInstance().Acquisition.alwaysExciteAllPorts) {
|
||||
for(unsigned int i=0;i<VirtualDevice::getInfo(window->getDevice()).ports;i++) {
|
||||
for(unsigned int i=0;i<DeviceDriver::getInfo(window->getDevice()).Limits.VNA.ports;i++) {
|
||||
s.excitedPorts.push_back(i);
|
||||
}
|
||||
} else {
|
||||
for(unsigned int i=0;i<VirtualDevice::getInfo(window->getDevice()).ports;i++) {
|
||||
for(unsigned int i=0;i<DeviceDriver::getInfo(window->getDevice()).Limits.VNA.ports;i++) {
|
||||
if(traceModel.PortExcitationRequired(i))
|
||||
s.excitedPorts.push_back(i);
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ public slots:
|
||||
bool SaveCalibration(QString filename = "");
|
||||
|
||||
private slots:
|
||||
void NewDatapoint(VirtualDevice::VNAMeasurement m);
|
||||
void NewDatapoint(DeviceDriver::VNAMeasurement m);
|
||||
void StartImpedanceMatching();
|
||||
void StartMixedModeConversion();
|
||||
// Sweep control
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "mode.h"
|
||||
#include "modehandler.h"
|
||||
#include "modewindow.h"
|
||||
#include "Device/librevnausbdriver.h"
|
||||
|
||||
#include <QDockWidget>
|
||||
#include <QDesktopWidget>
|
||||
@ -83,6 +84,9 @@ AppWindow::AppWindow(QWidget *parent)
|
||||
// qDebug().setVerbosity(0);
|
||||
qDebug() << "Application start";
|
||||
|
||||
// Register device drivers
|
||||
deviceDrivers.push_back(new LibreVNAUSBDriver());
|
||||
|
||||
this->setWindowIcon(QIcon(":/app/logo.png"));
|
||||
|
||||
parser.setApplicationDescription(qlibrevnaApp->applicationName());
|
||||
@ -102,7 +106,8 @@ AppWindow::AppWindow(QWidget *parent)
|
||||
} else {
|
||||
Preferences::getInstance().load();
|
||||
}
|
||||
vdevice = nullptr;
|
||||
device = nullptr;
|
||||
// vdevice = nullptr;
|
||||
modeHandler = nullptr;
|
||||
|
||||
if(parser.isSet("port")) {
|
||||
@ -233,12 +238,12 @@ void AppWindow::SetupMenu()
|
||||
modeHandler->getActiveMode()->saveSreenshot();
|
||||
});
|
||||
|
||||
connect(ui->actionManual_Control, &QAction::triggered, this, &AppWindow::StartManualControl);
|
||||
// connect(ui->actionManual_Control, &QAction::triggered, this, &AppWindow::StartManualControl);
|
||||
connect(ui->actionUSB_log, &QAction::triggered, this, &AppWindow::ShowUSBLog);
|
||||
connect(ui->actionFirmware_Update, &QAction::triggered, this, &AppWindow::StartFirmwareUpdateDialog);
|
||||
connect(ui->actionSource_Calibration, &QAction::triggered, this, &AppWindow::SourceCalibrationDialog);
|
||||
connect(ui->actionReceiver_Calibration, &QAction::triggered, this, &AppWindow::ReceiverCalibrationDialog);
|
||||
connect(ui->actionFrequency_Calibration, &QAction::triggered, this, &AppWindow::FrequencyCalibrationDialog);
|
||||
// connect(ui->actionFirmware_Update, &QAction::triggered, this, &AppWindow::StartFirmwareUpdateDialog);
|
||||
// connect(ui->actionSource_Calibration, &QAction::triggered, this, &AppWindow::SourceCalibrationDialog);
|
||||
// connect(ui->actionReceiver_Calibration, &QAction::triggered, this, &AppWindow::ReceiverCalibrationDialog);
|
||||
// connect(ui->actionFrequency_Calibration, &QAction::triggered, this, &AppWindow::FrequencyCalibrationDialog);
|
||||
|
||||
connect(ui->actionPreset, &QAction::triggered, [=](){
|
||||
modeHandler->getActiveMode()->preset();
|
||||
@ -278,14 +283,13 @@ void AppWindow::SetupMenu()
|
||||
}
|
||||
|
||||
// acquisition frequencies may have changed, update
|
||||
UpdateAcquisitionFrequencies();
|
||||
// UpdateAcquisitionFrequencies();
|
||||
|
||||
auto active = modeHandler->getActiveMode();
|
||||
if (active)
|
||||
{
|
||||
active->updateGraphColors();
|
||||
|
||||
if(vdevice) {
|
||||
if(device) {
|
||||
active->initializeDevice();
|
||||
}
|
||||
}
|
||||
@ -311,7 +315,13 @@ void AppWindow::closeEvent(QCloseEvent *event)
|
||||
if(modeHandler->getActiveMode()) {
|
||||
modeHandler->deactivate(modeHandler->getActiveMode());
|
||||
}
|
||||
delete vdevice;
|
||||
if(device) {
|
||||
device->disconnectDevice();
|
||||
device = nullptr;
|
||||
}
|
||||
for(auto driver : deviceDrivers) {
|
||||
delete driver;
|
||||
}
|
||||
delete modeHandler;
|
||||
modeHandler = nullptr;
|
||||
pref.store();
|
||||
@ -325,31 +335,41 @@ bool AppWindow::ConnectToDevice(QString serial)
|
||||
} else {
|
||||
qDebug() << "Trying to connect to" << serial;
|
||||
}
|
||||
if(vdevice) {
|
||||
if(device) {
|
||||
qDebug() << "Already connected to a device, disconnecting first...";
|
||||
DisconnectDevice();
|
||||
}
|
||||
try {
|
||||
qDebug() << "Attempting to connect to device...";
|
||||
vdevice = new VirtualDevice(serial);
|
||||
UpdateStatusBar(AppWindow::DeviceStatusBar::Connected);
|
||||
connect(vdevice, &VirtualDevice::InfoUpdated, this, &AppWindow::DeviceInfoUpdated);
|
||||
connect(vdevice, &VirtualDevice::LogLineReceived, &deviceLog, &DeviceLog::addLine);
|
||||
connect(vdevice, &VirtualDevice::ConnectionLost, this, &AppWindow::DeviceConnectionLost);
|
||||
connect(vdevice, &VirtualDevice::StatusUpdated, this, &AppWindow::DeviceStatusUpdated);
|
||||
connect(vdevice, &VirtualDevice::NeedsFirmwareUpdate, this, &AppWindow::DeviceNeedsUpdate);
|
||||
ui->actionDisconnect->setEnabled(true);
|
||||
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);
|
||||
for(auto driver : deviceDrivers) {
|
||||
if(driver->GetAvailableDevices().count(serial)) {
|
||||
// this driver can connect to the device
|
||||
if(driver->connectDevice(serial)) {
|
||||
device = driver;
|
||||
} else {
|
||||
// failed to connect
|
||||
// TODO show error message
|
||||
}
|
||||
}
|
||||
}
|
||||
UpdateStatusBar(AppWindow::DeviceStatusBar::Connected);
|
||||
connect(device, &DeviceDriver::InfoUpdated, this, &AppWindow::DeviceInfoUpdated);
|
||||
connect(device, &DeviceDriver::LogLineReceived, &deviceLog, &DeviceLog::addLine);
|
||||
connect(device, &DeviceDriver::ConnectionLost, this, &AppWindow::DeviceConnectionLost);
|
||||
connect(device, &DeviceDriver::StatusUpdated, this, &AppWindow::DeviceStatusUpdated);
|
||||
// connect(vdevice, &VirtualDevice::NeedsFirmwareUpdate, this, &AppWindow::DeviceNeedsUpdate);
|
||||
ui->actionDisconnect->setEnabled(true);
|
||||
// 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);
|
||||
|
||||
for(auto d : deviceActionGroup->actions()) {
|
||||
if(d->text() == vdevice->serial()) {
|
||||
if(d->text() == device->getSerial()) {
|
||||
d->blockSignals(true);
|
||||
d->setChecked(true);
|
||||
d->blockSignals(false);
|
||||
@ -357,12 +377,12 @@ bool AppWindow::ConnectToDevice(QString serial)
|
||||
}
|
||||
}
|
||||
for(auto m : modeHandler->getModes()) {
|
||||
connect(vdevice, &VirtualDevice::InfoUpdated, m, &Mode::deviceInfoUpdated);
|
||||
connect(device, &DeviceDriver::InfoUpdated, m, &Mode::deviceInfoUpdated);
|
||||
}
|
||||
|
||||
vdevice->initialize();
|
||||
// vdevice->initialize();
|
||||
|
||||
UpdateAcquisitionFrequencies();
|
||||
// UpdateAcquisitionFrequencies();
|
||||
if (modeHandler->getActiveMode()) {
|
||||
modeHandler->getActiveMode()->initializeDevice();
|
||||
}
|
||||
@ -377,8 +397,10 @@ bool AppWindow::ConnectToDevice(QString serial)
|
||||
|
||||
void AppWindow::DisconnectDevice()
|
||||
{
|
||||
delete vdevice;
|
||||
vdevice = nullptr;
|
||||
if(device) {
|
||||
device->disconnectDevice();
|
||||
device = nullptr;
|
||||
}
|
||||
ui->actionDisconnect->setEnabled(false);
|
||||
ui->actionManual_Control->setEnabled(false);
|
||||
ui->actionFirmware_Update->setEnabled(false);
|
||||
@ -446,8 +468,8 @@ void AppWindow::SetupSCPI()
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}
|
||||
}, [=](QStringList) -> QString {
|
||||
if(vdevice) {
|
||||
return vdevice->serial();
|
||||
if(device) {
|
||||
return device->getSerial();
|
||||
} else {
|
||||
return "Not connected";
|
||||
}
|
||||
@ -519,7 +541,11 @@ void AppWindow::SetupSCPI()
|
||||
}
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, [=](QStringList) -> QString {
|
||||
return VirtualDevice::getStatus(getDevice()).extRef ? "EXT" : "INT";
|
||||
if(device) {
|
||||
return device->asserted(DeviceDriver::Flag::ExtRef) ? "EXT" : "INT";
|
||||
} else {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
}));
|
||||
scpi_dev->add(new SCPICommand("MODE", [=](QStringList params) -> QString {
|
||||
if (params.size() != 1) {
|
||||
@ -557,84 +583,104 @@ void AppWindow::SetupSCPI()
|
||||
auto scpi_status = new SCPINode("STAtus");
|
||||
scpi_dev->add(scpi_status);
|
||||
scpi_status->add(new SCPICommand("UNLOcked", nullptr, [=](QStringList){
|
||||
return VirtualDevice::getStatus(getDevice()).unlocked ? "TRUE" : "FALSE";
|
||||
if(device) {
|
||||
return device->asserted(DeviceDriver::Flag::Unlocked) ? SCPI::getResultName(SCPI::Result::True) : SCPI::getResultName(SCPI::Result::False);
|
||||
} else {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
}));
|
||||
scpi_status->add(new SCPICommand("ADCOVERload", nullptr, [=](QStringList){
|
||||
return VirtualDevice::getStatus(getDevice()).overload ? "TRUE" : "FALSE";
|
||||
if(device) {
|
||||
return device->asserted(DeviceDriver::Flag::Overload) ? SCPI::getResultName(SCPI::Result::True) : SCPI::getResultName(SCPI::Result::False);
|
||||
} else {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
}));
|
||||
scpi_status->add(new SCPICommand("UNLEVel", nullptr, [=](QStringList){
|
||||
return VirtualDevice::getStatus(getDevice()).unlevel ? "TRUE" : "FALSE";
|
||||
if(device) {
|
||||
return device->asserted(DeviceDriver::Flag::Unlevel) ? SCPI::getResultName(SCPI::Result::True) : SCPI::getResultName(SCPI::Result::False);
|
||||
} else {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
}));
|
||||
auto scpi_info = new SCPINode("INFo");
|
||||
scpi_dev->add(scpi_info);
|
||||
scpi_info->add(new SCPICommand("FWREVision", nullptr, [=](QStringList){
|
||||
return QString::number(VirtualDevice::getInfo(getDevice()).FW_major)+"."+QString::number(VirtualDevice::getInfo(getDevice()).FW_minor)+"."+QString::number(VirtualDevice::getInfo(getDevice()).FW_patch);
|
||||
}));
|
||||
scpi_info->add(new SCPICommand("HWREVision", nullptr, [=](QStringList){
|
||||
return QString(VirtualDevice::getInfo(getDevice()).HW_Revision);
|
||||
}));
|
||||
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);
|
||||
if(device) {
|
||||
return device->getInfo().firmware_version;
|
||||
} else {
|
||||
auto dev = vdevice->getDevice();
|
||||
return QString::number(dev->StatusV1().temp_source)+"/"+QString::number(dev->StatusV1().temp_LO1)+"/"+QString::number(dev->StatusV1().temp_MCU);
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
}));
|
||||
scpi_info->add(new SCPICommand("HWREVision", nullptr, [=](QStringList){
|
||||
if(device) {
|
||||
return device->getInfo().hardware_version;
|
||||
} else {
|
||||
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){
|
||||
return QString::number(VirtualDevice::getInfo(getDevice()).Limits.minFreq);
|
||||
return QString::number(DeviceDriver::getInfo(getDevice()).Limits.VNA.minFreq);
|
||||
}));
|
||||
scpi_limits->add(new SCPICommand("MAXFrequency", nullptr, [=](QStringList){
|
||||
return QString::number(VirtualDevice::getInfo(getDevice()).Limits.maxFreq);
|
||||
return QString::number(DeviceDriver::getInfo(getDevice()).Limits.SA.maxFreq);
|
||||
}));
|
||||
scpi_limits->add(new SCPICommand("MINIFBW", nullptr, [=](QStringList){
|
||||
return QString::number(VirtualDevice::getInfo(getDevice()).Limits.minIFBW);
|
||||
return QString::number(DeviceDriver::getInfo(getDevice()).Limits.VNA.minIFBW);
|
||||
}));
|
||||
scpi_limits->add(new SCPICommand("MAXIFBW", nullptr, [=](QStringList){
|
||||
return QString::number(VirtualDevice::getInfo(getDevice()).Limits.maxIFBW);
|
||||
return QString::number(DeviceDriver::getInfo(getDevice()).Limits.VNA.maxIFBW);
|
||||
}));
|
||||
scpi_limits->add(new SCPICommand("MAXPoints", nullptr, [=](QStringList){
|
||||
return QString::number(VirtualDevice::getInfo(getDevice()).Limits.maxPoints);
|
||||
return QString::number(DeviceDriver::getInfo(getDevice()).Limits.VNA.maxPoints);
|
||||
}));
|
||||
scpi_limits->add(new SCPICommand("MINPOWer", nullptr, [=](QStringList){
|
||||
return QString::number(VirtualDevice::getInfo(getDevice()).Limits.mindBm);
|
||||
return QString::number(DeviceDriver::getInfo(getDevice()).Limits.VNA.mindBm);
|
||||
}));
|
||||
scpi_limits->add(new SCPICommand("MAXPOWer", nullptr, [=](QStringList){
|
||||
return QString::number(VirtualDevice::getInfo(getDevice()).Limits.maxdBm);
|
||||
return QString::number(DeviceDriver::getInfo(getDevice()).Limits.VNA.maxdBm);
|
||||
}));
|
||||
scpi_limits->add(new SCPICommand("MINRBW", nullptr, [=](QStringList){
|
||||
return QString::number(VirtualDevice::getInfo(getDevice()).Limits.minRBW);
|
||||
return QString::number(DeviceDriver::getInfo(getDevice()).Limits.SA.minRBW);
|
||||
}));
|
||||
scpi_limits->add(new SCPICommand("MAXRBW", nullptr, [=](QStringList){
|
||||
return QString::number(VirtualDevice::getInfo(getDevice()).Limits.maxRBW);
|
||||
return QString::number(DeviceDriver::getInfo(getDevice()).Limits.SA.maxRBW);
|
||||
}));
|
||||
scpi_limits->add(new SCPICommand("MAXHARMonicfrequency", nullptr, [=](QStringList){
|
||||
return QString::number(VirtualDevice::getInfo(getDevice()).Limits.maxFreqHarmonic);
|
||||
return QString::number(DeviceDriver::getInfo(getDevice()).Limits.VNA.maxFreq);
|
||||
}));
|
||||
|
||||
auto scpi_manual = new SCPINode("MANual");
|
||||
scpi_manual->add(new SCPICommand("STArt",[=](QStringList) -> QString {
|
||||
StartManualControl();
|
||||
// StartManualControl();
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, nullptr));
|
||||
scpi_manual->add(new SCPICommand("STOp",[=](QStringList) -> QString {
|
||||
@ -887,9 +933,12 @@ int AppWindow::UpdateDeviceList()
|
||||
{
|
||||
deviceActionGroup->setExclusive(true);
|
||||
ui->menuConnect_to->clear();
|
||||
auto devices = VirtualDevice::GetAvailableVirtualDevices();
|
||||
if(vdevice) {
|
||||
devices.insert(vdevice->serial());
|
||||
std::set<QString> devices;
|
||||
for(auto driver : deviceDrivers) {
|
||||
devices.merge(driver->GetAvailableDevices());
|
||||
}
|
||||
if(device) {
|
||||
devices.insert(device->getSerial());
|
||||
}
|
||||
int available = 0;
|
||||
bool found = false;
|
||||
@ -902,7 +951,7 @@ int AppWindow::UpdateDeviceList()
|
||||
auto connectAction = ui->menuConnect_to->addAction(d);
|
||||
connectAction->setCheckable(true);
|
||||
connectAction->setActionGroup(deviceActionGroup);
|
||||
if(vdevice && d == vdevice->serial()) {
|
||||
if(device && d == device->getSerial()) {
|
||||
connectAction->setChecked(true);
|
||||
}
|
||||
connect(connectAction, &QAction::triggered, [this, d]() {
|
||||
@ -917,59 +966,56 @@ int AppWindow::UpdateDeviceList()
|
||||
return available;
|
||||
}
|
||||
|
||||
void AppWindow::StartManualControl()
|
||||
{
|
||||
if(!vdevice || vdevice->isCompoundDevice()) {
|
||||
return;
|
||||
}
|
||||
if(manual) {
|
||||
// dialog already active, nothing to do
|
||||
return;
|
||||
}
|
||||
manual = new ManualControlDialog(*vdevice->getDevice(), this);
|
||||
connect(manual, &QDialog::finished, [=](){
|
||||
manual = nullptr;
|
||||
if(vdevice) {
|
||||
modeHandler->getActiveMode()->initializeDevice();
|
||||
}
|
||||
});
|
||||
if(AppWindow::showGUI()) {
|
||||
manual->show();
|
||||
}
|
||||
}
|
||||
//void AppWindow::StartManualControl()
|
||||
//{
|
||||
// if(!vdevice || vdevice->isCompoundDevice()) {
|
||||
// return;
|
||||
// }
|
||||
// if(manual) {
|
||||
// // dialog already active, nothing to do
|
||||
// return;
|
||||
// }
|
||||
// manual = new ManualControlDialog(*vdevice->getDevice(), this);
|
||||
// connect(manual, &QDialog::finished, [=](){
|
||||
// manual = nullptr;
|
||||
// if(vdevice) {
|
||||
// modeHandler->getActiveMode()->initializeDevice();
|
||||
// }
|
||||
// });
|
||||
// if(AppWindow::showGUI()) {
|
||||
// manual->show();
|
||||
// }
|
||||
//}
|
||||
|
||||
void AppWindow::UpdateReferenceToolbar()
|
||||
{
|
||||
toolbars.reference.type->blockSignals(true);
|
||||
toolbars.reference.outFreq->blockSignals(true);
|
||||
if(!vdevice || !vdevice->getInfo().supportsExtRef) {
|
||||
toolbars.reference.type->setEnabled(false);
|
||||
toolbars.reference.outFreq->setEnabled(false);
|
||||
} else {
|
||||
toolbars.reference.type->setEnabled(true);
|
||||
toolbars.reference.outFreq->setEnabled(true);
|
||||
}
|
||||
// save current setting
|
||||
auto refInBuf = toolbars.reference.type->currentText();
|
||||
auto refOutBuf = toolbars.reference.outFreq->currentText();
|
||||
toolbars.reference.type->clear();
|
||||
for(auto in : vdevice->availableExtRefInSettings()) {
|
||||
toolbars.reference.type->addItem(in);
|
||||
}
|
||||
toolbars.reference.outFreq->clear();
|
||||
for(auto out : vdevice->availableExtRefOutSettings()) {
|
||||
toolbars.reference.outFreq->addItem(out);
|
||||
}
|
||||
// restore previous setting if still available
|
||||
if(toolbars.reference.type->findText(refInBuf) >= 0) {
|
||||
toolbars.reference.type->setCurrentText(refInBuf);
|
||||
} else {
|
||||
toolbars.reference.type->setCurrentIndex(0);
|
||||
}
|
||||
if(toolbars.reference.outFreq->findText(refOutBuf) >= 0) {
|
||||
toolbars.reference.outFreq->setCurrentText(refOutBuf);
|
||||
} else {
|
||||
toolbars.reference.outFreq->setCurrentIndex(0);
|
||||
toolbars.reference.type->setEnabled(device || device->supports(DeviceDriver::Feature::ExtRefIn));
|
||||
toolbars.reference.outFreq->setEnabled(device || device->supports(DeviceDriver::Feature::ExtRefOut));
|
||||
if(device) {
|
||||
// save current setting
|
||||
auto refInBuf = toolbars.reference.type->currentText();
|
||||
auto refOutBuf = toolbars.reference.outFreq->currentText();
|
||||
toolbars.reference.type->clear();
|
||||
for(auto in : device->availableExtRefInSettings()) {
|
||||
toolbars.reference.type->addItem(in);
|
||||
}
|
||||
toolbars.reference.outFreq->clear();
|
||||
for(auto out : device->availableExtRefOutSettings()) {
|
||||
toolbars.reference.outFreq->addItem(out);
|
||||
}
|
||||
// restore previous setting if still available
|
||||
if(toolbars.reference.type->findText(refInBuf) >= 0) {
|
||||
toolbars.reference.type->setCurrentText(refInBuf);
|
||||
} else {
|
||||
toolbars.reference.type->setCurrentIndex(0);
|
||||
}
|
||||
if(toolbars.reference.outFreq->findText(refOutBuf) >= 0) {
|
||||
toolbars.reference.outFreq->setCurrentText(refOutBuf);
|
||||
} else {
|
||||
toolbars.reference.outFreq->setCurrentIndex(0);
|
||||
}
|
||||
}
|
||||
toolbars.reference.type->blockSignals(false);
|
||||
toolbars.reference.outFreq->blockSignals(false);
|
||||
@ -978,27 +1024,11 @@ void AppWindow::UpdateReferenceToolbar()
|
||||
|
||||
void AppWindow::UpdateReference()
|
||||
{
|
||||
if(!vdevice) {
|
||||
if(!device) {
|
||||
// can't update without a device connected
|
||||
return;
|
||||
}
|
||||
vdevice->setExtRef(toolbars.reference.type->currentText(), toolbars.reference.outFreq->currentText());
|
||||
}
|
||||
|
||||
void AppWindow::UpdateAcquisitionFrequencies()
|
||||
{
|
||||
if(!vdevice) {
|
||||
return;
|
||||
}
|
||||
Protocol::PacketInfo p;
|
||||
p.type = Protocol::PacketType::AcquisitionFrequencySettings;
|
||||
auto& pref = Preferences::getInstance();
|
||||
p.acquisitionFrequencySettings.IF1 = pref.Acquisition.IF1;
|
||||
p.acquisitionFrequencySettings.ADCprescaler = pref.Acquisition.ADCprescaler;
|
||||
p.acquisitionFrequencySettings.DFTphaseInc = pref.Acquisition.DFTPhaseInc;
|
||||
for(auto dev : vdevice->getDevices()) {
|
||||
dev->SendPacket(p);
|
||||
}
|
||||
device->setExtRef(toolbars.reference.type->currentText(), toolbars.reference.outFreq->currentText());
|
||||
}
|
||||
|
||||
void AppWindow::ShowUSBLog()
|
||||
@ -1009,34 +1039,21 @@ void AppWindow::ShowUSBLog()
|
||||
}
|
||||
}
|
||||
|
||||
void AppWindow::StartFirmwareUpdateDialog()
|
||||
{
|
||||
if(!vdevice || vdevice->isCompoundDevice()) {
|
||||
return;
|
||||
}
|
||||
auto fw_update = new FirmwareUpdateDialog(vdevice->getDevice());
|
||||
connect(fw_update, &FirmwareUpdateDialog::DeviceRebooting, this, &AppWindow::DisconnectDevice);
|
||||
connect(fw_update, &FirmwareUpdateDialog::DeviceRebooted, this, &AppWindow::ConnectToDevice);
|
||||
if(AppWindow::showGUI()) {
|
||||
fw_update->exec();
|
||||
}
|
||||
}
|
||||
|
||||
void AppWindow::DeviceNeedsUpdate(int reported, int expected)
|
||||
{
|
||||
auto ret = InformationBox::AskQuestion("Warning",
|
||||
"The device reports a different protocol"
|
||||
"version (" + QString::number(reported) + ") than expected (" + QString::number(expected) + ").\n"
|
||||
"A firmware update is strongly recommended. Do you want to update now?", false);
|
||||
if (ret) {
|
||||
if (vdevice->isCompoundDevice()) {
|
||||
InformationBox::ShowError("Unable to update the firmware", "The connected device is a compound device, direct firmware"
|
||||
" update is not supported. Connect to each LibreVNA individually for the update.");
|
||||
return;
|
||||
}
|
||||
StartFirmwareUpdateDialog();
|
||||
}
|
||||
}
|
||||
//void AppWindow::DeviceNeedsUpdate(int reported, int expected)
|
||||
//{
|
||||
// auto ret = InformationBox::AskQuestion("Warning",
|
||||
// "The device reports a different protocol"
|
||||
// "version (" + QString::number(reported) + ") than expected (" + QString::number(expected) + ").\n"
|
||||
// "A firmware update is strongly recommended. Do you want to update now?", false);
|
||||
// if (ret) {
|
||||
// if (vdevice->isCompoundDevice()) {
|
||||
// InformationBox::ShowError("Unable to update the firmware", "The connected device is a compound device, direct firmware"
|
||||
// " update is not supported. Connect to each LibreVNA individually for the update.");
|
||||
// return;
|
||||
// }
|
||||
// StartFirmwareUpdateDialog();
|
||||
// }
|
||||
//}
|
||||
|
||||
void AppWindow::DeviceStatusUpdated(VirtualDevice::Status status)
|
||||
{
|
||||
@ -1054,38 +1071,38 @@ void AppWindow::DeviceInfoUpdated()
|
||||
UpdateReferenceToolbar();
|
||||
}
|
||||
|
||||
void AppWindow::SourceCalibrationDialog()
|
||||
{
|
||||
if(!vdevice || vdevice->isCompoundDevice()) {
|
||||
return;
|
||||
}
|
||||
auto d = new SourceCalDialog(vdevice->getDevice(), modeHandler);
|
||||
if(AppWindow::showGUI()) {
|
||||
d->exec();
|
||||
}
|
||||
}
|
||||
//void AppWindow::SourceCalibrationDialog()
|
||||
//{
|
||||
// if(!vdevice || vdevice->isCompoundDevice()) {
|
||||
// return;
|
||||
// }
|
||||
// auto d = new SourceCalDialog(vdevice->getDevice(), modeHandler);
|
||||
// if(AppWindow::showGUI()) {
|
||||
// d->exec();
|
||||
// }
|
||||
//}
|
||||
|
||||
void AppWindow::ReceiverCalibrationDialog()
|
||||
{
|
||||
if(!vdevice || vdevice->isCompoundDevice()) {
|
||||
return;
|
||||
}
|
||||
auto d = new ReceiverCalDialog(vdevice->getDevice(), modeHandler);
|
||||
if(AppWindow::showGUI()) {
|
||||
d->exec();
|
||||
}
|
||||
}
|
||||
//void AppWindow::ReceiverCalibrationDialog()
|
||||
//{
|
||||
// if(!vdevice || vdevice->isCompoundDevice()) {
|
||||
// return;
|
||||
// }
|
||||
// auto d = new ReceiverCalDialog(vdevice->getDevice(), modeHandler);
|
||||
// if(AppWindow::showGUI()) {
|
||||
// d->exec();
|
||||
// }
|
||||
//}
|
||||
|
||||
void AppWindow::FrequencyCalibrationDialog()
|
||||
{
|
||||
if(!vdevice || vdevice->isCompoundDevice()) {
|
||||
return;
|
||||
}
|
||||
auto d = new FrequencyCalDialog(vdevice->getDevice(), modeHandler);
|
||||
if(AppWindow::showGUI()) {
|
||||
d->exec();
|
||||
}
|
||||
}
|
||||
//void AppWindow::FrequencyCalibrationDialog()
|
||||
//{
|
||||
// if(!vdevice || vdevice->isCompoundDevice()) {
|
||||
// return;
|
||||
// }
|
||||
// auto d = new FrequencyCalDialog(vdevice->getDevice(), modeHandler);
|
||||
// if(AppWindow::showGUI()) {
|
||||
// d->exec();
|
||||
// }
|
||||
//}
|
||||
|
||||
void AppWindow::SaveSetup(QString filename)
|
||||
{
|
||||
@ -1158,10 +1175,10 @@ void AppWindow::LoadSetup(nlohmann::json j)
|
||||
|
||||
// Disconnect device prior to deleting and creating new modes. This prevents excessice and unnnecessary configuration of the device
|
||||
QString serial = QString();
|
||||
if(vdevice->getConnected()) {
|
||||
serial = vdevice->serial();
|
||||
delete vdevice;
|
||||
vdevice = nullptr;
|
||||
if(device) {
|
||||
serial = device->getSerial();
|
||||
device->disconnectDevice();
|
||||
device = nullptr;
|
||||
}
|
||||
|
||||
modeHandler->closeModes();
|
||||
@ -1214,9 +1231,9 @@ void AppWindow::LoadSetup(nlohmann::json j)
|
||||
}
|
||||
}
|
||||
|
||||
VirtualDevice *AppWindow::getDevice()
|
||||
DeviceDriver *AppWindow::getDevice()
|
||||
{
|
||||
return vdevice;
|
||||
return device;
|
||||
}
|
||||
|
||||
QStackedWidget *AppWindow::getCentral() const
|
||||
@ -1290,8 +1307,8 @@ void AppWindow::UpdateStatusBar(DeviceStatusBar status)
|
||||
{
|
||||
switch(status) {
|
||||
case DeviceStatusBar::Connected:
|
||||
lConnectionStatus.setText("Connected to " + vdevice->serial());
|
||||
qInfo() << "Connected to" << vdevice->serial();
|
||||
lConnectionStatus.setText("Connected to " + device->getSerial());
|
||||
qInfo() << "Connected to" << device->getSerial();
|
||||
break;
|
||||
case DeviceStatusBar::Disconnected:
|
||||
lConnectionStatus.setText("No device connected");
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "scpi.h"
|
||||
#include "tcpserver.h"
|
||||
#include "Device/manualcontroldialog.h"
|
||||
#include "Device/devicedriver.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QMainWindow>
|
||||
@ -42,7 +43,7 @@ public:
|
||||
Ui::MainWindow *getUi() const;
|
||||
QStackedWidget *getCentral() const;
|
||||
ModeHandler* getModeHandler() const;
|
||||
VirtualDevice *getDevice();
|
||||
DeviceDriver *getDevice();
|
||||
|
||||
const QString& getAppVersion() const;
|
||||
const QString& getAppGitHash() const;
|
||||
@ -60,18 +61,18 @@ private slots:
|
||||
bool ConnectToDevice(QString serial = QString());
|
||||
void DisconnectDevice();
|
||||
int UpdateDeviceList();
|
||||
void StartManualControl();
|
||||
// void StartManualControl();
|
||||
void UpdateReferenceToolbar();
|
||||
void UpdateReference();
|
||||
void UpdateAcquisitionFrequencies();
|
||||
// void UpdateAcquisitionFrequencies();
|
||||
void ShowUSBLog();
|
||||
void StartFirmwareUpdateDialog();
|
||||
// void StartFirmwareUpdateDialog();
|
||||
void DeviceNeedsUpdate(int reported, int expected);
|
||||
void DeviceStatusUpdated(VirtualDevice::Status status);
|
||||
void DeviceInfoUpdated();
|
||||
void SourceCalibrationDialog();
|
||||
void ReceiverCalibrationDialog();
|
||||
void FrequencyCalibrationDialog();
|
||||
// void SourceCalibrationDialog();
|
||||
// void ReceiverCalibrationDialog();
|
||||
// void FrequencyCalibrationDialog();
|
||||
nlohmann::json SaveSetup();
|
||||
void SaveSetup(QString filename);
|
||||
void LoadSetup(QString filename);
|
||||
@ -103,7 +104,11 @@ private:
|
||||
} toolbars;
|
||||
|
||||
ModeHandler *modeHandler;
|
||||
VirtualDevice *vdevice;
|
||||
|
||||
// VirtualDevice *vdevice;
|
||||
std::vector<DeviceDriver*> deviceDrivers;
|
||||
DeviceDriver *device;
|
||||
|
||||
DeviceLog deviceLog;
|
||||
QString deviceSerial;
|
||||
QActionGroup *deviceActionGroup;
|
||||
|
@ -23,7 +23,7 @@ void Averaging::setAverages(unsigned int a)
|
||||
reset(avg.size());
|
||||
}
|
||||
|
||||
VirtualDevice::VNAMeasurement Averaging::process(VirtualDevice::VNAMeasurement d)
|
||||
DeviceDriver::VNAMeasurement Averaging::process(DeviceDriver::VNAMeasurement d)
|
||||
{
|
||||
if(d.measurements.size() != numMeasurements) {
|
||||
numMeasurements = d.measurements.size();
|
||||
@ -42,7 +42,7 @@ VirtualDevice::VNAMeasurement Averaging::process(VirtualDevice::VNAMeasurement d
|
||||
return d;
|
||||
}
|
||||
|
||||
VirtualDevice::SAMeasurement Averaging::process(VirtualDevice::SAMeasurement d)
|
||||
DeviceDriver::SAMeasurement Averaging::process(DeviceDriver::SAMeasurement d)
|
||||
{
|
||||
if(d.measurements.size() != numMeasurements) {
|
||||
numMeasurements = d.measurements.size();
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef AVERAGING_H
|
||||
#define AVERAGING_H
|
||||
|
||||
#include "Device/virtualdevice.h"
|
||||
#include "Device/devicedriver.h"
|
||||
|
||||
#include <array>
|
||||
#include <deque>
|
||||
@ -18,8 +18,8 @@ public:
|
||||
Averaging();
|
||||
void reset(unsigned int points);
|
||||
void setAverages(unsigned int a);
|
||||
VirtualDevice::VNAMeasurement process(VirtualDevice::VNAMeasurement d);
|
||||
VirtualDevice::SAMeasurement process(VirtualDevice::SAMeasurement d);
|
||||
DeviceDriver::VNAMeasurement process(DeviceDriver::VNAMeasurement d);
|
||||
DeviceDriver::SAMeasurement process(DeviceDriver::SAMeasurement d);
|
||||
// Returns the number of averaged sweeps. Value is incremented whenever the last point of the sweep is added.
|
||||
// Returned values are in range 0 to averages
|
||||
unsigned int getLevel();
|
||||
|
@ -93,7 +93,7 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>3</number>
|
||||
<number>6</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="Startup">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
@ -107,8 +107,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>530</width>
|
||||
<height>937</height>
|
||||
<width>749</width>
|
||||
<height>920</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||
@ -1795,8 +1795,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>168</width>
|
||||
<height>127</height>
|
||||
<width>763</width>
|
||||
<height>561</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
@ -1885,8 +1885,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>126</width>
|
||||
<height>90</height>
|
||||
<width>763</width>
|
||||
<height>561</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_24">
|
||||
@ -1956,8 +1956,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>263</width>
|
||||
<height>241</height>
|
||||
<width>763</width>
|
||||
<height>561</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_19">
|
||||
|
@ -21,7 +21,9 @@ public:
|
||||
bool openFromFileDialog(QString title, QString filetype);
|
||||
bool saveToFileDialog(QString title, QString filetype, QString ending = "");
|
||||
|
||||
using SettingDescription = struct {
|
||||
class SettingDescription {
|
||||
public:
|
||||
SettingDescription(QPointerVariant var, QString name, QVariant def) : var(var), name(name), def(def){}
|
||||
QPointerVariant var;
|
||||
QString name;
|
||||
QVariant def;
|
||||
|
@ -13,7 +13,7 @@ PortExtensionTests::PortExtensionTests() : QObject(nullptr)
|
||||
constexpr int steps = 501;
|
||||
for(int i=0;i<steps;i++) {
|
||||
double f = startFreq + (stopFreq - startFreq) * i / (steps - 1);
|
||||
VirtualDevice::VNAMeasurement m;
|
||||
DeviceDriver::VNAMeasurement m;
|
||||
m.frequency = f;
|
||||
m.dBm = -10;
|
||||
m.pointNum = i;
|
||||
|
@ -15,7 +15,7 @@ private slots:
|
||||
void autocalc();
|
||||
void correct();
|
||||
private:
|
||||
std::vector<VirtualDevice::VNAMeasurement> dummyData;
|
||||
std::vector<DeviceDriver::VNAMeasurement> dummyData;
|
||||
};
|
||||
|
||||
#endif // PORTEXTENSIONTESTS_H
|
||||
|
Loading…
Reference in New Issue
Block a user