Refactoring: splitting mode logic into different classes
This commit is contained in:
parent
e266d37b96
commit
b7033a029e
Binary file not shown.
@ -13,11 +13,8 @@ HEADERS += \
|
||||
Device/devicelog.h \
|
||||
Device/firmwareupdatedialog.h \
|
||||
Device/manualcontroldialog.h \
|
||||
Menu/menu.h \
|
||||
Menu/menuaction.h \
|
||||
Menu/menubool.h \
|
||||
Menu/menuitem.h \
|
||||
Menu/menuvalue.h \
|
||||
Generator/generator.h \
|
||||
Generator/signalgenwidget.h \
|
||||
Tools/eseries.h \
|
||||
Tools/impedancematchdialog.h \
|
||||
Traces/bodeplotaxisdialog.h \
|
||||
@ -33,14 +30,14 @@ HEADERS += \
|
||||
Traces/traceplot.h \
|
||||
Traces/tracesmithchart.h \
|
||||
Traces/tracewidget.h \
|
||||
VNA/vna.h \
|
||||
appwindow.h \
|
||||
averaging.h \
|
||||
mode.h \
|
||||
preferences.h \
|
||||
qwtplotpiecewisecurve.h \
|
||||
signalgenerator.h \
|
||||
touchstone.h \
|
||||
unit.h \
|
||||
valueinput.h \
|
||||
vna.h
|
||||
unit.h
|
||||
|
||||
SOURCES += \
|
||||
../VNA_embedded/Application/Communication/Protocol.cpp \
|
||||
@ -49,6 +46,7 @@ SOURCES += \
|
||||
Calibration/calkit.cpp \
|
||||
Calibration/calkitdialog.cpp \
|
||||
Calibration/measurementmodel.cpp \
|
||||
CustomWidgets/qwtplotpiecewisecurve.cpp \
|
||||
CustomWidgets/siunitedit.cpp \
|
||||
CustomWidgets/tilewidget.cpp \
|
||||
CustomWidgets/toggleswitch.cpp \
|
||||
@ -57,11 +55,8 @@ SOURCES += \
|
||||
Device/devicelog.cpp \
|
||||
Device/firmwareupdatedialog.cpp \
|
||||
Device/manualcontroldialog.cpp \
|
||||
Menu/menu.cpp \
|
||||
Menu/menuaction.cpp \
|
||||
Menu/menubool.cpp \
|
||||
Menu/menuitem.cpp \
|
||||
Menu/menuvalue.cpp \
|
||||
Generator/generator.cpp \
|
||||
Generator/signalgenwidget.cpp \
|
||||
Tools/eseries.cpp \
|
||||
Tools/impedancematchdialog.cpp \
|
||||
Traces/bodeplotaxisdialog.cpp \
|
||||
@ -77,15 +72,14 @@ SOURCES += \
|
||||
Traces/traceplot.cpp \
|
||||
Traces/tracesmithchart.cpp \
|
||||
Traces/tracewidget.cpp \
|
||||
VNA/vna.cpp \
|
||||
appwindow.cpp \
|
||||
averaging.cpp \
|
||||
main.cpp \
|
||||
mode.cpp \
|
||||
preferences.cpp \
|
||||
qwtplotpiecewisecurve.cpp \
|
||||
signalgenerator.cpp \
|
||||
touchstone.cpp \
|
||||
unit.cpp \
|
||||
valueinput.cpp \
|
||||
vna.cpp
|
||||
unit.cpp
|
||||
|
||||
LIBS += -lusb-1.0
|
||||
unix:INCLUDEPATH += /usr/include/qwt
|
||||
@ -103,6 +97,7 @@ FORMS += \
|
||||
Device/devicelog.ui \
|
||||
Device/firmwareupdatedialog.ui \
|
||||
Device/manualcontroldialog.ui \
|
||||
Generator/signalgenwidget.ui \
|
||||
Tools/impedancematchdialog.ui \
|
||||
Traces/bodeplotaxisdialog.ui \
|
||||
Traces/markerwidget.ui \
|
||||
@ -111,8 +106,7 @@ FORMS += \
|
||||
Traces/traceimportdialog.ui \
|
||||
Traces/tracewidget.ui \
|
||||
main.ui \
|
||||
preferencesdialog.ui \
|
||||
signalgenerator.ui
|
||||
preferencesdialog.ui
|
||||
|
||||
DISTFILES +=
|
||||
|
||||
|
@ -8,6 +8,96 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
USBInBuffer::USBInBuffer(libusb_device_handle *handle, unsigned char endpoint, int buffer_size) :
|
||||
buffer_size(buffer_size),
|
||||
received_size(0),
|
||||
inCallback(false)
|
||||
{
|
||||
buffer = new unsigned char[buffer_size];
|
||||
transfer = libusb_alloc_transfer(0);
|
||||
libusb_fill_bulk_transfer(transfer, handle, endpoint, buffer, 64, CallbackTrampoline, this, 100);
|
||||
libusb_submit_transfer(transfer);
|
||||
}
|
||||
|
||||
USBInBuffer::~USBInBuffer()
|
||||
{
|
||||
if(transfer) {
|
||||
qDebug() << "Start cancellation";
|
||||
libusb_cancel_transfer(transfer);
|
||||
// wait for cancellation to complete
|
||||
mutex mtx;
|
||||
unique_lock<mutex> lck(mtx);
|
||||
cv.wait(lck);
|
||||
qDebug() << "Cancellation complete";
|
||||
}
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
void USBInBuffer::removeBytes(int handled_bytes)
|
||||
{
|
||||
if(!inCallback) {
|
||||
throw runtime_error("Removing of bytes is only allowed from within receive callback");
|
||||
}
|
||||
if(handled_bytes >= received_size) {
|
||||
received_size = 0;
|
||||
} else {
|
||||
// not removing all bytes, have to move remaining data to the beginning of the buffer
|
||||
memmove(buffer, &buffer[handled_bytes], received_size - handled_bytes);
|
||||
received_size -= handled_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
int USBInBuffer::getReceived() const
|
||||
{
|
||||
return received_size;
|
||||
}
|
||||
|
||||
void USBInBuffer::Callback(libusb_transfer *transfer)
|
||||
{
|
||||
switch(transfer->status) {
|
||||
case LIBUSB_TRANSFER_COMPLETED:
|
||||
received_size += transfer->actual_length;
|
||||
inCallback = true;
|
||||
emit DataReceived();
|
||||
inCallback = false;
|
||||
break;
|
||||
case LIBUSB_TRANSFER_ERROR:
|
||||
case LIBUSB_TRANSFER_NO_DEVICE:
|
||||
case LIBUSB_TRANSFER_OVERFLOW:
|
||||
case LIBUSB_TRANSFER_STALL:
|
||||
qCritical() << "LIBUSB_TRANSFER_ERROR";
|
||||
libusb_free_transfer(transfer);
|
||||
this->transfer = nullptr;
|
||||
emit TransferError();
|
||||
return;
|
||||
break;
|
||||
case LIBUSB_TRANSFER_TIMED_OUT:
|
||||
// nothing to do
|
||||
break;
|
||||
case LIBUSB_TRANSFER_CANCELLED:
|
||||
// destructor called, do not resubmit
|
||||
libusb_free_transfer(transfer);
|
||||
this->transfer = nullptr;
|
||||
cv.notify_all();
|
||||
return;
|
||||
break;
|
||||
}
|
||||
// Resubmit the transfer
|
||||
transfer->buffer = &buffer[received_size];
|
||||
libusb_submit_transfer(transfer);
|
||||
}
|
||||
|
||||
void USBInBuffer::CallbackTrampoline(libusb_transfer *transfer)
|
||||
{
|
||||
auto usb = (USBInBuffer*) transfer->user_data;
|
||||
usb->Callback(transfer);
|
||||
}
|
||||
|
||||
uint8_t *USBInBuffer::getBuffer() const
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
|
||||
Device::Device(QString serial)
|
||||
{
|
||||
qDebug() << "Starting device connection...";
|
||||
@ -62,6 +152,9 @@ Device::Device(QString serial)
|
||||
connect(dataBuffer, &USBInBuffer::DataReceived, this, &Device::ReceivedData, Qt::DirectConnection);
|
||||
connect(dataBuffer, &USBInBuffer::TransferError, this, &Device::ConnectionLost);
|
||||
connect(logBuffer, &USBInBuffer::DataReceived, this, &Device::ReceivedLog, Qt::DirectConnection);
|
||||
connect(&transmissionTimer, &QTimer::timeout, this, &Device::transmissionTimeout);
|
||||
transmissionTimer.setSingleShot(true);
|
||||
transmissionActive = false;
|
||||
}
|
||||
|
||||
Device::~Device()
|
||||
@ -82,26 +175,17 @@ Device::~Device()
|
||||
}
|
||||
}
|
||||
|
||||
bool Device::SendPacket(Protocol::PacketInfo packet)
|
||||
bool Device::SendPacket(Protocol::PacketInfo packet, std::function<void(TransmissionResult)> cb, unsigned int timeout)
|
||||
{
|
||||
if(m_connected) {
|
||||
unsigned char buffer[1024];
|
||||
unsigned int length = Protocol::EncodePacket(packet, buffer, sizeof(buffer));
|
||||
if(!length) {
|
||||
qCritical() << "Failed to encode packet";
|
||||
return false;
|
||||
}
|
||||
int actual_length;
|
||||
auto ret = libusb_bulk_transfer(m_handle, EP_Data_Out_Addr, buffer, length, &actual_length, 0);
|
||||
if(ret < 0) {
|
||||
qCritical() << "Error sending data: "
|
||||
<< libusb_strerror((libusb_error) ret);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
Transmission t;
|
||||
t.packet = packet;
|
||||
t.timeout = timeout;
|
||||
t.callback = cb;
|
||||
transmissionQueue.enqueue(t);
|
||||
if(!transmissionActive) {
|
||||
startNextTransmission();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Device::Configure(Protocol::SweepSettings settings)
|
||||
@ -303,93 +387,38 @@ QString Device::serial() const
|
||||
return m_serial;
|
||||
}
|
||||
|
||||
USBInBuffer::USBInBuffer(libusb_device_handle *handle, unsigned char endpoint, int buffer_size) :
|
||||
buffer_size(buffer_size),
|
||||
received_size(0),
|
||||
inCallback(false)
|
||||
void Device::startNextTransmission()
|
||||
{
|
||||
buffer = new unsigned char[buffer_size];
|
||||
transfer = libusb_alloc_transfer(0);
|
||||
libusb_fill_bulk_transfer(transfer, handle, endpoint, buffer, 64, CallbackTrampoline, this, 100);
|
||||
libusb_submit_transfer(transfer);
|
||||
}
|
||||
|
||||
USBInBuffer::~USBInBuffer()
|
||||
{
|
||||
if(transfer) {
|
||||
qDebug() << "Start cancellation";
|
||||
libusb_cancel_transfer(transfer);
|
||||
// wait for cancellation to complete
|
||||
mutex mtx;
|
||||
unique_lock<mutex> lck(mtx);
|
||||
cv.wait(lck);
|
||||
qDebug() << "Cancellation complete";
|
||||
}
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
void USBInBuffer::removeBytes(int handled_bytes)
|
||||
{
|
||||
if(!inCallback) {
|
||||
throw runtime_error("Removing of bytes is only allowed from within receive callback");
|
||||
}
|
||||
if(handled_bytes >= received_size) {
|
||||
received_size = 0;
|
||||
} else {
|
||||
// not removing all bytes, have to move remaining data to the beginning of the buffer
|
||||
memmove(buffer, &buffer[handled_bytes], received_size - handled_bytes);
|
||||
received_size -= handled_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
int USBInBuffer::getReceived() const
|
||||
{
|
||||
return received_size;
|
||||
}
|
||||
|
||||
void USBInBuffer::Callback(libusb_transfer *transfer)
|
||||
{
|
||||
switch(transfer->status) {
|
||||
case LIBUSB_TRANSFER_COMPLETED:
|
||||
received_size += transfer->actual_length;
|
||||
inCallback = true;
|
||||
emit DataReceived();
|
||||
inCallback = false;
|
||||
break;
|
||||
case LIBUSB_TRANSFER_ERROR:
|
||||
case LIBUSB_TRANSFER_NO_DEVICE:
|
||||
case LIBUSB_TRANSFER_OVERFLOW:
|
||||
case LIBUSB_TRANSFER_STALL:
|
||||
qCritical() << "LIBUSB_TRANSFER_ERROR";
|
||||
libusb_free_transfer(transfer);
|
||||
this->transfer = nullptr;
|
||||
emit TransferError();
|
||||
if(transmissionQueue.empty() || !m_connected) {
|
||||
// nothing more to transmit
|
||||
transmissionActive = false;
|
||||
return;
|
||||
break;
|
||||
case LIBUSB_TRANSFER_TIMED_OUT:
|
||||
// nothing to do
|
||||
break;
|
||||
case LIBUSB_TRANSFER_CANCELLED:
|
||||
// destructor called, do not resubmit
|
||||
libusb_free_transfer(transfer);
|
||||
this->transfer = nullptr;
|
||||
cv.notify_all();
|
||||
return;
|
||||
break;
|
||||
}
|
||||
// Resubmit the transfer
|
||||
transfer->buffer = &buffer[received_size];
|
||||
libusb_submit_transfer(transfer);
|
||||
transmissionActive = true;
|
||||
auto t = transmissionQueue.head();
|
||||
unsigned char buffer[1024];
|
||||
unsigned int length = Protocol::EncodePacket(t.packet, buffer, sizeof(buffer));
|
||||
if(!length) {
|
||||
qCritical() << "Failed to encode packet";
|
||||
transmissionFinished(TransmissionResult::InternalError);
|
||||
}
|
||||
int actual_length;
|
||||
auto ret = libusb_bulk_transfer(m_handle, EP_Data_Out_Addr, buffer, length, &actual_length, 0);
|
||||
if(ret < 0) {
|
||||
qCritical() << "Error sending data: "
|
||||
<< libusb_strerror((libusb_error) ret);
|
||||
transmissionFinished(TransmissionResult::InternalError);
|
||||
}
|
||||
transmissionTimer.start(t.timeout);
|
||||
}
|
||||
|
||||
void USBInBuffer::CallbackTrampoline(libusb_transfer *transfer)
|
||||
void Device::transmissionFinished(TransmissionResult result)
|
||||
{
|
||||
auto usb = (USBInBuffer*) transfer->user_data;
|
||||
usb->Callback(transfer);
|
||||
transmissionTimer.stop();
|
||||
// remove transmitted packet
|
||||
auto t = transmissionQueue.dequeue();
|
||||
if(t.callback) {
|
||||
t.callback(result);
|
||||
}
|
||||
startNextTransmission();
|
||||
}
|
||||
|
||||
uint8_t *USBInBuffer::getBuffer() const
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#ifndef DEVICE_H
|
||||
#ifndef DEVICE_H
|
||||
#define DEVICE_H
|
||||
|
||||
#include "../VNA_embedded/Application/Communication/Protocol.hpp"
|
||||
@ -8,6 +8,8 @@
|
||||
#include <QObject>
|
||||
#include <condition_variable>
|
||||
#include <set>
|
||||
#include <QQueue>
|
||||
#include <QTimer>
|
||||
|
||||
Q_DECLARE_METATYPE(Protocol::Datapoint);
|
||||
Q_DECLARE_METATYPE(Protocol::ManualStatus);
|
||||
@ -43,10 +45,17 @@ class Device : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum class TransmissionResult {
|
||||
Ack,
|
||||
Nack,
|
||||
Timeout,
|
||||
InternalError,
|
||||
};
|
||||
|
||||
// connect to a VNA device. If serial is specified only connecting to this device, otherwise to the first one found
|
||||
Device(QString serial = QString());
|
||||
~Device();
|
||||
bool SendPacket(Protocol::PacketInfo packet);
|
||||
bool SendPacket(Protocol::PacketInfo packet, std::function<void(TransmissionResult)> cb = nullptr, unsigned int timeout = 10);
|
||||
bool Configure(Protocol::SweepSettings settings);
|
||||
bool SetManual(Protocol::ManualControl manual);
|
||||
bool SendFirmwareChunk(Protocol::FirmwarePacket &fw);
|
||||
@ -68,6 +77,9 @@ signals:
|
||||
private slots:
|
||||
void ReceivedData();
|
||||
void ReceivedLog();
|
||||
void transmissionTimeout() {
|
||||
transmissionFinished(TransmissionResult::Timeout);
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr int VID = 0x0483;
|
||||
@ -86,6 +98,17 @@ private:
|
||||
USBInBuffer *dataBuffer;
|
||||
USBInBuffer *logBuffer;
|
||||
|
||||
using Transmission = struct {
|
||||
Protocol::PacketInfo packet;
|
||||
unsigned int timeout;
|
||||
std::function<void(TransmissionResult)> callback;
|
||||
};
|
||||
|
||||
QQueue<Transmission> transmissionQueue;
|
||||
void startNextTransmission();
|
||||
void transmissionFinished(TransmissionResult result);
|
||||
QTimer transmissionTimer;
|
||||
bool transmissionActive;
|
||||
|
||||
QString m_serial;
|
||||
bool m_connected;
|
||||
|
@ -29,7 +29,8 @@
|
||||
<string>To File</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="document-save"/>
|
||||
<iconset theme="document-save">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -39,7 +40,8 @@
|
||||
<string>Clear</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="edit-clear"/>
|
||||
<iconset theme="edit-clear">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -48,6 +50,9 @@
|
||||
<property name="text">
|
||||
<string>Autoscroll</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
25
Software/PC_Application/Generator/generator.cpp
Normal file
25
Software/PC_Application/Generator/generator.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include "generator.h"
|
||||
|
||||
Generator::Generator(AppWindow *window)
|
||||
: Mode(window, "Signal Generator")
|
||||
{
|
||||
central = new SignalgeneratorWidget();
|
||||
finalize(central);
|
||||
connect(central, &SignalgeneratorWidget::SettingsChanged, this, &Generator::updateDevice);
|
||||
}
|
||||
|
||||
void Generator::initializeDevice()
|
||||
{
|
||||
updateDevice();
|
||||
}
|
||||
|
||||
void Generator::updateDevice()
|
||||
{
|
||||
if(!window->getDevice()) {
|
||||
// can't updat if not connected
|
||||
return;
|
||||
}
|
||||
auto status = central->getDeviceStatus();
|
||||
// TODO comment in once status is filled with valid values
|
||||
// window->getDevice()->SetManual(status);
|
||||
}
|
18
Software/PC_Application/Generator/generator.h
Normal file
18
Software/PC_Application/Generator/generator.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef GENERATOR_H
|
||||
#define GENERATOR_H
|
||||
|
||||
#include "mode.h"
|
||||
#include "signalgenwidget.h"
|
||||
|
||||
class Generator : public Mode
|
||||
{
|
||||
public:
|
||||
Generator(AppWindow *window);
|
||||
void initializeDevice() override;
|
||||
private slots:
|
||||
void updateDevice();
|
||||
private:
|
||||
SignalgeneratorWidget *central;
|
||||
};
|
||||
|
||||
#endif // GENERATOR_H
|
@ -1,9 +1,9 @@
|
||||
#include "signalgenerator.h"
|
||||
#include "signalgenwidget.h"
|
||||
#include "ui_signalgenerator.h"
|
||||
|
||||
Signalgenerator::Signalgenerator(QWidget *parent) :
|
||||
SignalgeneratorWidget::SignalgeneratorWidget(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::Signalgenerator)
|
||||
ui(new Ui::SignalgeneratorWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->frequency->setUnit("Hz");
|
||||
@ -17,9 +17,9 @@ Signalgenerator::Signalgenerator(QWidget *parent) :
|
||||
newval = 6000000000;
|
||||
}
|
||||
ui->frequency->setValueQuiet(newval);
|
||||
SettingsChanged();
|
||||
emit SettingsChanged();
|
||||
});
|
||||
connect(ui->levelSpin, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &Signalgenerator::setLevel);
|
||||
connect(ui->levelSpin, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &SignalgeneratorWidget::setLevel);
|
||||
connect(ui->levelSlider, &QSlider::valueChanged, [=](int value) {
|
||||
setLevel((double) value / 100.0);
|
||||
});
|
||||
@ -27,22 +27,29 @@ Signalgenerator::Signalgenerator(QWidget *parent) :
|
||||
if(ui->EnablePort1->isChecked() && ui->EnablePort2->isChecked()) {
|
||||
ui->EnablePort2->setCheckState(Qt::CheckState::Unchecked);
|
||||
}
|
||||
SettingsChanged();
|
||||
emit SettingsChanged();
|
||||
});
|
||||
connect(ui->EnablePort2, &QCheckBox::clicked, [=](){
|
||||
if(ui->EnablePort1->isChecked() && ui->EnablePort2->isChecked()) {
|
||||
ui->EnablePort1->setCheckState(Qt::CheckState::Unchecked);
|
||||
}
|
||||
SettingsChanged();
|
||||
emit SettingsChanged();
|
||||
});
|
||||
}
|
||||
|
||||
Signalgenerator::~Signalgenerator()
|
||||
SignalgeneratorWidget::~SignalgeneratorWidget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void Signalgenerator::setLevel(double level)
|
||||
Protocol::ManualControl SignalgeneratorWidget::getDeviceStatus()
|
||||
{
|
||||
// TODO
|
||||
Protocol::ManualControl s = {};
|
||||
return s;
|
||||
}
|
||||
|
||||
void SignalgeneratorWidget::setLevel(double level)
|
||||
{
|
||||
// TODO constrain to frequency dependent levels
|
||||
ui->levelSpin->blockSignals(true);
|
||||
@ -54,7 +61,3 @@ void Signalgenerator::setLevel(double level)
|
||||
SettingsChanged();
|
||||
}
|
||||
|
||||
void Signalgenerator::SettingsChanged()
|
||||
{
|
||||
// TODO compile manual settings packet and send
|
||||
}
|
@ -5,25 +5,26 @@
|
||||
#include "Device/device.h"
|
||||
|
||||
namespace Ui {
|
||||
class Signalgenerator;
|
||||
class SignalgeneratorWidget;
|
||||
}
|
||||
|
||||
class Signalgenerator : public QWidget
|
||||
class SignalgeneratorWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Signalgenerator(QWidget *parent = nullptr);
|
||||
~Signalgenerator();
|
||||
explicit SignalgeneratorWidget(QWidget *parent = nullptr);
|
||||
~SignalgeneratorWidget();
|
||||
|
||||
Protocol::ManualControl getDeviceStatus();
|
||||
|
||||
signals:
|
||||
void NewManualState(Protocol::ManualStatus s);
|
||||
void SettingsChanged();
|
||||
|
||||
private slots:
|
||||
void setLevel(double level);
|
||||
private:
|
||||
void SettingsChanged();
|
||||
Ui::Signalgenerator *ui;
|
||||
Ui::SignalgeneratorWidget *ui;
|
||||
};
|
||||
|
||||
#endif // SIGNALGENERATOR_H
|
@ -1,84 +0,0 @@
|
||||
#include "menu.h"
|
||||
#include <QKeyEvent>
|
||||
#include "menuaction.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
Menu::Menu(QStackedLayout &layout, QString name)
|
||||
: name(name),
|
||||
m_containingLayout(layout)
|
||||
{
|
||||
m_layout = new QVBoxLayout;
|
||||
setLayout(m_layout);
|
||||
m_widgetCount = 0;
|
||||
setFixedSize(180, 800);
|
||||
parent = nullptr;
|
||||
layout.addWidget(this);
|
||||
if(name.length() > 0) {
|
||||
auto back = new MenuAction(name, MenuAction::ArrowType::Left);
|
||||
back->setStyleSheet("background-color:lightblue;");
|
||||
connect(back, &MenuAction::triggered, this, &Menu::leave);
|
||||
addItem(back);
|
||||
}
|
||||
}
|
||||
|
||||
void Menu::addItem(MenuItem *i)
|
||||
{
|
||||
if(m_widgetCount >= maxWidgets) {
|
||||
throw runtime_error("Menu already at maximum capacity");
|
||||
}
|
||||
m_layout->addWidget(i, 1);
|
||||
items.push_back(i);
|
||||
m_widgetCount++;
|
||||
}
|
||||
|
||||
void Menu::addMenu(Menu *m)
|
||||
{
|
||||
auto menuLabel = new MenuAction(m->name, MenuAction::ArrowType::Right);
|
||||
submenus.push_back(SubmenuEntry(menuLabel, m, m_widgetCount));
|
||||
connect(menuLabel, &MenuAction::triggered, [=]() {
|
||||
m->m_containingLayout.setCurrentWidget(m);
|
||||
});
|
||||
addItem(menuLabel);
|
||||
m->parent = this;
|
||||
}
|
||||
|
||||
void Menu::finalize()
|
||||
{
|
||||
m_layout->addStretch(maxWidgets - m_widgetCount);
|
||||
}
|
||||
|
||||
void Menu::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
// check if softkey pressed
|
||||
int index = -1;
|
||||
switch(event->key()) {
|
||||
case Qt::Key_F1: index = 0; break;
|
||||
case Qt::Key_F2: index = 1; break;
|
||||
case Qt::Key_F3: index = 2; break;
|
||||
case Qt::Key_F4: index = 3; break;
|
||||
case Qt::Key_F5: index = 4; break;
|
||||
case Qt::Key_F6: index = 5; break;
|
||||
case Qt::Key_F7: index = 6; break;
|
||||
case Qt::Key_F8: index = 7; break;
|
||||
}
|
||||
if(index >= 0) {
|
||||
auto w = m_layout->itemAt(index);
|
||||
w->widget()->setFocus();
|
||||
items[index]->userSelected();
|
||||
event->accept();
|
||||
} else if(event->key() == Qt::Key_Escape) {
|
||||
leave();
|
||||
event->accept();
|
||||
}
|
||||
}
|
||||
|
||||
void Menu::leave()
|
||||
{
|
||||
if(parent) {
|
||||
// got a parent menu
|
||||
parent->m_containingLayout.setCurrentWidget(parent);
|
||||
}
|
||||
}
|
||||
|
@ -1,41 +0,0 @@
|
||||
#ifndef MENU_H
|
||||
#define MENU_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QStackedLayout>
|
||||
#include "menuitem.h"
|
||||
#include "menuaction.h"
|
||||
|
||||
class Menu : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Menu(QStackedLayout &layout, QString name = QString());
|
||||
void addItem(MenuItem *i);
|
||||
void addMenu(Menu *m);
|
||||
void finalize();
|
||||
signals:
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
private:
|
||||
void leave();
|
||||
class SubmenuEntry {
|
||||
public:
|
||||
SubmenuEntry(MenuAction *label, Menu *menu, int index) :
|
||||
label(label), menu(menu), index(index){};
|
||||
MenuAction *label;
|
||||
Menu *menu;
|
||||
int index;
|
||||
};
|
||||
static constexpr int maxWidgets = 12;
|
||||
QVBoxLayout *m_layout;
|
||||
Menu *parent;
|
||||
const QString name;
|
||||
QStackedLayout &m_containingLayout;
|
||||
std::vector<SubmenuEntry> submenus;
|
||||
std::vector<MenuItem*> items;
|
||||
int m_widgetCount;
|
||||
};
|
||||
|
||||
#endif // MENU_H
|
@ -1,65 +0,0 @@
|
||||
#include "menuaction.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QStyle>
|
||||
#include <QSizePolicy>
|
||||
|
||||
MenuAction::MenuAction(const QString &l, MenuAction::ArrowType arrow)
|
||||
{
|
||||
subline = nullptr;
|
||||
auto label = new QLabel(l, this);
|
||||
label->setAlignment(Qt::AlignCenter);
|
||||
auto labelLayout = new QHBoxLayout();
|
||||
if(arrow == ArrowType::Left) {
|
||||
auto lIcon = new QLabel(this);
|
||||
lIcon->setPixmap(style()->standardIcon(QStyle::SP_ArrowLeft).pixmap(16));
|
||||
lIcon->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
labelLayout->addWidget(lIcon);
|
||||
}
|
||||
labelLayout->addWidget(label);
|
||||
if(arrow == ArrowType::Right) {
|
||||
auto lIcon = new QLabel(this);
|
||||
lIcon->setPixmap(style()->standardIcon(QStyle::SP_ArrowRight).pixmap(16));
|
||||
lIcon->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
labelLayout->addWidget(lIcon);
|
||||
}
|
||||
layout.addLayout(labelLayout);
|
||||
setLayout(&layout);
|
||||
}
|
||||
|
||||
void MenuAction::AddSubline(const QString &l)
|
||||
{
|
||||
if(!subline) {
|
||||
subline = new QLabel(this);
|
||||
subline->setAlignment(Qt::AlignCenter);
|
||||
layout.addWidget(subline);
|
||||
}
|
||||
QFont f( "Arial", 8);
|
||||
subline->setFont( f);
|
||||
subline->setText(l);
|
||||
}
|
||||
|
||||
void MenuAction::RemoveSubline()
|
||||
{
|
||||
if(subline) {
|
||||
layout.removeWidget(subline);
|
||||
delete subline;
|
||||
subline = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void MenuAction::userSelected()
|
||||
{
|
||||
emit triggered();
|
||||
}
|
||||
|
||||
void MenuAction::mouseReleaseEvent(QMouseEvent *me)
|
||||
{
|
||||
setFrameStyle(QFrame::Raised | QFrame::Panel);
|
||||
MenuItem::mouseReleaseEvent(me);
|
||||
}
|
||||
|
||||
void MenuAction::mousePressEvent(QMouseEvent *)
|
||||
{
|
||||
setFrameStyle(QFrame::Sunken | QFrame::Panel);
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
#ifndef MENULABEL_H
|
||||
#define MENULABEL_H
|
||||
|
||||
#include "menuitem.h"
|
||||
#include <QVBoxLayout>
|
||||
#include <QLabel>
|
||||
|
||||
class MenuAction : public MenuItem
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum class ArrowType {
|
||||
None,
|
||||
Left,
|
||||
Right,
|
||||
};
|
||||
|
||||
MenuAction(const QString &l, ArrowType arrow = ArrowType::None);
|
||||
void AddSubline(const QString &l);
|
||||
void RemoveSubline();
|
||||
signals:
|
||||
void triggered();
|
||||
public slots:
|
||||
void userSelected() override;
|
||||
private:
|
||||
QVBoxLayout layout;
|
||||
QLabel *subline;
|
||||
protected:
|
||||
void mouseReleaseEvent(QMouseEvent *me) override;
|
||||
void mousePressEvent(QMouseEvent *me) override;
|
||||
};
|
||||
|
||||
#endif // MENULABEL_H
|
@ -1,36 +0,0 @@
|
||||
#include "menubool.h"
|
||||
|
||||
#include <QLabel>
|
||||
|
||||
MenuBool::MenuBool(QString name, bool defaultValue)
|
||||
{
|
||||
auto label = new QLabel(name, this);
|
||||
label->setAlignment(Qt::AlignCenter);
|
||||
layout.addWidget(label);
|
||||
sw = new ToggleSwitch(this, defaultValue);
|
||||
layout.addWidget(sw);
|
||||
setLayout(&layout);
|
||||
connect(sw, &ToggleSwitch::toggled, this, &MenuBool::valueChanged);
|
||||
sw->setFocusPolicy(Qt::NoFocus);
|
||||
}
|
||||
|
||||
void MenuBool::setValue(bool value)
|
||||
{
|
||||
sw->setState(value);
|
||||
}
|
||||
|
||||
void MenuBool::userSelected()
|
||||
{
|
||||
sw->toggle();
|
||||
}
|
||||
|
||||
void MenuBool::mouseReleaseEvent(QMouseEvent *me)
|
||||
{
|
||||
setFrameStyle(QFrame::Raised | QFrame::Panel);
|
||||
MenuItem::mouseReleaseEvent(me);
|
||||
}
|
||||
|
||||
void MenuBool::mousePressEvent(QMouseEvent *)
|
||||
{
|
||||
setFrameStyle(QFrame::Sunken | QFrame::Panel);
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
#ifndef MENUBOOL_H
|
||||
#define MENUBOOL_H
|
||||
|
||||
#include <QObject>
|
||||
#include "menuitem.h"
|
||||
#include <QVBoxLayout>
|
||||
#include "CustomWidgets/toggleswitch.h"
|
||||
|
||||
class MenuBool : public MenuItem
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MenuBool(QString name, bool defaultValue = false);
|
||||
|
||||
signals:
|
||||
void valueChanged(bool value);
|
||||
public slots:
|
||||
void setValue(bool value);
|
||||
void userSelected() override;
|
||||
protected:
|
||||
void mouseReleaseEvent(QMouseEvent *me) override;
|
||||
void mousePressEvent(QMouseEvent *me) override;
|
||||
private:
|
||||
QVBoxLayout layout;
|
||||
ToggleSwitch *sw;
|
||||
};
|
||||
|
||||
#endif // MENUBOOL_H
|
@ -1,17 +0,0 @@
|
||||
#include "menuitem.h"
|
||||
|
||||
#include <QMouseEvent>
|
||||
|
||||
MenuItem::MenuItem() : QFrame()
|
||||
{
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
//setStyleSheet("*:focus {background: lightblue}");
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
setFrameStyle(QFrame::Raised | QFrame::Panel);
|
||||
}
|
||||
|
||||
void MenuItem::mouseReleaseEvent(QMouseEvent *me)
|
||||
{
|
||||
userSelected();
|
||||
me->accept();
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
#ifndef MENUITEM_H
|
||||
#define MENUITEM_H
|
||||
|
||||
#include <QFrame>
|
||||
|
||||
class MenuItem : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MenuItem();
|
||||
|
||||
public slots:
|
||||
virtual void userSelected(){};
|
||||
|
||||
protected:
|
||||
void mouseReleaseEvent(QMouseEvent *me) override;
|
||||
|
||||
};
|
||||
|
||||
#endif // MENUITEM_H
|
@ -1,46 +0,0 @@
|
||||
#include "menuvalue.h"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <math.h>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include "valueinput.h"
|
||||
#include <QMouseEvent>
|
||||
#include "unit.h"
|
||||
#include <QDoubleValidator>
|
||||
|
||||
using namespace std;
|
||||
|
||||
MenuValue::MenuValue(QString name, double defaultValue, QString unit, QString prefixes, int precision)
|
||||
: name(name)
|
||||
{
|
||||
if(prefixes.indexOf(' ') < 0) {
|
||||
throw runtime_error("Prefix string must contain space");
|
||||
}
|
||||
auto layout = new QVBoxLayout;
|
||||
auto label = new QLabel(name, this);
|
||||
label->setAlignment(Qt::AlignCenter);
|
||||
layout->addWidget(label);
|
||||
lvalue = new SIUnitEdit(unit, prefixes, precision);
|
||||
// pass on signal
|
||||
connect(lvalue, &SIUnitEdit::valueChanged, this, &MenuValue::valueChanged);
|
||||
layout->addWidget(lvalue);
|
||||
setValue(defaultValue);
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
void MenuValue::setValue(double value)
|
||||
{
|
||||
lvalue->setValue(value);
|
||||
}
|
||||
|
||||
void MenuValue::setValueQuiet(double value)
|
||||
{
|
||||
lvalue->setValueQuiet(value);
|
||||
}
|
||||
|
||||
void MenuValue::userSelected()
|
||||
{
|
||||
lvalue->setFocus();
|
||||
//startInputDialog();
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
#ifndef MENUVALUE_H
|
||||
#define MENUVALUE_H
|
||||
|
||||
#include "menuitem.h"
|
||||
#include <QLabel>
|
||||
#include <CustomWidgets/siunitedit.h>
|
||||
|
||||
class MenuValue : public MenuItem
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MenuValue(QString name, double defaultValue = 0.0, QString unit = QString(), QString prefixes = " ", int precision = 0);
|
||||
|
||||
signals:
|
||||
void valueChanged(double value);
|
||||
public slots:
|
||||
void setValue(double value);
|
||||
// same as setValue, except that no valueChanged signal is emitted
|
||||
void setValueQuiet(double value);
|
||||
void userSelected() override;
|
||||
private:
|
||||
SIUnitEdit *lvalue;
|
||||
const QString name;
|
||||
};
|
||||
|
||||
#endif // MENUVALUE_H
|
File diff suppressed because it is too large
Load Diff
89
Software/PC_Application/VNA/vna.h
Normal file
89
Software/PC_Application/VNA/vna.h
Normal file
@ -0,0 +1,89 @@
|
||||
#ifndef VNA_H
|
||||
#define VNA_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
#include "appwindow.h"
|
||||
#include "mode.h"
|
||||
#include "CustomWidgets/tilewidget.h"
|
||||
|
||||
class VNA : public Mode
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
VNA(AppWindow *window);
|
||||
|
||||
void deactivate() override;
|
||||
void initializeDevice() override;
|
||||
private slots:
|
||||
void NewDatapoint(Protocol::Datapoint d);
|
||||
void StartImpedanceMatching();
|
||||
// Sweep control
|
||||
void SetStartFreq(double freq);
|
||||
void SetStopFreq(double freq);
|
||||
void SetCenterFreq(double freq);
|
||||
void SetSpan(double span);
|
||||
void SetFullSpan();
|
||||
void SpanZoomIn();
|
||||
void SpanZoomOut();
|
||||
// Acquisition control
|
||||
void SetSourceLevel(double level);
|
||||
void SetPoints(unsigned int points);
|
||||
void SetIFBandwidth(double bandwidth);
|
||||
void SetAveraging(unsigned int averages);
|
||||
// Calibration
|
||||
void DisableCalibration(bool force = false);
|
||||
void ApplyCalibration(Calibration::Type type);
|
||||
void StartCalibrationMeasurement(Calibration::Measurement m);
|
||||
|
||||
signals:
|
||||
void CalibrationMeasurementComplete(Calibration::Measurement m);
|
||||
|
||||
private:
|
||||
void UpdateStatusPanel();
|
||||
void SettingsChanged();
|
||||
void ConstrainAndUpdateFrequencies();
|
||||
void LoadSweepSettings();
|
||||
void StoreSweepSettings();
|
||||
|
||||
Preferences pref;
|
||||
|
||||
QActionGroup *deviceActionGroup;
|
||||
Protocol::SweepSettings settings;
|
||||
unsigned int averages;
|
||||
TraceModel traceModel;
|
||||
TraceMarkerModel *markerModel;
|
||||
Averaging average;
|
||||
|
||||
// Calibration
|
||||
Calibration cal;
|
||||
bool calValid;
|
||||
Calibration::Measurement calMeasurement;
|
||||
bool calMeasuring;
|
||||
bool calWaitFirst;
|
||||
QProgressDialog calDialog;
|
||||
|
||||
// Status Labels
|
||||
QLabel *lStart, *lCenter, *lStop, *lSpan, *lPoints, *lBandwidth;
|
||||
QLabel *lCalibration;
|
||||
QLabel *lAverages;
|
||||
|
||||
TileWidget *central;
|
||||
|
||||
signals:
|
||||
void dataChanged();
|
||||
void startFreqChanged(double freq);
|
||||
void stopFreqChanged(double freq);
|
||||
void centerFreqChanged(double freq);
|
||||
void spanChanged(double span);
|
||||
|
||||
void sourceLevelChanged(double level);
|
||||
void pointsChanged(unsigned int points);
|
||||
void IFBandwidthChanged(double bandwidth);
|
||||
void averagingChanged(unsigned int averages);
|
||||
|
||||
void CalibrationDisabled();
|
||||
void CalibrationApplied(Calibration::Type type);
|
||||
};
|
||||
|
||||
#endif // VNA_H
|
316
Software/PC_Application/appwindow.cpp
Normal file
316
Software/PC_Application/appwindow.cpp
Normal file
@ -0,0 +1,316 @@
|
||||
#include "appwindow.h"
|
||||
#include <QGridLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <math.h>
|
||||
#include <QToolBar>
|
||||
#include <QMenu>
|
||||
#include <QToolButton>
|
||||
#include <QActionGroup>
|
||||
#include <QSpinBox>
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QSettings>
|
||||
#include <algorithm>
|
||||
#include <QMessageBox>
|
||||
#include <QFileDialog>
|
||||
#include <QFile>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <QDateTime>
|
||||
#include "unit.h"
|
||||
#include "CustomWidgets/toggleswitch.h"
|
||||
#include "Device/manualcontroldialog.h"
|
||||
#include "Traces/tracemodel.h"
|
||||
#include "Traces/tracewidget.h"
|
||||
#include "Traces/tracesmithchart.h"
|
||||
#include "Traces/tracebodeplot.h"
|
||||
#include "Traces/traceimportdialog.h"
|
||||
#include "CustomWidgets/tilewidget.h"
|
||||
#include "CustomWidgets/siunitedit.h"
|
||||
#include <QDockWidget>
|
||||
#include "Traces/markerwidget.h"
|
||||
#include "Tools/impedancematchdialog.h"
|
||||
#include "Calibration/calibrationtracedialog.h"
|
||||
#include "ui_main.h"
|
||||
#include "Device/firmwareupdatedialog.h"
|
||||
#include "preferences.h"
|
||||
#include "Generator/signalgenwidget.h"
|
||||
#include <QDesktopWidget>
|
||||
#include <QApplication>
|
||||
#include <QActionGroup>
|
||||
#include <mode.h>
|
||||
#include "VNA/vna.h"
|
||||
#include "Generator/generator.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
AppWindow::AppWindow(QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
, deviceActionGroup(new QActionGroup(this))
|
||||
, ui(new Ui::MainWindow)
|
||||
{
|
||||
QCoreApplication::setOrganizationName("VNA");
|
||||
QCoreApplication::setApplicationName("Application");
|
||||
|
||||
pref.load();
|
||||
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);
|
||||
ui->statusbar->addWidget(div1);
|
||||
ui->statusbar->addWidget(&lDeviceInfo);
|
||||
ui->statusbar->addWidget(new QLabel, 1);
|
||||
//ui->statusbar->setStyleSheet("QStatusBar::item { border: 1px solid black; };");
|
||||
|
||||
CreateToolbars();
|
||||
auto logDock = new QDockWidget("Device Log");
|
||||
logDock->setWidget(&deviceLog);
|
||||
addDockWidget(Qt::BottomDockWidgetArea, logDock);
|
||||
|
||||
// fill toolbar/dock menu
|
||||
ui->menuDocks->clear();
|
||||
for(auto d : findChildren<QDockWidget*>()) {
|
||||
ui->menuDocks->addAction(d->toggleViewAction());
|
||||
}
|
||||
ui->menuToolbars->clear();
|
||||
for(auto t : findChildren<QToolBar*>()) {
|
||||
ui->menuToolbars->addAction(t->toggleViewAction());
|
||||
}
|
||||
|
||||
// Create GUI modes
|
||||
central = new QStackedWidget;
|
||||
setCentralWidget(central);
|
||||
auto vna = new VNA(this);
|
||||
new Generator(this);
|
||||
// auto signalGenWidget = new Signalgenerator;
|
||||
// modeSGen = new GUIMode(this, "Signal Generator", signalGenWidget);
|
||||
|
||||
// UI connections
|
||||
connect(ui->actionUpdate_Device_List, &QAction::triggered, this, &AppWindow::UpdateDeviceList);
|
||||
connect(ui->actionDisconnect, &QAction::triggered, this, &AppWindow::DisconnectDevice);
|
||||
connect(ui->actionQuit, &QAction::triggered, this, &AppWindow::close);
|
||||
connect(ui->actionManual_Control, &QAction::triggered, this, &AppWindow::StartManualControl);
|
||||
connect(ui->actionFirmware_Update, &QAction::triggered, [=](){
|
||||
if(device) {
|
||||
auto fw_update = new FirmwareUpdateDialog(device);
|
||||
fw_update->exec();
|
||||
}
|
||||
});
|
||||
connect(ui->actionPreferences, &QAction::triggered, [=](){
|
||||
pref.edit();
|
||||
});
|
||||
|
||||
setWindowTitle("VNA");
|
||||
|
||||
setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
|
||||
setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
|
||||
setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
|
||||
setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
|
||||
|
||||
{
|
||||
QSettings settings;
|
||||
restoreGeometry(settings.value("geometry").toByteArray());
|
||||
}
|
||||
|
||||
// Set ObjectName for toolbars and docks
|
||||
for(auto d : findChildren<QDockWidget*>()) {
|
||||
d->setObjectName(d->windowTitle());
|
||||
}
|
||||
for(auto t : findChildren<QToolBar*>()) {
|
||||
t->setObjectName(t->windowTitle());
|
||||
}
|
||||
|
||||
// Set default mode
|
||||
vna->activate();
|
||||
|
||||
qRegisterMetaType<Protocol::Datapoint>("Datapoint");
|
||||
|
||||
// List available devices
|
||||
if(UpdateDeviceList() && pref.Startup.ConnectToFirstDevice) {
|
||||
// at least one device available
|
||||
ConnectToDevice();
|
||||
}
|
||||
}
|
||||
|
||||
void AppWindow::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
QSettings settings;
|
||||
settings.setValue("geometry", saveGeometry());
|
||||
// deactivate currently used mode (stores mode state in settings)
|
||||
if(Mode::getActiveMode()) {
|
||||
Mode::getActiveMode()->deactivate();
|
||||
}
|
||||
pref.store();
|
||||
QMainWindow::closeEvent(event);
|
||||
}
|
||||
|
||||
void AppWindow::ConnectToDevice(QString serial)
|
||||
{
|
||||
if(device) {
|
||||
DisconnectDevice();
|
||||
}
|
||||
try {
|
||||
qDebug() << "Attempting to connect to device...";
|
||||
device = new Device(serial);
|
||||
lConnectionStatus.setText("Connected to " + device->serial());
|
||||
qInfo() << "Connected to " << device->serial();
|
||||
lDeviceInfo.setText(device->getLastDeviceInfoString());
|
||||
connect(device, &Device::LogLineReceived, &deviceLog, &DeviceLog::addLine);
|
||||
connect(device, &Device::ConnectionLost, this, &AppWindow::DeviceConnectionLost);
|
||||
connect(device, &Device::DeviceInfoUpdated, [this]() {
|
||||
lDeviceInfo.setText(device->getLastDeviceInfoString());
|
||||
});
|
||||
ui->actionDisconnect->setEnabled(true);
|
||||
ui->actionManual_Control->setEnabled(true);
|
||||
ui->menuDefault_Calibration->setEnabled(true);
|
||||
ui->actionFirmware_Update->setEnabled(true);
|
||||
|
||||
Mode::getActiveMode()->initializeDevice();
|
||||
UpdateReference();
|
||||
} catch (const runtime_error e) {
|
||||
DisconnectDevice();
|
||||
UpdateDeviceList();
|
||||
}
|
||||
}
|
||||
|
||||
void AppWindow::DisconnectDevice()
|
||||
{
|
||||
if(device) {
|
||||
delete device;
|
||||
device = nullptr;
|
||||
}
|
||||
ui->actionDisconnect->setEnabled(false);
|
||||
ui->actionManual_Control->setEnabled(false);
|
||||
ui->menuDefault_Calibration->setEnabled(false);
|
||||
ui->actionFirmware_Update->setEnabled(false);
|
||||
if(deviceActionGroup->checkedAction()) {
|
||||
deviceActionGroup->checkedAction()->setChecked(false);
|
||||
}
|
||||
lConnectionStatus.setText("No device connected");
|
||||
lDeviceInfo.setText("No device information available yet");
|
||||
}
|
||||
|
||||
void AppWindow::DeviceConnectionLost()
|
||||
{
|
||||
DisconnectDevice();
|
||||
QMessageBox::warning(this, "Disconnected", "The USB connection to the device has been lost");
|
||||
UpdateDeviceList();
|
||||
}
|
||||
|
||||
void AppWindow::CreateToolbars()
|
||||
{
|
||||
// Reference toolbar
|
||||
auto tb_reference = new QToolBar("Reference", this);
|
||||
tb_reference->addWidget(new QLabel("Ref:"));
|
||||
toolbars.reference.type = new QComboBox();
|
||||
toolbars.reference.type->addItem("Int");
|
||||
toolbars.reference.type->addItem("Ext");
|
||||
toolbars.reference.automatic = new QCheckBox("Auto");
|
||||
connect(toolbars.reference.automatic, &QCheckBox::clicked, [this](bool checked) {
|
||||
toolbars.reference.type->setEnabled(!checked);
|
||||
UpdateReference();
|
||||
});
|
||||
// toolbars.reference.automatic->setChecked(true);
|
||||
tb_reference->addWidget(toolbars.reference.type);
|
||||
tb_reference->addWidget(toolbars.reference.automatic);
|
||||
tb_reference->addSeparator();
|
||||
tb_reference->addWidget(new QLabel("Ref out:"));
|
||||
toolbars.reference.outputEnabled = new QCheckBox();
|
||||
toolbars.reference.outFreq = new QComboBox();
|
||||
toolbars.reference.outFreq->addItem("10 MHz");
|
||||
toolbars.reference.outFreq->addItem("100 MHz");
|
||||
tb_reference->addWidget(toolbars.reference.outputEnabled);
|
||||
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.outputEnabled, &QCheckBox::clicked, this, &AppWindow::UpdateReference);
|
||||
|
||||
addToolBar(tb_reference);
|
||||
}
|
||||
|
||||
int AppWindow::UpdateDeviceList()
|
||||
{
|
||||
ui->menuConnect_to->clear();
|
||||
auto devices = Device::GetDevices();
|
||||
if(devices.size()) {
|
||||
for(auto d : devices) {
|
||||
auto connectAction = ui->menuConnect_to->addAction(d);
|
||||
deviceActionGroup->addAction(connectAction);
|
||||
connectAction->setCheckable(true);
|
||||
if(device && d == device->serial()) {
|
||||
connectAction->setChecked(true);
|
||||
}
|
||||
connect(connectAction, &QAction::triggered, [this, connectAction, d]() {
|
||||
ConnectToDevice(d);
|
||||
if(device) {
|
||||
// connectAction might have been unchecked if it was a reconnect to the already connected device
|
||||
connectAction->setChecked(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
ui->menuConnect_to->setEnabled(true);
|
||||
} else {
|
||||
// no devices available, disable connection option
|
||||
ui->menuConnect_to->setEnabled(false);
|
||||
}
|
||||
return devices.size();
|
||||
}
|
||||
|
||||
void AppWindow::StartManualControl()
|
||||
{
|
||||
auto control = new ManualControlDialog(*device, this);
|
||||
connect(control, &QDialog::finished, [=](){
|
||||
Mode::getActiveMode()->initializeDevice();
|
||||
});
|
||||
control->show();
|
||||
}
|
||||
|
||||
void AppWindow::UpdateReference()
|
||||
{
|
||||
if(!device) {
|
||||
// can't update without a device connected
|
||||
return;
|
||||
}
|
||||
Protocol::ReferenceSettings s = {};
|
||||
if(toolbars.reference.automatic->isChecked()) {
|
||||
s.AutomaticSwitch = 1;
|
||||
}
|
||||
if(toolbars.reference.type->currentText()=="Ext") {
|
||||
s.UseExternalRef = 1;
|
||||
}
|
||||
if(toolbars.reference.outputEnabled->isChecked()) {
|
||||
switch(toolbars.reference.outFreq->currentIndex()) {
|
||||
case 0:
|
||||
s.ExtRefOuputFreq = 10000000;
|
||||
break;
|
||||
case 1:
|
||||
s.ExtRefOuputFreq = 100000000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Protocol::PacketInfo p;
|
||||
p.type = Protocol::PacketType::Reference;
|
||||
p.reference = s;
|
||||
device->SendPacket(p);
|
||||
}
|
||||
|
||||
Device *AppWindow::getDevice() const
|
||||
{
|
||||
return device;
|
||||
}
|
||||
|
||||
QStackedWidget *AppWindow::getCentral() const
|
||||
{
|
||||
return central;
|
||||
}
|
||||
|
||||
Ui::MainWindow *AppWindow::getUi() const
|
||||
{
|
||||
return ui;
|
||||
}
|
75
Software/PC_Application/appwindow.h
Normal file
75
Software/PC_Application/appwindow.h
Normal file
@ -0,0 +1,75 @@
|
||||
#ifndef APPWINDOW_H
|
||||
#define APPWINDOW_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QMainWindow>
|
||||
#include <QGridLayout>
|
||||
#include <QComboBox>
|
||||
#include <QStackedWidget>
|
||||
#include "Device/device.h"
|
||||
#include "Traces/traceplot.h"
|
||||
#include "Calibration/calibration.h"
|
||||
#include <QProgressDialog>
|
||||
#include "Traces/tracemodel.h"
|
||||
#include "Traces/tracemarkermodel.h"
|
||||
#include "averaging.h"
|
||||
#include "Device/devicelog.h"
|
||||
#include "preferences.h"
|
||||
#include <QButtonGroup>
|
||||
#include <QCheckBox>
|
||||
#include <QLabel>
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class AppWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AppWindow(QWidget *parent = nullptr);
|
||||
|
||||
|
||||
Ui::MainWindow *getUi() const;
|
||||
QStackedWidget *getCentral() const;
|
||||
Device *getDevice() const;
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
private slots:
|
||||
void ConnectToDevice(QString serial = QString());
|
||||
void DisconnectDevice();
|
||||
int UpdateDeviceList();
|
||||
void StartManualControl();
|
||||
void UpdateReference();
|
||||
|
||||
private:
|
||||
void DeviceConnectionLost();
|
||||
void CreateToolbars();
|
||||
|
||||
QStackedWidget *central;
|
||||
|
||||
struct {
|
||||
struct {
|
||||
QComboBox *type;
|
||||
QCheckBox *automatic;
|
||||
QCheckBox *outputEnabled;
|
||||
QComboBox *outFreq;
|
||||
} reference;
|
||||
} toolbars;
|
||||
|
||||
Preferences pref;
|
||||
|
||||
Device *device;
|
||||
DeviceLog deviceLog;
|
||||
QString deviceSerial;
|
||||
QActionGroup *deviceActionGroup;
|
||||
|
||||
// Status bar widgets
|
||||
QLabel lConnectionStatus;
|
||||
QLabel lDeviceInfo;
|
||||
|
||||
Ui::MainWindow *ui;
|
||||
};
|
||||
|
||||
#endif // VNA_H
|
@ -2,12 +2,7 @@
|
||||
|
||||
#include <unistd.h>
|
||||
#include <QtWidgets/QApplication>
|
||||
#include "vna.h"
|
||||
#include "valueinput.h"
|
||||
|
||||
#include "Menu/menu.h"
|
||||
#include "Menu/menuaction.h"
|
||||
#include "Menu/menuvalue.h"
|
||||
#include "appwindow.h"
|
||||
|
||||
#include "Calibration/calkit.h"
|
||||
#include "touchstone.h"
|
||||
@ -15,7 +10,7 @@
|
||||
#include <complex>
|
||||
int main(int argc, char *argv[]) {
|
||||
QApplication a(argc, argv);
|
||||
VNA vna;
|
||||
AppWindow vna;
|
||||
vna.resize(1280, 800);
|
||||
vna.show();
|
||||
a.exec();
|
||||
|
@ -60,12 +60,6 @@
|
||||
<addaction name="menuDefault_Calibration"/>
|
||||
<addaction name="actionFirmware_Update"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuTools">
|
||||
<property name="title">
|
||||
<string>Tools</string>
|
||||
</property>
|
||||
<addaction name="actionImpedance_Matching"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuWindow">
|
||||
<property name="title">
|
||||
<string>Window</string>
|
||||
@ -86,20 +80,8 @@
|
||||
<addaction name="menuToolbars"/>
|
||||
<addaction name="actionPreferences"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuCalibration">
|
||||
<property name="title">
|
||||
<string>Calibration</string>
|
||||
</property>
|
||||
<addaction name="actionCalDisabled"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionTracedata"/>
|
||||
<addaction name="actionImport_error_terms_as_traces"/>
|
||||
<addaction name="actionEdit_Calibration_Kit"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuDevice"/>
|
||||
<addaction name="menuCalibration"/>
|
||||
<addaction name="menuTools"/>
|
||||
<addaction name="menuWindow"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
@ -137,11 +119,6 @@
|
||||
<string>Dummy</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionImpedance_Matching">
|
||||
<property name="text">
|
||||
<string>Impedance Matching</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionManual_Control">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
@ -160,32 +137,6 @@
|
||||
<string>Dummy</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCalDisabled">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Disabled</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTracedata">
|
||||
<property name="text">
|
||||
<string>Calibration Data</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEdit_Calibration_Kit">
|
||||
<property name="text">
|
||||
<string>Edit Calibration Kit</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionImport_error_terms_as_traces">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Import error terms as traces</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAssignDefaultCal">
|
||||
<property name="text">
|
||||
<string>Assign...</string>
|
||||
@ -212,11 +163,6 @@
|
||||
<string>Preferences</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDummy_4">
|
||||
<property name="text">
|
||||
<string>Dummy</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
151
Software/PC_Application/mode.cpp
Normal file
151
Software/PC_Application/mode.cpp
Normal file
@ -0,0 +1,151 @@
|
||||
#include "mode.h"
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QSettings>
|
||||
#include "ui_main.h"
|
||||
|
||||
Mode* Mode::activeMode = nullptr;
|
||||
QWidget* Mode::cornerWidget = nullptr;
|
||||
QButtonGroup* Mode::modeButtonGroup = nullptr;
|
||||
|
||||
Mode::Mode(AppWindow *window, QString name)
|
||||
: window(window),
|
||||
name(name),
|
||||
central(nullptr)
|
||||
{
|
||||
// Create mode switch button
|
||||
auto modeSwitch = new QPushButton(name);
|
||||
modeSwitch->setCheckable(true);
|
||||
modeSwitch->setMaximumHeight(window->getUi()->menubar->height());
|
||||
if(!cornerWidget) {
|
||||
// this is the first created mode, initialize corner widget and set this mode as active
|
||||
modeSwitch->setChecked(true);
|
||||
cornerWidget = new QWidget;
|
||||
cornerWidget->setLayout(new QHBoxLayout);
|
||||
cornerWidget->layout()->setSpacing(0);
|
||||
cornerWidget->layout()->setMargin(0);
|
||||
cornerWidget->layout()->setContentsMargins(0,0,0,0);
|
||||
window->menuBar()->setCornerWidget(cornerWidget);
|
||||
modeButtonGroup = new QButtonGroup;
|
||||
window->getUi()->menubar->setMaximumHeight(window->getUi()->menubar->height());
|
||||
}
|
||||
cornerWidget->layout()->addWidget(modeSwitch);
|
||||
modeButtonGroup->addButton(modeSwitch);
|
||||
|
||||
connect(modeSwitch, &QPushButton::clicked, [=](){
|
||||
activate();
|
||||
});
|
||||
}
|
||||
|
||||
void Mode::activate()
|
||||
{
|
||||
if(activeMode == this) {
|
||||
// already active;
|
||||
return;
|
||||
} else if(activeMode) {
|
||||
activeMode->deactivate();
|
||||
}
|
||||
|
||||
// show all mode specific GUI elements
|
||||
for(auto t : toolbars) {
|
||||
t->show();
|
||||
window->getUi()->menuToolbars->addAction(t->toggleViewAction());
|
||||
}
|
||||
for(auto d : docks) {
|
||||
d->show();
|
||||
window->getUi()->menuDocks->addAction(d->toggleViewAction());
|
||||
}
|
||||
for(auto a : actions) {
|
||||
a->setVisible(true);
|
||||
}
|
||||
|
||||
QSettings settings;
|
||||
window->getCentral()->setCurrentWidget(central);
|
||||
|
||||
// restore dock and toolbar positions
|
||||
// window->restoreGeometry(settings.value("geometry_"+name).toByteArray());
|
||||
window->restoreState(settings.value("windowState_"+name).toByteArray());
|
||||
|
||||
// restore visibility of toolbars and docks
|
||||
// window->getUi()->menuDocks->clear();
|
||||
for(auto d : window->findChildren<QDockWidget*>()) {
|
||||
// window->getUi()->menuDocks->addAction(d->toggleViewAction());
|
||||
bool hidden = settings.value("dock_"+name+"_"+d->windowTitle(), d->isHidden()).toBool();
|
||||
if(hidden) {
|
||||
d->hide();
|
||||
} else {
|
||||
d->show();
|
||||
}
|
||||
}
|
||||
// window->getUi()->menuToolbars->clear();
|
||||
for(auto t : window->findChildren<QToolBar*>()) {
|
||||
// window->getUi()->menuToolbars->addAction(t->toggleViewAction());
|
||||
bool hidden = settings.value("toolbar_"+name+"_"+t->windowTitle(), t->isHidden()).toBool();
|
||||
if(hidden) {
|
||||
t->hide();
|
||||
} else {
|
||||
t->show();
|
||||
}
|
||||
}
|
||||
|
||||
activeMode = this;
|
||||
|
||||
if(window->getDevice()) {
|
||||
initializeDevice();
|
||||
}
|
||||
}
|
||||
|
||||
void Mode::deactivate()
|
||||
{
|
||||
QSettings settings;
|
||||
// save dock/toolbar visibility
|
||||
for(auto d : window->findChildren<QDockWidget*>()) {
|
||||
settings.setValue("dock_"+name+"_"+d->windowTitle(), d->isHidden());
|
||||
}
|
||||
for(auto t : window->findChildren<QToolBar*>()) {
|
||||
settings.setValue("toolbar_"+name+"_"+t->windowTitle(), t->isHidden());
|
||||
}
|
||||
// settings.setValue("geometry_"+name, window->saveGeometry());
|
||||
settings.setValue("windowState_"+name, window->saveState());
|
||||
|
||||
// hide all mode specific GUI elements
|
||||
for(auto t : toolbars) {
|
||||
t->hide();
|
||||
window->getUi()->menuToolbars->removeAction(t->toggleViewAction());
|
||||
}
|
||||
for(auto d : docks) {
|
||||
d->hide();
|
||||
window->getUi()->menuDocks->removeAction(d->toggleViewAction());
|
||||
}
|
||||
for(auto a : actions) {
|
||||
a->setVisible(false);
|
||||
}
|
||||
|
||||
activeMode = nullptr;
|
||||
}
|
||||
|
||||
Mode *Mode::getActiveMode()
|
||||
{
|
||||
return activeMode;
|
||||
}
|
||||
|
||||
void Mode::finalize(QWidget *centralWidget)
|
||||
{
|
||||
central = centralWidget;
|
||||
window->getCentral()->addWidget(central);
|
||||
// hide all mode specific GUI elements
|
||||
for(auto t : toolbars) {
|
||||
t->hide();
|
||||
}
|
||||
for(auto d : docks) {
|
||||
d->hide();
|
||||
}
|
||||
for(auto a : actions) {
|
||||
a->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
QString Mode::getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
39
Software/PC_Application/mode.h
Normal file
39
Software/PC_Application/mode.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef MODE_H
|
||||
#define MODE_H
|
||||
|
||||
#include <QString>
|
||||
#include <QWidget>
|
||||
#include <QButtonGroup>
|
||||
#include <QToolBar>
|
||||
#include <QDockWidget>
|
||||
#include <set>
|
||||
#include "appwindow.h"
|
||||
|
||||
class Mode : public QWidget
|
||||
{
|
||||
public:
|
||||
Mode(AppWindow *window, QString name);
|
||||
virtual void activate();
|
||||
virtual void deactivate();
|
||||
QString getName() const;
|
||||
static Mode *getActiveMode();
|
||||
|
||||
virtual void initializeDevice() = 0;
|
||||
|
||||
protected:
|
||||
// call once the derived class is fully initialized
|
||||
void finalize(QWidget *centralWidget);
|
||||
AppWindow *window;
|
||||
std::set<QAction*> actions;
|
||||
std::set<QToolBar*> toolbars;
|
||||
std::set<QDockWidget*> docks;
|
||||
|
||||
private:
|
||||
static Mode *activeMode;
|
||||
static QWidget *cornerWidget;
|
||||
static QButtonGroup *modeButtonGroup;
|
||||
const QString name;
|
||||
QWidget *central;
|
||||
};
|
||||
|
||||
#endif // MODE_H
|
@ -1,148 +0,0 @@
|
||||
#include "valueinput.h"
|
||||
#include <QGridLayout>
|
||||
#include <QKeyEvent>
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
|
||||
constexpr QSize ValueInput::minButtonSize;
|
||||
|
||||
ValueInput::ValueInput(std::vector<Unit> units, QString name, QString initialValue)
|
||||
{
|
||||
auto fontButton = QFont("Arial", 12);
|
||||
auto fontLabel = QFont("Arial", 30);
|
||||
|
||||
input = initialValue;
|
||||
// always use dots instead of comma
|
||||
input.replace(',', '.');
|
||||
this->units = units;
|
||||
setWindowTitle(name);
|
||||
|
||||
// Create layout
|
||||
auto layout = new QGridLayout();
|
||||
|
||||
// Add Label
|
||||
label = new QLabel();
|
||||
layout->addWidget(label, 0, 0, 2, 4);
|
||||
label->setText(input);
|
||||
label->setAlignment(Qt::AlignCenter);
|
||||
label->setFont(fontLabel);
|
||||
|
||||
// Create buttons and add to layout
|
||||
for(int i=0;i<3;i++) {
|
||||
for(int j=0;j<3;j++) {
|
||||
int number = i+1 + j*3;
|
||||
auto name = QString::number(number);
|
||||
auto button = new QPushButton(name);
|
||||
button->setFont(fontButton);
|
||||
button->setMinimumSize(minButtonSize);
|
||||
connect(button, &QPushButton::clicked, [=]() {this->AddToInput(name);});
|
||||
layout->addWidget(button, j+2, i);
|
||||
}
|
||||
}
|
||||
bDot = new QPushButton(".");
|
||||
bDot->setFont(fontButton);
|
||||
bDot->setMinimumSize(minButtonSize);
|
||||
if(input.contains('.')) {
|
||||
bDot->setDisabled(true);
|
||||
}
|
||||
layout->addWidget(bDot, 5, 0);
|
||||
connect(bDot, &QPushButton::clicked, [=]() {this->AddToInput(".");});
|
||||
auto bZero = new QPushButton("0");
|
||||
bZero->setFont(fontButton);
|
||||
bZero->setMinimumSize(minButtonSize);
|
||||
connect(bZero, &QPushButton::clicked, [=]() {this->AddToInput("0");});
|
||||
layout->addWidget(bZero, 5, 1);
|
||||
auto bSign = new QPushButton("+/-");
|
||||
bSign->setFont(fontButton);
|
||||
bSign->setMinimumSize(minButtonSize);
|
||||
layout->addWidget(bSign, 5, 2);
|
||||
connect(bSign, SIGNAL(clicked()), this, SLOT(ChangeSign()));
|
||||
|
||||
auto bDel = new QPushButton("Backspace");
|
||||
bDel->setMinimumSize(minButtonSize);
|
||||
layout->addWidget(bDel, 6, 0, 1, 3);
|
||||
connect(bDel, SIGNAL(clicked()), this, SLOT(Backspace()));
|
||||
|
||||
auto bAbort = new QPushButton("Abort");
|
||||
bAbort->setMinimumSize(minButtonSize);
|
||||
layout->addWidget(bAbort, 6, 3);
|
||||
connect(bAbort, SIGNAL(clicked()), this, SLOT(Abort()));
|
||||
|
||||
// Add unit inputs
|
||||
if(units.size() > 4) {
|
||||
units.resize(4);
|
||||
}
|
||||
for(unsigned int i=0;i<units.size();i++) {
|
||||
auto bUnit = new QPushButton(units[i].name);
|
||||
bUnit->setFont(fontButton);
|
||||
bUnit->setMinimumSize(minButtonSize);
|
||||
connect(bUnit, &QPushButton::clicked, [=](){this->UnitPressed(units[i].factor);});
|
||||
layout->addWidget(bUnit, i+2, 3);
|
||||
}
|
||||
|
||||
setLayout(layout);
|
||||
setWindowModality(Qt::ApplicationModal);
|
||||
show();
|
||||
}
|
||||
|
||||
void ValueInput::keyPressEvent(QKeyEvent *event) {
|
||||
auto key = event->key();
|
||||
if(key >= '0' && key <= '9') {
|
||||
AddToInput((QChar) key);
|
||||
event->accept();
|
||||
} else if((key == '.' || key == ',') && bDot->isEnabled()) {
|
||||
AddToInput(".");
|
||||
event->accept();
|
||||
} else if(key == Qt::Key_Escape) {
|
||||
Abort();
|
||||
event->accept();
|
||||
} else if(key == Qt::Key_Backspace) {
|
||||
Backspace();
|
||||
event->accept();
|
||||
} else if(key == '-') {
|
||||
ChangeSign();
|
||||
event->accept();
|
||||
}
|
||||
}
|
||||
|
||||
void ValueInput::AddToInput(QString a)
|
||||
{
|
||||
input.append(a);
|
||||
label->setText(input);
|
||||
if(a == '.') {
|
||||
bDot->setDisabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void ValueInput::ChangeSign()
|
||||
{
|
||||
if(input.at(0) == '-') {
|
||||
input.remove(0, 1);
|
||||
} else {
|
||||
input.prepend('-');
|
||||
}
|
||||
label->setText(input);
|
||||
}
|
||||
|
||||
void ValueInput::Backspace()
|
||||
{
|
||||
if(input.size() > 0) {
|
||||
if(input.at(input.size()-1) == '.') {
|
||||
bDot->setEnabled(true);
|
||||
}
|
||||
input.chop(1);
|
||||
label->setText(input);
|
||||
}
|
||||
}
|
||||
|
||||
void ValueInput::Abort()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void ValueInput::UnitPressed(double factor)
|
||||
{
|
||||
double value = input.toDouble() * factor;
|
||||
emit ValueChanged(value);
|
||||
close();
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
#ifndef VALUEINPUT_H
|
||||
#define VALUEINPUT_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <vector>
|
||||
#include <QPushButton>
|
||||
#include <QLabel>
|
||||
#include <QSignalMapper>
|
||||
|
||||
class ValueInput : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
class Unit {
|
||||
public:
|
||||
Unit(){};
|
||||
Unit(QString name, double factor):
|
||||
name(name), factor(factor){};
|
||||
QString name;
|
||||
double factor;
|
||||
};
|
||||
ValueInput(std::vector<Unit> units, QString name = "Value input", QString initialValue = QString());
|
||||
|
||||
signals:
|
||||
void ValueChanged(double value);
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
|
||||
private slots:
|
||||
void AddToInput(QString a);
|
||||
void ChangeSign();
|
||||
void Backspace();
|
||||
void Abort();
|
||||
void UnitPressed(double factor);
|
||||
private:
|
||||
static constexpr QSize minButtonSize = QSize(50, 50);
|
||||
QString input;
|
||||
QLabel *label;
|
||||
QPushButton *bDot;
|
||||
std::vector<Unit> units;
|
||||
};
|
||||
|
||||
#endif // VALUEINPUT_H
|
@ -1,169 +0,0 @@
|
||||
#ifndef VNA_H
|
||||
#define VNA_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QMainWindow>
|
||||
#include <QGridLayout>
|
||||
#include <QComboBox>
|
||||
#include <QStackedWidget>
|
||||
#include "Device/device.h"
|
||||
#include "Traces/traceplot.h"
|
||||
#include "Calibration/calibration.h"
|
||||
#include <QProgressDialog>
|
||||
#include "Menu/menuaction.h"
|
||||
#include "Traces/tracemodel.h"
|
||||
#include "Traces/tracemarkermodel.h"
|
||||
#include "averaging.h"
|
||||
#include "Device/devicelog.h"
|
||||
#include "preferences.h"
|
||||
#include <QButtonGroup>
|
||||
#include <QCheckBox>
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class VNA : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
VNA(QWidget *parent = nullptr);
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
private:
|
||||
static constexpr double minFreq = 0;
|
||||
static constexpr double maxFreq = 6000000000;
|
||||
static constexpr Protocol::SweepSettings defaultSweep = {
|
||||
.f_start = 1000000,
|
||||
.f_stop = (uint64_t) maxFreq,
|
||||
.points = 501,
|
||||
.if_bandwidth = 1000,
|
||||
.cdbm_excitation = 0,
|
||||
};
|
||||
private slots:
|
||||
void NewDatapoint(Protocol::Datapoint d);
|
||||
void ConnectToDevice(QString serial = QString());
|
||||
void DisconnectDevice();
|
||||
int UpdateDeviceList();
|
||||
void StartManualControl();
|
||||
void StartImpedanceMatching();
|
||||
// Sweep control
|
||||
void SetStartFreq(double freq);
|
||||
void SetStopFreq(double freq);
|
||||
void SetCenterFreq(double freq);
|
||||
void SetSpan(double span);
|
||||
void SetFullSpan();
|
||||
void SpanZoomIn();
|
||||
void SpanZoomOut();
|
||||
// Acquisition control
|
||||
void SetSourceLevel(double level);
|
||||
void SetPoints(unsigned int points);
|
||||
void SetIFBandwidth(double bandwidth);
|
||||
void SetAveraging(unsigned int averages);
|
||||
// Calibration
|
||||
void DisableCalibration(bool force = false);
|
||||
void ApplyCalibration(Calibration::Type type);
|
||||
void StartCalibrationMeasurement(Calibration::Measurement m);
|
||||
void UpdateReference();
|
||||
|
||||
signals:
|
||||
void CalibrationMeasurementComplete(Calibration::Measurement m);
|
||||
|
||||
private:
|
||||
void UpdateStatusPanel();
|
||||
void SettingsChanged();
|
||||
void DeviceConnectionLost();
|
||||
void CreateToolbars();
|
||||
void ConstrainAndUpdateFrequencies();
|
||||
void LoadSweepSettings();
|
||||
void StoreSweepSettings();
|
||||
|
||||
class GUIMode {
|
||||
friend class VNA;
|
||||
public:
|
||||
GUIMode(VNA *vna, QString name, QWidget *centralWidget);;
|
||||
void addHiddenElement(QAction* a) {
|
||||
hiddenActions.insert(a);
|
||||
}
|
||||
void addHiddenElement(QToolBar* a) {
|
||||
hiddenToolbars.insert(a);
|
||||
}
|
||||
void addHiddenElement(QDockWidget* a) {
|
||||
hiddenDocks.insert(a);
|
||||
}
|
||||
void activate();
|
||||
void deactivate();
|
||||
QString getName() const;
|
||||
static GUIMode *getActiveMode();
|
||||
|
||||
private:
|
||||
static GUIMode *activeMode;
|
||||
static QWidget *cornerWidget;
|
||||
static QButtonGroup *modeButtonGroup;
|
||||
std::set<QAction*> hiddenActions;
|
||||
std::set<QToolBar*> hiddenToolbars;
|
||||
std::set<QDockWidget*> hiddenDocks;
|
||||
VNA *vna;
|
||||
const QString name;
|
||||
QWidget *central;
|
||||
};
|
||||
GUIMode *modeVNA, *modeSGen;
|
||||
|
||||
QStackedWidget *central;
|
||||
|
||||
struct {
|
||||
struct {
|
||||
QComboBox *type;
|
||||
QCheckBox *automatic;
|
||||
QCheckBox *outputEnabled;
|
||||
QComboBox *outFreq;
|
||||
} reference;
|
||||
} toolbars;
|
||||
|
||||
Preferences pref;
|
||||
|
||||
Device *device;
|
||||
DeviceLog deviceLog;
|
||||
QString deviceSerial;
|
||||
QActionGroup *deviceActionGroup;
|
||||
Protocol::SweepSettings settings;
|
||||
unsigned int averages;
|
||||
TraceModel traceModel;
|
||||
TraceMarkerModel *markerModel;
|
||||
Averaging average;
|
||||
|
||||
// Calibration
|
||||
Calibration cal;
|
||||
bool calValid;
|
||||
Calibration::Measurement calMeasurement;
|
||||
bool calMeasuring;
|
||||
bool calWaitFirst;
|
||||
QProgressDialog calDialog;
|
||||
|
||||
// Status Labels
|
||||
QLabel lStart, lCenter, lStop, lSpan, lPoints, lBandwidth;
|
||||
QLabel lCalibration;
|
||||
QLabel lAverages;
|
||||
|
||||
// Status bar widgets
|
||||
QLabel lConnectionStatus;
|
||||
QLabel lDeviceInfo;
|
||||
|
||||
Ui::MainWindow *ui;
|
||||
signals:
|
||||
void dataChanged();
|
||||
void startFreqChanged(double freq);
|
||||
void stopFreqChanged(double freq);
|
||||
void centerFreqChanged(double freq);
|
||||
void spanChanged(double span);
|
||||
|
||||
void sourceLevelChanged(double level);
|
||||
void pointsChanged(unsigned int points);
|
||||
void IFBandwidthChanged(double bandwidth);
|
||||
void averagingChanged(unsigned int averages);
|
||||
|
||||
void CalibrationDisabled();
|
||||
void CalibrationApplied(Calibration::Type type);
|
||||
};
|
||||
|
||||
#endif // VNA_H
|
Loading…
Reference in New Issue
Block a user