Integrate the interleaver
This commit is contained in:
parent
325abdbd02
commit
017eb221f1
|
@ -39,6 +39,8 @@ set(sources
|
||||||
src/layer1/whitening.h
|
src/layer1/whitening.h
|
||||||
src/layer1/modcod.c
|
src/layer1/modcod.c
|
||||||
src/layer1/modcod.h
|
src/layer1/modcod.h
|
||||||
|
src/layer1/interleaver.c
|
||||||
|
src/layer1/interleaver.h
|
||||||
src/layer2/tundev.c
|
src/layer2/tundev.c
|
||||||
src/layer2/tundev.h
|
src/layer2/tundev.h
|
||||||
src/layer2/packet_queue.c
|
src/layer2/packet_queue.c
|
||||||
|
|
|
@ -1,12 +1,24 @@
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include "interleaver.h"
|
#include "interleaver.h"
|
||||||
|
|
||||||
#define INTERLEAVE_DISTANCE 16
|
#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_base = 0;
|
||||||
size_t interleaved_index = 0;
|
size_t interleaved_index = 0;
|
||||||
|
|
||||||
|
size_t interleave_distance = calculate_distance(n);
|
||||||
|
|
||||||
/* example for this algorithm with INTERLEAVE_DISTANCE = 5:
|
/* example for this algorithm with INTERLEAVE_DISTANCE = 5:
|
||||||
* original: abcdefghijklmn
|
* original: abcdefghijklmn
|
||||||
* output: adgjmbehkncfil
|
* 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++) {
|
for(size_t orig_index = 0; orig_index < n; orig_index++) {
|
||||||
out[interleaved_index] = in[orig_index];
|
out[interleaved_index] = in[orig_index];
|
||||||
|
|
||||||
interleaved_index += INTERLEAVE_DISTANCE;
|
interleaved_index += interleave_distance;
|
||||||
if(interleaved_index >= n) {
|
if(interleaved_index >= n) {
|
||||||
interleaved_base++;
|
interleaved_base++;
|
||||||
interleaved_index = 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_base = 0;
|
||||||
size_t interleaved_index = 0;
|
size_t interleaved_index = 0;
|
||||||
|
|
||||||
|
size_t interleave_distance = calculate_distance(n);
|
||||||
|
|
||||||
for(size_t orig_index = 0; orig_index < n; orig_index++) {
|
for(size_t orig_index = 0; orig_index < n; orig_index++) {
|
||||||
out[orig_index] = in[interleaved_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) {
|
if(interleaved_index >= n) {
|
||||||
interleaved_base++;
|
interleaved_base++;
|
||||||
interleaved_index = interleaved_base;
|
interleaved_index = interleaved_base;
|
||||||
|
|
|
@ -3,9 +3,12 @@
|
||||||
|
|
||||||
#include <complex.h>
|
#include <complex.h>
|
||||||
#include <stddef.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
|
#endif // INTERLEAVER_H
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "whitening.h"
|
#include "whitening.h"
|
||||||
|
#include "interleaver.h"
|
||||||
#include "preamble.h"
|
#include "preamble.h"
|
||||||
#include "config.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 int nsyms = (ctx->length * 8 + bps/2) / bps;
|
||||||
|
|
||||||
unsigned char msg_sym_idcs[nsyms];
|
unsigned char msg_sym_idcs[nsyms];
|
||||||
|
unsigned char msg_sym_idcs_interleaved[nsyms];
|
||||||
|
|
||||||
float complex *msg_mod = malloc(sizeof(float complex) * nsyms);
|
float complex *msg_mod = malloc(sizeof(float complex) * nsyms);
|
||||||
if(!msg_mod) {
|
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));
|
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++) {
|
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);
|
modem_destroy(payload_modem);
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "preamble.h"
|
#include "preamble.h"
|
||||||
#include "freq_est.h"
|
#include "freq_est.h"
|
||||||
#include "whitening.h"
|
#include "whitening.h"
|
||||||
|
#include "interleaver.h"
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "options.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_rssi = agc_crcf_get_rssi(rx->agc);
|
||||||
rx->packet_debug_info.data_evm = -1e38f; // FIXME
|
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(
|
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));
|
payload_enc, 8, sizeof(payload_enc), &nsyms));
|
||||||
|
|
||||||
fec payload_fec = modcod_create_fec(rx->modcod);
|
fec payload_fec = modcod_create_fec(rx->modcod);
|
||||||
|
|
|
@ -38,6 +38,8 @@ add_executable(
|
||||||
../src/layer1/whitening.h
|
../src/layer1/whitening.h
|
||||||
../src/layer1/modcod.c
|
../src/layer1/modcod.c
|
||||||
../src/layer1/modcod.h
|
../src/layer1/modcod.h
|
||||||
|
../src/layer1/interleaver.c
|
||||||
|
../src/layer1/interleaver.h
|
||||||
../src/utils.c
|
../src/utils.c
|
||||||
../src/utils.h
|
../src/utils.h
|
||||||
../src/var_array.c
|
../src/var_array.c
|
||||||
|
@ -89,6 +91,8 @@ add_executable(
|
||||||
../src/layer1/whitening.h
|
../src/layer1/whitening.h
|
||||||
../src/layer1/modcod.c
|
../src/layer1/modcod.c
|
||||||
../src/layer1/modcod.h
|
../src/layer1/modcod.h
|
||||||
|
../src/layer1/interleaver.c
|
||||||
|
../src/layer1/interleaver.h
|
||||||
../src/layer1/preamble.c
|
../src/layer1/preamble.c
|
||||||
../src/layer1/preamble.h
|
../src/layer1/preamble.h
|
||||||
../src/utils.c
|
../src/utils.c
|
||||||
|
@ -128,6 +132,8 @@ add_executable(
|
||||||
../src/layer1/whitening.h
|
../src/layer1/whitening.h
|
||||||
../src/layer1/modcod.c
|
../src/layer1/modcod.c
|
||||||
../src/layer1/modcod.h
|
../src/layer1/modcod.h
|
||||||
|
../src/layer1/interleaver.c
|
||||||
|
../src/layer1/interleaver.h
|
||||||
../src/layer1/preamble.c
|
../src/layer1/preamble.c
|
||||||
../src/layer1/preamble.h
|
../src/layer1/preamble.h
|
||||||
../src/utils.c
|
../src/utils.c
|
||||||
|
@ -214,4 +220,5 @@ add_executable(
|
||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
test_interleaver
|
test_interleaver
|
||||||
|
m
|
||||||
)
|
)
|
||||||
|
|
|
@ -16,8 +16,8 @@ int main(void)
|
||||||
orig[i] = (float complex)i;
|
orig[i] = (float complex)i;
|
||||||
}
|
}
|
||||||
|
|
||||||
interleaver_interleave(orig, interleaved, N);
|
interleaver_interleave_cf(orig, interleaved, N);
|
||||||
interleaver_deinterleave(interleaved, deinterleaved, N);
|
interleaver_deinterleave_cf(interleaved, deinterleaved, N);
|
||||||
|
|
||||||
for(size_t i = 0; i < N; i++) {
|
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]));
|
printf("%5zu %5.1f %5.1f %5.1f\n", i, crealf(orig[i]), crealf(interleaved[i]), crealf(deinterleaved[i]));
|
||||||
|
|
Loading…
Reference in a new issue