Skip to content

File mpsk_receiver_core.h

File List > inc > mpsk_receiver > mpsk_receiver_core.h

Go to the documentation of this file

#ifndef MPSK_RECEIVER_CORE_H
#define MPSK_RECEIVER_CORE_H

#include "clib_common.h"
#include "ddc/ddc_core.h"
#include "ddcr/ddcr_core.h"
#include "dp_state.h"
#include "jm_perf.h"
#include "mpsk_receiver/mpsk_rx_loops.h"
#include <complex.h>
#include "ratesync/ratesync_core.h"
#include "RateConverter/RateConverter_core.h"
#include "resamp/resamp_core.h"
#include "hbdecim/hbdecim_core.h"
#include "cic/cic_core.h"
#include "fir/fir_core.h"
#include "resample/resample_core.h"
#include "lo/lo_core.h"
#include "nco/nco_core.h"
#include "loop_filter/loop_filter_core.h"
#include "lockdet/lockdet_core.h"
#include "symsync/symsync_core.h"
#include "agc/agc_core.h"
#include "dp_tlm/dp_tlm_core.h"
#include "ber/ber_core.h"
#include "telemetry/telemetry_core.h"
#include "boxcar/boxcar_core.h"
#ifdef __cplusplus
extern "C"
{
#endif

  typedef struct
  {
    union
    {
      ddc_state_t  *c; 
      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; 
  } mpsk_receiver_state_t;

  mpsk_receiver_state_t *
  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);

  mpsk_receiver_state_t *
  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 mpsk_receiver_get_agc_gain_db (const mpsk_receiver_state_t *state);

  mpsk_receiver_state_t *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 mpsk_receiver_destroy (mpsk_receiver_state_t *state);

  void mpsk_receiver_reset (mpsk_receiver_state_t *state);

  JM_FORCEINLINE JM_HOT int
  mpsk_receiver_step_ted (mpsk_receiver_state_t *s, float _Complex x,
                          float _Complex *y_out, int ted)
  {
    float _Complex ys[4];
    size_t        n     = 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 (mpsk_receiver_state_t *s, float x,
                               float _Complex *y_out, int ted)
  {
    float _Complex ys[4];
    size_t        n     = 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 mpsk_receiver_steps_max_out (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);

  size_t mpsk_receiver_bits_max_out (mpsk_receiver_state_t *state);
  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);

  size_t mpsk_receiver_steps_real_max_out (mpsk_receiver_state_t *state);
  size_t mpsk_receiver_steps_real (mpsk_receiver_state_t *state,
                                   const float *x, size_t x_len,
                                   float _Complex *out, size_t max_out);

  size_t mpsk_receiver_bits_real_max_out (mpsk_receiver_state_t *state);
  size_t mpsk_receiver_bits_real (mpsk_receiver_state_t *state, const float *x,
                                  size_t x_len, uint8_t *out, size_t max_out);

  double mpsk_receiver_get_norm_freq (const mpsk_receiver_state_t *state);
  double mpsk_receiver_get_nco_freq (const mpsk_receiver_state_t *state);
  void mpsk_receiver_set_norm_freq (mpsk_receiver_state_t *state, double val);
  double mpsk_receiver_get_lock (const mpsk_receiver_state_t *state);
  int mpsk_receiver_get_locked (const mpsk_receiver_state_t *state);

  int64_t mpsk_receiver_get_lock_time (const mpsk_receiver_state_t *state);
  double mpsk_receiver_get_last_error (const mpsk_receiver_state_t *state);

  int mpsk_receiver_set_telemetry (mpsk_receiver_state_t *state, dp_tlm_t *tlm,
                                   const char *prefix, uint32_t decim);
  double mpsk_receiver_get_timing_rate (const mpsk_receiver_state_t *state);
  int    mpsk_receiver_get_m (const mpsk_receiver_state_t *state);
  double mpsk_receiver_get_sps (const mpsk_receiver_state_t *state);
  size_t mpsk_receiver_get_m_out (const mpsk_receiver_state_t *state);

  double mpsk_receiver_get_zeta (const mpsk_receiver_state_t *state);

  double mpsk_receiver_get_bn_agc_ratio (const mpsk_receiver_state_t *state);

  double mpsk_receiver_get_lock_thresh (const mpsk_receiver_state_t *state);

  double
  mpsk_receiver_get_lock_drop_thresh (const mpsk_receiver_state_t *state);

  double
  mpsk_receiver_get_sync_lock_thresh (const mpsk_receiver_state_t *state);

  double
  mpsk_receiver_get_sync_lock_drop_thresh (const mpsk_receiver_state_t *state);

  size_t mpsk_receiver_get_num_phases (const mpsk_receiver_state_t *state);

  int mpsk_receiver_get_clipped (const 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 mpsk_receiver_state_bytes (const mpsk_receiver_state_t *state);
  void   mpsk_receiver_get_state (const mpsk_receiver_state_t *state,
                                  void                        *blob);
  int mpsk_receiver_set_state (mpsk_receiver_state_t *state, const void *blob);

#ifdef __cplusplus
}
#endif

#endif /* MPSK_RECEIVER_CORE_H */