diff --git a/test/ofdmframe64.common.c b/test/ofdmframe64.common.c
deleted file mode 100644
index 91f9de6..0000000
--- a/test/ofdmframe64.common.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2007, 2009 Joseph Gaeddert
- * Copyright (c) 2007, 2009 Virginia Polytechnic Institute & State University
- *
- * This file is part of liquid.
- *
- * liquid is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * liquid is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with liquid. If not, see .
- */
-
-//
-// ofdmframe64 physical layer convergence procedure (PLCP) data
-//
-
-#include "liquid.experimental.h"
-#include "liquid.internal.h"
-
-int ofdmframe64_getsctype(unsigned int _id)
-{
- if (_id==0 || (_id>26 && _id<38))
- return OFDMFRAME64_SCTYPE_NULL;
- else if (_id==11 || _id==25 || _id==39 || _id==53)
- return OFDMFRAME64_SCTYPE_PILOT;
- else
- return OFDMFRAME64_SCTYPE_DATA;
-}
-
-// PLCP short sequence (frequency domain)
-const float complex ofdmframe64_plcp_Sf[64] = {
- 0.000000+ 0.000000*_Complex_I, 0.0f, 0.0f, 0.0f,
- -0.707110+ -0.707110*_Complex_I, 0.0f, 0.0f, 0.0f,
- -0.707110+ -0.707110*_Complex_I, 0.0f, 0.0f, 0.0f,
- 0.707110+ 0.707110*_Complex_I, 0.0f, 0.0f, 0.0f,
- 0.707110+ 0.707110*_Complex_I, 0.0f, 0.0f, 0.0f,
- 0.707110+ 0.707110*_Complex_I, 0.0f, 0.0f, 0.0f,
- 0.707110+ 0.707110*_Complex_I, 0.0f, 0.0f, 0.0f,
- 0.000000+ 0.000000*_Complex_I, 0.0f, 0.0f, 0.0f,
- 0.000000+ 0.000000*_Complex_I, 0.0f, 0.0f, 0.0f,
- 0.000000+ 0.000000*_Complex_I, 0.0f, 0.0f, 0.0f,
- 0.707110+ 0.707110*_Complex_I, 0.0f, 0.0f, 0.0f,
- -0.707110+ -0.707110*_Complex_I, 0.0f, 0.0f, 0.0f,
- 0.707110+ 0.707110*_Complex_I, 0.0f, 0.0f, 0.0f,
- -0.707110+ -0.707110*_Complex_I, 0.0f, 0.0f, 0.0f,
- -0.707110+ -0.707110*_Complex_I, 0.0f, 0.0f, 0.0f,
- 0.707110+ 0.707110*_Complex_I, 0.0f, 0.0f, 0.0f
-};
-
-// PLCP short sequence (time domain)
-const float complex ofdmframe64_plcp_St[64] = {
- 0.408250+ 0.408250*_Complex_I, -1.175500+ 0.020764*_Complex_I,
- -0.119570+ -0.696920*_Complex_I, 1.267000+ -0.112280*_Complex_I,
- 0.816500+ 0.000000*_Complex_I, 1.267000+ -0.112280*_Complex_I,
- -0.119570+ -0.696920*_Complex_I, -1.175500+ 0.020764*_Complex_I,
- 0.408250+ 0.408250*_Complex_I, 0.020764+ -1.175500*_Complex_I,
- -0.696920+ -0.119570*_Complex_I, -0.112280+ 1.267000*_Complex_I,
- 0.000000+ 0.816500*_Complex_I, -0.112280+ 1.267000*_Complex_I,
- -0.696920+ -0.119570*_Complex_I, 0.020764+ -1.175500*_Complex_I,
- 0.408250+ 0.408250*_Complex_I, -1.175500+ 0.020764*_Complex_I,
- -0.119570+ -0.696920*_Complex_I, 1.267000+ -0.112280*_Complex_I,
- 0.816500+ 0.000000*_Complex_I, 1.267000+ -0.112280*_Complex_I,
- -0.119570+ -0.696920*_Complex_I, -1.175500+ 0.020764*_Complex_I,
- 0.408250+ 0.408250*_Complex_I, 0.020764+ -1.175500*_Complex_I,
- -0.696920+ -0.119570*_Complex_I, -0.112280+ 1.267000*_Complex_I,
- 0.000000+ 0.816500*_Complex_I, -0.112280+ 1.267000*_Complex_I,
- -0.696920+ -0.119570*_Complex_I, 0.020764+ -1.175500*_Complex_I,
- 0.408250+ 0.408250*_Complex_I, -1.175500+ 0.020764*_Complex_I,
- -0.119570+ -0.696920*_Complex_I, 1.267000+ -0.112280*_Complex_I,
- 0.816500+ 0.000000*_Complex_I, 1.267000+ -0.112280*_Complex_I,
- -0.119570+ -0.696920*_Complex_I, -1.175500+ 0.020764*_Complex_I,
- 0.408250+ 0.408250*_Complex_I, 0.020764+ -1.175500*_Complex_I,
- -0.696920+ -0.119570*_Complex_I, -0.112280+ 1.267000*_Complex_I,
- 0.000000+ 0.816500*_Complex_I, -0.112280+ 1.267000*_Complex_I,
- -0.696920+ -0.119570*_Complex_I, 0.020764+ -1.175500*_Complex_I,
- 0.408250+ 0.408250*_Complex_I, -1.175500+ 0.020764*_Complex_I,
- -0.119570+ -0.696920*_Complex_I, 1.267000+ -0.112280*_Complex_I,
- 0.816500+ 0.000000*_Complex_I, 1.267000+ -0.112280*_Complex_I,
- -0.119570+ -0.696920*_Complex_I, -1.175500+ 0.020764*_Complex_I,
- 0.408250+ 0.408250*_Complex_I, 0.020764+ -1.175500*_Complex_I,
- -0.696920+ -0.119570*_Complex_I, -0.112280+ 1.267000*_Complex_I,
- 0.000000+ 0.816500*_Complex_I, -0.112280+ 1.267000*_Complex_I,
- -0.696920+ -0.119570*_Complex_I, 0.020764+ -1.175500*_Complex_I
-};
-
-// PLCP long sequence (frequency domain)
-const float complex ofdmframe64_plcp_Lf[64] = {
- 0.00, 1.00, -1.00, -1.00, 1.00, 1.00, -1.00, 1.00,
- -1.00, 1.00, -1.00, -1.00, -1.00, -1.00, -1.00, 1.00,
- 1.00, -1.00, -1.00, 1.00, -1.00, 1.00, -1.00, 1.00,
- 1.00, 1.00, 1.00, 0.00, 0.00, 0.00, 0.00, 0.00,
- 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 1.00, 1.00,
- -1.00, -1.00, 1.00, 1.00, -1.00, 1.00, -1.00, 1.00,
- 1.00, 1.00, 1.00, 1.00, 1.00, -1.00, -1.00, 1.00,
- 1.00, -1.00, 1.00, -1.00, 1.00, 1.00, 1.00, 1.00
-};
-
-// PLCP long sequence (time domain)
-const float complex ofdmframe64_plcp_Lt[64] = {
- 1.3868+ 0.0000*_Complex_I, -0.0455+ -1.0679*_Complex_I,
- 0.3528+ -0.9866*_Complex_I, 0.8594+ 0.7349*_Complex_I,
- 0.1874+ 0.2475*_Complex_I, 0.5310+ -0.7784*_Complex_I,
- -1.0218+ -0.4897*_Complex_I, -0.3401+ -0.9423*_Complex_I,
- 0.8657+ -0.2298*_Complex_I, 0.4734+ 0.0362*_Complex_I,
- 0.0088+ -1.0207*_Complex_I, -1.2142+ -0.4205*_Complex_I,
- 0.2172+ -0.5195*_Complex_I, 0.5207+ -0.1326*_Complex_I,
- -0.1995+ 1.4259*_Complex_I, 1.0583+ -0.0363*_Complex_I,
- 0.5547+ -0.5547*_Complex_I, 0.3276+ 0.8728*_Complex_I,
- -0.5077+ 0.3488*_Complex_I, -1.1650+ 0.5789*_Complex_I,
- 0.7297+ 0.8197*_Complex_I, 0.6173+ 0.1253*_Complex_I,
- -0.5353+ 0.7214*_Complex_I, -0.5010+ -0.1935*_Complex_I,
- -0.3110+ -1.3392*_Complex_I, -1.0818+ -0.1470*_Complex_I,
- -1.1300+ -0.1820*_Complex_I, 0.6663+ -0.6571*_Complex_I,
- -0.0249+ 0.4773*_Complex_I, -0.8155+ 1.0218*_Complex_I,
- 0.8140+ 0.9396*_Complex_I, 0.1090+ 0.8662*_Complex_I,
- -1.3868+ 0.0000*_Complex_I, 0.1090+ -0.8662*_Complex_I,
- 0.8140+ -0.9396*_Complex_I, -0.8155+ -1.0218*_Complex_I,
- -0.0249+ -0.4773*_Complex_I, 0.6663+ 0.6571*_Complex_I,
- -1.1300+ 0.1820*_Complex_I, -1.0818+ 0.1470*_Complex_I,
- -0.3110+ 1.3392*_Complex_I, -0.5010+ 0.1935*_Complex_I,
- -0.5353+ -0.7214*_Complex_I, 0.6173+ -0.1253*_Complex_I,
- 0.7297+ -0.8197*_Complex_I, -1.1650+ -0.5789*_Complex_I,
- -0.5077+ -0.3488*_Complex_I, 0.3276+ -0.8728*_Complex_I,
- 0.5547+ 0.5547*_Complex_I, 1.0583+ 0.0363*_Complex_I,
- -0.1995+ -1.4259*_Complex_I, 0.5207+ 0.1326*_Complex_I,
- 0.2172+ 0.5195*_Complex_I, -1.2142+ 0.4205*_Complex_I,
- 0.0088+ 1.0207*_Complex_I, 0.4734+ -0.0362*_Complex_I,
- 0.8657+ 0.2298*_Complex_I, -0.3401+ 0.9423*_Complex_I,
- -1.0218+ 0.4897*_Complex_I, 0.5310+ 0.7784*_Complex_I,
- 0.1874+ -0.2475*_Complex_I, 0.8594+ -0.7349*_Complex_I,
- 0.3528+ 0.9866*_Complex_I, -0.0455+ 1.0679*_Complex_I
-};
-
diff --git a/test/ofdmframe64.readme.txt b/test/ofdmframe64.readme.txt
deleted file mode 100644
index 56a13be..0000000
--- a/test/ofdmframe64.readme.txt
+++ /dev/null
@@ -1,109 +0,0 @@
-##
-## OFDM frame (64 subcarriers)
-##
-
-\section{General description}
-The ofdmframe64 describes a simple 802.11a-like PHY (physical layer)
-implementation. It consists of an orthogonal frequency-divisional
-multiplexing (OFDM) scheme with 64 subcarriers, 12 of which are
-disabled, and 4 are used as pilots.
-The cyclic prefix is fixed at 16 samples.
-The frame begins with a physical layer convergence procedure (PLCP)
-consisting of several short sequences
-(used for signal detection, and coarse frequency offset estimation)
-followed by several long sequences
-(used for timing acquisition, fine frequency offset estimation and
-channel estimation).
-The remainder of the frame consists of symbols with data stored on the
-remaining 48 subcarriers.
-
-
-\section{PLCP short sequences}
-The PLCP short sequences consist of a single OFDM symbol with 12
-subcarriers enabled.
-This corresponds to four repetitions in the time domain and is used
-primarily for signal detection and coarse carrier frequency offset
-estimation.
-The
-
- Sf(f)_{-26,26} = 1/sqrt(2)*{ 0, 0,
- 1+j, 0, 0, 0,
- -1-j, 0, 0, 0,
- 1+j, 0, 0, 0,
- -1-j, 0, 0, 0,
- -1-j, 0, 0, 0,
- 1+j, 0, 0, 0,
- 0, 0, 0, 0,
- -1-j, 0, 0, 0,
- -1-j, 0, 0, 0,
- 1+j, 0, 0, 0,
- 1+j, 0, 0, 0,
- 1+j, 0, 0, 0,
- 1+j, 0, 0 }
-
-with the time series transformed by
-
- St(t) = ifft( Sf(f) ) * sqrt(64*64/12)
-
-The scaling factor is used to ensure that the time series has a unity
-expected variance (corresponding to unity average power).
-
-\section{PLCP long sequences}
-
- Lf(f)_{-26,26} = { 1, 1,
- -1,-1, 1, 1,-1, 1,-1, 1,
- 1, 1, 1, 1, 1,-1,-1, 1,
- 1,-1, 1,-1, 1, 1, 1, 1,
- 0,
- 1,-1,-1, 1, 1,-1, 1,-1,
- 1,-1,-1,-1,-1,-1, 1, 1,
- -1,-1, 1,-1, 1,-1, 1, 1,
- 1, 1 }
-
-with the time series transformed by
-
- Lt(t) = ifft( Lf(f) ) / sqrt(64*64/52)
-
-\section{Pilot subcarriers}
-Pilot subcarriers are injected into data symbols at indices -21, -7,
-7, and 21.
-
-\section{Data symbols}
-
-\section{Synchronization Procedure}
-Synchronization is performed in several steps:
- - auto-correlate the received signal (delay of 16 samples) to find
- PLCP short sequence
- - once auto-correlation magnitude exceeds threshold, estimate
- coarse CFO ( nu_hat0 = arg(rxx)/16 ) and adjust input NCO
- - estimate coarse gain and lock AGC
- - cross-correlate received signal to find both PLCP long sequences
- - once both PLCP long sequences have been found, estimate channel
- gain (invert recevied symbol with known symbol), estimate fine
- CFO ( nu_hat1 = arg( ... ) /64 ) and adjust input NCO
-
-At this point the synchronizer is ready to receive data symbols.
-The procedure for extracting data symbols is as follows:
- - buffer 80 samples (64 + 16) and run FFT on last 64
- - apply channel subcarrier gain as determined by channel
- estimation procedure via PLCP long sequences
- - Extract pilot subcarriers {-21, -7, 7, 21} and de-rotate
- accoring to pilot P/N sequence
- - Unwrap phase of pilot subcarriers and fit to first-order
- polynomial; this corresponds to fractional sample timing offset
- - de-rotate phase of all data subcarriers according to polynomial
- fit of pilot phases
- - copy all 48 data subcarriers to buffer and invoke callback
-
-
-\section{MAC Data}
-
-octets: 2 2 6 6 6 2 6 0-2312 4
- +---------+---------+---------+---------+---------+---------+---------+---------+---------+
- | Frame |Duration/| Address | Address | Address | Sequence| Address | Frame | |
- | Control | ID | 1 | 2 | 3 | Control | 4 | Body | CRC |
- +---------+---------+---------+---------+---------+---------+---------+---------+---------+
- |<--- MAC Header --->|
-
-
-
diff --git a/test/ofdmframe64gen.c b/test/ofdmframe64gen.c
deleted file mode 100644
index 0bdfcf1..0000000
--- a/test/ofdmframe64gen.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (c) 2007, 2009 Joseph Gaeddert
- * Copyright (c) 2007, 2009 Virginia Polytechnic Institute & State University
- *
- * This file is part of liquid.
- *
- * liquid is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * liquid is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with liquid. If not, see .
- */
-
-//
-//
-//
-
-#include
-#include
-#include
-#include
-#include
-
-#include "liquid.experimental.h"
-#include "liquid.internal.h"
-
-#define DEBUG_OFDMFRAME64GEN 1
-
-struct ofdmframe64gen_s {
- unsigned int num_subcarriers;
- unsigned int cp_len;
-
- float complex * x; // time-domain buffer
- float complex * X; // freq-domain buffer
-
- // non-allocated pointers
- float complex * xcp; // cyclic prefix pointer
- float complex * St; // short PLCP array pointer (time-domain)
- float complex * Lt; // long PLCP array pointer (time-domain)
-
- msequence ms_pilot;
-
- FFT_PLAN fft;
-
- float zeta; // fft scaling factor
-};
-
-ofdmframe64gen ofdmframe64gen_create()
-{
- ofdmframe64gen q = (ofdmframe64gen) malloc(sizeof(struct ofdmframe64gen_s));
- q->num_subcarriers = 64;
- q->cp_len = 16;
-
- // allocate memory for buffers
- q->x = (float complex*) malloc((q->num_subcarriers)*sizeof(float complex));
- q->X = (float complex*) malloc((q->num_subcarriers)*sizeof(float complex));
-
- q->fft = FFT_CREATE_PLAN(q->num_subcarriers, q->X, q->x, FFT_DIR_BACKWARD, FFT_METHOD);
- q->zeta = sqrtf(1.0f / 52.0f); // sqrt((64/52)*(1/64)) : 52 subcarriers used
-
- // set cyclic prefix array pointer
- q->xcp = &(q->x[q->num_subcarriers - q->cp_len]);
- q->St = (float complex*) ofdmframe64_plcp_St;
- q->Lt = (float complex*) ofdmframe64_plcp_Lt;
-
- // set pilot sequence
- q->ms_pilot = msequence_create_default(8);
-
- return q;
-}
-
-void ofdmframe64gen_destroy(ofdmframe64gen _q)
-{
- free(_q->x);
- free(_q->X);
- msequence_destroy(_q->ms_pilot);
-
- FFT_DESTROY_PLAN(_q->fft);
-
- free(_q);
-}
-
-void ofdmframe64gen_print(ofdmframe64gen _q)
-{
- printf("ofdmframe64gen:\n");
- printf(" num subcarriers : %u\n", _q->num_subcarriers);
- printf(" cyclic prefix len : %u (%6.2f%%)\n",
- _q->cp_len,
- 100.0f*(float)(_q->cp_len)/(float)(_q->num_subcarriers));
-}
-
-void ofdmframe64gen_reset(ofdmframe64gen _q)
-{
- msequence_reset(_q->ms_pilot);
-}
-
-void ofdmframe64gen_writeshortsequence(ofdmframe64gen _q,
- float complex * _y)
-{
- // move cyclic prefix (double)
- memmove(_y+0, _q->St+32, 32*sizeof(float complex));
-
- // move remainder of signal (twice)
- memmove(_y+32, _q->St, 64*sizeof(float complex));
- memmove(_y+32+64, _q->St, 64*sizeof(float complex));
-}
-
-
-void ofdmframe64gen_writelongsequence(ofdmframe64gen _q,
- float complex * _y)
-{
- // move cyclic prefix (double)
- memmove(_y+0, _q->Lt+32, 32*sizeof(float complex));
-
- // move remainder of signal (twice)
- memmove(_y+32, _q->Lt, 64*sizeof(float complex));
- memmove(_y+32+64, _q->Lt, 64*sizeof(float complex));
-}
-
-void ofdmframe64gen_writeheader(ofdmframe64gen _q,
- float complex * _y)
-{
-}
-
-void ofdmframe64gen_writesymbol(ofdmframe64gen _q,
- float complex * _x,
- float complex * _y)
-{
- unsigned int pilot_phase = msequence_advance(_q->ms_pilot);
-
- // move frequency data to internal buffer
- unsigned int i, j=0;
- int sctype;
- for (i=0; i<64; i++) {
- sctype = ofdmframe64_getsctype(i);
- if (sctype==OFDMFRAME64_SCTYPE_NULL) {
- // disabled subcarrier
- _q->X[i] = 0.0f;
- } else if (sctype==OFDMFRAME64_SCTYPE_PILOT) {
- // pilot subcarrier
- _q->X[i] = (pilot_phase ? 1.0f : -1.0f) * _q->zeta;
- } else {
- // data subcarrier
- _q->X[i] = _x[j++] * _q->zeta;
- }
-
- //printf("X[%3u] = %12.8f + j*%12.8f;\n",i+1,crealf(_q->X[i]),cimagf(_q->X[i]));
- }
- assert(j==48);
-
- // execute inverse fft, store in buffer _q->x
- FFT_EXECUTE(_q->fft);
-
- // copy cyclic prefix
- memmove(_y, _q->xcp, (_q->cp_len)*sizeof(float complex));
-
- // copy remainder of signal
- memmove(&_y[_q->cp_len], _q->x, (_q->num_subcarriers)*sizeof(float complex));
-}
-
diff --git a/test/ofdmframe64sync.c b/test/ofdmframe64sync.c
deleted file mode 100644
index 6a11df9..0000000
--- a/test/ofdmframe64sync.c
+++ /dev/null
@@ -1,886 +0,0 @@
-/*
- * Copyright (c) 2007, 2009 Joseph Gaeddert
- * Copyright (c) 2007, 2009 Virginia Polytechnic Institute & State University
- *
- * This file is part of liquid.
- *
- * liquid is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * liquid is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with liquid. If not, see .
- */
-
-//
-//
-//
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "liquid.experimental.h"
-#include "liquid.internal.h"
-
-#define DEBUG_OFDMFRAME64SYNC 1
-#define DEBUG_OFDMFRAME64SYNC_PRINT 0
-#define DEBUG_OFDMFRAME64SYNC_FILENAME "ofdmframe64sync_internal_debug.m"
-#define DEBUG_OFDMFRAME64SYNC_BUFFER_LEN (1024)
-
-// auto-correlation integration length
-#define OFDMFRAME64SYNC_AUTOCORR_LEN (96)
-
-struct ofdmframe64sync_s {
- unsigned int num_subcarriers;
- unsigned int cp_len;
-
- // fast Fourier transform
- float complex * x; // FFT time-domain buffer
- float complex * X; // FFT freq-domain buffer
- FFT_PLAN fft;
-
- // initial gain correction / signal detection
- agc_crcf sigdet; // automatic gain control for signal detection
- float g; // flat gain estimation
-
- // equalization
- msequence ms_pilot; // P/N sequence pilot phase generator
- float complex G[64]; // complex channel gain correction
- float x_phase[4]; // pilot subcarrier index
- float y_phase[4]; // pilot subcarrier phase
- float p_phase[2]; // polynomial fit
-
- nco_crcf nco_pilot; // pilot phase nco
-
- float phi_prime; // previous average pilot phase
- float dphi; // differential pilot phase
- float m_prime; // previous phase slope
- float m_hat; // filtered phase slope
- unsigned int num_symbols_rx;
-
- // numerically-controlled oscillator for carrier offset correction
- nco_crcf nco_rx;
-
- // PLCP SHORT : delay correlator
- autocorr_cccf delay_correlator;
- float complex rxx_max;
-
- // PLCP LONG: cross correlator
- dotprod_cccf cross_correlator;
- float complex rxy;
- float complex rxy0;
- float complex rxy1;
- windowcf rxy_buffer;
- windowcf Lt_buffer;
- float complex Lt0[64], Lf0[64]; // received PLCP long sequence (first)
- float complex Lt1[64], Lf1[64]; // received PLCP long sequence (second)
- float complex G0[64], G1[64];
- int backoff;
- float complex B[64]; // subcarrier phase rotation due to backoff
-
- // timer
- unsigned int timer;
- float complex symbol[80]; // symbol data buffer
- float complex data[48]; // synchronized data subcarriers
-
- float nu_hat0; // carrier frequency offset estimation (coarse)
- float nu_hat1; // carrier frequency offset estimation (fine)
-
- // callback function and scaling factor
- ofdmframe64sync_callback callback;
- void * userdata;
-
- // receiver state
- enum {
- OFDMFRAME64SYNC_STATE_PLCPSHORT=0, // seek PLCP short sequence
- OFDMFRAME64SYNC_STATE_PLCPLONG0, // seek first PLCP long seq.
- OFDMFRAME64SYNC_STATE_PLCPLONG1, // seek second PLCP long seq.
- OFDMFRAME64SYNC_STATE_RXPAYLOAD // receive payload symbols
- } state;
-
-#if DEBUG_OFDMFRAME64SYNC
- windowcf debug_x;
- windowcf debug_rxx;
- windowcf debug_rxy;
- windowcf debug_framesyms;
- windowf debug_pilotphase;
- windowf debug_pilotphase_hat;
-#endif
-};
-
-ofdmframe64sync ofdmframe64sync_create(ofdmframe64sync_callback _callback,
- void * _userdata)
-{
- ofdmframe64sync q = (ofdmframe64sync) malloc(sizeof(struct ofdmframe64sync_s));
- q->num_subcarriers = 64;
- q->cp_len = 16;
-
- // allocate memory for buffers
- q->x = (float complex*) malloc((q->num_subcarriers)*sizeof(float complex));
- q->X = (float complex*) malloc((q->num_subcarriers)*sizeof(float complex));
-
- q->fft = FFT_CREATE_PLAN(q->num_subcarriers, q->x, q->X, FFT_DIR_FORWARD, FFT_METHOD);
-
- // initial gain correction / signal detection
- q->sigdet = agc_crcf_create();
- agc_crcf_set_target(q->sigdet,1.0f);
- agc_crcf_set_bandwidth(q->sigdet,0.1f);
-
- // carrier offset correction
- q->nco_rx = nco_crcf_create(LIQUID_VCO);
- q->nco_pilot = nco_crcf_create(LIQUID_VCO);
- nco_crcf_pll_set_bandwidth(q->nco_pilot,0.01f);
-
- // cyclic prefix correlation windows
- q->delay_correlator = autocorr_cccf_create(OFDMFRAME64SYNC_AUTOCORR_LEN,16);
-
- // cross-correlator
- unsigned int i;
- float complex h[64];
- for (i=0; i<64; i++)
- h[i] = conjf(ofdmframe64_plcp_Lt[i]);
- q->cross_correlator = dotprod_cccf_create(h,64);
- q->rxy_buffer = windowcf_create(64);
- q->Lt_buffer = windowcf_create(160);
-
-#if DEBUG_OFDMFRAME64SYNC
- q->debug_x = windowcf_create(DEBUG_OFDMFRAME64SYNC_BUFFER_LEN);
- q->debug_rxx = windowcf_create(DEBUG_OFDMFRAME64SYNC_BUFFER_LEN);
- q->debug_rxy = windowcf_create(DEBUG_OFDMFRAME64SYNC_BUFFER_LEN);
- q->debug_framesyms = windowcf_create(DEBUG_OFDMFRAME64SYNC_BUFFER_LEN);
- q->debug_pilotphase = windowf_create(DEBUG_OFDMFRAME64SYNC_BUFFER_LEN);
- q->debug_pilotphase_hat = windowf_create(DEBUG_OFDMFRAME64SYNC_BUFFER_LEN);
-#endif
-
- // pilot sequence generator
- q->ms_pilot = msequence_create_default(8);
- q->x_phase[0] = -21.0f;
- q->x_phase[1] = -7.0f;
- q->x_phase[2] = 7.0f;
- q->x_phase[3] = 21.0f;
-
- q->backoff = 2;
- float phi = (float)(q->backoff)*2.0f*M_PI/64.0f;
- for (i=0; i<64; i++)
- q->B[i] = liquid_cexpjf(i*phi);
-
- q->callback = _callback;
- q->userdata = _userdata;
-
- ofdmframe64sync_reset(q);
-
- return q;
-}
-
-void ofdmframe64sync_destroy(ofdmframe64sync _q)
-{
-#if DEBUG_OFDMFRAME64SYNC
- ofdmframe64sync_debug_print(_q);
- windowcf_destroy(_q->debug_x);
- windowcf_destroy(_q->debug_rxx);
- windowcf_destroy(_q->debug_rxy);
- windowcf_destroy(_q->debug_framesyms);
- windowf_destroy(_q->debug_pilotphase);
- windowf_destroy(_q->debug_pilotphase_hat);
-#endif
-
- free(_q->x);
- free(_q->X);
- windowcf_destroy(_q->rxy_buffer);
- windowcf_destroy(_q->Lt_buffer);
- FFT_DESTROY_PLAN(_q->fft);
-
- agc_crcf_destroy(_q->sigdet);
- msequence_destroy(_q->ms_pilot);
- autocorr_cccf_destroy(_q->delay_correlator);
- dotprod_cccf_destroy(_q->cross_correlator);
- nco_crcf_destroy(_q->nco_rx);
- nco_crcf_destroy(_q->nco_pilot);
- free(_q);
-}
-
-void ofdmframe64sync_print(ofdmframe64sync _q)
-{
- printf("ofdmframe64sync:\n");
-}
-
-void ofdmframe64sync_reset(ofdmframe64sync _q)
-{
- // reset pilot sequence generator
- msequence_reset(_q->ms_pilot);
-
- _q->g = 1.0f;
- agc_crcf_reset(_q->sigdet);
- _q->state = OFDMFRAME64SYNC_STATE_PLCPSHORT;
- autocorr_cccf_clear(_q->delay_correlator);
- _q->rxx_max = 0.0f;
- nco_crcf_set_frequency(_q->nco_rx, 0.0f);
- nco_crcf_set_phase(_q->nco_rx, 0.0f);
- nco_crcf_reset(_q->nco_pilot);
-
- // reset symbol timer
- _q->timer = 0;
-
- _q->num_symbols_rx = 0;
- _q->phi_prime = 0.0f;
- _q->dphi = 0.0f;
- _q->m_hat = 0.0f;
- _q->m_prime = 0.0f;
-
-#if 0
- unsigned int i;
- for (i=0; i<64; i++) {
- // clear PLCP long buffers
- _q->Lt0[i] = 0.0f;
- _q->Lt1[i] = 0.0f;
-
- // reset gain
- _q->G[i] = 1.0f;
- }
-#endif
-}
-
-void ofdmframe64sync_execute(ofdmframe64sync _q,
- float complex * _x,
- unsigned int _n)
-{
- unsigned int i;
- float complex x;
- for (i=0; i<_n; i++) {
- x = _x[i];
-#if DEBUG_OFDMFRAME64SYNC
- windowcf_push(_q->debug_x,x);
-#endif
-
- // coarse gain correction
- x *= _q->g;
-
- // carrier frequency offset estimation
- nco_crcf_mix_up(_q->nco_rx, x, &x);
-
- switch (_q->state) {
- case OFDMFRAME64SYNC_STATE_PLCPSHORT:
- ofdmframe64sync_execute_plcpshort(_q,x);
- break;
- case OFDMFRAME64SYNC_STATE_PLCPLONG0:
- ofdmframe64sync_execute_plcplong0(_q,x);
- break;
- case OFDMFRAME64SYNC_STATE_PLCPLONG1:
- ofdmframe64sync_execute_plcplong1(_q,x);
- break;
- case OFDMFRAME64SYNC_STATE_RXPAYLOAD:
- ofdmframe64sync_execute_rxpayload(_q,x);
- break;
- default:;
- }
- }
-}
-
-//
-// internal
-//
-
-void ofdmframe64sync_debug_print(ofdmframe64sync _q)
-{
-#if DEBUG_OFDMFRAME64SYNC
- FILE * fid = fopen(DEBUG_OFDMFRAME64SYNC_FILENAME,"w");
- if (!fid) {
- fprintf(stderr,"error: ofdmframe64_debug_print(), could not open file for writing\n");
- exit(1);
- }
- fprintf(fid,"%% %s : auto-generated file\n", DEBUG_OFDMFRAME64SYNC_FILENAME);
- fprintf(fid,"close all;\n");
- fprintf(fid,"clear all;\n");
- fprintf(fid,"n = %u;\n", DEBUG_OFDMFRAME64SYNC_BUFFER_LEN);
- unsigned int i;
- float complex * rc;
-
- fprintf(fid,"nu_hat = %12.4e;\n", _q->nu_hat0 + _q->nu_hat1);
-
- // gain vectors
- for (i=0; i<64; i++) {
- fprintf(fid,"G(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(_q->G[i]), cimagf(_q->G[i]));
- fprintf(fid,"G0(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(_q->G0[i]), cimagf(_q->G0[i]));
- fprintf(fid,"G1(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(_q->G1[i]), cimagf(_q->G1[i]));
- }
-
- fprintf(fid,"x = zeros(1,n);\n");
- windowcf_read(_q->debug_x, &rc);
- for (i=0; idebug_rxx, &rc);
- for (i=0; idebug_rxy, &rc);
- for (i=0; iLt0[i]), cimagf(_q->Lt0[i]));
- fprintf(fid,"Lf0(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(_q->Lf0[i]), cimagf(_q->Lf0[i]));
- fprintf(fid,"Lt1(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(_q->Lt1[i]), cimagf(_q->Lt1[i]));
- fprintf(fid,"Lf1(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(_q->Lf1[i]), cimagf(_q->Lf1[i]));
- }
- //fprintf(fid,"Lf0 = fft(Lt0).*G;\n");
- //fprintf(fid,"Lf1 = fft(Lt1).*G;\n");
- fprintf(fid,"figure;\n");
- fprintf(fid,"plot(real(Lf0(s)),imag(Lf0(s)),'x','MarkerSize',1,...\n");
- fprintf(fid," real(Lf1(s)),imag(Lf1(s)),'x','MarkerSize',1);\n");
- fprintf(fid,"axis square;\n");
- fprintf(fid,"axis([-1.5 1.5 -1.5 1.5]);\n");
- fprintf(fid,"xlabel('in-phase');\n");
- fprintf(fid,"ylabel('quadrature phase');\n");
- fprintf(fid,"title('PLCP Long Sequence (after gain correction)');\n");
-
- // plot gain vectors
- fprintf(fid,"f = [-32:31];\n");
- fprintf(fid,"figure;\n");
- fprintf(fid,"subplot(2,1,1);\n");
- fprintf(fid," plot(f,fftshift(abs(G0)),f,fftshift(abs(G1)),f,fftshift(abs(G)));\n");
- fprintf(fid," ylabel('gain');\n");
- fprintf(fid,"subplot(2,1,2);\n");
- fprintf(fid," plot(f,unwrap(fftshift(arg(G0))),...\n");
- fprintf(fid," f,unwrap(fftshift(arg(G1))),...\n");
- fprintf(fid," f,unwrap(fftshift(arg(G))));\n");
- fprintf(fid," ylabel('phase');\n");
-
- // frame symbols
- fprintf(fid,"framesyms = zeros(1,n);\n");
- windowcf_read(_q->debug_framesyms, &rc);
- for (i=0; idebug_pilotphase, &r);
- for (i=0; idebug_pilotphase_hat, &r);
- for (i=0; isigdet, _x, &y);
- //if (agc_crcf_get_signal_level(_q->sigdet) < -15.0f)
- // return;
- if (cabsf(y) > 2.0f)
- y = 2.0f*liquid_cexpjf(cargf(y));
-
- // run auto-correlator
- float complex rxx;
- autocorr_cccf_push(_q->delay_correlator, y);
- autocorr_cccf_execute(_q->delay_correlator, &rxx);
-
-#if DEBUG_OFDMFRAME64SYNC
- windowcf_push(_q->debug_rxx,rxx);
-#endif
-
- if (cabsf(rxx) > 0.75f*OFDMFRAME64SYNC_AUTOCORR_LEN) {
- // TODO : wait for auto-correlation to peak before changing state
-
-#if DEBUG_OFDMFRAME64SYNC_PRINT
- printf("rxx = %12.8f (angle : %12.8f);\n", cabsf(rxx),cargf(rxx)/16.0f);
-#endif
- _q->nu_hat0 = -cargf(rxx)/16.0f;
- nco_crcf_set_frequency(_q->nco_rx, -cargf(rxx)/16.0f);
- _q->state = OFDMFRAME64SYNC_STATE_PLCPLONG0;
- _q->timer = 0;
- _q->g = agc_crcf_get_gain(_q->sigdet);
- }
-}
-
-void ofdmframe64sync_execute_plcplong0(ofdmframe64sync _q,
- float complex _x)
-{
- // run cross-correlator
- float complex rxy, *rc;
- windowcf_push(_q->Lt_buffer, _x);
- windowcf_push(_q->rxy_buffer, _x);
- windowcf_read(_q->rxy_buffer, &rc);
- dotprod_cccf_execute(_q->cross_correlator, rc, &rxy);
-
-#if DEBUG_OFDMFRAME64SYNC
- windowcf_push(_q->debug_rxy,rxy);
-#endif
-
- _q->timer++;
-
- if (cabsf(rxy) > 48.0f) {
-#if DEBUG_OFDMFRAME64SYNC_PRINT
- printf("rxy = %12.8f (angle : %12.8f);\n", cabsf(rxy),cargf(rxy));
-#endif
- //nco_crcf_set_phase(_q->nco_rx, -cargf(rxy));
-
- // store sequence
- // TODO : back off PLCP long by a sample or 2 to help ensure no ISI
- //memmove(_q->Lt0, rc, 64*sizeof(float complex));
-
- _q->state = OFDMFRAME64SYNC_STATE_PLCPLONG1;
- _q->timer = 0;
- }
-
- if (_q->timer > 320)
- ofdmframe64sync_reset(_q);
-}
-
-void ofdmframe64sync_execute_plcplong1(ofdmframe64sync _q,
- float complex _x)
-{
- // push sample into cross-correlator buffer
- float complex rxy, *rc;
- windowcf_push(_q->Lt_buffer, _x);
- windowcf_push(_q->rxy_buffer, _x);
-
-#if DEBUG_OFDMFRAME64SYNC
- windowcf_read(_q->rxy_buffer, &rc);
- dotprod_cccf_execute(_q->cross_correlator, rc, &rxy);
- windowcf_push(_q->debug_rxy,rxy);
-#endif
-
- _q->timer++;
- if (_q->timer < 64)
- return;
-
- // reset timer
- _q->timer = 0;
-
- // run cross-correlator
- // TODO : back off PLCP long by a sample or 2 to help ensure no ISI
- windowcf_read(_q->rxy_buffer, &rc);
- dotprod_cccf_execute(_q->cross_correlator, rc, &rxy);
-
- // at this point we expect the cross-correlator output to be
- // high; if it's not, then the symbol
-
- if (cabsf(rxy) > 48.0f) {
-#if DEBUG_OFDMFRAME64SYNC_PRINT
- printf("rxy = %12.8f (angle : %12.8f);\n", cabsf(rxy),cargf(rxy));
-#endif
-
- // store sequence
- //memmove(_q->Lt1, rc, 64*sizeof(float complex));
- windowcf_read(_q->Lt_buffer, &rc);
- // estimate frequency offset
- unsigned int j;
- float complex rxx=0.0f;
- for (j=0; j<32+64; j++)
- rxx += rc[j] * conj(rc[j+64]);
- _q->nu_hat1 = cargf(rxx)/64.0f;
- // correct frequency offset
- float theta=0.0f;
- for (j=0; j<160; j++) {
- rc[j] *= liquid_cexpjf(theta);
- theta += _q->nu_hat1;
- }
- // compute cross-correlation
- dotprod_cccf_execute(_q->cross_correlator, rc+32, &_q->rxy0);
- dotprod_cccf_execute(_q->cross_correlator, rc+32+64, &_q->rxy1);
-#if DEBUG_OFDMFRAME64SYNC_PRINT
- printf("|rxy0| = %12.8f\n", cabsf(_q->rxy0));
- printf("|rxy1| = %12.8f\n", cabsf(_q->rxy1));
-#endif
-
- memmove(_q->Lt0, rc+32-_q->backoff, 64*sizeof(float complex));
- memmove(_q->Lt1, rc+32+64-_q->backoff, 64*sizeof(float complex));
-
- // correct phase term, backoff
- float theta0 = cargf(_q->rxy0);
- float theta1 = cargf(_q->rxy1);
- for (j=0; j<64; j++) {
- _q->Lt0[j] *= liquid_cexpjf(theta0);
- _q->Lt1[j] *= liquid_cexpjf(theta1);
- //theta0 += -2.0f*M_PI*(float)(backoff)/64.0f;
- //theta1 += -2.0f*M_PI*(float)(backoff)/64.0f;
- }
-
- // run fine CFO estimation and correct offset for
- // PLCP long sequences
- //ofdmframe64sync_estimate_cfo_plcplong(_q);
- nco_crcf_adjust_frequency(_q->nco_rx, _q->nu_hat1);
-#if DEBUG_OFDMFRAME64SYNC_PRINT
- printf("nu_hat0 = %12.8f;\n", _q->nu_hat0);
- printf("nu_hat1 = %12.8f;\n", _q->nu_hat1);
- printf("nu_hat = %12.8f;\n", _q->nco_rx->d_theta);
-#endif
- //ofdmframe64sync_correct_cfo_plcplong(_q);
-
- // compute DFT, estimate channel gains
- // TODO : determine when synchronizer should use flat gain estimation
- ofdmframe64sync_estimate_gain_plcplong(_q);
- //ofdmframe64sync_estimate_gain_plcplong_flat(_q);
-
- // change state
- _q->state = OFDMFRAME64SYNC_STATE_RXPAYLOAD;
- } else {
- // cross-correlator output not sufficiently high: reset synchronizer
- ofdmframe64sync_reset(_q);
- }
-}
-
-void ofdmframe64sync_compute_plcplong0(ofdmframe64sync _q)
-{
- // first PLCP long sequence
- memmove(_q->x, _q->Lt0, 64*sizeof(float complex));
- FFT_EXECUTE(_q->fft);
- memmove(_q->Lf0, _q->X, 64*sizeof(float complex));
-}
-
-void ofdmframe64sync_compute_plcplong1(ofdmframe64sync _q)
-{
- // second PLCP long sequence
- memmove(_q->x, _q->Lt1, 64*sizeof(float complex));
- FFT_EXECUTE(_q->fft);
- memmove(_q->Lf1, _q->X, 64*sizeof(float complex));
-}
-
-void ofdmframe64sync_estimate_gain_plcplong(ofdmframe64sync _q)
-{
- // compute FFT on PLCP long sequences
- ofdmframe64sync_compute_plcplong0(_q);
- ofdmframe64sync_compute_plcplong1(_q);
-
- unsigned int i;
- float g0, theta0;
- float g1, theta1;
- for (i=0; i<64; i++) {
- if (i==0 || (i>26 && i<38)) {
- // disabled subcarrier
- _q->G0[i] = 0.0f;
- _q->G1[i] = 0.0f;
- _q->G[i] = 0.0f;
- } else {
- // compute subcarrier gains
- _q->G0[i] = 1.0f / (_q->Lf0[i] * _q->B[i] * conj(ofdmframe64_plcp_Lf[i]));
- _q->G1[i] = 1.0f / (_q->Lf1[i] * _q->B[i] * conj(ofdmframe64_plcp_Lf[i]));
-
- // average amplitude, phase of subcarrier gains (note
- // that residual phase offset is taken care of by pilot
- // subcarriers)
- g0 = cabsf(_q->G0[i]);
- g1 = cabsf(_q->G1[i]);
- theta0 = cargf(_q->G0[i]);
- theta1 = cargf(_q->G1[i]);
- if (theta0 < 0) theta0 += 2.0f*M_PI; // ensure 0 <= theta0 <= 2*pi
- if (theta1 < 0) theta1 += 2.0f*M_PI; // ensure 0 <= theta0 <= 2*pi
-#if 1
- // average amplitude and phase
- _q->G[i] = 0.5f*(g0+g1)*liquid_cexpjf(0.5f*(theta0+theta1));
-#else
- // average amplitude; retain phase from first estimate
- _q->G[i] = 0.5f*(g0+g1)*liquid_cexpjf(theta0);
-#endif
- //_q->G[i] = _q->G0[i]; // use only first estimate
- }
- }
-
- // TODO: choose smoothing factor and range appropriately
- ofdmframe64sync_smooth_gain(_q, 0.8f, 6);
-
-#if DEBUG_OFDMFRAME64SYNC
- // correct long sequence (plotting purposes only)
- for (i=0; i<64; i++) {
- _q->Lf0[i] *= _q->G[i]*_q->B[i];
- _q->Lf1[i] *= _q->G[i]*_q->B[i];
- }
-#endif
-}
-
-// smooth subcarrier gains
-void ofdmframe64sync_smooth_gain(ofdmframe64sync _q,
- float _alpha,
- unsigned int _range)
-{
- if (_range == 0)
- return;
-
- // validate inputs
- if (_alpha < 0.0f) {
- fprintf(stderr,"error: ofdmframe64sync_smooth_gain(), smoothing factor is negative\n");
- exit(1);
- } else if (_range > 32) {
- fprintf(stderr,"error: ofdmframe64sync_smooth_gain(), range is too large\n");
- exit(1);
- }
-
- float complex G_hat[64];// temporary gain array
- float w; // weighting factor
- float w_total; // sum weighting factor
- int t = (int)(_range); // subcarrier smoothing bound
- int j; // subcarrier distance index
- unsigned int n; // subcarrier index
- int sctype;
- unsigned int i;
- for (i=0; i<64; i++) {
- G_hat[i] = 0.0f;
- sctype = ofdmframe64_getsctype(i);
- if (sctype != OFDMFRAME64_SCTYPE_NULL) {
- // average adjacent subcarrier gains (smoothing)
- w_total = 0.0f;
- for (j=-t; j<=t; j++) {
- // compute subcarrier index
- n = (i+j+64)%64;
-
- // ignore null subcarriers
- if (ofdmframe64_getsctype(n) == OFDMFRAME64_SCTYPE_NULL)
- continue;
-
- // compute weighting factor
- w = expf(-_alpha*fabsf(j*j));
- w_total += w;
-
- // average gain
- G_hat[i] += _q->G[n] * w;
- }
- G_hat[i] /= w_total;
- }
-
- // set new, smoothed gain value
- _q->G[i] = G_hat[i];
- }
-}
-
-void ofdmframe64sync_estimate_gain_plcplong_flat(ofdmframe64sync _q)
-{
- // compute FFT on PLCP long sequences
- ofdmframe64sync_compute_plcplong0(_q);
- ofdmframe64sync_compute_plcplong1(_q);
-
- unsigned int i;
- int sctype;
- float g=0.0f;
- for (i=0; i<64; i++) {
- sctype = ofdmframe64_getsctype(i);
- if (sctype != OFDMFRAME64_SCTYPE_NULL) {
-#if DEBUG_OFDMFRAME64SYNC
- // compute individual subcarrier gain, compensating for
- // fft backoff (plotting purposes only)
- _q->G0[i] = 1.0f / (_q->Lf0[i] * _q->B[i] * conj(ofdmframe64_plcp_Lf[i]));
- _q->G1[i] = 1.0f / (_q->Lf1[i] * _q->B[i] * conj(ofdmframe64_plcp_Lf[i]));
-#endif
-
- // average amplitude of subcarriers (note that residual
- // phase offset is taken care of by pilot subcarriers)
- g += cabsf(_q->Lf0[i]) + cabsf(_q->Lf1[i]);
- } else {
- _q->G0[i] = 0.0f;
- _q->G1[i] = 0.0f;
- }
- }
-
- // average signal level over all 52 enabled subcarriers (both
- // PLCP long sequences), invert
- g = (2.0f * 52.0f) / g;
-
- for (i=0; i<64; i++) {
- // compute flat subcarrier gain
- _q->G[i] = g;
-#if DEBUG_OFDMFRAME64SYNC
- // correct long sequence (plotting purposes only)
- // compensating for fft timing backoff
- _q->Lf0[i] *= _q->G[i]*_q->B[i];
- _q->Lf1[i] *= _q->G[i]*_q->B[i];
-#endif
- }
-}
-
-void ofdmframe64sync_estimate_cfo_plcplong(ofdmframe64sync _q)
-{
- float complex r=0.0f;
- unsigned int i;
- for (i=0; i<64; i++)
- r += _q->Lt0[i] * conjf(_q->Lt1[i]);
-
- _q->nu_hat1 = cargf(r) / 64.0f;
-}
-
-void ofdmframe64sync_correct_cfo_plcplong(ofdmframe64sync _q)
-{
- // mix Lt0,Lt1 by nu_hat1 (compensate for fine CFO estimation)
- unsigned int i;
- float theta=0.0f;
- for (i=0; i<64; i++) {
- _q->Lt0[i] *= liquid_cexpjf(theta);
- _q->Lt1[i] *= liquid_cexpjf(theta);
- theta += _q->nu_hat1;
- }
-}
-
-void ofdmframe64sync_execute_rxpayload(ofdmframe64sync _q, float complex _x)
-{
- _q->symbol[_q->timer] = _x;
- _q->timer++;
- if (_q->timer < 80)
- return;
-
- // reset timer
- _q->timer = 0;
-
- // copy buffer and execute FFT
- // NOTE: the -1 is used for backoff to help ensure that the FFT window
- // does not overlap the next OFDM symbol
- // TODO: compensate equalizer phase for timing backoff
- memmove(_q->x, _q->symbol+_q->cp_len-_q->backoff, 64*sizeof(float complex));
- FFT_EXECUTE(_q->fft);
-
- // gain correction (equalizer)
- unsigned int i;
- for (i=0; i<64; i++) {
- _q->X[i] *= _q->G[i]*_q->B[i];
- }
-
- // pilot phase correction
- unsigned int pilot_phase = msequence_advance(_q->ms_pilot);
- float complex p = pilot_phase ? 1.0f : -1.0f;
-
- _q->y_phase[0] = cargf(_q->X[11]*conjf(p)); // -21
- _q->y_phase[1] = cargf(_q->X[25]*conjf(p)); // -7
- _q->y_phase[2] = cargf(_q->X[39]*conjf(p)); // 7
- _q->y_phase[3] = cargf(_q->X[53]*conjf(p)); // 21
-
- // try to unwrap phase
- for (i=1; i<4; i++) {
- while ((_q->y_phase[i] - _q->y_phase[i-1]) > M_PI)
- _q->y_phase[i] -= 2*M_PI;
- while ((_q->y_phase[i] - _q->y_phase[i-1]) < -M_PI)
- _q->y_phase[i] += 2*M_PI;
- }
-
- // fit phase to 1st-order polynomial (2 coefficients)
- polyf_fit(_q->x_phase, _q->y_phase, 4, _q->p_phase, 2);
-
- float theta_hat = nco_crcf_get_phase(_q->nco_pilot);
- float phase_error = _q->p_phase[0] - theta_hat;
- nco_crcf_pll_step(_q->nco_pilot, phase_error);
- nco_crcf_step(_q->nco_pilot);
-
-#if DEBUG_OFDMFRAME64SYNC
- windowf_push(_q->debug_pilotphase, _q->p_phase[0]);
- windowf_push(_q->debug_pilotphase_hat, theta_hat);
-#endif
-
- // extract average pilot phase difference and unwrap
- _q->dphi = _q->num_symbols_rx == 0 ? 0.0f : _q->p_phase[0] - _q->phi_prime;
- while (_q->dphi > M_PI) _q->dphi -= 2.0f*M_PI;
- while (_q->dphi < -M_PI) _q->dphi += 2.0f*M_PI;
- _q->phi_prime = _q->p_phase[0];
-
- /*
- printf("phi(%3u) = %12.8f; dphi(%3u) = %12.8f;\n", _q->num_symbols_rx+1,
- _q->phi_prime,
- _q->num_symbols_rx+1,
- _q->dphi);
- */
- // adjust nco frequency based on some small percentage of
- // the differential average pilot phase
- nco_crcf_adjust_frequency(_q->nco_rx, -0.1f*_q->dphi / 64.0f);
-
- // filter phase slope
- float zeta = 0.02f;
- _q->m_hat = zeta*_q->m_prime + (1.0f - zeta)*_q->m_hat;
- _q->m_prime = _q->p_phase[1];
- _q->p_phase[1] = _q->m_hat;
- //printf("p(%3u) = %12.8f;\n", _q->num_symbols_rx+1, _q->p_phase[1]);
-
- // compensate for phase/time shift
- float theta;
- /*
- _q->p_phase[0] = theta_hat;
- _q->p_phase[1] = 0.0f;
- */
- for (i=0; i<64; i++) {
- theta = polyf_val(_q->p_phase, 2, (float)(i)-32.0f);
- _q->X[i] *= liquid_cexpjf(-theta);
- }
- nco_crcf_step(_q->nco_pilot);
-
- // TODO: perform additional polynomial gain compensation
-
- // strip data subcarriers
- unsigned int j=0;
- int sctype;
- for (i=0; i<64; i++) {
- sctype = ofdmframe64_getsctype(i);
- if (sctype==OFDMFRAME64_SCTYPE_NULL) {
- // disabled subcarrier
- } else if (sctype==OFDMFRAME64_SCTYPE_PILOT) {
- // pilot subcarrier : use p/n sequence for pilot phase
- } else {
- // data subcarrier
- _q->data[j++] = _q->X[i];
- }
-
- }
- assert(j==48);
-
- _q->num_symbols_rx++;
-
-#if DEBUG_OFDMFRAME64SYNC
- for (i=0; i<48; i++)
- windowcf_push(_q->debug_framesyms,_q->data[i]);
-#endif
-
- if (_q->callback != NULL) {
- int retval = _q->callback(_q->data, _q->userdata);
- if (retval == -1) {
- printf("exiting prematurely\n");
- ofdmframe64sync_destroy(_q);
- exit(0);
- } else if (retval == 1) {
-#if DEBUG_OFDMFRAME64SYNC_PRINT
- printf("resetting synchronizer\n");
-#endif
- ofdmframe64sync_reset(_q);
- } else {
- // do nothing
- }
- }
-}
-