USB logging

This commit is contained in:
Jan Käberich 2022-10-31 22:06:23 +01:00
parent 69f7c878b9
commit f3eb560d61
16 changed files with 731 additions and 12 deletions

View File

@ -1,6 +1,7 @@
#include "device.h"
#include "CustomWidgets/informationbox.h"
#include "deviceusblog.h"
#include <signal.h>
#include <QDebug>
@ -496,6 +497,14 @@ void Device::ReceivedData()
// qDebug() << "Decoding" << dataBuffer->getReceived() << "Bytes";
handled_len = Protocol::DecodeBuffer(dataBuffer->getBuffer(), dataBuffer->getReceived(), &packet);
// qDebug() << "Handled" << handled_len << "Bytes, type:" << (int) packet.type;
if(handled_len > 0) {
auto &log = DeviceUSBLog::getInstance();
if(packet.type != Protocol::PacketType::None) {
log.addPacket(packet, m_serial);
} else {
log.addInvalidBytes(dataBuffer->getBuffer(), handled_len, m_serial);
}
}
dataBuffer->removeBytes(handled_len);
switch(packet.type) {
case Protocol::PacketType::VNADatapoint:
@ -585,6 +594,8 @@ bool Device::startNextTransmission()
return false;
}
int actual_length;
auto &log = DeviceUSBLog::getInstance();
log.addPacket(t.packet);
auto ret = libusb_bulk_transfer(m_handle, EP_Data_Out_Addr, buffer, length, &actual_length, 0);
if(ret < 0) {
qCritical() << "Error sending data: "

View File

@ -0,0 +1,119 @@
#include "deviceusblog.h"
#include "preferences.h"
#include <QDateTime>
DeviceUSBLog::DeviceUSBLog()
: usedStorageSize(0)
{
auto &pref = Preferences::getInstance();
maxStorageSize = pref.Debug.USBlogSizeLimit;
}
DeviceUSBLog::~DeviceUSBLog()
{
}
void DeviceUSBLog::reset()
{
entries.clear();
usedStorageSize = 0;
}
void DeviceUSBLog::addPacket(Protocol::PacketInfo &p, QString serial)
{
LogEntry e;
e.timestamp = QDateTime::currentDateTimeUtc();
e.serial = serial;
e.type = LogEntry::Type::Packet;
e.p = new Protocol::PacketInfo;
*e.p = p;
addEntry(e);
}
void DeviceUSBLog::addInvalidBytes(const uint8_t *bytes, uint16_t len, QString serial)
{
LogEntry e;
e.timestamp = QDateTime::currentDateTimeUtc();
e.serial = serial;
e.type = LogEntry::Type::InvalidBytes;
while(len--) {
e.bytes.push_back(*bytes++);
}
addEntry(e);
}
nlohmann::json DeviceUSBLog::toJSON()
{
nlohmann::json j;
for(auto &e : entries) {
j.push_back(e.toJSON());
}
return j;
}
void DeviceUSBLog::fromJSON(nlohmann::json j)
{
reset();
for(auto jd : j) {
LogEntry e;
e.fromJSON(jd);
addEntry(e);
}
}
void DeviceUSBLog::addEntry(const DeviceUSBLog::LogEntry &e)
{
usedStorageSize += e.storageSize();
while(usedStorageSize > maxStorageSize) {
usedStorageSize -= entries.front().storageSize();
entries.pop_front();
}
entries.push_back(e);
emit entryAdded(e);
}
std::deque<DeviceUSBLog::LogEntry> DeviceUSBLog::getEntries() const
{
return entries;
}
nlohmann::json DeviceUSBLog::LogEntry::toJSON()
{
nlohmann::json j;
j["type"] = type == Type::Packet ? "Packet" : "InvalidBytes";
j["timestamp"] = timestamp.toMSecsSinceEpoch();
j["serial"] = serial.toStdString();
nlohmann::json jdata;
if(type == Type::Packet) {
for(unsigned int i=0;i<sizeof(Protocol::PacketInfo);i++) {
jdata.push_back(*(((uint8_t*) p) + i));
}
} else {
for(auto b : bytes) {
jdata.push_back(b);
}
}
j["data"] = jdata;
return j;
}
void DeviceUSBLog::LogEntry::fromJSON(nlohmann::json j)
{
type = QString::fromStdString(j.value("type", "")) == "Packet" ? Type::Packet : Type::InvalidBytes;
timestamp = QDateTime::fromMSecsSinceEpoch(j.value("timestamp", 0UL), Qt::TimeSpec::UTC);
serial = QString::fromStdString(j.value("serial", ""));
if(type == Type::Packet) {
p = new Protocol::PacketInfo;
auto jdata = j["data"];
for(unsigned int i=0;i<sizeof(Protocol::PacketInfo);i++) {
*(((uint8_t*) p) + i) = jdata[i];
}
} else {
for(auto v : j["data"]) {
bytes.push_back(v);
}
}
}

View File

@ -0,0 +1,75 @@
#ifndef DEVICEUSBLOG_H
#define DEVICEUSBLOG_H
#include "../../VNA_embedded/Application/Communication/Protocol.hpp"
#include "savable.h"
#include <deque>
#include <cstdint>
#include <QDateTime>
#include <QObject>
class DeviceUSBLog : public QObject, public Savable
{
Q_OBJECT
public:
static DeviceUSBLog& getInstance() {
static DeviceUSBLog instance;
return instance;
}
DeviceUSBLog(const DeviceUSBLog&) = delete;
virtual ~DeviceUSBLog();
void reset();
void addPacket(Protocol::PacketInfo &p, QString serial = "");
void addInvalidBytes(const uint8_t *bytes, uint16_t len, QString serial = "");
virtual nlohmann::json toJSON() override;
virtual void fromJSON(nlohmann::json j) override;
class LogEntry : public Savable {
public:
LogEntry()
: type(Type::InvalidBytes), timestamp(QDateTime()), serial(""), p(nullptr) {}
enum class Type {
Packet,
InvalidBytes,
};
Type type;
QDateTime timestamp;
QString serial;
std::vector<uint8_t> bytes;
Protocol::PacketInfo *p;
unsigned int storageSize() const {
unsigned long size = sizeof(type) + sizeof(timestamp) + serial.size();
switch(type) {
case Type::InvalidBytes: size += bytes.size(); break;
case Type::Packet: size += sizeof(Protocol::PacketInfo); break;
}
return size;
}
virtual nlohmann::json toJSON() override;
virtual void fromJSON(nlohmann::json j) override;
};
std::deque<LogEntry> getEntries() const;
signals:
void entryAdded(const LogEntry &e);
private:
DeviceUSBLog();
void addEntry(const LogEntry &e);
unsigned long maxStorageSize;
unsigned long usedStorageSize;
std::deque<LogEntry> entries;
};
#endif // DEVICEUSBLOG_H

View File

@ -0,0 +1,310 @@
#include "deviceusblogview.h"
#include "ui_deviceusblogview.h"
#include "CustomWidgets/informationbox.h"
#include "unit.h"
#include <fstream>
#include <iomanip>
#include <QPushButton>
#include <QFileDialog>
#include <QMessageBox>
using namespace std;
DeviceUSBLogView::DeviceUSBLogView(QWidget *parent) :
QDialog(parent),
ui(new Ui::DeviceUSBLogView)
{
setAttribute(Qt::WA_DeleteOnClose);
ui->setupUi(this);
// connect(&log, &DeviceUSBLog::entryAdded, this, &DeviceUSBLogView::addEntry);
connect(ui->buttonBox->button(QDialogButtonBox::Reset), &QPushButton::clicked, [=](){
DeviceUSBLog::getInstance().reset();
updateTree();
});
connect(ui->buttonBox->button(QDialogButtonBox::Save), &QPushButton::clicked, [=](){
QString filename = QFileDialog::getSaveFileName(nullptr, "Load USB log data", "", "USB log files (*.usblog)", nullptr, QFileDialog::DontUseNativeDialog);
if(filename.isEmpty()) {
// aborted selection
return;
}
if(!filename.endsWith(".usblog")) {
filename.append(".usblog");
}
ofstream file;
file.open(filename.toStdString());
file << setw(1) << DeviceUSBLog::getInstance().toJSON() << endl;
file.close();
});
connect(ui->buttonBox->button(QDialogButtonBox::Open), &QPushButton::clicked, [=](){
QString filename = QFileDialog::getOpenFileName(nullptr, "Load USB log data", "", "USB log files (*.usblog)", nullptr, QFileDialog::DontUseNativeDialog);
if(filename.isEmpty()) {
// aborted selection
return;
}
ifstream file;
file.open(filename.toStdString());
if(!file.is_open()) {
qWarning() << "Unable to open file:" << filename;
return;
}
nlohmann::json j;
try {
// TODO this can take a long time, move to thread
file >> j;
} catch (exception &e) {
InformationBox::ShowError("Error", "Failed to parse the USB log file (" + QString(e.what()) + ")");
qWarning() << "Parsing of USB log file failed: " << e.what();
file.close();
return;
}
file.close();
DeviceUSBLog::getInstance().fromJSON(j);
updateTree();
});
updateTree();
}
DeviceUSBLogView::~DeviceUSBLogView()
{
delete ui;
}
void DeviceUSBLogView::updateTree()
{
auto &log = DeviceUSBLog::getInstance();
ui->tree->clear();
ui->tree->setColumnCount(4);
ui->tree->setHeaderLabels({"Timestamp","Source","Type","Content"});
for(auto &e : log.getEntries()) {
addEntry(e);
}
}
void DeviceUSBLogView::addEntry(const DeviceUSBLog::LogEntry &e)
{
auto item = new QTreeWidgetItem;
item->setData(0, Qt::DisplayRole, e.timestamp.toString(Qt::DateFormat::ISODateWithMs));
item->setData(1, Qt::DisplayRole, e.serial.size() > 0 ? e.serial : "LibreVNA-GUI");
item->setData(2, Qt::DisplayRole, e.type == DeviceUSBLog::LogEntry::Type::Packet ? "Packet" : "Invalid bytes");
if(e.type == DeviceUSBLog::LogEntry::Type::Packet) {
item->setData(2, Qt::DisplayRole, "Packet");
static const QStringList packetNames = {"None", "Datapoint", "SweepSettings", "ManualStatusV1", "ManualControlV1", "DeviceInfo", "FirmwarePacket", "Ack",
"ClearFlash", "PerformFirmwareUpdate", "Nack", "Reference", "Generator", "SpectrumAnalyzerSettings",
"SpectrumAnalyzerResult", "RequestDeviceInfo", "RequestSourceCal", "RequestReceiverCal", "SourceCalPoint",
"ReceiverCalPoint", "SetIdle", "RequestFrequencyCorrection", "FrequencyCorrection", "RequestAcquisitionFrequencySettings",
"AcquisitionFrequencySettings", "DeviceStatusV1", "RequestDeviceStatus", "VNADatapoint", "SetTrigger", "ClearTrigger"};
item->setData(3, Qt::DisplayRole, "Type "+QString::number((int)e.p->type)+"("+packetNames[(int)e.p->type]+")");
auto addDouble = [=](QTreeWidgetItem *parent, QString name, double value, QString unit = "", int precision = 8) {
auto subitem = new QTreeWidgetItem;
subitem->setData(2, Qt::DisplayRole, name);
subitem->setData(3, Qt::DisplayRole, Unit::ToString(value, unit, "pnum kMG", precision));
parent->addChild(subitem);
};
auto addInteger = [=](QTreeWidgetItem *parent, QString name, int value) {
auto subitem = new QTreeWidgetItem;
subitem->setData(2, Qt::DisplayRole, name);
subitem->setData(3, Qt::DisplayRole, value);
parent->addChild(subitem);
};
auto addBool = [=](QTreeWidgetItem *parent, QString name, bool value) {
auto subitem = new QTreeWidgetItem;
subitem->setData(2, Qt::DisplayRole, name);
subitem->setData(3, Qt::DisplayRole, value ? "true" : "false");
parent->addChild(subitem);
};
auto addEnum = [=](QTreeWidgetItem *parent, QString name, int value, QStringList names) {
auto subitem = new QTreeWidgetItem;
subitem->setData(2, Qt::DisplayRole, name);
subitem->setData(3, Qt::DisplayRole, names[value]);
parent->addChild(subitem);
};
auto addString = [=](QTreeWidgetItem *parent, QString name, QString value) {
auto subitem = new QTreeWidgetItem;
subitem->setData(2, Qt::DisplayRole, name);
subitem->setData(3, Qt::DisplayRole, value);
parent->addChild(subitem);
};
switch(e.p->type) {
case Protocol::PacketType::SweepSettings: {
Protocol::SweepSettings s = e.p->settings;
addDouble(item, "Start frequency", s.f_start, "Hz");
addDouble(item, "Stop frequency", s.f_stop, "Hz");
addInteger(item, "Points", s.points);
addDouble(item, "IF bandwidth", s.if_bandwidth, "Hz");
addDouble(item, "Start power", (double) s.cdbm_excitation_start / 100.0, "dBm");
addDouble(item, "Stop power", (double) s.cdbm_excitation_stop / 100.0, "dBm");
addEnum(item, "Sync mode", s.syncMode, {"no synchronization", "USB", "Ext. reference", "Ext. trigger"});
addBool(item, "Sync Master", s.syncMaster);
addBool(item, "Suppress peaks", s.suppressPeaks);
addBool(item, "Fixed power setting", s.fixedPowerSetting);
addBool(item, "Logarithmic sweep", s.logSweep);
addInteger(item, "Stages", s.stages);
addInteger(item, "Port 1 stage", s.port1Stage);
addInteger(item, "Port 2 stage", s.port2Stage);
}
break;
case Protocol::PacketType::Reference: {
Protocol::ReferenceSettings s = e.p->reference;
addDouble(item, "Output frequency", s.ExtRefOuputFreq, "Hz");
addBool(item, "Switch automatically", s.AutomaticSwitch);
addBool(item, "Use external reference", s.UseExternalRef);
}
break;
case Protocol::PacketType::Generator: {
Protocol::GeneratorSettings s = e.p->generator;
addDouble(item, "Frequency", s.frequency, "Hz");
addDouble(item, "Power", (double) s.cdbm_level / 100.0, "dBm");
addBool(item, "Use source calibration", s.applyAmplitudeCorrection);
addInteger(item, "Active port", s.activePort);
}
break;
case Protocol::PacketType::DeviceStatusV1: {
Protocol::DeviceStatusV1 s = e.p->statusV1;
addBool(item, "External reference available", s.extRefAvailable);
addBool(item, "External reference in use", s.extRefInUse);
addBool(item, "FPGA configured", s.FPGA_configured);
addBool(item, "Source locked", s.source_locked);
addBool(item, "1.LO locked", s.LO1_locked);
addBool(item, "ADC overload", s.ADC_overload);
addBool(item, "Unlevel", s.unlevel);
addInteger(item, "Source temperature", s.temp_source);
addInteger(item, "1.LO temperature", s.temp_LO1);
addInteger(item, "MCU temperature", s.temp_MCU);
}
break;
case Protocol::PacketType::DeviceInfo: {
Protocol::DeviceInfo s = e.p->info;
addInteger(item, "Protocol version", s.ProtocolVersion);
addInteger(item, "Firmware major", s.FW_major);
addInteger(item, "Firmware minor", s.FW_minor);
addInteger(item, "Firmware patch", s.FW_patch);
addInteger(item, "Hardware version", s.hardware_version);
addString(item, "Hardware version", QString(s.HW_Revision));
addDouble(item, "Minimum frequency", s.limits_minFreq, "Hz");
addDouble(item, "Maximum frequency", s.limits_maxFreq, "Hz");
addDouble(item, "Minimum IF bandwidth", s.limits_minIFBW, "Hz");
addDouble(item, "Maximum IF bandwidht", s.limits_maxIFBW, "Hz");
addInteger(item, "Maximum points", s.limits_maxPoints);
addDouble(item, "Minimum power", (double) s.limits_cdbm_min / 100.0, "dBm");
addDouble(item, "Maximum power", (double) s.limits_cdbm_max / 100.0, "dBm");
addDouble(item, "Minimum RBW", s.limits_minRBW, "Hz");
addDouble(item, "Maximum RBW", s.limits_maxRBW, "Hz");
addInteger(item, "Maximum amplitude points", s.limits_maxAmplitudePoints);
addDouble(item, "Maximum harmonic frequency", s.limits_maxFreqHarmonic, "Hz");
}
break;
case Protocol::PacketType::ManualControlV1:
case Protocol::PacketType::ManualStatusV1:
// TODO
break;
case Protocol::PacketType::SpectrumAnalyzerSettings: {
Protocol::SpectrumAnalyzerSettings s = e.p->spectrumSettings;
addDouble(item, "Start frequency", s.f_start, "Hz");
addDouble(item, "Stop frequency", s.f_stop, "Hz");
addInteger(item, "Points", s.pointNum);
addDouble(item, "Resolution bandwidth", s.RBW, "Hz");
addEnum(item, "Window", s.syncMode, {"None", "Kaiser", "Hann", "Flattop"});
addBool(item, "Signal ID", s.SignalID);
addBool(item, "Use DFT", s.UseDFT);
addBool(item, "Use receiver calibration", s.applyReceiverCorrection);
addBool(item, "Use source calibration", s.applySourceCorrection);
addEnum(item, "Detector", s.Detector, {"Positive peak", "Negative peak", "Sample", "Normal", "Average"});
addEnum(item, "Sync mode", s.syncMode, {"no synchronization", "USB", "Ext. reference", "Ext. trigger"});
addBool(item, "Sync Master", s.syncMaster);
addBool(item, "Enable tracking generator", s.trackingGenerator);
addInteger(item, "Tracking generator port", s.trackingGeneratorPort+1);
addDouble(item, "Tracking generator offset", s.trackingGeneratorOffset, "Hz");
addDouble(item, "Tracking generator power", (double) s.trackingPower / 100.0, "dBm");
}
break;
case Protocol::PacketType::VNADatapoint: {
// TODO VNAdatapoint will already be deleted. Create deep copy when creating the log entry?
// Protocol::VNADatapoint<32>* s = e.p->VNAdatapoint;
// addInteger(item, "Point number", s->pointNum);
// addDouble(item, "Frequency/time", s->frequency, "Hz");
// addDouble(item, "Power", (double) s->cdBm / 100.0, "dBm");
// for(unsigned int i=0;i<s->getNumValues();i++) {
// auto v = s->getValue(i);
// vector<int> ports;
// if(v.flags & 0x01) {
// ports.push_back(1);
// }
// if(v.flags & 0x02) {
// ports.push_back(2);
// }
// if(v.flags & 0x04) {
// ports.push_back(3);
// }
// if(v.flags & 0x08) {
// ports.push_back(4);
// }
// bool reference = v.flags & 0x10;
// int stage = v.flags >> 5;
// auto vitem = new QTreeWidgetItem;
// vitem->setData(2, Qt::DisplayRole, "Measurement "+QString::number(i+1));
// vitem->setData(3, Qt::DisplayRole, "Real: "+QString::number(v.value.real())+" Imag: "+QString::number(v.value.imag()));
// addInteger(vitem, "Stage", stage);
// addBool(vitem, "Reference", reference);
// QString sports = QString::number(ports.front());
// for(unsigned int j=1;j<ports.size();j++) {
// sports += ","+QString::number(ports[j]);
// }
// addString(vitem, "Ports", sports);
// item->addChild(vitem);
// }
}
break;
case Protocol::PacketType::SpectrumAnalyzerResult: {
Protocol::SpectrumAnalyzerResult s = e.p->spectrumResult;
addDouble(item, "Port 1 level", s.port1);
addDouble(item, "Port 2 level", s.port2);
addDouble(item, "Frequency/time", s.frequency, "Hz");
addInteger(item, "Point number", s.pointNum);
}
break;
case Protocol::PacketType::SourceCalPoint:
case Protocol::PacketType::ReceiverCalPoint: {
Protocol::AmplitudeCorrectionPoint s = e.p->amplitudePoint;
addInteger(item, "Total points", s.totalPoints);
addInteger(item, "Point number", s.pointNum);
addDouble(item, "Frequency", s.freq, "Hz");
addInteger(item, "Port 1 correction", s.port1);
addInteger(item, "Port 2 correction", s.port2);
}
break;
case Protocol::PacketType::FrequencyCorrection: {
Protocol::FrequencyCorrection s = e.p->frequencyCorrection;
addDouble(item, "ppm", s.ppm, "");
}
break;
case Protocol::PacketType::AcquisitionFrequencySettings: {
Protocol::AcquisitionFrequencySettings s = e.p->acquisitionFrequencySettings;
addDouble(item, "1.IF", s.IF1, "Hz");
addInteger(item, "ADC prescaler", s.ADCprescaler);
addInteger(item, "DFT phase increment", s.DFTphaseInc);
}
break;
default:
break;
}
} else {
item->setData(2, Qt::DisplayRole, "Invalid bytes");
item->setData(3, Qt::DisplayRole, QString::number(e.bytes.size())+ " bytes");
for(auto b : e.bytes) {
auto subitem = new QTreeWidgetItem;
subitem->setData(3, Qt::DisplayRole, "0x"+QString::number(b, 16));
item->addChild(subitem);
}
}
ui->tree->addTopLevelItem(item);
}

View File

@ -0,0 +1,27 @@
#ifndef DEVICEUSBLOGVIEW_H
#define DEVICEUSBLOGVIEW_H
#include "deviceusblog.h"
#include <QDialog>
namespace Ui {
class DeviceUSBLogView;
}
class DeviceUSBLogView : public QDialog
{
Q_OBJECT
public:
explicit DeviceUSBLogView(QWidget *parent = nullptr);
~DeviceUSBLogView();
private slots:
void updateTree();
void addEntry(const DeviceUSBLog::LogEntry &e);
private:
Ui::DeviceUSBLogView *ui;
};
#endif // DEVICEUSBLOGVIEW_H

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DeviceUSBLogView</class>
<widget class="QDialog" name="DeviceUSBLogView">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>845</width>
<height>553</height>
</rect>
</property>
<property name="windowTitle">
<string>USB Log</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTreeWidget" name="tree">
<property name="headerHidden">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Open|QDialogButtonBox::Reset|QDialogButtonBox::Save</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -25,6 +25,8 @@ HEADERS += \
Device/compounddeviceeditdialog.h \
Device/device.h \
Device/devicelog.h \
Device/deviceusblog.h \
Device/deviceusblogview.h \
Device/firmwareupdatedialog.h \
Device/manualcontroldialog.h \
Device/virtualdevice.h \
@ -169,6 +171,8 @@ SOURCES += \
Device/compounddeviceeditdialog.cpp \
Device/device.cpp \
Device/devicelog.cpp \
Device/deviceusblog.cpp \
Device/deviceusblogview.cpp \
Device/firmwareupdatedialog.cpp \
Device/manualcontroldialog.cpp \
Device/virtualdevice.cpp \
@ -302,6 +306,7 @@ FORMS += \
CustomWidgets/touchstoneimport.ui \
Device/compounddeviceeditdialog.ui \
Device/devicelog.ui \
Device/deviceusblogview.ui \
Device/firmwareupdatedialog.ui \
Device/manualcontroldialog.ui \
Generator/signalgenwidget.ui \

View File

@ -3,6 +3,7 @@
#include "unit.h"
#include "CustomWidgets/toggleswitch.h"
#include "Device/manualcontroldialog.h"
#include "Device/deviceusblogview.h"
#include "Traces/tracemodel.h"
#include "Traces/tracewidget.h"
#include "Traces/tracesmithchart.h"
@ -232,6 +233,7 @@ void AppWindow::SetupMenu()
});
connect(ui->actionManual_Control, &QAction::triggered, this, &AppWindow::StartManualControl);
connect(ui->actionUSB_log, &QAction::triggered, this, &AppWindow::ShowUSBLog);
connect(ui->actionFirmware_Update, &QAction::triggered, this, &AppWindow::StartFirmwareUpdateDialog);
connect(ui->actionSource_Calibration, &QAction::triggered, this, &AppWindow::SourceCalibrationDialog);
connect(ui->actionReceiver_Calibration, &QAction::triggered, this, &AppWindow::ReceiverCalibrationDialog);
@ -993,6 +995,14 @@ void AppWindow::UpdateAcquisitionFrequencies()
}
}
void AppWindow::ShowUSBLog()
{
auto d = new DeviceUSBLogView();
if(AppWindow::showGUI()) {
d->exec();
}
}
void AppWindow::StartFirmwareUpdateDialog()
{
if(!vdevice || vdevice->isCompoundDevice()) {

View File

@ -64,6 +64,7 @@ private slots:
void UpdateReferenceToolbar();
void UpdateReference();
void UpdateAcquisitionFrequencies();
void ShowUSBLog();
void StartFirmwareUpdateDialog();
void DeviceNeedsUpdate(int reported, int expected);
void DeviceStatusUpdated(VirtualDevice::Status status);

View File

@ -55,6 +55,8 @@
<addaction name="actionSource_Calibration"/>
<addaction name="actionReceiver_Calibration"/>
<addaction name="actionFrequency_Calibration"/>
<addaction name="separator"/>
<addaction name="actionUSB_log"/>
</widget>
<widget class="QMenu" name="menuWindow">
<property name="title">
@ -224,6 +226,14 @@
<string>Preset</string>
</property>
</action>
<action name="actionUSB_log">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>View USB log</string>
</property>
</action>
</widget>
<resources>
<include location="icons.qrc"/>

View File

@ -212,6 +212,10 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
}
});
// Debug page
ui->DebugMaxUSBlogSize->setUnit("B");
ui->DebugMaxUSBlogSize->setPrefixes(" kMG");
// Page selection
connect(ui->treeWidget, &QTreeWidget::currentItemChanged, [=](QTreeWidgetItem *current, QTreeWidgetItem *) {
auto name = current->text(0);
@ -383,6 +387,8 @@ void PreferencesDialog::setInitialGUIState()
ui->SCPIServerEnabled->setChecked(p->SCPIServer.enabled);
ui->SCPIServerPort->setValue(p->SCPIServer.port);
ui->DebugMaxUSBlogSize->setValue(p->Debug.USBlogSizeLimit);
for(auto cd : p->compoundDevices) {
ui->compoundList->addItem(cd->getDesription());
}
@ -484,6 +490,8 @@ void PreferencesDialog::updateFromGUI()
p->SCPIServer.enabled = ui->SCPIServerEnabled->isChecked();
p->SCPIServer.port = ui->SCPIServerPort->value();
p->Debug.USBlogSizeLimit = ui->DebugMaxUSBlogSize->value();
p->nonTrivialWriting();
}

View File

@ -160,6 +160,9 @@ public:
bool enabled;
int port;
} SCPIServer;
struct {
double USBlogSizeLimit;
} Debug;
bool TCPoverride; // in case of manual port specification via command line
@ -264,6 +267,7 @@ private:
{&Marker.symbolStyle, "Marker.symbolStyle", MarkerSymbolStyle::EmptyNumberAbove},
{&SCPIServer.enabled, "SCPIServer.enabled", true},
{&SCPIServer.port, "SCPIServer.port", 19542},
{&Debug.USBlogSizeLimit, "Debug.USBlogSizeLimit", 10000000.0},
{&compoundDeviceJSON, "compoundDeviceJSON", "[]"},
}};
};

