correlator: improved phase estimation

The phase is now calculated based on the preamble correlation directly instead
of the method of the frequency estimator.
This commit is contained in:
Thomas Kolb 2024-01-06 23:54:41 +01:00
parent ef25ca2388
commit 16aa2ce92c
2 changed files with 19 additions and 15 deletions

View file

@ -97,6 +97,11 @@ float complex correlator_step(correlator_ctx_t *ctx, float complex sample)
result += ctx->search_sequence[m] * ctx->input_history[nm]; result += ctx->search_sequence[m] * ctx->input_history[nm];
} }
// the current mean phase can be basically calculated for free here, as the
// sum of rotated symbols is already available, so we do so and cache that
// value.
ctx->phase_deviation = cargf(result);
return result; return result;
} }
@ -118,19 +123,10 @@ const float complex* correlator_get_conj_search_sequence(correlator_ctx_t *ctx)
} }
float correlator_get_mean_phase_deviation(correlator_ctx_t *ctx, size_t L) float correlator_get_mean_phase_deviation(correlator_ctx_t *ctx)
{ {
float complex mean_unrotated_symbol = 0; // return cached value from last call to correlator_step().
return ctx->phase_deviation;
size_t n = (ctx->history_ptr - ctx->search_sequence_len + 1) & ctx->buffer_size_mask;
for(size_t m = ctx->search_sequence_len - L; m < ctx->search_sequence_len; m++) {
size_t nm = (n + m) & ctx->buffer_size_mask;
mean_unrotated_symbol += ctx->search_sequence[m] * ctx->input_history[nm];
}
// no need to divide by ctx->search_sequence_len because division does not change the angle
return cargf(mean_unrotated_symbol);
} }
@ -147,5 +143,12 @@ float correlator_get_mean_frequency_deviation(correlator_ctx_t *ctx, size_t L, f
z[m - m0] = conjf(ctx->search_sequence[m]) * ctx->input_history[nm]; z[m - m0] = conjf(ctx->search_sequence[m]) * ctx->input_history[nm];
} }
return freq_est_data_free(z, L, phase_offset); float freq = freq_est_data_free(z, L, NULL);
// we calculate the final phase based on the phase estimated from the
// preamble and not the phase from the frequency estimator because this
// method is more reliable.
*phase_offset = ctx->phase_deviation + (ctx->search_sequence_len+1)/2.0f * freq;
return freq;
} }

View file

@ -24,6 +24,8 @@ typedef struct
float complex *search_sequence; float complex *search_sequence;
float complex *input_history; float complex *input_history;
float phase_deviation;
/*! /*!
* \brief The history pointer. * \brief The history pointer.
* *
@ -120,10 +122,9 @@ const float complex* correlator_get_conj_search_sequence(correlator_ctx_t *ctx);
* found. * found.
* *
* \param ctx The correlator context to use. * \param ctx The correlator context to use.
* \param L Number of symbols to use (at the end of the sequence)
* \returns The mean phase deviation in radians. * \returns The mean phase deviation in radians.
*/ */
float correlator_get_mean_phase_deviation(correlator_ctx_t *ctx, size_t L); float correlator_get_mean_phase_deviation(correlator_ctx_t *ctx);
/*! /*!
* \brief Calculate mean frequency deviation between current input and search sequence. * \brief Calculate mean frequency deviation between current input and search sequence.