Skip to content

File mpsk_core.h

File List > inc > mpsk > mpsk_core.h

Go to the documentation of this file

#ifndef MPSK_CORE_H
#define MPSK_CORE_H

#include "clib_common.h"
#include "jm_perf.h"
#include <complex.h>
#include <math.h>
#ifdef __cplusplus
extern "C" {
#endif

#ifndef MPSK_PI
#define MPSK_PI 3.14159265358979323846
#endif

JM_FORCEINLINE int
mpsk_bps (int m)
{
  return (m == 2) ? 1 : (m == 4) ? 2 : (m == 8) ? 3 : 0;
}

JM_FORCEINLINE double
mpsk_phi0 (int m)
{
  return (m == 4) ? (MPSK_PI / 4.0) : 0.0;
}

JM_FORCEINLINE unsigned
mpsk_gray_encode (unsigned k)
{
  return k ^ (k >> 1);
}

JM_FORCEINLINE unsigned
mpsk_gray_decode (unsigned g)
{
  unsigned k = g;
  while (g >>= 1)
    k ^= g;
  return k;
}

JM_FORCEINLINE float complex
mpsk_constellation (unsigned g, int m)
{
  unsigned k    = mpsk_gray_decode (g & (unsigned)(m - 1));
  double   theta = 2.0 * MPSK_PI * (double)k / (double)m + mpsk_phi0 (m);
  return (float)cos (theta) + (float)sin (theta) * I;
}

JM_FORCEINLINE unsigned
mpsk_slice (float complex y, int m, float complex *ahat)
{
  double phi0 = mpsk_phi0 (m);
  double th   = atan2 ((double)cimagf (y), (double)crealf (y)) - phi0;
  long   k    = lround (th * (double)m / (2.0 * MPSK_PI));
  unsigned ki = (unsigned)(k & (long)(m - 1)); /* mod M (M power of two) */
  double   ta = 2.0 * MPSK_PI * (double)ki / (double)m + phi0;
  *ahat       = (float)cos (ta) + (float)sin (ta) * I;
  return mpsk_gray_encode (ki);
}

void mpsk_map(const uint8_t *sym, size_t sym_len, float complex *out, int m);

void mpsk_demap(const float complex *x, size_t x_len, uint8_t *out, int m);

void mpsk_diff_map(const uint8_t *sym, size_t sym_len, float complex *out,
                   int m);

void mpsk_diff_demap(const float complex *x, size_t x_len, uint8_t *out, int m);

int mpsk_bits_per_symbol(int m);

#ifdef __cplusplus
}
#endif

#endif /* MPSK_CORE_H */