From f3eb560d61f140939db94e09432fbf2b61e72dd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=A4berich?= Date: Mon, 31 Oct 2022 22:06:23 +0100 Subject: [PATCH] USB logging --- .../LibreVNA-GUI/Device/device.cpp | 11 + .../LibreVNA-GUI/Device/deviceusblog.cpp | 119 +++++++ .../LibreVNA-GUI/Device/deviceusblog.h | 75 +++++ .../LibreVNA-GUI/Device/deviceusblogview.cpp | 310 ++++++++++++++++++ .../LibreVNA-GUI/Device/deviceusblogview.h | 27 ++ .../LibreVNA-GUI/Device/deviceusblogview.ui | 38 +++ .../LibreVNA-GUI/LibreVNA-GUI.pro | 5 + .../PC_Application/LibreVNA-GUI/appwindow.cpp | 10 + .../PC_Application/LibreVNA-GUI/appwindow.h | 1 + Software/PC_Application/LibreVNA-GUI/main.ui | 10 + .../LibreVNA-GUI/preferences.cpp | 8 + .../PC_Application/LibreVNA-GUI/preferences.h | 4 + .../LibreVNA-GUI/preferencesdialog.ui | 97 +++++- .../LibreVNA-Test/LibreVNA-Test.pro | 5 + .../.settings/stm32cubeide.project.prefs | 4 +- .../Application/Communication/Protocol.hpp | 19 ++ 16 files changed, 731 insertions(+), 12 deletions(-) create mode 100644 Software/PC_Application/LibreVNA-GUI/Device/deviceusblog.cpp create mode 100644 Software/PC_Application/LibreVNA-GUI/Device/deviceusblog.h create mode 100644 Software/PC_Application/LibreVNA-GUI/Device/deviceusblogview.cpp create mode 100644 Software/PC_Application/LibreVNA-GUI/Device/deviceusblogview.h create mode 100644 Software/PC_Application/LibreVNA-GUI/Device/deviceusblogview.ui diff --git a/Software/PC_Application/LibreVNA-GUI/Device/device.cpp b/Software/PC_Application/LibreVNA-GUI/Device/device.cpp index 1706c9f..329d962 100644 --- a/Software/PC_Application/LibreVNA-GUI/Device/device.cpp +++ b/Software/PC_Application/LibreVNA-GUI/Device/device.cpp @@ -1,6 +1,7 @@ #include "device.h" #include "CustomWidgets/informationbox.h" +#include "deviceusblog.h" #include #include @@ -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: " diff --git a/Software/PC_Application/LibreVNA-GUI/Device/deviceusblog.cpp b/Software/PC_Application/LibreVNA-GUI/Device/deviceusblog.cpp new file mode 100644 index 0000000..d8c3605 --- /dev/null +++ b/Software/PC_Application/LibreVNA-GUI/Device/deviceusblog.cpp @@ -0,0 +1,119 @@ +#include "deviceusblog.h" + +#include "preferences.h" + +#include + +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::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 +#include +#include +#include + +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 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 getEntries() const; + +signals: + void entryAdded(const LogEntry &e); + +private: + DeviceUSBLog(); + + void addEntry(const LogEntry &e); + + unsigned long maxStorageSize; + unsigned long usedStorageSize; + std::deque entries; +}; + +#endif // DEVICEUSBLOG_H diff --git a/Software/PC_Application/LibreVNA-GUI/Device/deviceusblogview.cpp b/Software/PC_Application/LibreVNA-GUI/Device/deviceusblogview.cpp new file mode 100644 index 0000000..0e0692f --- /dev/null +++ b/Software/PC_Application/LibreVNA-GUI/Device/deviceusblogview.cpp @@ -0,0 +1,310 @@ +#include "deviceusblogview.h" +#include "ui_deviceusblogview.h" + +#include "CustomWidgets/informationbox.h" +#include "unit.h" + +#include +#include + +#include +#include +#include + +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;igetNumValues();i++) { +// auto v = s->getValue(i); +// vector 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;jaddChild(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); +} diff --git a/Software/PC_Application/LibreVNA-GUI/Device/deviceusblogview.h b/Software/PC_Application/LibreVNA-GUI/Device/deviceusblogview.h new file mode 100644 index 0000000..d6c4459 --- /dev/null +++ b/Software/PC_Application/LibreVNA-GUI/Device/deviceusblogview.h @@ -0,0 +1,27 @@ +#ifndef DEVICEUSBLOGVIEW_H +#define DEVICEUSBLOGVIEW_H + +#include "deviceusblog.h" + +#include + +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 diff --git a/Software/PC_Application/LibreVNA-GUI/Device/deviceusblogview.ui b/Software/PC_Application/LibreVNA-GUI/Device/deviceusblogview.ui new file mode 100644 index 0000000..63f325d --- /dev/null +++ b/Software/PC_Application/LibreVNA-GUI/Device/deviceusblogview.ui @@ -0,0 +1,38 @@ + + + DeviceUSBLogView + + + + 0 + 0 + 845 + 553 + + + + USB Log + + + + + + false + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Open|QDialogButtonBox::Reset|QDialogButtonBox::Save + + + + + + + + diff --git a/Software/PC_Application/LibreVNA-GUI/LibreVNA-GUI.pro b/Software/PC_Application/LibreVNA-GUI/LibreVNA-GUI.pro index 278f975..0c80239 100644 --- a/Software/PC_Application/LibreVNA-GUI/LibreVNA-GUI.pro +++ b/Software/PC_Application/LibreVNA-GUI/LibreVNA-GUI.pro @@ -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 \ diff --git a/Software/PC_Application/LibreVNA-GUI/appwindow.cpp b/Software/PC_Application/LibreVNA-GUI/appwindow.cpp index 9170e88..23ceed1 100644 --- a/Software/PC_Application/LibreVNA-GUI/appwindow.cpp +++ b/Software/PC_Application/LibreVNA-GUI/appwindow.cpp @@ -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()) { diff --git a/Software/PC_Application/LibreVNA-GUI/appwindow.h b/Software/PC_Application/LibreVNA-GUI/appwindow.h index 65ac1dc..8ff9517 100644 --- a/Software/PC_Application/LibreVNA-GUI/appwindow.h +++ b/Software/PC_Application/LibreVNA-GUI/appwindow.h @@ -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); diff --git a/Software/PC_Application/LibreVNA-GUI/main.ui b/Software/PC_Application/LibreVNA-GUI/main.ui index cf71388..d34044d 100644 --- a/Software/PC_Application/LibreVNA-GUI/main.ui +++ b/Software/PC_Application/LibreVNA-GUI/main.ui @@ -55,6 +55,8 @@ + + @@ -224,6 +226,14 @@ Preset + + + true + + + View USB log + + diff --git a/Software/PC_Application/LibreVNA-GUI/preferences.cpp b/Software/PC_Application/LibreVNA-GUI/preferences.cpp index c71751c..d5e7d73 100644 --- a/Software/PC_Application/LibreVNA-GUI/preferences.cpp +++ b/Software/PC_Application/LibreVNA-GUI/preferences.cpp @@ -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(); } diff --git a/Software/PC_Application/LibreVNA-GUI/preferences.h b/Software/PC_Application/LibreVNA-GUI/preferences.h index 521ffe3..76c1e14 100644 --- a/Software/PC_Application/LibreVNA-GUI/preferences.h +++ b/Software/PC_Application/LibreVNA-GUI/preferences.h @@ -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", "[]"}, }}; }; diff --git a/Software/PC_Application/LibreVNA-GUI/preferencesdialog.ui b/Software/PC_Application/LibreVNA-GUI/preferencesdialog.ui index cd46f7c..01e236d 100644 --- a/Software/PC_Application/LibreVNA-GUI/preferencesdialog.ui +++ b/Software/PC_Application/LibreVNA-GUI/preferencesdialog.ui @@ -71,6 +71,11 @@ Compound Devices + + + Debug + + @@ -88,7 +93,7 @@ - 3 + 6 @@ -707,8 +712,8 @@ 0 0 - 749 - 846 + 565 + 863 @@ -1028,8 +1033,8 @@ 0 0 - 749 - 952 + 553 + 969 @@ -1450,7 +1455,7 @@ 0 - -15 + 0 749 576 @@ -1769,8 +1774,8 @@ 0 0 - 168 - 127 + 763 + 561 @@ -1859,8 +1864,8 @@ 0 0 - 126 - 90 + 763 + 561 @@ -1918,6 +1923,78 @@ + + + + + + true + + + + + 0 + 0 + 763 + 561 + + + + + + + + + USB logging + + + + + + Maximum size: + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Qt::Horizontal + + + + 366 + 20 + + + + + + + + + + diff --git a/Software/PC_Application/LibreVNA-Test/LibreVNA-Test.pro b/Software/PC_Application/LibreVNA-Test/LibreVNA-Test.pro index 2ce06b9..8ea1981 100644 --- a/Software/PC_Application/LibreVNA-Test/LibreVNA-Test.pro +++ b/Software/PC_Application/LibreVNA-Test/LibreVNA-Test.pro @@ -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 \ diff --git a/Software/VNA_embedded/.settings/stm32cubeide.project.prefs b/Software/VNA_embedded/.settings/stm32cubeide.project.prefs index 586dde5..60e3eec 100644 --- a/Software/VNA_embedded/.settings/stm32cubeide.project.prefs +++ b/Software/VNA_embedded/.settings/stm32cubeide.project.prefs @@ -1,5 +1,5 @@ -2F62501ED4689FB349E356AB974DBE57=EF826FD321FB312AEADE4DB74B81458C +2F62501ED4689FB349E356AB974DBE57=6F84FD31C089E822CF61FFCABCD0B7D1 66BE74F758C12D739921AEA421D593D3=2 -8DF89ED150041C4CBC7CB9A9CAA90856=EF826FD321FB312AEADE4DB74B81458C +8DF89ED150041C4CBC7CB9A9CAA90856=6F84FD31C089E822CF61FFCABCD0B7D1 DC22A860405A8BF2F2C095E5B6529F12=6E2D4146EA2709ED1E4A1764BC291F57 eclipse.preferences.version=1 diff --git a/Software/VNA_embedded/Application/Communication/Protocol.hpp b/Software/VNA_embedded/Application/Communication/Protocol.hpp index 803eeb3..637eba1 100644 --- a/Software/VNA_embedded/Application/Communication/Protocol.hpp +++ b/Software/VNA_embedded/Application/Communication/Protocol.hpp @@ -88,6 +88,25 @@ public: return std::numeric_limits>::quiet_NaN(); } + class Value { + public: + std::complex 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(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); }