diff --git a/impl/CMakeLists.txt b/impl/CMakeLists.txt index ae88c11..afe2c84 100644 --- a/impl/CMakeLists.txt +++ b/impl/CMakeLists.txt @@ -29,6 +29,8 @@ set(sources src/layer1/rx.h src/layer1/whitening.c src/layer1/whitening.h + src/layer1/modcod.c + src/layer1/modcod.h ) include_directories( diff --git a/impl/src/layer1/modcod.c b/impl/src/layer1/modcod.c new file mode 100644 index 0000000..b381349 --- /dev/null +++ b/impl/src/layer1/modcod.c @@ -0,0 +1,34 @@ +#include + +#include "modcod.h" + +modem modcod_create_modem(modcod_t modcod) +{ + static const modulation_scheme mod_mapping[MODCOD_LIST_SIZE] = { + LIQUID_MODEM_QAM16, + LIQUID_MODEM_QPSK, + }; + + if(modcod < MODCOD_LIST_SIZE) { + return modem_create(mod_mapping[modcod]); + } else { + return NULL; + } +} + + +fec modcod_create_fec(modcod_t modcod) +{ + static const fec_scheme fec_mapping[MODCOD_LIST_SIZE] = { + LIQUID_FEC_CONV_V27P34, + LIQUID_FEC_CONV_V27P34, + }; + + if(modcod < MODCOD_LIST_SIZE) { + return fec_create(fec_mapping[modcod], NULL); + } else { + return NULL; + } +} + + diff --git a/impl/src/layer1/modcod.h b/impl/src/layer1/modcod.h new file mode 100644 index 0000000..48445c6 --- /dev/null +++ b/impl/src/layer1/modcod.h @@ -0,0 +1,23 @@ +#ifndef LAYER1_MODCOD_H +#define LAYER1_MODCOD_H + +#include + +// up to 32 ModCods are supported. Do not reuse indices, as that will break +// backwards compatibility! Only append new ModCods at the end of the list! +typedef enum +{ + MODCOD_16QAM_CONV_V27P34, + MODCOD_QPSK_CONV_V27P34, + + MODCOD_LIST_SIZE +} modcod_t; + +#define MODCOD_DEFAULT MODCOD_16QAM_CONV_V27P34 + +modem modcod_create_modem(modcod_t modcod); +fec modcod_create_fec(modcod_t modcod); + +#define MODCOD_IS_VALID(modcod) ((modcod) < MODCOD_LIST_SIZE) + +#endif // LAYER1_MODCOD_H diff --git a/impl/src/layer1/packet_mod.c b/impl/src/layer1/packet_mod.c index fcce2c4..e522304 100644 --- a/impl/src/layer1/packet_mod.c +++ b/impl/src/layer1/packet_mod.c @@ -14,12 +14,11 @@ result_t packet_mod_init(packet_mod_ctx_t *ctx) ctx->length = 0; - ctx->fec = fec_create(PAYLOAD_CHANNEL_CODE, NULL); - ctx->modem = modem_create(PAYLOAD_MODULATION); - ctx->hdr_fec = fec_create(HEADER_CHANNEL_CODE, NULL); ctx->hdr_modem = modem_create(HEADER_MODULATION); + ctx->modcod = MODCOD_DEFAULT; + ctx->state = NOT_STARTED; return OK; @@ -50,9 +49,6 @@ result_t packet_mod_free(packet_mod_ctx_t *ctx) ctx->state = NOT_STARTED; ctx->length = 0; - fec_destroy(ctx->fec); - modem_destroy(ctx->modem); - fec_destroy(ctx->hdr_fec); modem_destroy(ctx->hdr_modem); @@ -60,6 +56,18 @@ result_t packet_mod_free(packet_mod_ctx_t *ctx) } +result_t packet_mod_set_modcod(packet_mod_ctx_t *ctx, modcod_t modcod) +{ + if(ctx->state != NOT_STARTED) { + return ERR_INVALID_STATE; + } + + ctx->modcod = modcod; + + return OK; +} + + result_t packet_mod_set_data(packet_mod_ctx_t *ctx, const unsigned char *data, size_t length) { if(ctx->state != NOT_STARTED) { @@ -100,7 +108,9 @@ result_t packet_mod_encode(packet_mod_ctx_t *ctx) whitening_apply_in_place(ctx->pkt_bytes, ctx->length); // apply the FEC - ERR_CHECK_LIQUID(fec_encode(ctx->fec, ctx->length, ctx->pkt_bytes, enc_msg)); + fec payload_fec = modcod_create_fec(ctx->modcod); + ERR_CHECK_LIQUID(fec_encode(payload_fec, ctx->length, ctx->pkt_bytes, enc_msg)); + fec_destroy(payload_fec); free(ctx->pkt_bytes); @@ -119,22 +129,27 @@ result_t packet_mod_modulate(packet_mod_ctx_t *ctx) return ERR_INVALID_STATE; } - unsigned int bps = modem_get_bps(ctx->modem); + modem payload_modem = modcod_create_modem(ctx->modcod); + + unsigned int bps = modem_get_bps(payload_modem); unsigned int nsyms = (ctx->length * 8 + bps/2) / bps; unsigned char msg_sym_idcs[nsyms]; float complex *msg_mod = malloc(sizeof(float complex) * nsyms); if(!msg_mod) { + modem_destroy(payload_modem); return ERR_NO_MEM; } ERR_CHECK_LIQUID(liquid_repack_bytes(ctx->pkt_bytes, 8, ctx->length, msg_sym_idcs, bps, nsyms, &nsyms)); for(size_t i = 0; i < nsyms; i++) { - ERR_CHECK_LIQUID(modem_modulate(ctx->modem, msg_sym_idcs[i], &msg_mod[i])); + ERR_CHECK_LIQUID(modem_modulate(payload_modem, msg_sym_idcs[i], &msg_mod[i])); } + modem_destroy(payload_modem); + free(ctx->pkt_bytes); ctx->pkt_bytes = NULL; @@ -162,7 +177,8 @@ result_t packet_mod_add_header(packet_mod_ctx_t *ctx) uint8_t header[4]; // set length - header[0] = (ctx->raw_data_len >> 8) & 0xFF; + header[0] = (ctx->raw_data_len >> 8) & 0x07; + header[0] |= ctx->modcod << 3; header[1] = (ctx->raw_data_len >> 0) & 0xFF; // set raw data CRC header[2] = (ctx->raw_data_crc >> 8) & 0xFF; diff --git a/impl/src/layer1/packet_mod.h b/impl/src/layer1/packet_mod.h index 3d375d7..16555a9 100644 --- a/impl/src/layer1/packet_mod.h +++ b/impl/src/layer1/packet_mod.h @@ -6,6 +6,8 @@ #include +#include "modcod.h" + #include "results.h" typedef enum @@ -25,15 +27,14 @@ typedef struct packet_mod_state_t state; - modem modem; - fec fec; - modem hdr_modem; fec hdr_fec; uint16_t raw_data_crc; uint16_t raw_data_len; + uint8_t modcod; + size_t length; } packet_mod_ctx_t; @@ -52,6 +53,16 @@ result_t packet_mod_init(packet_mod_ctx_t *ctx); */ result_t packet_mod_free(packet_mod_ctx_t *ctx); +/*!\brief Set the modulation and code to use for the next packet. + * + * Must be called before setting the raw data. + * + * \param[inout] ctx The context to use for this operation. + * \param[in] modcod The modulation/code to use. + * \returns An result code (see results.h). + */ +result_t packet_mod_set_modcod(packet_mod_ctx_t *ctx, modcod_t modcod); + /*!\brief Set the raw packet data. * * In this step, the CRC of the data is calculated. diff --git a/impl/src/layer1/rx.c b/impl/src/layer1/rx.c index fc187ec..c83d425 100644 --- a/impl/src/layer1/rx.c +++ b/impl/src/layer1/rx.c @@ -12,7 +12,7 @@ #define HEADER_SIZE_BYTES 4 #define FREQ_EST_L 8 -#define SHOW_DEBUG_LOG 0 +#define SHOW_DEBUG_LOG 1 #if SHOW_DEBUG_LOG # define DEBUG_LOG(...) fprintf(stderr, __VA_ARGS__) @@ -150,10 +150,18 @@ result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t fec_decode(rx->hdr_fec, sizeof(header), header_enc, header); - uint16_t payload_bps = modem_get_bps(rx->payload_demod); - 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; + + // check the received information + if(!MODCOD_IS_VALID(rx->modcod)) { + rx->state = RX_STATE_ACQUISITION; + break; + } + + rx->payload_demod = modcod_create_modem(rx->modcod); + uint16_t payload_bps = modem_get_bps(rx->payload_demod); rx->payload_len_enc_bytes = fec_get_enc_msg_length(PAYLOAD_CHANNEL_CODE, rx->payload_len_bytes); rx->payload_len_symbols = (rx->payload_len_enc_bytes * 8 + payload_bps - 1) / payload_bps; @@ -194,7 +202,9 @@ result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t symbols_int, modem_get_bps(rx->payload_demod), rx->payload_len_symbols, payload_enc, 8, sizeof(payload_enc), &nsyms)); - fec_decode(rx->payload_fec, rx->payload_len_bytes, payload_enc, payload); + fec payload_fec = modcod_create_fec(rx->modcod); + fec_decode(payload_fec, rx->payload_len_bytes, payload_enc, payload); + fec_destroy(payload_fec); // de-whiten the data whitening_apply_in_place(payload, rx->payload_len_bytes); @@ -209,6 +219,8 @@ result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t } else { rx->callback(RX_EVT_CHECKSUM_ERROR, payload, rx->payload_len_bytes); } + + modem_destroy(rx->payload_demod); rx->state = RX_STATE_ACQUISITION; } break; @@ -237,11 +249,9 @@ result_t layer1_rx_init(layer1_rx_t *rx, rx_callback_t callback) // forward error correction objects rx->hdr_fec = fec_create(HEADER_CHANNEL_CODE, NULL); - rx->payload_fec = fec_create(PAYLOAD_CHANNEL_CODE, NULL); // demodulators rx->hdr_demod = modem_create(HEADER_MODULATION); - rx->payload_demod = modem_create(PAYLOAD_MODULATION); // symbol timing synchronizer rx->symsync = symsync_crcf_create_rnyquist(LIQUID_FIRFILT_RRC, RRC_SPS, RRC_DELAY, RRC_BETA, 32); @@ -264,10 +274,8 @@ result_t layer1_rx_shutdown(layer1_rx_t *rx) nco_crcf_destroy(rx->carrier_fine_nco); fec_destroy(rx->hdr_fec); - fec_destroy(rx->payload_fec); modem_destroy(rx->hdr_demod); - modem_destroy(rx->payload_demod); symsync_crcf_destroy(rx->symsync); diff --git a/impl/src/layer1/rx.h b/impl/src/layer1/rx.h index 877f871..2d49fca 100644 --- a/impl/src/layer1/rx.h +++ b/impl/src/layer1/rx.h @@ -3,6 +3,7 @@ #include +#include "modcod.h" #include "correlator.h" #include "results.h" @@ -32,7 +33,6 @@ typedef struct // Forward error correction objects fec hdr_fec; - fec payload_fec; // Demodulators modem hdr_demod; @@ -59,6 +59,7 @@ typedef struct uint16_t payload_len_bytes; uint16_t payload_crc; uint16_t payload_len_enc_bytes; + modcod_t modcod; } layer1_rx_t;