Exemple #1
0
// estimate long sequence gain
//  _q      :   ofdmframesync object
//  _x      :   input array (time), [size: M x 1]
//  _G      :   output gain (freq)
void ofdmframesync_estimate_gain_S1(ofdmframesync _q,
                                    float complex * _x,
                                    float complex * _G)
{
    // move input array into fft input buffer
    memmove(_q->x, _x, (_q->M)*sizeof(float complex));

    // compute fft, storing result into _q->X
    FFT_EXECUTE(_q->fft);
    
    // compute gain, ignoring NULL subcarriers
    unsigned int i;
    float gain = sqrtf(_q->M_S1) / (float)(_q->M);
    for (i=0; i<_q->M; i++) {
        if (_q->p[i] != OFDMFRAME_SCTYPE_NULL) {
            // NOTE : if cabsf(_q->S1[i]) == 0 then we can multiply by conjugate
            //        rather than compute division
            //_G[i] = _q->X[i] / _q->S1[i];
            _G[i] = _q->X[i] * conjf(_q->S1[i]);
        } else {
            _G[i] = 0.0f;
        }

        // normalize gain
        _G[i] *= gain;
    }   
}
Exemple #2
0
// write OFDM symbol
//  _q      :   framing generator object
//  _x      :   input symbols, [size: _M x 1]
//  _y      :   output samples, [size: _M x 1]
void ofdmframegen_writesymbol(ofdmframegen    _q,
                              float complex * _x,
                              float complex * _y)
{
    // move frequency data to internal buffer
    unsigned int i;
    unsigned int k;
    int sctype;
    for (i=0; i<_q->M; i++) {
        // start at mid-point (effective fftshift)
        k = (i + _q->M/2) % _q->M;

        sctype = _q->p[k];
        if (sctype==OFDMFRAME_SCTYPE_NULL) {
            // disabled subcarrier
            _q->X[k] = 0.0f;
        } else if (sctype==OFDMFRAME_SCTYPE_PILOT) {
            // pilot subcarrier
            _q->X[k] = (msequence_advance(_q->ms_pilot) ? 1.0f : -1.0f) * _q->g_data;
        } else {
            // data subcarrier
            _q->X[k] = _x[k] * _q->g_data;
        }

        //printf("X[%3u] = %12.8f + j*%12.8f;\n",i+1,crealf(_q->X[i]),cimagf(_q->X[i]));
    }

    // execute transform
    FFT_EXECUTE(_q->ifft);

    // copy result to output, adding cyclic prefix and tapering window
    ofdmframegen_gensymbol(_q, _y);
}
Exemple #3
0
// estimate long sequence gain
//  _q      :   wlanframesync object
//  _x      :   input array (time), [size: M x 1]
//  _G      :   output gain (freq)
void wlanframesync_estimate_gain_S1(wlanframesync _q,
                                    float complex * _x,
                                    float complex * _G)
{
    // move input array into fft input buffer
    memmove(_q->x, _x, 64*sizeof(float complex));

    // compute fft, storing result into _q->X
    FFT_EXECUTE(_q->fft);
    
    // nominal gain (normalization factor)
    float gain = 0.11267f; // sqrt(52)/64 ; sqrtf(_q->M_S1) / (float)(_q->M);

    // compute gain, ignoring NULL subcarriers
    unsigned int i;
    for (i=0; i<64; i++) {
        if (i == 0 || (i>26 && i<38) ) {
            // NULL subcarrier
            _G[i] = 0.0f;
        } else {
            // DATA/PILOT subcarrier (S1 enabled)
            _G[i] = _q->X[i] * conjf(wlanframe_S1[i]) * gain;
        }
    }
}
Exemple #4
0
// demodulate symbol, assuming perfect symbol timing
//  _q      :   fskdem object
//  _y      :   input sample array [size: _k x 1]
unsigned int fskdem_demodulate(fskdem          _q,
                               float complex * _y)
{
    // copy input to internal time buffer
    memmove(_q->buf_time, _y, _q->k*sizeof(float complex));

    // compute transform, storing result in 'buf_freq'
    FFT_EXECUTE(_q->fft);

    // find maximum by looking at particular bins
    float        vmax  = 0;
    unsigned int s     = 0;

    // run search
    for (s=0; s<_q->M; s++) {
        float v = cabsf( _q->buf_freq[_q->demod_map[s]] );
        if (s==0 || v > vmax) {
            // save optimal output symbol
            _q->s_demod = s;

            // save peak FFT bin value
            vmax = v;
        }
    }

    // save best result
    return _q->s_demod;
}
Exemple #5
0
// estimate short sequence gain
//  _q      :   wlanframesync object
//  _x      :   input array (time), [size: M x 1]
//  _G      :   output gain (freq)
void wlanframesync_estimate_gain_S0(wlanframesync _q,
                                    float complex * _x,
                                    float complex * _G)
{
    // move input array into fft input buffer
    memmove(_q->x, _x, 64*sizeof(float complex));

    // compute fft, storing result into _q->X
    FFT_EXECUTE(_q->fft);
    
    // compute gain, ignoring NULL subcarriers
    unsigned int i;
    float gain = 0.054127f; // sqrt(12)/64 ; sqrtf(_q->M_S0) / (float)(_q->M);

    // clear input
    for (i=0; i<64; i++) _G[i] = 0.0f;

    // NOTE : if cabsf(_q->S0[i]) == 0 then we can multiply by conjugate
    //        rather than compute division
    //_G[i] = _q->X[i] / _q->S0[i];
    _G[40] = _q->X[40] * conjf(wlanframe_S0[40]) * gain;
    _G[44] = _q->X[44] * conjf(wlanframe_S0[44]) * gain;
    _G[48] = _q->X[48] * conjf(wlanframe_S0[48]) * gain;
    _G[52] = _q->X[52] * conjf(wlanframe_S0[52]) * gain;
    _G[56] = _q->X[56] * conjf(wlanframe_S0[56]) * gain;
    _G[60] = _q->X[60] * conjf(wlanframe_S0[60]) * gain;
    //
    _G[ 4] = _q->X[ 4] * conjf(wlanframe_S0[ 4]) * gain;
    _G[ 8] = _q->X[ 8] * conjf(wlanframe_S0[ 8]) * gain;
    _G[12] = _q->X[12] * conjf(wlanframe_S0[12]) * gain;
    _G[16] = _q->X[16] * conjf(wlanframe_S0[16]) * gain;
    _G[20] = _q->X[20] * conjf(wlanframe_S0[20]) * gain;
    _G[24] = _q->X[24] * conjf(wlanframe_S0[24]) * gain;
}
Exemple #6
0
// estimate complex equalizer gain from G0 and G1
//  _q      :   ofdmframesync object
//  _ntaps  :   number of time-domain taps for smoothing
void ofdmframesync_estimate_eqgain(ofdmframesync _q,
                                   unsigned int _ntaps)
{
#if DEBUG_OFDMFRAMESYNC
    if (_q->debug_enabled) {
        // copy pre-smoothed gain
        memmove(_q->G_hat, _q->G, _q->M*sizeof(float complex));
    }
#endif

    // validate input
    if (_ntaps == 0 || _ntaps > _q->M) {
        fprintf(stderr, "error: ofdmframesync_estimate_eqgain(), ntaps must be in [1,M]\n");
        exit(1);
    }

    unsigned int i;

    // generate smoothing window (fft of temporal window)
    for (i=0; i<_q->M; i++)
        _q->x[i] = (i < _ntaps) ? 1.0f : 0.0f;
    FFT_EXECUTE(_q->fft);

    memmove(_q->G0, _q->G, _q->M*sizeof(float complex));

    // smooth complex equalizer gains
    for (i=0; i<_q->M; i++) {
        // set gain to zero for null subcarriers
        if (_q->p[i] == OFDMFRAME_SCTYPE_NULL) {
            _q->G[i] = 0.0f;
            continue;
        }

        float complex w;
        float complex w0 = 0.0f;
        float complex G_hat = 0.0f;

        unsigned int j;
        for (j=0; j<_q->M; j++) {
            if (_q->p[j] == OFDMFRAME_SCTYPE_NULL) continue;

            // select window sample from array
            w = _q->X[(i + _q->M - j) % _q->M];

            // accumulate gain
            //G_hat += w * 0.5f * (_q->G0[j] + _q->G1[j]);
            G_hat += w * _q->G0[j];
            w0 += w;
        }

        // eliminate divide-by-zero issues
        if (cabsf(w0) < 1e-4f) {
            fprintf(stderr,"error: ofdmframesync_estimate_eqgain(), weighting factor is zero\n");
            w0 = 1.0f;
        }
        _q->G[i] = G_hat / w0;
    }
}
Exemple #7
0
void firpfbch_analyzer_run(firpfbch _c, float complex * _y)
{
    // NOTE: The analyzer is different from the synthesizer in
    //       that the invocation of the commutator results in a
    //       delay from the first input sample to the resulting
    //       partitions.  As a result, the inverse DFT is
    //       invoked after the first filter is run, after which
    //       the remaining filters are executed.

    // restore saved IDFT input state X from X_prime
    memmove(_c->X, _c->X_prime, (_c->num_channels)*sizeof(float complex));

    unsigned int i, b;
    unsigned int k = _c->filter_index;

    // push first value and compute output
    float complex * r;
    WINDOW(_read)(_c->w[k], &r);
    DOTPROD(_execute)(_c->dp[0], r, &(_c->X[0]));

    // execute inverse fft, store in buffer _c->x
    FFT_EXECUTE(_c->fft);

    // copy results to output buffer
    memmove(_y, _c->x, (_c->num_channels)*sizeof(float complex));

    // push remaining samples into filter bank and execute in
    // *reverse* order, putting result into the inverse DFT
    // input buffer _c->X
    //for (i=1; i<_c->num_channels; i++) {
    // NOTE : the filter window buffers have already been loaded
    //        in the proper reverse order, so there is no need
    //        to execute the dot products in any particular order,
    //        so long as they are aligned with the proper input
    //        buffer.
    for (i=1; i<_c->num_channels; i++) {
        b = (k+i) % _c->num_channels;
        WINDOW(_read)(_c->w[b], &r);
        DOTPROD(_execute)(_c->dp[i], r, &(_c->X[i]));
    }
}
Exemple #8
0
void FFTransformer::fillComplexSub()
{
    auto plan = FFT_CREATE_PLAN(m_bufferSize, m_complexSub, m_complexSub, FFTW_FORWARD, FFTW_ESTIMATE);
    double speed = Options::getInstance()->getSignalSpeed();
    double rxRate = Options::getInstance()->getBand();
    for(size_t i = 0; i < m_bufferSize; i++)
    {
        double t = i / rxRate;
        t *= t;

        auto iter = *(m_complexSub + i);
        iter[0] = cos(M_PI * t * speed);
        iter[1] = sin(M_PI * t * speed);
    }

    FFT_EXECUTE(plan);
    for(size_t i = 0; i < m_bufferSize; i++)
      m_complexSub[i][1] *= -1;
      
    FFT_DESTROY_PLAN(plan);
}
Exemple #9
0
void firpfbch_synthesizer_execute(firpfbch _c, float complex * _x, float complex * _y)
{
    unsigned int i;

    // copy samples into ifft input buffer _c->X
    memmove(_c->X, _x, (_c->num_channels)*sizeof(float complex));

    // execute inverse fft, store in buffer _c->x
    FFT_EXECUTE(_c->fft);

    // push samples into filter bank and execute, putting
    // samples into output buffer _y
    float complex * r;
    for (i=0; i<_c->num_channels; i++) {
        WINDOW(_push)(_c->w[i], _c->x[i]);
        WINDOW(_read)(_c->w[i], &r);
        DOTPROD(_execute)(_c->dp[i], r, &(_y[i]));

        // invoke scaling factor
        _y[i] /= (float)(_c->num_channels);
    }
}
Exemple #10
0
void ofdmframesync_execute_rxsymbols(ofdmframesync _q)
{
    // wait for timeout
    _q->timer--;

    if (_q->timer == 0) {

        // run fft
        float complex * rc;
        windowcf_read(_q->input_buffer, &rc);
        memmove(_q->x, &rc[_q->cp_len-_q->backoff], (_q->M)*sizeof(float complex));
        FFT_EXECUTE(_q->fft);

        // recover symbol in internal _q->X buffer
        ofdmframesync_rxsymbol(_q);

#if DEBUG_OFDMFRAMESYNC
        if (_q->debug_enabled) {
            unsigned int i;
            for (i=0; i<_q->M; i++) {
                if (_q->p[i] == OFDMFRAME_SCTYPE_DATA)
                    windowcf_push(_q->debug_framesyms, _q->X[i]);
            }
        }
#endif
        // invoke callback
        if (_q->callback != NULL) {
            int retval = _q->callback(_q->X, _q->p, _q->M, _q->userdata);

            if (retval != 0)
                ofdmframesync_reset(_q);
        }

        // reset timer
        _q->timer = _q->M + _q->cp_len;
    }

}
Exemple #11
0
// receive data symbols
void wlanframesync_execute_rxdata(wlanframesync _q)
{
    _q->timer++;
    if (_q->timer < 80)
        return;

    //printf("    receiving symbol %u...\n", _q->num_symbols);

    // reset timer
    _q->timer = 0;

    // run fft
    float complex * rc;
    windowcf_read(_q->input_buffer, &rc);
    memmove(_q->x, &rc[16-2], 64*sizeof(float complex));

    // compute fft, storing result into _q->X
    FFT_EXECUTE(_q->fft);
  
    // recover symbol, correcting for gain, pilot phase, etc.
    wlanframesync_rxsymbol(_q);
   
    // demodulate and pack
    unsigned int i;
    unsigned int n=0;
    unsigned int sym;
    for (i=0; i<64; i++) {
        unsigned int k = (i + 32) % 64;

        if ( k==0 || (k > 26 && k < 38) ) {
            // NULL subcarrier
        } else if (k==43 || k==57 || k==7 || k==21) {
            // PILOT subcarrier
        } else {
            // DATA subcarrier
            assert(n<48);
            sym = wlan_demodulate(_q->mod_scheme, _q->X[k]);
            _q->modem_syms[n] = sym;
            n++;
#if DEBUG_WLANFRAMESYNC
            // TODO : move this outside loop
            if (_q->debug_enabled)
                windowcf_push(_q->debug_framesyms, _q->X[k]);
#endif

        }
    }
    assert(n==48);

    // pack modem symbols
    //printf("  %3u = %3u * %3u\n", _q->enc_msg_len, _q->nsym, _q->bytes_per_symbol);
    unsigned int num_written;
    liquid_wlan_repack_bytes(_q->modem_syms, _q->nbpsc, 48,
                             &_q->msg_enc[_q->num_symbols * _q->bytes_per_symbol], 8, _q->bytes_per_symbol,
                             &num_written);
    assert(num_written == _q->bytes_per_symbol);

    // increment number of received symbols
    _q->num_symbols++;

    // check number of symbols
    if (_q->num_symbols == _q->nsym) {
        // decode message
        wlan_packet_decode(_q->rate, _q->seed, _q->length, _q->msg_enc, _q->msg_dec);

        // assemble RX vector
        struct wlan_rxvector_s rxvector;
        rxvector.LENGTH     = _q->length;
        rxvector.RSSI       = 200 + (unsigned int) (10*log10f(_q->g0));
        rxvector.DATARATE   = _q->rate;
        rxvector.SERVICE    = 0;

        // invoke callback
        if (_q->callback != NULL) {
            //int retval = 
            _q->callback(_q->msg_dec, rxvector, _q->userdata);
        }

        // reset and return
        wlanframesync_reset(_q);
    }
}
Exemple #12
0
// receive the 'SIGNAL' field
void wlanframesync_execute_rxsignal(wlanframesync _q)
{
    _q->timer++;
    if (_q->timer < 80)
        return;

    // reset timer
    _q->timer = 0;

    // run fft
    float complex * rc;
    windowcf_read(_q->input_buffer, &rc);
    memmove(_q->x, &rc[16-2], 64*sizeof(float complex));

    // compute fft, storing result into _q->X
    FFT_EXECUTE(_q->fft);
  
    // recover symbol, correcting for gain, pilot phase, etc.
    wlanframesync_rxsymbol(_q);
    
    // demodulate, decode, ...
    memset(_q->signal_int, 0x00, 6*sizeof(unsigned char));

    _q->signal_int[0] |= crealf(_q->X[38]) > 0.0f ? 0x80 : 0x00;
    _q->signal_int[0] |= crealf(_q->X[39]) > 0.0f ? 0x40 : 0x00;
    _q->signal_int[0] |= crealf(_q->X[40]) > 0.0f ? 0x20 : 0x00;
    _q->signal_int[0] |= crealf(_q->X[41]) > 0.0f ? 0x10 : 0x00;
    _q->signal_int[0] |= crealf(_q->X[42]) > 0.0f ? 0x08 : 0x00;
    //  43 : pilot
    _q->signal_int[0] |= crealf(_q->X[44]) > 0.0f ? 0x04 : 0x00;
    _q->signal_int[0] |= crealf(_q->X[45]) > 0.0f ? 0x02 : 0x00;
    _q->signal_int[0] |= crealf(_q->X[46]) > 0.0f ? 0x01 : 0x00;
    _q->signal_int[1] |= crealf(_q->X[47]) > 0.0f ? 0x80 : 0x00;
    _q->signal_int[1] |= crealf(_q->X[48]) > 0.0f ? 0x40 : 0x00;
    _q->signal_int[1] |= crealf(_q->X[49]) > 0.0f ? 0x20 : 0x00;
    _q->signal_int[1] |= crealf(_q->X[50]) > 0.0f ? 0x10 : 0x00;
    _q->signal_int[1] |= crealf(_q->X[51]) > 0.0f ? 0x08 : 0x00;
    _q->signal_int[1] |= crealf(_q->X[52]) > 0.0f ? 0x04 : 0x00;
    _q->signal_int[1] |= crealf(_q->X[53]) > 0.0f ? 0x02 : 0x00;
    _q->signal_int[1] |= crealf(_q->X[54]) > 0.0f ? 0x01 : 0x00;
    _q->signal_int[2] |= crealf(_q->X[55]) > 0.0f ? 0x80 : 0x00;
    _q->signal_int[2] |= crealf(_q->X[56]) > 0.0f ? 0x40 : 0x00;
    //  57 : pilot
    _q->signal_int[2] |= crealf(_q->X[58]) > 0.0f ? 0x20 : 0x00;
    _q->signal_int[2] |= crealf(_q->X[59]) > 0.0f ? 0x10 : 0x00;
    _q->signal_int[2] |= crealf(_q->X[60]) > 0.0f ? 0x08 : 0x00;
    _q->signal_int[2] |= crealf(_q->X[61]) > 0.0f ? 0x04 : 0x00;
    _q->signal_int[2] |= crealf(_q->X[62]) > 0.0f ? 0x02 : 0x00;
    _q->signal_int[2] |= crealf(_q->X[63]) > 0.0f ? 0x01 : 0x00;
    //   0 : NULL
    _q->signal_int[3] |= crealf(_q->X[ 1]) > 0.0f ? 0x80 : 0x00;
    _q->signal_int[3] |= crealf(_q->X[ 2]) > 0.0f ? 0x40 : 0x00;
    _q->signal_int[3] |= crealf(_q->X[ 3]) > 0.0f ? 0x20 : 0x00;
    _q->signal_int[3] |= crealf(_q->X[ 4]) > 0.0f ? 0x10 : 0x00;
    _q->signal_int[3] |= crealf(_q->X[ 5]) > 0.0f ? 0x08 : 0x00;
    _q->signal_int[3] |= crealf(_q->X[ 6]) > 0.0f ? 0x04 : 0x00;
    //   7 : pilot
    _q->signal_int[3] |= crealf(_q->X[ 8]) > 0.0f ? 0x02 : 0x00;
    _q->signal_int[3] |= crealf(_q->X[ 9]) > 0.0f ? 0x01 : 0x00;
    _q->signal_int[4] |= crealf(_q->X[10]) > 0.0f ? 0x80 : 0x00;
    _q->signal_int[4] |= crealf(_q->X[11]) > 0.0f ? 0x40 : 0x00;
    _q->signal_int[4] |= crealf(_q->X[12]) > 0.0f ? 0x20 : 0x00;
    _q->signal_int[4] |= crealf(_q->X[13]) > 0.0f ? 0x10 : 0x00;
    _q->signal_int[4] |= crealf(_q->X[14]) > 0.0f ? 0x08 : 0x00;
    _q->signal_int[4] |= crealf(_q->X[15]) > 0.0f ? 0x04 : 0x00;
    _q->signal_int[4] |= crealf(_q->X[16]) > 0.0f ? 0x02 : 0x00;
    _q->signal_int[4] |= crealf(_q->X[17]) > 0.0f ? 0x01 : 0x00;
    _q->signal_int[5] |= crealf(_q->X[18]) > 0.0f ? 0x80 : 0x00;
    _q->signal_int[5] |= crealf(_q->X[19]) > 0.0f ? 0x40 : 0x00;
    _q->signal_int[5] |= crealf(_q->X[20]) > 0.0f ? 0x20 : 0x00;
    //  21 : pilot
    _q->signal_int[5] |= crealf(_q->X[22]) > 0.0f ? 0x10 : 0x00;
    _q->signal_int[5] |= crealf(_q->X[23]) > 0.0f ? 0x08 : 0x00;
    _q->signal_int[5] |= crealf(_q->X[24]) > 0.0f ? 0x04 : 0x00;
    _q->signal_int[5] |= crealf(_q->X[25]) > 0.0f ? 0x02 : 0x00;
    _q->signal_int[5] |= crealf(_q->X[26]) > 0.0f ? 0x01 : 0x00;

    // decode SIGNAL field
    wlanframesync_decode_signal(_q);

    // validate proper decoding
    if (!_q->signal_valid) {
        // reset synchronizer and return
        wlanframesync_reset(_q);
        return;
    }

    // set state
    _q->state = WLANFRAMESYNC_STATE_RXDATA;
}
Exemple #13
0
// create FFT-based FIR filter using external coefficients
//  _h      : filter coefficients [size: _h_len x 1]
//  _h_len  : filter length, _h_len > 0
//  _n      : block size = nfft/2, at least _h_len-1
FFTFILT() FFTFILT(_create)(TC *         _h,
                           unsigned int _h_len,
                           unsigned int _n)
{
    // validate input
    if (_h_len == 0) {
        fprintf(stderr,"error: fftfilt_%s_create(), filter length must be greater than zero\n",
                EXTENSION_FULL);
        exit(1);
    } else if (_n < _h_len-1) {
        fprintf(stderr,"error: fftfilt_%s_create(), block length must be greater than _h_len-1 (%u)\n",
                EXTENSION_FULL,
                _h_len-1);
        exit(1);
    }

    // create filter object and initialize
    FFTFILT() q = (FFTFILT()) malloc(sizeof(struct FFTFILT(_s)));
    q->h_len    = _h_len;
    q->n        = _n;

    // copy filter coefficients
    q->h = (TC *) malloc((q->h_len)*sizeof(TC));
    memmove(q->h, _h, _h_len*sizeof(TC));

    // allocate internal memory arrays
    q->time_buf = (float complex *) malloc((2*q->n)* sizeof(float complex)); // time buffer
    q->freq_buf = (float complex *) malloc((2*q->n)* sizeof(float complex)); // frequency buffer
    q->H        = (float complex *) malloc((2*q->n)* sizeof(float complex)); // FFT{ h }
    q->w        = (float complex *) malloc((  q->n)* sizeof(float complex)); // delay buffer

    // create internal FFT objects
#ifdef LIQUID_FFTOVERRIDE
    q->fft  = fft_create_plan(2*q->n, q->time_buf, q->freq_buf, LIQUID_FFT_FORWARD,  0);
    q->ifft = fft_create_plan(2*q->n, q->freq_buf, q->time_buf, LIQUID_FFT_BACKWARD, 0);
#else
    q->fft  = FFT_CREATE_PLAN(2*q->n, q->time_buf, q->freq_buf, FFT_DIR_FORWARD,  FFT_METHOD);
    q->ifft = FFT_CREATE_PLAN(2*q->n, q->freq_buf, q->time_buf, FFT_DIR_BACKWARD, FFT_METHOD);
#endif

    // compute FFT of filter coefficients and copy to internal H array
    unsigned int i;
    for (i=0; i<2*q->n; i++)
        q->time_buf[i] = (i < q->h_len) ? q->h[i] : 0;
    // time_buf > {FFT} > freq_buf
#ifdef LIQUID_FFTOVERRIDE
    fft_execute(q->fft);
#else
    FFT_EXECUTE(q->fft);
#endif
    memmove(q->H, q->freq_buf, 2*q->n*sizeof(float complex));

    // set default scaling
    FFTFILT(_set_scale)(q, 1);

    // reset filter state (clear buffer)
    FFTFILT(_reset)(q);

    // return object
    return q;
}