File mpsk_receiver_core.h¶
FileList > inc > mpsk_receiver > mpsk_receiver_core.h
Go to the source code of this file
Pulse-shaped M-PSK receiver: NDA-acquired carrier + Gardner timing. More...
#include "carrier_nda/carrier_nda_core.h"#include "clib_common.h"#include "dp_state.h"#include "fir/fir_core.h"#include "jm_perf.h"#include "mpsk/mpsk_core.h"#include "symsync/symsync_core.h"#include <complex.h>#include "lo/lo_core.h"#include "loop_filter/loop_filter_core.h"#include "farrow/farrow_core.h"
Classes¶
| Type | Name |
|---|---|
| struct | mpsk_receiver_state_t M-PSK receiver state. |
Public Types¶
| Type | Name |
|---|---|
| enum | mpsk__receiver__core_8h_1adf764cbdea00d65edcd07bb9953ad2b7 Matched-filter pulse shape selector. |
Public Functions¶
| Type | Name |
|---|---|
| size_t | mpsk_receiver_bits (mpsk_receiver_state_t * state, const float complex * x, size_t x_len, uint8_t * out, size_t max_out) Demodulate a cf32 block and emit hard Gray-coded bits. |
| size_t | mpsk_receiver_bits_max_out (mpsk_receiver_state_t * state) |
| mpsk_receiver_state_t * | mpsk_receiver_create (int m, size_t sps, int n, int pulse, double rrc_beta, int rrc_span, double bn_carrier, double zeta, double bn_timing, int auto_handover, double lock_thresh, double init_norm_freq, size_t warmup_syms, int differential) Create an M-PSK receiver. |
| void | mpsk_receiver_destroy (mpsk_receiver_state_t * state) Destroy an M-PSK receiver and release all memory. |
| double | mpsk_receiver_get_lock (const mpsk_receiver_state_t * state) |
| int | mpsk_receiver_get_m (const mpsk_receiver_state_t * state) |
| int | mpsk_receiver_get_n (const mpsk_receiver_state_t * state) |
| double | mpsk_receiver_get_norm_freq (const mpsk_receiver_state_t * state) |
| size_t | mpsk_receiver_get_sps (const mpsk_receiver_state_t * state) |
| void | mpsk_receiver_get_state (const mpsk_receiver_state_t * state, void * blob) |
| double | mpsk_receiver_get_timing_rate (const mpsk_receiver_state_t * state) |
| int | mpsk_receiver_get_tracking (const mpsk_receiver_state_t * state) |
| void | mpsk_receiver_reset (mpsk_receiver_state_t * state) Re-seed the carrier/timing loops to their create-time state. |
| void | mpsk_receiver_set_norm_freq (mpsk_receiver_state_t * state, double val) |
| int | mpsk_receiver_set_state (mpsk_receiver_state_t * state, const void * blob) |
| size_t | mpsk_receiver_state_bytes (const mpsk_receiver_state_t * state) |
| size_t | mpsk_receiver_steps (mpsk_receiver_state_t * state, const float complex * x, size_t x_len, float complex * out, size_t max_out) Demodulate a cf32 block and emit the recovered symbols. |
| size_t | mpsk_receiver_steps_max_out (mpsk_receiver_state_t * state) |
Macros¶
| Type | Name |
|---|---|
| define | MPSK_RECEIVER_STATE_MAGIC [**DP\_FOURCC**](dp__state_8h.md#define-dp_fourcc) ('M','P','S','K') |
| define | MPSK_RECEIVER_STATE_VERSION 1u |
Detailed Description¶
A complete per-sample inline modem for a continuous (unspread) M-PSK signal. It composes the project's tracking primitives on one shared sample loop:
- carrier_nda_state_t — per-sample carrier wipe-off with the integer NCO, plus a non-data-aided M-th-power discriminator on an I/Q arm integrate-and-dump (n dumps/symbol). This acquires the carrier with no symbol timing and no data present (cold start), which is what lets the receiver pull in before the matched filter / timing loop have settled.
- a matched filter (fir_state_t, owned) on the de-rotated stream: either an integrate-and-dump boxcar (
MPSK_RX_PULSE_IANDD, default) or a root-raised-cosine (MPSK_RX_PULSE_RRC) for band-limited links. - symsync_state_t — a carrier-blind Gardner symbol-timing loop on the matched-filter output, emitting one symbol per recovered symbol period.
Carrier recovery follows the project rule: predetection de-rotation (per-sample wipe, always) and postdetection discrimination. Two discriminators steer one shared NCO:
* acquisition — the NDA M-th-power error, n times/symbol, with no data or timing required (tracking == 0).
* tracking — once auto_handover is enabled and the loop has locked, a decision-directed error e = Im(y·conj(â))/|y| on the recovered symbols (lower jitter, naturally lower loop bandwidth at symbol rate). The same NCO/loop filter carries the frequency estimate across handover. Handover is opt-in (auto_handover, default off): by default the receiver stays in robust NDA tracking the whole time.
The loop locks to one of M phases — an M-fold ambiguity on absolute phase. Resolve it with differential demapping (bits(..., differential=1)) or a sync word downstream. A DSSS-MPSK receiver is Dll(segments) -> MpskReceiver: despread to symbol-rate soft chips, then this modem.
Lifecycle: mpsk_receiver_create -> [steps / bits / reset]* -> _destroy.
// QPSK, 8 samples/symbol, I&D matched filter, NDA acquisition
mpsk_receiver_state_t *rx = mpsk_receiver_create(
4, 8, 4, MPSK_RX_PULSE_IANDD, 0.35, 8,
0.01, 0.707, 0.01, 0, 0.5, 0.0, 100, 0);
float complex sym[256];
size_t k = mpsk_receiver_steps(rx, rx_in, rx_len, sym, 256);
double f = mpsk_receiver_get_norm_freq(rx); // tracked residual carrier
mpsk_receiver_destroy(rx);
Public Types Documentation¶
enum mpsk__receiver__core_8h_1adf764cbdea00d65edcd07bb9953ad2b7¶
Matched-filter pulse shape selector.
enum mpsk__receiver__core_8h_1adf764cbdea00d65edcd07bb9953ad2b7 {
MPSK_RX_PULSE_IANDD = 0,
MPSK_RX_PULSE_RRC = 1
};
Public Functions Documentation¶
function mpsk_receiver_bits¶
Demodulate a cf32 block and emit hard Gray-coded bits.
size_t mpsk_receiver_bits (
mpsk_receiver_state_t * state,
const float complex * x,
size_t x_len,
uint8_t * out,
size_t max_out
)
Like mpsk_receiver_steps(), but each recovered symbol is sliced to its nearest M-PSK point and unpacked to log2(M) hard bits (LSB-first). With the differential option set at create time, the Gray label is taken from the phase difference between consecutive symbols (rotation-invariant — it resolves the M-fold carrier ambiguity), else from the absolute (coherent) decision.
Parameters:
stateReceiver state. Must be non-NULL.xInput cf32 samples.x_lenNumber of input samples.outOutput bytes (0/1); caller providesmax_outcapacity.max_outOutput capacity.
Returns:
Number of bits written.
function mpsk_receiver_bits_max_out¶
function mpsk_receiver_create¶
Create an M-PSK receiver.
mpsk_receiver_state_t * mpsk_receiver_create (
int m,
size_t sps,
int n,
int pulse,
double rrc_beta,
int rrc_span,
double bn_carrier,
double zeta,
double bn_timing,
int auto_handover,
double lock_thresh,
double init_norm_freq,
size_t warmup_syms,
int differential
)
Parameters:
mConstellation order M, 2/4/8 (default 4 = QPSK).spsSamples per symbol (default 8).nCarrier arm dumps per symbol (default 4; sps % n == 0).pulseMatched-filter shape (default MPSK_RX_PULSE_IANDD).rrc_betaRRC roll-off in [0, 1] (default 0.35; RRC only).rrc_spanRRC one-sided span in symbols (default 8; RRC only).bn_carrierCarrier loop noise bandwidth (default 0.01).zetaDamping factor for both loops (default 0.707).bn_timingSymbol-timing loop noise bandwidth (default 0.01).auto_handoverEnable NDA->decision-directed handover (default 0).lock_threshLock metric required for handover (default 0.5).init_norm_freqSeed carrier frequency, cycles/sample (default 0.0).warmup_symsSymbols before handover is allowed (default 100).differentialbits(): differential (rotation-invariant) demap (default 0 = coherent).
Returns:
Heap-allocated state, or NULL on invalid args / allocation failure.
Note:
Caller must call mpsk_receiver_destroy() when done.
function mpsk_receiver_destroy¶
Destroy an M-PSK receiver and release all memory.
Parameters:
stateMay be NULL.
function mpsk_receiver_get_lock¶
function mpsk_receiver_get_m¶
function mpsk_receiver_get_n¶
function mpsk_receiver_get_norm_freq¶
function mpsk_receiver_get_sps¶
function mpsk_receiver_get_state¶
function mpsk_receiver_get_timing_rate¶
function mpsk_receiver_get_tracking¶
function mpsk_receiver_reset¶
Re-seed the carrier/timing loops to their create-time state.
Parameters:
stateMust be non-NULL.
function mpsk_receiver_set_norm_freq¶
function mpsk_receiver_set_state¶
function mpsk_receiver_state_bytes¶
function mpsk_receiver_steps¶
Demodulate a cf32 block and emit the recovered symbols.
size_t mpsk_receiver_steps (
mpsk_receiver_state_t * state,
const float complex * x,
size_t x_len,
float complex * out,
size_t max_out
)
Runs the per-sample loop (carrier wipe-off + NDA arm + matched filter + Gardner timing) over x and writes one cf32 symbol per recovered symbol period. Fewer outputs than inputs (~ x_len / sps). Read norm_freq for the tracked carrier and lock for the carrier lock metric.
Parameters:
stateReceiver state. Must be non-NULL.xInput cf32 samples.x_lenNumber of input samples.outOutput symbols; caller providesmax_outcapacity.max_outOutput capacity.
Returns:
Number of symbols written.
function mpsk_receiver_steps_max_out¶
Macro Definition Documentation¶
define MPSK_RECEIVER_STATE_MAGIC¶
define MPSK_RECEIVER_STATE_VERSION¶
The documentation for this class was generated from the following file native/inc/mpsk_receiver/mpsk_receiver_core.h