Move payload CRC to layer 2
Layer 1 only does decoding of the FEC, but the CRC check for data integrity is done in layer 2 now.
This commit is contained in:
parent
0e8e049e0a
commit
f6404dd0ea
|
@ -16,7 +16,7 @@
|
||||||
#define PAYLOAD_CHANNEL_CODE LIQUID_FEC_CONV_V27P34
|
#define PAYLOAD_CHANNEL_CODE LIQUID_FEC_CONV_V27P34
|
||||||
#define PAYLOAD_MODULATION LIQUID_MODEM_QAM16
|
#define PAYLOAD_MODULATION LIQUID_MODEM_QAM16
|
||||||
|
|
||||||
#define HEADER_CHANNEL_CODE LIQUID_FEC_HAMMING84
|
#define HEADER_CHANNEL_CODE LIQUID_FEC_HAMMING128
|
||||||
#define HEADER_MODULATION LIQUID_MODEM_QPSK
|
#define HEADER_MODULATION LIQUID_MODEM_QPSK
|
||||||
|
|
||||||
#define PAYLOAD_CRC_SCHEME LIQUID_CRC_16
|
#define PAYLOAD_CRC_SCHEME LIQUID_CRC_16
|
||||||
|
|
|
@ -81,7 +81,6 @@ result_t packet_mod_set_data(packet_mod_ctx_t *ctx, const unsigned char *data, s
|
||||||
memcpy(ctx->pkt_bytes, data, length);
|
memcpy(ctx->pkt_bytes, data, length);
|
||||||
ctx->length = length;
|
ctx->length = length;
|
||||||
|
|
||||||
ctx->raw_data_crc = crc_generate_key(PAYLOAD_CRC_SCHEME, (unsigned char *)data, length);
|
|
||||||
ctx->raw_data_len = length;
|
ctx->raw_data_len = length;
|
||||||
|
|
||||||
ctx->state = DATA_RAW;
|
ctx->state = DATA_RAW;
|
||||||
|
@ -173,18 +172,12 @@ result_t packet_mod_add_header(packet_mod_ctx_t *ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// build the header. All field are transferred in network byte order (big endian).
|
// build the header. All field are transferred in network byte order (big endian).
|
||||||
uint8_t header[5];
|
uint8_t header[2];
|
||||||
|
|
||||||
// set length
|
// set length
|
||||||
header[0] = (ctx->raw_data_len >> 8) & 0x07;
|
header[0] = (ctx->raw_data_len >> 8) & 0x07;
|
||||||
header[0] |= ctx->modcod << 3;
|
header[0] |= ctx->modcod << 3;
|
||||||
header[1] = (ctx->raw_data_len >> 0) & 0xFF;
|
header[1] = (ctx->raw_data_len >> 0) & 0xFF;
|
||||||
// set raw data CRC
|
|
||||||
header[2] = (ctx->raw_data_crc >> 8) & 0xFF;
|
|
||||||
header[3] = (ctx->raw_data_crc >> 0) & 0xFF;
|
|
||||||
|
|
||||||
// append an 8-bit CRC to the header
|
|
||||||
crc_append_key(LIQUID_CRC_8, header, 4);
|
|
||||||
|
|
||||||
// note: the header is coded and modulated differently than the data.
|
// note: the header is coded and modulated differently than the data.
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,6 @@ typedef struct
|
||||||
modem hdr_modem;
|
modem hdr_modem;
|
||||||
fec hdr_fec;
|
fec hdr_fec;
|
||||||
|
|
||||||
uint16_t raw_data_crc;
|
|
||||||
uint16_t raw_data_len;
|
uint16_t raw_data_len;
|
||||||
|
|
||||||
uint8_t modcod;
|
uint8_t modcod;
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
#define SYMBOL_BUFFER_SIZE 16384
|
#define SYMBOL_BUFFER_SIZE 16384
|
||||||
|
|
||||||
#define HEADER_SIZE_BYTES 5 // including CRC
|
#define HEADER_SIZE_BYTES 2
|
||||||
#define FREQ_EST_L 24
|
#define FREQ_EST_L 24
|
||||||
|
|
||||||
#define AGC_BW_ACQUISITION 5e-2f
|
#define AGC_BW_ACQUISITION 5e-2f
|
||||||
|
@ -370,18 +370,7 @@ result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CRC check
|
|
||||||
if(crc_check_key(LIQUID_CRC_8, header, HEADER_SIZE_BYTES) != LIQUID_OK) {
|
|
||||||
uint8_t expected_crc = crc_generate_key(LIQUID_CRC_8, header, 4);
|
|
||||||
LOG(LVL_WARN, "@%zu: Header CRC check failed! Expected: 0x%02x, received: 0x%02x",
|
|
||||||
rx->sample_index, expected_crc, header[4]);
|
|
||||||
rx->state = RX_STATE_ACQUISITION;
|
|
||||||
rx->callback(RX_EVT_HEADER_ERROR, rx, NULL, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
rx->payload_len_bytes = (((uint16_t)header[0] << 8) | header[1]) & 0x07FF;
|
rx->payload_len_bytes = (((uint16_t)header[0] << 8) | header[1]) & 0x07FF;
|
||||||
rx->payload_crc = ((uint16_t)header[2] << 8) | header[3];
|
|
||||||
rx->modcod = header[0] >> 3;
|
rx->modcod = header[0] >> 3;
|
||||||
|
|
||||||
// check the received information
|
// check the received information
|
||||||
|
@ -417,7 +406,6 @@ result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t
|
||||||
|
|
||||||
LOG(LVL_DUMP, "=== DECODED HEADER @%zu ===", rx->sample_index);
|
LOG(LVL_DUMP, "=== DECODED HEADER @%zu ===", rx->sample_index);
|
||||||
LOG(LVL_DUMP, "Payload length: %u symbols, %u bytes encoded, %u bytes decoded", rx->payload_len_symbols, rx->payload_len_enc_bytes, rx->payload_len_bytes);
|
LOG(LVL_DUMP, "Payload length: %u symbols, %u bytes encoded, %u bytes decoded", rx->payload_len_symbols, rx->payload_len_enc_bytes, rx->payload_len_bytes);
|
||||||
LOG(LVL_DUMP, "CRC16: 0x%04x", rx->payload_crc);
|
|
||||||
LOG(LVL_DUMP, "======================");
|
LOG(LVL_DUMP, "======================");
|
||||||
|
|
||||||
//dump_array_cf(symbols_cpx, symbol_counter, 1.0f, "/tmp/hdr.cpx");
|
//dump_array_cf(symbols_cpx, symbol_counter, 1.0f, "/tmp/hdr.cpx");
|
||||||
|
@ -461,22 +449,25 @@ result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t
|
||||||
payload_enc, 8, sizeof(payload_enc), &nsyms));
|
payload_enc, 8, sizeof(payload_enc), &nsyms));
|
||||||
|
|
||||||
fec payload_fec = modcod_create_fec(rx->modcod);
|
fec payload_fec = modcod_create_fec(rx->modcod);
|
||||||
fec_decode(payload_fec, rx->payload_len_bytes, payload_enc, payload);
|
result_t res = fec_decode(payload_fec, rx->payload_len_bytes, payload_enc, payload);
|
||||||
fec_destroy(payload_fec);
|
fec_destroy(payload_fec);
|
||||||
|
|
||||||
|
if(res != LIQUID_OK) {
|
||||||
|
LOG(LVL_WARN, "@%zu: Payload decoding failed!", rx->sample_index);
|
||||||
|
rx->state = RX_STATE_ACQUISITION;
|
||||||
|
rx->callback(RX_EVT_DECODE_FAILED, rx, NULL, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// de-whiten the data
|
// de-whiten the data
|
||||||
whitening_apply_in_place(payload, rx->payload_len_bytes);
|
whitening_apply_in_place(payload, rx->payload_len_bytes);
|
||||||
|
|
||||||
int valid = crc_validate_message(PAYLOAD_CRC_SCHEME, payload, rx->payload_len_bytes, rx->payload_crc);
|
// note: CRC is included in data and checked in layer 2
|
||||||
|
|
||||||
payload[rx->payload_len_bytes] = '\0';
|
payload[rx->payload_len_bytes] = '\0';
|
||||||
|
|
||||||
//dump_array_cf(symbols_cpx, symbol_counter, 1.0f, "/tmp/payload.cpx");
|
//dump_array_cf(symbols_cpx, symbol_counter, 1.0f, "/tmp/payload.cpx");
|
||||||
if(valid) {
|
|
||||||
rx->callback(RX_EVT_PACKET_RECEIVED, rx, payload, rx->payload_len_bytes);
|
rx->callback(RX_EVT_PACKET_RECEIVED, rx, payload, rx->payload_len_bytes);
|
||||||
} else {
|
|
||||||
rx->callback(RX_EVT_CHECKSUM_ERROR, rx, payload, rx->payload_len_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
modem_destroy(rx->payload_demod);
|
modem_destroy(rx->payload_demod);
|
||||||
rx->state = RX_STATE_ACQUISITION;
|
rx->state = RX_STATE_ACQUISITION;
|
||||||
|
|
|
@ -20,7 +20,7 @@ typedef enum {
|
||||||
RX_EVT_PACKET_RECEIVED,
|
RX_EVT_PACKET_RECEIVED,
|
||||||
RX_EVT_PREAMBLE_FOUND,
|
RX_EVT_PREAMBLE_FOUND,
|
||||||
RX_EVT_HEADER_ERROR,
|
RX_EVT_HEADER_ERROR,
|
||||||
RX_EVT_CHECKSUM_ERROR,
|
RX_EVT_DECODE_FAILED,
|
||||||
RX_EVT_PACKET_DEBUG_INFO_COMPLETE,
|
RX_EVT_PACKET_DEBUG_INFO_COMPLETE,
|
||||||
} rx_evt_t;
|
} rx_evt_t;
|
||||||
|
|
||||||
|
@ -69,7 +69,6 @@ typedef struct layer1_rx_s
|
||||||
// Information from the decoded header
|
// Information from the decoded header
|
||||||
uint16_t payload_len_symbols;
|
uint16_t payload_len_symbols;
|
||||||
uint16_t payload_len_bytes;
|
uint16_t payload_len_bytes;
|
||||||
uint16_t payload_crc;
|
|
||||||
uint16_t payload_len_enc_bytes;
|
uint16_t payload_len_enc_bytes;
|
||||||
modcod_t modcod;
|
modcod_t modcod;
|
||||||
|
|
||||||
|
|
|
@ -116,7 +116,7 @@ void cb_rx(rx_evt_t evt, const struct layer1_rx_s *rx, uint8_t *packet_data, siz
|
||||||
|
|
||||||
switch(evt)
|
switch(evt)
|
||||||
{
|
{
|
||||||
case RX_EVT_CHECKSUM_ERROR:
|
case RX_EVT_DECODE_FAILED:
|
||||||
//LOG(LVL_WARN, "Received a message of %zu bytes, but decoding failed.", packet_len);
|
//LOG(LVL_WARN, "Received a message of %zu bytes, but decoding failed.", packet_len);
|
||||||
//LOG(LVL_INFO, "=== FAILED PAYLOAD ===");
|
//LOG(LVL_INFO, "=== FAILED PAYLOAD ===");
|
||||||
//hexdump(packet_data, packet_len);
|
//hexdump(packet_data, packet_len);
|
||||||
|
@ -138,7 +138,15 @@ void cb_rx(rx_evt_t evt, const struct layer1_rx_s *rx, uint8_t *packet_data, siz
|
||||||
|
|
||||||
block_tx_for(TX_SWITCH_BACKOFF_END_OF_PACKET_MS);
|
block_tx_for(TX_SWITCH_BACKOFF_END_OF_PACKET_MS);
|
||||||
|
|
||||||
ret = write(m_tunfd, packet_data, packet_len);
|
unsigned int data_size = packet_len - crc_sizeof_key(PAYLOAD_CRC_SCHEME);
|
||||||
|
|
||||||
|
// FIXME: move to layer 2
|
||||||
|
if(!crc_check_key(PAYLOAD_CRC_SCHEME, packet_data, data_size)) {
|
||||||
|
LOG(LVL_WARN, "payload CRC check failed!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = write(m_tunfd, packet_data, data_size);
|
||||||
if(ret < 0) {
|
if(ret < 0) {
|
||||||
LOG(LVL_ERR, "write: %s", strerror(errno));
|
LOG(LVL_ERR, "write: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
|
@ -278,6 +286,16 @@ int main(int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* append CRC to packet */
|
||||||
|
|
||||||
|
unsigned int crc_size = crc_sizeof_key(PAYLOAD_CRC_SCHEME);
|
||||||
|
if((unsigned)ret > sizeof(packetbuf) - crc_size) {
|
||||||
|
LOG(LVL_ERR, "Packet is too large to append CRC! %i bytes.", ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
crc_append_key(PAYLOAD_CRC_SCHEME, packetbuf, ret);
|
||||||
|
|
||||||
LOG(LVL_DEBUG, "Transmitting packet with %d bytes.", ret);
|
LOG(LVL_DEBUG, "Transmitting packet with %d bytes.", ret);
|
||||||
|
|
||||||
RESULT_CHECK(layer1_tx_reset(&tx));
|
RESULT_CHECK(layer1_tx_reset(&tx));
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
#define RESULT_CHECK(stmt) { \
|
#define RESULT_CHECK(stmt) { \
|
||||||
result_t res = stmt; \
|
result_t res = stmt; \
|
||||||
|
@ -77,9 +78,11 @@ void cb_rx(rx_evt_t evt, const layer1_rx_t *rx, uint8_t *packet_data, size_t pac
|
||||||
{
|
{
|
||||||
(void)rx;
|
(void)rx;
|
||||||
|
|
||||||
|
unsigned int data_size;
|
||||||
|
|
||||||
switch(evt)
|
switch(evt)
|
||||||
{
|
{
|
||||||
case RX_EVT_CHECKSUM_ERROR:
|
case RX_EVT_DECODE_FAILED:
|
||||||
LOG(LVL_ERR, "Received a message of %zu bytes, but decoding failed.", packet_len);
|
LOG(LVL_ERR, "Received a message of %zu bytes, but decoding failed.", packet_len);
|
||||||
LOG(LVL_INFO, "=== FAILED PAYLOAD ===");
|
LOG(LVL_INFO, "=== FAILED PAYLOAD ===");
|
||||||
hexdump(packet_data, packet_len);
|
hexdump(packet_data, packet_len);
|
||||||
|
@ -87,10 +90,19 @@ void cb_rx(rx_evt_t evt, const layer1_rx_t *rx, uint8_t *packet_data, size_t pac
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RX_EVT_PACKET_RECEIVED:
|
case RX_EVT_PACKET_RECEIVED:
|
||||||
LOG(LVL_INFO, "A message of %zu bytes was decoded successfully.", packet_len);
|
data_size = packet_len - crc_sizeof_key(PAYLOAD_CRC_SCHEME);
|
||||||
|
|
||||||
LOG(LVL_INFO, "=== DECODED PAYLOAD (%4zu bytes) ===", packet_len);
|
LOG(LVL_INFO, "=== DECODED PAYLOAD (%4zu bytes) ===", packet_len);
|
||||||
hexdump(packet_data, packet_len < 64 ? packet_len : 64);
|
hexdump(packet_data, packet_len);
|
||||||
LOG(LVL_INFO, "====================================");
|
LOG(LVL_INFO, "====================================");
|
||||||
|
|
||||||
|
// FIXME: move to layer 2
|
||||||
|
if(!crc_check_key(PAYLOAD_CRC_SCHEME, packet_data, data_size)) {
|
||||||
|
LOG(LVL_WARN, "payload CRC check failed!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(LVL_INFO, "A message of %zu bytes was decoded successfully.", packet_len);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RX_EVT_HEADER_ERROR:
|
case RX_EVT_HEADER_ERROR:
|
||||||
|
@ -127,19 +139,24 @@ int main(void)
|
||||||
|
|
||||||
RESULT_CHECK(layer1_tx_reset(&tx));
|
RESULT_CHECK(layer1_tx_reset(&tx));
|
||||||
|
|
||||||
uint8_t packetbuf1[] = "Hello World! 1234567890";
|
uint8_t packetbuf1[64] = "Hello World! 1234567890";
|
||||||
size_t l = sizeof(packetbuf1);
|
size_t crc_size = crc_sizeof_key(PAYLOAD_CRC_SCHEME);
|
||||||
|
size_t l = strlen((char*)packetbuf1);
|
||||||
|
|
||||||
LOG(LVL_INFO, "Transmitting packet with %zd bytes.", l);
|
crc_append_key(PAYLOAD_CRC_SCHEME, packetbuf1, l);
|
||||||
|
|
||||||
RESULT_CHECK(layer1_tx_add_packet_to_burst(&tx, packetbuf1, l));
|
LOG(LVL_INFO, "Transmitting packet with %zd bytes.", l + crc_size);
|
||||||
|
|
||||||
uint8_t packetbuf2[] = "This is just a test message. Just writing some stuff here to create a longer packet.";
|
RESULT_CHECK(layer1_tx_add_packet_to_burst(&tx, packetbuf1, l + crc_size));
|
||||||
l = sizeof(packetbuf2);
|
|
||||||
|
|
||||||
LOG(LVL_INFO, "Transmitting packet with %zd bytes.", l);
|
uint8_t packetbuf2[128] = "This is just a test message. Just writing some stuff here to create a longer packet.";
|
||||||
|
l = strlen((char*)packetbuf2);
|
||||||
|
|
||||||
RESULT_CHECK(layer1_tx_add_packet_to_burst(&tx, packetbuf2, l));
|
crc_append_key(PAYLOAD_CRC_SCHEME, packetbuf2, l);
|
||||||
|
|
||||||
|
LOG(LVL_INFO, "Transmitting packet with %zd bytes.", l + crc_size);
|
||||||
|
|
||||||
|
RESULT_CHECK(layer1_tx_add_packet_to_burst(&tx, packetbuf2, l + crc_size));
|
||||||
|
|
||||||
RESULT_CHECK(layer1_tx_finalize_burst(&tx));
|
RESULT_CHECK(layer1_tx_finalize_burst(&tx));
|
||||||
|
|
||||||
|
@ -150,7 +167,7 @@ int main(void)
|
||||||
|
|
||||||
// ** Simulate channel effects **
|
// ** Simulate channel effects **
|
||||||
channel_cccf ch = channel_cccf_create();
|
channel_cccf ch = channel_cccf_create();
|
||||||
channel_cccf_add_awgn(ch, -30, 10);
|
channel_cccf_add_awgn(ch, -30, 30);
|
||||||
//channel_cccf_add_carrier_offset(ch, 0.05f, 1.23f);
|
//channel_cccf_add_carrier_offset(ch, 0.05f, 1.23f);
|
||||||
|
|
||||||
float complex whole_burst_ch[burst_len];
|
float complex whole_burst_ch[burst_len];
|
||||||
|
|
|
@ -64,9 +64,11 @@ void cb_rx(rx_evt_t evt, const layer1_rx_t *rx, uint8_t *packet_data, size_t pac
|
||||||
(void)packet_len;
|
(void)packet_len;
|
||||||
(void)rx;
|
(void)rx;
|
||||||
|
|
||||||
|
unsigned int data_size;
|
||||||
|
|
||||||
switch(evt)
|
switch(evt)
|
||||||
{
|
{
|
||||||
case RX_EVT_CHECKSUM_ERROR:
|
case RX_EVT_DECODE_FAILED:
|
||||||
//LOG(LVL_WARN, "Received a message of %zu bytes, but decoding failed.", packet_len);
|
//LOG(LVL_WARN, "Received a message of %zu bytes, but decoding failed.", packet_len);
|
||||||
//LOG(LVL_INFO, "=== FAILED PAYLOAD ===");
|
//LOG(LVL_INFO, "=== FAILED PAYLOAD ===");
|
||||||
//hexdump(packet_data, packet_len);
|
//hexdump(packet_data, packet_len);
|
||||||
|
@ -84,6 +86,14 @@ void cb_rx(rx_evt_t evt, const layer1_rx_t *rx, uint8_t *packet_data, size_t pac
|
||||||
//hexdump(packet_data, packet_len < 64 ? packet_len : 64);
|
//hexdump(packet_data, packet_len < 64 ? packet_len : 64);
|
||||||
//LOG(LVL_INFO, "====================================");
|
//LOG(LVL_INFO, "====================================");
|
||||||
|
|
||||||
|
data_size = packet_len - crc_sizeof_key(PAYLOAD_CRC_SCHEME);
|
||||||
|
|
||||||
|
// FIXME: move to layer 2
|
||||||
|
if(!crc_check_key(PAYLOAD_CRC_SCHEME, packet_data, data_size)) {
|
||||||
|
LOG(LVL_WARN, "payload CRC check failed!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
m_rx_stats.successful_decodes++;
|
m_rx_stats.successful_decodes++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue