diff --git a/impl/src/layer1/interleaver.c b/impl/src/layer1/interleaver.c index c639ccb..278f3c4 100644 --- a/impl/src/layer1/interleaver.c +++ b/impl/src/layer1/interleaver.c @@ -1,12 +1,24 @@ +#include + #include "interleaver.h" #define INTERLEAVE_DISTANCE 16 -void interleaver_interleave(const float complex *in, float complex *out, size_t n) +static size_t calculate_distance(size_t n) +{ + // note: benchmarking shows that this is faster than a integer-specific + // Newton-Raphson implementation on systems with an FPU. On amd64, sqrtf + // was faster by a factor of 6. + return ceilf(sqrtf(n)); +} + +void interleaver_interleave_cf(const float complex *in, float complex *out, size_t n) { size_t interleaved_base = 0; size_t interleaved_index = 0; + size_t interleave_distance = calculate_distance(n); + /* example for this algorithm with INTERLEAVE_DISTANCE = 5: * original: abcdefghijklmn * output: adgjmbehkncfil @@ -14,7 +26,7 @@ void interleaver_interleave(const float complex *in, float complex *out, size_t for(size_t orig_index = 0; orig_index < n; orig_index++) { out[interleaved_index] = in[orig_index]; - interleaved_index += INTERLEAVE_DISTANCE; + interleaved_index += interleave_distance; if(interleaved_index >= n) { interleaved_base++; interleaved_index = interleaved_base; @@ -22,15 +34,58 @@ void interleaver_interleave(const float complex *in, float complex *out, size_t } } -void interleaver_deinterleave(const float complex *in, float complex *out, size_t n) +void interleaver_deinterleave_cf(const float complex *in, float complex *out, size_t n) { size_t interleaved_base = 0; size_t interleaved_index = 0; + size_t interleave_distance = calculate_distance(n); + for(size_t orig_index = 0; orig_index < n; orig_index++) { out[orig_index] = in[interleaved_index]; - interleaved_index += INTERLEAVE_DISTANCE; + interleaved_index += interleave_distance; + if(interleaved_index >= n) { + interleaved_base++; + interleaved_index = interleaved_base; + } + } +} + + +void interleaver_interleave_u8(const uint8_t *in, uint8_t *out, size_t n) +{ + size_t interleaved_base = 0; + size_t interleaved_index = 0; + + size_t interleave_distance = calculate_distance(n); + + /* example for this algorithm with INTERLEAVE_DISTANCE = 5: + * original: abcdefghijklmn + * output: adgjmbehkncfil + */ + for(size_t orig_index = 0; orig_index < n; orig_index++) { + out[interleaved_index] = in[orig_index]; + + interleaved_index += interleave_distance; + if(interleaved_index >= n) { + interleaved_base++; + interleaved_index = interleaved_base; + } + } +} + +void interleaver_deinterleave_u8(const uint8_t *in, uint8_t *out, size_t n) +{ + size_t interleaved_base = 0; + size_t interleaved_index = 0; + + size_t interleave_distance = calculate_distance(n); + + for(size_t orig_index = 0; orig_index < n; orig_index++) { + out[orig_index] = in[interleaved_index]; + + interleaved_index += interleave_distance; if(interleaved_index >= n) { interleaved_base++; interleaved_index = interleaved_base; diff --git a/impl/src/layer1/interleaver.h b/impl/src/layer1/interleaver.h index 5bdfa71..861ac16 100644 --- a/impl/src/layer1/interleaver.h +++ b/impl/src/layer1/interleaver.h @@ -3,9 +3,12 @@ #include #include +#include -void interleaver_interleave(const float complex *in, float complex *out, size_t n); +void interleaver_interleave_cf(const float complex *in, float complex *out, size_t n); +void interleaver_deinterleave_cf(const float complex *in, float complex *out, size_t n); -void interleaver_deinterleave(const float complex *in, float complex *out, size_t n); +void interleaver_interleave_u8(const uint8_t *in, uint8_t *out, size_t n); +void interleaver_deinterleave_u8(const uint8_t *in, uint8_t *out, size_t n); #endif // INTERLEAVER_H diff --git a/impl/src/layer1/packet_mod.c b/impl/src/layer1/packet_mod.c index c916d26..5851261 100644 --- a/impl/src/layer1/packet_mod.c +++ b/impl/src/layer1/packet_mod.c @@ -2,6 +2,7 @@ #include #include "whitening.h" +#include "interleaver.h" #include "preamble.h" #include "config.h" @@ -133,6 +134,7 @@ result_t packet_mod_modulate(packet_mod_ctx_t *ctx) unsigned int nsyms = (ctx->length * 8 + bps/2) / bps; unsigned char msg_sym_idcs[nsyms]; + unsigned char msg_sym_idcs_interleaved[nsyms]; float complex *msg_mod = malloc(sizeof(float complex) * nsyms); if(!msg_mod) { @@ -142,8 +144,11 @@ result_t packet_mod_modulate(packet_mod_ctx_t *ctx) ERR_CHECK_LIQUID(liquid_repack_bytes(ctx->pkt_bytes, 8, ctx->length, msg_sym_idcs, bps, nsyms, &nsyms)); + // interleave the message symbols + interleaver_interleave_u8(msg_sym_idcs, msg_sym_idcs_interleaved, nsyms); + for(size_t i = 0; i < nsyms; i++) { - ERR_CHECK_LIQUID(modem_modulate(payload_modem, msg_sym_idcs[i], &msg_mod[i])); + ERR_CHECK_LIQUID(modem_modulate(payload_modem, msg_sym_idcs_interleaved[i], &msg_mod[i])); } modem_destroy(payload_modem); diff --git a/impl/src/layer1/rx.c b/impl/src/layer1/rx.c index 7b1db0e..011a29f 100644 --- a/impl/src/layer1/rx.c +++ b/impl/src/layer1/rx.c @@ -12,6 +12,7 @@ #include "preamble.h" #include "freq_est.h" #include "whitening.h" +#include "interleaver.h" #include "config.h" #include "options.h" @@ -465,8 +466,12 @@ result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t rx->packet_debug_info.data_rssi = agc_crcf_get_rssi(rx->agc); rx->packet_debug_info.data_evm = -1e38f; // FIXME + // deinterleave the message symbols + uint8_t symbols_int_deinterleaved[rx->payload_len_symbols]; + interleaver_deinterleave_u8(symbols_int, symbols_int_deinterleaved, rx->payload_len_symbols); + ERR_CHECK_LIQUID(liquid_repack_bytes( - symbols_int, modem_get_bps(rx->payload_demod), rx->payload_len_symbols, + symbols_int_deinterleaved, modem_get_bps(rx->payload_demod), rx->payload_len_symbols, payload_enc, 8, sizeof(payload_enc), &nsyms)); fec payload_fec = modcod_create_fec(rx->modcod); diff --git a/impl/test/CMakeLists.txt b/impl/test/CMakeLists.txt index 9ac3f9e..f47beaa 100644 --- a/impl/test/CMakeLists.txt +++ b/impl/test/CMakeLists.txt @@ -214,4 +214,5 @@ add_executable( target_link_libraries( test_interleaver + m ) diff --git a/impl/test/test_interleaver.c b/impl/test/test_interleaver.c index 2f702a7..27c9966 100644 --- a/impl/test/test_interleaver.c +++ b/impl/test/test_interleaver.c @@ -16,8 +16,8 @@ int main(void) orig[i] = (float complex)i; } - interleaver_interleave(orig, interleaved, N); - interleaver_deinterleave(interleaved, deinterleaved, N); + interleaver_interleave_cf(orig, interleaved, N); + interleaver_deinterleave_cf(interleaved, deinterleaved, N); for(size_t i = 0; i < N; i++) { printf("%5zu %5.1f %5.1f %5.1f\n", i, crealf(orig[i]), crealf(interleaved[i]), crealf(deinterleaved[i]));