2020-08-25 01:06:50 +08:00
|
|
|
#include "Protocol.hpp"
|
|
|
|
#include <cstring>
|
2022-11-29 16:44:27 +08:00
|
|
|
#include "PacketConstants.h"
|
2020-08-25 01:06:50 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* General packet format:
|
|
|
|
* 1. 1 byte header
|
|
|
|
* 2. 2 byte overall packet length (with header and checksum)
|
2022-11-29 16:44:27 +08:00
|
|
|
* 3. 1 byte packet type
|
|
|
|
* 4. variable length packet payload
|
2020-08-25 01:06:50 +08:00
|
|
|
* 5. 4 byte CRC32 (with header)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define CRC32_POLYGON 0xEDB88320
|
2020-08-30 22:20:00 +08:00
|
|
|
uint32_t Protocol::CRC32(uint32_t crc, const void *data, uint32_t len) {
|
2020-08-25 01:06:50 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
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 */
|
2022-11-29 16:44:27 +08:00
|
|
|
while (*data != PCKT_HEADER_DATA) {
|
2020-08-25 01:06:50 +08:00
|
|
|
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 */
|
2022-11-29 16:44:27 +08:00
|
|
|
if(len < PCKT_COMBINED_HEADER_LEN) {
|
2020-08-25 01:06:50 +08:00
|
|
|
/* the frame header has not been completely received */
|
|
|
|
info->type = PacketType::None;
|
|
|
|
return data - buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Evaluate frame size */
|
2022-11-29 16:44:27 +08:00
|
|
|
uint16_t length = data[PCKT_LENGTH_OFFSET] | ((uint16_t) data[2] << 8);
|
2020-08-25 01:06:50 +08:00
|
|
|
|
2022-11-29 16:44:27 +08:00
|
|
|
if(length > sizeof(PacketInfo) * 2 || length < PCKT_EXCL_PAYLOAD_LEN) {
|
2022-10-28 06:14:24 +08:00
|
|
|
// larger than twice the maximum expected packet size or too small, probably an error, ignore
|
2022-08-22 04:20:59 +08:00
|
|
|
info->type = PacketType::None;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2022-10-28 06:14:24 +08:00
|
|
|
if(len < length) {
|
|
|
|
/* The frame payload has not been completely received */
|
|
|
|
info->type = PacketType::None;
|
|
|
|
return data - buf;
|
|
|
|
}
|
|
|
|
|
2021-02-18 01:37:50 +08:00
|
|
|
/* The complete frame has been received, check checksum */
|
2022-11-29 16:44:27 +08:00
|
|
|
auto type = (PacketType) data[PCKT_TYPE_OFFSET];
|
2022-10-28 06:14:24 +08:00
|
|
|
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);
|
2022-08-06 22:22:12 +08:00
|
|
|
if(type != PacketType::VNADatapoint) {
|
2022-11-29 16:44:27 +08:00
|
|
|
uint32_t compare = CRC32(0, data, length - PCKT_CRC_LEN);
|
2021-02-18 01:37:50 +08:00
|
|
|
if(crc != compare) {
|
|
|
|
// CRC mismatch, remove header
|
|
|
|
data += 1;
|
|
|
|
info->type = PacketType::None;
|
|
|
|
return data - buf;
|
|
|
|
}
|
2022-08-06 22:22:12 +08:00
|
|
|
// Valid packet, copy packet type and payload
|
2022-11-29 16:44:27 +08:00
|
|
|
memcpy(info, &data[PCKT_TYPE_OFFSET], length - 7);
|
2021-02-18 01:37:50 +08:00
|
|
|
} else {
|
|
|
|
// Datapoint has the CRC set to zero
|
|
|
|
if(crc != 0x00000000) {
|
|
|
|
data += 1;
|
|
|
|
info->type = PacketType::None;
|
|
|
|
return data - buf;
|
|
|
|
}
|
2022-08-06 22:22:12 +08:00
|
|
|
// Create the datapoint
|
2022-11-29 16:44:27 +08:00
|
|
|
info->type = (PacketType) data[PCKT_TYPE_OFFSET];
|
2022-08-06 22:22:12 +08:00
|
|
|
info->VNAdatapoint = new VNADatapoint<32>;
|
2022-11-29 16:44:27 +08:00
|
|
|
info->VNAdatapoint->decode(&data[PCKT_PAYLOAD_OFFSET], length - PCKT_EXCL_PAYLOAD_LEN);
|
2020-08-25 01:06:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return data - buf + length;
|
|
|
|
}
|
|
|
|
|
2020-10-04 03:56:09 +08:00
|
|
|
uint16_t Protocol::EncodePacket(const PacketInfo &packet, uint8_t *dest, uint16_t destsize) {
|
|
|
|
int16_t payload_size = 0;
|
2020-08-25 01:06:50 +08:00
|
|
|
switch (packet.type) {
|
2022-08-06 22:22:12 +08:00
|
|
|
// case PacketType::Datapoint: payload_size = sizeof(packet.datapoint); break;
|
2021-02-18 01:37:50 +08:00
|
|
|
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;
|
2022-04-04 02:26:30 +08:00
|
|
|
case PacketType::DeviceStatusV1: payload_size = sizeof(packet.statusV1); break;
|
|
|
|
case PacketType::ManualStatusV1: payload_size = sizeof(packet.manualStatusV1); break;
|
|
|
|
case PacketType::ManualControlV1: payload_size = sizeof(packet.manual); break;
|
2021-02-18 01:37:50 +08:00
|
|
|
case PacketType::FirmwarePacket: payload_size = sizeof(packet.firmware); break;
|
|
|
|
case PacketType::Generator: payload_size = sizeof(packet.generator); break;
|
|
|
|
case PacketType::SpectrumAnalyzerSettings: payload_size = sizeof(packet.spectrumSettings); break;
|
|
|
|
case PacketType::SpectrumAnalyzerResult: payload_size = sizeof(packet.spectrumResult); break;
|
2020-11-17 03:05:29 +08:00
|
|
|
case PacketType::SourceCalPoint:
|
2021-02-18 01:37:50 +08:00
|
|
|
case PacketType::ReceiverCalPoint: payload_size = sizeof(packet.amplitudePoint); break;
|
2021-05-02 00:34:53 +08:00
|
|
|
case PacketType::FrequencyCorrection: payload_size = sizeof(packet.frequencyCorrection); break;
|
2022-01-15 23:11:33 +08:00
|
|
|
case PacketType::AcquisitionFrequencySettings: payload_size = sizeof(packet.acquisitionFrequencySettings); break;
|
2020-08-31 04:03:41 +08:00
|
|
|
case PacketType::Ack:
|
2020-08-31 23:57:24 +08:00
|
|
|
case PacketType::PerformFirmwareUpdate:
|
|
|
|
case PacketType::ClearFlash:
|
2020-09-12 18:17:35 +08:00
|
|
|
case PacketType::Nack:
|
2020-11-07 20:22:10 +08:00
|
|
|
case PacketType::RequestDeviceInfo:
|
2020-11-17 03:05:29 +08:00
|
|
|
case PacketType::RequestSourceCal:
|
|
|
|
case PacketType::RequestReceiverCal:
|
2020-12-16 01:03:29 +08:00
|
|
|
case PacketType::SetIdle:
|
2021-05-02 00:34:53 +08:00
|
|
|
case PacketType::RequestFrequencyCorrection:
|
2022-01-15 23:11:33 +08:00
|
|
|
case PacketType::RequestAcquisitionFrequencySettings:
|
2022-08-06 00:29:31 +08:00
|
|
|
case PacketType::RequestDeviceStatus:
|
2022-08-07 09:01:22 +08:00
|
|
|
case PacketType::SetTrigger:
|
|
|
|
case PacketType::ClearTrigger:
|
2022-12-06 14:29:33 +08:00
|
|
|
case PacketType::StopStatusUpdates:
|
|
|
|
case PacketType::StartStatusUpdates:
|
2022-12-17 15:41:59 +08:00
|
|
|
case PacketType::InitiateSweep:
|
2021-02-18 01:37:50 +08:00
|
|
|
// no payload
|
2020-08-31 04:03:41 +08:00
|
|
|
break;
|
2022-08-06 22:22:12 +08:00
|
|
|
case PacketType::VNADatapoint: payload_size = packet.VNAdatapoint->requiredBufferSize(); break;
|
2020-08-25 01:06:50 +08:00
|
|
|
case PacketType::None:
|
|
|
|
break;
|
|
|
|
}
|
2022-11-29 16:44:27 +08:00
|
|
|
if (payload_size < 0 || payload_size + PCKT_EXCL_PAYLOAD_LEN > destsize) {
|
2020-08-25 01:06:50 +08:00
|
|
|
// encoding failed, buffer too small
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
// Write header
|
2022-11-29 16:44:27 +08:00
|
|
|
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);
|
2022-08-06 22:22:12 +08:00
|
|
|
// Further encoding uses a special case for VNADatapoint packettype
|
2020-10-04 03:56:09 +08:00
|
|
|
uint32_t crc = 0x00000000;
|
2022-08-06 22:22:12 +08:00
|
|
|
if(packet.type == PacketType::VNADatapoint) {
|
2020-10-04 03:56:09 +08:00
|
|
|
// 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
|
2022-11-29 16:44:27 +08:00
|
|
|
dest[PCKT_TYPE_OFFSET] = (uint8_t) packet.type;
|
|
|
|
packet.VNAdatapoint->encode(&dest[PCKT_PAYLOAD_OFFSET], destsize - PCKT_EXCL_PAYLOAD_LEN);
|
2020-10-04 03:56:09 +08:00
|
|
|
crc = 0x00000000;
|
|
|
|
} else {
|
2022-08-06 22:22:12 +08:00
|
|
|
// Copy rest of the packet
|
2022-11-29 16:44:27 +08:00
|
|
|
memcpy(&dest[PCKT_TYPE_OFFSET], &packet, payload_size + PCKT_TYPE_LEN); // one additional byte for the packet type
|
2022-08-06 22:22:12 +08:00
|
|
|
// Calculate the CRC
|
2022-11-29 16:44:27 +08:00
|
|
|
crc = CRC32(0, dest, overall_size - PCKT_CRC_LEN);
|
2020-10-04 03:56:09 +08:00
|
|
|
}
|
2022-11-29 16:44:27 +08:00
|
|
|
memcpy(&dest[overall_size - PCKT_CRC_LEN], &crc, PCKT_CRC_LEN);
|
2020-08-25 01:06:50 +08:00
|
|
|
return overall_size;
|
|
|
|
}
|
|
|
|
|