File costas_core.h¶
FileList > costas > costas_core.h
Go to the source code of this file
Costas carrier-tracking loop (integer-NCO de-rotation + PI loop). More...
#include "clib_common.h"#include "dp_state.h"#include "jm_perf.h"#include "lo/lo_core.h"#include "loop_filter/loop_filter_core.h"#include <math.h>
Classes¶
| Type | Name |
|---|---|
| struct | costas_state_t Costas loop state. |
Public Functions¶
| Type | Name |
|---|---|
| void | costas_configure (costas_state_t * state, double bn, double zeta) |
| costas_state_t * | costas_create (double bn, double zeta, double init_norm_freq, size_t tsamps, double bn_fll) Create a Costas instance. |
| void | costas_destroy (costas_state_t * state) Destroy a Costas instance and release all memory. |
| double | costas_get_bn (const costas_state_t * state) |
| double | costas_get_bn_fll (const costas_state_t * state) |
| double | costas_get_last_error (const costas_state_t * state) |
| double | costas_get_lock_metric (const costas_state_t * state) |
| double | costas_get_norm_freq (const costas_state_t * state) |
| void | costas_get_state (const costas_state_t * state, void * blob) Serialize the full loop state into blob . |
| void | costas_init (costas_state_t * s, double bn, double zeta, double init_norm_freq, size_t tsamps, double bn_fll) Initialise a Costas loop in place (no allocation). |
| void | costas_reset (costas_state_t * state) Re-seed the loop to its create-time frequency/phase; keep config. |
| void | costas_set_bn (costas_state_t * state, double val) |
| void | costas_set_bn_fll (costas_state_t * state, double val) |
| void | costas_set_norm_freq (costas_state_t * state, double val) |
| int | costas_set_state (costas_state_t * state, const void * blob) Restore state; DP_OK, or DP_ERR_INVALID if the envelope rejects. |
| size_t | costas_state_bytes (const costas_state_t * state) Serialized-state byte size. |
| size_t | costas_steps (costas_state_t * state, const float complex * x, size_t x_len, float complex * out, size_t max_out) |
| size_t | costas_steps_max_out (costas_state_t * state) |
| JM_FORCEINLINE JM_HOT void | costas_update (costas_state_t * s, float complex P) Per-symbol carrier update: discriminator -> loop filter -> steer NCO. |
| JM_FORCEINLINE JM_HOT float complex | costas_wipeoff (costas_state_t * s, float complex x) Per-sample carrier wipe-off: de-rotate x by the NCO, advance it. |
Macros¶
| Type | Name |
|---|---|
| define | COSTAS_EPS 1e-12f |
| define | COSTAS_LOCK_ALPHA 0.1 |
| define | COSTAS_STATE_MAGIC [**DP\_FOURCC**](dp__state_8h.md#define-dp_fourcc)('C', 'S', 'T', 'S') |
| define | COSTAS_STATE_VERSION 1u |
Detailed Description¶
A continuous BPSK carrier-recovery loop: per sample it de-rotates the input with the integer-phase lo NCO (carrier wipe-off); every tsamps samples it dumps the coherent integrate-and-dump accumulator, runs a decision-directed Costas phase discriminator, filters the error through an embedded 2nd-order loop_filter_state_t, and steers the NCO frequency + phase. It tracks a small residual carrier offset (the bulk Doppler is removed upstream by FFT acquisition); the steering NCO is lo, so the phase is bounded and exactly reproducible (no double-accumulator drift).
The block API (costas_steps) is the Python face; the JM_FORCEINLINE costas_wipeoff()/costas_update() are the C composition API a despreader / tracking channel inlines into its own sample loop.
Lifecycle: costas_create -> [steps / configure / reset]* -> costas_destroy, or embed by value with costas_init().
Set bn_fll > 0 to enable FLL assist (a wide-pull-in frequency-lock loop aiding the PLL) for large or fast-moving residuals; bn_fll = 0 is a pure Costas PLL.
costas_state_t *c = costas_create(0.05, 0.707, 0.01, 64, 0.0);
float complex sym[16];
size_t k = costas_steps(c, rx, rx_len, sym, 16); // one prompt per symbol
double f = c->nco.norm_freq; // tracked residual
costas_destroy(c);
Public Functions Documentation¶
function costas_configure¶
function costas_create¶
Create a Costas instance.
costas_state_t * costas_create (
double bn,
double zeta,
double init_norm_freq,
size_t tsamps,
double bn_fll
)
Parameters:
bnLoop noise bandwidth (default 0.05).zetaDamping factor (default 0.707).init_norm_freqSeed carrier frequency, cycles/sample (default 0.0).tsampsSamples per symbol (default 64).bn_fllFLL-assist bandwidth (default 0.0 = pure PLL).
Returns:
Heap-allocated state, or NULL on allocation failure.
Note:
Caller must call costas_destroy() when done.
function costas_destroy¶
Destroy a Costas instance and release all memory.
Parameters:
stateMay be NULL.
function costas_get_bn¶
function costas_get_bn_fll¶
function costas_get_last_error¶
function costas_get_lock_metric¶
function costas_get_norm_freq¶
function costas_get_state¶
Serialize the full loop state into blob .
function costas_init¶
Initialise a Costas loop in place (no allocation).
void costas_init (
costas_state_t * s,
double bn,
double zeta,
double init_norm_freq,
size_t tsamps,
double bn_fll
)
The by-value counterpart to costas_create(): a tracking channel that embeds a costas_state_t initialises it here. Seeds the NCO at init_norm_freq and the loop integrator to the matching per-symbol frequency so de-rotation is correct from the first sample.
Parameters:
sState to initialise. Must be non-NULL.bnLoop noise bandwidth, normalised to the symbol rate.zetaDamping factor (0.707 = critically damped).init_norm_freqSeed carrier frequency, cycles/sample.tsampsSamples per symbol (the integrate-and-dump period).bn_fllFLL-assist bandwidth (0 = pure PLL).
function costas_reset¶
Re-seed the loop to its create-time frequency/phase; keep config.
Parameters:
stateMust be non-NULL.
function costas_set_bn¶
function costas_set_bn_fll¶
function costas_set_norm_freq¶
function costas_set_state¶
Restore state; DP_OK, or DP_ERR_INVALID if the envelope rejects.
function costas_state_bytes¶
Serialized-state byte size.
function costas_steps¶
size_t costas_steps (
costas_state_t * state,
const float complex * x,
size_t x_len,
float complex * out,
size_t max_out
)
function costas_steps_max_out¶
function costas_update¶
Per-symbol carrier update: discriminator -> loop filter -> steer NCO.
Runs the decision-directed BPSK Costas discriminator on the prompt P, filters it, and writes the new frequency (lo_set_norm_freq) plus a proportional phase nudge into the NCO. Updates the lock metric and last_error (the instantaneous loop stress). Inline for composition.
Parameters:
sCostas state. Must be non-NULL.PThe dumped integrate-and-dump prompt for this symbol.
function costas_wipeoff¶
Per-sample carrier wipe-off: de-rotate x by the NCO, advance it.
x * conj(lo_step(nco)) — strips the (tracked) carrier ahead of the matched-filter integrate-and-dump. Inline, zero call overhead.
Parameters:
sCostas state. Must be non-NULL.xOne input sample.
Returns:
The de-rotated sample to feed the integrator.
Macro Definition Documentation¶
define COSTAS_EPS¶
define COSTAS_LOCK_ALPHA¶
define COSTAS_STATE_MAGIC¶
define COSTAS_STATE_VERSION¶
The documentation for this class was generated from the following file native/inc/costas/costas_core.h