diff --git a/Software/PC_Application/LibreVNA-GUI/Device/SSA3000X/ssa3000xdriver.cpp b/Software/PC_Application/LibreVNA-GUI/Device/SSA3000X/ssa3000xdriver.cpp index 80b9db3..8434831 100644 --- a/Software/PC_Application/LibreVNA-GUI/Device/SSA3000X/ssa3000xdriver.cpp +++ b/Software/PC_Application/LibreVNA-GUI/Device/SSA3000X/ssa3000xdriver.cpp @@ -7,6 +7,7 @@ #include SSA3000XDriver::SSA3000XDriver() + : DeviceTCPDriver("SSA3000X") { diffGen = new TraceDifferenceGenerator([=](const SpectrumPoint &p){ SAMeasurement m; @@ -15,7 +16,6 @@ SSA3000XDriver::SSA3000XDriver() m.measurements["PORT1"] = pow(10.0, p.dBm / 20.0); emit SAmeasurementReceived(m); }); - searchAddresses.push_back(QHostAddress("192.168.22.2")); connect(&traceTimer, &QTimer::timeout, this, &SSA3000XDriver::extractTracePoints); traceTimer.setSingleShot(true); } @@ -32,7 +32,7 @@ std::set SSA3000XDriver::GetAvailableDevices() // 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) { + for(auto address : getSearchAddresses()) { sock.connectToHost(address, 5024); if(sock.waitForConnected(50)) { // connection successful @@ -54,8 +54,6 @@ std::set SSA3000XDriver::GetAvailableDevices() } } sock.disconnect(); - } else { - qDebug() << "SSA3000X failed to connect"; } } return ret; @@ -113,7 +111,7 @@ bool SSA3000XDriver::connectTo(QString serial) info.supportedFeatures.insert(DeviceDriver::Feature::SA); info.supportedFeatures.insert(DeviceDriver::Feature::SATrackingGenerator); info.supportedFeatures.insert(DeviceDriver::Feature::Generator); - info.supportedFeatures.insert(DeviceDriver::Feature::ExtRefIn); +// info.supportedFeatures.insert(DeviceDriver::Feature::ExtRefIn); double maxFreq = 0; if(info.hardware_version == "SSA3032X") { @@ -146,27 +144,6 @@ bool SSA3000XDriver::connectTo(QString serial) emit InfoUpdated(); -// // sockets are connected now -// dataBuffer.clear(); -// logBuffer.clear(); -// connect(&dataSocket, qOverload(&QTcpSocket::error), this, &LibreVNATCPDriver::ConnectionLost, Qt::QueuedConnection); -// connect(&logSocket, qOverload(&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::QueuedConnection | Qt::UniqueConnection)); -// connect(this, &LibreVNATCPDriver::receivedPacket, this, &LibreVNATCPDriver::handleReceivedPacket, static_cast(Qt::QueuedConnection | Qt::UniqueConnection)); -// transmissionTimer.setSingleShot(true); -// transmissionActive = false; - -// sendWithoutPayload(Protocol::PacketType::RequestDeviceInfo); -// sendWithoutPayload(Protocol::PacketType::RequestDeviceStatus); -// updateIFFrequencies(); return true; } @@ -295,6 +272,7 @@ bool SSA3000XDriver::setIdle(std::function cb) if(cb) { cb(true); } + return true; } QStringList SSA3000XDriver::availableExtRefInSettings() diff --git a/Software/PC_Application/LibreVNA-GUI/Device/SSA3000X/ssa3000xdriver.h b/Software/PC_Application/LibreVNA-GUI/Device/SSA3000X/ssa3000xdriver.h index 895a247..4214fd3 100644 --- a/Software/PC_Application/LibreVNA-GUI/Device/SSA3000X/ssa3000xdriver.h +++ b/Software/PC_Application/LibreVNA-GUI/Device/SSA3000X/ssa3000xdriver.h @@ -1,7 +1,7 @@ #ifndef SSA3000XDRIVER_H #define SSA3000XDRIVER_H -#include "../devicedriver.h" +#include "../devicetcpdriver.h" #include "../tracedifferencegenerator.h" @@ -9,7 +9,7 @@ #include #include -class SSA3000XDriver : public DeviceDriver +class SSA3000XDriver : public DeviceTCPDriver { public: SSA3000XDriver(); @@ -167,7 +167,6 @@ private: QTimer traceTimer; TraceDifferenceGenerator *diffGen; - std::vector searchAddresses; std::map detectedDevices; }; diff --git a/Software/PC_Application/LibreVNA-GUI/Device/devicetcpdriver.cpp b/Software/PC_Application/LibreVNA-GUI/Device/devicetcpdriver.cpp new file mode 100644 index 0000000..09950c6 --- /dev/null +++ b/Software/PC_Application/LibreVNA-GUI/Device/devicetcpdriver.cpp @@ -0,0 +1,89 @@ +#include "devicetcpdriver.h" + +#include "ui_devicetcpdriversettings.h" + +#include + +DeviceTCPDriver::DeviceTCPDriver(QString driverName) +{ + specificSettings.push_back(Savable::SettingDescription(&searchAddressString, driverName+".searchAddressString", "")); +} + +QWidget *DeviceTCPDriver::createSettingsWidget() +{ + parseSearchAddressString(); + auto w = new QWidget(); + auto ui = new Ui::DeviceTCPDriverSettingsWidget; + ui->setupUi(w); + + ui->list->clear(); + for(auto &a : searchAddresses) { + auto item = new QListWidgetItem(); + if(a.isNull()) { + item->setText("0.0.0.0"); + } else { + item->setText(a.toString()); + } + item->setFlags(item->flags() | Qt::ItemIsEditable); + ui->list->addItem(item); + } + + connect(ui->list->itemDelegate(), &QAbstractItemDelegate::commitData, this, [=](QWidget *pLineEdit) { + QString strNewText = reinterpret_cast(pLineEdit)->text(); + int nRow = ui->list->currentRow(); + auto address = QHostAddress(strNewText); + if(!address.isNull()) { + // valid IP + searchAddresses[nRow] = address; + updateSearchAddressString(); + } + ui->list->item(nRow)->setText(searchAddresses[nRow].toString()); + }); + + connect(ui->add, &QPushButton::clicked, [=](){ + searchAddresses.push_back(QHostAddress("0.0.0.0")); + auto item = new QListWidgetItem(searchAddresses.back().toString()); + item->setFlags(item->flags() | Qt::ItemIsEditable); + ui->list->addItem(item); + updateSearchAddressString(); + }); + + connect(ui->remove, &QPushButton::clicked, [=](){ + auto index = ui->list->currentRow(); + if(index >= 0 && index < (int) searchAddresses.size()) { + delete ui->list->takeItem(index); + searchAddresses.erase(searchAddresses.begin() + index); + updateSearchAddressString(); + } + }); + + return w; +} + +std::vector DeviceTCPDriver::getSearchAddresses() +{ + parseSearchAddressString(); + return searchAddresses; +} + +void DeviceTCPDriver::parseSearchAddressString() +{ + QStringList list = searchAddressString.split(","); + searchAddresses.clear(); + for(auto &l : list) { + searchAddresses.push_back(QHostAddress(l)); + } +} + +void DeviceTCPDriver::updateSearchAddressString() +{ + searchAddressString = ""; + for(auto &a : searchAddresses) { + searchAddressString += a.toString(); + searchAddressString += ","; + } + if(searchAddressString.length() > 0) { + // remove trailing comma + searchAddressString.chop(1); + } +} diff --git a/Software/PC_Application/LibreVNA-GUI/Device/devicetcpdriver.h b/Software/PC_Application/LibreVNA-GUI/Device/devicetcpdriver.h new file mode 100644 index 0000000..6b6b0cf --- /dev/null +++ b/Software/PC_Application/LibreVNA-GUI/Device/devicetcpdriver.h @@ -0,0 +1,46 @@ +#ifndef DEVICETCPDRIVER_H +#define DEVICETCPDRIVER_H + +#include "devicedriver.h" + +#include + +/** + * @brief DeviceTCPDriver + * + * This is a convenience class for device drivers that are TCP/IP based and need to search for + * connected devices at specific IP addresses. If this is the case for your device driver, + * inherit from DeviceTCPDriver instead of DeviceDriver. + * When searching for connected devices, search the IP addresses as given by getSearchAddresses(). + * When overwriting createSettingsWidget in your derived driver, include the widget returned + * by DeviceTCPDriver::createSettingsWidget if you want the search addresses to be editable by + * the user. + */ + +class DeviceTCPDriver : public DeviceDriver +{ +public: + DeviceTCPDriver(QString driverName); + + /** + * @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; + +protected: + std::vector getSearchAddresses(); +private: + void parseSearchAddressString(); + void updateSearchAddressString(); + std::vector searchAddresses; + QString searchAddressString; +}; + +#endif // DEVICETCPDRIVER_H diff --git a/Software/PC_Application/LibreVNA-GUI/Device/devicetcpdriversettings.ui b/Software/PC_Application/LibreVNA-GUI/Device/devicetcpdriversettings.ui new file mode 100644 index 0000000..bcb002b --- /dev/null +++ b/Software/PC_Application/LibreVNA-GUI/Device/devicetcpdriversettings.ui @@ -0,0 +1,78 @@ + + + DeviceTCPDriverSettingsWidget + + + + 0 + 0 + 480 + 252 + + + + Form + + + + + + IP addresses to search for devices: + + + + + + + + + + + + + + + + + + :/icons/add.png + :/icons/add.png:/icons/add.png + + + + + + + + + + + :/icons/remove.png + :/icons/remove.png:/icons/remove.png + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + diff --git a/Software/PC_Application/LibreVNA-GUI/LibreVNA-GUI.pro b/Software/PC_Application/LibreVNA-GUI/LibreVNA-GUI.pro index 10e3ba8..9bfbb56 100644 --- a/Software/PC_Application/LibreVNA-GUI/LibreVNA-GUI.pro +++ b/Software/PC_Application/LibreVNA-GUI/LibreVNA-GUI.pro @@ -36,6 +36,7 @@ HEADERS += \ Device/SSA3000X/ssa3000xdriver.h \ Device/devicedriver.h \ Device/devicelog.h \ + Device/devicetcpdriver.h \ Device/tracedifferencegenerator.h \ Generator/generator.h \ Generator/signalgenwidget.h \ @@ -189,6 +190,7 @@ SOURCES += \ Device/SSA3000X/ssa3000xdriver.cpp \ Device/devicedriver.cpp \ Device/devicelog.cpp \ + Device/devicetcpdriver.cpp \ Generator/generator.cpp \ Generator/signalgenwidget.cpp \ SpectrumAnalyzer/spectrumanalyzer.cpp \ @@ -325,6 +327,7 @@ FORMS += \ Device/LibreVNA/librevnadriversettingswidget.ui \ Device/LibreVNA/manualcontroldialog.ui \ Device/devicelog.ui \ + Device/devicetcpdriversettings.ui \ Generator/signalgenwidget.ui \ Tools/impedancematchdialog.ui \ Tools/mixedmodeconversion.ui \ diff --git a/Software/PC_Application/LibreVNA-GUI/VNA/vna.cpp b/Software/PC_Application/LibreVNA-GUI/VNA/vna.cpp index b68857e..29110d8 100644 --- a/Software/PC_Application/LibreVNA-GUI/VNA/vna.cpp +++ b/Software/PC_Application/LibreVNA-GUI/VNA/vna.cpp @@ -51,6 +51,7 @@ #include #include #include +#include VNA::VNA(AppWindow *window, QString name) : Mode(window, name, "VNA"), @@ -267,7 +268,7 @@ VNA::VNA(AppWindow *window, QString name) tb_sweep->addWidget(bSingle); tb_sweep->addWidget(new QLabel("Sweep type:")); - auto cbSweepType = new QComboBox(); + cbSweepType = new QComboBox(); cbSweepType->addItem("Frequency"); cbSweepType->addItem("Power"); tb_sweep->addWidget(cbSweepType); @@ -321,14 +322,14 @@ VNA::VNA(AppWindow *window, QString name) connect(bZoomOut, &QPushButton::clicked, this, &VNA::SpanZoomOut); frequencySweepActions.push_back(tb_sweep->addWidget(bZoomOut)); - auto bZero = new QPushButton("0"); + bZero = new QPushButton("0"); bZero->setToolTip("Zero span"); bZero->setMaximumWidth(28); bZero->setMaximumHeight(24); connect(bZero, &QPushButton::clicked, this, &VNA::SetZeroSpan); frequencySweepActions.push_back(tb_sweep->addWidget(bZero)); - auto cbLogSweep = new QCheckBox("Log"); + cbLogSweep = new QCheckBox("Log"); cbLogSweep->setToolTip("Logarithmic sweep"); connect(cbLogSweep, &QCheckBox::toggled, this, &VNA::SetLogSweep); connect(this, &VNA::logSweepChanged, cbLogSweep, &QCheckBox::setChecked); @@ -673,12 +674,33 @@ void VNA::deactivate() Mode::deactivate(); } +static void SetComboBoxItemEnabled(QComboBox * comboBox, int index, bool enabled) +{ + auto * model = qobject_cast(comboBox->model()); + assert(model); + if(!model) return; + + auto * item = model->item(index); + assert(item); + if(!item) return; + item->setEnabled(enabled); +} + void VNA::initializeDevice() { if(!window->getDevice()->supports(DeviceDriver::Feature::VNA)) { InformationBox::ShowError("Unsupported", "The connected device does not support VNA mode"); return; } + cbLogSweep->setEnabled(window->getDevice()->supports(DeviceDriver::Feature::VNALogSweep)); + if(!window->getDevice()->supports(DeviceDriver::Feature::VNALogSweep)) { + SetLogSweep(false); + } + + bZero->setEnabled(window->getDevice()->supports(DeviceDriver::Feature::VNAZeroSpan)); + SetComboBoxItemEnabled(cbSweepType, 0, window->getDevice()->supports(DeviceDriver::Feature::VNAFrequencySweep)); + SetComboBoxItemEnabled(cbSweepType, 1, window->getDevice()->supports(DeviceDriver::Feature::VNAPowerSweep)); + defaultCalMenu->setEnabled(true); connect(window->getDevice(), &DeviceDriver::VNAmeasurementReceived, this, &VNA::NewDatapoint, Qt::UniqueConnection); // Check if default calibration exists and attempt to load it diff --git a/Software/PC_Application/LibreVNA-GUI/VNA/vna.h b/Software/PC_Application/LibreVNA-GUI/VNA/vna.h index 8b6de60..4a5dc8d 100644 --- a/Software/PC_Application/LibreVNA-GUI/VNA/vna.h +++ b/Software/PC_Application/LibreVNA-GUI/VNA/vna.h @@ -156,6 +156,9 @@ private: QString getCalStyle(); QString getCalToolTip(); + QComboBox *cbSweepType; + QCheckBox *cbLogSweep; + QPushButton *bZero; QMenu *defaultCalMenu; QAction *assignDefaultCal, *removeDefaultCal; diff --git a/Software/PC_Application/LibreVNA-GUI/appwindow.cpp b/Software/PC_Application/LibreVNA-GUI/appwindow.cpp index 0176477..ac93b52 100644 --- a/Software/PC_Application/LibreVNA-GUI/appwindow.cpp +++ b/Software/PC_Application/LibreVNA-GUI/appwindow.cpp @@ -1032,8 +1032,8 @@ void AppWindow::UpdateReferenceToolbar() { toolbars.reference.type->blockSignals(true); toolbars.reference.outFreq->blockSignals(true); - toolbars.reference.type->setEnabled(device || device->supports(DeviceDriver::Feature::ExtRefIn)); - toolbars.reference.outFreq->setEnabled(device || device->supports(DeviceDriver::Feature::ExtRefOut)); + toolbars.reference.type->setEnabled(device && device->supports(DeviceDriver::Feature::ExtRefIn)); + toolbars.reference.outFreq->setEnabled(device && device->supports(DeviceDriver::Feature::ExtRefOut)); if(device) { // save current setting auto refInBuf = toolbars.reference.type->currentText(); diff --git a/Software/PC_Application/LibreVNA-Test/LibreVNA-Test.pro b/Software/PC_Application/LibreVNA-Test/LibreVNA-Test.pro index 0932988..ffc7b53 100644 --- a/Software/PC_Application/LibreVNA-Test/LibreVNA-Test.pro +++ b/Software/PC_Application/LibreVNA-Test/LibreVNA-Test.pro @@ -42,6 +42,7 @@ SOURCES += \ ../LibreVNA-GUI/Device/devicelog.cpp \ ../LibreVNA-GUI/Device/LibreVNA/devicepacketlog.cpp \ ../LibreVNA-GUI/Device/LibreVNA/devicepacketlogview.cpp \ + ../LibreVNA-GUI/Device/devicetcpdriver.cpp \ ../LibreVNA-GUI/Generator/generator.cpp \ ../LibreVNA-GUI/Generator/signalgenwidget.cpp \ ../LibreVNA-GUI/SpectrumAnalyzer/spectrumanalyzer.cpp \ @@ -213,6 +214,7 @@ HEADERS += \ ../LibreVNA-GUI/Device/devicelog.h \ ../LibreVNA-GUI/Device/LibreVNA/devicepacketlog.h \ ../LibreVNA-GUI/Device/LibreVNA/devicepacketlogview.h \ + ../LibreVNA-GUI/Device/devicetcpdriver.h \ ../LibreVNA-GUI/Generator/generator.h \ ../LibreVNA-GUI/Generator/signalgenwidget.h \ ../LibreVNA-GUI/SpectrumAnalyzer/spectrumanalyzer.h \ @@ -358,6 +360,7 @@ FORMS += \ ../LibreVNA-GUI/Device/LibreVNA/Compound/compounddeviceeditdialog.ui \ ../LibreVNA-GUI/Device/devicelog.ui \ ../LibreVNA-GUI/Device/LibreVNA/devicepacketlogview.ui \ + ../LibreVNA-GUI/Device/devicetcpdriversettings.ui \ ../LibreVNA-GUI/Generator/signalgenwidget.ui \ ../LibreVNA-GUI/Tools/impedancematchdialog.ui \ ../LibreVNA-GUI/Tools/mixedmodeconversion.ui \