WIP: device driver abstraction

This commit is contained in:
Jan Käberich 2023-01-17 00:25:58 +01:00
parent db6d823e0f
commit cde564299c
19 changed files with 1729 additions and 1345 deletions

View File

@ -277,7 +277,7 @@ void LibreCALDialog::startCalibration()
}
ui->lCalibrationStatus->setText("Creating calibration measurements...");
cal->reset();
auto vnaPorts = VirtualDevice::getInfo(VirtualDevice::getConnected()).ports;
auto vnaPorts = DeviceDriver::getInfo(DeviceDriver::getActiveDriver()).Limits.VNA.ports;
set<CalibrationMeasurement::Base*> openMeasurements;
set<CalibrationMeasurement::Base*> shortMeasurements;
set<CalibrationMeasurement::Base*> loadMeasurements;
@ -432,7 +432,7 @@ void LibreCALDialog::createPortAssignmentUI()
while(layout->rowCount() > 1) {
layout->removeRow(1);
}
auto vnaPorts = VirtualDevice::getInfo(VirtualDevice::getConnected()).ports;
auto vnaPorts = DeviceDriver::getInfo(DeviceDriver::getActiveDriver()).Limits.VNA.ports;
portAssignment.resize(vnaPorts, 0);
auto calPorts = 0;
if(device) {

View File

@ -8,6 +8,7 @@
#include <QString>
#include <QMessageBox>
#include <mutex>
#include "devicedriver.h"
using namespace std;
@ -20,126 +21,126 @@ static constexpr USBID IDs[] = {
{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(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;
}
// qDebug() << libusb_error_name(transfer->status);
switch(transfer->status) {
case LIBUSB_TRANSFER_COMPLETED:
received_size += transfer->actual_length;
// Change/insert/delete random data to check the data handling for robustness
// srand((unsigned)time(0));
// for(unsigned int i=0;i<received_size;i++) {
// auto r = rand() % 100;
// if(r == 0) {
// // modify this byte
// buffer[i] = rand() % 256;
// } else if(r == 1) {
// // insert random byte
// memmove(&buffer[i+1], &buffer[i], received_size - i);
// buffer[i] = rand() % 256;
// received_size++;
// } else if(r == 2) {
// // remove byte
// memmove(&buffer[i], &buffer[i+1], received_size - i - 1);
// received_size--;
// }
//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";
// }
// qDebug() << transfer->actual_length <<"total:" << received_size;
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);
}
// }
// delete[] buffer;
//}
void USBInBuffer::CallbackTrampoline(libusb_transfer *transfer)
{
auto usb = (USBInBuffer*) transfer->user_data;
usb->Callback(transfer);
}
//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;
// }
//}
uint8_t *USBInBuffer::getBuffer() const
{
return buffer;
}
//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;
// }
//// qDebug() << libusb_error_name(transfer->status);
// switch(transfer->status) {
// case LIBUSB_TRANSFER_COMPLETED:
// received_size += transfer->actual_length;
// // Change/insert/delete random data to check the data handling for robustness
//// srand((unsigned)time(0));
//// for(unsigned int i=0;i<received_size;i++) {
//// auto r = rand() % 100;
//// if(r == 0) {
//// // modify this byte
//// buffer[i] = rand() % 256;
//// } else if(r == 1) {
//// // insert random byte
//// memmove(&buffer[i+1], &buffer[i], received_size - i);
//// buffer[i] = rand() % 256;
//// received_size++;
//// } else if(r == 2) {
//// // remove byte
//// memmove(&buffer[i], &buffer[i+1], received_size - i - 1);
//// received_size--;
//// }
//// }
//// qDebug() << transfer->actual_length <<"total:" << received_size;
// 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;
//}
static constexpr Protocol::DeviceInfo defaultInfo = {
.ProtocolVersion = Protocol::Version,

View File

@ -3,6 +3,8 @@
#include "../../VNA_embedded/Application/Communication/Protocol.hpp"
#include "librevnausbdriver.h"
#include <functional>
#include <libusb-1.0/libusb.h>
#include <thread>
@ -18,31 +20,31 @@ Q_DECLARE_METATYPE(Protocol::ManualStatusV1)
Q_DECLARE_METATYPE(Protocol::SpectrumAnalyzerResult)
Q_DECLARE_METATYPE(Protocol::AmplitudeCorrectionPoint)
class USBInBuffer : public QObject {
Q_OBJECT
public:
USBInBuffer(libusb_device_handle *handle, unsigned char endpoint, int buffer_size);
~USBInBuffer();
//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;
// void removeBytes(int handled_bytes);
// int getReceived() const;
// uint8_t *getBuffer() const;
signals:
void DataReceived();
void TransferError();
//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;
};
//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 Device : public QObject

View File

@ -20,3 +20,85 @@ void DeviceDriver::disconnectDevice()
disconnect();
activeDriver = nullptr;
}
unsigned int DeviceDriver::SApoints() {
if(activeDriver) {
return activeDriver->getSApoints();
} else {
// return default value instead
return 1001;
}
}
Sparam DeviceDriver::VNAMeasurement::toSparam(int port1, int port2) const
{
Sparam S;
S.m11 = measurements.at("S"+QString::number(port1)+QString::number(port1));
S.m12 = measurements.at("S"+QString::number(port1)+QString::number(port2));
S.m21 = measurements.at("S"+QString::number(port2)+QString::number(port1));
S.m22 = measurements.at("S"+QString::number(port2)+QString::number(port2));
return S;
}
void DeviceDriver::VNAMeasurement::fromSparam(Sparam S, int port1, int port2)
{
QString s11 = "S"+QString::number(port1)+QString::number(port1);
QString s12 = "S"+QString::number(port1)+QString::number(port2);
QString s21 = "S"+QString::number(port2)+QString::number(port1);
QString s22 = "S"+QString::number(port2)+QString::number(port2);
if(measurements.count(s11)) {
measurements[s11] = S.m11;
}
if(measurements.count(s12)) {
measurements[s12] = S.m12;
}
if(measurements.count(s21)) {
measurements[s21] = S.m21;
}
if(measurements.count(s22)) {
measurements[s22] = S.m22;
}
}
DeviceDriver::VNAMeasurement DeviceDriver::VNAMeasurement::interpolateTo(const DeviceDriver::VNAMeasurement &to, double a)
{
VNAMeasurement ret;
ret.frequency = frequency * (1.0 - a) + to.frequency * a;
ret.dBm = dBm * (1.0 - a) + to.dBm * a;
ret.Z0 = Z0 * (1.0 - a) + to.Z0 * a;
for(auto m : measurements) {
if(to.measurements.count(m.first) == 0) {
throw std::runtime_error("Nothing to interpolate to, expected measurement +\""+m.first.toStdString()+"\"");
}
ret.measurements[m.first] = measurements[m.first] * (1.0 - a) + to.measurements.at(m.first) * a;
}
return ret;
}
DeviceDriver::Info::Info()
{
firmware_version = "missing";
hardware_version = "missing";
Limits.VNA.ports = 2;
Limits.VNA.minFreq = 0;
Limits.VNA.maxFreq = 6000000000;
Limits.VNA.mindBm = -100;
Limits.VNA.maxdBm = 30;
Limits.VNA.minIFBW = 1;
Limits.VNA.maxIFBW = 1000000;
Limits.VNA.maxPoints = 65535;
Limits.Generator.ports = 2;
Limits.Generator.minFreq = 0;
Limits.Generator.maxFreq = 6000000000;
Limits.Generator.mindBm = -100;
Limits.Generator.maxdBm = 30;
Limits.SA.ports = 2;
Limits.SA.minFreq = 0;
Limits.SA.maxFreq = 6000000000;
Limits.SA.mindBm = -100;
Limits.SA.maxdBm = 30;
Limits.SA.minRBW = 1;
Limits.SA.maxRBW = 1000000;
}

View File

@ -78,7 +78,7 @@ public:
class Info {
public:
// TODO create constructor with default values
Info();
QString firmware_version;
QString hardware_version;
std::set<Feature> supportedFeatures;
@ -161,6 +161,13 @@ public:
*/
virtual std::set<Flag> getFlags() = 0;
signals:
/**
* @brief Emit this signal whenever a flag changes
*/
void FlagsUpdated();
public:
/**
* @brief Checks whether a specific flag is asserted
* @param f Flag to check
@ -428,6 +435,14 @@ public:
}
}
/**
* @brief Registers metatypes within the Qt Framework.
*
* If the device driver uses a queued signal/slot connection with custom data types, these types must be registered before emitting the signal.
* Register them within this function with qRegisterMetaType<Type>("Name");
*/
virtual void registerTypes() {}
signals:
/**
* @brief Emit this signal when the device connection has been lost unexpectedly
@ -445,6 +460,7 @@ public:
bool connectDevice(QString serial);
void disconnectDevice();
static DeviceDriver* getActiveDriver() {return activeDriver;}
static unsigned int SApoints();
private:
static DeviceDriver *activeDriver;

View File

@ -2,6 +2,96 @@
using namespace std;
class Reference
{
public:
enum class TypeIn {
Internal,
External,
Auto,
None
};
enum class OutFreq {
MHZ10,
MHZ100,
Off,
None
};
static QString OutFreqToLabel(Reference::OutFreq t)
{
switch(t) {
case OutFreq::MHZ10: return "10 MHz";
case OutFreq::MHZ100: return "100 MHz";
case OutFreq::Off: return "Off";
default: return "Invalid";
}
}
static QString OutFreqToKey(Reference::OutFreq f)
{
switch(f) {
case OutFreq::MHZ10: return "10 MHz";
case OutFreq::MHZ100: return "100 MHz";
case OutFreq::Off: return "Off";
default: return "Invalid";
}
}
static Reference::OutFreq KeyToOutFreq(QString key)
{
for (auto r: Reference::getOutFrequencies()) {
if(OutFreqToKey(r) == key|| OutFreqToLabel(r) == key) {
return r;
}
}
// not found
return Reference::OutFreq::None;
}
static QString TypeToLabel(TypeIn t)
{
switch(t) {
case TypeIn::Internal: return "Internal";
case TypeIn::External: return "External";
case TypeIn::Auto: return "Auto";
default: return "Invalid";
}
}
static const QString TypeToKey(TypeIn t)
{
switch(t) {
case TypeIn::Internal: return "Int";
case TypeIn::External: return "Ext";
case TypeIn::Auto: return "Auto";
default: return "Invalid";
}
}
static TypeIn KeyToType(QString key)
{
for (auto r: Reference::getReferencesIn()) {
if(TypeToKey(r) == key || TypeToLabel(r) == key) {
return r;
}
}
// not found
return TypeIn::None;
}
static std::vector<Reference::TypeIn> getReferencesIn()
{
return {TypeIn::Internal, TypeIn::External, TypeIn::Auto};
}
static std::vector<Reference::OutFreq> getOutFrequencies()
{
return {OutFreq::Off, OutFreq::MHZ10, OutFreq::MHZ100};
}
};
LibreVNADriver::LibreVNADriver()
{
connected = false;
@ -142,6 +232,7 @@ bool LibreVNADriver::setSA(const DeviceDriver::SASettings &s, std::function<void
zerospan = s.freqStart == s.freqStop;
Protocol::PacketInfo p = {};
p.type = Protocol::PacketType::SpectrumAnalyzerSettings;
p.spectrumSettings.f_start = s.freqStart;
p.spectrumSettings.f_stop = s.freqStop;
@ -207,6 +298,62 @@ bool LibreVNADriver::setIdle(std::function<void (bool)> cb)
});
}
QStringList LibreVNADriver::availableExtRefInSettings()
{
QStringList ret;
for(auto r : Reference::getReferencesIn()) {
ret.push_back(Reference::TypeToLabel(r));
}
return ret;
}
QStringList LibreVNADriver::availableExtRefOutSettings()
{
QStringList ret;
for(auto r : Reference::getOutFrequencies()) {
ret.push_back(Reference::OutFreqToLabel(r));
}
return ret;
}
bool LibreVNADriver::setExtRef(QString option_in, QString option_out)
{
auto refIn = Reference::KeyToType(option_in);
if(refIn == Reference::TypeIn::None) {
refIn = Reference::TypeIn::Internal;
}
auto refOut = Reference::KeyToOutFreq(option_out);
if(refOut == Reference::OutFreq::None) {
refOut = Reference::OutFreq::Off;
}
Protocol::PacketInfo p = {};
p.type = Protocol::PacketType::Reference;
switch(refIn) {
case Reference::TypeIn::Internal:
case Reference::TypeIn::None:
p.reference.UseExternalRef = 0;
p.reference.AutomaticSwitch = 0;
break;
case Reference::TypeIn::Auto:
p.reference.UseExternalRef = 0;
p.reference.AutomaticSwitch = 1;
break;
case Reference::TypeIn::External:
p.reference.UseExternalRef = 1;
p.reference.AutomaticSwitch = 0;
break;
}
switch(refOut) {
case Reference::OutFreq::None:
case Reference::OutFreq::Off: p.reference.ExtRefOuputFreq = 0; break;
case Reference::OutFreq::MHZ10: p.reference.ExtRefOuputFreq = 10000000; break;
case Reference::OutFreq::MHZ100: p.reference.ExtRefOuputFreq = 100000000; break;
}
return SendPacket(p);
}
void LibreVNADriver::handleReceivedPacket(const Protocol::PacketInfo &packet)
{
emit passOnReceivedPacket(packet);
@ -253,6 +400,7 @@ void LibreVNADriver::handleReceivedPacket(const Protocol::PacketInfo &packet)
case Protocol::PacketType::DeviceStatusV1:
lastStatus = packet.statusV1;
emit StatusUpdated();
emit FlagsUpdated();
break;
case Protocol::PacketType::VNADatapoint: {
VNAMeasurement m;

View File

@ -249,6 +249,12 @@ void LibreVNAUSBDriver::disconnect()
}
}
void LibreVNAUSBDriver::registerTypes()
{
qRegisterMetaType<Protocol::PacketInfo>("LibreVNAUSBPacket");
qRegisterMetaType<TransmissionResult>("LibreVNAUSBResult");
}
void LibreVNAUSBDriver::ReceivedData()
{
Protocol::PacketInfo packet;
@ -429,3 +435,32 @@ void LibreVNAUSBDriver::SearchDevices(std::function<bool (libusb_device_handle *
}
libusb_free_device_list(devList, 1);
}
bool LibreVNAUSBDriver::startNextTransmission()
{
if(transmissionQueue.isEmpty() || !connected) {
// nothing more to transmit
transmissionActive = false;
return false;
}
transmissionActive = true;
auto t = transmissionQueue.head();
unsigned char buffer[1024];
unsigned int length = Protocol::EncodePacket(t.packet, buffer, sizeof(buffer));
if(!length) {
qCritical() << "Failed to encode packet";
return false;
}
int actual_length;
auto &log = DeviceUSBLog::getInstance();
log.addPacket(t.packet);
auto ret = libusb_bulk_transfer(m_handle, EP_Data_Out_Addr, buffer, length, &actual_length, 0);
if(ret < 0) {
qCritical() << "Error sending data: "
<< libusb_strerror((libusb_error) ret);
return false;
}
transmissionTimer.start(t.timeout);
// qDebug() << "Transmission started, queue at " << transmissionQueue.size();
return true;
}

View File

@ -10,6 +10,9 @@
#include <QQueue>
#include <QTimer>
Q_DECLARE_METATYPE(Protocol::PacketInfo)
Q_DECLARE_METATYPE(LibreVNADriver::TransmissionResult)
class USBInBuffer : public QObject {
Q_OBJECT
public:
@ -63,6 +66,14 @@ public:
*/
virtual void disconnect() override;
/**
* @brief Registers metatypes within the Qt Framework.
*
* If the device driver uses a queued signal/slot connection with custom data types, these types must be registered before emitting the signal.
* Register them within this function with qRegisterMetaType<Type>("Name");
*/
virtual void registerTypes();
private slots:
void ReceivedData();
void ReceivedLog();
@ -101,11 +112,6 @@ private:
bool transmissionActive;
std::thread *m_receiveThread;
Protocol::DeviceInfo info;
bool infoValid;
union {
Protocol::DeviceStatusV1 v1;
} status;
std::mutex accessMutex;
};

File diff suppressed because it is too large Load Diff

View File

@ -1,220 +1,220 @@
#ifndef VIRTUALDEVICE_H
#define VIRTUALDEVICE_H
//#ifndef VIRTUALDEVICE_H
//#define VIRTUALDEVICE_H
#include "device.h"
#include "Tools/parameters.h"
#include "compounddevice.h"
//#include "device.h"
//#include "Tools/parameters.h"
//#include "compounddevice.h"
#include <set>
#include <complex>
//#include <set>
//#include <complex>
#include <QObject>
//#include <QObject>
class VirtualDevice : public QObject
{
Q_OBJECT
public:
VirtualDevice(QString serial = "");
~VirtualDevice();
//class VirtualDevice : public QObject
//{
// Q_OBJECT
//public:
// VirtualDevice(QString serial = "");
// ~VirtualDevice();
class Info {
public:
Info();
Info(Device *dev);
// class Info {
// public:
// Info();
// Info(Device *dev);
void subset(const Info &merge);
// void subset(const Info &merge);
uint16_t ProtocolVersion;
uint8_t FW_major;
uint8_t FW_minor;
uint8_t FW_patch;
uint8_t hardware_version;
char HW_Revision;
unsigned int ports;
bool supportsVNAmode;
bool supportsSAmode;
bool supportsSGmode;
bool supportsExtRef;
struct {
double minFreq, maxFreq, maxFreqHarmonic;
double minIFBW, maxIFBW;
unsigned int maxPoints;
double mindBm;
double maxdBm;
double minRBW, maxRBW;
} Limits;
};
// uint16_t ProtocolVersion;
// uint8_t FW_major;
// uint8_t FW_minor;
// uint8_t FW_patch;
// uint8_t hardware_version;
// char HW_Revision;
// unsigned int ports;
// bool supportsVNAmode;
// bool supportsSAmode;
// bool supportsSGmode;
// bool supportsExtRef;
// struct {
// double minFreq, maxFreq, maxFreqHarmonic;
// double minIFBW, maxIFBW;
// unsigned int maxPoints;
// double mindBm;
// double maxdBm;
// double minRBW, maxRBW;
// } Limits;
// };
class Status {
public:
Status();
Status(Device *dev);
// class Status {
// public:
// Status();
// Status(Device *dev);
void merge(const Status &merge);
// void merge(const Status &merge);
QString statusString;
bool overload;
bool unlocked;
bool unlevel;
bool extRef;
};
// QString statusString;
// bool overload;
// bool unlocked;
// bool unlevel;
// bool extRef;
// };
static void RegisterTypes();
// static void RegisterTypes();
void initialize(); // call this after creating the virtual device and all connections to signals have been made
// void initialize(); // call this after creating the virtual device and all connections to signals have been made
bool isCompoundDevice() const;
Device *getDevice();
CompoundDevice *getCompoundDevice();
std::vector<Device*> getDevices();
const Info& getInfo() const;
static VirtualDevice::Info getInfo(VirtualDevice *vdev);
const Status &getStatus() const;
static VirtualDevice::Status getStatus(VirtualDevice *vdev);
// bool isCompoundDevice() const;
// Device *getDevice();
// CompoundDevice *getCompoundDevice();
// std::vector<Device*> getDevices();
// const Info& getInfo() const;
// static VirtualDevice::Info getInfo(VirtualDevice *vdev);
// const Status &getStatus() const;
// static VirtualDevice::Status getStatus(VirtualDevice *vdev);
class VNASettings {
public:
double freqStart, freqStop;
double dBmStart, dBmStop;
double IFBW;
int points;
bool logSweep;
std::vector<int> excitedPorts; // port count starts at one
};
class VNAMeasurement {
public:
unsigned int pointNum;
double Z0;
union {
struct {
// for non-zero span
double frequency;
double dBm;
};
struct {
// for zero span
double us; // time in us since first datapoint
};
};
std::map<QString, std::complex<double>> measurements;
// class VNASettings {
// public:
// double freqStart, freqStop;
// double dBmStart, dBmStop;
// double IFBW;
// int points;
// bool logSweep;
// std::vector<int> excitedPorts; // port count starts at one
// };
// class VNAMeasurement {
// public:
// unsigned int pointNum;
// double Z0;
// union {
// struct {
// // for non-zero span
// double frequency;
// double dBm;
// };
// struct {
// // for zero span
// double us; // time in us since first datapoint
// };
// };
// std::map<QString, std::complex<double>> measurements;
Sparam toSparam(int port1, int port2) const;
void fromSparam(Sparam S, int port1, int port2);
VNAMeasurement interpolateTo(const VNAMeasurement &to, double a);
};
// Sparam toSparam(int port1, int port2) const;
// void fromSparam(Sparam S, int port1, int port2);
// VNAMeasurement interpolateTo(const VNAMeasurement &to, double a);
// };
QStringList availableVNAMeasurements();
bool setVNA(const VNASettings &s, std::function<void(bool)> cb = nullptr);
QString serial();
// QStringList availableVNAMeasurements();
// bool setVNA(const VNASettings &s, std::function<void(bool)> cb = nullptr);
// QString serial();
class SASettings {
public:
enum class Window {
None = 0,
Kaiser = 1,
Hann = 2,
FlatTop = 3,
Last
};
enum class Detector {
PPeak = 0,
NPeak = 1,
Sample = 2,
Normal = 3,
Average = 4,
Last
};
// class SASettings {
// public:
// enum class Window {
// None = 0,
// Kaiser = 1,
// Hann = 2,
// FlatTop = 3,
// Last
// };
// enum class Detector {
// PPeak = 0,
// NPeak = 1,
// Sample = 2,
// Normal = 3,
// Average = 4,
// Last
// };
double freqStart, freqStop;
double RBW;
int points;
Window window;
Detector detector;
bool signalID;
bool trackingGenerator;
int trackingPort; // counting starts at zero
double trackingOffset;
double trackingPower;
};
class SAMeasurement {
public:
int pointNum;
union {
struct {
// for non-zero span
double frequency;
};
struct {
// for zero span
double us; // time in us since first datapoint
};
};
std::map<QString, double> measurements;
};
// double freqStart, freqStop;
// double RBW;
// int points;
// Window window;
// Detector detector;
// bool signalID;
// bool trackingGenerator;
// int trackingPort; // counting starts at zero
// double trackingOffset;
// double trackingPower;
// };
// class SAMeasurement {
// public:
// int pointNum;
// union {
// struct {
// // for non-zero span
// double frequency;
// };
// struct {
// // for zero span
// double us; // time in us since first datapoint
// };
// };
// std::map<QString, double> measurements;
// };
QStringList availableSAMeasurements();
bool setSA(const SASettings &s, std::function<void(bool)> cb = nullptr);
// QStringList availableSAMeasurements();
// bool setSA(const SASettings &s, std::function<void(bool)> cb = nullptr);
class SGSettings {
public:
double freq;
double dBm;
int port; // starts at one, set to zero to disable all ports
};
// class SGSettings {
// public:
// double freq;
// double dBm;
// int port; // starts at one, set to zero to disable all ports
// };
QStringList availableSGPorts();
bool setSG(const SGSettings &s);
// QStringList availableSGPorts();
// bool setSG(const SGSettings &s);
bool setIdle(std::function<void(bool)> cb = nullptr);
// bool setIdle(std::function<void(bool)> cb = nullptr);
QStringList availableExtRefInSettings();
QStringList availableExtRefOutSettings();
// QStringList availableExtRefInSettings();
// QStringList availableExtRefOutSettings();
bool setExtRef(QString option_in, QString option_out);
// bool setExtRef(QString option_in, QString option_out);
static std::set<QString> GetAvailableVirtualDevices();
static VirtualDevice* getConnected();
// static std::set<QString> GetAvailableVirtualDevices();
// static VirtualDevice* getConnected();
static constexpr unsigned int maximumSupportedPorts = 8;
// static constexpr unsigned int maximumSupportedPorts = 8;
signals:
void VNAmeasurementReceived(VNAMeasurement m);
void SAmeasurementReceived(SAMeasurement m);
void ConnectionLost();
void InfoUpdated();
void StatusUpdated(Status status);
void LogLineReceived(QString line);
void NeedsFirmwareUpdate(int usedProtocol, int requiredProtocol);
//signals:
// void VNAmeasurementReceived(VNAMeasurement m);
// void SAmeasurementReceived(SAMeasurement m);
// void ConnectionLost();
// void InfoUpdated();
// void StatusUpdated(Status status);
// void LogLineReceived(QString line);
// void NeedsFirmwareUpdate(int usedProtocol, int requiredProtocol);
private slots:
void singleDatapointReceived(Device *dev, Protocol::VNADatapoint<32> *res);
void compoundDatapointReceivecd(Device *dev, Protocol::VNADatapoint<32> *data);
void singleSpectrumResultReceived(Device *dev, Protocol::SpectrumAnalyzerResult res);
void compoundSpectrumResultReceived(Device *dev, Protocol::SpectrumAnalyzerResult res);
void compoundInfoUpdated(Device *dev);
void compoundStatusUpdated(Device *dev);
private:
void checkIfAllTransmissionsComplete(std::function<void(bool)> cb = nullptr);
//private slots:
// void singleDatapointReceived(Device *dev, Protocol::VNADatapoint<32> *res);
// void compoundDatapointReceivecd(Device *dev, Protocol::VNADatapoint<32> *data);
// void singleSpectrumResultReceived(Device *dev, Protocol::SpectrumAnalyzerResult res);
// void compoundSpectrumResultReceived(Device *dev, Protocol::SpectrumAnalyzerResult res);
// void compoundInfoUpdated(Device *dev);
// void compoundStatusUpdated(Device *dev);
//private:
// void checkIfAllTransmissionsComplete(std::function<void(bool)> cb = nullptr);
Info info;
Status status;
std::vector<Device*> devices;
bool zerospan;
// Info info;
// Status status;
// std::vector<Device*> devices;
// bool zerospan;
std::map<Device*, Device::TransmissionResult> results;
// std::map<Device*, Device::TransmissionResult> results;
CompoundDevice *cdev;
// CompoundDevice *cdev;
std::map<int, std::map<Device*, Protocol::VNADatapoint<32>*>> compoundVNABuffer;
std::map<int, std::map<Device*, Protocol::SpectrumAnalyzerResult>> compoundSABuffer;
std::map<Device*, Protocol::DeviceInfo> compoundInfoBuffer;
std::map<Device*, Protocol::DeviceStatusV1> compoundStatusBuffer;
// std::map<int, std::map<Device*, Protocol::VNADatapoint<32>*>> compoundVNABuffer;
// std::map<int, std::map<Device*, Protocol::SpectrumAnalyzerResult>> compoundSABuffer;
// std::map<Device*, Protocol::DeviceInfo> compoundInfoBuffer;
// std::map<Device*, Protocol::DeviceStatusV1> compoundStatusBuffer;
std::map<int, int> portStageMapping; // maps from excitedPort (count starts at zero) to stage (count starts at zero)
};
// std::map<int, int> portStageMapping; // maps from excitedPort (count starts at zero) to stage (count starts at zero)
//};
Q_DECLARE_METATYPE(VirtualDevice::Status)
Q_DECLARE_METATYPE(VirtualDevice::VNAMeasurement)
Q_DECLARE_METATYPE(VirtualDevice::SAMeasurement)
//Q_DECLARE_METATYPE(VirtualDevice::Status)
//Q_DECLARE_METATYPE(VirtualDevice::VNAMeasurement)
//Q_DECLARE_METATYPE(VirtualDevice::SAMeasurement)
#endif // VIRTUALDEVICE_H
//#endif // VIRTUALDEVICE_H

View File

@ -499,18 +499,18 @@ void SpectrumAnalyzer::NewDatapoint(DeviceDriver::SAMeasurement m)
for(auto m : m_avg.measurements) {
normalize.portCorrection[m.first].push_back(m.second);
}
if(m_avg.pointNum == DeviceDriver::getActiveDriver()->getSApoints() - 1) {
if(m_avg.pointNum == DeviceDriver::SApoints() - 1) {
// this was the last point
normalize.measuring = false;
normalize.f_start = settings.freqStart;
normalize.f_stop = settings.freqStop;
normalize.points = DeviceDriver::getActiveDriver()->getSApoints();
normalize.points = DeviceDriver::SApoints();
EnableNormalization(true);
qDebug() << "Normalization measurement complete";
}
}
}
int percentage = (((average.currentSweep() - 1) * 100) + (m_avg.pointNum + 1) * 100 / DeviceDriver::getActiveDriver()->getSApoints()) / averages;
int percentage = (((average.currentSweep() - 1) * 100) + (m_avg.pointNum + 1) * 100 / DeviceDriver::SApoints()) / averages;
normalize.dialog.setValue(percentage);
}
@ -524,7 +524,7 @@ void SpectrumAnalyzer::NewDatapoint(DeviceDriver::SAMeasurement m)
traceModel.addSAData(m_avg, settings);
emit dataChanged();
if(m_avg.pointNum == DeviceDriver::getActiveDriver()->getSApoints() - 1) {
if(m_avg.pointNum == DeviceDriver::SApoints() - 1) {
UpdateAverageCount();
markerModel->updateMarkers();
}
@ -771,7 +771,8 @@ void SpectrumAnalyzer::EnableNormalization(bool enabled)
if(enabled != normalize.active) {
if(enabled) {
// check if measurements already taken
if(normalize.f_start == settings.freqStart && normalize.f_stop == settings.freqStop && normalize.points == settings.points) {
if(normalize.f_start == settings.freqStart && normalize.f_stop == settings.freqStop
&& normalize.points == DeviceDriver::SApoints()) {
// same settings as with normalization measurement, can enable
normalize.active = true;
} else {
@ -856,7 +857,7 @@ void SpectrumAnalyzer::ConfigureDevice()
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()) {
if(normalize.f_start != settings.freqStart || normalize.f_stop != settings.freqStop || normalize.points != DeviceDriver::SApoints()) {
// normalization was taken at different settings, disable
EnableNormalization(false);
InformationBox::ShowMessage("Information", "Normalization was disabled because the span has been changed");
@ -869,7 +870,7 @@ void SpectrumAnalyzer::ConfigureDevice()
emit sweepStopped();
changingSettings = false;
}
average.reset(DeviceDriver::getActiveDriver()->getSApoints());
average.reset(DeviceDriver::SApoints());
UpdateAverageCount();
traceModel.clearLiveData();
emit traceModel.SpanChanged(settings.freqStart, settings.freqStop);
@ -890,7 +891,7 @@ void SpectrumAnalyzer::ConfigureDevice()
void SpectrumAnalyzer::ResetLiveTraces()
{
average.reset(DeviceDriver::getActiveDriver()->getSApoints());
average.reset(DeviceDriver::SApoints());
traceModel.clearLiveData();
UpdateAverageCount();
}

View File

@ -125,12 +125,11 @@ TraceEditDialog::TraceEditDialog(Trace &t, QWidget *parent) :
}
VNAtrace = Trace::isVNAParameter(t.liveParameter());
if(VirtualDevice::getConnected()) {
qDebug() << VirtualDevice::getConnected();
if(DeviceDriver::getActiveDriver()) {
if(VNAtrace) {
ui->CLiveParam->addItems(VirtualDevice::getConnected()->availableVNAMeasurements());
ui->CLiveParam->addItems(DeviceDriver::getActiveDriver()->availableVNAMeasurements());
} else {
ui->CLiveParam->addItems(VirtualDevice::getConnected()->availableSAMeasurements());
ui->CLiveParam->addItems(DeviceDriver::getActiveDriver()->availableSAMeasurements());
}
}

View File

@ -1430,8 +1430,8 @@ void VNA::SetupSCPI()
void VNA::ConstrainAndUpdateFrequencies()
{
if(settings.Freq.stop > DeviceDriver::getInfo(window->getDevice()).Limits.VNA.minFreq) {
settings.Freq.stop = DeviceDriver::getInfo(window->getDevice()).Limits.VNA.minFreq;
if(settings.Freq.stop > DeviceDriver::getInfo(window->getDevice()).Limits.VNA.maxFreq) {
settings.Freq.stop = DeviceDriver::getInfo(window->getDevice()).Limits.VNA.maxFreq;
}
if(settings.Freq.start > settings.Freq.stop) {
settings.Freq.start = settings.Freq.stop;

View File

@ -60,6 +60,7 @@
#include <QDateTime>
#include <QCommandLineParser>
#include <QScrollArea>
#include <QStringList>
using namespace std;
@ -84,9 +85,6 @@ 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());
@ -106,6 +104,15 @@ AppWindow::AppWindow(QWidget *parent)
} else {
Preferences::getInstance().load();
}
// Register device drivers
deviceDrivers.push_back(new LibreVNAUSBDriver());
for(auto driver : deviceDrivers) {
driver->registerTypes();
Preferences::getInstance().load(driver->driverSpecificSettings());
}
device = nullptr;
// vdevice = nullptr;
modeHandler = nullptr;
@ -184,9 +191,9 @@ AppWindow::AppWindow(QWidget *parent)
}
// List available devices
UpdateDeviceList();
if(pref.Startup.ConnectToFirstDevice) {
if(pref.Startup.ConnectToFirstDevice && deviceList.size() > 0) {
// at least one device available
ConnectToDevice();
ConnectToDevice(deviceList[0].serial);
}
if(parser.isSet("setup")) {
@ -325,10 +332,13 @@ void AppWindow::closeEvent(QCloseEvent *event)
delete modeHandler;
modeHandler = nullptr;
pref.store();
for(auto driver : deviceDrivers) {
Preferences::getInstance().store(driver->driverSpecificSettings());
}
QMainWindow::closeEvent(event);
}
bool AppWindow::ConnectToDevice(QString serial)
bool AppWindow::ConnectToDevice(QString serial, DeviceDriver *driver)
{
if(serial.isEmpty()) {
qDebug() << "Trying to connect to any device";
@ -341,17 +351,25 @@ bool AppWindow::ConnectToDevice(QString serial)
}
try {
qDebug() << "Attempting to connect to device...";
for(auto driver : deviceDrivers) {
if(driver->GetAvailableDevices().count(serial)) {
for(auto d : deviceDrivers) {
if(driver && driver != d) {
// not the specified driver
continue;
}
if(d->GetAvailableDevices().count(serial)) {
// this driver can connect to the device
if(driver->connectDevice(serial)) {
device = driver;
if(d->connectDevice(serial)) {
device = d;
} else {
// failed to connect
// TODO show error message
break;
}
}
}
if(!device) {
// failed to connect
InformationBox::ShowError("Failed to connect", "Could not connect to "+serial);
return false;
}
UpdateStatusBar(AppWindow::DeviceStatusBar::Connected);
connect(device, &DeviceDriver::InfoUpdated, this, &AppWindow::DeviceInfoUpdated);
connect(device, &DeviceDriver::LogLineReceived, &deviceLog, &DeviceLog::addLine);
@ -368,8 +386,11 @@ bool AppWindow::ConnectToDevice(QString serial)
// }
ui->actionPreset->setEnabled(true);
DeviceEntry e;
e.serial = device->getSerial();
e.driver = device;
for(auto d : deviceActionGroup->actions()) {
if(d->text() == device->getSerial()) {
if(d->text() == e.toString()) {
d->blockSignals(true);
d->setChecked(true);
d->blockSignals(false);
@ -476,8 +497,10 @@ void AppWindow::SetupSCPI()
}));
scpi_dev->add(new SCPICommand("LIST", nullptr, [=](QStringList) -> QString {
QString ret;
for(auto d : VirtualDevice::GetAvailableVirtualDevices()) {
ret += d + ",";
for(auto driver : deviceDrivers) {
for(auto d : driver->GetAvailableDevices()) {
ret += d + ",";
}
}
// remove last comma
ret.chop(1);
@ -933,33 +956,42 @@ int AppWindow::UpdateDeviceList()
{
deviceActionGroup->setExclusive(true);
ui->menuConnect_to->clear();
std::set<QString> devices;
deviceList.clear();
for(auto driver : deviceDrivers) {
devices.merge(driver->GetAvailableDevices());
for(auto serial : driver->GetAvailableDevices()) {
DeviceEntry e;
e.driver = driver;
e.serial = serial;
deviceList.push_back(e);
}
}
if(device) {
devices.insert(device->getSerial());
DeviceEntry e;
e.driver = device;
e.serial = device->getSerial();
if(std::find(deviceList.begin(), deviceList.end(), e) == deviceList.end()) {
// connected device is not in list (this may happen if the driver does not detect a connected device as "available")
deviceList.push_back(e);
}
}
int available = 0;
bool found = false;
if(devices.size()) {
for(auto d : devices) {
if(!parser.value("device").isEmpty() && parser.value("device") != d) {
// specified device does not match, ignore
continue;
}
auto connectAction = ui->menuConnect_to->addAction(d);
connectAction->setCheckable(true);
connectAction->setActionGroup(deviceActionGroup);
if(device && d == device->getSerial()) {
connectAction->setChecked(true);
}
connect(connectAction, &QAction::triggered, [this, d]() {
ConnectToDevice(d);
});
found = true;
available++;
for(auto d : deviceList) {
if(!parser.value("device").isEmpty() && parser.value("device") != d.serial) {
// specified device does not match, ignore
continue;
}
auto connectAction = ui->menuConnect_to->addAction(d.toString());
connectAction->setCheckable(true);
connectAction->setActionGroup(deviceActionGroup);
if(device && d.serial == device->getSerial()) {
connectAction->setChecked(true);
}
connect(connectAction, &QAction::triggered, [this, d]() {
ConnectToDevice(d.serial, d.driver);
});
found = true;
available++;
}
ui->menuConnect_to->setEnabled(found);
qDebug() << "Updated device list, found" << available;
@ -1055,12 +1087,16 @@ void AppWindow::ShowUSBLog()
// }
//}
void AppWindow::DeviceStatusUpdated(VirtualDevice::Status status)
void AppWindow::DeviceStatusUpdated()
{
lDeviceInfo.setText(status.statusString);
lADCOverload.setVisible(status.overload);
lUnlevel.setVisible(status.unlevel);
lUnlock.setVisible(status.unlocked);
lDeviceInfo.setText(device->getStatus());
}
void AppWindow::DeviceFlagsUpdated()
{
lADCOverload.setVisible(device->asserted(DeviceDriver::Flag::Overload));
lUnlevel.setVisible(device->asserted(DeviceDriver::Flag::Unlevel));
lUnlock.setVisible(device->asserted(DeviceDriver::Flag::Unlocked));
}
void AppWindow::DeviceInfoUpdated()
@ -1320,3 +1356,31 @@ void AppWindow::UpdateStatusBar(DeviceStatusBar status)
}
}
QString AppWindow::DeviceEntry::toString()
{
return serial + " (" + driver->getDriverName()+")";
}
AppWindow::DeviceEntry AppWindow::DeviceEntry::fromString(QString s, std::vector<DeviceDriver*> drivers)
{
DeviceEntry e;
QStringList parts = s.split(" ");
if(parts.size() < 2) {
// invalid string
e.serial = "";
e.driver = nullptr;
} else {
e.serial = parts[0];
e.driver = nullptr;
parts[1].chop(1);
auto driverName = parts[1].mid(1);
for(auto d : drivers) {
if(d->getDriverName() == driverName) {
e.driver = d;
break;
}
}
}
return e;
}

View File

@ -58,7 +58,7 @@ public slots:
protected:
void closeEvent(QCloseEvent *event) override;
private slots:
bool ConnectToDevice(QString serial = QString());
bool ConnectToDevice(QString serial = QString(), DeviceDriver *driver = nullptr);
void DisconnectDevice();
int UpdateDeviceList();
// void StartManualControl();
@ -67,8 +67,9 @@ private slots:
// void UpdateAcquisitionFrequencies();
void ShowUSBLog();
// void StartFirmwareUpdateDialog();
void DeviceNeedsUpdate(int reported, int expected);
void DeviceStatusUpdated(VirtualDevice::Status status);
// void DeviceNeedsUpdate(int reported, int expected);
void DeviceStatusUpdated();
void DeviceFlagsUpdated();
void DeviceInfoUpdated();
// void SourceCalibrationDialog();
// void ReceiverCalibrationDialog();
@ -109,6 +110,20 @@ private:
std::vector<DeviceDriver*> deviceDrivers;
DeviceDriver *device;
class DeviceEntry {
public:
QString toString();
static DeviceEntry fromString(QString s, std::vector<DeviceDriver*> drivers);
bool operator==(const DeviceEntry& rhs) {
return serial == rhs.serial && driver == rhs.driver;
}
QString serial;
DeviceDriver *driver;
};
std::vector<DeviceEntry> deviceList;
DeviceLog deviceLog;
QString deviceSerial;
QActionGroup *deviceActionGroup;

View File

@ -21,7 +21,6 @@ int main(int argc, char *argv[]) {
qSetMessagePattern("%{time process}: [%{type}] %{message}");
Device::RegisterTypes();
VirtualDevice::RegisterTypes();
app = new QApplication(argc, argv);
QCoreApplication::setOrganizationName("LibreVNA");

View File

@ -163,14 +163,14 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
});
// Compound device page
connect(ui->compoundList, &QListWidget::currentRowChanged, [=](){
if(VirtualDevice::getConnected() && VirtualDevice::getConnected()->getCompoundDevice() == p->compoundDevices[ui->compoundList->currentRow()]) {
// can't remove the device we are connected to
ui->compoundDelete->setEnabled(false);
} else {
ui->compoundDelete->setEnabled(true);
}
});
// connect(ui->compoundList, &QListWidget::currentRowChanged, [=](){
// if(VirtualDevice::getConnected() && VirtualDevice::getConnected()->getCompoundDevice() == p->compoundDevices[ui->compoundList->currentRow()]) {
// // can't remove the device we are connected to
// ui->compoundDelete->setEnabled(false);
// } else {
// ui->compoundDelete->setEnabled(true);
// }
// });
connect(ui->compoundList, &QListWidget::doubleClicked, [=](){
auto index = ui->compoundList->currentRow();
if(index >= 0 && index < (int) p->compoundDevices.size()) {
@ -195,22 +195,22 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
});
d->show();
});
connect(ui->compoundDelete, &QPushButton::clicked, [=](){
auto index = ui->compoundList->currentRow();
if(index >= 0 && index < (int) p->compoundDevices.size()) {
// delete the actual compound device
if(VirtualDevice::getConnected() && VirtualDevice::getConnected()->getCompoundDevice() == p->compoundDevices[index]) {
// can't remove the device we are currently connected to
return;
}
delete p->compoundDevices[index];
// delete the line in the GUI list
delete ui->compoundList->takeItem(index);
// remove compound device from list
p->compoundDevices.erase(p->compoundDevices.begin() + index);
p->nonTrivialWriting();
}
});
// connect(ui->compoundDelete, &QPushButton::clicked, [=](){
// auto index = ui->compoundList->currentRow();
// if(index >= 0 && index < (int) p->compoundDevices.size()) {
// // delete the actual compound device
// if(VirtualDevice::getConnected() && VirtualDevice::getConnected()->getCompoundDevice() == p->compoundDevices[index]) {
// // can't remove the device we are currently connected to
// return;
// }
// delete p->compoundDevices[index];
// // delete the line in the GUI list
// delete ui->compoundList->takeItem(index);
// // remove compound device from list
// p->compoundDevices.erase(p->compoundDevices.begin() + index);
// p->nonTrivialWriting();
// }
// });
// Debug page
ui->DebugMaxUSBlogSize->setUnit("B");
@ -514,24 +514,32 @@ Preferences::~Preferences()
void Preferences::load()
{
QSettings settings;
// load settings, using default values if not present
qInfo() << "Loading preferences";
load(descr);
nonTrivialParsing();
}
void Preferences::load(std::vector<Savable::SettingDescription> descr)
{
QSettings settings;
for(auto d : descr) {
try {
d.var.setValue(settings.value(d.name, d.def));
// qDebug() << "Setting" << d.name << "is set to" << d.var.value();
} catch (const exception& e){
d.var.setValue(d.def);
// qDebug() << "Setting" << d.name << "reset to default:" << d.def;
}
}
nonTrivialParsing();
}
void Preferences::store()
{
nonTrivialWriting();
store(descr);
}
void Preferences::store(std::vector<Savable::SettingDescription> descr)
{
QSettings settings;
// store settings
for(auto d : descr) {

View File

@ -51,7 +51,9 @@ public:
Preferences(const Preferences&) = delete;
~Preferences();
void load();
void load(std::vector<Savable::SettingDescription> descr);
void store();
void store(std::vector<Savable::SettingDescription> descr);
void edit();
void setDefault();

View File

@ -32,10 +32,13 @@ SOURCES += \
../LibreVNA-GUI/Device/compounddevice.cpp \
../LibreVNA-GUI/Device/compounddeviceeditdialog.cpp \
../LibreVNA-GUI/Device/device.cpp \
../LibreVNA-GUI/Device/devicedriver.cpp \
../LibreVNA-GUI/Device/devicelog.cpp \
../LibreVNA-GUI/Device/deviceusblog.cpp \
../LibreVNA-GUI/Device/deviceusblogview.cpp \
../LibreVNA-GUI/Device/firmwareupdatedialog.cpp \
../LibreVNA-GUI/Device/librevnadriver.cpp \
../LibreVNA-GUI/Device/librevnausbdriver.cpp \
../LibreVNA-GUI/Device/manualcontroldialog.cpp \
../LibreVNA-GUI/Device/virtualdevice.cpp \
../LibreVNA-GUI/Generator/generator.cpp \
@ -199,10 +202,13 @@ HEADERS += \
../LibreVNA-GUI/Device/compounddevice.h \
../LibreVNA-GUI/Device/compounddeviceeditdialog.h \
../LibreVNA-GUI/Device/device.h \
../LibreVNA-GUI/Device/devicedriver.h \
../LibreVNA-GUI/Device/devicelog.h \
../LibreVNA-GUI/Device/deviceusblog.h \
../LibreVNA-GUI/Device/deviceusblogview.h \
../LibreVNA-GUI/Device/firmwareupdatedialog.h \
../LibreVNA-GUI/Device/librevnadriver.h \
../LibreVNA-GUI/Device/librevnausbdriver.h \
../LibreVNA-GUI/Device/manualcontroldialog.h \
../LibreVNA-GUI/Device/virtualdevice.h \
../LibreVNA-GUI/Generator/generator.h \