hamnet70/impl/src/correlator.c

114 lines
2.6 KiB
C

#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include "correlator.h"
bool correlator_init(correlator_ctx_t *ctx, const float complex *search_seq, size_t nsymbols)
{
// copy arguments and initialize variables
ctx->search_sequence_len = nsymbols;
ctx->input_history = NULL;
ctx->search_sequence = NULL;
ctx->history_ptr = 0;
// Determine the smallest power of two greater than nsymbols
ctx->buffer_size = 1;
while(nsymbols > 0) {
ctx->buffer_size <<= 1;
nsymbols >>= 1;
}
// If buffer_size = 0b1000, then buffer_size_mask=0b0111
ctx->buffer_size_mask = ctx->buffer_size - 1;
// Allocate the buffers
ctx->input_history = malloc(ctx->buffer_size * sizeof(ctx->input_history[0]));
if(!ctx->input_history) {
fprintf(stderr, "correlator: malloc() failed!\n");
goto fail;
}
ctx->search_sequence = malloc(ctx->buffer_size * sizeof(ctx->search_sequence[0]));
if(!ctx->search_sequence) {
fprintf(stderr, "correlator: malloc() failed!\n");
goto fail;
}
// Clear the history buffer
memset(ctx->input_history, 0, ctx->buffer_size * sizeof(ctx->input_history[0]));
// Prepare the search sequence.
// The complex values are conjugated in the process.
for(size_t i = 0; i < ctx->search_sequence_len; i++) {
ctx->search_sequence[i] = conjf(search_seq[i]);
}
// Success!
return true;
fail:
correlator_free(ctx);
return false;
}
void correlator_free(correlator_ctx_t *ctx)
{
if(ctx->input_history) {
free(ctx->input_history);
ctx->input_history = NULL;
}
if(ctx->search_sequence) {
free(ctx->search_sequence);
ctx->input_history = NULL;
}
ctx->buffer_size = 0;
ctx->search_sequence_len = 0;
}
float complex correlator_step(correlator_ctx_t *ctx, float complex sample)
{
float complex result = 0;
// increment and wrap the history pointer
ctx->history_ptr++;
ctx->history_ptr &= ctx->buffer_size_mask;
// copy the input sample to the history
ctx->input_history[ctx->history_ptr] = sample;
size_t n = (ctx->history_ptr - ctx->search_sequence_len + 1) & ctx->buffer_size_mask;
// calculate the correlation
for(size_t m = 0; m < ctx->search_sequence_len; m++) {
size_t nm = (n + m) & ctx->buffer_size_mask;
result += ctx->search_sequence[m] * ctx->input_history[nm];
}
return result;
}
void correlator_get_input_history(correlator_ctx_t *ctx, float complex *history)
{
size_t n = (ctx->history_ptr - ctx->search_sequence_len + 1) & ctx->buffer_size_mask;
for(size_t m = 0; m < ctx->search_sequence_len; m++) {
size_t nm = (n + m) & ctx->buffer_size_mask;
history[m] = ctx->input_history[nm];
}
}
const float complex* correlator_get_conj_search_sequence(correlator_ctx_t *ctx)
{
return ctx->search_sequence;
}