diff --git a/Software/PC_Application/Application.pro b/Software/PC_Application/Application.pro index 28a273d..4afcd2e 100644 --- a/Software/PC_Application/Application.pro +++ b/Software/PC_Application/Application.pro @@ -123,3 +123,5 @@ RESOURCES += \ icons.qrc CONFIG += c++14 +REVISION = $$system(git rev-parse HEAD) +DEFINES += GITHASH=\\"\"$$REVISION\\"\" diff --git a/Software/PC_Application/Calibration/calibration.cpp b/Software/PC_Application/Calibration/calibration.cpp index dc62c9f..5849d77 100644 --- a/Software/PC_Application/Calibration/calibration.cpp +++ b/Software/PC_Application/Calibration/calibration.cpp @@ -676,8 +676,9 @@ istream& operator >>(istream &in, Calibration &c) { std::string line; while(getline(in, line)) { + QString qLine = QString::fromStdString(line).simplified(); for(auto m : c.Measurements()) { - if(Calibration::MeasurementToString(m) == QString::fromStdString(line)) { + if(Calibration::MeasurementToString(m) == qLine) { // this is the correct measurement c.clearMeasurement(m); uint timestamp; @@ -699,8 +700,8 @@ istream& operator >>(istream &in, Calibration &c) } } for(auto t : Calibration::Types()) { - if(Calibration::TypeToString(t) == QString::fromStdString(line)) { - // try to P2 this calibration type + if(Calibration::TypeToString(t) == qLine) { + // try to apply this calibration type if(c.calculationPossible(t)) { c.constructErrorTerms(t); } else { diff --git a/Software/PC_Application/CustomWidgets/siunitedit.cpp b/Software/PC_Application/CustomWidgets/siunitedit.cpp index ff3c3ca..62153b6 100644 --- a/Software/PC_Application/CustomWidgets/siunitedit.cpp +++ b/Software/PC_Application/CustomWidgets/siunitedit.cpp @@ -8,12 +8,13 @@ SIUnitEdit::SIUnitEdit(QString unit, QString prefixes, int precision, QWidget *parent) : QLineEdit(parent) { + _value = 0; this->unit = unit; this->prefixes = prefixes; this->precision = precision; setAlignment(Qt::AlignCenter); installEventFilter(this); - setValidator(new QDoubleValidator); + setValidator(new QDoubleValidator(this)); connect(this, &QLineEdit::editingFinished, [this]() { parseNewValue(1.0); }); diff --git a/Software/PC_Application/Device/device.cpp b/Software/PC_Application/Device/device.cpp index 7961454..52c9286 100644 --- a/Software/PC_Application/Device/device.cpp +++ b/Software/PC_Application/Device/device.cpp @@ -40,7 +40,7 @@ USBInBuffer::~USBInBuffer() qWarning() << "Timed out waiting for mutex acquisition during disconnect"; } } - delete buffer; + delete[] buffer; } void USBInBuffer::removeBytes(int handled_bytes) @@ -71,16 +71,15 @@ void USBInBuffer::Callback(libusb_transfer *transfer) emit DataReceived(); inCallback = false; break; - case LIBUSB_TRANSFER_ERROR: - qCritical() << "LIBUSB_TRANSFER_ERROR"; case LIBUSB_TRANSFER_NO_DEVICE: qCritical() << "LIBUSB_TRANSFER_NO_DEVICE"; - case LIBUSB_TRANSFER_OVERFLOW: - qCritical() << "LIBUSB_TRANSFER_OVERFLOW"; - case LIBUSB_TRANSFER_STALL: - qCritical() << "LIBUSB_TRANSFER_STALL"; libusb_free_transfer(transfer); - this->transfer = nullptr; + return; + case LIBUSB_TRANSFER_ERROR: + case LIBUSB_TRANSFER_OVERFLOW: + case LIBUSB_TRANSFER_STALL: + qCritical() << "LIBUSB_ERROR" << transfer->status; + libusb_free_transfer(transfer); emit TransferError(); return; break; @@ -129,6 +128,7 @@ Device::Device(QString serial) qDebug() << "Starting device connection..."; m_handle = nullptr; + lastInfoValid = false; libusb_init(&m_context); SearchDevices([=](libusb_device_handle *handle, QString found_serial) -> bool { @@ -202,6 +202,7 @@ Device::~Device() libusb_close(m_handle); m_receiveThread->join(); libusb_exit(m_context); + delete m_receiveThread; } } @@ -245,9 +246,7 @@ bool Device::SetManual(Protocol::ManualControl manual) bool Device::SetIdle() { - Protocol::SweepSettings s; - s.excitePort1 = 0; - s.excitePort2 = 0; + Protocol::SweepSettings s = {}; return Configure(s); } diff --git a/Software/PC_Application/Generator/generator.cpp b/Software/PC_Application/Generator/generator.cpp index ae274ed..7a46bbf 100644 --- a/Software/PC_Application/Generator/generator.cpp +++ b/Software/PC_Application/Generator/generator.cpp @@ -4,7 +4,7 @@ Generator::Generator(AppWindow *window) : Mode(window, "Signal Generator") { - central = new SignalgeneratorWidget(); + central = new SignalgeneratorWidget(window); auto pref = Preferences::getInstance(); diff --git a/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.cpp b/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.cpp index 3d676a5..43c4de3 100644 --- a/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.cpp +++ b/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.cpp @@ -43,9 +43,10 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window) : Mode(window, "Spectrum Analyzer"), - central(new TileWidget(traceModel)) + central(new TileWidget(traceModel, window)) { averages = 1; + settings = {}; // Create default traces auto tPort1 = new Trace("Port1", Qt::yellow); @@ -120,7 +121,6 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window) auto tb_acq = new QToolBar("Acquisition"); auto eBandwidth = new SIUnitEdit("Hz", " k", 3); - eBandwidth->setValueQuiet(settings.RBW); eBandwidth->setFixedWidth(70); eBandwidth->setToolTip("RBW"); connect(eBandwidth, &SIUnitEdit::valueChanged, this, &SpectrumAnalyzer::SetRBW); @@ -180,7 +180,7 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window) markerModel = new TraceMarkerModel(traceModel); auto tracesDock = new QDockWidget("Traces"); - tracesDock->setWidget(new TraceWidget(traceModel, this, true)); + tracesDock->setWidget(new TraceWidget(traceModel, window, true)); window->addDockWidget(Qt::LeftDockWidgetArea, tracesDock); docks.insert(tracesDock); diff --git a/Software/PC_Application/Traces/markerwidget.cpp b/Software/PC_Application/Traces/markerwidget.cpp index 072d26f..5ae7d63 100644 --- a/Software/PC_Application/Traces/markerwidget.cpp +++ b/Software/PC_Application/Traces/markerwidget.cpp @@ -22,6 +22,9 @@ MarkerWidget::MarkerWidget(TraceMarkerModel &model, QWidget *parent) : MarkerWidget::~MarkerWidget() { + delete ui->tableView->itemDelegateForColumn(TraceMarkerModel::ColIndexTrace); + delete ui->tableView->itemDelegateForColumn(TraceMarkerModel::ColIndexType); + delete ui->tableView->itemDelegateForColumn(TraceMarkerModel::ColIndexSettings); delete ui; } diff --git a/Software/PC_Application/Traces/tracemodel.cpp b/Software/PC_Application/Traces/tracemodel.cpp index f30355f..387f931 100644 --- a/Software/PC_Application/Traces/tracemodel.cpp +++ b/Software/PC_Application/Traces/tracemodel.cpp @@ -9,6 +9,14 @@ TraceModel::TraceModel(QObject *parent) traces.clear(); } +TraceModel::~TraceModel() +{ + while(!traces.empty()) { + delete traces[0]; + traces.erase(traces.begin()); + } +} + void TraceModel::addTrace(Trace *t) { beginInsertRows(QModelIndex(), traces.size(), traces.size()); diff --git a/Software/PC_Application/Traces/tracemodel.h b/Software/PC_Application/Traces/tracemodel.h index 874b238..26253ca 100644 --- a/Software/PC_Application/Traces/tracemodel.h +++ b/Software/PC_Application/Traces/tracemodel.h @@ -11,6 +11,7 @@ class TraceModel : public QAbstractTableModel Q_OBJECT public: TraceModel(QObject *parent = 0); + ~TraceModel(); void addTrace(Trace *t); void removeTrace(unsigned int index); diff --git a/Software/PC_Application/Traces/traceplot.cpp b/Software/PC_Application/Traces/traceplot.cpp index 63dbfca..a0015de 100644 --- a/Software/PC_Application/Traces/traceplot.cpp +++ b/Software/PC_Application/Traces/traceplot.cpp @@ -75,7 +75,7 @@ void TracePlot::updateContextMenu() contextmenu->addSection("Traces"); // Populate context menu for(auto t : traces) { - auto action = new QAction(t.first->name()); + auto action = new QAction(t.first->name(), contextmenu); action->setCheckable(true); if(t.second) { action->setChecked(true); @@ -86,7 +86,7 @@ void TracePlot::updateContextMenu() contextmenu->addAction(action); } contextmenu->addSeparator(); - auto close = new QAction("Close"); + auto close = new QAction("Close", contextmenu); contextmenu->addAction(close); connect(close, &QAction::triggered, [=]() { markedForDeletion = true; diff --git a/Software/PC_Application/Traces/tracexyplot.cpp b/Software/PC_Application/Traces/tracexyplot.cpp index ed26502..9a8122c 100644 --- a/Software/PC_Application/Traces/tracexyplot.cpp +++ b/Software/PC_Application/Traces/tracexyplot.cpp @@ -115,6 +115,25 @@ TraceXYPlot::TraceXYPlot(TraceModel &model, QWidget *parent) : TracePlot(parent), selectedMarker(nullptr) { + YAxis[0].log = false; + YAxis[0].Ytype = YAxisType::Disabled; + YAxis[0].rangeDiv = 1; + YAxis[0].rangeMax = 10; + YAxis[0].rangeMin = 0; + YAxis[0].autorange = false; + YAxis[1].log = false; + YAxis[1].Ytype = YAxisType::Disabled; + YAxis[1].rangeDiv = 1; + YAxis[1].rangeMax = 10; + YAxis[1].rangeMin = 0; + YAxis[1].autorange = false; + XAxis.Xtype = XAxisType::Frequency; + XAxis.log = false; + XAxis.rangeDiv = 1; + XAxis.rangeMax = 10; + XAxis.rangeMin = 0; + XAxis.autorange = true; + plot = new QwtPlot(this); auto canvas = new QwtPlotCanvas(plot); @@ -274,7 +293,7 @@ bool TraceXYPlot::isTDRtype(TraceXYPlot::YAxisType type) void TraceXYPlot::updateContextMenu() { contextmenu->clear(); - auto setup = new QAction("Axis setup..."); + auto setup = new QAction("Axis setup...", contextmenu); connect(setup, &QAction::triggered, [this]() { auto setup = new XYplotAxisDialog(this); setup->show(); @@ -295,7 +314,7 @@ void TraceXYPlot::updateContextMenu() continue; } - auto action = new QAction(t.first->name()); + auto action = new QAction(t.first->name(), contextmenu); action->setCheckable(true); if(tracesAxis[axis].find(t.first) != tracesAxis[axis].end()) { action->setChecked(true); @@ -307,7 +326,7 @@ void TraceXYPlot::updateContextMenu() } } contextmenu->addSeparator(); - auto close = new QAction("Close"); + auto close = new QAction("Close", contextmenu); contextmenu->addAction(close); connect(close, &QAction::triggered, [=]() { markedForDeletion = true; diff --git a/Software/PC_Application/VNA/portextension.cpp b/Software/PC_Application/VNA/portextension.cpp index 6558261..3bbc6be 100644 --- a/Software/PC_Application/VNA/portextension.cpp +++ b/Software/PC_Application/VNA/portextension.cpp @@ -2,6 +2,7 @@ #include "ui_portextensioneditdialog.h" #include #include +#include using namespace std; @@ -31,11 +32,92 @@ void PortExtension::applyToMeasurement(Protocol::Datapoint &d) if(measurements.size() > 0) { if(d.pointNum == 0) { // sweep complete, evaluate measurement - // TODO + + double last_phase = 0.0; + double phasediff_sum = 0.0; + vector att_x, att_y; + double avg_x = 0.0, avg_y = 0.0; + for(auto m : measurements) { + // grab correct measurement + complex reflection; + if(isPort1) { + reflection = complex(m.real_S11, m.imag_S11); + } else { + reflection = complex(m.real_S22, m.imag_S22); + } + // remove calkit if specified + if(!isIdeal) { + complex calStandard; + auto standards = kit->toSOLT(m.frequency); + if(isOpen) { + calStandard = standards.Open; + } else { + calStandard = standards.Short; + } + // remove effect of calibration standard + reflection /= calStandard; + } + // sum phase differences to previous point + auto phase = arg(reflection); + if(m.pointNum == 0) { + last_phase = phase; + } else { + auto phasediff = phase - last_phase; + last_phase = phase; + if(phasediff > M_PI) { + phasediff -= 2 * M_PI; + } else if(phasediff <= -M_PI) { + phasediff += 2 * M_PI; + } + phasediff_sum += phasediff; + qDebug() << phasediff; + } + + double x = sqrt(m.frequency / measurements.back().frequency); + double y = 20*log10(abs(reflection)); + att_x.push_back(x); + att_y.push_back(y); + avg_x += x; + avg_y += y; + } + auto phase = phasediff_sum / (measurements.size() - 1); + auto freq_diff = measurements[1].frequency - measurements[0].frequency; + auto delay = -phase / (2 * M_PI * freq_diff); + // measured delay is two-way but port extension expects one-way + delay /= 2; + + // calculate linear regression with transformed square root model + avg_x /= measurements.size(); + avg_y /= measurements.size(); + double sum_top = 0.0; + double sum_bottom = 0.0; + for(unsigned int i=0;iP1Time->setValue(delay); + ui->P1DCloss->setValue(DCloss); + ui->P1Loss->setValue(loss); + ui->P1Frequency->setValue(freq); + } else { + ui->P2Time->setValue(delay); + ui->P2DCloss->setValue(DCloss); + ui->P2Loss->setValue(loss); + ui->P2Frequency->setValue(freq); + } + if(msgBox) { msgBox->close(); msgBox = nullptr; } + measurements.clear(); } else { measurements.push_back(d); } @@ -94,7 +176,7 @@ void PortExtension::edit() constexpr double c = 299792458; auto dialog = new QDialog(); - auto ui = new Ui::PortExtensionEditDialog(); + ui = new Ui::PortExtensionEditDialog(); ui->setupUi(dialog); // set initial values diff --git a/Software/PC_Application/VNA/portextension.h b/Software/PC_Application/VNA/portextension.h index a7d145e..1045afd 100644 --- a/Software/PC_Application/VNA/portextension.h +++ b/Software/PC_Application/VNA/portextension.h @@ -7,6 +7,10 @@ #include "Calibration/calkit.h" #include +namespace Ui { +class PortExtensionEditDialog; +} + class PortExtension : public QObject { Q_OBJECT @@ -39,6 +43,7 @@ private: bool isIdeal; std::vector measurements; QMessageBox *msgBox; + Ui::PortExtensionEditDialog *ui; }; #endif // PORTEXTENSION_H diff --git a/Software/PC_Application/VNA/vna.cpp b/Software/PC_Application/VNA/vna.cpp index d85d416..43de246 100644 --- a/Software/PC_Application/VNA/vna.cpp +++ b/Software/PC_Application/VNA/vna.cpp @@ -86,7 +86,7 @@ VNA::VNA(AppWindow *window) central->Child2()->Child2()->setPlot(tracesmith2); // Create menu entries and connections - auto calMenu = new QMenu("Calibration"); + auto calMenu = new QMenu("Calibration", window); window->menuBar()->insertMenu(window->getUi()->menuWindow->menuAction(), calMenu); actions.insert(calMenu->menuAction()); auto calDisable = calMenu->addAction("Disabled"); @@ -112,13 +112,13 @@ VNA::VNA(AppWindow *window) portExtension.setCalkit(&cal.getCalibrationKit()); // Tools menu - auto toolsMenu = new QMenu("Tools"); + auto toolsMenu = new QMenu("Tools", window); window->menuBar()->insertMenu(window->getUi()->menuWindow->menuAction(), toolsMenu); actions.insert(toolsMenu->menuAction()); auto impedanceMatching = toolsMenu->addAction("Impedance Matching"); connect(impedanceMatching, &QAction::triggered, this, &VNA::StartImpedanceMatching); - defaultCalMenu = new QMenu("Default Calibration"); + defaultCalMenu = new QMenu("Default Calibration", window); assignDefaultCal = defaultCalMenu->addAction("Assign..."); removeDefaultCal = defaultCalMenu->addAction("Remove"); removeDefaultCal->setEnabled(false); @@ -201,7 +201,6 @@ VNA::VNA(AppWindow *window) // Acquisition toolbar auto tb_acq = new QToolBar("Acquisition"); auto dbm = new QDoubleSpinBox(); - dbm->setValue(settings.cdbm_excitation * 100); dbm->setFixedWidth(95); dbm->setRange(-100.0, 100.0); dbm->setSingleStep(0.25); @@ -215,7 +214,6 @@ VNA::VNA(AppWindow *window) auto points = new QSpinBox(); points->setFixedWidth(55); points->setRange(1, 4501); - points->setValue(settings.points); points->setSingleStep(100); points->setToolTip("Points/sweep"); connect(points, qOverload(&QSpinBox::valueChanged), this, &VNA::SetPoints); @@ -224,7 +222,6 @@ VNA::VNA(AppWindow *window) tb_acq->addWidget(points); auto eBandwidth = new SIUnitEdit("Hz", " k", 3); - eBandwidth->setValueQuiet(settings.if_bandwidth); eBandwidth->setFixedWidth(70); eBandwidth->setToolTip("IF bandwidth"); connect(eBandwidth, &SIUnitEdit::valueChanged, this, &VNA::SetIFBandwidth); @@ -255,7 +252,7 @@ VNA::VNA(AppWindow *window) calMenuGroup->addAction(calDisable); for(auto type : Calibration::Types()) { cbType->addItem(Calibration::TypeToString(type), (int) type); - auto menuAction = new QAction(Calibration::TypeToString(type)); + auto menuAction = new QAction(Calibration::TypeToString(type), calMenu); calMenuGroup->addAction(menuAction); connect(menuAction, &QAction::triggered, [=](){ ApplyCalibration(type); @@ -316,7 +313,7 @@ VNA::VNA(AppWindow *window) toolbars.insert(tb_portExtension); - markerModel = new TraceMarkerModel(traceModel); + markerModel = new TraceMarkerModel(traceModel, this); auto tracesDock = new QDockWidget("Traces"); tracesDock->setWidget(new TraceWidget(traceModel)); @@ -609,13 +606,13 @@ void VNA::ApplyCalibration(Calibration::Type type) emit CalibrationApplied(type); } } catch (runtime_error e) { - QMessageBox::critical(this, "Calibration failure", e.what()); + QMessageBox::critical(window, "Calibration failure", e.what()); DisableCalibration(true); } } else { // Not all required traces available // TODO start tracedata dialog with required traces - QMessageBox::information(this, "Missing calibration traces", "Not all calibration traces for this type of calibration have been measured. The calibration can be enabled after the missing traces have been acquired."); + QMessageBox::information(window, "Missing calibration traces", "Not all calibration traces for this type of calibration have been measured. The calibration can be enabled after the missing traces have been acquired."); DisableCalibration(true); StartCalibrationDialog(type); } @@ -679,11 +676,11 @@ void VNA::LoadSweepSettings() QSettings s; settings.f_start = s.value("SweepStart", pref.Startup.DefaultSweep.start).toULongLong(); settings.f_stop = s.value("SweepStop", pref.Startup.DefaultSweep.stop).toULongLong(); - ConstrainAndUpdateFrequencies(); - SetIFBandwidth(s.value("SweepBandwidth", pref.Startup.DefaultSweep.bandwidth).toUInt()); SetPoints(s.value("SweepPoints", pref.Startup.DefaultSweep.points).toInt()); + SetIFBandwidth(s.value("SweepBandwidth", pref.Startup.DefaultSweep.bandwidth).toUInt()); SetAveraging(s.value("SweepAveraging", pref.Startup.DefaultSweep.averaging).toInt()); SetSourceLevel(s.value("SweepLevel", pref.Startup.DefaultSweep.excitation).toDouble()); + ConstrainAndUpdateFrequencies(); } void VNA::StoreSweepSettings() diff --git a/Software/PC_Application/appwindow.cpp b/Software/PC_Application/appwindow.cpp index 1549bcc..15f164b 100644 --- a/Software/PC_Application/appwindow.cpp +++ b/Software/PC_Application/appwindow.cpp @@ -59,8 +59,6 @@ AppWindow::AppWindow(QWidget *parent) device = nullptr; ui->setupUi(this); -// ui->statusbar->insertPermanentWidget(0, &lDeviceStatus); -// ui->statusbar->insertPermanentWidget(1, new QPushButton("Test")); ui->statusbar->addWidget(&lConnectionStatus); auto div1 = new QFrame; div1->setFrameShape(QFrame::VLine); @@ -91,8 +89,6 @@ AppWindow::AppWindow(QWidget *parent) auto vna = new VNA(this); new Generator(this); new SpectrumAnalyzer(this); -// auto signalGenWidget = new Signalgenerator; -// modeSGen = new GUIMode(this, "Signal Generator", signalGenWidget); // UI connections connect(ui->actionUpdate_Device_List, &QAction::triggered, this, &AppWindow::UpdateDeviceList); @@ -112,6 +108,11 @@ AppWindow::AppWindow(QWidget *parent) // settings might have changed, update necessary stuff TraceXYPlot::updateGraphColors(); }); + connect(ui->actionAbout, &QAction::triggered, [=](){ + auto commit = QString(GITHASH); + commit.truncate(7); + QMessageBox::about(this, "About", "More information: github.com/jankae/VNA2\n\nVersion: " + commit); + }); setWindowTitle("VNA"); @@ -137,6 +138,11 @@ AppWindow::AppWindow(QWidget *parent) } } +AppWindow::~AppWindow() +{ + delete ui; +} + void AppWindow::closeEvent(QCloseEvent *event) { delete device; diff --git a/Software/PC_Application/appwindow.h b/Software/PC_Application/appwindow.h index 32dd158..e83c5ff 100644 --- a/Software/PC_Application/appwindow.h +++ b/Software/PC_Application/appwindow.h @@ -28,7 +28,7 @@ class AppWindow : public QMainWindow Q_OBJECT public: AppWindow(QWidget *parent = nullptr); - + ~AppWindow(); Ui::MainWindow *getUi() const; QStackedWidget *getCentral() const; diff --git a/Software/PC_Application/main.ui b/Software/PC_Application/main.ui index f06b85a..8217b38 100644 --- a/Software/PC_Application/main.ui +++ b/Software/PC_Application/main.ui @@ -69,9 +69,16 @@ + + + Help + + + + @@ -139,6 +146,11 @@ Preferences + + + About + + diff --git a/Software/PC_Application/mode.cpp b/Software/PC_Application/mode.cpp index 977c981..8bfca2d 100644 --- a/Software/PC_Application/mode.cpp +++ b/Software/PC_Application/mode.cpp @@ -9,7 +9,8 @@ QWidget* Mode::cornerWidget = nullptr; QButtonGroup* Mode::modeButtonGroup = nullptr; Mode::Mode(AppWindow *window, QString name) - : window(window), + : QObject(window), + window(window), name(name), central(nullptr) { diff --git a/Software/PC_Application/mode.h b/Software/PC_Application/mode.h index d747c53..bde9739 100644 --- a/Software/PC_Application/mode.h +++ b/Software/PC_Application/mode.h @@ -9,10 +9,11 @@ #include #include "appwindow.h" -class Mode : public QWidget +class Mode : public QObject { public: Mode(AppWindow *window, QString name); + virtual void activate(); virtual void deactivate(); QString getName() const;