View File

@ -71,6 +71,11 @@
<string>Compound Devices</string>
</property>
</item>
<item>
<property name="text">
<string>Debug</string>
</property>
</item>
</widget>
</item>
<item>
@ -88,7 +93,7 @@
</size>
</property>
<property name="currentIndex">
<number>3</number>
<number>6</number>
</property>
<widget class="QWidget" name="Startup">
<layout class="QHBoxLayout" name="horizontalLayout_4">
@ -707,8 +712,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>749</width>
<height>846</height>
<width>565</width>
<height>863</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_21">
@ -1028,8 +1033,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>749</width>
<height>952</height>
<width>553</width>
<height>969</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_22">
@ -1450,7 +1455,7 @@
<property name="geometry">
<rect>
<x>0</x>
<y>-15</y>
<y>0</y>
<width>749</width>
<height>576</height>
</rect>
@ -1769,8 +1774,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>168</width>
<height>127</height>
<width>763</width>
<height>561</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_12">
@ -1859,8 +1864,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>126</width>
<height>90</height>
<width>763</width>
<height>561</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_24">
@ -1918,6 +1923,78 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="Debug">
<layout class="QVBoxLayout" name="verticalLayout_29">
<item>
<widget class="QScrollArea" name="scrollArea_7">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_5">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>763</width>
<height>561</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_19">
<item>
<layout class="QVBoxLayout" name="verticalLayout_30">
<item>
<widget class="QGroupBox" name="groupBox_23">
<property name="title">
<string>USB logging</string>
</property>
<layout class="QFormLayout" name="formLayout_15">
<item row="0" column="0">
<widget class="QLabel" name="label_54">
<property name="text">
<string>Maximum size:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="SIUnitEdit" name="DebugMaxUSBlogSize"/>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_9">
<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>
<item>
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>366</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>

