WIP: working compound driver, partial SSA3000X as a demonstration
This commit is contained in:
parent
89e46057a5
commit
b701479e87
@ -3,7 +3,7 @@
|
|||||||
CompoundDevice::CompoundDevice()
|
CompoundDevice::CompoundDevice()
|
||||||
{
|
{
|
||||||
name = "";
|
name = "";
|
||||||
sync = Synchronization::USB;
|
sync = LibreVNADriver::Synchronization::GUI;
|
||||||
}
|
}
|
||||||
|
|
||||||
nlohmann::json CompoundDevice::toJSON()
|
nlohmann::json CompoundDevice::toJSON()
|
||||||
@ -49,26 +49,26 @@ void CompoundDevice::fromJSON(nlohmann::json j)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CompoundDevice::SyncToString(CompoundDevice::Synchronization sync)
|
QString CompoundDevice::SyncToString(LibreVNADriver::Synchronization sync)
|
||||||
{
|
{
|
||||||
switch(sync) {
|
switch(sync) {
|
||||||
case Synchronization::USB: return "USB";
|
case LibreVNADriver::Synchronization::Disabled: return "Disabled";
|
||||||
case Synchronization::ExtRef: return "Ext. Ref.";
|
case LibreVNADriver::Synchronization::GUI: return "GUI";
|
||||||
case Synchronization::Trigger: return "Trigger";
|
case LibreVNADriver::Synchronization::ExternalTrigger: return "Trigger";
|
||||||
default:
|
default:
|
||||||
case Synchronization::Last: return "Invalid";
|
return "Invalid";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CompoundDevice::Synchronization CompoundDevice::SyncFromString(QString s)
|
LibreVNADriver::Synchronization CompoundDevice::SyncFromString(QString s)
|
||||||
{
|
{
|
||||||
for(int i=0;i<(int) Synchronization::Last;i++) {
|
for(int i=0;i<(int) LibreVNADriver::Synchronization::Last;i++) {
|
||||||
if(SyncToString((Synchronization)i) == s) {
|
if(SyncToString((LibreVNADriver::Synchronization)i) == s) {
|
||||||
return (Synchronization) i;
|
return (LibreVNADriver::Synchronization) i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// default to USB
|
// default to GUI
|
||||||
return Synchronization::USB;
|
return LibreVNADriver::Synchronization::GUI;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CompoundDevice::getDesription()
|
QString CompoundDevice::getDesription()
|
||||||
@ -76,7 +76,7 @@ QString CompoundDevice::getDesription()
|
|||||||
return name + ", "+QString::number(deviceSerials.size())+" devices, "+QString::number(portMapping.size())+" ports in total";
|
return name + ", "+QString::number(deviceSerials.size())+" devices, "+QString::number(portMapping.size())+" ports in total";
|
||||||
}
|
}
|
||||||
|
|
||||||
int CompoundDevice::PortMapping::findActiveStage(std::vector<CompoundDevice::PortMapping> map, unsigned int device, unsigned int port)
|
unsigned int CompoundDevice::PortMapping::findActiveStage(std::vector<CompoundDevice::PortMapping> map, unsigned int device, unsigned int port)
|
||||||
{
|
{
|
||||||
for(unsigned int i=0;i<map.size();i++) {
|
for(unsigned int i=0;i<map.size();i++) {
|
||||||
if(map[i].device == device && map[i].port == port) {
|
if(map[i].device == device && map[i].port == port) {
|
@ -2,6 +2,7 @@
|
|||||||
#define COMPOUNDDEVICE_H
|
#define COMPOUNDDEVICE_H
|
||||||
|
|
||||||
#include "savable.h"
|
#include "savable.h"
|
||||||
|
#include "../librevnadriver.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -18,25 +19,18 @@ public:
|
|||||||
|
|
||||||
class PortMapping {
|
class PortMapping {
|
||||||
public:
|
public:
|
||||||
unsigned int device;
|
unsigned int device; // starts at zero
|
||||||
unsigned int port;
|
unsigned int port; // starts at zero
|
||||||
static int findActiveStage(std::vector<PortMapping> map, unsigned int device, unsigned int port);
|
static unsigned int findActiveStage(std::vector<PortMapping> map, unsigned int device, unsigned int port);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Synchronization {
|
static QString SyncToString(LibreVNADriver::Synchronization sync);
|
||||||
USB,
|
static LibreVNADriver::Synchronization SyncFromString(QString s);
|
||||||
ExtRef,
|
|
||||||
Trigger,
|
|
||||||
Last
|
|
||||||
};
|
|
||||||
|
|
||||||
static QString SyncToString(Synchronization sync);
|
|
||||||
static Synchronization SyncFromString(QString s);
|
|
||||||
|
|
||||||
QString getDesription();
|
QString getDesription();
|
||||||
|
|
||||||
QString name;
|
QString name;
|
||||||
Synchronization sync;
|
LibreVNADriver::Synchronization sync;
|
||||||
std::vector<QString> deviceSerials;
|
std::vector<QString> deviceSerials;
|
||||||
std::vector<PortMapping> portMapping;
|
std::vector<PortMapping> portMapping;
|
||||||
};
|
};
|
@ -1,7 +1,7 @@
|
|||||||
#include "compounddeviceeditdialog.h"
|
#include "compounddeviceeditdialog.h"
|
||||||
#include "ui_compounddeviceeditdialog.h"
|
#include "ui_compounddeviceeditdialog.h"
|
||||||
|
|
||||||
#include "device.h"
|
#include "../../device.h"
|
||||||
|
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QDrag>
|
#include <QDrag>
|
||||||
@ -25,9 +25,9 @@ CompoundDeviceEditDialog::CompoundDeviceEditDialog(CompoundDevice *cdev, QWidget
|
|||||||
ldev.name = ui->name->text();
|
ldev.name = ui->name->text();
|
||||||
checkIfOkay();
|
checkIfOkay();
|
||||||
});
|
});
|
||||||
for(int i=0;i<(int)CompoundDevice::Synchronization::Last;i++) {
|
for(int i=0;i<(int)LibreVNADriver::Synchronization::Last;i++) {
|
||||||
ui->sync->addItem(CompoundDevice::SyncToString((CompoundDevice::Synchronization) i));
|
ui->sync->addItem(CompoundDevice::SyncToString((LibreVNADriver::Synchronization) i));
|
||||||
if((CompoundDevice::Synchronization) i == CompoundDevice::Synchronization::Trigger) {
|
if((LibreVNADriver::Synchronization) i == LibreVNADriver::Synchronization::ExternalTrigger) {
|
||||||
// Disable for now
|
// Disable for now
|
||||||
auto *model = qobject_cast<QStandardItemModel *>(ui->sync->model());
|
auto *model = qobject_cast<QStandardItemModel *>(ui->sync->model());
|
||||||
Q_ASSERT(model != nullptr);
|
Q_ASSERT(model != nullptr);
|
||||||
@ -522,9 +522,9 @@ void DeviceFrame::update()
|
|||||||
// }
|
// }
|
||||||
serial->setCurrentText(s);
|
serial->setCurrentText(s);
|
||||||
|
|
||||||
if(dev->sync == CompoundDevice::Synchronization::USB) {
|
if(dev->sync == LibreVNADriver::Synchronization::GUI) {
|
||||||
setStyleSheet("image: url(:/icons/compound_V1_USB.png);");
|
setStyleSheet("image: url(:/icons/compound_V1_USB.png);");
|
||||||
} else if(dev->sync == CompoundDevice::Synchronization::ExtRef) {
|
} else if(dev->sync == LibreVNADriver::Synchronization::Reserved) {
|
||||||
if(position == 0) {
|
if(position == 0) {
|
||||||
setStyleSheet("image: url(:/icons/compound_V1_Ref_Left.png);");
|
setStyleSheet("image: url(:/icons/compound_V1_Ref_Left.png);");
|
||||||
} else if(position == dev->deviceSerials.size() - 1) {
|
} else if(position == dev->deviceSerials.size() - 1) {
|
@ -0,0 +1,706 @@
|
|||||||
|
#include "compounddriver.h"
|
||||||
|
|
||||||
|
#include "../librevnatcpdriver.h"
|
||||||
|
#include "../librevnausbdriver.h"
|
||||||
|
|
||||||
|
#include "ui_compounddriversettingswidget.h"
|
||||||
|
#include "compounddeviceeditdialog.h"
|
||||||
|
#include "preferences.h"
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
CompoundDriver::CompoundDriver()
|
||||||
|
{
|
||||||
|
connected = false;
|
||||||
|
|
||||||
|
drivers.push_back(new LibreVNAUSBDriver);
|
||||||
|
drivers.push_back(new LibreVNATCPDriver);
|
||||||
|
|
||||||
|
auto &p = Preferences::getInstance();
|
||||||
|
for(auto d : drivers) {
|
||||||
|
p.load(d->driverSpecificSettings());
|
||||||
|
}
|
||||||
|
|
||||||
|
specificSettings.push_back(Savable::SettingDescription(&compoundJSONString, "compoundDriver.compoundDeviceJSON", ""));
|
||||||
|
specificSettings.push_back(Savable::SettingDescription(&captureRawReceiverValues, "compoundDriver.captureRawReceiverValues", false));
|
||||||
|
}
|
||||||
|
|
||||||
|
CompoundDriver::~CompoundDriver()
|
||||||
|
{
|
||||||
|
disconnect();
|
||||||
|
for(auto d : drivers) {
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<QString> CompoundDriver::GetAvailableDevices()
|
||||||
|
{
|
||||||
|
parseCompoundJSON();
|
||||||
|
|
||||||
|
std::set<QString> availableSerials;
|
||||||
|
for(auto d : drivers) {
|
||||||
|
availableSerials.merge(d->GetAvailableDevices());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<QString> ret;
|
||||||
|
|
||||||
|
for(auto cd : configuredDevices) {
|
||||||
|
bool allAvailable = true;
|
||||||
|
for(auto s : cd->deviceSerials) {
|
||||||
|
if(availableSerials.count(s) == 0) {
|
||||||
|
allAvailable = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(allAvailable) {
|
||||||
|
ret.insert(cd->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CompoundDriver::connectTo(QString getSerial)
|
||||||
|
{
|
||||||
|
if(connected) {
|
||||||
|
disconnect();
|
||||||
|
}
|
||||||
|
bool found = false;
|
||||||
|
for(auto cd : configuredDevices) {
|
||||||
|
if(cd->name == getSerial) {
|
||||||
|
activeDevice = *cd;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!found) {
|
||||||
|
qWarning() << "Attempted to connect to an unknown compound device";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::vector<std::set<QString>> availableSerials;
|
||||||
|
for(auto d : drivers) {
|
||||||
|
availableSerials.push_back(d->GetAvailableDevices());
|
||||||
|
}
|
||||||
|
// attempt to connect to all individual devices
|
||||||
|
for(auto s : activeDevice.deviceSerials) {
|
||||||
|
LibreVNADriver *device = nullptr;
|
||||||
|
for(unsigned int i=0;i<availableSerials.size();i++) {
|
||||||
|
if(availableSerials[i].count(s) > 0) {
|
||||||
|
// this driver can connect to the requested device
|
||||||
|
if (i == 0) {
|
||||||
|
device = new LibreVNAUSBDriver();
|
||||||
|
break;
|
||||||
|
} else if(i == 1) {
|
||||||
|
device = new LibreVNATCPDriver();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!device) {
|
||||||
|
qWarning() << "Unable to find required serial for compound device:" <<s;
|
||||||
|
disconnect();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto &p = Preferences::getInstance();
|
||||||
|
p.load(device->driverSpecificSettings());
|
||||||
|
if(!device->connectDevice(s, true)) {
|
||||||
|
qWarning() << "Unable to connect to required serial for compound device:" <<s;
|
||||||
|
delete device;
|
||||||
|
disconnect();
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
devices.push_back(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// make device connections
|
||||||
|
for(auto dev : devices) {
|
||||||
|
// Create device connections
|
||||||
|
connect(dev, &LibreVNADriver::ConnectionLost, this, &CompoundDriver::ConnectionLost, Qt::QueuedConnection);
|
||||||
|
connect(dev, &LibreVNADriver::LogLineReceived, this, [=](QString line){
|
||||||
|
emit LogLineReceived(line.prepend(dev->getSerial()+": "));
|
||||||
|
});
|
||||||
|
connect(dev, &LibreVNADriver::InfoUpdated, this, [=]() {
|
||||||
|
updatedInfo(dev);
|
||||||
|
});
|
||||||
|
connect(dev, &LibreVNADriver::passOnReceivedPacket, this, [=](const Protocol::PacketInfo& packet) {
|
||||||
|
incomingPacket(dev, packet);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
connected = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompoundDriver::disconnect()
|
||||||
|
{
|
||||||
|
for(auto d : devices) {
|
||||||
|
QObject::disconnect(d, nullptr, this, nullptr);
|
||||||
|
d->disconnect();
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
devices.clear();
|
||||||
|
deviceInfos.clear();
|
||||||
|
deviceStatus.clear();
|
||||||
|
compoundSABuffer.clear();
|
||||||
|
compoundVNABuffer.clear();
|
||||||
|
connected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CompoundDriver::getSerial()
|
||||||
|
{
|
||||||
|
if(connected) {
|
||||||
|
return activeDevice.name;
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<DeviceDriver::Flag> CompoundDriver::getFlags()
|
||||||
|
{
|
||||||
|
std::set<DeviceDriver::Flag> ret;
|
||||||
|
if(lastStatus.extRefInUse) {
|
||||||
|
ret.insert(Flag::ExtRef);
|
||||||
|
}
|
||||||
|
if(!lastStatus.source_locked || !lastStatus.LO1_locked) {
|
||||||
|
ret.insert(Flag::Unlocked);
|
||||||
|
}
|
||||||
|
if(lastStatus.unlevel) {
|
||||||
|
ret.insert(Flag::Unlevel);
|
||||||
|
}
|
||||||
|
if(lastStatus.ADC_overload) {
|
||||||
|
ret.insert(Flag::Overload);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CompoundDriver::getStatus()
|
||||||
|
{
|
||||||
|
QString ret;
|
||||||
|
ret.append("HW Rev.");
|
||||||
|
ret.append(info.hardware_version);
|
||||||
|
ret.append(" FW "+info.firmware_version);
|
||||||
|
ret.append(" Temps: "+QString::number(lastStatus.temp_source)+"°C/"+QString::number(lastStatus.temp_LO1)+"°C/"+QString::number(lastStatus.temp_MCU)+"°C");
|
||||||
|
ret.append(" Reference:");
|
||||||
|
if(lastStatus.extRefInUse) {
|
||||||
|
ret.append("External");
|
||||||
|
} else {
|
||||||
|
ret.append("Internal");
|
||||||
|
if(lastStatus.extRefAvailable) {
|
||||||
|
ret.append(" (External available)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget *CompoundDriver::createSettingsWidget()
|
||||||
|
{
|
||||||
|
auto w = new QWidget();
|
||||||
|
auto ui = new Ui::CompoundDriverSettingsWidget;
|
||||||
|
ui->setupUi(w);
|
||||||
|
|
||||||
|
// Set initial values
|
||||||
|
ui->CaptureRawReceiverValues->setChecked(captureRawReceiverValues);
|
||||||
|
|
||||||
|
// make connections
|
||||||
|
connect(ui->CaptureRawReceiverValues, &QCheckBox::toggled, this, [=](){
|
||||||
|
captureRawReceiverValues = ui->CaptureRawReceiverValues->isChecked();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(ui->compoundList, &QListWidget::doubleClicked, [=](){
|
||||||
|
auto index = ui->compoundList->currentRow();
|
||||||
|
if(index >= 0 && index < (int) configuredDevices.size()) {
|
||||||
|
auto d = new CompoundDeviceEditDialog(configuredDevices[index]);
|
||||||
|
connect(d, &QDialog::accepted, [=](){
|
||||||
|
ui->compoundList->item(index)->setText(configuredDevices[index]->getDesription());
|
||||||
|
createCompoundJSON();
|
||||||
|
});
|
||||||
|
d->show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
connect(ui->compoundAdd, &QPushButton::clicked, [=](){
|
||||||
|
auto cd = new CompoundDevice;
|
||||||
|
auto d = new CompoundDeviceEditDialog(cd);
|
||||||
|
connect(d, &QDialog::accepted, [=](){
|
||||||
|
configuredDevices.push_back(cd);
|
||||||
|
ui->compoundList->addItem(cd->getDesription());
|
||||||
|
createCompoundJSON();
|
||||||
|
});
|
||||||
|
connect(d, &QDialog::rejected, [=](){
|
||||||
|
delete cd;
|
||||||
|
});
|
||||||
|
d->show();
|
||||||
|
});
|
||||||
|
connect(ui->compoundDelete, &QPushButton::clicked, [=](){
|
||||||
|
auto index = ui->compoundList->currentRow();
|
||||||
|
if(index >= 0 && index < (int) configuredDevices.size()) {
|
||||||
|
// delete the actual compound device
|
||||||
|
delete configuredDevices[index];
|
||||||
|
// delete the line in the GUI list
|
||||||
|
delete ui->compoundList->takeItem(index);
|
||||||
|
// remove compound device from list
|
||||||
|
configuredDevices.erase(configuredDevices.begin() + index);
|
||||||
|
createCompoundJSON();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for(auto cd : configuredDevices) {
|
||||||
|
ui->compoundList->addItem(cd->getDesription());
|
||||||
|
}
|
||||||
|
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList CompoundDriver::availableVNAMeasurements()
|
||||||
|
{
|
||||||
|
QStringList ret;
|
||||||
|
for(unsigned int i=1;i<=info.Limits.VNA.ports;i++) {
|
||||||
|
for(unsigned int j=1;j<=info.Limits.VNA.ports;j++) {
|
||||||
|
ret.push_back("S"+QString::number(i)+QString::number(j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(captureRawReceiverValues) {
|
||||||
|
for(unsigned int i=1;i<=info.Limits.VNA.ports;i++) {
|
||||||
|
for(unsigned int j=0;j<info.Limits.VNA.ports;j++) {
|
||||||
|
ret.push_back("RawPort"+QString::number(i)+"Stage"+QString::number(j));
|
||||||
|
ret.push_back("RawPort"+QString::number(i)+"Stage"+QString::number(j)+"Ref");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CompoundDriver::setVNA(const DeviceDriver::VNASettings &s, std::function<void (bool)> cb)
|
||||||
|
{
|
||||||
|
if(!supports(Feature::VNA)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(s.excitedPorts.size() == 0) {
|
||||||
|
return setIdle(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create port->stage mapping
|
||||||
|
portStageMapping.clear();
|
||||||
|
for(unsigned int i=0;i<s.excitedPorts.size();i++) {
|
||||||
|
portStageMapping[s.excitedPorts[i]] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
zerospan = (s.freqStart == s.freqStop) && (s.dBmStart == s.dBmStop);
|
||||||
|
// create vector of currently used stimulus ports
|
||||||
|
std::vector<CompoundDevice::PortMapping> activeMapping;
|
||||||
|
for(auto p : s.excitedPorts) {
|
||||||
|
activeMapping.push_back(activeDevice.portMapping[p-1]);
|
||||||
|
}
|
||||||
|
// Configure the devices
|
||||||
|
results.clear();
|
||||||
|
bool success = true;
|
||||||
|
for(unsigned int i=0;i<devices.size();i++) {
|
||||||
|
auto dev = devices[i];
|
||||||
|
dev->setSynchronization(activeDevice.sync, i == 0);
|
||||||
|
auto devSetting = s;
|
||||||
|
// indicate the number of stages
|
||||||
|
devSetting.excitedPorts = std::vector<int>(s.excitedPorts.size(), 0);
|
||||||
|
// activate the ports of this specific device at the correct stage
|
||||||
|
auto p1Stage = CompoundDevice::PortMapping::findActiveStage(activeMapping, i, 0);
|
||||||
|
if(p1Stage < s.excitedPorts.size()) {
|
||||||
|
devSetting.excitedPorts[p1Stage] = 1;
|
||||||
|
}
|
||||||
|
auto p2Stage = CompoundDevice::PortMapping::findActiveStage(activeMapping, i, 1);
|
||||||
|
if(p2Stage < s.excitedPorts.size()) {
|
||||||
|
devSetting.excitedPorts[p2Stage] = 2;
|
||||||
|
}
|
||||||
|
success &= devices[i]->setVNA(devSetting, [=](bool success){
|
||||||
|
if(cb) {
|
||||||
|
results[devices[i]] = success;
|
||||||
|
checkIfAllTransmissionsComplete(cb);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList CompoundDriver::availableSAMeasurements()
|
||||||
|
{
|
||||||
|
QStringList ret;
|
||||||
|
for(unsigned int i=1;i<=info.Limits.SA.ports;i++) {
|
||||||
|
ret.push_back("PORT"+QString::number(i));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CompoundDriver::setSA(const DeviceDriver::SASettings &s, std::function<void (bool)> cb)
|
||||||
|
{
|
||||||
|
if(!supports(Feature::SA)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
zerospan = s.freqStart == s.freqStop;
|
||||||
|
|
||||||
|
// Configure the devices
|
||||||
|
results.clear();
|
||||||
|
bool success = true;
|
||||||
|
for(unsigned int i=0;i<devices.size();i++) {
|
||||||
|
auto dev = devices[i];
|
||||||
|
dev->setSynchronization(activeDevice.sync, i == 0);
|
||||||
|
auto devSettings = s;
|
||||||
|
devSettings.trackingGenerator = false;
|
||||||
|
devSettings.trackingPort = 0;
|
||||||
|
if(s.trackingGenerator) {
|
||||||
|
if(activeDevice.portMapping[s.trackingPort-1].device == i) {
|
||||||
|
// tracking generator active on this device
|
||||||
|
devSettings.trackingGenerator = true;
|
||||||
|
devSettings.trackingPort = activeDevice.portMapping[s.trackingPort-1].port + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
success &= devices[i]->setSA(devSettings, [=](bool success){
|
||||||
|
if(cb) {
|
||||||
|
results[devices[i]] = success;
|
||||||
|
checkIfAllTransmissionsComplete(cb);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
SApoints = devices[0]->getSApoints();
|
||||||
|
for(unsigned int i=1;i<devices.size();i++) {
|
||||||
|
if(devices[i]->getSApoints() != SApoints) {
|
||||||
|
qWarning() << "Individual devices report different number of SA points, unable to start compound SA sweep";
|
||||||
|
setIdle();
|
||||||
|
success = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList CompoundDriver::availableSGPorts()
|
||||||
|
{
|
||||||
|
QStringList ret;
|
||||||
|
for(unsigned int i=1;i<info.Limits.Generator.ports;i++) {
|
||||||
|
ret.push_back("PORT"+QString::number(i));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CompoundDriver::setSG(const DeviceDriver::SGSettings &s)
|
||||||
|
{
|
||||||
|
if(!supports(Feature::Generator)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// configure all devices
|
||||||
|
bool success = true;
|
||||||
|
for(unsigned int i=0;i<devices.size();i++) {
|
||||||
|
auto devSettings = s;
|
||||||
|
devSettings.port = 0;
|
||||||
|
if(s.port > 0) {
|
||||||
|
if(activeDevice.portMapping[s.port-1].device == i) {
|
||||||
|
// this device has the active port
|
||||||
|
devSettings.port = activeDevice.portMapping[s.port-1].port+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
success &= devices[i]->setSG(devSettings);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CompoundDriver::setIdle(std::function<void (bool)> cb)
|
||||||
|
{
|
||||||
|
auto success = true;
|
||||||
|
results.clear();
|
||||||
|
for(auto dev : devices) {
|
||||||
|
success &= dev->setIdle([=](bool success){
|
||||||
|
if(cb) {
|
||||||
|
results[dev] = success;
|
||||||
|
checkIfAllTransmissionsComplete(cb);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList CompoundDriver::availableExtRefInSettings()
|
||||||
|
{
|
||||||
|
if(!connected) {
|
||||||
|
return QStringList();
|
||||||
|
}
|
||||||
|
auto set = devices[0]->availableExtRefInSettings().toSet();
|
||||||
|
for(unsigned int i=1;i<devices.size();i++) {
|
||||||
|
set = set.intersect(devices[i]->availableExtRefInSettings().toSet());
|
||||||
|
}
|
||||||
|
return QStringList(set.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList CompoundDriver::availableExtRefOutSettings()
|
||||||
|
{
|
||||||
|
if(!connected) {
|
||||||
|
return QStringList();
|
||||||
|
}
|
||||||
|
auto set = devices[0]->availableExtRefOutSettings().toSet();
|
||||||
|
for(unsigned int i=1;i<devices.size();i++) {
|
||||||
|
set = set.intersect(devices[i]->availableExtRefOutSettings().toSet());
|
||||||
|
}
|
||||||
|
return QStringList(set.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CompoundDriver::setExtRef(QString option_in, QString option_out)
|
||||||
|
{
|
||||||
|
auto success = true;
|
||||||
|
for(auto dev : devices) {
|
||||||
|
success &= dev->setExtRef(option_in, option_out);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompoundDriver::parseCompoundJSON()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
configuredDevices.clear();
|
||||||
|
nlohmann::json jc = nlohmann::json::parse(compoundJSONString.toStdString());
|
||||||
|
for(auto j : jc) {
|
||||||
|
auto cd = new CompoundDevice();
|
||||||
|
cd->fromJSON(j);
|
||||||
|
configuredDevices.push_back(cd);
|
||||||
|
}
|
||||||
|
} catch(const std::exception& e){
|
||||||
|
qDebug() << "Failed to parse compound device string: " << e.what();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompoundDriver::createCompoundJSON()
|
||||||
|
{
|
||||||
|
if(configuredDevices.size() > 0) {
|
||||||
|
nlohmann::json j;
|
||||||
|
for(auto cd : configuredDevices) {
|
||||||
|
j.push_back(cd->toJSON());
|
||||||
|
}
|
||||||
|
compoundJSONString = QString::fromStdString(j.dump());
|
||||||
|
} else {
|
||||||
|
compoundJSONString = "[]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompoundDriver::incomingPacket(LibreVNADriver *device, const Protocol::PacketInfo &p)
|
||||||
|
{
|
||||||
|
switch(p.type) {
|
||||||
|
case Protocol::PacketType::DeviceStatusV1:
|
||||||
|
updatedStatus(device, p.statusV1);
|
||||||
|
break;
|
||||||
|
case Protocol::PacketType::VNADatapoint:
|
||||||
|
datapointReceivecd(device, p.VNAdatapoint);
|
||||||
|
break;
|
||||||
|
case Protocol::PacketType::SpectrumAnalyzerResult:
|
||||||
|
spectrumResultReceived(device, p.spectrumResult);
|
||||||
|
break;
|
||||||
|
case Protocol::PacketType::SetTrigger:
|
||||||
|
if(activeDevice.sync == LibreVNADriver::Synchronization::GUI) {
|
||||||
|
for(unsigned int i=0;i<devices.size();i++) {
|
||||||
|
if(devices[i] == device) {
|
||||||
|
// pass on to the next device
|
||||||
|
if(i < devices.size() - 1) {
|
||||||
|
devices[i+1]->sendWithoutPayload(Protocol::PacketType::SetTrigger);
|
||||||
|
} else {
|
||||||
|
devices[0]->sendWithoutPayload(Protocol::PacketType::SetTrigger);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Protocol::PacketType::ClearTrigger:
|
||||||
|
if(activeDevice.sync == LibreVNADriver::Synchronization::GUI) {
|
||||||
|
for(unsigned int i=0;i<devices.size();i++) {
|
||||||
|
if(devices[i] == device) {
|
||||||
|
// pass on to the next device
|
||||||
|
if(i < devices.size() - 1) {
|
||||||
|
devices[i+1]->sendWithoutPayload(Protocol::PacketType::ClearTrigger);
|
||||||
|
} else {
|
||||||
|
devices[0]->sendWithoutPayload(Protocol::PacketType::ClearTrigger);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// nothing to do for other packet types
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompoundDriver::updatedInfo(LibreVNADriver *device)
|
||||||
|
{
|
||||||
|
deviceInfos[device] = device->getInfo();
|
||||||
|
if(deviceInfos.size() == devices.size()) {
|
||||||
|
// got infos from all devices
|
||||||
|
info = devices[0]->getInfo();
|
||||||
|
for(unsigned int i=1;i<devices.size();i++) {
|
||||||
|
info.subset(devices[i]->getInfo());
|
||||||
|
}
|
||||||
|
// overwrite number of ports (not all physical ports may be configured for this compound device)
|
||||||
|
info.Limits.VNA.ports = activeDevice.portMapping.size();
|
||||||
|
info.Limits.Generator.ports = activeDevice.portMapping.size();
|
||||||
|
info.Limits.SA.ports = activeDevice.portMapping.size();
|
||||||
|
emit InfoUpdated();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompoundDriver::updatedStatus(LibreVNADriver *device, const Protocol::DeviceStatusV1 &status)
|
||||||
|
{
|
||||||
|
deviceStatus[device] = status;
|
||||||
|
if(deviceStatus.size() == devices.size()) {
|
||||||
|
// got status from all devices
|
||||||
|
for(unsigned int i=0;i<devices.size();i++) {
|
||||||
|
auto devStat = deviceStatus[devices[i]];
|
||||||
|
if(i==0) {
|
||||||
|
lastStatus = devStat;
|
||||||
|
} else {
|
||||||
|
lastStatus.extRefAvailable &= devStat.extRefAvailable;
|
||||||
|
lastStatus.extRefInUse |= devStat.extRefInUse;
|
||||||
|
lastStatus.FPGA_configured &= devStat.FPGA_configured;
|
||||||
|
lastStatus.source_locked &= devStat.source_locked;
|
||||||
|
lastStatus.LO1_locked &= devStat.LO1_locked;
|
||||||
|
lastStatus.ADC_overload |= devStat.ADC_overload;
|
||||||
|
lastStatus.unlevel |= devStat.unlevel;
|
||||||
|
lastStatus.temp_source = std::max(lastStatus.temp_source, devStat.temp_source);
|
||||||
|
lastStatus.temp_LO1 = std::max(lastStatus.temp_LO1, devStat.temp_LO1);
|
||||||
|
lastStatus.temp_MCU = std::max(lastStatus.temp_MCU, devStat.temp_MCU);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emit StatusUpdated();
|
||||||
|
emit FlagsUpdated();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompoundDriver::spectrumResultReceived(LibreVNADriver *dev, Protocol::SpectrumAnalyzerResult res)
|
||||||
|
{
|
||||||
|
if(!compoundSABuffer.count(res.pointNum)) {
|
||||||
|
compoundSABuffer[res.pointNum] = std::map<LibreVNADriver*, Protocol::SpectrumAnalyzerResult>();
|
||||||
|
}
|
||||||
|
auto &buf = compoundSABuffer[res.pointNum];
|
||||||
|
buf[dev] = res;
|
||||||
|
if(buf.size() == devices.size()) {
|
||||||
|
// Got datapoints from all devices, can create merged VNA result
|
||||||
|
SAMeasurement m;
|
||||||
|
m.pointNum = res.pointNum;
|
||||||
|
if(zerospan) {
|
||||||
|
m.us = res.us;
|
||||||
|
} else {
|
||||||
|
m.frequency = res.frequency;
|
||||||
|
}
|
||||||
|
// assemble data
|
||||||
|
for(unsigned int port=0;port<activeDevice.portMapping.size();port++) {
|
||||||
|
auto device = devices[activeDevice.portMapping[port].device];
|
||||||
|
auto devicePort = activeDevice.portMapping[port].port;
|
||||||
|
|
||||||
|
QString name = "PORT"+QString::number(port+1);
|
||||||
|
if(devicePort == 0) {
|
||||||
|
m.measurements[name] = buf[device].port1;
|
||||||
|
} else {
|
||||||
|
m.measurements[name] = buf[device].port2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emit SAmeasurementReceived(m);
|
||||||
|
|
||||||
|
// Clear this and all (incomplete) older datapoint buffers
|
||||||
|
auto it = compoundSABuffer.begin();
|
||||||
|
while(it != compoundSABuffer.end()) {
|
||||||
|
if(it->first <= res.pointNum) {
|
||||||
|
it = compoundSABuffer.erase(it);
|
||||||
|
} else {
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompoundDriver::datapointReceivecd(LibreVNADriver *dev, Protocol::VNADatapoint<32> *data)
|
||||||
|
{
|
||||||
|
if(!compoundVNABuffer.count(data->pointNum)) {
|
||||||
|
compoundVNABuffer[data->pointNum] = std::map<LibreVNADriver*, Protocol::VNADatapoint<32>*>();
|
||||||
|
}
|
||||||
|
auto &buf = compoundVNABuffer[data->pointNum];
|
||||||
|
// create copy of datapoint as it will be deleted by the device driver
|
||||||
|
buf[dev] = new Protocol::VNADatapoint<32>(*data);
|
||||||
|
if(buf.size() == devices.size()) {
|
||||||
|
// Got datapoints from all devices, can create merged VNA result
|
||||||
|
VNAMeasurement m;
|
||||||
|
m.pointNum = data->pointNum;
|
||||||
|
m.Z0 = 50.0;
|
||||||
|
if(zerospan) {
|
||||||
|
m.us = data->us;
|
||||||
|
} else {
|
||||||
|
m.frequency = data->frequency;
|
||||||
|
m.dBm = (double) data->cdBm / 100;
|
||||||
|
}
|
||||||
|
// assemble data
|
||||||
|
for(auto map : portStageMapping) {
|
||||||
|
// map.first is the port (starts at one)
|
||||||
|
// map.second is the stage at which this port had the stimulus (starts at zero)
|
||||||
|
|
||||||
|
// figure out which device had the stimulus for the port...
|
||||||
|
auto stimulusDev = devices[activeDevice.portMapping[map.first-1].device];
|
||||||
|
// ...and which device port was used for the stimulus...
|
||||||
|
auto stimulusDevPort = activeDevice.portMapping[map.first-1].port;
|
||||||
|
// ...grab the reference receiver data
|
||||||
|
std::complex<double> ref = buf[stimulusDev]->getValue(map.second, stimulusDevPort, true);
|
||||||
|
|
||||||
|
// for all ports of the compound device...
|
||||||
|
for(unsigned int i=0;i<activeDevice.portMapping.size();i++) {
|
||||||
|
// ...figure out which physical device and port was used for this input...
|
||||||
|
auto inputDevice = devices[activeDevice.portMapping[i].device];
|
||||||
|
// ...and grab the data
|
||||||
|
auto inputPort = activeDevice.portMapping[i].port;
|
||||||
|
std::complex<double> input = buf[inputDevice]->getValue(map.second, inputPort, false);
|
||||||
|
if(!std::isnan(ref.real()) && !std::isnan(input.real())) {
|
||||||
|
// got both required measurements
|
||||||
|
QString name = "S"+QString::number(i+1)+QString::number(map.first);
|
||||||
|
auto S = input / ref;
|
||||||
|
if(inputDevice != stimulusDev) {
|
||||||
|
// can't use phase information when measuring across devices
|
||||||
|
S = abs(S);
|
||||||
|
}
|
||||||
|
m.measurements[name] = S;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(captureRawReceiverValues) {
|
||||||
|
QString name = "RawPort"+QString::number(inputPort+1)+"Stage"+QString::number(map.second);
|
||||||
|
m.measurements[name] = input;
|
||||||
|
name = "RawPort"+QString::number(inputPort+1)+"Stage"+QString::number(map.second)+"Ref";
|
||||||
|
m.measurements[name] = buf[inputDevice]->getValue(map.second, inputPort, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emit VNAmeasurementReceived(m);
|
||||||
|
|
||||||
|
// Clear this and all (incomplete) older datapoint buffers
|
||||||
|
int pointNum = data->pointNum;
|
||||||
|
auto it = compoundVNABuffer.begin();
|
||||||
|
while(it != compoundVNABuffer.end()) {
|
||||||
|
if(it->first <= pointNum) {
|
||||||
|
for(auto d : it->second) {
|
||||||
|
delete d.second;
|
||||||
|
}
|
||||||
|
it = compoundVNABuffer.erase(it);
|
||||||
|
} else {
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompoundDriver::checkIfAllTransmissionsComplete(std::function<void (bool)> cb)
|
||||||
|
{
|
||||||
|
if(results.size() == devices.size()) {
|
||||||
|
// got all responses
|
||||||
|
bool success = true;
|
||||||
|
for(auto res : results) {
|
||||||
|
if(res.second != true) {
|
||||||
|
success = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(cb) {
|
||||||
|
cb(success);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,210 @@
|
|||||||
|
#ifndef COMPOUNDDRIVER_H
|
||||||
|
#define COMPOUNDDRIVER_H
|
||||||
|
|
||||||
|
#include "../../devicedriver.h"
|
||||||
|
#include "compounddevice.h"
|
||||||
|
|
||||||
|
class CompoundDriver : public DeviceDriver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CompoundDriver();
|
||||||
|
~CompoundDriver();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the driver name. It must be unique across all implemented drivers and is used to identify the driver
|
||||||
|
* @return driver name
|
||||||
|
*/
|
||||||
|
virtual QString getDriverName() override {return "LibreVNA/Compound";}
|
||||||
|
/**
|
||||||
|
* @brief Lists all available devices by their serial numbers
|
||||||
|
* @return Serial numbers of detected devices
|
||||||
|
*/
|
||||||
|
virtual std::set<QString> GetAvailableDevices() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* @brief Connects to a device, given by its serial number
|
||||||
|
*
|
||||||
|
* @param serial Serial number of device that should be connected to
|
||||||
|
* @return true if connection successful, otherwise false
|
||||||
|
*/
|
||||||
|
virtual bool connectTo(QString getSerial) override;
|
||||||
|
/**
|
||||||
|
* @brief Disconnects from device. Has no effect if no device was connected
|
||||||
|
*/
|
||||||
|
virtual void disconnect() override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Returns the serial number of the connected device
|
||||||
|
* @return Serial number of connected device (empty string if no device is connected)
|
||||||
|
*/
|
||||||
|
virtual QString getSerial() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the device information. This function will be called when a device has been connected. Its return value must be valid
|
||||||
|
* directly after returning from DeviceDriver::connectTo()
|
||||||
|
*
|
||||||
|
* Emit the InfoUpdate() signal whenever the return value of this function changes.
|
||||||
|
*
|
||||||
|
* @return Device information
|
||||||
|
*/
|
||||||
|
virtual Info getInfo() override {return info;}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a set of all active flags
|
||||||
|
*
|
||||||
|
* There is also a convenience function to check a specific flag, see DeviceDriver::asserted()
|
||||||
|
*
|
||||||
|
* @return Set of active flags
|
||||||
|
*/
|
||||||
|
virtual std::set<Flag> getFlags() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the device status string. It will be displayed in the status bar of the application
|
||||||
|
*
|
||||||
|
* Emit the StatusUpdated() signal whenever the return value of this function changes
|
||||||
|
*
|
||||||
|
* @return Status string
|
||||||
|
*/
|
||||||
|
virtual QString getStatus() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a widget to edit the driver specific settings.
|
||||||
|
*
|
||||||
|
* The widget is displayed in the global settings dialog and allows the user to edit the settings
|
||||||
|
* specific to this driver. The application takes ownership of the widget after returning,
|
||||||
|
* create a new widget for every call to this function. If the driver has no specific settings
|
||||||
|
* or the settings do not need to be editable by the user, return a nullptr. In this case, no
|
||||||
|
* page for this driver is created in the settings dialog
|
||||||
|
* @return newly constructed settings widget or nullptr
|
||||||
|
*/
|
||||||
|
virtual QWidget* createSettingsWidget() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Names of available measurements.
|
||||||
|
*
|
||||||
|
* The names must be identical to the names used in the returned VNAMeasurement.
|
||||||
|
* Typically the S parameters, e.g. this function may return {"S11","S12","S21","S22"} but any other names are also allowed.
|
||||||
|
*
|
||||||
|
* @return List of available VNA measurement parameters
|
||||||
|
*/
|
||||||
|
virtual QStringList availableVNAMeasurements() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Configures the VNA and starts a sweep
|
||||||
|
* @param s VNA settings
|
||||||
|
* @param cb Callback, must be called after the VNA has been configured
|
||||||
|
* @return true if configuration successful, false otherwise
|
||||||
|
*/
|
||||||
|
virtual bool setVNA(const VNASettings &s, std::function<void(bool)> cb = nullptr) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Names of available measurements.
|
||||||
|
*
|
||||||
|
* The names must be identical to the names used in the returned SAMeasurement.
|
||||||
|
* Typically the port names, e.g. this function may return {"PORT1","PORT2"} but any other names are also allowed.
|
||||||
|
*
|
||||||
|
* @return List of available SA measurement parameters
|
||||||
|
*/
|
||||||
|
virtual QStringList availableSAMeasurements() override;
|
||||||
|
/**
|
||||||
|
* @brief Configures the SA and starts a sweep
|
||||||
|
* @param s SA settings
|
||||||
|
* @param cb Callback, must be called after the SA has been configured
|
||||||
|
* @return true if configuration successful, false otherwise
|
||||||
|
*/
|
||||||
|
virtual bool setSA(const SASettings &s, std::function<void(bool)> cb = nullptr) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the number of points in one spectrum analyzer sweep (as configured by the last setSA() call)
|
||||||
|
* @return Number of points in the sweep
|
||||||
|
*/
|
||||||
|
virtual unsigned int getSApoints() override {return SApoints;}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Names of available generator ports.
|
||||||
|
*
|
||||||
|
* Typically the port names, e.g. this function may return {"PORT1","PORT2"} but any other names are also allowed.
|
||||||
|
*
|
||||||
|
* @return List of available SA measurement parameters
|
||||||
|
*/
|
||||||
|
virtual QStringList availableSGPorts() override;
|
||||||
|
/**
|
||||||
|
* @brief Configures the generator
|
||||||
|
* @param s Generator settings
|
||||||
|
* @return true if configuration successful, false otherwise
|
||||||
|
*/
|
||||||
|
virtual bool setSG(const SGSettings &s) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the device to idle
|
||||||
|
*
|
||||||
|
* Stops all sweeps and signal generation
|
||||||
|
*
|
||||||
|
* @param cb Callback, must be called after the device has stopped all operations
|
||||||
|
* @return true if configuration successful, false otherwise
|
||||||
|
*/
|
||||||
|
virtual bool setIdle(std::function<void(bool)> cb = nullptr) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the available options for the external reference input
|
||||||
|
* @return External reference input options
|
||||||
|
*/
|
||||||
|
virtual QStringList availableExtRefInSettings() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the available options for the external reference output
|
||||||
|
* @return External reference output options
|
||||||
|
*/
|
||||||
|
virtual QStringList availableExtRefOutSettings() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Configures the external reference input/output
|
||||||
|
* @param option_in Reference input option (one of the options returned by availableExtRefInSettings())
|
||||||
|
* @param option_out Reference output option (one of the options returned by availableExtRefOutSettings())
|
||||||
|
* @return true if configuration successful, false otherwise
|
||||||
|
*/
|
||||||
|
virtual bool setExtRef(QString option_in, QString option_out) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void parseCompoundJSON();
|
||||||
|
void createCompoundJSON();
|
||||||
|
void incomingPacket(LibreVNADriver *device, const Protocol::PacketInfo &p);
|
||||||
|
void updatedInfo(LibreVNADriver *device);
|
||||||
|
void updatedStatus(LibreVNADriver *device, const Protocol::DeviceStatusV1 &status);
|
||||||
|
void datapointReceivecd(LibreVNADriver *dev, Protocol::VNADatapoint<32> *data);
|
||||||
|
void spectrumResultReceived(LibreVNADriver *dev, Protocol::SpectrumAnalyzerResult res);
|
||||||
|
|
||||||
|
Info info;
|
||||||
|
std::map<LibreVNADriver*, Info> deviceInfos;
|
||||||
|
std::map<LibreVNADriver*, Protocol::DeviceStatusV1> deviceStatus;
|
||||||
|
std::map<int, std::map<LibreVNADriver*, Protocol::VNADatapoint<32>*>> compoundVNABuffer;
|
||||||
|
std::map<int, std::map<LibreVNADriver*, Protocol::SpectrumAnalyzerResult>> compoundSABuffer;
|
||||||
|
Protocol::DeviceStatusV1 lastStatus;
|
||||||
|
|
||||||
|
// Parsed configuration of compound devices (as extracted from compoundJSONString
|
||||||
|
std::vector<CompoundDevice*> configuredDevices;
|
||||||
|
|
||||||
|
std::map<int, int> portStageMapping; // maps from excitedPort (count starts at one) to stage (count starts at zero)
|
||||||
|
|
||||||
|
// All possible drivers to interact with a LibreVNA
|
||||||
|
std::vector<LibreVNADriver*> drivers;
|
||||||
|
|
||||||
|
// Configuration of the device we are connected to
|
||||||
|
CompoundDevice activeDevice;
|
||||||
|
bool connected;
|
||||||
|
std::vector<LibreVNADriver*> devices;
|
||||||
|
bool zerospan;
|
||||||
|
unsigned int SApoints;
|
||||||
|
|
||||||
|
// Driver specific settings
|
||||||
|
bool captureRawReceiverValues;
|
||||||
|
QString compoundJSONString;
|
||||||
|
|
||||||
|
// Buffers for storing individual device answers
|
||||||
|
std::map<LibreVNADriver*, bool> results;
|
||||||
|
void checkIfAllTransmissionsComplete(std::function<void(bool)> cb = nullptr);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COMPOUNDDRIVER_H
|
@ -0,0 +1,87 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>CompoundDriverSettingsWidget</class>
|
||||||
|
<widget class="QWidget" name="CompoundDriverSettingsWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>893</width>
|
||||||
|
<height>559</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>CompoundDriverSettingsWidget</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_13">
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="compoundList"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_19">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="compoundAdd">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset theme="list-add" resource="../../../icons.qrc">
|
||||||
|
<normaloff>:/icons/add.png</normaloff>
|
||||||
|
<normalon>:/icons/add.png</normalon>:/icons/add.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="compoundDelete">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset theme="list-remove" resource="../../../icons.qrc">
|
||||||
|
<normaloff>:/icons/remove.png</normaloff>
|
||||||
|
<normalon>:/icons/remove.png</normalon>:/icons/remove.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer_8">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_25">
|
||||||
|
<property name="title">
|
||||||
|
<string>Debug - Acquisition</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_32">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="CaptureRawReceiverValues">
|
||||||
|
<property name="text">
|
||||||
|
<string>Capture raw receiver values</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources>
|
||||||
|
<include location="../../../icons.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
@ -107,6 +107,7 @@ LibreVNADriver::LibreVNADriver()
|
|||||||
connected = false;
|
connected = false;
|
||||||
skipOwnPacketHandling = false;
|
skipOwnPacketHandling = false;
|
||||||
SApoints = 0;
|
SApoints = 0;
|
||||||
|
setSynchronization(Synchronization::Disabled, false);
|
||||||
|
|
||||||
auto manual = new QAction("Manual Control");
|
auto manual = new QAction("Manual Control");
|
||||||
connect(manual, &QAction::triggered, this, [=](){
|
connect(manual, &QAction::triggered, this, [=](){
|
||||||
@ -146,17 +147,6 @@ LibreVNADriver::LibreVNADriver()
|
|||||||
d->show();
|
d->show();
|
||||||
});
|
});
|
||||||
specificActions.push_back(freqcal);
|
specificActions.push_back(freqcal);
|
||||||
|
|
||||||
specificSettings.push_back(Savable::SettingDescription(&captureRawReceiverValues, "captureRawReceiverValues", false));
|
|
||||||
specificSettings.push_back(Savable::SettingDescription(&harmonicMixing, "harmonicMixing", false));
|
|
||||||
specificSettings.push_back(Savable::SettingDescription(&SASignalID, "signalID", true));
|
|
||||||
specificSettings.push_back(Savable::SettingDescription(&VNASuppressInvalidPeaks, "suppressInvalidPeaks", true));
|
|
||||||
specificSettings.push_back(Savable::SettingDescription(&VNAAdjustPowerLevel, "adjustPowerLevel", false));
|
|
||||||
specificSettings.push_back(Savable::SettingDescription(&SAUseDFT, "useDFT", true));
|
|
||||||
specificSettings.push_back(Savable::SettingDescription(&SARBWLimitForDFT, "RBWlimitDFT", 3000));
|
|
||||||
specificSettings.push_back(Savable::SettingDescription(&IF1, "IF1", 62000000));
|
|
||||||
specificSettings.push_back(Savable::SettingDescription(&ADCprescaler, "ADCprescaler", 128));
|
|
||||||
specificSettings.push_back(Savable::SettingDescription(&DFTPhaseInc, "DFTPhaseInc", 1280));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<DeviceDriver::Flag> LibreVNADriver::getFlags()
|
std::set<DeviceDriver::Flag> LibreVNADriver::getFlags()
|
||||||
@ -232,6 +222,12 @@ QWidget *LibreVNADriver::createSettingsWidget()
|
|||||||
ui->IF1->setUnit("Hz");
|
ui->IF1->setUnit("Hz");
|
||||||
ui->IF1->setPrefixes(" kM");
|
ui->IF1->setPrefixes(" kM");
|
||||||
ui->IF1->setPrecision(5);
|
ui->IF1->setPrecision(5);
|
||||||
|
ui->ADCRate->setUnit("Hz");
|
||||||
|
ui->ADCRate->setPrefixes(" kM");
|
||||||
|
ui->ADCRate->setPrecision(5);
|
||||||
|
ui->IF2->setUnit("Hz");
|
||||||
|
ui->IF2->setPrefixes(" kM");
|
||||||
|
ui->IF2->setPrecision(5);
|
||||||
ui->IF1->setValue(IF1);
|
ui->IF1->setValue(IF1);
|
||||||
ui->ADCpresc->setValue(ADCprescaler);
|
ui->ADCpresc->setValue(ADCprescaler);
|
||||||
ui->ADCphaseInc->setValue(DFTPhaseInc);
|
ui->ADCphaseInc->setValue(DFTPhaseInc);
|
||||||
@ -333,10 +329,10 @@ bool LibreVNADriver::setVNA(const DeviceDriver::VNASettings &s, std::function<vo
|
|||||||
p.settings.logSweep = s.logSweep ? 1 : 0;
|
p.settings.logSweep = s.logSweep ? 1 : 0;
|
||||||
|
|
||||||
zerospan = (s.freqStart == s.freqStop) && (s.dBmStart == s.dBmStop);
|
zerospan = (s.freqStart == s.freqStop) && (s.dBmStart == s.dBmStop);
|
||||||
p.settings.port1Stage = find(s.excitedPorts.begin(), s.excitedPorts.end(), 0) - s.excitedPorts.begin();
|
p.settings.port1Stage = find(s.excitedPorts.begin(), s.excitedPorts.end(), 1) - s.excitedPorts.begin();
|
||||||
p.settings.port2Stage = find(s.excitedPorts.begin(), s.excitedPorts.end(), 1) - s.excitedPorts.begin();
|
p.settings.port2Stage = find(s.excitedPorts.begin(), s.excitedPorts.end(), 2) - s.excitedPorts.begin();
|
||||||
p.settings.syncMode = 0;
|
p.settings.syncMode = (int) sync;
|
||||||
p.settings.syncMaster = 0;
|
p.settings.syncMaster = syncMaster ? 1 : 0;
|
||||||
|
|
||||||
return SendPacket(p, [=](TransmissionResult r){
|
return SendPacket(p, [=](TransmissionResult r){
|
||||||
if(cb) {
|
if(cb) {
|
||||||
@ -385,12 +381,12 @@ bool LibreVNADriver::setSA(const DeviceDriver::SASettings &s, std::function<void
|
|||||||
}
|
}
|
||||||
p.spectrumSettings.applyReceiverCorrection = 1;
|
p.spectrumSettings.applyReceiverCorrection = 1;
|
||||||
p.spectrumSettings.trackingGeneratorOffset = s.trackingOffset;
|
p.spectrumSettings.trackingGeneratorOffset = s.trackingOffset;
|
||||||
p.spectrumSettings.trackingPower = s.trackingPower;
|
p.spectrumSettings.trackingPower = s.trackingPower * 100;
|
||||||
|
|
||||||
p.spectrumSettings.trackingGenerator = s.trackingGenerator ? 1 : 0;
|
p.spectrumSettings.trackingGenerator = s.trackingGenerator ? 1 : 0;
|
||||||
p.spectrumSettings.trackingGeneratorPort = s.trackingPort;
|
p.spectrumSettings.trackingGeneratorPort = s.trackingPort == 2 ? 1 : 0;
|
||||||
p.spectrumSettings.syncMode = 0;
|
p.spectrumSettings.syncMode = (int) sync;
|
||||||
p.spectrumSettings.syncMaster = 0;
|
p.spectrumSettings.syncMaster = syncMaster ? 1 : 0;
|
||||||
|
|
||||||
if(p.spectrumSettings.trackingGenerator && p.spectrumSettings.f_stop >= 25000000) {
|
if(p.spectrumSettings.trackingGenerator && p.spectrumSettings.f_stop >= 25000000) {
|
||||||
// Check point spacing.
|
// Check point spacing.
|
||||||
@ -518,6 +514,12 @@ void LibreVNADriver::registerTypes()
|
|||||||
qRegisterMetaType<TransmissionResult>();
|
qRegisterMetaType<TransmissionResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LibreVNADriver::setSynchronization(LibreVNADriver::Synchronization s, bool master)
|
||||||
|
{
|
||||||
|
sync = s;
|
||||||
|
syncMaster = master;
|
||||||
|
}
|
||||||
|
|
||||||
void LibreVNADriver::handleReceivedPacket(const Protocol::PacketInfo &packet)
|
void LibreVNADriver::handleReceivedPacket(const Protocol::PacketInfo &packet)
|
||||||
{
|
{
|
||||||
emit passOnReceivedPacket(packet);
|
emit passOnReceivedPacket(packet);
|
||||||
@ -591,20 +593,20 @@ void LibreVNADriver::handleReceivedPacket(const Protocol::PacketInfo &packet)
|
|||||||
m.dBm = (double) res->cdBm / 100;
|
m.dBm = (double) res->cdBm / 100;
|
||||||
}
|
}
|
||||||
for(auto map : portStageMapping) {
|
for(auto map : portStageMapping) {
|
||||||
// map.first is the port (starts at zero)
|
// map.first is the port (starts at one)
|
||||||
// map.second is the stage at which this port had the stimulus (starts at zero)
|
// map.second is the stage at which this port had the stimulus (starts at zero)
|
||||||
complex<double> ref = res->getValue(map.second, map.first, true);
|
complex<double> ref = res->getValue(map.second, map.first-1, true);
|
||||||
for(unsigned int i=0;i<info.Limits.VNA.ports;i++) {
|
for(unsigned int i=1;i<=info.Limits.VNA.ports;i++) {
|
||||||
complex<double> input = res->getValue(map.second, i, false);
|
complex<double> input = res->getValue(map.second, i-1, false);
|
||||||
if(!std::isnan(ref.real()) && !std::isnan(input.real())) {
|
if(!std::isnan(ref.real()) && !std::isnan(input.real())) {
|
||||||
// got both required measurements
|
// got both required measurements
|
||||||
QString name = "S"+QString::number(i+1)+QString::number(map.first+1);
|
QString name = "S"+QString::number(i)+QString::number(map.first);
|
||||||
m.measurements[name] = input / ref;
|
m.measurements[name] = input / ref;
|
||||||
}
|
}
|
||||||
if(captureRawReceiverValues) {
|
if(captureRawReceiverValues) {
|
||||||
QString name = "RawPort"+QString::number(i+1)+"Stage"+QString::number(map.first);
|
QString name = "RawPort"+QString::number(i)+"Stage"+QString::number(map.second);
|
||||||
m.measurements[name] = input;
|
m.measurements[name] = input;
|
||||||
name = "RawPort"+QString::number(i+1)+"Stage"+QString::number(map.first)+"Ref";
|
name = "RawPort"+QString::number(i)+"Stage"+QString::number(map.second)+"Ref";
|
||||||
m.measurements[name] = res->getValue(map.second, i, true);
|
m.measurements[name] = res->getValue(map.second, i, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
class LibreVNADriver : public DeviceDriver
|
class LibreVNADriver : public DeviceDriver
|
||||||
{
|
{
|
||||||
|
friend class CompoundDriver;
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
enum class TransmissionResult {
|
enum class TransmissionResult {
|
||||||
@ -161,6 +162,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual void registerTypes();
|
virtual void registerTypes();
|
||||||
|
|
||||||
|
enum class Synchronization {
|
||||||
|
Disabled = 0,
|
||||||
|
GUI = 1,
|
||||||
|
Reserved = 2,
|
||||||
|
ExternalTrigger = 3,
|
||||||
|
Last = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
void setSynchronization(Synchronization s, bool master);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
signals:
|
signals:
|
||||||
// Required for the compound device driver
|
// Required for the compound device driver
|
||||||
@ -191,7 +202,10 @@ protected:
|
|||||||
bool zerospan;
|
bool zerospan;
|
||||||
unsigned int SApoints;
|
unsigned int SApoints;
|
||||||
|
|
||||||
std::map<int, int> portStageMapping; // maps from excitedPort (count starts at zero) to stage (count starts at zero)
|
Synchronization sync;
|
||||||
|
bool syncMaster;
|
||||||
|
|
||||||
|
std::map<int, int> portStageMapping; // maps from excitedPort (count starts at one) to stage (count starts at zero)
|
||||||
|
|
||||||
// Driver specific settings
|
// Driver specific settings
|
||||||
bool captureRawReceiverValues;
|
bool captureRawReceiverValues;
|
||||||
|
@ -26,16 +26,26 @@ LibreVNATCPDriver::LibreVNATCPDriver()
|
|||||||
|
|
||||||
auto interfaces = QNetworkInterface::allInterfaces();
|
auto interfaces = QNetworkInterface::allInterfaces();
|
||||||
for(auto i : interfaces) {
|
for(auto i : interfaces) {
|
||||||
qDebug() << "Creating socket for interface" << i.name();
|
|
||||||
auto socket = new QUdpSocket();
|
auto socket = new QUdpSocket();
|
||||||
socket->bind(QHostAddress::AnyIPv4, 0, QUdpSocket::ShareAddress);
|
socket->bind(QHostAddress::AnyIPv4, 0, QUdpSocket::ShareAddress);
|
||||||
socket->setMulticastInterface(i);
|
socket->setMulticastInterface(i);
|
||||||
qDebug() << socket->joinMulticastGroup(SSDPaddress, i);
|
socket->joinMulticastGroup(SSDPaddress, i);
|
||||||
connect(socket, &QUdpSocket::readyRead, this, [=](){
|
connect(socket, &QUdpSocket::readyRead, this, [=](){
|
||||||
SSDPreceived(socket);
|
SSDPreceived(socket);
|
||||||
});
|
});
|
||||||
ssdpSockets.push_back(socket);
|
ssdpSockets.push_back(socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
specificSettings.push_back(Savable::SettingDescription(&captureRawReceiverValues, "LibreVNATCPDriver.captureRawReceiverValues", false));
|
||||||
|
specificSettings.push_back(Savable::SettingDescription(&harmonicMixing, "LibreVNATCPDriver.harmonicMixing", false));
|
||||||
|
specificSettings.push_back(Savable::SettingDescription(&SASignalID, "LibreVNATCPDriver.signalID", true));
|
||||||
|
specificSettings.push_back(Savable::SettingDescription(&VNASuppressInvalidPeaks, "LibreVNATCPDriver.suppressInvalidPeaks", true));
|
||||||
|
specificSettings.push_back(Savable::SettingDescription(&VNAAdjustPowerLevel, "LibreVNATCPDriver.adjustPowerLevel", false));
|
||||||
|
specificSettings.push_back(Savable::SettingDescription(&SAUseDFT, "LibreVNATCPDriver.useDFT", true));
|
||||||
|
specificSettings.push_back(Savable::SettingDescription(&SARBWLimitForDFT, "LibreVNATCPDriver.RBWlimitDFT", 3000));
|
||||||
|
specificSettings.push_back(Savable::SettingDescription(&IF1, "LibreVNATCPDriver.IF1", 62000000));
|
||||||
|
specificSettings.push_back(Savable::SettingDescription(&ADCprescaler, "LibreVNATCPDriver.ADCprescaler", 128));
|
||||||
|
specificSettings.push_back(Savable::SettingDescription(&DFTPhaseInc, "LibreVNATCPDriver.DFTPhaseInc", 1280));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString LibreVNATCPDriver::getDriverName()
|
QString LibreVNATCPDriver::getDriverName()
|
||||||
|
@ -126,6 +126,17 @@ LibreVNAUSBDriver::LibreVNAUSBDriver()
|
|||||||
dataBuffer = nullptr;
|
dataBuffer = nullptr;
|
||||||
logBuffer = nullptr;
|
logBuffer = nullptr;
|
||||||
m_receiveThread = nullptr;
|
m_receiveThread = nullptr;
|
||||||
|
|
||||||
|
specificSettings.push_back(Savable::SettingDescription(&captureRawReceiverValues, "LibreVNAUSBDriver.captureRawReceiverValues", false));
|
||||||
|
specificSettings.push_back(Savable::SettingDescription(&harmonicMixing, "LibreVNAUSBDriver.harmonicMixing", false));
|
||||||
|
specificSettings.push_back(Savable::SettingDescription(&SASignalID, "LibreVNAUSBDriver.signalID", true));
|
||||||
|
specificSettings.push_back(Savable::SettingDescription(&VNASuppressInvalidPeaks, "LibreVNAUSBDriver.suppressInvalidPeaks", true));
|
||||||
|
specificSettings.push_back(Savable::SettingDescription(&VNAAdjustPowerLevel, "LibreVNAUSBDriver.adjustPowerLevel", false));
|
||||||
|
specificSettings.push_back(Savable::SettingDescription(&SAUseDFT, "LibreVNAUSBDriver.useDFT", true));
|
||||||
|
specificSettings.push_back(Savable::SettingDescription(&SARBWLimitForDFT, "LibreVNAUSBDriver.RBWlimitDFT", 3000));
|
||||||
|
specificSettings.push_back(Savable::SettingDescription(&IF1, "LibreVNAUSBDriver.IF1", 62000000));
|
||||||
|
specificSettings.push_back(Savable::SettingDescription(&ADCprescaler, "LibreVNAUSBDriver.ADCprescaler", 128));
|
||||||
|
specificSettings.push_back(Savable::SettingDescription(&DFTPhaseInc, "LibreVNAUSBDriver.DFTPhaseInc", 1280));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString LibreVNAUSBDriver::getDriverName()
|
QString LibreVNAUSBDriver::getDriverName()
|
||||||
|
@ -0,0 +1,296 @@
|
|||||||
|
#include "ssa3000xdriver.h"
|
||||||
|
|
||||||
|
#include "CustomWidgets/informationbox.h"
|
||||||
|
|
||||||
|
#include <QTcpSocket>
|
||||||
|
|
||||||
|
SSA3000XDriver::SSA3000XDriver()
|
||||||
|
{
|
||||||
|
searchAddresses.push_back(QHostAddress("192.168.22.2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
SSA3000XDriver::~SSA3000XDriver()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<QString> SSA3000XDriver::GetAvailableDevices()
|
||||||
|
{
|
||||||
|
std::set<QString> ret;
|
||||||
|
|
||||||
|
// attempt to establish a connection to check if the device is available and extract the serial number
|
||||||
|
detectedDevices.clear();
|
||||||
|
auto sock = QTcpSocket();
|
||||||
|
for(auto address : searchAddresses) {
|
||||||
|
sock.connectToHost(address, 5024);
|
||||||
|
if(sock.waitForConnected(50)) {
|
||||||
|
// connection successful
|
||||||
|
sock.waitForReadyRead(100);
|
||||||
|
auto line = QString(sock.readLine());
|
||||||
|
if(line.startsWith("Welcome to the SCPI instrument 'Siglent SSA3")) {
|
||||||
|
// throw away command prompt ">>"
|
||||||
|
sock.readLine();
|
||||||
|
// looks like we are connected to the correct instrument, request serial number
|
||||||
|
sock.write("*IDN?\r\n");
|
||||||
|
sock.waitForReadyRead(100);
|
||||||
|
sock.read(1);
|
||||||
|
sock.waitForReadyRead(100);
|
||||||
|
line = QString(sock.readLine());
|
||||||
|
auto fields = line.split(",");
|
||||||
|
if(fields.size() == 4) {
|
||||||
|
detectedDevices[fields[2]] = address;
|
||||||
|
ret.insert(fields[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sock.disconnect();
|
||||||
|
} else {
|
||||||
|
qDebug() << "SSA3000X failed to connect";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SSA3000XDriver::connectTo(QString serial)
|
||||||
|
{
|
||||||
|
if(connected) {
|
||||||
|
disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if this device is actually available
|
||||||
|
QHostAddress address;
|
||||||
|
bool available = false;
|
||||||
|
for(auto d : detectedDevices) {
|
||||||
|
if(d.first == serial) {
|
||||||
|
address = d.second;
|
||||||
|
available = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!available) {
|
||||||
|
// no location information about this device available
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
dataSocket.connectToHost(address, 5025);
|
||||||
|
|
||||||
|
// check if connection succeeds
|
||||||
|
if(!dataSocket.waitForConnected(1000)) {
|
||||||
|
// socket failed
|
||||||
|
dataSocket.close();
|
||||||
|
InformationBox::ShowError("Error", "TCP connection timed out");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// grab model information
|
||||||
|
dataSocket.write("*IDN?\r\n");
|
||||||
|
dataSocket.waitForReadyRead(100);
|
||||||
|
auto line = QString(dataSocket.readLine());
|
||||||
|
auto fields = line.split(",");
|
||||||
|
if(fields.size() != 4) {
|
||||||
|
dataSocket.close();
|
||||||
|
InformationBox::ShowError("Error", "Invalid *IDN? response");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->serial = fields[2];
|
||||||
|
|
||||||
|
info = Info();
|
||||||
|
info.hardware_version = fields[1];
|
||||||
|
info.firmware_version = fields[3].trimmed();
|
||||||
|
info.supportedFeatures.insert(DeviceDriver::Feature::SA);
|
||||||
|
info.supportedFeatures.insert(DeviceDriver::Feature::SATrackingGenerator);
|
||||||
|
info.supportedFeatures.insert(DeviceDriver::Feature::Generator);
|
||||||
|
info.supportedFeatures.insert(DeviceDriver::Feature::ExtRefIn);
|
||||||
|
|
||||||
|
double maxFreq = 0;
|
||||||
|
if(info.hardware_version == "SSA3032X") {
|
||||||
|
maxFreq = 3200000000;
|
||||||
|
} else if(info.hardware_version == "SSA3021X") {
|
||||||
|
maxFreq = 2100000000;
|
||||||
|
} else {
|
||||||
|
dataSocket.close();
|
||||||
|
InformationBox::ShowError("Error", "Invalid hardware version: " + info.hardware_version);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
info.Limits.SA.ports = 1;
|
||||||
|
info.Limits.SA.minFreq = 0;
|
||||||
|
info.Limits.SA.maxFreq = maxFreq;
|
||||||
|
info.Limits.SA.minRBW = 1;
|
||||||
|
info.Limits.SA.maxRBW = 1000000;
|
||||||
|
info.Limits.SA.mindBm = -20;
|
||||||
|
info.Limits.SA.maxdBm = 0;
|
||||||
|
info.Limits.Generator.ports = 1;
|
||||||
|
info.Limits.Generator.minFreq = 0;
|
||||||
|
info.Limits.Generator.maxFreq = maxFreq;
|
||||||
|
info.Limits.Generator.mindBm = -20;
|
||||||
|
info.Limits.Generator.maxdBm = 0;
|
||||||
|
|
||||||
|
connected = true;
|
||||||
|
|
||||||
|
// reset to default configuration
|
||||||
|
dataSocket.write("*RST\r\n");
|
||||||
|
|
||||||
|
emit InfoUpdated();
|
||||||
|
|
||||||
|
// // sockets are connected now
|
||||||
|
// dataBuffer.clear();
|
||||||
|
// logBuffer.clear();
|
||||||
|
// connect(&dataSocket, qOverload<QAbstractSocket::SocketError>(&QTcpSocket::error), this, &LibreVNATCPDriver::ConnectionLost, Qt::QueuedConnection);
|
||||||
|
// connect(&logSocket, qOverload<QAbstractSocket::SocketError>(&QTcpSocket::error), this, &LibreVNATCPDriver::ConnectionLost, Qt::QueuedConnection);
|
||||||
|
|
||||||
|
// qInfo() << "TCP connection established" << flush;
|
||||||
|
// this->serial = serial;
|
||||||
|
// connected = true;
|
||||||
|
|
||||||
|
// connect(&dataSocket, &QTcpSocket::readyRead, this, &LibreVNATCPDriver::ReceivedData, Qt::UniqueConnection);
|
||||||
|
// connect(&logSocket, &QTcpSocket::readyRead, this, &LibreVNATCPDriver::ReceivedLog, Qt::UniqueConnection);
|
||||||
|
// connect(&transmissionTimer, &QTimer::timeout, this, &LibreVNATCPDriver::transmissionTimeout, Qt::UniqueConnection);
|
||||||
|
// connect(this, &LibreVNATCPDriver::receivedAnswer, this, &LibreVNATCPDriver::transmissionFinished, static_cast<Qt::ConnectionType>(Qt::QueuedConnection | Qt::UniqueConnection));
|
||||||
|
// connect(this, &LibreVNATCPDriver::receivedPacket, this, &LibreVNATCPDriver::handleReceivedPacket, static_cast<Qt::ConnectionType>(Qt::QueuedConnection | Qt::UniqueConnection));
|
||||||
|
// transmissionTimer.setSingleShot(true);
|
||||||
|
// transmissionActive = false;
|
||||||
|
|
||||||
|
// sendWithoutPayload(Protocol::PacketType::RequestDeviceInfo);
|
||||||
|
// sendWithoutPayload(Protocol::PacketType::RequestDeviceStatus);
|
||||||
|
// updateIFFrequencies();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSA3000XDriver::disconnect()
|
||||||
|
{
|
||||||
|
dataSocket.close();
|
||||||
|
connected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceDriver::Info SSA3000XDriver::getInfo()
|
||||||
|
{
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<DeviceDriver::Flag> SSA3000XDriver::getFlags()
|
||||||
|
{
|
||||||
|
return std::set<DeviceDriver::Flag>();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SSA3000XDriver::getStatus()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList SSA3000XDriver::availableSAMeasurements()
|
||||||
|
{
|
||||||
|
return {"PORT1"};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SSA3000XDriver::setSA(const DeviceDriver::SASettings &s, std::function<void (bool)> cb)
|
||||||
|
{
|
||||||
|
if(!connected) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write(":FREQ:STAR "+QString::number(s.freqStart));
|
||||||
|
write(":FREQ:STOP "+QString::number(s.freqStop));
|
||||||
|
write(":BWID "+QString::number(s.RBW));
|
||||||
|
write(":FREQ:STAR "+QString::number(s.freqStart));
|
||||||
|
write(":FREQ:STAR "+QString::number(s.freqStart));
|
||||||
|
write(":FREQ:STAR "+QString::number(s.freqStart));
|
||||||
|
|
||||||
|
QString windowName = "";
|
||||||
|
switch(s.window) {
|
||||||
|
case SASettings::Window::FlatTop:
|
||||||
|
windowName = "FLATtop";
|
||||||
|
break;
|
||||||
|
case SASettings::Window::Hann:
|
||||||
|
windowName = "HANNing";
|
||||||
|
break;
|
||||||
|
case SASettings::Window::Kaiser:
|
||||||
|
windowName = "HAMMing"; // kaiser is not available
|
||||||
|
break;
|
||||||
|
case SASettings::Window::None:
|
||||||
|
windowName = "RECTangular";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
write(":DDEM:FFT:WIND "+windowName);
|
||||||
|
|
||||||
|
QString detName = "";
|
||||||
|
switch(s.detector) {
|
||||||
|
case SASettings::Detector::Average:
|
||||||
|
detName = "AVERage";
|
||||||
|
break;
|
||||||
|
case SASettings::Detector::Normal:
|
||||||
|
detName = "NORMAL";
|
||||||
|
break;
|
||||||
|
case SASettings::Detector::NPeak:
|
||||||
|
detName = "NEGative";
|
||||||
|
break;
|
||||||
|
case SASettings::Detector::PPeak:
|
||||||
|
detName = "POSitive";
|
||||||
|
break;
|
||||||
|
case SASettings::Detector::Sample:
|
||||||
|
detName = "SAMPle";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
write(":DET:TRAC:FUNC "+detName);
|
||||||
|
|
||||||
|
write(":OUTP:STAT " + (s.trackingGenerator ? QString("ON") : QString("OFF")));
|
||||||
|
write(":SOUR:POW "+QString::number((int) s.trackingPower));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int SSA3000XDriver::getSApoints()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList SSA3000XDriver::availableSGPorts()
|
||||||
|
{
|
||||||
|
return {"PORT1"};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SSA3000XDriver::setSG(const DeviceDriver::SGSettings &s)
|
||||||
|
{
|
||||||
|
if(!connected) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(s.port == 1) {
|
||||||
|
write(":FREQ:SPAN:ZERO");
|
||||||
|
write(":FREQ:CENT "+QString::number(s.freq));
|
||||||
|
write(":OUTP:STAT ON");
|
||||||
|
write(":SOUR:POW "+QString::number((int) s.dBm));
|
||||||
|
} else {
|
||||||
|
write(":OUTP:STAT OFF");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SSA3000XDriver::setIdle(std::function<void (bool)> cb)
|
||||||
|
{
|
||||||
|
if(!connected) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
write("*RST\r\n");
|
||||||
|
if(cb) {
|
||||||
|
cb(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList SSA3000XDriver::availableExtRefInSettings()
|
||||||
|
{
|
||||||
|
return {""};
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList SSA3000XDriver::availableExtRefOutSettings()
|
||||||
|
{
|
||||||
|
return {""};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SSA3000XDriver::setExtRef(QString option_in, QString option_out)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSA3000XDriver::write(QString s)
|
||||||
|
{
|
||||||
|
dataSocket.write(QString(s + "\r\n").toLocal8Bit());
|
||||||
|
}
|
@ -0,0 +1,154 @@
|
|||||||
|
#ifndef SSA3000XDRIVER_H
|
||||||
|
#define SSA3000XDRIVER_H
|
||||||
|
|
||||||
|
#include "../devicedriver.h"
|
||||||
|
|
||||||
|
#include <QHostAddress>
|
||||||
|
#include <QTcpSocket>
|
||||||
|
|
||||||
|
class SSA3000XDriver : public DeviceDriver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SSA3000XDriver();
|
||||||
|
virtual ~SSA3000XDriver();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the driver name. It must be unique across all implemented drivers and is used to identify the driver
|
||||||
|
* @return driver name
|
||||||
|
*/
|
||||||
|
virtual QString getDriverName() override {return "SSA3000X";}
|
||||||
|
/**
|
||||||
|
* @brief Lists all available devices by their serial numbers
|
||||||
|
* @return Serial numbers of detected devices
|
||||||
|
*/
|
||||||
|
virtual std::set<QString> GetAvailableDevices() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* @brief Connects to a device, given by its serial number
|
||||||
|
*
|
||||||
|
* @param serial Serial number of device that should be connected to
|
||||||
|
* @return true if connection successful, otherwise false
|
||||||
|
*/
|
||||||
|
virtual bool connectTo(QString serial) override;
|
||||||
|
/**
|
||||||
|
* @brief Disconnects from device. Has no effect if no device was connected
|
||||||
|
*/
|
||||||
|
virtual void disconnect() override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Returns the serial number of the connected device
|
||||||
|
* @return Serial number of connected device (empty string if no device is connected)
|
||||||
|
*/
|
||||||
|
virtual QString getSerial() override {return serial;}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the device information. This function will be called when a device has been connected. Its return value must be valid
|
||||||
|
* directly after returning from DeviceDriver::connectTo()
|
||||||
|
*
|
||||||
|
* Emit the InfoUpdate() signal whenever the return value of this function changes.
|
||||||
|
*
|
||||||
|
* @return Device information
|
||||||
|
*/
|
||||||
|
virtual Info getInfo() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a set of all active flags
|
||||||
|
*
|
||||||
|
* There is also a convenience function to check a specific flag, see DeviceDriver::asserted()
|
||||||
|
*
|
||||||
|
* @return Set of active flags
|
||||||
|
*/
|
||||||
|
virtual std::set<Flag> getFlags() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the device status string. It will be displayed in the status bar of the application
|
||||||
|
*
|
||||||
|
* Emit the StatusUpdated() signal whenever the return value of this function changes
|
||||||
|
*
|
||||||
|
* @return Status string
|
||||||
|
*/
|
||||||
|
virtual QString getStatus() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Names of available measurements.
|
||||||
|
*
|
||||||
|
* The names must be identical to the names used in the returned SAMeasurement.
|
||||||
|
* Typically the port names, e.g. this function may return {"PORT1","PORT2"} but any other names are also allowed.
|
||||||
|
*
|
||||||
|
* @return List of available SA measurement parameters
|
||||||
|
*/
|
||||||
|
virtual QStringList availableSAMeasurements() override;
|
||||||
|
/**
|
||||||
|
* @brief Configures the SA and starts a sweep
|
||||||
|
* @param s SA settings
|
||||||
|
* @param cb Callback, must be called after the SA has been configured
|
||||||
|
* @return true if configuration successful, false otherwise
|
||||||
|
*/
|
||||||
|
virtual bool setSA(const SASettings &s, std::function<void(bool)> cb = nullptr) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the number of points in one spectrum analyzer sweep (as configured by the last setSA() call)
|
||||||
|
* @return Number of points in the sweep
|
||||||
|
*/
|
||||||
|
virtual unsigned int getSApoints() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Names of available generator ports.
|
||||||
|
*
|
||||||
|
* Typically the port names, e.g. this function may return {"PORT1","PORT2"} but any other names are also allowed.
|
||||||
|
*
|
||||||
|
* @return List of available SA measurement parameters
|
||||||
|
*/
|
||||||
|
virtual QStringList availableSGPorts() override;
|
||||||
|
/**
|
||||||
|
* @brief Configures the generator
|
||||||
|
* @param s Generator settings
|
||||||
|
* @return true if configuration successful, false otherwise
|
||||||
|
*/
|
||||||
|
virtual bool setSG(const SGSettings &s) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the device to idle
|
||||||
|
*
|
||||||
|
* Stops all sweeps and signal generation
|
||||||
|
*
|
||||||
|
* @param cb Callback, must be called after the device has stopped all operations
|
||||||
|
* @return true if configuration successful, false otherwise
|
||||||
|
*/
|
||||||
|
virtual bool setIdle(std::function<void(bool)> cb = nullptr) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the available options for the external reference input
|
||||||
|
* @return External reference input options
|
||||||
|
*/
|
||||||
|
virtual QStringList availableExtRefInSettings() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the available options for the external reference output
|
||||||
|
* @return External reference output options
|
||||||
|
*/
|
||||||
|
virtual QStringList availableExtRefOutSettings() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Configures the external reference input/output
|
||||||
|
* @param option_in Reference input option (one of the options returned by availableExtRefInSettings())
|
||||||
|
* @param option_out Reference output option (one of the options returned by availableExtRefOutSettings())
|
||||||
|
* @return true if configuration successful, false otherwise
|
||||||
|
*/
|
||||||
|
virtual bool setExtRef(QString option_in, QString option_out) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void write(QString s);
|
||||||
|
QString serial;
|
||||||
|
QTcpSocket dataSocket;
|
||||||
|
|
||||||
|
bool connected;
|
||||||
|
Info info;
|
||||||
|
|
||||||
|
std::vector<QHostAddress> searchAddresses;
|
||||||
|
std::map<QString, QHostAddress> detectedDevices;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SSA3000XDRIVER_H
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "LibreVNA/librevnatcpdriver.h"
|
#include "LibreVNA/librevnatcpdriver.h"
|
||||||
#include "LibreVNA/librevnausbdriver.h"
|
#include "LibreVNA/librevnausbdriver.h"
|
||||||
|
#include "LibreVNA/Compound/compounddriver.h"
|
||||||
|
#include "SSA3000X/ssa3000xdriver.h"
|
||||||
|
|
||||||
DeviceDriver *DeviceDriver::activeDriver = nullptr;
|
DeviceDriver *DeviceDriver::activeDriver = nullptr;
|
||||||
|
|
||||||
@ -19,17 +21,23 @@ std::vector<DeviceDriver *> DeviceDriver::getDrivers()
|
|||||||
// first function call
|
// first function call
|
||||||
ret.push_back(new LibreVNAUSBDriver);
|
ret.push_back(new LibreVNAUSBDriver);
|
||||||
ret.push_back(new LibreVNATCPDriver);
|
ret.push_back(new LibreVNATCPDriver);
|
||||||
|
ret.push_back(new CompoundDriver);
|
||||||
|
ret.push_back(new SSA3000XDriver);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeviceDriver::connectDevice(QString serial)
|
bool DeviceDriver::connectDevice(QString serial, bool isIndepedentDriver)
|
||||||
{
|
{
|
||||||
if(activeDriver && activeDriver != this) {
|
if(!isIndepedentDriver) {
|
||||||
activeDriver->disconnect();
|
if(activeDriver && activeDriver != this) {
|
||||||
|
activeDriver->disconnect();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(connectTo(serial)) {
|
if(connectTo(serial)) {
|
||||||
activeDriver = this;
|
if(!isIndepedentDriver) {
|
||||||
|
activeDriver = this;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@ -123,3 +131,41 @@ DeviceDriver::Info::Info()
|
|||||||
Limits.SA.minRBW = 1;
|
Limits.SA.minRBW = 1;
|
||||||
Limits.SA.maxRBW = 1000000;
|
Limits.SA.maxRBW = 1000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeviceDriver::Info::subset(const DeviceDriver::Info &info)
|
||||||
|
{
|
||||||
|
if (info.firmware_version != firmware_version) {
|
||||||
|
firmware_version = "Mixed";
|
||||||
|
}
|
||||||
|
if (info.hardware_version != hardware_version) {
|
||||||
|
hardware_version = "Mixed";
|
||||||
|
}
|
||||||
|
|
||||||
|
Limits.VNA.ports += info.Limits.VNA.ports;
|
||||||
|
Limits.VNA.minFreq = std::max(Limits.VNA.minFreq, info.Limits.VNA.minFreq);
|
||||||
|
Limits.VNA.maxFreq = std::min(Limits.VNA.maxFreq, info.Limits.VNA.maxFreq);
|
||||||
|
Limits.VNA.mindBm = std::max(Limits.VNA.mindBm, info.Limits.VNA.mindBm);
|
||||||
|
Limits.VNA.maxdBm = std::min(Limits.VNA.maxdBm, info.Limits.VNA.maxdBm);
|
||||||
|
Limits.VNA.minIFBW = std::max(Limits.VNA.minIFBW, info.Limits.VNA.minIFBW);
|
||||||
|
Limits.VNA.maxIFBW = std::min(Limits.VNA.maxIFBW, info.Limits.VNA.maxIFBW);
|
||||||
|
Limits.VNA.maxPoints = std::min(Limits.VNA.maxPoints, info.Limits.VNA.maxPoints);
|
||||||
|
|
||||||
|
Limits.Generator.ports += info.Limits.Generator.ports;
|
||||||
|
Limits.Generator.minFreq = std::max(Limits.Generator.minFreq, info.Limits.Generator.minFreq);
|
||||||
|
Limits.Generator.maxFreq = std::min(Limits.Generator.maxFreq, info.Limits.Generator.maxFreq);
|
||||||
|
Limits.Generator.mindBm = std::max(Limits.Generator.mindBm, info.Limits.Generator.mindBm);
|
||||||
|
Limits.Generator.maxdBm = std::min(Limits.Generator.maxdBm, info.Limits.Generator.maxdBm);
|
||||||
|
|
||||||
|
Limits.SA.ports += info.Limits.SA.ports;
|
||||||
|
Limits.SA.minFreq = std::max(Limits.SA.minFreq, info.Limits.SA.minFreq);
|
||||||
|
Limits.SA.maxFreq = std::min(Limits.SA.maxFreq, info.Limits.SA.maxFreq);
|
||||||
|
Limits.SA.mindBm = std::max(Limits.SA.mindBm, info.Limits.SA.mindBm);
|
||||||
|
Limits.SA.maxdBm = std::min(Limits.SA.maxdBm, info.Limits.SA.maxdBm);
|
||||||
|
Limits.SA.minRBW = std::max(Limits.SA.minRBW, info.Limits.SA.minRBW);
|
||||||
|
Limits.SA.maxRBW = std::min(Limits.SA.maxRBW, info.Limits.SA.maxRBW);
|
||||||
|
|
||||||
|
std::set<Feature> intersectFeatures;
|
||||||
|
std::set_intersection(supportedFeatures.begin(), supportedFeatures.end(), info.supportedFeatures.begin(), info.supportedFeatures.end(),
|
||||||
|
std::inserter(intersectFeatures, intersectFeatures.begin()));
|
||||||
|
supportedFeatures = intersectFeatures;
|
||||||
|
}
|
||||||
|
@ -51,7 +51,7 @@ protected:
|
|||||||
* @param serial Serial number of device that should be connected to
|
* @param serial Serial number of device that should be connected to
|
||||||
* @return true if connection successful, otherwise false
|
* @return true if connection successful, otherwise false
|
||||||
*/
|
*/
|
||||||
virtual bool connectTo(QString getSerial) = 0;
|
virtual bool connectTo(QString serial) = 0;
|
||||||
/**
|
/**
|
||||||
* @brief Disconnects from device. Has no effect if no device was connected
|
* @brief Disconnects from device. Has no effect if no device was connected
|
||||||
*/
|
*/
|
||||||
@ -120,6 +120,7 @@ public:
|
|||||||
double mindBm, maxdBm;
|
double mindBm, maxdBm;
|
||||||
} SA;
|
} SA;
|
||||||
} Limits;
|
} Limits;
|
||||||
|
void subset(const Info &info);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -486,7 +487,7 @@ signals:
|
|||||||
void releaseControl();
|
void releaseControl();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool connectDevice(QString serial);
|
bool connectDevice(QString serial, bool isIndepedentDriver = false);
|
||||||
void disconnectDevice();
|
void disconnectDevice();
|
||||||
static DeviceDriver* getActiveDriver() {return activeDriver;}
|
static DeviceDriver* getActiveDriver() {return activeDriver;}
|
||||||
static unsigned int SApoints();
|
static unsigned int SApoints();
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "generator.h"
|
#include "generator.h"
|
||||||
|
|
||||||
|
#include "CustomWidgets/informationbox.h"
|
||||||
|
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
|
||||||
Generator::Generator(AppWindow *window, QString name)
|
Generator::Generator(AppWindow *window, QString name)
|
||||||
@ -37,6 +39,10 @@ void Generator::deactivate()
|
|||||||
|
|
||||||
void Generator::initializeDevice()
|
void Generator::initializeDevice()
|
||||||
{
|
{
|
||||||
|
if(!window->getDevice()->supports(DeviceDriver::Feature::Generator)) {
|
||||||
|
InformationBox::ShowError("Unsupported", "The connected device does not support generator mode");
|
||||||
|
return;
|
||||||
|
}
|
||||||
updateDevice();
|
updateDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,9 @@ HEADERS += \
|
|||||||
CustomWidgets/toggleswitch.h \
|
CustomWidgets/toggleswitch.h \
|
||||||
CustomWidgets/touchstoneimport.h \
|
CustomWidgets/touchstoneimport.h \
|
||||||
CustomWidgets/tracesetselector.h \
|
CustomWidgets/tracesetselector.h \
|
||||||
|
Device/LibreVNA/Compound/compounddevice.h \
|
||||||
|
Device/LibreVNA/Compound/compounddeviceeditdialog.h \
|
||||||
|
Device/LibreVNA/Compound/compounddriver.h \
|
||||||
Device/LibreVNA/amplitudecaldialog.h \
|
Device/LibreVNA/amplitudecaldialog.h \
|
||||||
Device/LibreVNA/firmwareupdatedialog.h \
|
Device/LibreVNA/firmwareupdatedialog.h \
|
||||||
Device/LibreVNA/frequencycaldialog.h \
|
Device/LibreVNA/frequencycaldialog.h \
|
||||||
@ -28,8 +31,7 @@ HEADERS += \
|
|||||||
Device/LibreVNA/manualcontroldialog.h \
|
Device/LibreVNA/manualcontroldialog.h \
|
||||||
Device/LibreVNA/receivercaldialog.h \
|
Device/LibreVNA/receivercaldialog.h \
|
||||||
Device/LibreVNA/sourcecaldialog.h \
|
Device/LibreVNA/sourcecaldialog.h \
|
||||||
Device/compounddevice.h \
|
Device/SSA3000X/ssa3000xdriver.h \
|
||||||
Device/compounddeviceeditdialog.h \
|
|
||||||
Device/device.h \
|
Device/device.h \
|
||||||
Device/devicedriver.h \
|
Device/devicedriver.h \
|
||||||
Device/devicelog.h \
|
Device/devicelog.h \
|
||||||
@ -171,6 +173,9 @@ SOURCES += \
|
|||||||
CustomWidgets/toggleswitch.cpp \
|
CustomWidgets/toggleswitch.cpp \
|
||||||
CustomWidgets/touchstoneimport.cpp \
|
CustomWidgets/touchstoneimport.cpp \
|
||||||
CustomWidgets/tracesetselector.cpp \
|
CustomWidgets/tracesetselector.cpp \
|
||||||
|
Device/LibreVNA/Compound/compounddevice.cpp \
|
||||||
|
Device/LibreVNA/Compound/compounddeviceeditdialog.cpp \
|
||||||
|
Device/LibreVNA/Compound/compounddriver.cpp \
|
||||||
Device/LibreVNA/amplitudecaldialog.cpp \
|
Device/LibreVNA/amplitudecaldialog.cpp \
|
||||||
Device/LibreVNA/firmwareupdatedialog.cpp \
|
Device/LibreVNA/firmwareupdatedialog.cpp \
|
||||||
Device/LibreVNA/frequencycaldialog.cpp \
|
Device/LibreVNA/frequencycaldialog.cpp \
|
||||||
@ -180,8 +185,7 @@ SOURCES += \
|
|||||||
Device/LibreVNA/manualcontroldialog.cpp \
|
Device/LibreVNA/manualcontroldialog.cpp \
|
||||||
Device/LibreVNA/receivercaldialog.cpp \
|
Device/LibreVNA/receivercaldialog.cpp \
|
||||||
Device/LibreVNA/sourcecaldialog.cpp \
|
Device/LibreVNA/sourcecaldialog.cpp \
|
||||||
Device/compounddevice.cpp \
|
Device/SSA3000X/ssa3000xdriver.cpp \
|
||||||
Device/compounddeviceeditdialog.cpp \
|
|
||||||
Device/device.cpp \
|
Device/device.cpp \
|
||||||
Device/devicedriver.cpp \
|
Device/devicedriver.cpp \
|
||||||
Device/devicelog.cpp \
|
Device/devicelog.cpp \
|
||||||
@ -313,6 +317,8 @@ FORMS += \
|
|||||||
CustomWidgets/jsonpickerdialog.ui \
|
CustomWidgets/jsonpickerdialog.ui \
|
||||||
CustomWidgets/tilewidget.ui \
|
CustomWidgets/tilewidget.ui \
|
||||||
CustomWidgets/touchstoneimport.ui \
|
CustomWidgets/touchstoneimport.ui \
|
||||||
|
Device/LibreVNA/Compound/compounddeviceeditdialog.ui \
|
||||||
|
Device/LibreVNA/Compound/compounddriversettingswidget.ui \
|
||||||
Device/LibreVNA/addamplitudepointsdialog.ui \
|
Device/LibreVNA/addamplitudepointsdialog.ui \
|
||||||
Device/LibreVNA/amplitudecaldialog.ui \
|
Device/LibreVNA/amplitudecaldialog.ui \
|
||||||
Device/LibreVNA/automaticamplitudedialog.ui \
|
Device/LibreVNA/automaticamplitudedialog.ui \
|
||||||
@ -320,7 +326,6 @@ FORMS += \
|
|||||||
Device/LibreVNA/frequencycaldialog.ui \
|
Device/LibreVNA/frequencycaldialog.ui \
|
||||||
Device/LibreVNA/librevnadriversettingswidget.ui \
|
Device/LibreVNA/librevnadriversettingswidget.ui \
|
||||||
Device/LibreVNA/manualcontroldialog.ui \
|
Device/LibreVNA/manualcontroldialog.ui \
|
||||||
Device/compounddeviceeditdialog.ui \
|
|
||||||
Device/devicelog.ui \
|
Device/devicelog.ui \
|
||||||
Device/deviceusblogview.ui \
|
Device/deviceusblogview.ui \
|
||||||
Generator/signalgenwidget.ui \
|
Generator/signalgenwidget.ui \
|
||||||
|
@ -173,7 +173,7 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name)
|
|||||||
// Acquisition toolbar
|
// Acquisition toolbar
|
||||||
auto tb_acq = new QToolBar("Acquisition");
|
auto tb_acq = new QToolBar("Acquisition");
|
||||||
|
|
||||||
auto eBandwidth = new SIUnitEdit("Hz", " k", 3);
|
auto eBandwidth = new SIUnitEdit("Hz", " kM", 3);
|
||||||
eBandwidth->setFixedWidth(70);
|
eBandwidth->setFixedWidth(70);
|
||||||
eBandwidth->setToolTip("RBW");
|
eBandwidth->setToolTip("RBW");
|
||||||
connect(eBandwidth, &SIUnitEdit::valueChanged, this, &SpectrumAnalyzer::SetRBW);
|
connect(eBandwidth, &SIUnitEdit::valueChanged, this, &SpectrumAnalyzer::SetRBW);
|
||||||
@ -221,7 +221,7 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name)
|
|||||||
toolbars.insert(tb_acq);
|
toolbars.insert(tb_acq);
|
||||||
|
|
||||||
// Tracking generator toolbar
|
// Tracking generator toolbar
|
||||||
auto tb_trackgen = new QToolBar("Tracking Generator");
|
tb_trackgen = new QToolBar("Tracking Generator");
|
||||||
auto cbTrackGenEnable = new QCheckBox("Tracking Generator");
|
auto cbTrackGenEnable = new QCheckBox("Tracking Generator");
|
||||||
connect(cbTrackGenEnable, &QCheckBox::toggled, this, &SpectrumAnalyzer::SetTGEnabled);
|
connect(cbTrackGenEnable, &QCheckBox::toggled, this, &SpectrumAnalyzer::SetTGEnabled);
|
||||||
connect(this, &SpectrumAnalyzer::TGStateChanged, cbTrackGenEnable, &QCheckBox::setChecked);
|
connect(this, &SpectrumAnalyzer::TGStateChanged, cbTrackGenEnable, &QCheckBox::setChecked);
|
||||||
@ -231,8 +231,12 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name)
|
|||||||
cbTrackGenPort->addItem("Port 1");
|
cbTrackGenPort->addItem("Port 1");
|
||||||
cbTrackGenPort->addItem("Port 2");
|
cbTrackGenPort->addItem("Port 2");
|
||||||
cbTrackGenPort->setCurrentIndex(0);
|
cbTrackGenPort->setCurrentIndex(0);
|
||||||
connect(cbTrackGenPort, qOverload<int>(&QComboBox::currentIndexChanged), this, &SpectrumAnalyzer::SetTGPort);
|
connect(cbTrackGenPort, qOverload<int>(&QComboBox::currentIndexChanged), this, [=](int index) {
|
||||||
connect(this, &SpectrumAnalyzer::TGPortChanged, cbTrackGenPort, qOverload<int>(&QComboBox::setCurrentIndex));
|
SetTGPort(index + 1);
|
||||||
|
});
|
||||||
|
connect(this, &SpectrumAnalyzer::TGPortChanged, this, [=](int port) {
|
||||||
|
cbTrackGenPort->setCurrentIndex(port - 1);
|
||||||
|
});
|
||||||
tb_trackgen->addWidget(cbTrackGenPort);
|
tb_trackgen->addWidget(cbTrackGenPort);
|
||||||
|
|
||||||
auto dbm = new QDoubleSpinBox();
|
auto dbm = new QDoubleSpinBox();
|
||||||
@ -247,7 +251,7 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name)
|
|||||||
tb_trackgen->addWidget(new QLabel("Level:"));
|
tb_trackgen->addWidget(new QLabel("Level:"));
|
||||||
tb_trackgen->addWidget(dbm);
|
tb_trackgen->addWidget(dbm);
|
||||||
|
|
||||||
auto tgOffset = new SIUnitEdit("Hz", " kMG", 6);
|
tgOffset = new SIUnitEdit("Hz", " kMG", 6);
|
||||||
tgOffset->setFixedWidth(width);
|
tgOffset->setFixedWidth(width);
|
||||||
tgOffset->setToolTip("Tracking generator offset");
|
tgOffset->setToolTip("Tracking generator offset");
|
||||||
connect(tgOffset, &SIUnitEdit::valueChanged, this, &SpectrumAnalyzer::SetTGOffset);
|
connect(tgOffset, &SIUnitEdit::valueChanged, this, &SpectrumAnalyzer::SetTGOffset);
|
||||||
@ -330,6 +334,20 @@ void SpectrumAnalyzer::deactivate()
|
|||||||
|
|
||||||
void SpectrumAnalyzer::initializeDevice()
|
void SpectrumAnalyzer::initializeDevice()
|
||||||
{
|
{
|
||||||
|
if(!window->getDevice()->supports(DeviceDriver::Feature::SA)) {
|
||||||
|
InformationBox::ShowError("Unsupported", "The connected device does not support spectrum analyzer mode");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bool hasTG = window->getDevice()->supports(DeviceDriver::Feature::SATrackingGenerator);
|
||||||
|
bool hasTGoffset = window->getDevice()->supports(DeviceDriver::Feature::SATrackingOffset);
|
||||||
|
tb_trackgen->setEnabled(hasTG);
|
||||||
|
if(hasTG) {
|
||||||
|
SetTGEnabled(settings.trackingGenerator);
|
||||||
|
if(!hasTGoffset) {
|
||||||
|
tgOffset->setValue(0);
|
||||||
|
tgOffset->setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
connect(window->getDevice(), &DeviceDriver::SAmeasurementReceived, this, &SpectrumAnalyzer::NewDatapoint, Qt::UniqueConnection);
|
connect(window->getDevice(), &DeviceDriver::SAmeasurementReceived, this, &SpectrumAnalyzer::NewDatapoint, Qt::UniqueConnection);
|
||||||
|
|
||||||
// Configure initial state of device
|
// Configure initial state of device
|
||||||
@ -358,9 +376,9 @@ nlohmann::json SpectrumAnalyzer::toJSON()
|
|||||||
sweep["acquisition"] = acq;
|
sweep["acquisition"] = acq;
|
||||||
nlohmann::json tracking;
|
nlohmann::json tracking;
|
||||||
tracking["enabled"] = settings.trackingGenerator ? true : false;
|
tracking["enabled"] = settings.trackingGenerator ? true : false;
|
||||||
tracking["port"] = settings.trackingPort ? 2 : 1;
|
tracking["port"] = settings.trackingPort;
|
||||||
tracking["offset"] = settings.trackingOffset;
|
tracking["offset"] = settings.trackingOffset;
|
||||||
tracking["power"] = (double) settings.trackingPower / 100.0; // convert to dBm
|
tracking["power"] = settings.trackingPower;
|
||||||
sweep["trackingGenerator"] = tracking;
|
sweep["trackingGenerator"] = tracking;
|
||||||
|
|
||||||
if(normalize.active) {
|
if(normalize.active) {
|
||||||
@ -426,8 +444,7 @@ void SpectrumAnalyzer::fromJSON(nlohmann::json j)
|
|||||||
auto tracking = sweep["trackingGenerator"];
|
auto tracking = sweep["trackingGenerator"];
|
||||||
SetTGEnabled(tracking.value("enabled", settings.trackingGenerator ? true : false));
|
SetTGEnabled(tracking.value("enabled", settings.trackingGenerator ? true : false));
|
||||||
int port = tracking.value("port", 1);
|
int port = tracking.value("port", 1);
|
||||||
// Function expects 0 for port1, 1 for port2
|
SetTGPort(port);
|
||||||
SetTGPort(port - 1);
|
|
||||||
SetTGLevel(tracking.value("power", settings.trackingPower));
|
SetTGLevel(tracking.value("power", settings.trackingPower));
|
||||||
SetTGOffset(tracking.value("offset", settings.trackingOffset));
|
SetTGOffset(tracking.value("offset", settings.trackingOffset));
|
||||||
}
|
}
|
||||||
@ -699,7 +716,7 @@ void SpectrumAnalyzer::SetTGEnabled(bool enabled)
|
|||||||
|
|
||||||
void SpectrumAnalyzer::SetTGPort(int port)
|
void SpectrumAnalyzer::SetTGPort(int port)
|
||||||
{
|
{
|
||||||
if(port < 0 || port >= cbTrackGenPort->count()) {
|
if(port < 1 || port > cbTrackGenPort->count()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(port != settings.trackingPort) {
|
if(port != settings.trackingPort) {
|
||||||
@ -719,7 +736,7 @@ void SpectrumAnalyzer::SetTGLevel(double level)
|
|||||||
level = DeviceDriver::getInfo(window->getDevice()).Limits.SA.mindBm;
|
level = DeviceDriver::getInfo(window->getDevice()).Limits.SA.mindBm;
|
||||||
}
|
}
|
||||||
emit TGLevelChanged(level);
|
emit TGLevelChanged(level);
|
||||||
settings.trackingPower = level * 100;
|
settings.trackingPower = level;
|
||||||
if(settings.trackingGenerator) {
|
if(settings.trackingGenerator) {
|
||||||
SettingsChanged();
|
SettingsChanged();
|
||||||
}
|
}
|
||||||
@ -1058,7 +1075,7 @@ void SpectrumAnalyzer::SetupSCPI()
|
|||||||
if(!SCPI::paramToULongLong(params, 0, newval)) {
|
if(!SCPI::paramToULongLong(params, 0, newval)) {
|
||||||
return SCPI::getResultName(SCPI::Result::Error);
|
return SCPI::getResultName(SCPI::Result::Error);
|
||||||
} else if(newval > 0 && newval <= DeviceDriver::getInfo(window->getDevice()).Limits.SA.ports){
|
} else if(newval > 0 && newval <= DeviceDriver::getInfo(window->getDevice()).Limits.SA.ports){
|
||||||
SetTGPort(newval-1);
|
SetTGPort(newval);
|
||||||
return SCPI::getResultName(SCPI::Result::Empty);
|
return SCPI::getResultName(SCPI::Result::Empty);
|
||||||
} else {
|
} else {
|
||||||
// invalid port number
|
// invalid port number
|
||||||
@ -1066,7 +1083,7 @@ void SpectrumAnalyzer::SetupSCPI()
|
|||||||
}
|
}
|
||||||
return SCPI::getResultName(SCPI::Result::Empty);
|
return SCPI::getResultName(SCPI::Result::Empty);
|
||||||
}, [=](QStringList) -> QString {
|
}, [=](QStringList) -> QString {
|
||||||
return QString::number(settings.trackingPort+1);
|
return QString::number(settings.trackingPort);
|
||||||
}));
|
}));
|
||||||
scpi_tg->add(new SCPICommand("LVL", [=](QStringList params) -> QString {
|
scpi_tg->add(new SCPICommand("LVL", [=](QStringList params) -> QString {
|
||||||
double newval;
|
double newval;
|
||||||
@ -1077,7 +1094,7 @@ void SpectrumAnalyzer::SetupSCPI()
|
|||||||
return SCPI::getResultName(SCPI::Result::Empty);
|
return SCPI::getResultName(SCPI::Result::Empty);
|
||||||
}
|
}
|
||||||
}, [=](QStringList) -> QString {
|
}, [=](QStringList) -> QString {
|
||||||
return QString::number(settings.trackingPower / 100.0);
|
return QString::number(settings.trackingPower);
|
||||||
}));
|
}));
|
||||||
scpi_tg->add(new SCPICommand("OFFset", [=](QStringList params) -> QString {
|
scpi_tg->add(new SCPICommand("OFFset", [=](QStringList params) -> QString {
|
||||||
long newval;
|
long newval;
|
||||||
|
@ -224,7 +224,6 @@ std::vector<Trace *> TraceModel::getLiveTraces() const
|
|||||||
|
|
||||||
bool TraceModel::PortExcitationRequired(int port)
|
bool TraceModel::PortExcitationRequired(int port)
|
||||||
{
|
{
|
||||||
port++;
|
|
||||||
for(auto t : traces) {
|
for(auto t : traces) {
|
||||||
if(t->getSource() == Trace::Source::Live && !t->isPaused()) {
|
if(t->getSource() == Trace::Source::Live && !t->isPaused()) {
|
||||||
// this trace needs measurements from VNA, check if port has to be excited for its measurement
|
// this trace needs measurements from VNA, check if port has to be excited for its measurement
|
||||||
|
@ -403,7 +403,7 @@ VNA::VNA(AppWindow *window, QString name)
|
|||||||
tb_acq->addWidget(new QLabel("Points:"));
|
tb_acq->addWidget(new QLabel("Points:"));
|
||||||
tb_acq->addWidget(points);
|
tb_acq->addWidget(points);
|
||||||
|
|
||||||
auto eBandwidth = new SIUnitEdit("Hz", " k", 3);
|
auto eBandwidth = new SIUnitEdit("Hz", " kM", 3);
|
||||||
eBandwidth->setFixedWidth(70);
|
eBandwidth->setFixedWidth(70);
|
||||||
eBandwidth->setToolTip("IF bandwidth");
|
eBandwidth->setToolTip("IF bandwidth");
|
||||||
connect(eBandwidth, &SIUnitEdit::valueChanged, this, &VNA::SetIFBandwidth);
|
connect(eBandwidth, &SIUnitEdit::valueChanged, this, &VNA::SetIFBandwidth);
|
||||||
@ -675,6 +675,10 @@ void VNA::deactivate()
|
|||||||
|
|
||||||
void VNA::initializeDevice()
|
void VNA::initializeDevice()
|
||||||
{
|
{
|
||||||
|
if(!window->getDevice()->supports(DeviceDriver::Feature::VNA)) {
|
||||||
|
InformationBox::ShowError("Unsupported", "The connected device does not support VNA mode");
|
||||||
|
return;
|
||||||
|
}
|
||||||
defaultCalMenu->setEnabled(true);
|
defaultCalMenu->setEnabled(true);
|
||||||
connect(window->getDevice(), &DeviceDriver::VNAmeasurementReceived, this, &VNA::NewDatapoint, Qt::UniqueConnection);
|
connect(window->getDevice(), &DeviceDriver::VNAmeasurementReceived, this, &VNA::NewDatapoint, Qt::UniqueConnection);
|
||||||
// Check if default calibration exists and attempt to load it
|
// Check if default calibration exists and attempt to load it
|
||||||
@ -1680,11 +1684,11 @@ void VNA::ConfigureDevice(bool resetTraces, std::function<void(bool)> cb)
|
|||||||
DeviceDriver::VNASettings s = {};
|
DeviceDriver::VNASettings s = {};
|
||||||
s.IFBW = settings.bandwidth;
|
s.IFBW = settings.bandwidth;
|
||||||
if(Preferences::getInstance().Acquisition.alwaysExciteAllPorts) {
|
if(Preferences::getInstance().Acquisition.alwaysExciteAllPorts) {
|
||||||
for(unsigned int i=0;i<DeviceDriver::getInfo(window->getDevice()).Limits.VNA.ports;i++) {
|
for(unsigned int i=1;i<=DeviceDriver::getInfo(window->getDevice()).Limits.VNA.ports;i++) {
|
||||||
s.excitedPorts.push_back(i);
|
s.excitedPorts.push_back(i);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for(unsigned int i=0;i<DeviceDriver::getInfo(window->getDevice()).Limits.VNA.ports;i++) {
|
for(unsigned int i=1;i<=DeviceDriver::getInfo(window->getDevice()).Limits.VNA.ports;i++) {
|
||||||
if(traceModel.PortExcitationRequired(i))
|
if(traceModel.PortExcitationRequired(i))
|
||||||
s.excitedPorts.push_back(i);
|
s.excitedPorts.push_back(i);
|
||||||
}
|
}
|
||||||
|
@ -100,11 +100,6 @@ AppWindow::AppWindow(QWidget *parent)
|
|||||||
Preferences::getInstance().load();
|
Preferences::getInstance().load();
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto driver : DeviceDriver::getDrivers()) {
|
|
||||||
driver->registerTypes();
|
|
||||||
Preferences::getInstance().load(driver->driverSpecificSettings());
|
|
||||||
}
|
|
||||||
|
|
||||||
device = nullptr;
|
device = nullptr;
|
||||||
// vdevice = nullptr;
|
// vdevice = nullptr;
|
||||||
modeHandler = nullptr;
|
modeHandler = nullptr;
|
||||||
@ -254,6 +249,8 @@ void AppWindow::SetupMenu()
|
|||||||
auto SCPIenabled = p.SCPIServer.enabled;
|
auto SCPIenabled = p.SCPIServer.enabled;
|
||||||
auto SCPIport = p.SCPIServer.port;
|
auto SCPIport = p.SCPIServer.port;
|
||||||
p.edit();
|
p.edit();
|
||||||
|
// store the updated settings
|
||||||
|
p.store();
|
||||||
if(SCPIenabled != p.SCPIServer.enabled || SCPIport != p.SCPIServer.port) {
|
if(SCPIenabled != p.SCPIServer.enabled || SCPIport != p.SCPIServer.port) {
|
||||||
StopTCPServer();
|
StopTCPServer();
|
||||||
if(p.SCPIServer.enabled) {
|
if(p.SCPIServer.enabled) {
|
||||||
@ -321,9 +318,6 @@ void AppWindow::closeEvent(QCloseEvent *event)
|
|||||||
delete modeHandler;
|
delete modeHandler;
|
||||||
modeHandler = nullptr;
|
modeHandler = nullptr;
|
||||||
pref.store();
|
pref.store();
|
||||||
for(auto driver : DeviceDriver::getDrivers()) {
|
|
||||||
Preferences::getInstance().store(driver->driverSpecificSettings());
|
|
||||||
}
|
|
||||||
for(auto driver : DeviceDriver::getDrivers()) {
|
for(auto driver : DeviceDriver::getDrivers()) {
|
||||||
delete driver;
|
delete driver;
|
||||||
}
|
}
|
||||||
@ -350,9 +344,11 @@ bool AppWindow::ConnectToDevice(QString serial, DeviceDriver *driver)
|
|||||||
}
|
}
|
||||||
if(d->GetAvailableDevices().count(serial)) {
|
if(d->GetAvailableDevices().count(serial)) {
|
||||||
// this driver can connect to the device
|
// this driver can connect to the device
|
||||||
|
connect(d, &DeviceDriver::InfoUpdated, this, &AppWindow::DeviceInfoUpdated, Qt::QueuedConnection);
|
||||||
if(d->connectDevice(serial)) {
|
if(d->connectDevice(serial)) {
|
||||||
device = d;
|
device = d;
|
||||||
} else {
|
} else {
|
||||||
|
disconnect(d, nullptr, this, nullptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -363,7 +359,6 @@ bool AppWindow::ConnectToDevice(QString serial, DeviceDriver *driver)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
UpdateStatusBar(AppWindow::DeviceStatusBar::Connected);
|
UpdateStatusBar(AppWindow::DeviceStatusBar::Connected);
|
||||||
connect(device, &DeviceDriver::InfoUpdated, this, &AppWindow::DeviceInfoUpdated);
|
|
||||||
connect(device, &DeviceDriver::LogLineReceived, &deviceLog, &DeviceLog::addLine);
|
connect(device, &DeviceDriver::LogLineReceived, &deviceLog, &DeviceLog::addLine);
|
||||||
connect(device, &DeviceDriver::ConnectionLost, this, &AppWindow::DeviceConnectionLost);
|
connect(device, &DeviceDriver::ConnectionLost, this, &AppWindow::DeviceConnectionLost);
|
||||||
connect(device, &DeviceDriver::StatusUpdated, this, &AppWindow::DeviceStatusUpdated);
|
connect(device, &DeviceDriver::StatusUpdated, this, &AppWindow::DeviceStatusUpdated);
|
||||||
@ -420,9 +415,9 @@ bool AppWindow::ConnectToDevice(QString serial, DeviceDriver *driver)
|
|||||||
// vdevice->initialize();
|
// vdevice->initialize();
|
||||||
|
|
||||||
// UpdateAcquisitionFrequencies();
|
// UpdateAcquisitionFrequencies();
|
||||||
if (modeHandler->getActiveMode()) {
|
// if (modeHandler->getActiveMode()) {
|
||||||
modeHandler->getActiveMode()->initializeDevice();
|
// modeHandler->getActiveMode()->initializeDevice();
|
||||||
}
|
// }
|
||||||
return true;
|
return true;
|
||||||
} catch (const runtime_error &e) {
|
} catch (const runtime_error &e) {
|
||||||
qWarning() << "Failed to connect:" << e.what();
|
qWarning() << "Failed to connect:" << e.what();
|
||||||
@ -1370,7 +1365,7 @@ void AppWindow::UpdateStatusBar(DeviceStatusBar status)
|
|||||||
break;
|
break;
|
||||||
case DeviceStatusBar::Disconnected:
|
case DeviceStatusBar::Disconnected:
|
||||||
lConnectionStatus.setText("No device connected");
|
lConnectionStatus.setText("No device connected");
|
||||||
lDeviceInfo.setText("No device information available yet");
|
lDeviceInfo.setText("No status information available yet");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// invalid status
|
// invalid status
|
||||||
|
@ -62,6 +62,8 @@ protected:
|
|||||||
AppWindow *window;
|
AppWindow *window;
|
||||||
std::set<QAction*> actions;
|
std::set<QAction*> actions;
|
||||||
std::set<QToolBar*> toolbars;
|
std::set<QToolBar*> toolbars;
|
||||||
|
QToolBar *tb_trackgen;
|
||||||
|
SIUnitEdit *tgOffset;
|
||||||
std::set<QDockWidget*> docks;
|
std::set<QDockWidget*> docks;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include "ui_preferencesdialog.h"
|
#include "ui_preferencesdialog.h"
|
||||||
#include "CustomWidgets/informationbox.h"
|
#include "CustomWidgets/informationbox.h"
|
||||||
#include "appwindow.h"
|
#include "appwindow.h"
|
||||||
#include "Device/compounddeviceeditdialog.h"
|
#include "Device/LibreVNA/Compound/compounddeviceeditdialog.h"
|
||||||
|
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
@ -137,56 +137,6 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
|
|||||||
ui->MarkerShowP1dB->setEnabled(enabled);
|
ui->MarkerShowP1dB->setEnabled(enabled);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 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::doubleClicked, [=](){
|
|
||||||
auto index = ui->compoundList->currentRow();
|
|
||||||
if(index >= 0 && index < (int) p->compoundDevices.size()) {
|
|
||||||
auto d = new CompoundDeviceEditDialog(p->compoundDevices[index]);
|
|
||||||
connect(d, &QDialog::accepted, [=](){
|
|
||||||
ui->compoundList->item(index)->setText(p->compoundDevices[index]->getDesription());
|
|
||||||
p->nonTrivialWriting();
|
|
||||||
});
|
|
||||||
d->show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
connect(ui->compoundAdd, &QPushButton::clicked, [=](){
|
|
||||||
auto cd = new CompoundDevice;
|
|
||||||
auto d = new CompoundDeviceEditDialog(cd);
|
|
||||||
connect(d, &QDialog::accepted, [=](){
|
|
||||||
p->compoundDevices.push_back(cd);
|
|
||||||
ui->compoundList->addItem(cd->getDesription());
|
|
||||||
p->nonTrivialWriting();
|
|
||||||
});
|
|
||||||
connect(d, &QDialog::rejected, [=](){
|
|
||||||
delete cd;
|
|
||||||
});
|
|
||||||
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();
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
// Debug page
|
// Debug page
|
||||||
ui->DebugMaxUSBlogSize->setUnit("B");
|
ui->DebugMaxUSBlogSize->setUnit("B");
|
||||||
ui->DebugMaxUSBlogSize->setPrefixes(" kMG");
|
ui->DebugMaxUSBlogSize->setPrefixes(" kMG");
|
||||||
@ -362,10 +312,6 @@ void PreferencesDialog::setInitialGUIState()
|
|||||||
ui->DebugMaxUSBlogSize->setValue(p->Debug.USBlogSizeLimit);
|
ui->DebugMaxUSBlogSize->setValue(p->Debug.USBlogSizeLimit);
|
||||||
ui->DebugSaveTraceData->setChecked(p->Debug.saveTraceData);
|
ui->DebugSaveTraceData->setChecked(p->Debug.saveTraceData);
|
||||||
|
|
||||||
for(auto cd : p->compoundDevices) {
|
|
||||||
ui->compoundList->addItem(cd->getDesription());
|
|
||||||
}
|
|
||||||
|
|
||||||
QTreeWidgetItem *item = ui->treeWidget->topLevelItem(0);
|
QTreeWidgetItem *item = ui->treeWidget->topLevelItem(0);
|
||||||
if (item != nullptr) {
|
if (item != nullptr) {
|
||||||
ui->treeWidget->setCurrentItem(item); // visually select first item
|
ui->treeWidget->setCurrentItem(item); // visually select first item
|
||||||
@ -466,9 +412,7 @@ void PreferencesDialog::updateFromGUI()
|
|||||||
|
|
||||||
Preferences::~Preferences()
|
Preferences::~Preferences()
|
||||||
{
|
{
|
||||||
for(auto cd : compoundDevices) {
|
|
||||||
delete cd;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Preferences::load()
|
void Preferences::load()
|
||||||
@ -476,6 +420,10 @@ void Preferences::load()
|
|||||||
// load settings, using default values if not present
|
// load settings, using default values if not present
|
||||||
qInfo() << "Loading preferences";
|
qInfo() << "Loading preferences";
|
||||||
load(descr);
|
load(descr);
|
||||||
|
for(auto driver : DeviceDriver::getDrivers()) {
|
||||||
|
driver->registerTypes();
|
||||||
|
load(driver->driverSpecificSettings());
|
||||||
|
}
|
||||||
nonTrivialParsing();
|
nonTrivialParsing();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -495,6 +443,9 @@ void Preferences::store()
|
|||||||
{
|
{
|
||||||
nonTrivialWriting();
|
nonTrivialWriting();
|
||||||
store(descr);
|
store(descr);
|
||||||
|
for(auto driver : DeviceDriver::getDrivers()) {
|
||||||
|
store(driver->driverSpecificSettings());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Preferences::store(std::vector<Savable::SettingDescription> descr)
|
void Preferences::store(std::vector<Savable::SettingDescription> descr)
|
||||||
@ -515,6 +466,16 @@ void Preferences::edit()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Preferences::setDefault()
|
void Preferences::setDefault()
|
||||||
|
{
|
||||||
|
for(auto d : descr) {
|
||||||
|
d.var.setValue(d.def);
|
||||||
|
}
|
||||||
|
for(auto driver : DeviceDriver::getDrivers()) {
|
||||||
|
setDefault(driver->driverSpecificSettings());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Preferences::setDefault(std::vector<Savable::SettingDescription> descr)
|
||||||
{
|
{
|
||||||
for(auto d : descr) {
|
for(auto d : descr) {
|
||||||
d.var.setValue(d.def);
|
d.var.setValue(d.def);
|
||||||
@ -524,39 +485,42 @@ void Preferences::setDefault()
|
|||||||
void Preferences::fromJSON(nlohmann::json j)
|
void Preferences::fromJSON(nlohmann::json j)
|
||||||
{
|
{
|
||||||
parseJSON(j, descr);
|
parseJSON(j, descr);
|
||||||
|
for(auto driver : DeviceDriver::getDrivers()) {
|
||||||
|
Savable::parseJSON(j, driver->driverSpecificSettings());
|
||||||
|
}
|
||||||
nonTrivialParsing();
|
nonTrivialParsing();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static nlohmann::json merge(const nlohmann::json &a, const nlohmann::json &b)
|
||||||
|
{
|
||||||
|
nlohmann::json result = a.flatten();
|
||||||
|
nlohmann::json tmp = b.flatten();
|
||||||
|
|
||||||
|
for (nlohmann::json::iterator it = tmp.begin(); it != tmp.end(); ++it)
|
||||||
|
{
|
||||||
|
result[it.key()] = it.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.unflatten();
|
||||||
|
}
|
||||||
|
|
||||||
nlohmann::json Preferences::toJSON()
|
nlohmann::json Preferences::toJSON()
|
||||||
{
|
{
|
||||||
nonTrivialWriting();
|
nonTrivialWriting();
|
||||||
return createJSON(descr);
|
auto j = createJSON(descr);
|
||||||
|
for(auto driver : DeviceDriver::getDrivers()) {
|
||||||
|
j = merge(j, Savable::createJSON(driver->driverSpecificSettings()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Preferences::nonTrivialParsing()
|
void Preferences::nonTrivialParsing()
|
||||||
{
|
{
|
||||||
try {
|
|
||||||
compoundDevices.clear();
|
|
||||||
nlohmann::json jc = nlohmann::json::parse(compoundDeviceJSON.toStdString());
|
|
||||||
for(auto j : jc) {
|
|
||||||
auto cd = new CompoundDevice();
|
|
||||||
cd->fromJSON(j);
|
|
||||||
compoundDevices.push_back(cd);
|
|
||||||
}
|
|
||||||
} catch(const exception& e){
|
|
||||||
qDebug() << "Failed to parse compound device string: " << e.what();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Preferences::nonTrivialWriting()
|
void Preferences::nonTrivialWriting()
|
||||||
{
|
{
|
||||||
if(compoundDevices.size() > 0) {
|
|
||||||
nlohmann::json j;
|
|
||||||
for(auto cd : compoundDevices) {
|
|
||||||
j.push_back(cd->toJSON());
|
|
||||||
}
|
|
||||||
compoundDeviceJSON = QString::fromStdString(j.dump());
|
|
||||||
} else {
|
|
||||||
compoundDeviceJSON = "[]";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include "Util/qpointervariant.h"
|
#include "Util/qpointervariant.h"
|
||||||
#include "savable.h"
|
#include "savable.h"
|
||||||
|
|
||||||
#include "Device/compounddevice.h"
|
#include "Device/LibreVNA/Compound/compounddevice.h"
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
@ -56,6 +56,7 @@ public:
|
|||||||
void store(std::vector<Savable::SettingDescription> descr);
|
void store(std::vector<Savable::SettingDescription> descr);
|
||||||
void edit();
|
void edit();
|
||||||
void setDefault();
|
void setDefault();
|
||||||
|
void setDefault(std::vector<Savable::SettingDescription> descr);
|
||||||
|
|
||||||
void manualTCPport() { TCPoverride = true; }
|
void manualTCPport() { TCPoverride = true; }
|
||||||
|
|
||||||
@ -159,9 +160,6 @@ public:
|
|||||||
|
|
||||||
bool TCPoverride; // in case of manual port specification via command line
|
bool TCPoverride; // in case of manual port specification via command line
|
||||||
|
|
||||||
QString compoundDeviceJSON;
|
|
||||||
std::vector<CompoundDevice*> compoundDevices;
|
|
||||||
|
|
||||||
void fromJSON(nlohmann::json j) override;
|
void fromJSON(nlohmann::json j) override;
|
||||||
nlohmann::json toJSON() override;
|
nlohmann::json toJSON() override;
|
||||||
|
|
||||||
@ -258,7 +256,6 @@ private:
|
|||||||
{&SCPIServer.port, "SCPIServer.port", 19542},
|
{&SCPIServer.port, "SCPIServer.port", 19542},
|
||||||
{&Debug.USBlogSizeLimit, "Debug.USBlogSizeLimit", 10000000.0},
|
{&Debug.USBlogSizeLimit, "Debug.USBlogSizeLimit", 10000000.0},
|
||||||
{&Debug.saveTraceData, "Debug.saveTraceData", false},
|
{&Debug.saveTraceData, "Debug.saveTraceData", false},
|
||||||
{&compoundDeviceJSON, "compoundDeviceJSON", "[]"},
|
|
||||||
}};
|
}};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -53,6 +53,7 @@ public:
|
|||||||
switch(static_cast<QMetaType::Type>(val.type())) {
|
switch(static_cast<QMetaType::Type>(val.type())) {
|
||||||
case QMetaType::Double: e.var.setValue((*json_entry).get<double>()); break;
|
case QMetaType::Double: e.var.setValue((*json_entry).get<double>()); break;
|
||||||
case QMetaType::Int: e.var.setValue((*json_entry).get<int>()); break;
|
case QMetaType::Int: e.var.setValue((*json_entry).get<int>()); break;
|
||||||
|
case QMetaType::UInt: e.var.setValue((*json_entry).get<unsigned int>()); break;
|
||||||
case QMetaType::Bool: e.var.setValue((*json_entry).get<bool>()); break;
|
case QMetaType::Bool: e.var.setValue((*json_entry).get<bool>()); break;
|
||||||
case QMetaType::QString: {
|
case QMetaType::QString: {
|
||||||
auto s = QString::fromStdString((*json_entry).get<std::string>());
|
auto s = QString::fromStdString((*json_entry).get<std::string>());
|
||||||
@ -82,6 +83,7 @@ public:
|
|||||||
switch(static_cast<QMetaType::Type>(val.type())) {
|
switch(static_cast<QMetaType::Type>(val.type())) {
|
||||||
case QMetaType::Double: *json_entry = val.toDouble(); break;
|
case QMetaType::Double: *json_entry = val.toDouble(); break;
|
||||||
case QMetaType::Int: *json_entry = val.toInt(); break;
|
case QMetaType::Int: *json_entry = val.toInt(); break;
|
||||||
|
case QMetaType::UInt: *json_entry = val.toUInt(); break;
|
||||||
case QMetaType::Bool: *json_entry = val.toBool(); break;
|
case QMetaType::Bool: *json_entry = val.toBool(); break;
|
||||||
case QMetaType::QString: *json_entry = val.toString().toStdString(); break;
|
case QMetaType::QString: *json_entry = val.toString().toStdString(); break;
|
||||||
case QMetaType::QColor: *json_entry = val.value<QColor>().name().toStdString(); break;
|
case QMetaType::QColor: *json_entry = val.value<QColor>().name().toStdString(); break;
|
||||||
|
@ -34,8 +34,10 @@ SOURCES += \
|
|||||||
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialog.cpp \
|
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialog.cpp \
|
||||||
../LibreVNA-GUI/Device/LibreVNA/receivercaldialog.cpp \
|
../LibreVNA-GUI/Device/LibreVNA/receivercaldialog.cpp \
|
||||||
../LibreVNA-GUI/Device/LibreVNA/sourcecaldialog.cpp \
|
../LibreVNA-GUI/Device/LibreVNA/sourcecaldialog.cpp \
|
||||||
../LibreVNA-GUI/Device/compounddevice.cpp \
|
../LibreVNA-GUI/Device/LibreVNA/Compound/compounddevice.cpp \
|
||||||
../LibreVNA-GUI/Device/compounddeviceeditdialog.cpp \
|
../LibreVNA-GUI/Device/LibreVNA/Compound/compounddriver.cpp \
|
||||||
|
../LibreVNA-GUI/Device/LibreVNA/Compound/compounddeviceeditdialog.cpp \
|
||||||
|
../LibreVNA-GUI/Device/SSA3000X/ssa3000xdriver.cpp \
|
||||||
../LibreVNA-GUI/Device/device.cpp \
|
../LibreVNA-GUI/Device/device.cpp \
|
||||||
../LibreVNA-GUI/Device/devicedriver.cpp \
|
../LibreVNA-GUI/Device/devicedriver.cpp \
|
||||||
../LibreVNA-GUI/Device/devicelog.cpp \
|
../LibreVNA-GUI/Device/devicelog.cpp \
|
||||||
@ -205,8 +207,10 @@ HEADERS += \
|
|||||||
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialog.h \
|
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialog.h \
|
||||||
../LibreVNA-GUI/Device/LibreVNA/receivercaldialog.h \
|
../LibreVNA-GUI/Device/LibreVNA/receivercaldialog.h \
|
||||||
../LibreVNA-GUI/Device/LibreVNA/sourcecaldialog.h \
|
../LibreVNA-GUI/Device/LibreVNA/sourcecaldialog.h \
|
||||||
../LibreVNA-GUI/Device/compounddevice.h \
|
../LibreVNA-GUI/Device/LibreVNA/Compound/compounddevice.h \
|
||||||
../LibreVNA-GUI/Device/compounddeviceeditdialog.h \
|
../LibreVNA-GUI/Device/LibreVNA/Compound/compounddriver.h \
|
||||||
|
../LibreVNA-GUI/Device/LibreVNA/Compound/compounddeviceeditdialog.h \
|
||||||
|
../LibreVNA-GUI/Device/SSA3000X/ssa3000xdriver.h \
|
||||||
../LibreVNA-GUI/Device/device.h \
|
../LibreVNA-GUI/Device/device.h \
|
||||||
../LibreVNA-GUI/Device/devicedriver.h \
|
../LibreVNA-GUI/Device/devicedriver.h \
|
||||||
../LibreVNA-GUI/Device/devicelog.h \
|
../LibreVNA-GUI/Device/devicelog.h \
|
||||||
@ -355,7 +359,7 @@ FORMS += \
|
|||||||
../LibreVNA-GUI/Device/LibreVNA/firmwareupdatedialog.ui \
|
../LibreVNA-GUI/Device/LibreVNA/firmwareupdatedialog.ui \
|
||||||
../LibreVNA-GUI/Device/LibreVNA/frequencycaldialog.ui \
|
../LibreVNA-GUI/Device/LibreVNA/frequencycaldialog.ui \
|
||||||
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialog.ui \
|
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialog.ui \
|
||||||
../LibreVNA-GUI/Device/compounddeviceeditdialog.ui \
|
../LibreVNA-GUI/Device/LibreVNA/Compound/compounddeviceeditdialog.ui \
|
||||||
../LibreVNA-GUI/Device/devicelog.ui \
|
../LibreVNA-GUI/Device/devicelog.ui \
|
||||||
../LibreVNA-GUI/Device/deviceusblogview.ui \
|
../LibreVNA-GUI/Device/deviceusblogview.ui \
|
||||||
../LibreVNA-GUI/Generator/signalgenwidget.ui \
|
../LibreVNA-GUI/Generator/signalgenwidget.ui \
|
||||||
|
Loading…
Reference in New Issue
Block a user