improve GUI synchronization for compound device

This commit is contained in:
Jan Käberich 2025-05-04 13:01:00 +02:00
parent b3b3fa7718
commit 199bb7bbd7
9 changed files with 161 additions and 38 deletions

View file

@ -13,6 +13,8 @@
CompoundDriver::CompoundDriver()
{
connected = false;
isIdle = true;
triggerForwarding = false;
SApoints = 0;
drivers.push_back(new LibreVNAUSBDriver);
@ -296,6 +298,11 @@ bool CompoundDriver::setVNA(const DeviceDriver::VNASettings &s, std::function<vo
return setIdle(cb);
}
setIdle([this](bool){
enableTriggerForwarding();
qDebug() << "Start trigger forwarding";
});
// create port->stage mapping
portStageMapping.clear();
for(unsigned int i=0;i<s.excitedPorts.size();i++) {
@ -334,6 +341,11 @@ bool CompoundDriver::setVNA(const DeviceDriver::VNASettings &s, std::function<vo
}
});
}
lastNonIdleSettings.type = lastNonIdleSettings.Types::VNA;
lastNonIdleSettings.vna = s;
isIdle = false;
return success;
}
@ -353,6 +365,11 @@ bool CompoundDriver::setSA(const DeviceDriver::SASettings &s, std::function<void
}
zerospan = s.freqStart == s.freqStop;
setIdle([this](bool){
enableTriggerForwarding();
qDebug() << "Start trigger forwarding";
});
// Configure the devices
results.clear();
bool success = true;
@ -385,6 +402,11 @@ bool CompoundDriver::setSA(const DeviceDriver::SASettings &s, std::function<void
break;
}
}
lastNonIdleSettings.type = lastNonIdleSettings.Types::SA;
lastNonIdleSettings.sa = s;
isIdle = false;
return success;
}
@ -415,14 +437,22 @@ bool CompoundDriver::setSG(const DeviceDriver::SGSettings &s)
}
success &= devices[i]->setSG(devSettings);
}
lastNonIdleSettings.type = lastNonIdleSettings.Types::SG;
lastNonIdleSettings.sg = s;
isIdle = false;
return success;
}
bool CompoundDriver::setIdle(std::function<void (bool)> cb)
{
disableTriggerForwarding();
qDebug() << "Stop trigger forwarding";
auto success = true;
results.clear();
for(auto dev : devices) {
dev->sendWithoutPayload(Protocol::PacketType::ClearTrigger);
success &= dev->setIdle([=](bool success){
if(cb) {
results[dev] = success;
@ -430,6 +460,9 @@ bool CompoundDriver::setIdle(std::function<void (bool)> cb)
}
});
}
isIdle = true;
return success;
}
@ -464,9 +497,36 @@ QStringList CompoundDriver::availableExtRefOutSettings()
bool CompoundDriver::setExtRef(QString option_in, QString option_out)
{
auto success = true;
for(auto dev : devices) {
success &= dev->setExtRef(option_in, option_out);
qDebug() << "Ref change start";
if(isIdle) {
// can immediately switch reference settings
for(auto dev : devices) {
success &= dev->setExtRef(option_in, option_out);
}
} else {
// can not switch during a sweep
// set to idle first
setIdle();
// change reference
for(auto dev : devices) {
success &= dev->setExtRef(option_in, option_out);
}
// restore last non idle state
switch(lastNonIdleSettings.type) {
case lastNonIdleSettings.Types::VNA:
setVNA(lastNonIdleSettings.vna);
break;
case lastNonIdleSettings.Types::SA:
setSA(lastNonIdleSettings.sa);
break;
case lastNonIdleSettings.Types::SG:
setSG(lastNonIdleSettings.sg);
break;
}
}
qDebug() << "Ref change stop";
return success;
}
@ -485,6 +545,27 @@ std::set<QString> CompoundDriver::getIndividualDeviceSerials()
return ret;
}
void CompoundDriver::triggerReceived(LibreVNADriver *device, bool set)
{
triggerMutex.lock();
if(activeDevice.sync == LibreVNADriver::Synchronization::GUI && triggerForwarding) {
for(unsigned int i=0;i<devices.size();i++) {
if(devices[i] == device) {
// pass on to the next device
if(i < devices.size() - 1) {
qDebug() << "Passing on trigger" << set << "from" << device->getSerial() << "to" << devices[i+1]->getSerial();
devices[i+1]->sendWithoutPayload(set ? Protocol::PacketType::SetTrigger : Protocol::PacketType::ClearTrigger);
} else {
qDebug() << "Passing on trigger" << set << "from" << device->getSerial() << "to" << devices[0]->getSerial();
devices[0]->sendWithoutPayload(set ? Protocol::PacketType::SetTrigger : Protocol::PacketType::ClearTrigger);
}
break;
}
}
}
triggerMutex.unlock();
}
void CompoundDriver::parseCompoundJSON()
{
try {
@ -529,36 +610,6 @@ void CompoundDriver::incomingPacket(LibreVNADriver *device, const Protocol::Pack
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;
@ -652,6 +703,26 @@ void CompoundDriver::spectrumResultReceived(LibreVNADriver *dev, Protocol::Spect
}
}
void CompoundDriver::enableTriggerForwarding()
{
triggerMutex.lock();
for(auto d : devices) {
connect(d, &LibreVNADriver::receivedTrigger, this, &CompoundDriver::triggerReceived, Qt::UniqueConnection);
}
triggerForwarding = true;
triggerMutex.unlock();
}
void CompoundDriver::disableTriggerForwarding()
{
triggerMutex.lock();
triggerForwarding = false;
for(auto d : devices) {
QObject::disconnect(d, &LibreVNADriver::receivedTrigger, this, &CompoundDriver::triggerReceived);
}
triggerMutex.unlock();
}
void CompoundDriver::datapointReceivecd(LibreVNADriver *dev, Protocol::VNADatapoint<32> *data)
{
if(!compoundVNABuffer.count(data->pointNum)) {

View file

@ -4,6 +4,8 @@
#include "../../devicedriver.h"
#include "compounddevice.h"
#include <QMutex>
class CompoundDriver : public DeviceDriver
{
public:
@ -169,6 +171,8 @@ public:
static std::set<QString> getIndividualDeviceSerials();
private slots:
void triggerReceived(LibreVNADriver *device, bool set);
private:
void parseCompoundJSON();
void createCompoundJSON();
@ -177,6 +181,8 @@ private:
void updatedStatus(LibreVNADriver *device, const Protocol::DeviceStatus &status);
void datapointReceivecd(LibreVNADriver *dev, Protocol::VNADatapoint<32> *data);
void spectrumResultReceived(LibreVNADriver *dev, Protocol::SpectrumAnalyzerResult res);
void enableTriggerForwarding();
void disableTriggerForwarding();
Info info;
std::map<LibreVNADriver*, Info> deviceInfos;
@ -196,8 +202,17 @@ private:
// Configuration of the device we are connected to
CompoundDevice activeDevice;
bool connected;
bool triggerForwarding;
QMutex triggerMutex;
std::vector<LibreVNADriver*> devices;
bool zerospan;
bool isIdle;
struct {
VNASettings vna;
SASettings sa;
SGSettings sg;
enum class Types{VNA, SA, SG} type;
} lastNonIdleSettings;
unsigned int VNApoints;
unsigned int SApoints;

View file

@ -191,6 +191,8 @@ signals:
void receivedAnswer(const LibreVNADriver::TransmissionResult &result);
void receivedPacket(const Protocol::PacketInfo& packet);
void receivedTrigger(LibreVNADriver *driver, bool set);
protected slots:
void handleReceivedPacket(const Protocol::PacketInfo& packet);
protected:

View file

@ -242,6 +242,12 @@ void LibreVNATCPDriver::ReceivedData()
case Protocol::PacketType::Nack:
emit receivedAnswer(TransmissionResult::Nack);
break;
case Protocol::PacketType::SetTrigger:
emit receivedTrigger(this, true);
break;
case Protocol::PacketType::ClearTrigger:
emit receivedTrigger(this, false);
break;
default:
// pass on to LibreVNADriver class
emit receivedPacket(packet);

View file

@ -179,6 +179,12 @@ void LibreVNAUSBDriver::ReceivedData()
}
}
dataBuffer->removeBytes(handled_len);
if(packet.type == Protocol::PacketType::SetTrigger) {
qDebug() << "Incoming set trigger from " << serial;
}
if(packet.type == Protocol::PacketType::ClearTrigger) {
qDebug() << "Incoming clear trigger from " << serial;
}
switch(packet.type) {
case Protocol::PacketType::Ack:
emit receivedAnswer(TransmissionResult::Ack);
@ -186,6 +192,12 @@ void LibreVNAUSBDriver::ReceivedData()
case Protocol::PacketType::Nack:
emit receivedAnswer(TransmissionResult::Nack);
break;
case Protocol::PacketType::SetTrigger:
emit receivedTrigger(this, true);
break;
case Protocol::PacketType::ClearTrigger:
emit receivedTrigger(this, false);
break;
case Protocol::PacketType::None:
break;
default:

View file

@ -507,10 +507,13 @@ void AppWindow::CreateToolbars()
tb_reference->addWidget(new QLabel("Ref out:"));
toolbars.reference.outFreq = new QComboBox();
tb_reference->addWidget(toolbars.reference.outFreq);
connect(toolbars.reference.type, qOverload<int>(&QComboBox::currentIndexChanged), this, &AppWindow::UpdateReference);
connect(toolbars.reference.outFreq, qOverload<int>(&QComboBox::currentIndexChanged), this, &AppWindow::UpdateReference);
connect(toolbars.reference.type, qOverload<int>(&QComboBox::currentIndexChanged), this, &AppWindow::ReferenceChanged);
connect(toolbars.reference.outFreq, qOverload<int>(&QComboBox::currentIndexChanged), this, &AppWindow::ReferenceChanged);
addToolBar(tb_reference);
tb_reference->setObjectName("Reference Toolbar");
referenceTimer.setSingleShot(true);
connect(&referenceTimer, &QTimer::timeout, this, &AppWindow::UpdateReference);
}
void AppWindow::SetupSCPI()
@ -952,7 +955,7 @@ void AppWindow::ResetReference()
toolbars.reference.outFreq->setCurrentIndex(0);
toolbars.reference.type->blockSignals(false);
toolbars.reference.outFreq->blockSignals(false);
UpdateReference();
ReferenceChanged();
}
//void AppWindow::StartManualControl()
@ -1008,7 +1011,16 @@ void AppWindow::UpdateReferenceToolbar()
}
toolbars.reference.type->blockSignals(false);
toolbars.reference.outFreq->blockSignals(false);
UpdateReference();
ReferenceChanged();
}
void AppWindow::ReferenceChanged()
{
if(!device) {
// can't update without a device connected
return;
}
referenceTimer.start(100);
}
void AppWindow::UpdateReference()

