mirror of
https://github.com/jankae/LibreVNA.git
synced 2026-04-04 14:07:30 +00:00
PC Application: partial firmware update dialog
This commit is contained in:
parent
8c8749accd
commit
07ba714f1f
134 changed files with 13954 additions and 7 deletions
408
Software/PC_Application/Device/device.cpp
Normal file
408
Software/PC_Application/Device/device.cpp
Normal file
|
|
@ -0,0 +1,408 @@
|
|||
#include "device.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
#include <QMessageBox>
|
||||
#include <mutex>
|
||||
|
||||
using namespace std;
|
||||
|
||||
Device::Device(QString serial)
|
||||
{
|
||||
qDebug() << "Starting device connection...";
|
||||
|
||||
m_handle = nullptr;
|
||||
libusb_init(&m_context);
|
||||
|
||||
SearchDevices([=](libusb_device_handle *handle, QString found_serial) -> bool {
|
||||
if(serial.isEmpty() || serial == found_serial) {
|
||||
// accept connection to this device
|
||||
m_serial = found_serial;
|
||||
m_handle = handle;
|
||||
// abort device search
|
||||
return false;
|
||||
} else {
|
||||
// not the requested device, continue search
|
||||
return true;
|
||||
}
|
||||
}, m_context);
|
||||
|
||||
if(!m_handle) {
|
||||
QString message = "No device found";
|
||||
auto msg = new QMessageBox(QMessageBox::Icon::Warning, "Error opening device", message);
|
||||
msg->exec();
|
||||
libusb_exit(m_context);
|
||||
throw std::runtime_error(message.toStdString());
|
||||
return;
|
||||
}
|
||||
|
||||
// Found the correct device, now connect
|
||||
/* claim the interfaces */
|
||||
for (int if_num = 0; if_num < 1; if_num++) {
|
||||
int ret = libusb_claim_interface(m_handle, if_num);
|
||||
if (ret < 0) {
|
||||
libusb_close(m_handle);
|
||||
/* Failed to open */
|
||||
QString message = "Failed to claim interface: \"";
|
||||
message.append(libusb_strerror((libusb_error) ret));
|
||||
message.append("\" Maybe you are already connected to this device?");
|
||||
qWarning() << message;
|
||||
auto msg = new QMessageBox(QMessageBox::Icon::Warning, "Error opening device", message);
|
||||
msg->exec();
|
||||
libusb_exit(m_context);
|
||||
throw std::runtime_error(message.toStdString());
|
||||
}
|
||||
}
|
||||
qInfo() << "USB connection established" << flush;
|
||||
m_connected = true;
|
||||
m_receiveThread = new std::thread(&Device::USBHandleThread, this);
|
||||
dataBuffer = new USBInBuffer(m_handle, EP_Data_In_Addr, 2048);
|
||||
logBuffer = new USBInBuffer(m_handle, EP_Log_In_Addr, 2048);
|
||||
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);
|
||||
}
|
||||
|
||||
Device::~Device()
|
||||
{
|
||||
if(m_connected) {
|
||||
delete dataBuffer;
|
||||
delete logBuffer;
|
||||
m_connected = false;
|
||||
for (int if_num = 0; if_num < 1; if_num++) {
|
||||
int ret = libusb_release_interface(m_handle, if_num);
|
||||
if (ret < 0) {
|
||||
qCritical() << "Error releasing interface" << libusb_error_name(ret);
|
||||
}
|
||||
}
|
||||
libusb_close(m_handle);
|
||||
m_receiveThread->join();
|
||||
libusb_exit(m_context);
|
||||
}
|
||||
}
|
||||
|
||||
bool Device::Configure(Protocol::SweepSettings settings)
|
||||
{
|
||||
if(m_connected) {
|
||||
unsigned char buffer[128];
|
||||
Protocol::PacketInfo p;
|
||||
p.type = Protocol::PacketType::SweepSettings;
|
||||
p.settings = settings;
|
||||
unsigned int length = Protocol::EncodePacket(p, 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;
|
||||
}
|
||||
}
|
||||
|
||||
bool Device::SetManual(Protocol::ManualControl manual)
|
||||
{
|
||||
if(m_connected) {
|
||||
unsigned char buffer[128];
|
||||
Protocol::PacketInfo p;
|
||||
p.type = Protocol::PacketType::ManualControl;
|
||||
p.manual = manual;
|
||||
unsigned int length = Protocol::EncodePacket(p, 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;
|
||||
}
|
||||
}
|
||||
|
||||
bool Device::SendFirmwareChunk(Protocol::FirmwarePacket &fw)
|
||||
{
|
||||
if(m_connected) {
|
||||
unsigned char buffer[Protocol::FirmwareChunkSize + 4 + 8];
|
||||
Protocol::PacketInfo p;
|
||||
p.type = Protocol::PacketType::FirmwarePacket;
|
||||
p.firmware = fw;
|
||||
unsigned int length = Protocol::EncodePacket(p, 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;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<QString> Device::GetDevices()
|
||||
{
|
||||
std::vector<QString> serials;
|
||||
|
||||
libusb_context *ctx;
|
||||
libusb_init(&ctx);
|
||||
|
||||
SearchDevices([&serials](libusb_device_handle *, QString serial) -> bool {
|
||||
serials.push_back(serial);
|
||||
return true;
|
||||
}, ctx);
|
||||
|
||||
libusb_exit(ctx);
|
||||
|
||||
return serials;
|
||||
}
|
||||
|
||||
void Device::USBHandleThread()
|
||||
{
|
||||
qInfo() << "Receive thread started" << flush;
|
||||
while (m_connected) {
|
||||
libusb_handle_events(m_context);
|
||||
}
|
||||
qDebug() << "Disconnected, receive thread exiting";
|
||||
}
|
||||
|
||||
void Device::SearchDevices(std::function<bool (libusb_device_handle *, QString)> foundCallback, libusb_context *context)
|
||||
{
|
||||
libusb_device **devList;
|
||||
auto ndevices = libusb_get_device_list(context, &devList);
|
||||
|
||||
for (ssize_t idx = 0; idx < ndevices; idx++) {
|
||||
int ret;
|
||||
libusb_device *device = devList[idx];
|
||||
libusb_device_descriptor desc = {};
|
||||
|
||||
ret = libusb_get_device_descriptor(device, &desc);
|
||||
if (ret) {
|
||||
/* some error occured */
|
||||
qCritical() << "Failed to get device descriptor: "
|
||||
<< libusb_strerror((libusb_error) ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (desc.idVendor != VID || desc.idProduct != PID) {
|
||||
/* Not the correct IDs */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Try to open the device */
|
||||
libusb_device_handle *handle = nullptr;
|
||||
ret = libusb_open(device, &handle);
|
||||
if (ret) {
|
||||
/* Failed to open */
|
||||
QString message = "Found potential device but failed to open usb connection: \"";
|
||||
message.append(libusb_strerror((libusb_error) ret));
|
||||
message.append("\" On Linux this is most likely caused by a missing udev rule. On Windows it could be a missing driver. Try installing the WinUSB driver using Zadig (https://zadig.akeo.ie/)");
|
||||
qWarning() << message;
|
||||
auto msg = new QMessageBox(QMessageBox::Icon::Warning, "Error opening device", message);
|
||||
msg->exec();
|
||||
continue;
|
||||
}
|
||||
|
||||
char c_product[256];
|
||||
char c_serial[256];
|
||||
libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber,
|
||||
(unsigned char*) c_serial, sizeof(c_serial));
|
||||
ret = libusb_get_string_descriptor_ascii(handle, desc.iProduct,
|
||||
(unsigned char*) c_product, sizeof(c_product));
|
||||
if (ret > 0) {
|
||||
/* managed to read the product string */
|
||||
QString product(c_product);
|
||||
qDebug() << "Opened device: " << product;
|
||||
if (product == "VNA") {
|
||||
// this is a match
|
||||
if(!foundCallback(handle, QString(c_serial))) {
|
||||
// abort search
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qWarning() << "Failed to get product descriptor: "
|
||||
<< libusb_strerror((libusb_error) ret);
|
||||
}
|
||||
libusb_close(handle);
|
||||
}
|
||||
libusb_free_device_list(devList, 1);
|
||||
}
|
||||
|
||||
Protocol::DeviceInfo Device::getLastInfo() const
|
||||
{
|
||||
return lastInfo;
|
||||
}
|
||||
|
||||
QString Device::getLastDeviceInfoString()
|
||||
{
|
||||
QString ret;
|
||||
if(!lastInfoValid) {
|
||||
ret.append("No device information available yet");
|
||||
} else {
|
||||
ret.append("HW Rev.");
|
||||
ret.append(lastInfo.HW_Revision);
|
||||
ret.append(" FW "+QString::number(lastInfo.FW_major)+"."+QString::number(lastInfo.FW_minor).rightJustified(2, '0'));
|
||||
ret.append(" Temps: "+QString::number(lastInfo.temperatures.source)+"°C/"+QString::number(lastInfo.temperatures.LO1)+"°C/"+QString::number(lastInfo.temperatures.MCU)+"°C");
|
||||
ret.append(" Reference:");
|
||||
if(lastInfo.extRefInUse) {
|
||||
ret.append("External");
|
||||
} else {
|
||||
ret.append("Internal");
|
||||
if(lastInfo.extRefAvailable) {
|
||||
ret.append(" (External available)");
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Device::ReceivedData()
|
||||
{
|
||||
Protocol::PacketInfo packet;
|
||||
uint16_t handled_len;
|
||||
do {
|
||||
handled_len = Protocol::DecodeBuffer(dataBuffer->getBuffer(), dataBuffer->getReceived(), &packet);
|
||||
dataBuffer->removeBytes(handled_len);
|
||||
if(packet.type == Protocol::PacketType::Datapoint) {
|
||||
emit DatapointReceived(packet.datapoint);
|
||||
} else if(packet.type == Protocol::PacketType::Status) {
|
||||
qDebug() << "Got status";
|
||||
emit ManualStatusReceived(packet.status);
|
||||
} else if(packet.type == Protocol::PacketType::DeviceInfo) {
|
||||
lastInfo = packet.info;
|
||||
lastInfoValid = true;
|
||||
emit DeviceInfoUpdated();
|
||||
} else if(packet.type == Protocol::PacketType::Ack) {
|
||||
emit AckReceived();
|
||||
}
|
||||
} while (handled_len > 0);
|
||||
}
|
||||
|
||||
void Device::ReceivedLog()
|
||||
{
|
||||
uint16_t handled_len;
|
||||
do {
|
||||
handled_len = 0;
|
||||
auto firstLinebreak = (uint8_t*) memchr(logBuffer->getBuffer(), '\n', logBuffer->getReceived());
|
||||
if(firstLinebreak) {
|
||||
handled_len = firstLinebreak - logBuffer->getBuffer();
|
||||
auto line = QString::fromLatin1((const char*) logBuffer->getBuffer(), handled_len - 1);
|
||||
emit LogLineReceived(line);
|
||||
logBuffer->removeBytes(handled_len + 1);
|
||||
}
|
||||
} while(handled_len > 0);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
93
Software/PC_Application/Device/device.h
Normal file
93
Software/PC_Application/Device/device.h
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
#ifndef DEVICE_H
|
||||
#define DEVICE_H
|
||||
|
||||
#include "../VNA_embedded/Application/Communication/Protocol.hpp"
|
||||
#include <functional>
|
||||
#include <libusb-1.0/libusb.h>
|
||||
#include <thread>
|
||||
#include <QObject>
|
||||
#include <condition_variable>
|
||||
|
||||
Q_DECLARE_METATYPE(Protocol::Datapoint);
|
||||
Q_DECLARE_METATYPE(Protocol::ManualStatus);
|
||||
Q_DECLARE_METATYPE(Protocol::DeviceInfo);
|
||||
|
||||
class USBInBuffer : public QObject {
|
||||
Q_OBJECT;
|
||||
public:
|
||||
USBInBuffer(libusb_device_handle *handle, unsigned char endpoint, int buffer_size);
|
||||
~USBInBuffer();
|
||||
|
||||
void removeBytes(int handled_bytes);
|
||||
int getReceived() const;
|
||||
uint8_t *getBuffer() const;
|
||||
|
||||
signals:
|
||||
void DataReceived();
|
||||
void TransferError();
|
||||
|
||||
private:
|
||||
void Callback(libusb_transfer *transfer);
|
||||
static void LIBUSB_CALL CallbackTrampoline(libusb_transfer *transfer);
|
||||
libusb_transfer *transfer;
|
||||
unsigned char *buffer;
|
||||
int buffer_size;
|
||||
int received_size;
|
||||
bool inCallback;
|
||||
std::condition_variable cv;
|
||||
};
|
||||
|
||||
|
||||
class Device : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
// 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 Configure(Protocol::SweepSettings settings);
|
||||
bool SetManual(Protocol::ManualControl manual);
|
||||
bool SendFirmwareChunk(Protocol::FirmwarePacket &fw);
|
||||
// Returns serial numbers of all connected devices
|
||||
static std::vector<QString> GetDevices();
|
||||
QString serial() const;
|
||||
Protocol::DeviceInfo getLastInfo() const;
|
||||
QString getLastDeviceInfoString();
|
||||
|
||||
signals:
|
||||
void DatapointReceived(Protocol::Datapoint);
|
||||
void ManualStatusReceived(Protocol::ManualStatus);
|
||||
void DeviceInfoUpdated();
|
||||
void ConnectionLost();
|
||||
void AckReceived();
|
||||
void LogLineReceived(QString line);
|
||||
private slots:
|
||||
void ReceivedData();
|
||||
void ReceivedLog();
|
||||
|
||||
private:
|
||||
static constexpr int VID = 0x0483;
|
||||
static constexpr int PID = 0x564e;
|
||||
static constexpr int EP_Data_Out_Addr = 0x01;
|
||||
static constexpr int EP_Data_In_Addr = 0x81;
|
||||
static constexpr int EP_Log_In_Addr = 0x82;
|
||||
|
||||
void USBHandleThread();
|
||||
// foundCallback is called for every device that is found. If it returns true the search continues, otherwise it is aborted.
|
||||
// When the search is aborted the last found device is still opened
|
||||
static void SearchDevices(std::function<bool(libusb_device_handle *handle, QString serial)> foundCallback, libusb_context *context);
|
||||
|
||||
libusb_device_handle *m_handle;
|
||||
libusb_context *m_context;
|
||||
USBInBuffer *dataBuffer;
|
||||
USBInBuffer *logBuffer;
|
||||
|
||||
|
||||
QString m_serial;
|
||||
bool m_connected;
|
||||
std::thread *m_receiveThread;
|
||||
Protocol::DeviceInfo lastInfo;
|
||||
bool lastInfoValid;
|
||||
};
|
||||
|
||||
#endif // DEVICE_H
|
||||
61
Software/PC_Application/Device/devicelog.cpp
Normal file
61
Software/PC_Application/Device/devicelog.cpp
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#include "devicelog.h"
|
||||
#include "ui_devicelog.h"
|
||||
#include <QScrollBar>
|
||||
#include <QFileDialog>
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
DeviceLog::DeviceLog(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::DeviceLog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
connect(ui->bClear, &QPushButton::clicked, this, &DeviceLog::clear);
|
||||
}
|
||||
|
||||
DeviceLog::~DeviceLog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void DeviceLog::addLine(QString line)
|
||||
{
|
||||
// Set color depending on log level
|
||||
QColor color = Qt::black;
|
||||
if(line.contains(",CRT]")) {
|
||||
color = Qt::red;
|
||||
} else if(line.contains(",ERR]")) {
|
||||
color = QColor("orange");
|
||||
} else if(line.contains(",WRN]")) {
|
||||
color = Qt::darkYellow;
|
||||
} else if(line.contains(",DBG")) {
|
||||
color = Qt::gray;
|
||||
}
|
||||
QTextCharFormat tf;
|
||||
tf = ui->text->currentCharFormat();
|
||||
tf.setForeground(QBrush(color));
|
||||
ui->text->setCurrentCharFormat(tf);
|
||||
ui->text->appendPlainText(line);
|
||||
if(ui->cbAutoscroll->isChecked()) {
|
||||
QScrollBar *sb = ui->text->verticalScrollBar();
|
||||
sb->setValue(sb->maximum());
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceLog::clear()
|
||||
{
|
||||
ui->text->clear();
|
||||
}
|
||||
|
||||
void DeviceLog::on_bToFile_clicked()
|
||||
{
|
||||
auto filename = QFileDialog::getSaveFileName(this, "Select file for device log", "", "", nullptr, QFileDialog::DontUseNativeDialog);
|
||||
if(filename.length() > 0) {
|
||||
// create file
|
||||
ofstream file;
|
||||
file.open(filename.toStdString());
|
||||
file << ui->text->toPlainText().toStdString();
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
29
Software/PC_Application/Device/devicelog.h
Normal file
29
Software/PC_Application/Device/devicelog.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef DEVICELOG_H
|
||||
#define DEVICELOG_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class DeviceLog;
|
||||
}
|
||||
|
||||
class DeviceLog : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DeviceLog(QWidget *parent = nullptr);
|
||||
~DeviceLog();
|
||||
|
||||
public slots:
|
||||
void addLine(QString line);
|
||||
void clear();
|
||||
|
||||
private slots:
|
||||
void on_bToFile_clicked();
|
||||
|
||||
private:
|
||||
Ui::DeviceLog *ui;
|
||||
};
|
||||
|
||||
#endif // DEVICELOG_H
|
||||
72
Software/PC_Application/Device/devicelog.ui
Normal file
72
Software/PC_Application/Device/devicelog.ui
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DeviceLog</class>
|
||||
<widget class="QWidget" name="DeviceLog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>810</width>
|
||||
<height>211</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="text">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="bToFile">
|
||||
<property name="text">
|
||||
<string>To File</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="document-save"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="bClear">
|
||||
<property name="text">
|
||||
<string>Clear</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="edit-clear"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbAutoscroll">
|
||||
<property name="text">
|
||||
<string>Autoscroll</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
127
Software/PC_Application/Device/firmwareupdatedialog.cpp
Normal file
127
Software/PC_Application/Device/firmwareupdatedialog.cpp
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
#include "firmwareupdatedialog.h"
|
||||
#include "ui_firmwareupdatedialog.h"
|
||||
#include <QFileDialog>
|
||||
|
||||
FirmwareUpdateDialog::FirmwareUpdateDialog(Device &dev, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::FirmwareUpdateDialog),
|
||||
dev(dev),
|
||||
file(),
|
||||
timer(),
|
||||
state(State::Idle)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->bFile->setIcon(this->style()->standardPixmap(QStyle::SP_FileDialogStart));
|
||||
ui->bStart->setIcon(this->style()->standardPixmap(QStyle::SP_MediaPlay));
|
||||
timer.setSingleShot(true);
|
||||
connect(&timer, &QTimer::timeout, [=](){
|
||||
abortWithError("Response timed out");
|
||||
});
|
||||
}
|
||||
|
||||
FirmwareUpdateDialog::~FirmwareUpdateDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void FirmwareUpdateDialog::on_bFile_clicked()
|
||||
{
|
||||
ui->bStart->setEnabled(false);
|
||||
auto filename = QFileDialog::getOpenFileName(nullptr, "Open firmware file", "", "Firmware file (*.vnafw)", nullptr, QFileDialog::DontUseNativeDialog);
|
||||
if (filename.length() > 0) {
|
||||
ui->lFile->setText(filename);
|
||||
if(file) {
|
||||
delete file;
|
||||
}
|
||||
file = new QFile(filename);
|
||||
ui->bStart->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void FirmwareUpdateDialog::on_bStart_clicked()
|
||||
{
|
||||
ui->status->clear();
|
||||
ui->bStart->setEnabled(false);
|
||||
if(!file->isOpen()) {
|
||||
if(!file->open(QIODevice::ReadOnly)) {
|
||||
abortWithError("Unable to open file");
|
||||
return;
|
||||
}
|
||||
}
|
||||
file->seek(0);
|
||||
addStatus("Evaluating file...");
|
||||
if(file->size() % Protocol::FirmwareChunkSize != 0) {
|
||||
abortWithError("Invalid file size");
|
||||
return;
|
||||
}
|
||||
char header[24];
|
||||
file->read(header, sizeof(header));
|
||||
if(strncmp(header, "VNA!", 4)) {
|
||||
abortWithError("Invalid magic header constant");
|
||||
return;
|
||||
}
|
||||
state = State::ErasingFLASH;
|
||||
addStatus("Erasing device memory...");
|
||||
// TODO issue write command
|
||||
timer.start(10000);
|
||||
}
|
||||
|
||||
void FirmwareUpdateDialog::addStatus(QString line)
|
||||
{
|
||||
ui->status->appendPlainText(line);
|
||||
}
|
||||
|
||||
void FirmwareUpdateDialog::abortWithError(QString error)
|
||||
{
|
||||
QTextCharFormat tf;
|
||||
tf = ui->status->currentCharFormat();
|
||||
tf.setForeground(QBrush(Qt::red));
|
||||
ui->status->setCurrentCharFormat(tf);
|
||||
ui->status->appendPlainText(error);
|
||||
tf.setForeground(QBrush(Qt::black));
|
||||
ui->status->setCurrentCharFormat(tf);
|
||||
ui->bStart->setEnabled(true);
|
||||
state = State::Idle;
|
||||
}
|
||||
|
||||
void FirmwareUpdateDialog::receivedAck()
|
||||
{
|
||||
switch(state) {
|
||||
case State::Idle:
|
||||
// no firmware update in progress, ignore
|
||||
break;
|
||||
case State::ErasingFLASH:
|
||||
// FLASH erased, begin transferring firmware
|
||||
state = State::TransferringData;
|
||||
transferredBytes = 0;
|
||||
addStatus("Transferring firmware...");
|
||||
sendNextFirmwareChunk();
|
||||
timer.start(1000);
|
||||
break;
|
||||
case State::TransferringData:
|
||||
transferredBytes += Protocol::FirmwareChunkSize;
|
||||
ui->progress->setValue(100 * transferredBytes / file->size());
|
||||
if(transferredBytes >= file->size()) {
|
||||
// complete file transferred
|
||||
addStatus("Triggering device update...");
|
||||
state = State::TriggeringUpdate;
|
||||
// TODO trigger update
|
||||
timer.start(5000);
|
||||
}
|
||||
sendNextFirmwareChunk();
|
||||
timer.start(1000);
|
||||
break;
|
||||
case State::TriggeringUpdate:
|
||||
addStatus("Rebooting device...");
|
||||
// TODO listen for detected device
|
||||
state = State::Idle;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FirmwareUpdateDialog::sendNextFirmwareChunk()
|
||||
{
|
||||
Protocol::FirmwarePacket fw;
|
||||
fw.address = transferredBytes;
|
||||
file->read((char*) &fw.data, Protocol::FirmwareChunkSize);
|
||||
}
|
||||
46
Software/PC_Application/Device/firmwareupdatedialog.h
Normal file
46
Software/PC_Application/Device/firmwareupdatedialog.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
#ifndef FIRMWAREUPDATEDIALOG_H
|
||||
#define FIRMWAREUPDATEDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include "device.h"
|
||||
#include <QFile>
|
||||
#include <QTimer>
|
||||
|
||||
namespace Ui {
|
||||
class FirmwareUpdateDialog;
|
||||
}
|
||||
|
||||
class FirmwareUpdateDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FirmwareUpdateDialog(Device &dev, QWidget *parent = nullptr);
|
||||
~FirmwareUpdateDialog();
|
||||
|
||||
private slots:
|
||||
void on_bFile_clicked();
|
||||
|
||||
void on_bStart_clicked();
|
||||
|
||||
private:
|
||||
void addStatus(QString line);
|
||||
void abortWithError(QString error);
|
||||
void receivedAck();
|
||||
void sendNextFirmwareChunk();
|
||||
Ui::FirmwareUpdateDialog *ui;
|
||||
Device &dev;
|
||||
QFile *file;
|
||||
QTimer timer;
|
||||
|
||||
enum class State {
|
||||
Idle,
|
||||
ErasingFLASH,
|
||||
TransferringData,
|
||||
TriggeringUpdate,
|
||||
};
|
||||
State state;
|
||||
unsigned int transferredBytes;
|
||||
};
|
||||
|
||||
#endif // FIRMWAREUPDATEDIALOG_H
|
||||
105
Software/PC_Application/Device/firmwareupdatedialog.ui
Normal file
105
Software/PC_Application/Device/firmwareupdatedialog.ui
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FirmwareUpdateDialog</class>
|
||||
<widget class="QDialog" name="FirmwareUpdateDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>520</width>
|
||||
<height>327</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Firmware Update</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>File:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lFile">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="bFile">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="status">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progress">
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="bStart">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Start</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
254
Software/PC_Application/Device/manualcontroldialog.cpp
Normal file
254
Software/PC_Application/Device/manualcontroldialog.cpp
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
#include "manualcontroldialog.h"
|
||||
#include "ui_manualcontroldialog.h"
|
||||
#include <QComboBox>
|
||||
#include <QDebug>
|
||||
#include <QButtonGroup>
|
||||
#include <complex>
|
||||
|
||||
using namespace std;
|
||||
|
||||
ManualControlDialog::ManualControlDialog(Device &dev, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::ManualControlDialog),
|
||||
dev(dev)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->SourceLowFrequency->setUnit("Hz");
|
||||
ui->SourceLowFrequency->setPrefixes(" kM");
|
||||
ui->SourceLowFrequency->setPrecision(6);
|
||||
ui->SourceLowFrequency->setValueQuiet(1000000);
|
||||
|
||||
ui->SourceHighFrequency->setUnit("Hz");
|
||||
ui->SourceHighFrequency->setPrefixes(" kMG");
|
||||
ui->SourceHighFrequency->setPrecision(6);
|
||||
ui->SourceHighFrequency->setValueQuiet(1000000000);
|
||||
|
||||
ui->IF1->setUnit("Hz");
|
||||
ui->IF1->setPrefixes(" kM");
|
||||
ui->IF1->setPrecision(6);
|
||||
|
||||
ui->LO1Frequency->setUnit("Hz");
|
||||
ui->LO1Frequency->setPrefixes(" kMG");
|
||||
ui->LO1Frequency->setPrecision(6);
|
||||
|
||||
ui->IF2->setUnit("Hz");
|
||||
ui->IF2->setPrefixes(" kM");
|
||||
ui->IF2->setPrecision(6);
|
||||
|
||||
ui->LO2Frequency->setUnit("Hz");
|
||||
ui->LO2Frequency->setPrefixes(" kM");
|
||||
ui->LO2Frequency->setPrecision(6);
|
||||
|
||||
auto UpdateLO1 = [=]() {
|
||||
double sourceFreq;
|
||||
if (ui->SwitchLowband->isChecked()) {
|
||||
sourceFreq = ui->SourceLowFrequency->value();
|
||||
} else {
|
||||
sourceFreq = ui->SourceHighFrequency->value();
|
||||
}
|
||||
if (ui->LO1FreqType->currentIndex() == 0) {
|
||||
// fixed IF mode
|
||||
ui->LO1Frequency->setValueQuiet(sourceFreq + ui->IF1->value());
|
||||
} else {
|
||||
// Manual Frequency mode
|
||||
ui->IF1->setValueQuiet(ui->LO1Frequency->value() - sourceFreq);
|
||||
}
|
||||
};
|
||||
auto UpdateLO2 = [=]() {
|
||||
double IF1 = ui->IF1->value();
|
||||
if (ui->LO2FreqType->currentIndex() == 0) {
|
||||
// fixed IF mode
|
||||
ui->LO2Frequency->setValueQuiet(IF1 + ui->IF2->value());
|
||||
} else {
|
||||
// Manual Frequency mode
|
||||
ui->IF2->setValueQuiet(ui->LO2Frequency->value() - IF1);
|
||||
}
|
||||
};
|
||||
|
||||
connect(ui->IF1, &SIUnitEdit::valueChanged, [=](double) {
|
||||
UpdateLO1();
|
||||
UpdateLO2();
|
||||
});
|
||||
connect(ui->LO1Frequency, &SIUnitEdit::valueChanged, [=](double) {
|
||||
UpdateLO1();
|
||||
UpdateLO2();
|
||||
});
|
||||
connect(ui->IF2, &SIUnitEdit::valueChanged, [=](double) {
|
||||
UpdateLO2();
|
||||
});
|
||||
connect(ui->LO2Frequency, &SIUnitEdit::valueChanged, [=](double) {
|
||||
UpdateLO2();
|
||||
});
|
||||
connect(ui->SourceSwitchGroup, qOverload<int, bool>(&QButtonGroup::buttonToggled), [=](int, bool) {
|
||||
UpdateLO1();
|
||||
UpdateLO2();
|
||||
});
|
||||
connect(ui->SourceLowFrequency, &SIUnitEdit::valueChanged, [=](double) {
|
||||
UpdateLO1();
|
||||
UpdateLO2();
|
||||
});
|
||||
connect(ui->SourceHighFrequency, &SIUnitEdit::valueChanged, [=](double) {
|
||||
UpdateLO1();
|
||||
UpdateLO2();
|
||||
});
|
||||
|
||||
ui->IF1->setValue(60000000);
|
||||
ui->IF2->setValue(250000);
|
||||
|
||||
// LO1/LO2 mode switch connections
|
||||
connect(ui->LO1FreqType, qOverload<int>(&QComboBox::activated), [=](int index) {
|
||||
switch(index) {
|
||||
case 0:
|
||||
ui->LO1Frequency->setEnabled(false);
|
||||
ui->IF1->setEnabled(true);
|
||||
break;
|
||||
case 1:
|
||||
ui->LO1Frequency->setEnabled(true);
|
||||
ui->IF1->setEnabled(false);
|
||||
break;
|
||||
}
|
||||
});
|
||||
connect(ui->LO2FreqType, qOverload<int>(&QComboBox::activated), [=](int index) {
|
||||
switch(index) {
|
||||
case 0:
|
||||
ui->LO2Frequency->setEnabled(false);
|
||||
ui->IF2->setEnabled(true);
|
||||
break;
|
||||
case 1:
|
||||
ui->LO2Frequency->setEnabled(true);
|
||||
ui->IF2->setEnabled(false);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// Readonly widgets
|
||||
auto MakeReadOnly = [](QWidget* w) {
|
||||
w->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
w->setFocusPolicy(Qt::NoFocus);
|
||||
};
|
||||
MakeReadOnly(ui->SourceLocked);
|
||||
MakeReadOnly(ui->LO1locked);
|
||||
MakeReadOnly(ui->port1min);
|
||||
MakeReadOnly(ui->port1max);
|
||||
MakeReadOnly(ui->port1mag);
|
||||
MakeReadOnly(ui->port1phase);
|
||||
MakeReadOnly(ui->port1referenced);
|
||||
MakeReadOnly(ui->port2min);
|
||||
MakeReadOnly(ui->port2max);
|
||||
MakeReadOnly(ui->port2mag);
|
||||
MakeReadOnly(ui->port2phase);
|
||||
MakeReadOnly(ui->port2referenced);
|
||||
MakeReadOnly(ui->refmin);
|
||||
MakeReadOnly(ui->refmax);
|
||||
MakeReadOnly(ui->refmag);
|
||||
MakeReadOnly(ui->refphase);
|
||||
|
||||
qRegisterMetaType<Protocol::ManualStatus>("Status");
|
||||
connect(&dev, &Device::ManualStatusReceived, this, &ManualControlDialog::NewStatus);
|
||||
|
||||
connect(ui->SourceCE, &QCheckBox::toggled, [=](bool) { UpdateDevice(); });
|
||||
connect(ui->SourceRFEN, &QCheckBox::toggled, [=](bool) { UpdateDevice(); });
|
||||
connect(ui->LO1CE, &QCheckBox::toggled, [=](bool) { UpdateDevice(); });
|
||||
connect(ui->LO1RFEN, &QCheckBox::toggled, [=](bool) { UpdateDevice(); });
|
||||
connect(ui->SourceLowEnable, &QCheckBox::toggled, [=](bool) { UpdateDevice(); });
|
||||
connect(ui->AmplifierEnable, &QCheckBox::toggled, [=](bool) { UpdateDevice(); });
|
||||
connect(ui->LO2EN, &QCheckBox::toggled, [=](bool) { UpdateDevice(); });
|
||||
connect(ui->Port1Enable, &QCheckBox::toggled, [=](bool) { UpdateDevice(); });
|
||||
connect(ui->Port2Enable, &QCheckBox::toggled, [=](bool) { UpdateDevice(); });
|
||||
connect(ui->RefEnable, &QCheckBox::toggled, [=](bool) { UpdateDevice(); });
|
||||
|
||||
connect(ui->SourceHighPower, qOverload<int>(&QComboBox::activated), [=](int) { UpdateDevice(); });
|
||||
connect(ui->SourceLowpass, qOverload<int>(&QComboBox::activated), [=](int) { UpdateDevice(); });
|
||||
connect(ui->SourceLowPower, qOverload<int>(&QComboBox::activated), [=](int) { UpdateDevice(); });
|
||||
|
||||
connect(ui->SourceHighFrequency, &SIUnitEdit::valueChanged, [=](double) { UpdateDevice(); });
|
||||
connect(ui->SourceLowFrequency, &SIUnitEdit::valueChanged, [=](double) { UpdateDevice(); });
|
||||
connect(ui->LO1Frequency, &SIUnitEdit::valueChanged, [=](double) { UpdateDevice(); });
|
||||
connect(ui->IF1, &SIUnitEdit::valueChanged, [=](double) { UpdateDevice(); });
|
||||
connect(ui->LO2Frequency, &SIUnitEdit::valueChanged, [=](double) { UpdateDevice(); });
|
||||
connect(ui->IF2, &SIUnitEdit::valueChanged, [=](double) { UpdateDevice(); });
|
||||
|
||||
connect(ui->PortSwitchGroup, qOverload<int, bool>(&QButtonGroup::buttonToggled), [=](int, bool) { UpdateDevice(); });
|
||||
connect(ui->SourceSwitchGroup, qOverload<int, bool>(&QButtonGroup::buttonToggled), [=](int, bool) { UpdateDevice(); });
|
||||
|
||||
connect(ui->Attenuator, qOverload<double>(&QDoubleSpinBox::valueChanged), [=](double) { UpdateDevice(); });
|
||||
connect(ui->Samples, qOverload<int>(&QSpinBox::valueChanged), [=](double) { UpdateDevice(); });
|
||||
|
||||
UpdateDevice();
|
||||
}
|
||||
|
||||
ManualControlDialog::~ManualControlDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ManualControlDialog::NewStatus(Protocol::ManualStatus status)
|
||||
{
|
||||
// ADC values
|
||||
ui->port1min->setText(QString::number(status.port1min));
|
||||
ui->port1max->setText(QString::number(status.port1max));
|
||||
auto port1 = complex<double>(status.port1real, status.port1imag);
|
||||
ui->port1mag->setText(QString::number(abs(port1)));
|
||||
ui->port1phase->setText(QString::number(arg(port1)*180/M_PI));
|
||||
|
||||
ui->port2min->setText(QString::number(status.port2min));
|
||||
ui->port2max->setText(QString::number(status.port2max));
|
||||
auto port2 = complex<double>(status.port2real, status.port2imag);
|
||||
ui->port2mag->setText(QString::number(abs(port2)));
|
||||
ui->port2phase->setText(QString::number(arg(port2)*180/M_PI));
|
||||
|
||||
ui->refmin->setText(QString::number(status.refmin));
|
||||
ui->refmax->setText(QString::number(status.refmax));
|
||||
auto ref = complex<double>(status.refreal, status.refimag);
|
||||
ui->refmag->setText(QString::number(abs(ref)));
|
||||
ui->refphase->setText(QString::number(arg(ref)*180/M_PI));
|
||||
|
||||
auto port1referenced = port1 / ref;
|
||||
auto port2referenced = port2 / ref;
|
||||
auto port1db = 20*log10(abs(port1referenced));
|
||||
auto port2db = 20*log10(abs(port2referenced));
|
||||
|
||||
ui->port1referenced->setText(QString::number(port1db, 'f', 1) + "db@" + QString::number(arg(port1referenced)*180/M_PI, 'f', 0) + "°");
|
||||
ui->port2referenced->setText(QString::number(port2db, 'f', 1) + "db@" + QString::number(arg(port2referenced)*180/M_PI, 'f', 0) + "°");
|
||||
|
||||
// PLL state
|
||||
ui->SourceLocked->setChecked(status.source_locked);
|
||||
ui->LO1locked->setChecked(status.LO_locked);
|
||||
}
|
||||
|
||||
void ManualControlDialog::UpdateDevice()
|
||||
{
|
||||
Protocol::ManualControl m;
|
||||
// Source highband
|
||||
m.SourceHighCE = ui->SourceCE->isChecked();
|
||||
m.SourceHighRFEN = ui->SourceRFEN->isChecked();
|
||||
m.SourceHighPower = ui->SourceHighPower->currentIndex();
|
||||
m.SourceHighFrequency = ui->SourceHighFrequency->value();
|
||||
m.SourceHighLowpass = ui->SourceLowpass->currentIndex();
|
||||
// Source lowband
|
||||
m.SourceLowEN = ui->SourceLowEnable->isChecked();
|
||||
m.SourceLowPower = ui->SourceLowPower->currentIndex();
|
||||
m.SourceLowFrequency = ui->SourceLowFrequency->value();
|
||||
// Source signal path
|
||||
m.SourceHighband = ui->SwitchHighband->isChecked();
|
||||
m.AmplifierEN = ui->AmplifierEnable->isChecked();
|
||||
m.PortSwitch = ui->Port2Switch->isChecked();
|
||||
m.attenuator = -ui->Attenuator->value() / 0.25;
|
||||
// LO1
|
||||
m.LO1CE = ui->LO1CE->isChecked();
|
||||
m.LO1RFEN = ui->LO1RFEN->isChecked();
|
||||
m.LO1Frequency = ui->LO1Frequency->value();
|
||||
// LO2
|
||||
m.LO2EN = ui->LO2EN->isChecked();
|
||||
m.LO2Frequency = ui->LO2Frequency->value();
|
||||
// Acquisition
|
||||
m.Port1EN = ui->Port1Enable->isChecked();
|
||||
m.Port2EN = ui->Port2Enable->isChecked();
|
||||
m.RefEN = ui->RefEnable->isChecked();
|
||||
m.Samples = ui->Samples->value();
|
||||
|
||||
qDebug() << "Updating manual control state";
|
||||
|
||||
dev.SetManual(m);
|
||||
}
|
||||
28
Software/PC_Application/Device/manualcontroldialog.h
Normal file
28
Software/PC_Application/Device/manualcontroldialog.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef MANUALCONTROLDIALOG_H
|
||||
#define MANUALCONTROLDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include "device.h"
|
||||
|
||||
namespace Ui {
|
||||
class ManualControlDialog;
|
||||
}
|
||||
|
||||
class ManualControlDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ManualControlDialog(Device &dev, QWidget *parent = nullptr);
|
||||
~ManualControlDialog();
|
||||
|
||||
public slots:
|
||||
void NewStatus(Protocol::ManualStatus status);
|
||||
|
||||
private:
|
||||
void UpdateDevice();
|
||||
Ui::ManualControlDialog *ui;
|
||||
Device &dev;
|
||||
};
|
||||
|
||||
#endif // MANUALCONTROLDIALOG_H
|
||||
751
Software/PC_Application/Device/manualcontroldialog.ui
Normal file
751
Software/PC_Application/Device/manualcontroldialog.ui
Normal file
|
|
@ -0,0 +1,751 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ManualControlDialog</class>
|
||||
<widget class="QDialog" name="ManualControlDialog">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::ApplicationModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1023</width>
|
||||
<height>628</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Manual System Control</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_15">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_10">
|
||||
<property name="title">
|
||||
<string>Signal Generation</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_14">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Highband Source</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="SourceCE">
|
||||
<property name="text">
|
||||
<string>Chip Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="SourceRFEN">
|
||||
<property name="text">
|
||||
<string>RF Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="SourceLocked">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Locked</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Power:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="SourceHighPower">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>-4dbm</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>-1dbm</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>+2dbm</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>+5dbm</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Frequency:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="SIUnitEdit" name="SourceHighFrequency"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Lowpass:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="SourceLowpass">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>947MHz</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>1880MHz</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>3500MHz</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Lowband Source</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="SourceLowEnable">
|
||||
<property name="text">
|
||||
<string>Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Power:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="SourceLowPower">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>2mA</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>4mA</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>6mA</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>8mA</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Frequency:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="SIUnitEdit" name="SourceLowFrequency"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Source Switch</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="SwitchLowband">
|
||||
<property name="text">
|
||||
<string>Lowband</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">SourceSwitchGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="SwitchHighband">
|
||||
<property name="text">
|
||||
<string>Highband</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">SourceSwitchGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_12">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="title">
|
||||
<string>Attenuator</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="Attenuator">
|
||||
<property name="suffix">
|
||||
<string>db</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-31.750000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.250000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="title">
|
||||
<string>Amplifier</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="AmplifierEnable">
|
||||
<property name="text">
|
||||
<string>Enable</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_6">
|
||||
<property name="title">
|
||||
<string>Port Switch</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="Port1Switch">
|
||||
<property name="text">
|
||||
<string>Port 1</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">PortSwitchGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="Port2Switch">
|
||||
<property name="text">
|
||||
<string>Port 2</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">PortSwitchGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_11">
|
||||
<property name="title">
|
||||
<string>Signal Analysis</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_7">
|
||||
<property name="title">
|
||||
<string>LO1</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="LO1CE">
|
||||
<property name="text">
|
||||
<string>Chip Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="LO1RFEN">
|
||||
<property name="text">
|
||||
<string>RF Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="LO1locked">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Locked</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Freq. Type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="LO1FreqType">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>IF1</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Absolute</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Frequency:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="SIUnitEdit" name="LO1Frequency">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>IF1:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="SIUnitEdit" name="IF1"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_8">
|
||||
<property name="title">
|
||||
<string>LO2</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="LO2EN">
|
||||
<property name="text">
|
||||
<string>Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Freq. Type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="LO2FreqType">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>IF2</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Absolute</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Frequency:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="SIUnitEdit" name="LO2Frequency">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>IF2:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="SIUnitEdit" name="IF2"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_9">
|
||||
<property name="title">
|
||||
<string>Aquisition</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="Port1Enable">
|
||||
<property name="text">
|
||||
<string>Port 1 Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="Port2Enable">
|
||||
<property name="text">
|
||||
<string>Port 2 Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="RefEnable">
|
||||
<property name="text">
|
||||
<string>Reference Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_5">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Samples:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="Samples">
|
||||
<property name="minimum">
|
||||
<number>128</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>131072</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>128</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>131072</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_12">
|
||||
<property name="title">
|
||||
<string>Measurements</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_16">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_16">
|
||||
<property name="title">
|
||||
<string>Port 1</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_19">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_9">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_25">
|
||||
<property name="text">
|
||||
<string>ADC min:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="port1min"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_26">
|
||||
<property name="text">
|
||||
<string>ADC max:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="port1max"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_27">
|
||||
<property name="text">
|
||||
<string>Magnitude:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="port1mag"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_28">
|
||||
<property name="text">
|
||||
<string>Phase:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="port1phase"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Referenced:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="port1referenced"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_14">
|
||||
<property name="title">
|
||||
<string>Port 2</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_17">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_7">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string>ADC min:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="port2min"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>ADC max:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="port2max"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="text">
|
||||
<string>Magnitude:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="port2mag"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="text">
|
||||
<string>Phase:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="port2phase"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Referenced:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="port2referenced"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_15">
|
||||
<property name="title">
|
||||
<string>Reference</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_18">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_8">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="text">
|
||||
<string>ADC min:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="refmin"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_22">
|
||||
<property name="text">
|
||||
<string>ADC max:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="refmax"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_23">
|
||||
<property name="text">
|
||||
<string>Magnitude:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="refmag"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="text">
|
||||
<string>Phase:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="refphase"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SIUnitEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>CustomWidgets/siunitedit.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
<buttongroups>
|
||||
<buttongroup name="PortSwitchGroup"/>
|
||||
<buttongroup name="SourceSwitchGroup"/>
|
||||
</buttongroups>
|
||||
</ui>
|
||||
Loading…
Add table
Add a link
Reference in a new issue