View File

@ -32,6 +32,8 @@ SOURCES += \
../LibreVNA-GUI/Device/compounddeviceeditdialog.cpp \
../LibreVNA-GUI/Device/device.cpp \
../LibreVNA-GUI/Device/devicelog.cpp \
../LibreVNA-GUI/Device/deviceusblog.cpp \
../LibreVNA-GUI/Device/deviceusblogview.cpp \
../LibreVNA-GUI/Device/firmwareupdatedialog.cpp \
../LibreVNA-GUI/Device/manualcontroldialog.cpp \
../LibreVNA-GUI/Device/virtualdevice.cpp \
@ -195,6 +197,8 @@ HEADERS += \
../LibreVNA-GUI/Device/compounddeviceeditdialog.h \
../LibreVNA-GUI/Device/device.h \
../LibreVNA-GUI/Device/devicelog.h \
../LibreVNA-GUI/Device/deviceusblog.h \
../LibreVNA-GUI/Device/deviceusblogview.h \
../LibreVNA-GUI/Device/firmwareupdatedialog.h \
../LibreVNA-GUI/Device/manualcontroldialog.h \
../LibreVNA-GUI/Device/virtualdevice.h \
@ -339,6 +343,7 @@ FORMS += \
../LibreVNA-GUI/CustomWidgets/touchstoneimport.ui \
../LibreVNA-GUI/Device/compounddeviceeditdialog.ui \
../LibreVNA-GUI/Device/devicelog.ui \
../LibreVNA-GUI/Device/deviceusblogview.ui \
../LibreVNA-GUI/Device/firmwareupdatedialog.ui \
../LibreVNA-GUI/Device/manualcontroldialog.ui \
../LibreVNA-GUI/Generator/signalgenwidget.ui \

