Integrate the interleaver

This commit is contained in:
Thomas Kolb 2024-08-14 19:13:41 +02:00
parent 325abdbd02
commit 9b7bae5bd8
6 changed files with 77 additions and 8 deletions

View file

@ -1,12 +1,24 @@
#include <math.h>
#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;

View file

@ -3,9 +3,12 @@
#include <complex.h>
#include <stddef.h>
#include <stdint.h>
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

View file

@ -2,6 +2,7 @@
#include <string.h>
#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,6 +144,9 @@ 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]));
}

View file

@ -12,6 +12,7 @@
#include "preamble.h"
#include "freq_est.h"
#include "whitening.h"
#include "interleaver.h"
#include "config.h"
#include "options.h"
@ -465,6 +466,10 @@ 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,
payload_enc, 8, sizeof(payload_enc), &nsyms));

View file

@ -214,4 +214,5 @@ add_executable(
target_link_libraries(
test_interleaver
m
)

View file

@ -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]));