git stults online alsa-signals / master liquid-test.c
master

Tree @master (Download .tar.gz)

liquid-test.c @masterraw · history · blame

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <math.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <complex.h>
#include <assert.h>
#include <liquid/liquid.h>

#define TWOPI (6.283185307179586)
#define SQRTTWO (1.4142135623730951)

void main(int argc, char *argv[])
{
  int            i;
  int            rem;

  FILE          *in;
  FILE          *out;
  unsigned char *ptr;
  unsigned char *din;
  unsigned int   dinlen;
  struct stat    statbf;

  unsigned int  s1,s2,s3,s4;
  float complex c1,c2,c3,c4;
  unsigned char mask1, mask2, mask3, mask4;

  /* modem encoding stuff */
  unsigned int      symb_up;
  unsigned int      symb_down;
  float complex     symb_mod;
  modulation_scheme ms    = LIQUID_MODEM_QPSK;
  modem             mod   = modem_create(ms);
  modem             demod = modem_create(ms);
  unsigned int      bps   = modem_get_bps(mod);
  unsigned int      num_symbols = 1 << bps;

  /* framing stuff */
  float complex    *cframe;
  unsigned int      cframelen;

  if (argc != 3)
    {
      fprintf (stdout, "usage: %s <infile> <outfile>\n", __func__);
      return;
    }

  if ((in = fopen (argv[1], "rb")) == NULL)
    {
      fprintf (stderr, "file %s does not exist\n", argv[1]);
      return;
    }

  /* in file and buffer */
  fstat (fileno (in), &statbf);
  dinlen = statbf.st_size;
  din = calloc (dinlen, sizeof(unsigned char));
  fread (din, sizeof(unsigned char), dinlen, in);
  fclose (in);
        
  fprintf (stdout, "transferring %u bits...\n", 8 * dinlen);
  fprintf (stdout, "%u bits at a time...\n", bps);

  /* create frame -- this is just the modulated complex symbols right
     now */
  cframelen = dinlen << bps;
  cframe = calloc (cframelen, sizeof(float complex));

  /* mask off bits bps at a time hardcode for now */
  /* encode them with 2-bit modem -- this is very inefficient; need a
     bit serial way w/e */
  mask1 = 0xC0;
  mask2 = 0x30;
  mask3 = 0x0C;
  mask4 = 0x03;
  for (i = 0; i < dinlen; ++i)
    {
      s1 = (din[i] & mask1) >> 6;
      s2 = (din[i] & mask2) >> 4;
      s3 = (din[i] & mask3) >> 2;
      s4 = (din[i] & mask4) >> 0;
      modem_modulate(mod, s1, &c1);
      modem_modulate(mod, s2, &c2);
      modem_modulate(mod, s3, &c3);
      modem_modulate(mod, s4, &c4);
      cframe[(1 << bps) * i    ] = c1;
      cframe[(1 << bps) * i + 1] = c2;
      cframe[(1 << bps) * i + 2] = c3;
      cframe[(1 << bps) * i + 3] = c4;
    }

  /* turn complex frame into a real signal at passband that can be
     transmitted */
  float        *rframe;
  unsigned int  rframelen;
  unsigned int semilen = 60;
  float        atten   = 60.0f;
  firhilbf q = firhilbf_create (semilen, atten);

  rframelen = cframelen << 1;
  rframe = calloc (rframelen, sizeof(float));
  for (i = 0; i < cframelen; ++i)
    firhilbf_interp_execute (q, cframe[i], &rframe[2 * i]);
  /* destroy complex frame */
  free (cframe);

  fprintf (stdout, "... done sending\n");

  fprintf (stdout, "receiving... \n");

  /* open file for writing received */
  out = fopen (argv[2], "wb");

  /* complex baseband signal */
  cframe = calloc (cframelen, sizeof(float complex));
  for (i = 0; i < cframelen; ++i)
    firhilbf_decim_execute (q, &rframe[2 * i], &cframe[i]);
  /* destroy real frame */
  free (rframe);

  firhilbf_destroy (q);

  /* demodulate and reassemble bytes, write them to file; still
     hardcoded for 2-bit symbols */
  for (i = 0; i < dinlen; ++i)
    {
      unsigned char byte = 0x00;
      modem_demodulate(demod, cframe[(1 << bps) * i    ], &s1);
      modem_demodulate(demod, cframe[(1 << bps) * i + 1], &s2);
      modem_demodulate(demod, cframe[(1 << bps) * i + 2], &s3);
      modem_demodulate(demod, cframe[(1 << bps) * i + 3], &s4);
      byte ^= (unsigned char)(s1 << 6);
      byte ^= (unsigned char)(s2 << 4);
      byte ^= (unsigned char)(s3 << 2);
      byte ^= (unsigned char)(s4 << 0);
      fputc (byte, out);
    }

  fclose (out);

  free (cframe);

  modem_destroy (mod);
  modem_destroy (demod);

  free (din);
  
  return;
}