File mpsk_receiver_core.h¶
File List > doppler > mpsk_receiver > mpsk_receiver_core.h
Go to the documentation of this file
#ifndef DP_MPSK_RECEIVER_CORE_H
#define DP_MPSK_RECEIVER_CORE_H
#include "doppler/clib_common.h"
#include "doppler/ddc/ddc_core.h"
#include "doppler/ddcr/ddcr_core.h"
#include "doppler/dp_state.h"
#include "doppler/jm_perf.h"
#include "doppler/mpsk_receiver/mpsk_rx_loops.h"
#include "doppler/dp_complex.h"
#include "doppler/ratesync/ratesync_core.h"
#include "doppler/RateConverter/RateConverter_core.h"
#include "doppler/resamp/resamp_core.h"
#include "doppler/hbdecim/hbdecim_core.h"
#include "doppler/cic/cic_core.h"
#include "doppler/fir/fir_core.h"
#include "doppler/resample/resample_core.h"
#include "doppler/lo/lo_core.h"
#include "doppler/nco/nco_core.h"
#include "doppler/loop_filter/loop_filter_core.h"
#include "doppler/lockdet/lockdet_core.h"
#include "doppler/symsync/symsync_core.h"
#include "doppler/agc/agc_core.h"
#include "doppler/dp_tlm/dp_tlm_core.h"
#include "doppler/ber/ber_core.h"
#include "doppler/telemetry/telemetry_core.h"
#include "doppler/boxcar/boxcar_core.h"
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct
{
union
{
dp_ddc_state_t *c;
dp_ddcr_state_t *r;
} fe;
mpsk_rx_loops_t l;
/* ── config (restored by create(), never packed in a state blob) ── */
/* The pulse geometry lives in the front end, which is the only thing
that uses it; keeping a second copy here would be a shadow of the
cascade's own configuration, free to drift out of step with it. */
int real;
double centre_freq;
} dp_mpsk_receiver_state_t;
dp_mpsk_receiver_state_t *
dp_mpsk_receiver_create (int m, double sps, size_t m_out, int pulse,
double rrc_beta, int rrc_span, double bn_carrier,
double zeta, double bn_timing, double lock_thresh,
double init_norm_freq, int differential,
size_t num_phases, int agc, double bn_agc_ratio);
dp_mpsk_receiver_state_t *
dp_mpsk_receiver_create_real (int m, double sps, size_t m_out, int pulse,
double rrc_beta, int rrc_span, double bn_carrier,
double zeta, double bn_timing,
double lock_thresh, double init_norm_freq,
int differential, size_t num_phases, int agc,
double bn_agc_ratio);
double dp_mpsk_receiver_get_agc_gain_db (const dp_mpsk_receiver_state_t *state);
dp_mpsk_receiver_state_t *dp_mpsk_receiver_create_bpsk (
double sample_rate_hz, double symbol_rate_hz, double carrier_freq_hz,
int pulse, double rrc_beta, int rrc_span, double bn_carrier,
double bn_timing, int differential, int agc);
void dp_mpsk_receiver_destroy (dp_mpsk_receiver_state_t *state);
void dp_mpsk_receiver_reset (dp_mpsk_receiver_state_t *state);
JM_FORCEINLINE JM_HOT int
mpsk_receiver_step_ted (dp_mpsk_receiver_state_t *s, float _Complex x,
float _Complex *y_out, int ted)
{
float _Complex ys[4];
size_t n = dp_ddc_execute_ctrl_push_tap2 (
s->fe.c, x, s->l.timing.ctrl, s->l.freq_ctrl, ys,
sizeof (ys) / sizeof (ys[0]), NULL, NULL, NULL, NULL);
return mpsk_rx_fold (&s->l, ys, n, y_out, ted);
}
JM_FORCEINLINE JM_HOT int
mpsk_receiver_step_real_ted (dp_mpsk_receiver_state_t *s, float x,
float _Complex *y_out, int ted)
{
float _Complex ys[4];
size_t n = dp_ddcr_execute_ctrl_push_tap2 (
s->fe.r, x, s->l.timing.ctrl, s->l.freq_ctrl, ys,
sizeof (ys) / sizeof (ys[0]), NULL, NULL, NULL, NULL);
return mpsk_rx_fold (&s->l, ys, n, y_out, ted);
}
size_t dp_mpsk_receiver_steps_max_out (dp_mpsk_receiver_state_t *state);
size_t dp_mpsk_receiver_steps (dp_mpsk_receiver_state_t *state,
const float _Complex *x, size_t x_len,
float _Complex *out, size_t max_out);
size_t dp_mpsk_receiver_bits_max_out (dp_mpsk_receiver_state_t *state);
size_t dp_mpsk_receiver_bits (dp_mpsk_receiver_state_t *state,
const float _Complex *x, size_t x_len,
uint8_t *out, size_t max_out);
size_t dp_mpsk_receiver_steps_real_max_out (dp_mpsk_receiver_state_t *state);
size_t dp_mpsk_receiver_steps_real (dp_mpsk_receiver_state_t *state,
const float *x, size_t x_len,
float _Complex *out, size_t max_out);
size_t dp_mpsk_receiver_bits_real_max_out (dp_mpsk_receiver_state_t *state);
size_t dp_mpsk_receiver_bits_real (dp_mpsk_receiver_state_t *state, const float *x,
size_t x_len, uint8_t *out, size_t max_out);
double dp_mpsk_receiver_get_norm_freq (const dp_mpsk_receiver_state_t *state);
double dp_mpsk_receiver_get_nco_freq (const dp_mpsk_receiver_state_t *state);
void dp_mpsk_receiver_set_norm_freq (dp_mpsk_receiver_state_t *state, double val);
double dp_mpsk_receiver_get_lock (const dp_mpsk_receiver_state_t *state);
int dp_mpsk_receiver_get_locked (const dp_mpsk_receiver_state_t *state);
int64_t dp_mpsk_receiver_get_lock_time (const dp_mpsk_receiver_state_t *state);
double dp_mpsk_receiver_get_last_error (const dp_mpsk_receiver_state_t *state);
int dp_mpsk_receiver_set_telemetry (dp_mpsk_receiver_state_t *state, dp_tlm_t *tlm,
const char *prefix, uint32_t decim);
double dp_mpsk_receiver_get_timing_rate (const dp_mpsk_receiver_state_t *state);
int dp_mpsk_receiver_get_m (const dp_mpsk_receiver_state_t *state);
double dp_mpsk_receiver_get_sps (const dp_mpsk_receiver_state_t *state);
size_t dp_mpsk_receiver_get_m_out (const dp_mpsk_receiver_state_t *state);
double dp_mpsk_receiver_get_zeta (const dp_mpsk_receiver_state_t *state);
double dp_mpsk_receiver_get_bn_agc_ratio (const dp_mpsk_receiver_state_t *state);
double dp_mpsk_receiver_get_lock_thresh (const dp_mpsk_receiver_state_t *state);
double
dp_mpsk_receiver_get_lock_drop_thresh (const dp_mpsk_receiver_state_t *state);
double
dp_mpsk_receiver_get_sync_lock_thresh (const dp_mpsk_receiver_state_t *state);
double
dp_mpsk_receiver_get_sync_lock_drop_thresh (const dp_mpsk_receiver_state_t *state);
size_t dp_mpsk_receiver_get_num_phases (const dp_mpsk_receiver_state_t *state);
int dp_mpsk_receiver_get_clipped (const dp_mpsk_receiver_state_t *state);
/* ── Serializable state (standard bytes interface; see dp_state.h) ──────────
* composition: the front end's and the loops' self-validating child blobs.
* Every scalar this object carries across inputs lives in one of them; the
* cascade, its banks, the LO centre and the `real` tag are restored by create.
*
* The MAGIC is keyed on the face. The two faces hold genuinely different
* state — a DDC's cascade against a DDCR's halfband plus cascade — so a blob
* taken from one must be REFUSED by the other rather than reinterpreted, and
* refused at the envelope by name rather than three levels down in a child.
* The layouts are otherwise identical, which is why one triplet serves both.
*/
#define MPSK_RECEIVER_STATE_MAGIC DP_FOURCC ('M', 'P', 'S', 'K')
#define MPSK_RECEIVER_STATE_VERSION 6u /* v5: rebuilt on the matched DDC */
#define MPSK_RECEIVER_R_STATE_MAGIC DP_FOURCC ('M', 'P', 'S', 'R')
#define MPSK_RECEIVER_R_STATE_VERSION 2u
size_t dp_mpsk_receiver_state_bytes (const dp_mpsk_receiver_state_t *state);
void dp_mpsk_receiver_get_state (const dp_mpsk_receiver_state_t *state,
void *blob);
int dp_mpsk_receiver_set_state (dp_mpsk_receiver_state_t *state, const void *blob);
#ifdef __cplusplus
}
#endif
#endif /* MPSK_RECEIVER_CORE_H */