149 lines
4.5 KiB
C
149 lines
4.5 KiB
C
#ifndef LAYER1_CORRELATOR_H
|
|
#define LAYER1_CORRELATOR_H
|
|
|
|
/*!
|
|
* \file
|
|
*
|
|
* \brief A cross-correlator.
|
|
*
|
|
* \details
|
|
* This module implements a cross-correlator that correlates a static sequence
|
|
* (like a preamble) with a continuous stream of symbols. For example, it can
|
|
* be used to detect the start of a packet in a stream of samples.
|
|
*/
|
|
|
|
#include <stdbool.h>
|
|
#include <stdlib.h>
|
|
#include <complex.h>
|
|
|
|
/*!
|
|
* \brief Context information for the correlator.
|
|
*/
|
|
typedef struct
|
|
{
|
|
float complex *search_sequence;
|
|
float complex *input_history;
|
|
|
|
float phase_deviation;
|
|
|
|
/*!
|
|
* \brief The history pointer.
|
|
*
|
|
* \details
|
|
* Always points to the last updated sample in the input_history. On every
|
|
* written sample, the pointer is incremented and wrapped using
|
|
* buffer_size_mask. Therefore, older samples have lower indices in the
|
|
* array.
|
|
*/
|
|
size_t history_ptr;
|
|
|
|
size_t search_sequence_len;
|
|
size_t buffer_size;
|
|
size_t buffer_size_mask;
|
|
} correlator_ctx_t;
|
|
|
|
|
|
/*!
|
|
* \brief Initialize a correlator.
|
|
*
|
|
* \details
|
|
* Initializes all variables in the given context and imports the search sequence.
|
|
*
|
|
* The search sequence needs to be given such that index 0 contains the
|
|
* „oldest“ correlated sample.
|
|
*
|
|
* \param ctx The correlator context to initialize.
|
|
* \param search_seq The search sequence.
|
|
* \param nsymbols Length of the search sequence.
|
|
*
|
|
* \returns Whether the correlator was initialized successfully.
|
|
*/
|
|
bool correlator_init(correlator_ctx_t *ctx, const float complex *search_seq, size_t nsymbols);
|
|
|
|
/*!
|
|
* \brief Delete a correlator.
|
|
*
|
|
* \param ctx The correlator context to free.
|
|
*/
|
|
void correlator_free(correlator_ctx_t *ctx);
|
|
|
|
/*!
|
|
* \brief Process one sample in the correlator.
|
|
*
|
|
* The input sample will be stored in the internal history buffer and then the
|
|
* following calculation will be executed, where k determines the “age” of the
|
|
* sample and n is the size of the search sequence:
|
|
*
|
|
* result = sum{k = 0..n-1} (input_history[k] * search_sequence[k])
|
|
*
|
|
* \param ctx The correlator context to use.
|
|
* \param sample The input sample to process.
|
|
*
|
|
* \returns The new correlator output value.
|
|
*/
|
|
float complex correlator_step(correlator_ctx_t *ctx, float complex sample);
|
|
|
|
/*!
|
|
* \brief Retrieve the history of input values.
|
|
*
|
|
* \details
|
|
* This function gives the last n input values, where n is the size of the
|
|
* search sequence.
|
|
*
|
|
* The values will be ordered such that the oldest value has index 0.
|
|
*
|
|
* Note that this function is rather expensive as it copies all the data.
|
|
* However it might releave the user of keeping track of the input samples in
|
|
* case the history is only used occasionally.
|
|
*
|
|
* \param ctx The correlator context to use.
|
|
* \param history Pointer to the output array. Must have space for n values.
|
|
*/
|
|
void correlator_get_input_history(correlator_ctx_t *ctx, float complex *history);
|
|
|
|
/*!
|
|
* \brief Retrieve the conjugated search sequence.
|
|
*
|
|
* \details
|
|
* Returns a pointer to the internally used search sequence, which corresponds
|
|
* to the sequence given to \ref correlator_init(), but all values are
|
|
* conjugated.
|
|
*
|
|
* \param ctx The correlator context to use.
|
|
* \returns A pointer to the internal search sequence.
|
|
*/
|
|
const float complex* correlator_get_conj_search_sequence(correlator_ctx_t *ctx);
|
|
|
|
/*!
|
|
* \brief Calculate mean phase deviation between current input and search sequence.
|
|
*
|
|
* \details
|
|
* Calling this probably only makes sense directly after a correlation peak was
|
|
* found.
|
|
*
|
|
* \param ctx The correlator context to use.
|
|
* \returns The mean phase deviation in radians.
|
|
*/
|
|
float correlator_get_mean_phase_deviation(correlator_ctx_t *ctx);
|
|
|
|
/*!
|
|
* \brief Calculate mean frequency deviation between current input and search sequence.
|
|
*
|
|
* \details
|
|
* Calling this probably only makes sense directly after a correlation peak was
|
|
* found.
|
|
*
|
|
* This uses the Louise & Regiannini frequency estimation algorithm for known
|
|
* symbol sequences.
|
|
*
|
|
* \param ctx The correlator context to use.
|
|
* \param L Number of symbols to use (at the end of the sequence)
|
|
* \param phase_offset The phase offset of the symbol *following* the preamble.
|
|
* May be NULL if not needed.
|
|
* \returns The mean frequency deviation in radians/symbol.
|
|
*/
|
|
float correlator_get_mean_frequency_deviation(correlator_ctx_t *ctx, size_t L, float *phase_offset);
|
|
|
|
|
|
#endif // LAYER1_CORRELATOR_H
|