View File

@ -1,5 +1,5 @@
2F62501ED4689FB349E356AB974DBE57=EF826FD321FB312AEADE4DB74B81458C
2F62501ED4689FB349E356AB974DBE57=6F84FD31C089E822CF61FFCABCD0B7D1
66BE74F758C12D739921AEA421D593D3=2
8DF89ED150041C4CBC7CB9A9CAA90856=EF826FD321FB312AEADE4DB74B81458C
8DF89ED150041C4CBC7CB9A9CAA90856=6F84FD31C089E822CF61FFCABCD0B7D1
DC22A860405A8BF2F2C095E5B6529F12=6E2D4146EA2709ED1E4A1764BC291F57
eclipse.preferences.version=1

View File

@ -88,6 +88,25 @@ public:
return std::numeric_limits<std::complex<double>>::quiet_NaN();
}
class Value {
public:
std::complex<double> value;
uint8_t flags;
};
Value getValue(unsigned int index) {
Value v;
v.value = 0.0;
v.flags = 0;
if(index <= num_values) {
v.value = std::complex<double>(real_values[index], imag_values[index]);
v.flags = descr_values[index];
}
return v;
}
unsigned int getNumValues() {
return num_values;
}
uint16_t requiredBufferSize() {
return 8+2+2+ num_values * (4+4+1);
}