Handle more than two ports in SCPI and SA/SG GUI

This commit is contained in:
Jan Käberich 2022-08-23 00:37:25 +02:00
parent 4107c6ca73
commit 2b591aa362
12 changed files with 135 additions and 123 deletions

View File

@ -373,6 +373,8 @@ bool VirtualDevice::setSA(const VirtualDevice::SASettings &s, std::function<void
results.clear();
bool success = true;
for(unsigned int i=0;i<devices.size();i++) {
sd.trackingGenerator = 0;
sd.trackingGeneratorPort = 0;
if(s.trackingGenerator) {
if(CompoundDevice::PortMapping::findActiveStage(cdev->portMapping, i, 0) == s.trackingPort) {
sd.trackingGenerator = 1;
@ -381,10 +383,6 @@ bool VirtualDevice::setSA(const VirtualDevice::SASettings &s, std::function<void
sd.trackingGenerator = 1;
sd.trackingGeneratorPort = 1;
}
} else {
// not used
sd.trackingGenerator = 0;
sd.trackingGeneratorPort = 0;
}
sd.syncMaster = i == 0 ? 1 : 0;
success &= devices[i]->Configure(sd, [=](Device::TransmissionResult r){

View File

@ -5,7 +5,7 @@
Generator::Generator(AppWindow *window, QString name)
: Mode(window, name, "GENerator")
{
central = new SignalgeneratorWidget(window->getDevice(), window);
central = new SignalgeneratorWidget(window, window);
auto pref = Preferences::getInstance();
@ -58,6 +58,11 @@ void Generator::preset()
}
void Generator::deviceInfoUpdated()
{
central->deviceInfoUpdated();
}
void Generator::updateDevice()
{
if(!window->getDevice() || isActive != true) {
@ -83,7 +88,6 @@ void Generator::setupSCPI()
add(new SCPICommand("LVL", [=](QStringList params) -> QString {
double newval;
if(!SCPI::paramToDouble(params, 0, newval)) {
return SCPI::getResultName(SCPI::Result::Error);
} else {
central->setLevel(newval);
@ -94,7 +98,7 @@ void Generator::setupSCPI()
}));
add(new SCPICommand("PORT", [=](QStringList params) -> QString {
unsigned long long newval;
if(!SCPI::paramToULongLong(params, 0, newval) || newval > 2) {
if(!SCPI::paramToULongLong(params, 0, newval) || newval > VirtualDevice::getInfo(window->getDevice()).ports) {
return SCPI::getResultName(SCPI::Result::Error);
} else {
central->setPort(newval);

View File

@ -23,6 +23,8 @@ public:
void preset() override;
virtual void deviceInfoUpdated() override;
private slots:
void updateDevice();

View File

@ -2,10 +2,10 @@
#include "ui_signalgenwidget.h"
SignalgeneratorWidget::SignalgeneratorWidget(VirtualDevice *dev, QWidget *parent) :
SignalgeneratorWidget::SignalgeneratorWidget(AppWindow *window, QWidget *parent) :
QWidget(parent),
ui(new Ui::SignalgeneratorWidget),
dev(dev)
window(window)
{
ui->setupUi(this);
ui->frequency->setUnit("Hz");
@ -32,16 +32,16 @@ SignalgeneratorWidget::SignalgeneratorWidget(VirtualDevice *dev, QWidget *parent
ui->steps->setPrecision(0);
connect(ui->frequency, &SIUnitEdit::valueChanged, [=](double newval) {
if(newval < VirtualDevice::getInfo(dev).Limits.minFreq) {
newval = VirtualDevice::getInfo(dev).Limits.minFreq;
} else if (newval > VirtualDevice::getInfo(dev).Limits.maxFreq) {
newval = VirtualDevice::getInfo(dev).Limits.maxFreq;
if(newval < VirtualDevice::getInfo(window->getDevice()).Limits.minFreq) {
newval = VirtualDevice::getInfo(window->getDevice()).Limits.minFreq;
} else if (newval > VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq) {
newval = VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq;
}
ui->frequency->setValueQuiet(newval);
if (newval < ui->span->value()/2)
ui->span->setValueQuiet(newval/2);
if (newval + ui->span->value()/2 > VirtualDevice::getInfo(dev).Limits.maxFreq)
ui->span->setValueQuiet((VirtualDevice::getInfo(dev).Limits.maxFreq - newval)*2);
if (newval + ui->span->value()/2 > VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq)
ui->span->setValueQuiet((VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq - newval)*2);
newval = ui->frequency->value() - ui->span->value()/2;
ui->current->setValueQuiet(newval);
emit SettingsChanged();
@ -50,8 +50,8 @@ SignalgeneratorWidget::SignalgeneratorWidget(VirtualDevice *dev, QWidget *parent
connect(ui->span, &SIUnitEdit::valueChanged, [=](double newval) {
if(newval < 0 ) {
newval = 0;
} else if (newval > VirtualDevice::getInfo(dev).Limits.maxFreq - VirtualDevice::getInfo(dev).Limits.minFreq) {
newval = VirtualDevice::getInfo(dev).Limits.maxFreq - VirtualDevice::getInfo(dev).Limits.minFreq;
} else if (newval > VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq - VirtualDevice::getInfo(window->getDevice()).Limits.minFreq) {
newval = VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq - VirtualDevice::getInfo(window->getDevice()).Limits.minFreq;
}
ui->span->setValueQuiet(newval);
@ -60,8 +60,8 @@ SignalgeneratorWidget::SignalgeneratorWidget(VirtualDevice *dev, QWidget *parent
ui->frequency->setValueQuiet(ui->span->value()/2);
}
newF = ui->frequency->value() + ui->span->value()/2;
if (newF > VirtualDevice::getInfo(dev).Limits.maxFreq) {
ui->frequency->setValueQuiet(VirtualDevice::getInfo(dev).Limits.maxFreq - ui->span->value()/2);
if (newF > VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq) {
ui->frequency->setValueQuiet(VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq - ui->span->value()/2);
}
newval = ui->frequency->value() - ui->span->value()/2;
@ -72,8 +72,8 @@ SignalgeneratorWidget::SignalgeneratorWidget(VirtualDevice *dev, QWidget *parent
connect(ui->current, &SIUnitEdit::valueChanged, [=](double newval) {
if(newval < 0 ) {
newval = 0;
} else if (newval > VirtualDevice::getInfo(dev).Limits.maxFreq - VirtualDevice::getInfo(dev).Limits.minFreq) {
newval = VirtualDevice::getInfo(dev).Limits.maxFreq - VirtualDevice::getInfo(dev).Limits.minFreq;
} else if (newval > VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq - VirtualDevice::getInfo(window->getDevice()).Limits.minFreq) {
newval = VirtualDevice::getInfo(window->getDevice()).Limits.maxFreq - VirtualDevice::getInfo(window->getDevice()).Limits.minFreq;
}
ui->current->setValueQuiet(newval);
emit SettingsChanged();
@ -94,10 +94,9 @@ SignalgeneratorWidget::SignalgeneratorWidget(VirtualDevice *dev, QWidget *parent
connect(ui->levelSlider, &QSlider::valueChanged, [=](int value) {
setLevel((double) value / 100.0);
});
connect(ui->EnablePort1, &QCheckBox::toggled, this, &SignalgeneratorWidget::SettingsChanged);
connect(ui->EnablePort2, &QCheckBox::toggled, this, &SignalgeneratorWidget::SettingsChanged);
connect(ui->EnablePort3, &QCheckBox::toggled, this, &SignalgeneratorWidget::SettingsChanged);
connect(ui->EnablePort4, &QCheckBox::toggled, this, &SignalgeneratorWidget::SettingsChanged);
deviceInfoUpdated();
connect(ui->EnabledSweep, &QCheckBox::toggled, [=](bool enabled){
ui->current->setEnabled(enabled);
if(enabled) {
@ -140,32 +139,22 @@ VirtualDevice::SGSettings SignalgeneratorWidget::getDeviceStatus()
else
s.freq = ui->frequency->value();
s.dBm = ui->levelSpin->value();
if(ui->EnablePort1->isChecked()) {
s.port = 1;
} else if(ui->EnablePort2->isChecked()) {
s.port = 2;
} else if(ui->EnablePort3->isChecked()) {
s.port = 3;
} else if(ui->EnablePort4->isChecked()) {
s.port = 4;
} else {
s.port = 0;
s.port = 0;
for(unsigned int i=0;i<portCheckboxes.size();i++) {
if(portCheckboxes[i]->isChecked()) {
s.port = i+1;
}
}
return s;
}
nlohmann::json SignalgeneratorWidget::toJSON()
{
auto s = getDeviceStatus();
nlohmann::json j;
j["frequency"] = ui->frequency->value();
j["power"] = ui->levelSpin->value();
if(ui->EnablePort1->isChecked()) {
j["port"] = 1;
} else if(ui->EnablePort2->isChecked()) {
j["port"] = 2;
} else {
j["port"] = 0;
}
j["frequency"] = s.freq;
j["power"] = s.dBm;
j["port"] = s.port;
nlohmann::json sweep;
sweep["span"] = ui->span->value();
sweep["steps"] = ui->steps->value();
@ -192,6 +181,33 @@ void SignalgeneratorWidget::fromJSON(nlohmann::json j)
}
}
void SignalgeneratorWidget::deviceInfoUpdated()
{
auto port = getDeviceStatus().port;
for(auto cb : portCheckboxes) {
delete cb;
}
portCheckboxes.clear();
for(unsigned int i=1;i<=VirtualDevice::getInfo(window->getDevice()).ports;i++) {
auto cb = new QCheckBox("Port "+QString::number(i));
ui->portBox->layout()->addWidget(cb);
portCheckboxes.push_back(cb);
connect(cb, &QCheckBox::toggled, [=](bool enabled){
if(enabled) {
for(auto other : portCheckboxes) {
if(other != cb) {
other->blockSignals(true);
other->setChecked(false);
other->blockSignals(false);
}
}
}
emit SettingsChanged();
});
}
setPort(port);
}
void SignalgeneratorWidget::setLevel(double level)
{
// TODO constrain to frequency dependent levels
@ -211,22 +227,15 @@ void SignalgeneratorWidget::setFrequency(double frequency)
void SignalgeneratorWidget::setPort(int port)
{
if(port < 0 || port > 2) {
if(port < 0 || port > portCheckboxes.size()) {
return;
}
switch(port) {
case 0:
ui->EnablePort1->setChecked(false);
ui->EnablePort2->setChecked(false);
break;
case 1:
ui->EnablePort1->setChecked(true);
ui->EnablePort2->setChecked(false);
break;
case 2:
ui->EnablePort1->setChecked(false);
ui->EnablePort2->setChecked(true);
break;
if(port == 0) {
for(auto cb : portCheckboxes) {
cb->setChecked(false);
}
} else {
portCheckboxes[port-1]->setChecked(true);
}
}

View File

@ -1,8 +1,8 @@
#ifndef SIGNALGENERATOR_H
#define SIGNALGENERATOR_H
#include "Device/virtualdevice.h"
#include "savable.h"
#include "appwindow.h"
#include <QWidget>
@ -15,13 +15,14 @@ class SignalgeneratorWidget : public QWidget, public Savable
Q_OBJECT
public:
explicit SignalgeneratorWidget(VirtualDevice *dev, QWidget *parent = nullptr);
explicit SignalgeneratorWidget(AppWindow *window, QWidget *parent = nullptr);
~SignalgeneratorWidget();
VirtualDevice::SGSettings getDeviceStatus();
virtual nlohmann::json toJSON() override;
virtual void fromJSON(nlohmann::json j) override;
void deviceInfoUpdated();
signals:
void SettingsChanged();
@ -36,7 +37,8 @@ protected:
private:
Ui::SignalgeneratorWidget *ui;
int m_timerId;
VirtualDevice *dev;
AppWindow *window;
std::vector<QCheckBox*> portCheckboxes;
};
#endif // SIGNALGENERATOR_H

View File

@ -132,52 +132,11 @@
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<widget class="QGroupBox" name="portBox">
<property name="title">
<string>Enable</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QCheckBox" name="EnablePort1">
<property name="text">
<string>Port 1</string>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item>
<widget class="QCheckBox" name="EnablePort2">
<property name="text">
<string>Port 2</string>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item>
<widget class="QCheckBox" name="EnablePort3">
<property name="text">
<string>Port 3</string>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item>
<widget class="QCheckBox" name="EnablePort4">
<property name="text">
<string>Port 4</string>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
</layout>
<layout class="QVBoxLayout" name="verticalLayout_3"/>
</widget>
</item>
</layout>
@ -303,7 +262,4 @@
</customwidgets>
<resources/>
<connections/>
<buttongroups>
<buttongroup name="buttonGroup"/>
</buttongroups>
</ui>

View File

@ -193,7 +193,7 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name)
connect(this, &SpectrumAnalyzer::TGStateChanged, cbTrackGenEnable, &QCheckBox::setChecked);
tb_trackgen->addWidget(cbTrackGenEnable);
auto cbTrackGenPort = new QComboBox();
cbTrackGenPort = new QComboBox();
cbTrackGenPort->addItem("Port 1");
cbTrackGenPort->addItem("Port 2");
cbTrackGenPort->setCurrentIndex(0);
@ -254,6 +254,9 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name)
window->addDockWidget(Qt::BottomDockWidgetArea, markerDock);
docks.insert(markerDock);
// Set initial GUI state
deviceInfoUpdated();
SetupSCPI();
// Set initial TG settings
@ -464,7 +467,7 @@ void SpectrumAnalyzer::NewDatapoint(VirtualDevice::SAMeasurement m)
if(normalize.measuring) {
if(average.currentSweep() == averages) {
// this is the last averaging sweep, use values for normalization
if(normalize.portCorrection[0].size() > 0 || m_avg.pointNum == 0) {
if(normalize.portCorrection.size() > 0 || m_avg.pointNum == 0) {
// add measurement
for(auto m : m_avg.measurements) {
normalize.portCorrection[m.first].push_back(m.second);
@ -719,7 +722,7 @@ void SpectrumAnalyzer::SetTGEnabled(bool enabled)
void SpectrumAnalyzer::SetTGPort(int port)
{
if(port < 0 || port > 1) {
if(port < 0 || port >= cbTrackGenPort->count()) {
return;
}
if(port != settings.trackingPort) {
@ -733,10 +736,10 @@ void SpectrumAnalyzer::SetTGPort(int port)
void SpectrumAnalyzer::SetTGLevel(double level)
{
if(level > VirtualDevice::getInfo(window->getDevice()).Limits.maxdBm / 100.0) {
level = VirtualDevice::getInfo(window->getDevice()).Limits.maxdBm / 100.0;
} else if(level < VirtualDevice::getInfo(window->getDevice()).Limits.mindBm / 100.0) {
level = VirtualDevice::getInfo(window->getDevice()).Limits.mindBm / 100.0;
if(level > VirtualDevice::getInfo(window->getDevice()).Limits.maxdBm) {
level = VirtualDevice::getInfo(window->getDevice()).Limits.maxdBm;
} else if(level < VirtualDevice::getInfo(window->getDevice()).Limits.mindBm) {
level = VirtualDevice::getInfo(window->getDevice()).Limits.mindBm;
}
emit TGLevelChanged(level);
settings.trackingPower = level * 100;
@ -781,8 +784,7 @@ void SpectrumAnalyzer::MeasureNormalization()
void SpectrumAnalyzer::AbortNormalization()
{
EnableNormalization(false);
normalize.measuring = false;
normalize.points = 0;
ClearNormalization();
normalize.dialog.reset();
}
@ -808,6 +810,17 @@ void SpectrumAnalyzer::EnableNormalization(bool enabled)
normalize.enable->blockSignals(false);
}
void SpectrumAnalyzer::ClearNormalization()
{
EnableNormalization(false);
normalize.active = false;
normalize.measuring = false;
normalize.points = 0;
normalize.portCorrection.clear();
normalize.f_start = 0;
normalize.f_stop = 0;
}
void SpectrumAnalyzer::SetNormalizationLevel(double level)
{
normalize.Level->setValueQuiet(level);
@ -1005,11 +1018,14 @@ void SpectrumAnalyzer::SetupSCPI()
if (params.size() != 1) {
return SCPI::getResultName(SCPI::Result::Error);
}
if(params[0] == "1") {
SetTGPort(0);
} else if(params[0] == "2") {
SetTGPort(1);
unsigned long long newval;
if(!SCPI::paramToULongLong(params, 0, newval)) {
return SCPI::getResultName(SCPI::Result::Error);
} else if(newval >= 0 && newval <= VirtualDevice::getInfo(window->getDevice()).ports){
SetTGPort(newval);
return SCPI::getResultName(SCPI::Result::Empty);
} else {
// invalid port number
return SCPI::getResultName(SCPI::Result::Error);
}
return SCPI::getResultName(SCPI::Result::Empty);
@ -1019,7 +1035,6 @@ void SpectrumAnalyzer::SetupSCPI()
scpi_tg->add(new SCPICommand("LVL", [=](QStringList params) -> QString {
double newval;
if(!SCPI::paramToDouble(params, 0, newval)) {
return SCPI::getResultName(SCPI::Result::Error);
} else {
SetTGLevel(newval);
@ -1176,6 +1191,18 @@ void SpectrumAnalyzer::preset()
createDefaultTracesAndGraphs(VirtualDevice::getInfo(window->getDevice()).ports);
}
void SpectrumAnalyzer::deviceInfoUpdated()
{
// new device connected, throw away normalization
ClearNormalization();
auto tgPort = cbTrackGenPort->currentIndex();
cbTrackGenPort->clear();
for(unsigned int i=0;i<VirtualDevice::getInfo(window->getDevice()).ports;i++) {
cbTrackGenPort->addItem("Port "+QString::number(i+1));
}
SetTGPort(tgPort);
}
QString SpectrumAnalyzer::WindowToString(VirtualDevice::SASettings::Window w)
{
switch(w) {

View File

@ -33,6 +33,8 @@ public:
void preset() override;
virtual void deviceInfoUpdated() override;
private:
static QString WindowToString(VirtualDevice::SASettings::Window w);
static VirtualDevice::SASettings::Window WindowFromString(QString s);
@ -65,6 +67,7 @@ private slots:
void MeasureNormalization();
void AbortNormalization();
void EnableNormalization(bool enabled);
void ClearNormalization();
void SetNormalizationLevel(double level);
private:
@ -90,6 +93,7 @@ private:
TileWidget *central;
QCheckBox *cbSignalID;
QComboBox *cbWindowType, *cbDetector;
QComboBox *cbTrackGenPort;
QLabel *lAverages;
struct {

View File

@ -376,7 +376,7 @@ void TraceWidget::SetupSCPI()
}
auto newparam = params[1];
if((Trace::isVNAParameter(t->liveParameter()) && Trace::isVNAParameter(newparam))
|| (Trace::isVNAParameter(t->liveParameter()) && Trace::isVNAParameter(newparam))) {
|| (Trace::isSAParameter(t->liveParameter()) && Trace::isSAParameter(newparam))) {
t->fromLivedata(t->liveType(), newparam);
return "";
} else {

View File

@ -355,6 +355,13 @@ bool AppWindow::ConnectToDevice(QString serial)
break;
}
}
for(auto m : modeHandler->getModes()) {
connect(vdevice, &VirtualDevice::InfoUpdated, m, &Mode::deviceInfoUpdated);
}
if (modeHandler->getActiveMode()) {
modeHandler->getActiveMode()->initializeDevice();
}
return true;
} catch (const runtime_error &e) {
qWarning() << "Failed to connect:" << e.what();

View File

@ -47,6 +47,9 @@ public:
signals:
void statusbarMessage(QString msg);
public slots:
virtual void deviceInfoUpdated() {} // If the mode has settings that depend on the device capabilites, it should update these in here
protected:
virtual void activate(); // derived classes must call Mode::activate before doing anything

View File

@ -253,7 +253,7 @@ void PreferencesDialog::setInitialGUIState()
ui->StartupAutoconnect->setChecked(p->Startup.ConnectToFirstDevice);
if(p->Startup.RememberSweepSettings) {
ui->StartupSweepLastUsed->click();
} if(p->Startup.UseSetupFile) {
} else if(p->Startup.UseSetupFile) {
ui->StartupUseSetupFile->click();
} else {
ui->StartupSweepDefault->click();