Merge pull request #165 from andredunford/packet_constants

replace USB protocol literals with named constants
This commit is contained in:
jankae 2022-11-30 21:40:15 +01:00 committed by GitHub
commit e6dfc83330
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 107 additions and 49 deletions

View File

@ -1,6 +1,7 @@
#include "firmwareupdatedialog.h" #include "firmwareupdatedialog.h"
#include "ui_firmwareupdatedialog.h" #include "ui_firmwareupdatedialog.h"
#include "../../VNA_embedded/Application/Communication/PacketConstants.h"
#include <QFileDialog> #include <QFileDialog>
#include <QStyle> #include <QStyle>
@ -49,7 +50,7 @@ void FirmwareUpdateDialog::on_bStart_clicked()
} }
file->seek(0); file->seek(0);
addStatus("Evaluating file..."); addStatus("Evaluating file...");
if(file->size() % Protocol::FirmwareChunkSize != 0) { if(file->size() % PacketConstants::FW_CHUNK_SIZE != 0) {
abortWithError("Invalid file size"); abortWithError("Invalid file size");
return; return;
} }
@ -132,7 +133,7 @@ void FirmwareUpdateDialog::receivedAck()
timer.start(1000); timer.start(1000);
break; break;
case State::TransferringData: case State::TransferringData:
transferredBytes += Protocol::FirmwareChunkSize; transferredBytes += PacketConstants::FW_CHUNK_SIZE;
ui->progress->setValue(100 * transferredBytes / file->size()); ui->progress->setValue(100 * transferredBytes / file->size());
if(transferredBytes >= file->size()) { if(transferredBytes >= file->size()) {
// complete file transferred // complete file transferred
@ -175,6 +176,6 @@ void FirmwareUpdateDialog::sendNextFirmwareChunk()
{ {
Protocol::FirmwarePacket fw; Protocol::FirmwarePacket fw;
fw.address = transferredBytes; fw.address = transferredBytes;
file->read((char*) &fw.data, Protocol::FirmwareChunkSize); file->read((char*) &fw.data, PacketConstants::FW_CHUNK_SIZE);
dev->SendFirmwareChunk(fw); dev->SendFirmwareChunk(fw);
} }

View File

@ -1,5 +1,6 @@
HEADERS += \ HEADERS += \
../../VNA_embedded/Application/Communication/Protocol.hpp \ ../../VNA_embedded/Application/Communication/Protocol.hpp \
../../VNA_embedded/Application/Communication/PacketConstants.h \
Calibration/LibreCAL/caldevice.h \ Calibration/LibreCAL/caldevice.h \
Calibration/LibreCAL/librecaldialog.h \ Calibration/LibreCAL/librecaldialog.h \
Calibration/LibreCAL/usbdevice.h \ Calibration/LibreCAL/usbdevice.h \

View File

@ -0,0 +1,49 @@
#pragma once
#include <cstdint>
namespace PacketConstants {
// USB protocol packet field constants
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;
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
// 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 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;
}

View File

@ -1,19 +1,16 @@
#include "Protocol.hpp" #include "Protocol.hpp"
#include <cstring> #include <cstring>
#include "PacketConstants.h"
/* /*
* General packet format: * General packet format:
* 1. 1 byte header * 1. 1 byte header
* 2. 2 byte overall packet length (with header and checksum) * 2. 2 byte overall packet length (with header and checksum)
* 3. packet type * 3. 1 byte packet type
* 4. packet payload * 4. variable length packet payload
* 5. 4 byte CRC32 (with header) * 5. 4 byte CRC32 (with header)
*/ */
static constexpr uint8_t header = 0x5A;
static constexpr uint8_t header_size = 4;
#define CRC32_POLYGON 0xEDB88320 #define CRC32_POLYGON 0xEDB88320
uint32_t Protocol::CRC32(uint32_t crc, const void *data, uint32_t len) { uint32_t Protocol::CRC32(uint32_t crc, const void *data, uint32_t len) {
uint8_t *u8buf = (uint8_t*) data; uint8_t *u8buf = (uint8_t*) data;
@ -35,7 +32,7 @@ uint16_t Protocol::DecodeBuffer(uint8_t *buf, uint16_t len, PacketInfo *info) {
} }
uint8_t *data = buf; uint8_t *data = buf;
/* Remove any out-of-order bytes in front of the frame */ /* Remove any out-of-order bytes in front of the frame */
while (*data != header) { while (*data != PCKT_HEADER_DATA) {
data++; data++;
if(--len == 0) { if(--len == 0) {
/* Reached end of data */ /* Reached end of data */
@ -45,16 +42,16 @@ uint16_t Protocol::DecodeBuffer(uint8_t *buf, uint16_t len, PacketInfo *info) {
} }
} }
/* At this point, data points to the beginning of the frame */ /* At this point, data points to the beginning of the frame */
if(len < header_size) { if(len < PCKT_COMBINED_HEADER_LEN) {
/* the frame header has not been completely received */ /* the frame header has not been completely received */
info->type = PacketType::None; info->type = PacketType::None;
return data - buf; return data - buf;
} }
/* Evaluate frame size */ /* Evaluate frame size */
uint16_t length = data[1] | ((uint16_t) data[2] << 8); uint16_t length = data[PCKT_LENGTH_OFFSET] | ((uint16_t) data[2] << 8);
if(length > sizeof(PacketInfo) * 2 || length < 8) { if(length > sizeof(PacketInfo) * 2 || length < PCKT_EXCL_PAYLOAD_LEN) {
// larger than twice the maximum expected packet size or too small, probably an error, ignore // larger than twice the maximum expected packet size or too small, probably an error, ignore
info->type = PacketType::None; info->type = PacketType::None;
return 1; return 1;
@ -67,10 +64,10 @@ uint16_t Protocol::DecodeBuffer(uint8_t *buf, uint16_t len, PacketInfo *info) {
} }
/* The complete frame has been received, check checksum */ /* The complete frame has been received, check checksum */
auto type = (PacketType) data[3]; 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); 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) { if(type != PacketType::VNADatapoint) {
uint32_t compare = CRC32(0, data, length - 4); uint32_t compare = CRC32(0, data, length - PCKT_CRC_LEN);
if(crc != compare) { if(crc != compare) {
// CRC mismatch, remove header // CRC mismatch, remove header
data += 1; data += 1;
@ -78,7 +75,7 @@ uint16_t Protocol::DecodeBuffer(uint8_t *buf, uint16_t len, PacketInfo *info) {
return data - buf; return data - buf;
} }
// Valid packet, copy packet type and payload // Valid packet, copy packet type and payload
memcpy(info, &data[3], length - 7); memcpy(info, &data[PCKT_TYPE_OFFSET], length - 7);
} else { } else {
// Datapoint has the CRC set to zero // Datapoint has the CRC set to zero
if(crc != 0x00000000) { if(crc != 0x00000000) {
@ -87,9 +84,9 @@ uint16_t Protocol::DecodeBuffer(uint8_t *buf, uint16_t len, PacketInfo *info) {
return data - buf; return data - buf;
} }
// Create the datapoint // Create the datapoint
info->type = (PacketType) data[3]; info->type = (PacketType) data[PCKT_TYPE_OFFSET];
info->VNAdatapoint = new VNADatapoint<32>; info->VNAdatapoint = new VNADatapoint<32>;
info->VNAdatapoint->decode(&data[4], length - 8); info->VNAdatapoint->decode(&data[PCKT_PAYLOAD_OFFSET], length - PCKT_EXCL_PAYLOAD_LEN);
} }
return data - buf + length; return data - buf + length;
@ -132,29 +129,29 @@ uint16_t Protocol::EncodePacket(const PacketInfo &packet, uint8_t *dest, uint16_
case PacketType::None: case PacketType::None:
break; break;
} }
if (payload_size < 0 || payload_size + 8 > destsize) { if (payload_size < 0 || payload_size + PCKT_EXCL_PAYLOAD_LEN > destsize) {
// encoding failed, buffer too small // encoding failed, buffer too small
return 0; return 0;
} }
// Write header // Write header
dest[0] = header; dest[PCKT_HEADER_OFFSET] = PCKT_HEADER_DATA;
uint16_t overall_size = payload_size + 8; uint16_t overall_size = payload_size + PCKT_EXCL_PAYLOAD_LEN;
memcpy(&dest[1], &overall_size, 2); memcpy(&dest[PCKT_LENGTH_OFFSET], &overall_size, PCKT_LENGTH_LEN);
// Further encoding uses a special case for VNADatapoint packettype // Further encoding uses a special case for VNADatapoint packettype
uint32_t crc = 0x00000000; uint32_t crc = 0x00000000;
if(packet.type == PacketType::VNADatapoint) { if(packet.type == PacketType::VNADatapoint) {
// CRC calculation takes about 18us which is the bulk of the time required to encode and transmit a datapoint. // 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 // Skip CRC for data points to optimize throughput
dest[3] = (uint8_t) packet.type; dest[PCKT_TYPE_OFFSET] = (uint8_t) packet.type;
packet.VNAdatapoint->encode(&dest[4], destsize - 8); packet.VNAdatapoint->encode(&dest[PCKT_PAYLOAD_OFFSET], destsize - PCKT_EXCL_PAYLOAD_LEN);
crc = 0x00000000; crc = 0x00000000;
} else { } else {
// Copy rest of the packet // Copy rest of the packet
memcpy(&dest[3], &packet, payload_size + 1); // one additional byte for the packet type memcpy(&dest[PCKT_TYPE_OFFSET], &packet, payload_size + PCKT_TYPE_LEN); // one additional byte for the packet type
// Calculate the CRC // Calculate the CRC
crc = CRC32(0, dest, overall_size - 4); crc = CRC32(0, dest, overall_size - PCKT_CRC_LEN);
} }
memcpy(&dest[overall_size - 4], &crc, 4); memcpy(&dest[overall_size - PCKT_CRC_LEN], &crc, PCKT_CRC_LEN);
return overall_size; return overall_size;
} }

View File

@ -1,9 +1,13 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
#include <limits> #include <limits>
#include <complex> #include <complex>
#include "PacketConstants.h"
using namespace PacketConstants;
namespace Protocol { namespace Protocol {
@ -37,7 +41,7 @@ public:
} }
real_values[num_values] = real; real_values[num_values] = real;
imag_values[num_values] = imag; imag_values[num_values] = imag;
descr_values[num_values] = stage << 5 | sourceMask; descr_values[num_values] = stage << DPNT_CONF_STAGE_OFFSET | sourceMask;
num_values++; num_values++;
return true; return true;
} }
@ -46,27 +50,32 @@ public:
if(requiredBufferSize() > destSize) { if(requiredBufferSize() > destSize) {
return false; return false;
} }
memcpy(dest, &frequency, 8); memcpy(dest, &frequency, DPNT_FREQ_LEN);
memcpy(dest+8, &cdBm, 2); dest += DPNT_FREQ_LEN;
memcpy(dest+10, &pointNum, 2); memcpy(dest, &cdBm, DPNT_POW_LVL_LEN);
dest += 12; dest += DPNT_POW_LVL_LEN;
memcpy(dest, real_values, num_values * 4); memcpy(dest, &pointNum, DPNT_PNT_NUM_LEN);
dest += num_values * 4; dest += DPNT_PNT_NUM_LEN;
memcpy(dest, imag_values, num_values * 4); memcpy(dest, real_values, num_values * DPNT_REAL_PART_LEN);
dest += num_values * 4; 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); memcpy(dest, descr_values, num_values);
return true; return true;
} }
void decode(const uint8_t *buffer, uint16_t size) { void decode(const uint8_t *buffer, uint16_t size) {
num_values = (size - (8+2+2)) / (1+4+4); num_values = (size - (DPNT_FREQ_LEN + DPNT_POW_LVL_LEN + DPNT_PNT_NUM_LEN)) /
memcpy(&frequency, buffer, 8); (DPNT_REAL_PART_LEN + DPNT_IMAG_PART_LEN + DPNT_DESC_LEN);
memcpy(&cdBm, buffer+8, 2); memcpy(&frequency, buffer, DPNT_FREQ_LEN);
memcpy(&pointNum, buffer+10, 2); buffer += DPNT_FREQ_LEN;
buffer += 12; memcpy(&cdBm, buffer, DPNT_POW_LVL_LEN);
memcpy(real_values, buffer, num_values * 4); buffer += DPNT_POW_LVL_LEN;
buffer += num_values * 4; memcpy(&pointNum, buffer, DPNT_PNT_NUM_LEN);
memcpy(imag_values, buffer, num_values * 4); buffer += DPNT_PNT_NUM_LEN;
buffer += num_values * 4; memcpy(real_values, buffer, num_values * DPNT_REAL_PART_LEN);
buffer += num_values * DPNT_REAL_PART_LEN;
memcpy(imag_values, buffer, num_values * DPNT_IMAG_PART_LEN);
buffer += num_values * DPNT_IMAG_PART_LEN;
memcpy(descr_values, buffer, num_values); memcpy(descr_values, buffer, num_values);
} }
@ -77,7 +86,7 @@ public:
sourceMask |= (int) Source::Reference; sourceMask |= (int) Source::Reference;
} }
for(int i=0;i<num_values;i++) { for(int i=0;i<num_values;i++) {
if(descr_values[i] >> 5 != stage) { if(descr_values[i] >> DPNT_CONF_STAGE_OFFSET != stage) {
continue; continue;
} }
if((descr_values[i] & sourceMask) != sourceMask) { if((descr_values[i] & sourceMask) != sourceMask) {
@ -108,7 +117,8 @@ public:
} }
uint16_t requiredBufferSize() { uint16_t requiredBufferSize() {
return 8+2+2+ num_values * (4+4+1); 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 { union {
@ -299,10 +309,10 @@ using SpectrumAnalyzerResult = struct _spectrumAnalyzerResult {
uint16_t pointNum; uint16_t pointNum;
}; };
static constexpr uint16_t FirmwareChunkSize = 256;
using FirmwarePacket = struct _firmwarePacket { using FirmwarePacket = struct _firmwarePacket {
uint32_t address; uint32_t address;
uint8_t data[FirmwareChunkSize]; uint8_t data[FW_CHUNK_SIZE];
}; };
using AmplitudeCorrectionPoint = struct _amplitudecorrectionpoint { using AmplitudeCorrectionPoint = struct _amplitudecorrectionpoint {