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

View File

@ -8,6 +8,7 @@
#include <QString> #include <QString>
#include <QMessageBox> #include <QMessageBox>
#include <mutex> #include <mutex>
#include "devicedriver.h"
using namespace std; using namespace std;
@ -20,126 +21,126 @@ static constexpr USBID IDs[] = {
{0x0483, 0x4121}, {0x0483, 0x4121},
}; };
USBInBuffer::USBInBuffer(libusb_device_handle *handle, unsigned char endpoint, int buffer_size) : //USBInBuffer::USBInBuffer(libusb_device_handle *handle, unsigned char endpoint, int buffer_size) :
buffer_size(buffer_size), // buffer_size(buffer_size),
received_size(0), // received_size(0),
inCallback(false), // inCallback(false),
cancelling(false) // cancelling(false)
{ //{
buffer = new unsigned char[buffer_size]; // buffer = new unsigned char[buffer_size];
memset(buffer, 0, buffer_size); // memset(buffer, 0, buffer_size);
transfer = libusb_alloc_transfer(0); // transfer = libusb_alloc_transfer(0);
libusb_fill_bulk_transfer(transfer, handle, endpoint, buffer, buffer_size, CallbackTrampoline, this, 0); // libusb_fill_bulk_transfer(transfer, handle, endpoint, buffer, buffer_size, CallbackTrampoline, this, 0);
libusb_submit_transfer(transfer); // libusb_submit_transfer(transfer);
} //}
USBInBuffer::~USBInBuffer() //USBInBuffer::~USBInBuffer()
{ //{
if(transfer) { // if(transfer) {
cancelling = true; // cancelling = true;
libusb_cancel_transfer(transfer); // libusb_cancel_transfer(transfer);
// wait for cancellation to complete // // wait for cancellation to complete
mutex mtx; // mutex mtx;
unique_lock<mutex> lck(mtx); // unique_lock<mutex> lck(mtx);
using namespace std::chrono_literals; // using namespace std::chrono_literals;
if(cv.wait_for(lck, 100ms) == cv_status::timeout) { // if(cv.wait_for(lck, 100ms) == cv_status::timeout) {
qWarning() << "Timed out waiting for mutex acquisition during disconnect"; // 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--;
// } // }
// } // }
// qDebug() << transfer->actual_length <<"total:" << received_size; // delete[] buffer;
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) //void USBInBuffer::removeBytes(int handled_bytes)
{ //{
auto usb = (USBInBuffer*) transfer->user_data; // if(!inCallback) {
usb->Callback(transfer); // 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 //int USBInBuffer::getReceived() const
{ //{
return buffer; // 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 = { static constexpr Protocol::DeviceInfo defaultInfo = {
.ProtocolVersion = Protocol::Version, .ProtocolVersion = Protocol::Version,

View File

@ -3,6 +3,8 @@
#include "../../VNA_embedded/Application/Communication/Protocol.hpp" #include "../../VNA_embedded/Application/Communication/Protocol.hpp"
#include "librevnausbdriver.h"
#include <functional> #include <functional>
#include <libusb-1.0/libusb.h> #include <libusb-1.0/libusb.h>
#include <thread> #include <thread>
@ -18,31 +20,31 @@ Q_DECLARE_METATYPE(Protocol::ManualStatusV1)
Q_DECLARE_METATYPE(Protocol::SpectrumAnalyzerResult) Q_DECLARE_METATYPE(Protocol::SpectrumAnalyzerResult)
Q_DECLARE_METATYPE(Protocol::AmplitudeCorrectionPoint) Q_DECLARE_METATYPE(Protocol::AmplitudeCorrectionPoint)
class USBInBuffer : public QObject { //class USBInBuffer : public QObject {
Q_OBJECT // Q_OBJECT
public: //public:
USBInBuffer(libusb_device_handle *handle, unsigned char endpoint, int buffer_size); // USBInBuffer(libusb_device_handle *handle, unsigned char endpoint, int buffer_size);
~USBInBuffer(); // ~USBInBuffer();
void removeBytes(int handled_bytes); // void removeBytes(int handled_bytes);
int getReceived() const; // int getReceived() const;
uint8_t *getBuffer() const; // uint8_t *getBuffer() const;
signals: //signals:
void DataReceived(); // void DataReceived();
void TransferError(); // void TransferError();
private: //private:
void Callback(libusb_transfer *transfer); // void Callback(libusb_transfer *transfer);
static void LIBUSB_CALL CallbackTrampoline(libusb_transfer *transfer); // static void LIBUSB_CALL CallbackTrampoline(libusb_transfer *transfer);
libusb_transfer *transfer; // libusb_transfer *transfer;
unsigned char *buffer; // unsigned char *buffer;
int buffer_size; // int buffer_size;
int received_size; // int received_size;
bool inCallback; // bool inCallback;
bool cancelling; // bool cancelling;
std::condition_variable cv; // std::condition_variable cv;
}; //};
class Device : public QObject class Device : public QObject

View File

@ -20,3 +20,85 @@ void DeviceDriver::disconnectDevice()
disconnect(); disconnect();
activeDriver = nullptr; 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 { class Info {
public: public:
// TODO create constructor with default values Info();
QString firmware_version; QString firmware_version;
QString hardware_version; QString hardware_version;
std::set<Feature> supportedFeatures; std::set<Feature> supportedFeatures;
@ -161,6 +161,13 @@ public:
*/ */
virtual std::set<Flag> getFlags() = 0; 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 * @brief Checks whether a specific flag is asserted
* @param f Flag to check * @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: signals:
/** /**
* @brief Emit this signal when the device connection has been lost unexpectedly * @brief Emit this signal when the device connection has been lost unexpectedly
@ -445,6 +460,7 @@ public:
bool connectDevice(QString serial); bool connectDevice(QString serial);
void disconnectDevice(); void disconnectDevice();
static DeviceDriver* getActiveDriver() {return activeDriver;} static DeviceDriver* getActiveDriver() {return activeDriver;}
static unsigned int SApoints();
private: private:
static DeviceDriver *activeDriver; static DeviceDriver *activeDriver;

View File

@ -2,6 +2,96 @@
using namespace std; 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() LibreVNADriver::LibreVNADriver()
{ {
connected = false; connected = false;
@ -142,6 +232,7 @@ bool LibreVNADriver::setSA(const DeviceDriver::SASettings &s, std::function<void
zerospan = s.freqStart == s.freqStop; zerospan = s.freqStart == s.freqStop;
Protocol::PacketInfo p = {}; Protocol::PacketInfo p = {};
p.type = Protocol::PacketType::SpectrumAnalyzerSettings;
p.spectrumSettings.f_start = s.freqStart; p.spectrumSettings.f_start = s.freqStart;
p.spectrumSettings.f_stop = s.freqStop; 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) void LibreVNADriver::handleReceivedPacket(const Protocol::PacketInfo &packet)
{ {
emit passOnReceivedPacket(packet); emit passOnReceivedPacket(packet);
@ -253,6 +400,7 @@ void LibreVNADriver::handleReceivedPacket(const Protocol::PacketInfo &packet)
case Protocol::PacketType::DeviceStatusV1: case Protocol::PacketType::DeviceStatusV1:
lastStatus = packet.statusV1; lastStatus = packet.statusV1;
emit StatusUpdated(); emit StatusUpdated();
emit FlagsUpdated();
break; break;
case Protocol::PacketType::VNADatapoint: { case Protocol::PacketType::VNADatapoint: {
VNAMeasurement m; VNAMeasurement m;

View File

@ -249,6 +249,12 @@ void LibreVNAUSBDriver::disconnect()
} }
} }
void LibreVNAUSBDriver::registerTypes()
{
qRegisterMetaType<Protocol::PacketInfo>("LibreVNAUSBPacket");
qRegisterMetaType<TransmissionResult>("LibreVNAUSBResult");
}
void LibreVNAUSBDriver::ReceivedData() void LibreVNAUSBDriver::ReceivedData()
{ {
Protocol::PacketInfo packet; Protocol::PacketInfo packet;
@ -429,3 +435,32 @@ void LibreVNAUSBDriver::SearchDevices(std::function<bool (libusb_device_handle *
} }
libusb_free_device_list(devList, 1); 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 <QQueue>
#include <QTimer> #include <QTimer>
Q_DECLARE_METATYPE(Protocol::PacketInfo)
Q_DECLARE_METATYPE(LibreVNADriver::TransmissionResult)
class USBInBuffer : public QObject { class USBInBuffer : public QObject {
Q_OBJECT Q_OBJECT
public: public:
@ -63,6 +66,14 @@ public:
*/ */
virtual void disconnect() override; 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: private slots:
void ReceivedData(); void ReceivedData();
void ReceivedLog(); void ReceivedLog();
@ -101,11 +112,6 @@ private:
bool transmissionActive; bool transmissionActive;
std::thread *m_receiveThread; std::thread *m_receiveThread;
Protocol::DeviceInfo info;
bool infoValid;
union {
Protocol::DeviceStatusV1 v1;
} status;
std::mutex accessMutex; std::mutex accessMutex;
}; };

File diff suppressed because it is too large Load Diff

View File

@ -1,220 +1,220 @@
#ifndef VIRTUALDEVICE_H //#ifndef VIRTUALDEVICE_H
#define VIRTUALDEVICE_H //#define VIRTUALDEVICE_H
#include "device.h" //#include "device.h"
#include "Tools/parameters.h" //#include "Tools/parameters.h"
#include "compounddevice.h" //#include "compounddevice.h"
#include <set> //#include <set>
#include <complex> //#include <complex>
#include <QObject> //#include <QObject>
class VirtualDevice : public QObject //class VirtualDevice : public QObject
{ //{
Q_OBJECT // Q_OBJECT
public: //public:
VirtualDevice(QString serial = ""); // VirtualDevice(QString serial = "");
~VirtualDevice(); // ~VirtualDevice();
class Info { // class Info {
public: // public:
Info(); // Info();
Info(Device *dev); // Info(Device *dev);
void subset(const Info &merge); // void subset(const Info &merge);
uint16_t ProtocolVersion; // uint16_t ProtocolVersion;
uint8_t FW_major; // uint8_t FW_major;
uint8_t FW_minor; // uint8_t FW_minor;
uint8_t FW_patch; // uint8_t FW_patch;
uint8_t hardware_version; // uint8_t hardware_version;
char HW_Revision; // char HW_Revision;
unsigned int ports; // unsigned int ports;
bool supportsVNAmode; // bool supportsVNAmode;
bool supportsSAmode; // bool supportsSAmode;
bool supportsSGmode; // bool supportsSGmode;
bool supportsExtRef; // bool supportsExtRef;
struct { // struct {
double minFreq, maxFreq, maxFreqHarmonic; // double minFreq, maxFreq, maxFreqHarmonic;
double minIFBW, maxIFBW; // double minIFBW, maxIFBW;
unsigned int maxPoints; // unsigned int maxPoints;
double mindBm; // double mindBm;
double maxdBm; // double maxdBm;
double minRBW, maxRBW; // double minRBW, maxRBW;
} Limits; // } Limits;
}; // };
class Status { // class Status {
public: // public:
Status(); // Status();
Status(Device *dev); // Status(Device *dev);
void merge(const Status &merge); // void merge(const Status &merge);
QString statusString; // QString statusString;
bool overload; // bool overload;
bool unlocked; // bool unlocked;
bool unlevel; // bool unlevel;
bool extRef; // 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; // bool isCompoundDevice() const;
Device *getDevice(); // Device *getDevice();
CompoundDevice *getCompoundDevice(); // CompoundDevice *getCompoundDevice();
std::vector<Device*> getDevices(); // std::vector<Device*> getDevices();
const Info& getInfo() const; // const Info& getInfo() const;
static VirtualDevice::Info getInfo(VirtualDevice *vdev); // static VirtualDevice::Info getInfo(VirtualDevice *vdev);
const Status &getStatus() const; // const Status &getStatus() const;
static VirtualDevice::Status getStatus(VirtualDevice *vdev); // static VirtualDevice::Status getStatus(VirtualDevice *vdev);
class VNASettings { // class VNASettings {
public: // public:
double freqStart, freqStop; // double freqStart, freqStop;
double dBmStart, dBmStop; // double dBmStart, dBmStop;
double IFBW; // double IFBW;
int points; // int points;
bool logSweep; // bool logSweep;
std::vector<int> excitedPorts; // port count starts at one // std::vector<int> excitedPorts; // port count starts at one
}; // };
class VNAMeasurement { // class VNAMeasurement {
public: // public:
unsigned int pointNum; // unsigned int pointNum;
double Z0; // double Z0;
union { // union {
struct { // struct {
// for non-zero span // // for non-zero span
double frequency; // double frequency;
double dBm; // double dBm;
}; // };
struct { // struct {
// for zero span // // for zero span
double us; // time in us since first datapoint // double us; // time in us since first datapoint
}; // };
}; // };
std::map<QString, std::complex<double>> measurements; // std::map<QString, std::complex<double>> measurements;
Sparam toSparam(int port1, int port2) const; // Sparam toSparam(int port1, int port2) const;
void fromSparam(Sparam S, int port1, int port2); // void fromSparam(Sparam S, int port1, int port2);
VNAMeasurement interpolateTo(const VNAMeasurement &to, double a); // VNAMeasurement interpolateTo(const VNAMeasurement &to, double a);
}; // };
QStringList availableVNAMeasurements(); // QStringList availableVNAMeasurements();
bool setVNA(const VNASettings &s, std::function<void(bool)> cb = nullptr); // bool setVNA(const VNASettings &s, std::function<void(bool)> cb = nullptr);
QString serial(); // QString serial();
class SASettings { // class SASettings {
public: // public:
enum class Window { // enum class Window {
None = 0, // None = 0,
Kaiser = 1, // Kaiser = 1,
Hann = 2, // Hann = 2,
FlatTop = 3, // FlatTop = 3,
Last // Last
}; // };
enum class Detector { // enum class Detector {
PPeak = 0, // PPeak = 0,
NPeak = 1, // NPeak = 1,
Sample = 2, // Sample = 2,
Normal = 3, // Normal = 3,
Average = 4, // Average = 4,
Last // Last
}; // };
double freqStart, freqStop; // double freqStart, freqStop;
double RBW; // double RBW;
int points; // int points;
Window window; // Window window;
Detector detector; // Detector detector;
bool signalID; // bool signalID;
bool trackingGenerator; // bool trackingGenerator;
int trackingPort; // counting starts at zero // int trackingPort; // counting starts at zero
double trackingOffset; // double trackingOffset;
double trackingPower; // double trackingPower;
}; // };
class SAMeasurement { // class SAMeasurement {
public: // public:
int pointNum; // int pointNum;
union { // union {
struct { // struct {
// for non-zero span // // for non-zero span
double frequency; // double frequency;
}; // };
struct { // struct {
// for zero span // // for zero span
double us; // time in us since first datapoint // double us; // time in us since first datapoint
}; // };
}; // };
std::map<QString, double> measurements; // std::map<QString, double> measurements;
}; // };
QStringList availableSAMeasurements(); // QStringList availableSAMeasurements();
bool setSA(const SASettings &s, std::function<void(bool)> cb = nullptr); // bool setSA(const SASettings &s, std::function<void(bool)> cb = nullptr);
class SGSettings { // class SGSettings {
public: // public:
double freq; // double freq;
double dBm; // double dBm;
int port; // starts at one, set to zero to disable all ports // int port; // starts at one, set to zero to disable all ports
}; // };
QStringList availableSGPorts(); // QStringList availableSGPorts();
bool setSG(const SGSettings &s); // bool setSG(const SGSettings &s);
bool setIdle(std::function<void(bool)> cb = nullptr); // bool setIdle(std::function<void(bool)> cb = nullptr);
QStringList availableExtRefInSettings(); // QStringList availableExtRefInSettings();
QStringList availableExtRefOutSettings(); // QStringList availableExtRefOutSettings();
bool setExtRef(QString option_in, QString option_out); // bool setExtRef(QString option_in, QString option_out);
static std::set<QString> GetAvailableVirtualDevices(); // static std::set<QString> GetAvailableVirtualDevices();
static VirtualDevice* getConnected(); // static VirtualDevice* getConnected();
static constexpr unsigned int maximumSupportedPorts = 8; // static constexpr unsigned int maximumSupportedPorts = 8;
signals: //signals:
void VNAmeasurementReceived(VNAMeasurement m); // void VNAmeasurementReceived(VNAMeasurement m);
void SAmeasurementReceived(SAMeasurement m); // void SAmeasurementReceived(SAMeasurement m);
void ConnectionLost(); // void ConnectionLost();
void InfoUpdated(); // void InfoUpdated();
void StatusUpdated(Status status); // void StatusUpdated(Status status);
void LogLineReceived(QString line); // void LogLineReceived(QString line);
void NeedsFirmwareUpdate(int usedProtocol, int requiredProtocol); // void NeedsFirmwareUpdate(int usedProtocol, int requiredProtocol);
private slots: //private slots:
void singleDatapointReceived(Device *dev, Protocol::VNADatapoint<32> *res); // void singleDatapointReceived(Device *dev, Protocol::VNADatapoint<32> *res);
void compoundDatapointReceivecd(Device *dev, Protocol::VNADatapoint<32> *data); // void compoundDatapointReceivecd(Device *dev, Protocol::VNADatapoint<32> *data);
void singleSpectrumResultReceived(Device *dev, Protocol::SpectrumAnalyzerResult res); // void singleSpectrumResultReceived(Device *dev, Protocol::SpectrumAnalyzerResult res);
void compoundSpectrumResultReceived(Device *dev, Protocol::SpectrumAnalyzerResult res); // void compoundSpectrumResultReceived(Device *dev, Protocol::SpectrumAnalyzerResult res);
void compoundInfoUpdated(Device *dev); // void compoundInfoUpdated(Device *dev);
void compoundStatusUpdated(Device *dev); // void compoundStatusUpdated(Device *dev);
private: //private:
void checkIfAllTransmissionsComplete(std::function<void(bool)> cb = nullptr); // void checkIfAllTransmissionsComplete(std::function<void(bool)> cb = nullptr);
Info info; // Info info;
Status status; // Status status;
std::vector<Device*> devices; // std::vector<Device*> devices;
bool zerospan; // 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::VNADatapoint<32>*>> compoundVNABuffer;
std::map<int, std::map<Device*, Protocol::SpectrumAnalyzerResult>> compoundSABuffer; // std::map<int, std::map<Device*, Protocol::SpectrumAnalyzerResult>> compoundSABuffer;
std::map<Device*, Protocol::DeviceInfo> compoundInfoBuffer; // std::map<Device*, Protocol::DeviceInfo> compoundInfoBuffer;
std::map<Device*, Protocol::DeviceStatusV1> compoundStatusBuffer; // 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::Status)
Q_DECLARE_METATYPE(VirtualDevice::VNAMeasurement) //Q_DECLARE_METATYPE(VirtualDevice::VNAMeasurement)
Q_DECLARE_METATYPE(VirtualDevice::SAMeasurement) //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) { for(auto m : m_avg.measurements) {
normalize.portCorrection[m.first].push_back(m.second); 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 // this was the last point
normalize.measuring = false; normalize.measuring = false;
normalize.f_start = settings.freqStart; normalize.f_start = settings.freqStart;
normalize.f_stop = settings.freqStop; normalize.f_stop = settings.freqStop;
normalize.points = DeviceDriver::getActiveDriver()->getSApoints(); normalize.points = DeviceDriver::SApoints();
EnableNormalization(true); EnableNormalization(true);
qDebug() << "Normalization measurement complete"; 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); normalize.dialog.setValue(percentage);
} }
@ -524,7 +524,7 @@ void SpectrumAnalyzer::NewDatapoint(DeviceDriver::SAMeasurement m)
traceModel.addSAData(m_avg, settings); traceModel.addSAData(m_avg, settings);
emit dataChanged(); emit dataChanged();
if(m_avg.pointNum == DeviceDriver::getActiveDriver()->getSApoints() - 1) { if(m_avg.pointNum == DeviceDriver::SApoints() - 1) {
UpdateAverageCount(); UpdateAverageCount();
markerModel->updateMarkers(); markerModel->updateMarkers();
} }
@ -771,7 +771,8 @@ void SpectrumAnalyzer::EnableNormalization(bool enabled)
if(enabled != normalize.active) { if(enabled != normalize.active) {
if(enabled) { if(enabled) {
// check if measurements already taken // 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 // same settings as with normalization measurement, can enable
normalize.active = true; normalize.active = true;
} else { } else {
@ -856,7 +857,7 @@ void SpectrumAnalyzer::ConfigureDevice()
if(normalize.active) { if(normalize.active) {
// check if normalization is still valid // 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 // normalization was taken at different settings, disable
EnableNormalization(false); EnableNormalization(false);
InformationBox::ShowMessage("Information", "Normalization was disabled because the span has been changed"); InformationBox::ShowMessage("Information", "Normalization was disabled because the span has been changed");
@ -869,7 +870,7 @@ void SpectrumAnalyzer::ConfigureDevice()
emit sweepStopped(); emit sweepStopped();
changingSettings = false; changingSettings = false;
} }
average.reset(DeviceDriver::getActiveDriver()->getSApoints()); average.reset(DeviceDriver::SApoints());
UpdateAverageCount(); UpdateAverageCount();
traceModel.clearLiveData(); traceModel.clearLiveData();
emit traceModel.SpanChanged(settings.freqStart, settings.freqStop); emit traceModel.SpanChanged(settings.freqStart, settings.freqStop);
@ -890,7 +891,7 @@ void SpectrumAnalyzer::ConfigureDevice()
void SpectrumAnalyzer::ResetLiveTraces() void SpectrumAnalyzer::ResetLiveTraces()
{ {
average.reset(DeviceDriver::getActiveDriver()->getSApoints()); average.reset(DeviceDriver::SApoints());
traceModel.clearLiveData(); traceModel.clearLiveData();
UpdateAverageCount(); UpdateAverageCount();
} }

View File

@ -125,12 +125,11 @@ TraceEditDialog::TraceEditDialog(Trace &t, QWidget *parent) :
} }
VNAtrace = Trace::isVNAParameter(t.liveParameter()); VNAtrace = Trace::isVNAParameter(t.liveParameter());
if(VirtualDevice::getConnected()) { if(DeviceDriver::getActiveDriver()) {
qDebug() << VirtualDevice::getConnected();
if(VNAtrace) { if(VNAtrace) {
ui->CLiveParam->addItems(VirtualDevice::getConnected()->availableVNAMeasurements()); ui->CLiveParam->addItems(DeviceDriver::getActiveDriver()->availableVNAMeasurements());
} else { } 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() void VNA::ConstrainAndUpdateFrequencies()
{ {
if(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.minFreq; settings.Freq.stop = DeviceDriver::getInfo(window->getDevice()).Limits.VNA.maxFreq;
} }
if(settings.Freq.start > settings.Freq.stop) { if(settings.Freq.start > settings.Freq.stop) {
settings.Freq.start = settings.Freq.stop; settings.Freq.start = settings.Freq.stop;

View File

@ -60,6 +60,7 @@
#include <QDateTime> #include <QDateTime>
#include <QCommandLineParser> #include <QCommandLineParser>
#include <QScrollArea> #include <QScrollArea>
#include <QStringList>
using namespace std; using namespace std;
@ -84,9 +85,6 @@ AppWindow::AppWindow(QWidget *parent)
// qDebug().setVerbosity(0); // qDebug().setVerbosity(0);
qDebug() << "Application start"; qDebug() << "Application start";
// Register device drivers
deviceDrivers.push_back(new LibreVNAUSBDriver());
this->setWindowIcon(QIcon(":/app/logo.png")); this->setWindowIcon(QIcon(":/app/logo.png"));
parser.setApplicationDescription(qlibrevnaApp->applicationName()); parser.setApplicationDescription(qlibrevnaApp->applicationName());
@ -106,6 +104,15 @@ AppWindow::AppWindow(QWidget *parent)
} else { } else {
Preferences::getInstance().load(); Preferences::getInstance().load();
} }
// Register device drivers
deviceDrivers.push_back(new LibreVNAUSBDriver());
for(auto driver : deviceDrivers) {
driver->registerTypes();
Preferences::getInstance().load(driver->driverSpecificSettings());
}
device = nullptr; device = nullptr;
// vdevice = nullptr; // vdevice = nullptr;
modeHandler = nullptr; modeHandler = nullptr;
@ -184,9 +191,9 @@ AppWindow::AppWindow(QWidget *parent)
} }
// List available devices // List available devices
UpdateDeviceList(); UpdateDeviceList();
if(pref.Startup.ConnectToFirstDevice) { if(pref.Startup.ConnectToFirstDevice && deviceList.size() > 0) {
// at least one device available // at least one device available
ConnectToDevice(); ConnectToDevice(deviceList[0].serial);
} }
if(parser.isSet("setup")) { if(parser.isSet("setup")) {
@ -325,10 +332,13 @@ void AppWindow::closeEvent(QCloseEvent *event)
delete modeHandler; delete modeHandler;
modeHandler = nullptr; modeHandler = nullptr;
pref.store(); pref.store();
for(auto driver : deviceDrivers) {
Preferences::getInstance().store(driver->driverSpecificSettings());
}
QMainWindow::closeEvent(event); QMainWindow::closeEvent(event);
} }
bool AppWindow::ConnectToDevice(QString serial) bool AppWindow::ConnectToDevice(QString serial, DeviceDriver *driver)
{ {
if(serial.isEmpty()) { if(serial.isEmpty()) {
qDebug() << "Trying to connect to any device"; qDebug() << "Trying to connect to any device";
@ -341,16 +351,24 @@ bool AppWindow::ConnectToDevice(QString serial)
} }
try { try {
qDebug() << "Attempting to connect to device..."; qDebug() << "Attempting to connect to device...";
for(auto driver : deviceDrivers) { for(auto d : deviceDrivers) {
if(driver->GetAvailableDevices().count(serial)) { if(driver && driver != d) {
// not the specified driver
continue;
}
if(d->GetAvailableDevices().count(serial)) {
// this driver can connect to the device // this driver can connect to the device
if(driver->connectDevice(serial)) { if(d->connectDevice(serial)) {
device = driver; device = d;
} else { } else {
break;
}
}
}
if(!device) {
// failed to connect // failed to connect
// TODO show error message InformationBox::ShowError("Failed to connect", "Could not connect to "+serial);
} return false;
}
} }
UpdateStatusBar(AppWindow::DeviceStatusBar::Connected); UpdateStatusBar(AppWindow::DeviceStatusBar::Connected);
connect(device, &DeviceDriver::InfoUpdated, this, &AppWindow::DeviceInfoUpdated); connect(device, &DeviceDriver::InfoUpdated, this, &AppWindow::DeviceInfoUpdated);
@ -368,8 +386,11 @@ bool AppWindow::ConnectToDevice(QString serial)
// } // }
ui->actionPreset->setEnabled(true); ui->actionPreset->setEnabled(true);
DeviceEntry e;
e.serial = device->getSerial();
e.driver = device;
for(auto d : deviceActionGroup->actions()) { for(auto d : deviceActionGroup->actions()) {
if(d->text() == device->getSerial()) { if(d->text() == e.toString()) {
d->blockSignals(true); d->blockSignals(true);
d->setChecked(true); d->setChecked(true);
d->blockSignals(false); d->blockSignals(false);
@ -476,9 +497,11 @@ void AppWindow::SetupSCPI()
})); }));
scpi_dev->add(new SCPICommand("LIST", nullptr, [=](QStringList) -> QString { scpi_dev->add(new SCPICommand("LIST", nullptr, [=](QStringList) -> QString {
QString ret; QString ret;
for(auto d : VirtualDevice::GetAvailableVirtualDevices()) { for(auto driver : deviceDrivers) {
for(auto d : driver->GetAvailableDevices()) {
ret += d + ","; ret += d + ",";
} }
}
// remove last comma // remove last comma
ret.chop(1); ret.chop(1);
return ret; return ret;
@ -933,34 +956,43 @@ int AppWindow::UpdateDeviceList()
{ {
deviceActionGroup->setExclusive(true); deviceActionGroup->setExclusive(true);
ui->menuConnect_to->clear(); ui->menuConnect_to->clear();
std::set<QString> devices; deviceList.clear();
for(auto driver : deviceDrivers) { 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) { 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; int available = 0;
bool found = false; bool found = false;
if(devices.size()) { for(auto d : deviceList) {
for(auto d : devices) { if(!parser.value("device").isEmpty() && parser.value("device") != d.serial) {
if(!parser.value("device").isEmpty() && parser.value("device") != d) {
// specified device does not match, ignore // specified device does not match, ignore
continue; continue;
} }
auto connectAction = ui->menuConnect_to->addAction(d); auto connectAction = ui->menuConnect_to->addAction(d.toString());
connectAction->setCheckable(true); connectAction->setCheckable(true);
connectAction->setActionGroup(deviceActionGroup); connectAction->setActionGroup(deviceActionGroup);
if(device && d == device->getSerial()) { if(device && d.serial == device->getSerial()) {
connectAction->setChecked(true); connectAction->setChecked(true);
} }
connect(connectAction, &QAction::triggered, [this, d]() { connect(connectAction, &QAction::triggered, [this, d]() {
ConnectToDevice(d); ConnectToDevice(d.serial, d.driver);
}); });
found = true; found = true;
available++; available++;
} }
}
ui->menuConnect_to->setEnabled(found); ui->menuConnect_to->setEnabled(found);
qDebug() << "Updated device list, found" << available; qDebug() << "Updated device list, found" << available;
return available; return available;
@ -1055,12 +1087,16 @@ void AppWindow::ShowUSBLog()
// } // }
//} //}
void AppWindow::DeviceStatusUpdated(VirtualDevice::Status status) void AppWindow::DeviceStatusUpdated()
{ {
lDeviceInfo.setText(status.statusString); lDeviceInfo.setText(device->getStatus());
lADCOverload.setVisible(status.overload); }
lUnlevel.setVisible(status.unlevel);
lUnlock.setVisible(status.unlocked); 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() 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: protected:
void closeEvent(QCloseEvent *event) override; void closeEvent(QCloseEvent *event) override;
private slots: private slots:
bool ConnectToDevice(QString serial = QString()); bool ConnectToDevice(QString serial = QString(), DeviceDriver *driver = nullptr);
void DisconnectDevice(); void DisconnectDevice();
int UpdateDeviceList(); int UpdateDeviceList();
// void StartManualControl(); // void StartManualControl();
@ -67,8 +67,9 @@ private slots:
// void UpdateAcquisitionFrequencies(); // void UpdateAcquisitionFrequencies();
void ShowUSBLog(); void ShowUSBLog();
// void StartFirmwareUpdateDialog(); // void StartFirmwareUpdateDialog();
void DeviceNeedsUpdate(int reported, int expected); // void DeviceNeedsUpdate(int reported, int expected);
void DeviceStatusUpdated(VirtualDevice::Status status); void DeviceStatusUpdated();
void DeviceFlagsUpdated();
void DeviceInfoUpdated(); void DeviceInfoUpdated();
// void SourceCalibrationDialog(); // void SourceCalibrationDialog();
// void ReceiverCalibrationDialog(); // void ReceiverCalibrationDialog();
@ -109,6 +110,20 @@ private:
std::vector<DeviceDriver*> deviceDrivers; std::vector<DeviceDriver*> deviceDrivers;
DeviceDriver *device; 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; DeviceLog deviceLog;
QString deviceSerial; QString deviceSerial;
QActionGroup *deviceActionGroup; QActionGroup *deviceActionGroup;

View File

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

View File

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

View File

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

View File

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