Implement CRC check and phase tracking

This commit is contained in:
Thomas Kolb 2022-02-12 21:58:53 +01:00
parent 947615f5cd
commit 87b844a2da
3 changed files with 37 additions and 13 deletions

View file

@ -3,12 +3,14 @@
#include <liquid/liquid.h> #include <liquid/liquid.h>
#define CHANNEL_CODE LIQUID_FEC_CONV_V27P34 #define PAYLOAD_CHANNEL_CODE LIQUID_FEC_CONV_V27P34
#define MODULATION LIQUID_MODEM_QAM16 #define PAYLOAD_MODULATION LIQUID_MODEM_QAM16
#define HEADER_CHANNEL_CODE LIQUID_FEC_NONE #define HEADER_CHANNEL_CODE LIQUID_FEC_NONE
#define HEADER_MODULATION LIQUID_MODEM_QPSK #define HEADER_MODULATION LIQUID_MODEM_QPSK
#define PAYLOAD_CRC_SCHEME LIQUID_CRC_16
#define PREAMBLE_MSEQ_M 6 #define PREAMBLE_MSEQ_M 6
#define PREAMBLE_MSEQ_POLY LIQUID_MSEQUENCE_GENPOLY_M6 #define PREAMBLE_MSEQ_POLY LIQUID_MSEQUENCE_GENPOLY_M6
#define PREAMBLE_MSEQ_INIT 0x00000001 #define PREAMBLE_MSEQ_INIT 0x00000001

View file

