WIP: device driver abstraction
This commit is contained in:
parent
db6d823e0f
commit
cde564299c
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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 \
|
||||
|
Loading…
Reference in New Issue
Block a user