コード例 #1
0
// Helper function to keep code base small
void polyf_fit_bench(struct rusage *_start,
                     struct rusage *_finish,
                     unsigned long int *_num_iterations,
                     unsigned int _Q,
                     unsigned int _N)
{
    // normalize number of iterations
    // time ~ 0.2953 + 0.03381 * _N
    *_num_iterations /= 0.2953 + 0.03381 * _N;
    if (*_num_iterations < 1) *_num_iterations = 1;

    float p[_Q+1];

    float x[_N];
    float y[_N];
    unsigned int i;
    for (i=0; i<_N; i++) {
        x[i] = randnf();
        y[i] = randnf();
    }
    
    // start trials
    getrusage(RUSAGE_SELF, _start);
    for (i=0; i<(*_num_iterations); i++) {
        polyf_fit(x,y,_N, p,_Q+1);
        polyf_fit(x,y,_N, p,_Q+1);
        polyf_fit(x,y,_N, p,_Q+1);
        polyf_fit(x,y,_N, p,_Q+1);
    }
    getrusage(RUSAGE_SELF, _finish);
    *_num_iterations *= 4;
}
コード例 #2
0
ファイル: wlanframesync.c プロジェクト: pk-mds/liquid-wlan
// recover symbol, correcting for gain, pilot phase, etc.
void wlanframesync_rxsymbol(wlanframesync _q)
{
    // apply gain
    unsigned int i;
    for (i=0; i<64; i++)
        _q->X[i] *= _q->R[i];

    // polynomial curve-fit
    float x_phase[4] = {-21.0f, -7.0f, 7.0f, 21.0f};
    float y_phase[4];
    float p_phase[2];

    // update pilot phase
    unsigned int pilot_phase = wlan_lfsr_advance(_q->ms_pilot);

    y_phase[0] = pilot_phase ? cargf(-_q->X[43]) : cargf( _q->X[43]);
    y_phase[1] = pilot_phase ? cargf(-_q->X[57]) : cargf( _q->X[57]);
    y_phase[2] = pilot_phase ? cargf(-_q->X[ 7]) : cargf( _q->X[ 7]);
    y_phase[3] = pilot_phase ? cargf( _q->X[21]) : cargf(-_q->X[21]);

    // unwrap phase
    if ( (y_phase[1]-y_phase[0]) >  M_PI ) y_phase[1] -= 2*M_PI;
    if ( (y_phase[1]-y_phase[0]) < -M_PI ) y_phase[1] += 2*M_PI;

    if ( (y_phase[2]-y_phase[1]) >  M_PI ) y_phase[2] -= 2*M_PI;
    if ( (y_phase[2]-y_phase[1]) < -M_PI ) y_phase[2] += 2*M_PI;

    if ( (y_phase[3]-y_phase[2]) >  M_PI ) y_phase[3] -= 2*M_PI;
    if ( (y_phase[3]-y_phase[2]) < -M_PI ) y_phase[3] += 2*M_PI;

#if 0
    printf("    x = [-21 -7 7 21]; y = [%6.3f %6.3f %6.3f %6.3f];\n", y_phase[0], y_phase[1], y_phase[2], y_phase[3]);
#endif

    // fit phase to 1st-order polynomial (2 coefficients)
    polyf_fit(x_phase, y_phase, 4, p_phase, 2);

    // compensate for phase offset
    // TODO : find more computationally efficient way to do this
    for (i=0; i<64; i++) {
        float fx    = (i > 31) ? (float)i - (float)(64) : (float)i;
        float theta = polyf_val(p_phase, 2, fx);
        _q->X[i] *= cexpf(-_Complex_I*theta);
    }

    // adjust NCO frequency based on differential phase
    if (_q->num_symbols > 0) {
        // compute phase error (unwrapped)
        float dphi_prime = p_phase[0] - _q->phi_prime;
        if (dphi_prime >  M_PI) dphi_prime -= M_2_PI;
        if (dphi_prime < -M_PI) dphi_prime += M_2_PI;

        // adjust NCO proportionally to phase error
        nco_crcf_adjust_frequency(_q->nco_rx, 1e-3f*dphi_prime);
    }
    // set internal phase state
    _q->phi_prime = p_phase[0];
}
コード例 #3
0
// estimate phase parameters using first-order polynomial fit
//  _t          :   time vector
//  _phi        :   phase input (unwrapped)
//  _n          :   length of _t, _g
//  _dphi_hat   :   frequency estimate (phase slope)
//  _phi_hat    :   phase estimate
void liquid_estimate_phase(float * _t,
                           float * _phi,
                           unsigned int _n,
                           float * _dphi_hat,
                           float * _phi_hat)
{
    // use first-order (2-parameter) polynomial curve-fit
    float p[2];
    polyf_fit(_t, _phi, _n, p, 2);

    *_phi_hat  = p[0];  // y-intercept point
    *_dphi_hat = p[1];  // phase slope
}
コード例 #4
0
ファイル: ofdmframesync.c プロジェクト: Sangstbk/liquid-dsp
// recover symbol, correcting for gain, pilot phase, etc.
void ofdmframesync_rxsymbol(ofdmframesync _q)
{
    // apply gain
    unsigned int i;
    for (i=0; i<_q->M; i++)
        _q->X[i] *= _q->R[i];

    // polynomial curve-fit
    float x_phase[_q->M_pilot];
    float y_phase[_q->M_pilot];
    float p_phase[2];

    unsigned int n=0;
    unsigned int k;
    float complex pilot = 1.0f;
    for (i=0; i<_q->M; i++) {

        // start at mid-point (effective fftshift)
        k = (i + _q->M2) % _q->M;

        if (_q->p[k]==OFDMFRAME_SCTYPE_PILOT) {
            if (n == _q->M_pilot) {
                fprintf(stderr,"warning: ofdmframesync_rxsymbol(), pilot subcarrier mismatch\n");
                return;
            }
            pilot = (msequence_advance(_q->ms_pilot) ? 1.0f : -1.0f);
#if 0
            printf("pilot[%3u] = %12.4e + j*%12.4e (expected %12.4e + j*%12.4e)\n",
                    k,
                    crealf(_q->X[k]), cimagf(_q->X[k]),
                    crealf(pilot),    cimagf(pilot));
#endif
            // store resulting...
            x_phase[n] = (k > _q->M2) ? (float)k - (float)(_q->M) : (float)k;
            y_phase[n] = cargf(_q->X[k]*conjf(pilot));

            // update counter
            n++;

        }
    }

    if (n != _q->M_pilot) {
        fprintf(stderr,"warning: ofdmframesync_rxsymbol(), pilot subcarrier mismatch\n");
        return;
    }

    // try to unwrap phase
    for (i=1; i<_q->M_pilot; i++) {
        while ((y_phase[i] - y_phase[i-1]) >  M_PI)
            y_phase[i] -= 2*M_PI;
        while ((y_phase[i] - y_phase[i-1]) < -M_PI)
            y_phase[i] += 2*M_PI;
    }

    // fit phase to 1st-order polynomial (2 coefficients)
    polyf_fit(x_phase, y_phase, _q->M_pilot, p_phase, 2);

    // filter slope estimate (timing offset)
    float alpha = 0.3f;
    p_phase[1] = alpha*p_phase[1] + (1-alpha)*_q->p1_prime;
    _q->p1_prime = p_phase[1];

#if DEBUG_OFDMFRAMESYNC
    if (_q->debug_enabled) {
        // save pilots
        memmove(_q->px, x_phase, _q->M_pilot*sizeof(float));
        memmove(_q->py, y_phase, _q->M_pilot*sizeof(float));

        // NOTE : swapping values for octave
        _q->p_phase[0] = p_phase[1];
        _q->p_phase[1] = p_phase[0];

        windowf_push(_q->debug_pilot_0, p_phase[0]);
        windowf_push(_q->debug_pilot_1, p_phase[1]);
    }
#endif

    // compensate for phase offset
    // TODO : find more computationally efficient way to do this
    for (i=0; i<_q->M; i++) {
        // only apply to data/pilot subcarriers
        if (_q->p[i] == OFDMFRAME_SCTYPE_NULL) {
            _q->X[i] = 0.0f;
        } else {
            float fx    = (i > _q->M2) ? (float)i - (float)(_q->M) : (float)i;
            float theta = polyf_val(p_phase, 2, fx);
            _q->X[i] *= liquid_cexpjf(-theta);
        }
    }

    // adjust NCO frequency based on differential phase
    if (_q->num_symbols > 0) {
        // compute phase error (unwrapped)
        float dphi_prime = p_phase[0] - _q->phi_prime;
        while (dphi_prime >  M_PI) dphi_prime -= M_2_PI;
        while (dphi_prime < -M_PI) dphi_prime += M_2_PI;

        // adjust NCO proportionally to phase error
        nco_crcf_adjust_frequency(_q->nco_rx, 1e-3f*dphi_prime);
    }
    // set internal phase state
    _q->phi_prime = p_phase[0];
    //printf("%3u : theta : %12.8f, nco freq: %12.8f\n", _q->num_symbols, p_phase[0], nco_crcf_get_frequency(_q->nco_rx));
    
    // increment symbol counter
    _q->num_symbols++;

#if 0
    for (i=0; i<_q->M_pilot; i++)
        printf("x_phase(%3u) = %12.8f; y_phase(%3u) = %12.8f;\n", i+1, x_phase[i], i+1, y_phase[i]);
    printf("poly : p0=%12.8f, p1=%12.8f\n", p_phase[0], p_phase[1]);
#endif
}
コード例 #5
0
ファイル: ofdmframesync.c プロジェクト: Sangstbk/liquid-dsp
// estimate complex equalizer gain from G0 and G1 using polynomial fit
//  _q      :   ofdmframesync object
//  _order  :   polynomial order
void ofdmframesync_estimate_eqgain_poly(ofdmframesync _q,
                                        unsigned int _order)
{
#if DEBUG_OFDMFRAMESYNC
    if (_q->debug_enabled) {
        // copy pre-smoothed gain
        memmove(_q->G_hat, _q->G, _q->M*sizeof(float complex));
    }
#endif

    // polynomial interpolation
    unsigned int i;
    unsigned int N = _q->M_pilot + _q->M_data;
    if (_order > N-1) _order = N-1;
    if (_order > 10)  _order = 10;
    float x_freq[N];
    float y_abs[N];
    float y_arg[N];
    float p_abs[_order+1];
    float p_arg[_order+1];

    unsigned int n=0;
    unsigned int k;
    for (i=0; i<_q->M; i++) {

        // start at mid-point (effective fftshift)
        k = (i + _q->M2) % _q->M;

        if (_q->p[k] != OFDMFRAME_SCTYPE_NULL) {
            if (n == N) {
                fprintf(stderr, "error: ofdmframesync_estimate_eqgain_poly(), pilot subcarrier mismatch\n");
                exit(1);
            }
            // store resulting...
            x_freq[n] = (k > _q->M2) ? (float)k - (float)(_q->M) : (float)k;
            x_freq[n] = x_freq[n] / (float)(_q->M);
            y_abs[n] = cabsf(_q->G[k]);
            y_arg[n] = cargf(_q->G[k]);

            // update counter
            n++;
        }
    }

    if (n != N) {
        fprintf(stderr, "error: ofdmframesync_estimate_eqgain_poly(), pilot subcarrier mismatch\n");
        exit(1);
    }

    // try to unwrap phase
    for (i=1; i<N; i++) {
        while ((y_arg[i] - y_arg[i-1]) >  M_PI)
            y_arg[i] -= 2*M_PI;
        while ((y_arg[i] - y_arg[i-1]) < -M_PI)
            y_arg[i] += 2*M_PI;
    }

    // fit to polynomial
    polyf_fit(x_freq, y_abs, N, p_abs, _order+1);
    polyf_fit(x_freq, y_arg, N, p_arg, _order+1);

    // compute subcarrier gain
    for (i=0; i<_q->M; i++) {
        float freq = (i > _q->M2) ? (float)i - (float)(_q->M) : (float)i;
        freq = freq / (float)(_q->M);
        float A     = polyf_val(p_abs, _order+1, freq);
        float theta = polyf_val(p_arg, _order+1, freq);
        _q->G[i] = (_q->p[i] == OFDMFRAME_SCTYPE_NULL) ? 0.0f : A * liquid_cexpjf(theta);
    }

#if 0
    for (i=0; i<N; i++)
        printf("x(%3u) = %12.8f; y_abs(%3u) = %12.8f; y_arg(%3u) = %12.8f;\n",
                i+1, x_freq[i],
                i+1, y_abs[i],
                i+1, y_arg[i]);

    for (i=0; i<=_order; i++)
        printf("p_abs(%3u) = %12.8f;\n", i+1, p_abs[i]);
    for (i=0; i<=_order; i++)
        printf("p_arg(%3u) = %12.8f;\n", i+1, p_arg[i]);
#endif
}
コード例 #6
0
ファイル: wlanframesync.c プロジェクト: pk-mds/liquid-wlan
// estimate complex equalizer gain from G0 and G1 using polynomial fit
void wlanframesync_estimate_eqgain_poly(wlanframesync _q)
{
    // polynomial order
    unsigned int order = 2;

    // equalizer (polynomial)
    float x_eq[52];             // frequency array
    float y_eq_abs[52];         // magnitude array
    float y_eq_arg[52];         // phase array
    float p_eq_abs[order+1];    // polynomial coefficients (magnitude)
    float p_eq_arg[order+1];    // polynomial coefficients (phase)

    // average complex gains
    unsigned int i;
    unsigned int k;
    unsigned int n=0;
    for (i=0; i<64; i++) {
        // start at mid-point (effective fftshift)
        k = (i + 32) % 64;

        if (k == 0 || (k>26 && k<38) ) {
            // NULL subcarrier
        } else {
            // validate counter
            assert(n < 52);

            // DATA/PILOT subcarrier (S1 enabled)
            //float complex G = 0.5f*(_q->G1a + _q->G1b);
            float complex G = _q->G1b[k];

            // store resulting...
            x_eq[n] = (k > 31) ? (float)k - (float)(64) : (float)k;
            x_eq[n] = x_eq[n] / (float)(64);
            y_eq_abs[n] = cabsf(G);
            y_eq_arg[n] = cargf(G);

            // update counter
            n++;
        }
    }
    
    // validate counter
    assert(n == 52);

    // try to unwrap phase
    for (i=1; i<52; i++) {
        while ((y_eq_arg[i] - y_eq_arg[i-1]) >  M_PI)
            y_eq_arg[i] -= 2*M_PI;
        while ((y_eq_arg[i] - y_eq_arg[i-1]) < -M_PI)
            y_eq_arg[i] += 2*M_PI;
    }

    // fit to polynomial(s)
    polyf_fit(x_eq, y_eq_abs, 52, p_eq_abs, order+1);
    polyf_fit(x_eq, y_eq_arg, 52, p_eq_arg, order+1);

    // compute subcarrier gain
    for (i=0; i<64; i++) {
        
        if (i == 0 || (i>26 && i<38) ) {
            // NULL subcarrier
            _q->G[i] = 0.0f;
            _q->R[i] = 0.0f;
        } else {
            // DATA/PILOT subcarrier (S1 enabled)
            float freq = (i > 31) ? (float)i - (float)(64) : (float)i;
            freq = freq / (float)(64);
            float A     = polyf_val(p_eq_abs, order+1, freq);
            float theta = polyf_val(p_eq_arg, order+1, freq);

            // composite channel estimation
            _q->G[i] = A * cexpf(_Complex_I*theta);

            // composite channel correction
            // 0.11267 = sqrt(52)/64
            _q->R[i] = 0.11267f / (A + 1e-12f) * cexpf(-_Complex_I*theta);
        }
    }

}
コード例 #7
0
void ofdmoqamframe64sync_rxpayload(ofdmoqamframe64sync _q,
                                   float complex * _Y0,
                                   float complex * _Y1)
{
    unsigned int j=0;
    unsigned int t=0;
    int sctype;
    unsigned int pilot_phase = msequence_advance(_q->ms_pilot);

    // gain correction (equalizer)
    unsigned int i;
    for (i=0; i<_q->num_subcarriers; i++) {
        _Y0[i] *= _q->G[i];// * _q->zeta;
        _Y1[i] *= _q->G[i];// * _q->zeta;
    }

    // TODO : extract pilots
    for (i=0; i<_q->num_subcarriers; i++) {
        sctype = ofdmoqamframe64_getsctype(i);
        if (sctype==OFDMOQAMFRAME64_SCTYPE_PILOT) {
            // pilot subcarrier : use p/n sequence for pilot phase
            float complex y0 = ((i%2)==0 ? _Y0[i] : _Y1[i]) / _q->zeta;
            float complex y1 = ((i%2)==0 ? _Y1[i] : _Y0[i]) / _q->zeta;
            float complex p = (pilot_phase ? 1.0f : -1.0f);
            float phi_hat =
            ofdmoqamframe64sync_estimate_pilot_phase(y0,y1,p);
            _q->y_phase[t] = phi_hat;
            t++;
#if DEBUG_OFDMOQAMFRAME64SYNC_PRINT
            printf("i = %u\n", i);
            printf("y0 = %12.8f + j*%12.8f;\n", crealf(y0),cimagf(y0));
            printf("y1 = %12.8f + j*%12.8f;\n", crealf(y1),cimagf(y1));
            printf("phi_hat = %12.8f\n", phi_hat);
#endif
            /*
            printf("exiting prematurely\n");
            ofdmoqamframe64sync_destroy(_q);
            exit(1);
            */
        }
    }
    assert(t==4);
 
    // pilot phase correction
    /*
    _q->y_phase[0] = cargf(_q->X[11]);  // -21
    _q->y_phase[1] = cargf(_q->X[25]);  //  -7
    _q->y_phase[2] = cargf(_q->X[39]);  //   7
    _q->y_phase[3] = cargf(_q->X[53]);  //  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);

    //nco_crcf_step(_q->nco_pilot);
    float theta_hat = nco_crcf_get_phase(_q->nco_pilot);
    float phase_error = _q->p_phase[0] - theta_hat;
    while (phase_error >  M_PI) phase_error -= 2.0f*M_PI;
    while (phase_error < -M_PI) phase_error += 2.0f*M_PI;
    pll_step(_q->pll_pilot, _q->nco_pilot, 0.1f*phase_error);

#if DEBUG_OFDMOQAMFRAME64SYNC_PRINT
    // print phase results
    for (i=0; i<4; i++) {
        printf("x(%3u) = %12.8f; y(%3u) = %12.8f;\n", i+1, _q->x_phase[i], i+1, _q->y_phase[i]);
    }
    printf("p(1) = %12.8f\n", _q->p_phase[0]);
    printf("p(2) = %12.8f\n", _q->p_phase[1]);
#endif

#if DEBUG_OFDMOQAMFRAME64SYNC
    windowf_push(_q->debug_pilotphase,      _q->p_phase[0]);
    windowf_push(_q->debug_pilotphase_hat,  theta_hat);
#endif

    // compensate for phase shift due to timing offset
    float theta;
    _q->p_phase[0] = theta_hat;
    _q->p_phase[1] = 0.0f;
    for (i=0; i<_q->num_subcarriers; i++) {
        // TODO : compute phase for delayed symbol (different from non-delayed symbol)
        theta = polyf_val(_q->p_phase, 2, (float)(i)-32.0f);
        _Y0[i] *= liquid_cexpjf(-theta);
        _Y1[i] *= liquid_cexpjf(-theta);
    }
    nco_crcf_step(_q->nco_pilot);

    // strip data subcarriers
    for (i=0; i<_q->num_subcarriers; i++) {
        sctype = ofdmoqamframe64_getsctype(i);
        if (sctype==OFDMOQAMFRAME64_SCTYPE_NULL) {
            // disabled subcarrier
        } else if (sctype==OFDMOQAMFRAME64_SCTYPE_PILOT) {
            // pilot subcarrier
        } else {
            // data subcarrier
            if ((i%2)==0) {
                // even subcarrier
                _q->data[j] = crealf(_Y0[i]) + 
                              cimagf(_Y1[i]) * _Complex_I;
            } else {
                // odd subcarrier
                _q->data[j] = cimagf(_Y0[i]) * _Complex_I +
                              crealf(_Y1[i]);
            }
            // scaling factor
            _q->data[j] /= _q->zeta;
            j++;
        }
    }
    assert(j==48);

#if DEBUG_OFDMOQAMFRAME64SYNC
    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");
            ofdmoqamframe64sync_destroy(_q);
            exit(0);
        } else if (retval == 1) {
#if DEBUG_OFDMOQAMFRAME64SYNC_PRINT
            printf("resetting synchronizer\n");
#endif
            ofdmoqamframe64sync_reset(_q);
        } else {
            // do nothing
        }
    }

}