From be7cf38e050e09e81dfb502751d2c19e8927d328 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=A4berich?= Date: Mon, 19 May 2025 16:50:24 +0200 Subject: [PATCH] WIP: ADC spectrum --- .../Device/LibreVNA/librevnadriver.cpp | 2 +- .../LibreVNA/manualcontroldialogvfd.cpp | 120 +++- .../Device/LibreVNA/manualcontroldialogvfd.h | 14 + .../Device/LibreVNA/manualcontroldialogvfd.ui | 429 +++++++----- .../LibreVNA-GUI/LibreVNA-GUI.pro | 2 +- .../LibreVNA-Test/LibreVNA-Test.pro | 2 +- .../Communication/PacketConstants.h | 67 +- .../Application/Communication/Protocol.cpp | 182 +++--- .../Application/Communication/Protocol.hpp | 618 +++++++++--------- 9 files changed, 861 insertions(+), 575 deletions(-) diff --git a/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/librevnadriver.cpp b/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/librevnadriver.cpp index bae9d11..37d89e2 100644 --- a/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/librevnadriver.cpp +++ b/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/librevnadriver.cpp @@ -146,7 +146,7 @@ LibreVNADriver::LibreVNADriver() break; } if(manualControlDialog) { - manualControlDialog->show(); + manualControlDialog->showMaximized(); connect(manualControlDialog, &QDialog::finished, this, [=](){ manualControlDialog = nullptr; }); diff --git a/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/manualcontroldialogvfd.cpp b/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/manualcontroldialogvfd.cpp index fa35898..308dc37 100644 --- a/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/manualcontroldialogvfd.cpp +++ b/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/manualcontroldialogvfd.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -18,6 +19,7 @@ ManualControlDialogVFD::ManualControlDialogVFD(LibreVNADriver &dev, QWidget *par { ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose); + setWindowFlags(Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint); emit dev.acquireControl(); @@ -44,6 +46,8 @@ ManualControlDialogVFD::ManualControlDialogVFD(LibreVNADriver &dev, QWidget *par ui->DACAmplitudeA->setValue(2047); ui->DACAmplitudeB->setValue(2047); + ui->ADCSamples->setValue(1024); + auto updateVariableAtt = [=](unsigned int value){ ui->SourceVariableAttSlider->setValue(value); ui->SourceVariableAttEntry->setValueQuiet(value); @@ -64,11 +68,38 @@ ManualControlDialogVFD::ManualControlDialogVFD(LibreVNADriver &dev, QWidget *par MakeReadOnly(ui->SourceLocked); MakeReadOnly(ui->LOLocked); -// connect(&dev, &LibreVNADriver::receivedPacket, this, [=](const Protocol::PacketInfo &p){ -// if(p.type == Protocol::PacketType::ManualStatus) { -// NewStatus(p.manualStatus); -// } -// }, Qt::QueuedConnection); + // ADC spectrum charts + for(int i=0;i<4;i++) { + charts[i] = new QChart(); + spectrumSeries[i] = new QLineSeries; + + auto pen = spectrumSeries[i]->pen(); + pen.setWidth(2); + pen.setBrush(QBrush("blue")); + spectrumSeries[i]->setPen(pen); + + auto xAxis = new QValueAxis; + xAxis->setTitleText("Frequency [MHz]"); + xAxis->setRange(0,12.5); + auto yAxis = new QValueAxis; + yAxis->setTitleText("Amplitude [dBFS]"); + yAxis->setRange(-120, 0); + + charts[i]->legend()->hide(); + charts[i]->addSeries(spectrumSeries[i]); + charts[i]->addAxis(xAxis, Qt::AlignBottom); + charts[i]->addAxis(yAxis, Qt::AlignLeft); + spectrumSeries[i]->attachAxis(xAxis); + spectrumSeries[i]->attachAxis(yAxis); + } + ui->spectrumA->setChart(charts[0]); + charts[0]->setTitle("ADC A Spectrum"); + ui->spectrumB->setChart(charts[1]); + charts[1]->setTitle("ADC B Spectrum"); + ui->spectrumC->setChart(charts[2]); + charts[2]->setTitle("ADC C Spectrum"); + ui->spectrumD->setChart(charts[3]); + charts[3]->setTitle("ADC D Spectrum"); connect(ui->SourceCE, &QCheckBox::toggled, [=](bool) { UpdateDevice(); }); connect(ui->SourceRFEN, &QCheckBox::toggled, [=](bool) { UpdateDevice(); }); @@ -79,11 +110,13 @@ ManualControlDialogVFD::ManualControlDialogVFD(LibreVNADriver &dev, QWidget *par connect(ui->SourceAmp2En, &QCheckBox::toggled, [=](bool) { UpdateDevice(); }); connect(ui->LOAmpEn, &QCheckBox::toggled, [=](bool) { UpdateDevice(); }); connect(ui->DACEnable, &QCheckBox::toggled, [=](bool) { UpdateDevice(); }); + connect(ui->ADCEnable, &QCheckBox::toggled, [=](bool) { UpdateDevice(); }); connect(ui->SourceFilter, qOverload(&QComboBox::currentIndexChanged), [=](int) { UpdateDevice(); }); connect(ui->SourceBandsel, qOverload(&QComboBox::currentIndexChanged), [=](int) { UpdateDevice(); }); connect(ui->SourcePortSel, qOverload(&QComboBox::currentIndexChanged), [=](int) { UpdateDevice(); }); connect(ui->LOMode, qOverload(&QComboBox::currentIndexChanged), [=](int) { UpdateDevice(); }); + connect(ui->ADCTestPattern, qOverload(&QComboBox::currentIndexChanged), [=](int) { UpdateDevice(); }); connect(ui->SourceFrequency, &SIUnitEdit::valueChanged, [=](double) { UpdateDevice(); }); connect(ui->LOFrequency, &SIUnitEdit::valueChanged, [=](double) { UpdateDevice(); }); @@ -93,6 +126,7 @@ ManualControlDialogVFD::ManualControlDialogVFD(LibreVNADriver &dev, QWidget *par connect(ui->SourceStepAtt, qOverload(&QSpinBox::valueChanged), [=](int) { UpdateDevice(); }); connect(ui->DACAmplitudeA, qOverload(&QSpinBox::valueChanged), [=](int) { UpdateDevice(); }); connect(ui->DACAmplitudeB, qOverload(&QSpinBox::valueChanged), [=](int) { UpdateDevice(); }); + connect(ui->ADCSamples, qOverload(&QSpinBox::valueChanged), [=](int) { UpdateDevice(); }); // Create the SCPI commands @@ -333,6 +367,47 @@ ManualControlDialogVFD::ManualControlDialogVFD(LibreVNADriver &dev, QWidget *par addDoubleManualSetting("MANual:DACB_FREQ", &ManualControlDialogVFD::setDACBFrequency, &ManualControlDialogVFD::getDACBFrequency); addIntegerManualSetting("MANual:DACB_AMPlitude", &ManualControlDialogVFD::setDACBAmplitude, &ManualControlDialogVFD::getDACBAmplitude); + addBooleanManualSetting("MANual:ADC_EN", &ManualControlDialogVFD::setADCEnable, &ManualControlDialogVFD::getADCEnable); + addIntegerManualSetting("MANual:ADC_SAMPLES", &ManualControlDialogVFD::setADCSamples, &ManualControlDialogVFD::getADCSamples); + addIntegerManualSetting("MANual:ADC_TESTPATTERN", &ManualControlDialogVFD::setADCTestPattern, &ManualControlDialogVFD::getADCTestPattern); + + connect(&dev, &LibreVNADriver::receivedPacket, this, [=](const Protocol::PacketInfo &p){ + if(p.type == Protocol::PacketType::ArrayData) { + // incoming spectrum data + const Protocol::ArrayData data = p.arrayData; + int index = 0; + auto series = spectrumSeries[data.id]; + auto chart = charts[data.id]; + chart->removeSeries(series); +// qDebug() << "Incoming spectrum data"; + for(unsigned int i=0;i(data.data[i*2], data.data[i*2+1]); + auto dB = 20*log10(abs(d)); + auto point = QPointF(freq, dB); + // get index at which this point should be inserted + while(index < series->count() && series->at(index).x() < freq) { + index++; + } +// qDebug() << "point at" << freq <<": " << dB << "(index:" << index << ")"; + if(index >= series->count()) { + // append at the end + series->append(point); + } else if(freq == series->at(index).x()) { + // replace existing point + series->replace(index, point); + } else { + // insert at position + series->insert(index, point); + } + } + chart->addSeries(series); + series->attachAxis(chart->axes(Qt::Horizontal)[0]); + series->attachAxis(chart->axes(Qt::Vertical)[0]); + } + }, Qt::QueuedConnection); + for(auto c : commands) { emit dev.addSCPICommand(c); } @@ -627,6 +702,36 @@ int ManualControlDialogVFD::getDACBAmplitude() return ui->DACAmplitudeB->value(); } +void ManualControlDialogVFD::setADCEnable(bool enable) +{ + ui->ADCEnable->setChecked(enable); +} + +bool ManualControlDialogVFD::getADCEnable() +{ + return ui->ADCEnable->isChecked(); +} + +void ManualControlDialogVFD::setADCSamples(int samples) +{ + ui->ADCSamples->setValue(samples); +} + +int ManualControlDialogVFD::getADCSamples() +{ + return ui->ADCSamples->value(); +} + +void ManualControlDialogVFD::setADCTestPattern(int tp) +{ + ui->ADCTestPattern->setCurrentIndex(tp); +} + +int ManualControlDialogVFD::getADCTestPattern() +{ + return ui->ADCTestPattern->currentIndex(); +} + void ManualControlDialogVFD::UpdateDevice() { Protocol::PacketInfo p; @@ -659,6 +764,11 @@ void ManualControlDialogVFD::UpdateDevice() m.DACAmpB = ui->DACAmplitudeB->value(); m.DACEn = ui->DACEnable->isChecked(); + // ADC + m.ADCEn = ui->ADCEnable->isChecked(); + m.ADCSamples = ui->ADCSamples->value(); + m.ADCTestPattern = ui->ADCTestPattern->currentIndex(); + qDebug() << "Updating manual control state"; dev.SendPacket(p); diff --git a/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/manualcontroldialogvfd.h b/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/manualcontroldialogvfd.h index 1b47f68..ade10e7 100644 --- a/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/manualcontroldialogvfd.h +++ b/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/manualcontroldialogvfd.h @@ -4,6 +4,8 @@ #include "librevnadriver.h" #include +#include +#include #include namespace Ui { @@ -106,12 +108,24 @@ public: void setDACBAmplitude(int a); int getDACBAmplitude(); + void setADCEnable(bool enable); + bool getADCEnable(); + + void setADCSamples(int samples); + int getADCSamples(); + + void setADCTestPattern(int tp); + int getADCTestPattern(); + private: void UpdateDevice(); Ui::ManualControlDialogVFD *ui; LibreVNADriver &dev; std::vector commands; + + std::array charts; + std::array spectrumSeries; }; #endif // MANUALCONTROLDIALOGV1_H diff --git a/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/manualcontroldialogvfd.ui b/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/manualcontroldialogvfd.ui index aba8701..57738f7 100644 --- a/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/manualcontroldialogvfd.ui +++ b/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/manualcontroldialogvfd.ui @@ -9,20 +9,20 @@ 0 0 - 640 - 453 + 1270 + 827 Manual Control - + Signal Generation - + @@ -265,162 +265,292 @@ - - - - - LO PLL - - - - - - Frequency: - - + + + DAC + + + + + + Enabled: + + + + + + + + + + + + + + Output A Frequency: + + + + + + + + + + Output A Amplitude: + + + + + + + 2047 + + + + + + + Output A Frequency: + + + + + + + + + + Output A Amplitude: + + + + + + + 2047 + + + + + + + + + + LO PLL + + + + + + Frequency: + + + + + + + + + + Mode: + + + + + + + + Internal - HF + - - + + + Internal -LF + - - - - Mode: - - + + + External + - - - - - Internal - HF - - - - - Internal -LF - - - - - External - - - + + + + + + true + + + Locked + + + + + + + RF Enable + + + + + + + Chip Enable + + + + + + + Amplifier: + + + + + + + + + + + + + + + + + + + + Data Acquisition + + + + + + Spectrum View + + + + + + + + + + + + + + + + + + + + + Settings + + + + + + ADC Enable: + + + + + + + + + + + + + + Samples: + + + + + + + 16 + + + 131072 + + + 16 + + + + + + + Testpattern: + + + + + + + + Off + - - - - true - - - Locked - - + + + Zeros + - - - - RF Enable - - + + + Ones + - - - - Chip Enable - - + + + Toggle + - - - - Amplifier: - - + + + Ramp + - - - - - - + + + Custom + - - - - - - - DAC - - - - - - Enabled: - - + + + Deskew + - - - - - - + + + Reserved + - - - - Output A Frequency: - - + + + PRBS + - - + + + Sine + - - - - Output A Amplitude: - - - - - - - 2047 - - - - - - - Output A Frequency: - - - - - - - - - - Output A Amplitude: - - - - - - - 2047 - - - - - - - + + + + @@ -433,6 +563,11 @@ QLineEdit
CustomWidgets/siunitedit.h
+ + QChartView + QGraphicsView +
QtCharts
+
diff --git a/Software/PC_Application/LibreVNA-GUI/LibreVNA-GUI.pro b/Software/PC_Application/LibreVNA-GUI/LibreVNA-GUI.pro index cee4829..8f52757 100644 --- a/Software/PC_Application/LibreVNA-GUI/LibreVNA-GUI.pro +++ b/Software/PC_Application/LibreVNA-GUI/LibreVNA-GUI.pro @@ -330,7 +330,7 @@ mac{ PKGCONFIG += libusb-1.0 } -QT += widgets network +QT += widgets network charts FORMS += \ Calibration/CalStandardLineEditDialog.ui \ diff --git a/Software/PC_Application/LibreVNA-Test/LibreVNA-Test.pro b/Software/PC_Application/LibreVNA-Test/LibreVNA-Test.pro index 2787bea..eb5d929 100644 --- a/Software/PC_Application/LibreVNA-Test/LibreVNA-Test.pro +++ b/Software/PC_Application/LibreVNA-Test/LibreVNA-Test.pro @@ -1,4 +1,4 @@ -QT += testlib widgets network +QT += testlib widgets network charts CONFIG += qt console warn_on depend_includepath testcase CONFIG -= app_bundle diff --git a/Software/VNA_embedded/Application/Communication/PacketConstants.h b/Software/VNA_embedded/Application/Communication/PacketConstants.h index 1b35f79..f478b6d 100644 --- a/Software/VNA_embedded/Application/Communication/PacketConstants.h +++ b/Software/VNA_embedded/Application/Communication/PacketConstants.h @@ -5,45 +5,48 @@ namespace PacketConstants { - // USB protocol packet field constants +// USB protocol packet field constants - static constexpr uint8_t PCKT_HEADER_DATA = 0x5A; +static constexpr uint8_t PCKT_HEADER_DATA = 0x5A; - ///////////////////////////////////////////////////////////// - // General packet structure field sizes and offsets in bytes - static constexpr uint8_t PCKT_HEADER_OFFSET = 0; - static constexpr uint8_t PCKT_HEADER_LEN = 1; - static constexpr uint8_t PCKT_LENGTH_OFFSET = PCKT_HEADER_OFFSET + PCKT_HEADER_LEN; // offset one byte - static constexpr uint8_t PCKT_LENGTH_LEN = 2; - static constexpr uint8_t PCKT_TYPE_OFFSET = PCKT_LENGTH_OFFSET + PCKT_LENGTH_LEN; // offset three bytes - static constexpr uint8_t PCKT_TYPE_LEN = 1; - static constexpr uint8_t PCKT_PAYLOAD_OFFSET = PCKT_TYPE_OFFSET + PCKT_TYPE_LEN; // offset four bytes - static constexpr uint8_t PCKT_CRC_LEN = 4; +///////////////////////////////////////////////////////////// +// General packet structure field sizes and offsets in bytes +static constexpr uint8_t PCKT_HEADER_OFFSET = 0; +static constexpr uint8_t PCKT_HEADER_LEN = 1; +static constexpr uint8_t PCKT_LENGTH_OFFSET = PCKT_HEADER_OFFSET + PCKT_HEADER_LEN; // offset one byte +static constexpr uint8_t PCKT_LENGTH_LEN = 2; +static constexpr uint8_t PCKT_TYPE_OFFSET = PCKT_LENGTH_OFFSET + PCKT_LENGTH_LEN; // offset three bytes +static constexpr uint8_t PCKT_TYPE_LEN = 1; +static constexpr uint8_t PCKT_PAYLOAD_OFFSET = PCKT_TYPE_OFFSET + PCKT_TYPE_LEN; // offset four bytes +static constexpr uint8_t PCKT_CRC_LEN = 4; - static constexpr uint8_t PCKT_COMBINED_HEADER_LEN = PCKT_HEADER_LEN + PCKT_LENGTH_LEN + PCKT_TYPE_LEN; // combined length of fields preceding payload - static constexpr uint8_t PCKT_EXCL_PAYLOAD_LEN = PCKT_COMBINED_HEADER_LEN + PCKT_CRC_LEN; // combined length of all packet fields, excluding payload +static constexpr uint8_t PCKT_COMBINED_HEADER_LEN = PCKT_HEADER_LEN + PCKT_LENGTH_LEN + PCKT_TYPE_LEN; // combined length of fields preceding payload +static constexpr uint8_t PCKT_EXCL_PAYLOAD_LEN = PCKT_COMBINED_HEADER_LEN + PCKT_CRC_LEN; // combined length of all packet fields, excluding payload - ///////////////////////////////////////////////////////////// - // Payload content +///////////////////////////////////////////////////////////// +// Payload content - // Firmware packets - static constexpr uint16_t FW_CHUNK_SIZE = 256; +// Firmware packets +static constexpr uint16_t FW_CHUNK_SIZE = 256; - // VNADataPoint payload fields in bytes - static constexpr uint8_t DPNT_FREQ_LEN = 8; - static constexpr uint8_t DPNT_POW_LVL_LEN = 2; - static constexpr uint8_t DPNT_PNT_NUM_LEN = 2; - static constexpr uint8_t DPNT_REAL_PART_LEN = 4; - static constexpr uint8_t DPNT_IMAG_PART_LEN = 4; - static constexpr uint8_t DPNT_DESC_LEN = 1; +// VNADataPoint payload fields in bytes +static constexpr uint8_t DPNT_FREQ_LEN = 8; +static constexpr uint8_t DPNT_POW_LVL_LEN = 2; +static constexpr uint8_t DPNT_PNT_NUM_LEN = 2; +static constexpr uint8_t DPNT_REAL_PART_LEN = 4; +static constexpr uint8_t DPNT_IMAG_PART_LEN = 4; +static constexpr uint8_t DPNT_DESC_LEN = 1; - // VNADataPoint configuration bitmask offsets in bits - static constexpr uint8_t DPNT_CONF_P1_OFFSET = 0; - static constexpr uint8_t DPNT_CONF_P2_OFFSET = 1; - static constexpr uint8_t DPNT_CONF_P3_OFFSET = 2; - static constexpr uint8_t DPNT_CONF_P4_OFFSET = 3; - static constexpr uint8_t DPNT_CONF_REF_OFFSET = 4; - static constexpr uint8_t DPNT_CONF_STAGE_OFFSET = 5; +// VNADataPoint configuration bitmask offsets in bits +static constexpr uint8_t DPNT_CONF_P1_OFFSET = 0; +static constexpr uint8_t DPNT_CONF_P2_OFFSET = 1; +static constexpr uint8_t DPNT_CONF_P3_OFFSET = 2; +static constexpr uint8_t DPNT_CONF_P4_OFFSET = 3; +static constexpr uint8_t DPNT_CONF_REF_OFFSET = 4; +static constexpr uint8_t DPNT_CONF_STAGE_OFFSET = 5; + +// DataArray packets +static constexpr uint16_t ARRAY_PCKT_MAX_NUM = 62; } diff --git a/Software/VNA_embedded/Application/Communication/Protocol.cpp b/Software/VNA_embedded/Application/Communication/Protocol.cpp index 80f91b8..f0e066e 100644 --- a/Software/VNA_embedded/Application/Communication/Protocol.cpp +++ b/Software/VNA_embedded/Application/Communication/Protocol.cpp @@ -13,42 +13,42 @@ #define CRC32_POLYGON 0xEDB88320 uint32_t Protocol::CRC32(uint32_t crc, const void *data, uint32_t len) { - uint8_t *u8buf = (uint8_t*) data; - int k; + uint8_t *u8buf = (uint8_t*) data; + int k; - crc = ~crc; - while (len--) { - crc ^= *u8buf++; - for (k = 0; k < 8; k++) - crc = crc & 1 ? (crc >> 1) ^ CRC32_POLYGON : crc >> 1; - } - return ~crc; + crc = ~crc; + while (len--) { + crc ^= *u8buf++; + for (k = 0; k < 8; k++) + crc = crc & 1 ? (crc >> 1) ^ CRC32_POLYGON : crc >> 1; + } + return ~crc; } uint16_t Protocol::DecodeBuffer(uint8_t *buf, uint16_t len, PacketInfo *info) { if (!info || !len) { info->type = PacketType::None; - return 0; - } - uint8_t *data = buf; - /* Remove any out-of-order bytes in front of the frame */ - while (*data != PCKT_HEADER_DATA) { - data++; - if(--len == 0) { - /* Reached end of data */ - /* No frame contained in data */ - info->type = PacketType::None; - return data - buf; - } - } - /* At this point, data points to the beginning of the frame */ - if(len < PCKT_COMBINED_HEADER_LEN) { - /* the frame header has not been completely received */ - info->type = PacketType::None; - return data - buf; - } + return 0; + } + uint8_t *data = buf; + /* Remove any out-of-order bytes in front of the frame */ + while (*data != PCKT_HEADER_DATA) { + data++; + if(--len == 0) { + /* Reached end of data */ + /* No frame contained in data */ + info->type = PacketType::None; + return data - buf; + } + } + /* At this point, data points to the beginning of the frame */ + if(len < PCKT_COMBINED_HEADER_LEN) { + /* the frame header has not been completely received */ + info->type = PacketType::None; + return data - buf; + } - /* Evaluate frame size */ + /* Evaluate frame size */ uint16_t length = data[PCKT_LENGTH_OFFSET] | ((uint16_t) data[2] << 8); if(length > sizeof(PacketInfo) * 2 || length < PCKT_EXCL_PAYLOAD_LEN) { @@ -58,46 +58,46 @@ uint16_t Protocol::DecodeBuffer(uint8_t *buf, uint16_t len, PacketInfo *info) { } if(len < length) { - /* The frame payload has not been completely received */ - info->type = PacketType::None; - return data - buf; - } + /* The frame payload has not been completely received */ + info->type = PacketType::None; + return data - buf; + } - /* The complete frame has been received, check checksum */ - auto type = (PacketType) data[PCKT_TYPE_OFFSET]; + /* The complete frame has been received, check checksum */ + auto type = (PacketType) data[PCKT_TYPE_OFFSET]; uint32_t crc = (uint32_t) data[length-4] | ((uint32_t) data[length-3] << 8) | ((uint32_t) data[length-2] << 16) | ((uint32_t) data[length-1] << 24); - if(type != PacketType::VNADatapoint) { - uint32_t compare = CRC32(0, data, length - PCKT_CRC_LEN); - if(crc != compare) { - // CRC mismatch, remove header - data += 1; - info->type = PacketType::None; - return data - buf; - } - // Valid packet, copy packet type and payload - memcpy(info, &data[PCKT_TYPE_OFFSET], length - 7); - } else { - // Datapoint has the CRC set to zero - if(crc != 0x00000000) { - data += 1; - info->type = PacketType::None; - return data - buf; - } - // Create the datapoint - info->type = (PacketType) data[PCKT_TYPE_OFFSET]; - info->VNAdatapoint = new VNADatapoint<32>; - info->VNAdatapoint->decode(&data[PCKT_PAYLOAD_OFFSET], length - PCKT_EXCL_PAYLOAD_LEN); - } + if(type != PacketType::VNADatapoint) { + uint32_t compare = CRC32(0, data, length - PCKT_CRC_LEN); + if(crc != compare) { + // CRC mismatch, remove header + data += 1; + info->type = PacketType::None; + return data - buf; + } + // Valid packet, copy packet type and payload + memcpy(info, &data[PCKT_TYPE_OFFSET], length - 7); + } else { + // Datapoint has the CRC set to zero + if(crc != 0x00000000) { + data += 1; + info->type = PacketType::None; + return data - buf; + } + // Create the datapoint + info->type = (PacketType) data[PCKT_TYPE_OFFSET]; + info->VNAdatapoint = new VNADatapoint<32>; + info->VNAdatapoint->decode(&data[PCKT_PAYLOAD_OFFSET], length - PCKT_EXCL_PAYLOAD_LEN); + } - return data - buf + length; + return data - buf + length; } -uint16_t Protocol::EncodePacket(const PacketInfo &packet, uint8_t *dest, uint16_t destsize) { - int16_t payload_size = 0; - switch (packet.type) { -// case PacketType::Datapoint: payload_size = sizeof(packet.datapoint); break; - case PacketType::SweepSettings: payload_size = sizeof(packet.settings); break; - case PacketType::Reference: payload_size = sizeof(packet.reference); break; +uint16_t Protocol::GetRequiredSize(const PacketInfo &packet) { + int16_t payload_size = 0; + switch (packet.type) { + // case PacketType::Datapoint: payload_size = sizeof(packet.datapoint); break; + case PacketType::SweepSettings: payload_size = sizeof(packet.settings); break; + case PacketType::Reference: payload_size = sizeof(packet.reference); break; case PacketType::DeviceInfo: payload_size = sizeof(packet.info); break; case PacketType::DeviceStatus: payload_size = sizeof(packet.status); break; case PacketType::ManualStatus: payload_size = sizeof(packet.manualStatus); break; @@ -129,32 +129,38 @@ uint16_t Protocol::EncodePacket(const PacketInfo &packet, uint8_t *dest, uint16_ // no payload break; case PacketType::VNADatapoint: payload_size = packet.VNAdatapoint->requiredBufferSize(); break; + case PacketType::ArrayData: payload_size = 12 + packet.arrayData.values * 4; break; case PacketType::None: break; } - if (payload_size < 0 || payload_size + PCKT_EXCL_PAYLOAD_LEN > destsize) { - // encoding failed, buffer too small - return 0; - } - // Write header - dest[PCKT_HEADER_OFFSET] = PCKT_HEADER_DATA; - uint16_t overall_size = payload_size + PCKT_EXCL_PAYLOAD_LEN; - memcpy(&dest[PCKT_LENGTH_OFFSET], &overall_size, PCKT_LENGTH_LEN); - // Further encoding uses a special case for VNADatapoint packettype - uint32_t crc = 0x00000000; - if(packet.type == PacketType::VNADatapoint) { - // CRC calculation takes about 18us which is the bulk of the time required to encode and transmit a datapoint. - // Skip CRC for data points to optimize throughput - dest[PCKT_TYPE_OFFSET] = (uint8_t) packet.type; - packet.VNAdatapoint->encode(&dest[PCKT_PAYLOAD_OFFSET], destsize - PCKT_EXCL_PAYLOAD_LEN); - crc = 0x00000000; - } else { - // Copy rest of the packet - memcpy(&dest[PCKT_TYPE_OFFSET], &packet, payload_size + PCKT_TYPE_LEN); // one additional byte for the packet type - // Calculate the CRC - crc = CRC32(0, dest, overall_size - PCKT_CRC_LEN); - } - memcpy(&dest[overall_size - PCKT_CRC_LEN], &crc, PCKT_CRC_LEN); - return overall_size; + + return payload_size + PCKT_EXCL_PAYLOAD_LEN; +} + +uint16_t Protocol::EncodePacket(const PacketInfo &packet, uint8_t *dest, uint16_t destsize) { + uint16_t overall_size = GetRequiredSize(packet); + if(overall_size > destsize) { + // encoding faile, buffer too small + return 0; + } + // Write header + dest[PCKT_HEADER_OFFSET] = PCKT_HEADER_DATA; + memcpy(&dest[PCKT_LENGTH_OFFSET], &overall_size, PCKT_LENGTH_LEN); + // Further encoding uses a special case for VNADatapoint packettype + uint32_t crc = 0x00000000; + if(packet.type == PacketType::VNADatapoint) { + // CRC calculation takes about 18us which is the bulk of the time required to encode and transmit a datapoint. + // Skip CRC for data points to optimize throughput + dest[PCKT_TYPE_OFFSET] = (uint8_t) packet.type; + packet.VNAdatapoint->encode(&dest[PCKT_PAYLOAD_OFFSET], destsize - PCKT_EXCL_PAYLOAD_LEN); + crc = 0x00000000; + } else { + // Copy rest of the packet + memcpy(&dest[PCKT_TYPE_OFFSET], &packet, overall_size - PCKT_EXCL_PAYLOAD_LEN + PCKT_TYPE_LEN); // one additional byte for the packet type + // Calculate the CRC + crc = CRC32(0, dest, overall_size - PCKT_CRC_LEN); + } + memcpy(&dest[overall_size - PCKT_CRC_LEN], &crc, PCKT_CRC_LEN); + return overall_size; } diff --git a/Software/VNA_embedded/Application/Communication/Protocol.hpp b/Software/VNA_embedded/Application/Communication/Protocol.hpp index 5feaa6f..0d6e8f1 100644 --- a/Software/VNA_embedded/Application/Communication/Protocol.hpp +++ b/Software/VNA_embedded/Application/Communication/Protocol.hpp @@ -15,56 +15,56 @@ static constexpr uint16_t Version = 14; #pragma pack(push, 1) enum class Source : uint8_t { - Port1 = 0x01, - Port2 = 0x02, - Port3 = 0x04, - Port4 = 0x08, - Reference = 0x10, + Port1 = 0x01, + Port2 = 0x02, + Port3 = 0x04, + Port4 = 0x08, + Reference = 0x10, }; template class VNADatapoint { public: - VNADatapoint() { - clear(); - } + VNADatapoint() { + clear(); + } - void clear() { - num_values = 0; - pointNum = 0; - cdBm = 0; - frequency = 0; - } - bool addValue(float real, float imag, uint8_t stage, int sourceMask) { - if(num_values >= s) { - return false; - } - real_values[num_values] = real; - imag_values[num_values] = imag; - descr_values[num_values] = stage << DPNT_CONF_STAGE_OFFSET | sourceMask; - num_values++; - return true; - } + void clear() { + num_values = 0; + pointNum = 0; + cdBm = 0; + frequency = 0; + } + bool addValue(float real, float imag, uint8_t stage, int sourceMask) { + if(num_values >= s) { + return false; + } + real_values[num_values] = real; + imag_values[num_values] = imag; + descr_values[num_values] = stage << DPNT_CONF_STAGE_OFFSET | sourceMask; + num_values++; + return true; + } - bool encode(uint8_t *dest, uint16_t destSize) { - if(requiredBufferSize() > destSize) { - return false; - } - memcpy(dest, &frequency, DPNT_FREQ_LEN); - dest += DPNT_FREQ_LEN; - memcpy(dest, &cdBm, DPNT_POW_LVL_LEN); - dest += DPNT_POW_LVL_LEN; - memcpy(dest, &pointNum, DPNT_PNT_NUM_LEN); + bool encode(uint8_t *dest, uint16_t destSize) { + if(requiredBufferSize() > destSize) { + return false; + } + memcpy(dest, &frequency, DPNT_FREQ_LEN); + dest += DPNT_FREQ_LEN; + memcpy(dest, &cdBm, DPNT_POW_LVL_LEN); + dest += DPNT_POW_LVL_LEN; + memcpy(dest, &pointNum, DPNT_PNT_NUM_LEN); dest += DPNT_PNT_NUM_LEN; - memcpy(dest, real_values, num_values * DPNT_REAL_PART_LEN); - dest += num_values * DPNT_REAL_PART_LEN; - memcpy(dest, imag_values, num_values * DPNT_IMAG_PART_LEN); - dest += num_values * DPNT_IMAG_PART_LEN; - memcpy(dest, descr_values, num_values); - return true; - } + memcpy(dest, real_values, num_values * DPNT_REAL_PART_LEN); + dest += num_values * DPNT_REAL_PART_LEN; + memcpy(dest, imag_values, num_values * DPNT_IMAG_PART_LEN); + dest += num_values * DPNT_IMAG_PART_LEN; + memcpy(dest, descr_values, num_values); + return true; + } void decode(const uint8_t *buffer, uint16_t size) { num_values = (size - (DPNT_FREQ_LEN + DPNT_POW_LVL_LEN + DPNT_PNT_NUM_LEN)) / - (DPNT_REAL_PART_LEN + DPNT_IMAG_PART_LEN + DPNT_DESC_LEN); + (DPNT_REAL_PART_LEN + DPNT_IMAG_PART_LEN + DPNT_DESC_LEN); memcpy(&frequency, buffer, DPNT_FREQ_LEN); buffer += DPNT_FREQ_LEN; memcpy(&cdBm, buffer, DPNT_POW_LVL_LEN); @@ -76,25 +76,25 @@ public: memcpy(imag_values, buffer, num_values * DPNT_IMAG_PART_LEN); buffer += num_values * DPNT_IMAG_PART_LEN; memcpy(descr_values, buffer, num_values); - } + } - std::complex getValue(uint8_t stage, uint8_t port, bool reference) { - uint8_t sourceMask = 0; - sourceMask |= 0x01 << port; - if(reference) { - sourceMask |= (int) Source::Reference; - } - for(int i=0;i> DPNT_CONF_STAGE_OFFSET != stage) { - continue; - } - if((descr_values[i] & sourceMask) != sourceMask) { - continue; - } - return std::complex(real_values[i], imag_values[i]); - } - return std::numeric_limits>::quiet_NaN(); - } + std::complex getValue(uint8_t stage, uint8_t port, bool reference) { + uint8_t sourceMask = 0; + sourceMask |= 0x01 << port; + if(reference) { + sourceMask |= (int) Source::Reference; + } + for(int i=0;i> DPNT_CONF_STAGE_OFFSET != stage) { + continue; + } + if((descr_values[i] & sourceMask) != sourceMask) { + continue; + } + return std::complex(real_values[i], imag_values[i]); + } + return std::numeric_limits>::quiet_NaN(); + } class Value { public: @@ -115,104 +115,104 @@ public: return num_values; } - uint16_t requiredBufferSize() { - return DPNT_FREQ_LEN + DPNT_POW_LVL_LEN + DPNT_PNT_NUM_LEN + - num_values * (DPNT_REAL_PART_LEN + DPNT_IMAG_PART_LEN + DPNT_DESC_LEN); - } + uint16_t requiredBufferSize() { + return DPNT_FREQ_LEN + DPNT_POW_LVL_LEN + DPNT_PNT_NUM_LEN + + num_values * (DPNT_REAL_PART_LEN + DPNT_IMAG_PART_LEN + DPNT_DESC_LEN); + } - union { - uint64_t frequency; - uint64_t us; - }; - int16_t cdBm; - uint16_t pointNum; + union { + uint64_t frequency; + uint64_t us; + }; + int16_t cdBm; + uint16_t pointNum; private: - float real_values[s]; - float imag_values[s]; - uint8_t descr_values[s]; - uint8_t num_values; + float real_values[s]; + float imag_values[s]; + uint8_t descr_values[s]; + uint8_t num_values; }; using Datapoint = struct _datapoint { - float real_S11, imag_S11; - float real_S21, imag_S21; - float real_S12, imag_S12; - float real_S22, imag_S22; - union { - struct { - // for non-zero span - uint64_t frequency; - int16_t cdbm; - }; - struct { - // for zero span - uint64_t us; // time in us since first datapoint - }; - }; + float real_S11, imag_S11; + float real_S21, imag_S21; + float real_S12, imag_S12; + float real_S22, imag_S22; + union { + struct { + // for non-zero span + uint64_t frequency; + int16_t cdbm; + }; + struct { + // for zero span + uint64_t us; // time in us since first datapoint + }; + }; uint16_t pointNum; }; using SweepSettings = struct _sweepSettings { - uint64_t f_start; - uint64_t f_stop; + uint64_t f_start; + uint64_t f_stop; uint16_t points; uint32_t if_bandwidth; int16_t cdbm_excitation_start; // in 1/100 dbm uint8_t standby:1; - uint8_t syncMaster:1; - uint8_t suppressPeaks:1; - uint8_t fixedPowerSetting:1; // if set the attenuator and source PLL power will not be changed across the sweep - uint8_t logSweep:1; - /* - * 0: no synchronization - * 1: USB synchronization - * 2: External reference synchronization - * 3: Trigger synchronization (not supported yet by hardware) - */ - uint8_t syncMode:2; - uint8_t unused1:1; + uint8_t syncMaster:1; + uint8_t suppressPeaks:1; + uint8_t fixedPowerSetting:1; // if set the attenuator and source PLL power will not be changed across the sweep + uint8_t logSweep:1; + /* + * 0: no synchronization + * 1: USB synchronization + * 2: External reference synchronization + * 3: Trigger synchronization (not supported yet by hardware) + */ + uint8_t syncMode:2; + uint8_t unused1:1; - uint16_t stages:3; - uint16_t port1Stage:3; - uint16_t port2Stage:3; - uint16_t port3Stage:3; - uint16_t port4Stage:3; - uint16_t unused2:1; + uint16_t stages:3; + uint16_t port1Stage:3; + uint16_t port2Stage:3; + uint16_t port3Stage:3; + uint16_t port4Stage:3; + uint16_t unused2:1; int16_t cdbm_excitation_stop; // in 1/100 dbm uint16_t dwell_time; // in us }; using ReferenceSettings = struct _referenceSettings { - uint32_t ExtRefOuputFreq; - uint8_t AutomaticSwitch:1; - uint8_t UseExternalRef:1; + uint32_t ExtRefOuputFreq; + uint8_t AutomaticSwitch:1; + uint8_t UseExternalRef:1; }; using GeneratorSettings = struct _generatorSettings { - uint64_t frequency; - int16_t cdbm_level; + uint64_t frequency; + int16_t cdbm_level; uint8_t activePort :3; uint8_t applyAmplitudeCorrection :1; uint8_t unused :4; }; using DeviceInfo = struct _deviceInfo { - uint16_t ProtocolVersion; + uint16_t ProtocolVersion; uint8_t FW_major; uint8_t FW_minor; uint8_t FW_patch; uint8_t hardware_version; char HW_Revision; - uint64_t limits_minFreq; - uint64_t limits_maxFreq; - uint32_t limits_minIFBW; - uint32_t limits_maxIFBW; - uint16_t limits_maxPoints; - int16_t limits_cdbm_min; - int16_t limits_cdbm_max; - uint32_t limits_minRBW; - uint32_t limits_maxRBW; + uint64_t limits_minFreq; + uint64_t limits_maxFreq; + uint32_t limits_minIFBW; + uint32_t limits_maxIFBW; + uint16_t limits_maxPoints; + int16_t limits_cdbm_min; + int16_t limits_cdbm_max; + uint32_t limits_minRBW; + uint32_t limits_maxRBW; uint8_t limits_maxAmplitudePoints; uint64_t limits_maxFreqHarmonic; uint8_t num_ports; @@ -220,26 +220,26 @@ using DeviceInfo = struct _deviceInfo { }; using DeviceStatus = struct _deviceStatus { - union { - struct { - uint8_t extRefAvailable:1; - uint8_t extRefInUse:1; - uint8_t FPGA_configured:1; - uint8_t source_locked:1; - uint8_t LO1_locked:1; - uint8_t ADC_overload:1; - uint8_t unlevel:1; - uint8_t temp_source; - uint8_t temp_LO1; - uint8_t temp_MCU; - } V1; - struct { - uint8_t source_locked:1; - uint8_t LO_locked:1; - uint8_t ADC_overload:1; - uint8_t unlevel:1; - uint8_t temp_MCU; - } VFF; + union { + struct { + uint8_t extRefAvailable:1; + uint8_t extRefInUse:1; + uint8_t FPGA_configured:1; + uint8_t source_locked:1; + uint8_t LO1_locked:1; + uint8_t ADC_overload:1; + uint8_t unlevel:1; + uint8_t temp_source; + uint8_t temp_LO1; + uint8_t temp_MCU; + } V1; + struct { + uint8_t source_locked:1; + uint8_t LO_locked:1; + uint8_t ADC_overload:1; + uint8_t unlevel:1; + uint8_t temp_MCU; + } VFF; struct { uint8_t source_locked:1; uint8_t LO_locked:1; @@ -249,32 +249,32 @@ using DeviceStatus = struct _deviceStatus { uint16_t temp_eCal; // in 1/100 °C uint16_t power_heater; // in mW } VFE; - }; + }; }; using ManualStatus = struct _manualstatus { - union { - struct { - int16_t port1min, port1max; - int16_t port2min, port2max; - int16_t refmin, refmax; - float port1real, port1imag; - float port2real, port2imag; - float refreal, refimag; - uint8_t temp_source; - uint8_t temp_LO; - uint8_t source_locked :1; - uint8_t LO_locked :1; - } V1; - struct { - int16_t portmin, portmax; - int16_t refmin, refmax; - float portreal, portimag; - float refreal, refimag; - uint8_t source_locked :1; - uint8_t LO_locked :1; - } VFF; + union { + struct { + int16_t port1min, port1max; + int16_t port2min, port2max; + int16_t refmin, refmax; + float port1real, port1imag; + float port2real, port2imag; + float refreal, refimag; + uint8_t temp_source; + uint8_t temp_LO; + uint8_t source_locked :1; + uint8_t LO_locked :1; + } V1; + struct { + int16_t portmin, portmax; + int16_t refmin, refmax; + float portreal, portimag; + float refreal, refimag; + uint8_t source_locked :1; + uint8_t LO_locked :1; + } VFF; struct { int16_t portmin, portmax; int16_t refmin, refmax; @@ -285,41 +285,41 @@ using ManualStatus = struct _manualstatus { uint16_t temp_eCal; // in 1/100 °C uint16_t power_heater; // in mW } VFE; - }; + }; }; using ManualControl = struct _manualControl { - union { - struct { - // Highband Source - uint8_t SourceHighCE :1; - uint8_t SourceHighRFEN :1; - uint8_t SourceHighPower :2; - uint8_t SourceHighLowpass :2; - uint64_t SourceHighFrequency; - // Lowband Source - uint8_t SourceLowEN :1; - uint8_t SourceLowPower :2; - uint32_t SourceLowFrequency; - // Source signal path - uint8_t attenuator :7; - uint8_t SourceHighband :1; - uint8_t AmplifierEN :1; - uint8_t PortSwitch :1; - // LO1 - uint8_t LO1CE :1; - uint8_t LO1RFEN :1; - uint64_t LO1Frequency; - // LO2 - uint8_t LO2EN :1; - uint32_t LO2Frequency; - // Acquisition - uint8_t Port1EN :1; - uint8_t Port2EN :1; - uint8_t RefEN :1; - uint32_t Samples; - uint8_t WindowType :2; - } V1; + union { + struct { + // Highband Source + uint8_t SourceHighCE :1; + uint8_t SourceHighRFEN :1; + uint8_t SourceHighPower :2; + uint8_t SourceHighLowpass :2; + uint64_t SourceHighFrequency; + // Lowband Source + uint8_t SourceLowEN :1; + uint8_t SourceLowPower :2; + uint32_t SourceLowFrequency; + // Source signal path + uint8_t attenuator :7; + uint8_t SourceHighband :1; + uint8_t AmplifierEN :1; + uint8_t PortSwitch :1; + // LO1 + uint8_t LO1CE :1; + uint8_t LO1RFEN :1; + uint64_t LO1Frequency; + // LO2 + uint8_t LO2EN :1; + uint32_t LO2Frequency; + // Acquisition + uint8_t Port1EN :1; + uint8_t Port2EN :1; + uint8_t RefEN :1; + uint32_t Samples; + uint8_t WindowType :2; + } V1; struct { uint64_t SourceFrequency; @@ -351,30 +351,35 @@ using ManualControl = struct _manualControl { uint32_t DACFreqB; uint16_t DACAmpA; uint16_t DACAmpB; + + // ADC + uint8_t ADCTestPattern :4; + uint8_t ADCEn :1; + uint32_t ADCSamples; } VFD; - struct { - // Source - uint8_t SourceCE :1; - uint8_t SourceRFEN :1; + struct { + // Source + uint8_t SourceCE :1; + uint8_t SourceRFEN :1; uint8_t SourcePower :3; uint64_t SourceFrequency; - // Source signal path - uint8_t attenuator :7; + // Source signal path + uint8_t attenuator :7; uint8_t SourceAmplifierEN :1; - // LO - uint8_t LOCE :1; - uint8_t LORFEN :1; + // LO + uint8_t LOCE :1; + uint8_t LORFEN :1; uint8_t LOAmplifierEN :1; uint8_t LOexternal :1; uint64_t LOFrequency; - // Acquisition - uint16_t PortEN :1; - uint16_t RefEN :1; - uint16_t WindowType :2; - uint16_t PortGain :4; - uint16_t RefGain :4; - uint16_t Samples; - } VFF; + // Acquisition + uint16_t PortEN :1; + uint16_t RefEN :1; + uint16_t WindowType :2; + uint16_t PortGain :4; + uint16_t RefGain :4; + uint16_t Samples; + } VFF; struct { // Source uint8_t SourceCE :1; @@ -399,28 +404,28 @@ using ManualControl = struct _manualControl { uint8_t eCal_state :2; uint16_t eCal_target; // in 1/100 °C } VFE; - }; + }; }; using SpectrumAnalyzerSettings = struct _spectrumAnalyzerSettings { - uint64_t f_start; - uint64_t f_stop; - uint32_t RBW; - uint16_t pointNum; - uint8_t WindowType :2; - uint8_t SignalID :1; - uint8_t Detector :3; - uint8_t UseDFT :1; + uint64_t f_start; + uint64_t f_stop; + uint32_t RBW; + uint16_t pointNum; + uint8_t WindowType :2; + uint8_t SignalID :1; + uint8_t Detector :3; + uint8_t UseDFT :1; uint8_t applyReceiverCorrection :1; uint8_t trackingGenerator :1; uint8_t applySourceCorrection :1; uint8_t trackingGeneratorPort :2; // port count starts at zero - /* - * 0: no synchronization - * 1: Protocol synchronization (via SetTrigger and ClearTrigger packets) - * 2: Reserved - * 3: Trigger synchronization (not supported yet by hardware) - */ + /* + * 0: no synchronization + * 1: Protocol synchronization (via SetTrigger and ClearTrigger packets) + * 2: Reserved + * 3: Trigger synchronization (not supported yet by hardware) + */ uint8_t syncMode :2; uint8_t syncMaster :1; int64_t trackingGeneratorOffset; @@ -428,21 +433,21 @@ using SpectrumAnalyzerSettings = struct _spectrumAnalyzerSettings { }; using SpectrumAnalyzerResult = struct _spectrumAnalyzerResult { - float port1; - float port2; - float port3; - float port4; - union { - struct { - // for non-zero span - uint64_t frequency; - }; - struct { - // for zero span - uint64_t us; // time in us since first datapoint - }; - }; - uint16_t pointNum; + float port1; + float port2; + float port3; + float port4; + union { + struct { + // for non-zero span + uint64_t frequency; + }; + struct { + // for zero span + uint64_t us; // time in us since first datapoint + }; + }; + uint16_t pointNum; }; @@ -452,89 +457,100 @@ using FirmwarePacket = struct _firmwarePacket { }; using AmplitudeCorrectionPoint = struct _amplitudecorrectionpoint { - uint8_t totalPoints; - uint8_t pointNum; - uint32_t freq; - int16_t port1; - int16_t port2; - int16_t port3; - int16_t port4; + uint8_t totalPoints; + uint8_t pointNum; + uint32_t freq; + int16_t port1; + int16_t port2; + int16_t port3; + int16_t port4; }; using FrequencyCorrection = struct _frequencycorrection { - float ppm; + float ppm; }; using DeviceConfig = struct _deviceconfig { - union { - struct { - uint32_t IF1; - uint8_t ADCprescaler; - uint16_t DFTphaseInc; - uint8_t PLLSettlingDelay; - } V1; - struct { - uint32_t ip; - uint32_t mask; - uint32_t gw; + union { + struct { + uint32_t IF1; + uint8_t ADCprescaler; + uint16_t DFTphaseInc; + uint8_t PLLSettlingDelay; + } V1; + struct { + uint32_t ip; + uint32_t mask; + uint32_t gw; uint8_t dhcp :1; uint8_t unused :7; uint16_t autogain :1; uint16_t portGain :4; uint16_t refGain :4; - } VFF; + } VFF; struct { uint16_t autogain :1; uint16_t portGain :4; uint16_t refGain :4; } VFE; - }; + }; +}; + +#define PROTOCOL_ + +using ArrayData = struct _arraydata { + uint16_t id; + uint16_t values; + float xbegin; + float xend; + float data[ARRAY_PCKT_MAX_NUM]; }; enum class PacketType : uint8_t { - None = 0, - //Datapoint = 1, // Deprecated, replaced by VNADatapoint - SweepSettings = 2, + None = 0, + //Datapoint = 1, // Deprecated, replaced by VNADatapoint + SweepSettings = 2, ManualStatus = 3, ManualControl = 4, DeviceInfo = 5, FirmwarePacket = 6, Ack = 7, - ClearFlash = 8, - PerformFirmwareUpdate = 9, - Nack = 10, - Reference = 11, - Generator = 12, - SpectrumAnalyzerSettings = 13, - SpectrumAnalyzerResult = 14, + ClearFlash = 8, + PerformFirmwareUpdate = 9, + Nack = 10, + Reference = 11, + Generator = 12, + SpectrumAnalyzerSettings = 13, + SpectrumAnalyzerResult = 14, RequestDeviceInfo = 15, - RequestSourceCal = 16, - RequestReceiverCal = 17, - SourceCalPoint = 18, - ReceiverCalPoint = 19, - SetIdle = 20, - RequestFrequencyCorrection = 21, - FrequencyCorrection = 22, - RequestDeviceConfiguration = 23, - DeviceConfiguration = 24, - DeviceStatus = 25, - RequestDeviceStatus = 26, - VNADatapoint = 27, - SetTrigger = 28, - ClearTrigger = 29, - StopStatusUpdates = 30, - StartStatusUpdates = 31, - InitiateSweep = 32 + RequestSourceCal = 16, + RequestReceiverCal = 17, + SourceCalPoint = 18, + ReceiverCalPoint = 19, + SetIdle = 20, + RequestFrequencyCorrection = 21, + FrequencyCorrection = 22, + RequestDeviceConfiguration = 23, + DeviceConfiguration = 24, + DeviceStatus = 25, + RequestDeviceStatus = 26, + VNADatapoint = 27, + SetTrigger = 28, + ClearTrigger = 29, + StopStatusUpdates = 30, + StartStatusUpdates = 31, + InitiateSweep = 32, + ArrayData = 33, }; using PacketInfo = struct _packetinfo { - PacketType type; - union { -// Datapoint datapoint; // Deprecated, use VNADatapoint instead - SweepSettings settings; - ReferenceSettings reference; - GeneratorSettings generator; - DeviceStatus status; + PacketType type; + union { + // Datapoint datapoint; // Deprecated, use VNADatapoint instead + SweepSettings settings; + ReferenceSettings reference; + GeneratorSettings generator; + DeviceStatus status; DeviceInfo info; ManualControl manual; FirmwarePacket firmware; @@ -549,13 +565,15 @@ using PacketInfo = struct _packetinfo { * When decoding: VNADatapoint is created on heap by DecodeBuffer, freeing is up to the caller */ VNADatapoint<32> *VNAdatapoint; - }; + ArrayData arrayData; + }; }; #pragma pack(pop) uint32_t CRC32(uint32_t crc, const void *data, uint32_t len); uint16_t DecodeBuffer(uint8_t *buf, uint16_t len, PacketInfo *info); +uint16_t GetRequiredSize(const PacketInfo &packet); uint16_t EncodePacket(const PacketInfo &packet, uint8_t *dest, uint16_t destsize); }