View file

@ -82,6 +82,7 @@ private slots:
// void StartManualControl();
void ResetReference();
void UpdateReferenceToolbar();
void ReferenceChanged();
void UpdateReference();
void DeviceStatusUpdated();
void DeviceFlagsUpdated();
@ -144,6 +145,9 @@ private:
QString deviceSerial;
QActionGroup *deviceActionGroup;
// Reference change timer
QTimer referenceTimer;
// Status bar widgets
QLabel lConnectionStatus;
QLabel lDeviceInfo;

View file

@ -1,5 +1,5 @@
2F62501ED4689FB349E356AB974DBE57=EF826FD321FB312AEADE4DB74B81458C
2F62501ED4689FB349E356AB974DBE57=6F84FD31C089E822CF61FFCABCD0B7D1
66BE74F758C12D739921AEA421D593D3=2
8DF89ED150041C4CBC7CB9A9CAA90856=EF826FD321FB312AEADE4DB74B81458C
8DF89ED150041C4CBC7CB9A9CAA90856=6F84FD31C089E822CF61FFCABCD0B7D1
DC22A860405A8BF2F2C095E5B6529F12=BF78DB58F29884459C61AFB6BB93F7B6
eclipse.preferences.version=1

View file

@ -146,6 +146,7 @@ bool VNA::Setup(Protocol::SweepSettings s) {
vTaskDelay(5);
data.clear();
HW::SetMode(HW::Mode::VNA);
Trigger::SetInput(false);
sourceRefIndex = 0;
LO1RefIndex = 0;