#include #include #include #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; }