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 - } - } -} -