@ -30,6 +30,16 @@ void print_complex_array(const char *varname, float complex const *array, size_t
} }
void update_nco_pll(nco_crcf nco, float phase_error)
{
static const float pll_alpha = 0.05f; // phase adjustment factor
static const float pll_beta = (pll_alpha * pll_alpha) / 2.0f; // frequency adjustment factor
nco_crcf_adjust_phase(nco, pll_alpha * phase_error);
nco_crcf_adjust_frequency(nco, pll_beta * phase_error);
}
int main(void) int main(void)
{ {
uint8_t msg_org[] = "Hello Liquid! This is the message to transmit. Hopefully it can be decoded correctly..."; uint8_t msg_org[] = "Hello Liquid! This is the message to transmit. Hopefully it can be decoded correctly...";
@ -37,14 +47,14 @@ int main(void)
uint8_t header[4]; uint8_t header[4];
fec hdr_fec = fec_create(HEADER_CHANNEL_CODE, NULL); fec hdr_fec = fec_create(HEADER_CHANNEL_CODE, NULL);
fec payload_fec = fec_create(CHANNEL_CODE, NULL); fec payload_fec = fec_create(PAYLOAD_CHANNEL_CODE, NULL);
modem hdr_demod = modem_create(HEADER_MODULATION); modem hdr_demod = modem_create(HEADER_MODULATION);
modem payload_demod = modem_create(MODULATION); modem payload_demod = modem_create(PAYLOAD_MODULATION);
channel_cccf channel = channel_cccf_create(); channel_cccf channel = channel_cccf_create();
float snr = 12.0f; float snr = 7.0f;
channel_cccf_add_awgn(channel, -snr, snr); channel_cccf_add_awgn(channel, -snr, snr);
channel_cccf_add_carrier_offset(channel, 0.20f, 1.00f); channel_cccf_add_carrier_offset(channel, 0.20f, 1.00f);
@ -210,7 +220,11 @@ int main(void)
if(symbol_counter < hdr_len_symbols) { if(symbol_counter < hdr_len_symbols) {
unsigned int sym_demod; unsigned int sym_demod;
modem_demodulate(hdr_demod, mixed_sample, &sym_demod); modem_demodulate(hdr_demod, mixed_sample, &sym_demod);
printf("Sym: %d; Phase error: %f\n", sym_demod, modem_get_demodulator_phase_error(hdr_demod));
float phase_error = modem_get_demodulator_phase_error(hdr_demod);
printf("Sym: %d; Phase error: %f\n", sym_demod, phase_error);
update_nco_pll(carrier_fine_nco, phase_error);
symbols_cpx[symbol_counter] = mixed_sample; symbols_cpx[symbol_counter] = mixed_sample;
symbols_int[symbol_counter] = sym_demod; symbols_int[symbol_counter] = sym_demod;
@ -230,7 +244,7 @@ int main(void)
payload_len_bytes = ((uint16_t)header[0] << 8) | header[1]; payload_len_bytes = ((uint16_t)header[0] << 8) | header[1];
payload_crc = ((uint16_t)header[2] << 8) | header[3]; payload_crc = ((uint16_t)header[2] << 8) | header[3];
payload_len_enc_bytes = fec_get_enc_msg_length(CHANNEL_CODE, payload_len_bytes); payload_len_enc_bytes = fec_get_enc_msg_length(PAYLOAD_CHANNEL_CODE, payload_len_bytes);
payload_len_symbols = (payload_len_enc_bytes * 8 + payload_bps - 1) / payload_bps; payload_len_symbols = (payload_len_enc_bytes * 8 + payload_bps - 1) / payload_bps;
printf("=== DECODED HEADER ===\n"); printf("=== DECODED HEADER ===\n");
@ -250,7 +264,11 @@ int main(void)
if(symbol_counter < payload_len_symbols) { if(symbol_counter < payload_len_symbols) {
unsigned int sym_demod; unsigned int sym_demod;
modem_demodulate(payload_demod, mixed_sample, &sym_demod); modem_demodulate(payload_demod, mixed_sample, &sym_demod);
printf("Sym: %d; Phase error: %f\n", sym_demod, modem_get_demodulator_phase_error(payload_demod));
float phase_error = modem_get_demodulator_phase_error(payload_demod);
printf("Sym: %d; Phase error: %f\n", sym_demod, phase_error);
update_nco_pll(carrier_fine_nco, phase_error);
symbols_cpx[symbol_counter] = mixed_sample; symbols_cpx[symbol_counter] = mixed_sample;
symbols_int[symbol_counter] = sym_demod; symbols_int[symbol_counter] = sym_demod;
@ -268,11 +286,13 @@ int main(void)
fec_decode(payload_fec, payload_len_bytes, payload_enc, payload); fec_decode(payload_fec, payload_len_bytes, payload_enc, payload);
int valid = crc_validate_message(PAYLOAD_CRC_SCHEME, payload, payload_len_bytes, payload_crc);
payload[payload_len_bytes] = '\0'; payload[payload_len_bytes] = '\0';
printf("=== DECODED PAYLOAD ===\n"); printf("=== DECODED PAYLOAD (valid: %d) ===\n", valid);
printf("%s\n", payload); printf("%s\n", payload);
printf("=======================\n"); printf("==================================\n");
dump_array_cf(symbols_cpx, symbol_counter, 1.0f, "/tmp/payload.cpx"); dump_array_cf(symbols_cpx, symbol_counter, 1.0f, "/tmp/payload.cpx");
rx_state = RX_STATE_ACQUISITION; rx_state = RX_STATE_ACQUISITION;

View file

@ -1,3 +1,4 @@
#include <liquid/liquid.h>
#include <string.h> #include <string.h>
#include "preamble.h" #include "preamble.h"
@ -12,8 +13,8 @@ result_t packet_mod_init(packet_mod_ctx_t *ctx)
ctx->length = 0; ctx->length = 0;
ctx->fec = fec_create(CHANNEL_CODE, NULL); ctx->fec = fec_create(PAYLOAD_CHANNEL_CODE, NULL);
ctx->modem = modem_create(MODULATION); ctx->modem = modem_create(PAYLOAD_MODULATION);
ctx->hdr_fec = fec_create(HEADER_CHANNEL_CODE, NULL); ctx->hdr_fec = fec_create(HEADER_CHANNEL_CODE, NULL);
ctx->hdr_modem = modem_create(HEADER_MODULATION); ctx->hdr_modem = modem_create(HEADER_MODULATION);
@ -72,6 +73,7 @@ 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, data, length);
ctx->raw_data_len = length; ctx->raw_data_len = length;
ctx->state = DATA_RAW; ctx->state = DATA_RAW;
@ -86,7 +88,7 @@ result_t packet_mod_encode(packet_mod_ctx_t *ctx)
return ERR_INVALID_STATE; return ERR_INVALID_STATE;
} }
unsigned int enc_length = fec_get_enc_msg_length(CHANNEL_CODE, ctx->length); unsigned int enc_length = fec_get_enc_msg_length(PAYLOAD_CHANNEL_CODE, ctx->length);
unsigned char *enc_msg = malloc(enc_length); unsigned char *enc_msg = malloc(enc_length);
if(!enc_msg) { if(!enc_msg) {