Ejemplo n.º 1
0
/*  _m          :   number of correlators                   */
PRESYNC() PRESYNC(_create)(TC *         _v,
                           unsigned int _n,
                           float        _dphi_max,
                           unsigned int _m)
{
    // validate input
    if (_n < 1) {
        fprintf(stderr, "error: bpresync_%s_create(), invalid input length\n", EXTENSION_FULL);
        exit(1);
    } else if (_m == 0) {
        fprintf(stderr, "error: bpresync_%s_create(), number of correlators must be at least 1\n", EXTENSION_FULL);
        exit(1);
    }

    // allocate main object memory and initialize
    PRESYNC() _q = (PRESYNC()) malloc(sizeof(struct PRESYNC(_s)));
    _q->n = _n;
    _q->m = _m;

    _q->n_inv = 1.0f / (float)(_q->n);

    unsigned int i;

    // create internal receive buffers
    _q->rx_i = WINDOW(_create)(_q->n);
    _q->rx_q = WINDOW(_create)(_q->n);

    // create internal array of frequency offsets
    _q->dphi = (float*) malloc( _q->m*sizeof(float) );

    // create internal synchronizers
    _q->sync_i = (DOTPROD()*) malloc( _q->m*sizeof(DOTPROD()) );
    _q->sync_q = (DOTPROD()*) malloc( _q->m*sizeof(DOTPROD()) );

    // buffer
    T vi_prime[_n];
    T vq_prime[_n];
    for (i=0; i<_q->m; i++) {

        // generate signal with frequency offset
        _q->dphi[i] = (float)i / (float)(_q->m-1)*_dphi_max;
        unsigned int k;
        for (k=0; k<_q->n; k++) {
            vi_prime[k] = REAL( _v[k] * cexpf(-_Complex_I*k*_q->dphi[i]) );
            vq_prime[k] = IMAG( _v[k] * cexpf(-_Complex_I*k*_q->dphi[i]) );
        }

        _q->sync_i[i] = DOTPROD(_create)(vi_prime, _q->n);
        _q->sync_q[i] = DOTPROD(_create)(vq_prime, _q->n);
    }

    // allocate memory for cross-correlation
    _q->rxy = (float*) malloc( _q->m*sizeof(float) );

    // reset object
    PRESYNC(_reset)(_q);

    return _q;
}
Ejemplo n.º 2
0
// create firpfb from external coefficients
//  _M      : number of filters in the bank
//  _h      : coefficients [size: _M*_h_len x 1]
//  _h_len  : filter delay (symbols)
FIRPFB() FIRPFB(_create)(unsigned int _M,
                         TC *         _h,
                         unsigned int _h_len)
{
    // validate input
    if (_M == 0) {
        fprintf(stderr,"error: firpfb_%s_create(), number of filters must be greater than zero\n",
                EXTENSION_FULL);
        exit(1);
    } else if (_h_len == 0) {
        fprintf(stderr,"error: firpfb_%s_create(), filter length must be greater than zero\n",
                EXTENSION_FULL);
        exit(1);
    }

    // create main filter object
    FIRPFB() q = (FIRPFB()) malloc(sizeof(struct FIRPFB(_s)));

    // set user-defined parameters
    q->num_filters = _M;
    q->h_len       = _h_len;

    // each filter is realized as a dotprod object
    q->dp = (DOTPROD()*) malloc((q->num_filters)*sizeof(DOTPROD()));

    // generate bank of sub-samped filters
    // length of each sub-sampled filter
    unsigned int h_sub_len = _h_len / q->num_filters;
    TC h_sub[h_sub_len];
    unsigned int i, n;
    for (i=0; i<q->num_filters; i++) {
        for (n=0; n<h_sub_len; n++) {
            // load filter in reverse order
            h_sub[h_sub_len-n-1] = _h[i + n*(q->num_filters)];
        }

        // create dot product object
        q->dp[i] = DOTPROD(_create)(h_sub,h_sub_len);
    }

    // save sub-sampled filter length
    q->h_sub_len = h_sub_len;

    // create window buffer
    q->w = WINDOW(_create)(q->h_sub_len);

    // set default scaling
    q->scale = 1;

    // reset object and return
    FIRPFB(_reset)(q);
    return q;
}
Ejemplo n.º 3
0
// create a resamp2 object
//  _m      :   filter semi-length (effective length: 4*_m+1)
//  _fc     :   center frequency of half-band filter
//  _As     :   stop-band attenuation [dB], _As > 0
RESAMP2() RESAMP2(_create)(unsigned int _m,
                           float        _fc,
                           float        _As)
{
    // validate input
    if (_m < 2) {
        fprintf(stderr,"error: resamp2_%s_create(), filter semi-length must be at least 2\n", EXTENSION_FULL);
        exit(1);
    }

    RESAMP2() q = (RESAMP2()) malloc(sizeof(struct RESAMP2(_s)));
    q->m  = _m;
    q->fc = _fc;
    q->As = _As;
    if ( q->fc < -0.5f || q->fc > 0.5f ) {
        fprintf(stderr,"error: resamp2_%s_create(), fc (%12.4e) must be in (-1,1)\n", EXTENSION_FULL, q->fc);
        exit(1);
    }

    // change filter length as necessary
    q->h_len = 4*(q->m) + 1;
    q->h = (TC *) malloc((q->h_len)*sizeof(TC));

    q->h1_len = 2*(q->m);
    q->h1 = (TC *) malloc((q->h1_len)*sizeof(TC));

    // design filter prototype
    unsigned int i;
    float t, h1, h2;
    TC h3;
    float beta = kaiser_beta_As(q->As);
    for (i=0; i<q->h_len; i++) {
        t = (float)i - (float)(q->h_len-1)/2.0f;
        h1 = sincf(t/2.0f);
        h2 = kaiser(i,q->h_len,beta,0);
#if TC_COMPLEX == 1
        h3 = cosf(2.0f*M_PI*t*q->fc) + _Complex_I*sinf(2.0f*M_PI*t*q->fc);
#else
        h3 = cosf(2.0f*M_PI*t*q->fc);
#endif
        q->h[i] = h1*h2*h3;
    }

    // resample, alternate sign, [reverse direction]
    unsigned int j=0;
    for (i=1; i<q->h_len; i+=2)
        q->h1[j++] = q->h[q->h_len - i - 1];

    // create dotprod object
    q->dp = DOTPROD(_create)(q->h1, 2*q->m);

    // create window buffers
    q->w0 = WINDOW(_create)(2*(q->m));
    q->w1 = WINDOW(_create)(2*(q->m));

    RESAMP2(_clear)(q);

    return q;
}
Ejemplo n.º 4
0
void firpfbch_print(firpfbch _c)
{
    printf("firpfbch: [%u channels]\n", _c->num_channels);
    unsigned int i;
    for (i=0; i<_c->num_channels; i++) {
        DOTPROD(_print)(_c->dp[i]);
    }
}
Ejemplo n.º 5
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]));
    }
}
Ejemplo n.º 6
0
// create firhilb object
//  _m      :   filter semi-length (delay: 2*m+1)
//  _As     :   stop-band attenuation [dB]
FIRHILB() FIRHILB(_create)(unsigned int _m,
                           float        _As)
{
    // validate firhilb inputs
    if (_m < 2) {
        fprintf(stderr,"error: firhilb_create(), filter semi-length (m) must be at least 2\n");
        exit(1);
    }

    // allocate memory for main object
    FIRHILB() q = (FIRHILB()) malloc(sizeof(struct FIRHILB(_s)));
    q->m  = _m;         // filter semi-length
    q->As = fabsf(_As); // stop-band attenuation

    // set filter length and allocate memory for coefficients
    q->h_len = 4*(q->m) + 1;
    q->h     = (T *)         malloc((q->h_len)*sizeof(T));
    q->hc    = (T complex *) malloc((q->h_len)*sizeof(T complex));

    // allocate memory for quadrature filter component
    q->hq_len = 2*(q->m);
    q->hq     = (T *) malloc((q->hq_len)*sizeof(T));

    // compute filter coefficients for half-band filter
    liquid_firdes_kaiser(q->h_len, 0.25f, q->As, 0.0f, q->h);

    // alternate sign of non-zero elements
    unsigned int i;
    for (i=0; i<q->h_len; i++) {
        float t = (float)i - (float)(q->h_len-1)/2.0f;
        q->hc[i] = q->h[i] * cexpf(_Complex_I*0.5f*M_PI*t);
        q->h[i]  = cimagf(q->hc[i]);
    }

    // resample, reverse direction
    unsigned int j=0;
    for (i=1; i<q->h_len; i+=2)
        q->hq[j++] = q->h[q->h_len - i - 1];

    // create windows for upper and lower polyphase filter branches
    q->w1 = WINDOW(_create)(2*(q->m));
    q->w0 = WINDOW(_create)(2*(q->m));
    WINDOW(_clear)(q->w0);
    WINDOW(_clear)(q->w1);

    // create internal dot product object
    q->dpq = DOTPROD(_create)(q->hq, q->hq_len);

    // reset internal state and return object
    FIRHILB(_reset)(q);
    return q;
}
Ejemplo n.º 7
0
void firpfbch_destroy(firpfbch _c)
{
    unsigned int i;
    for (i=0; i<_c->num_channels; i++) {
        DOTPROD(_destroy)(_c->dp[i]);
        WINDOW(_destroy)(_c->w[i]);
    }
    free(_c->dp);
    free(_c->w);

    FFT_DESTROY_PLAN(_c->fft);
    free(_c->h);
    free(_c->x);
    free(_c->X);
    free(_c->X_prime);
    free(_c);
}
Ejemplo n.º 8
0
// create firfilt object
//  _h      :   coefficients (filter taps) [size: _n x 1]
//  _n      :   filter length
FIRFILT() FIRFILT(_create)(TC * _h,
                           unsigned int _n)
{
    // validate input
    if (_n == 0) {
        fprintf(stderr,"error: firfilt_%s_create(), filter length must be greater than zero\n", EXTENSION_FULL);
        exit(1);
    }

    // create filter object and initialize
    FIRFILT() q = (FIRFILT()) malloc(sizeof(struct FIRFILT(_s)));
    q->h_len = _n;
    q->h = (TC *) malloc((q->h_len)*sizeof(TC));

#if LIQUID_FIRFILT_USE_WINDOW
    // create window (internal buffer)
    q->w = WINDOW(_create)(q->h_len);
#else
    // initialize array for buffering
    q->w_len   = 1<<liquid_msb_index(q->h_len); // effectively 2^{floor(log2(len))+1}
    q->w_mask  = q->w_len - 1;
    q->w       = (TI *) malloc((q->w_len + q->h_len + 1)*sizeof(TI));
    q->w_index = 0;
#endif

    // load filter in reverse order
    unsigned int i;
    for (i=_n; i>0; i--)
        q->h[i-1] = _h[_n-i];

    // create dot product object
    q->dp = DOTPROD(_create)(q->h, q->h_len);

    // set default scaling
    q->scale = 1;

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

    return q;
}
Ejemplo n.º 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);
    }
}
Ejemplo n.º 10
0
// create decimator object
//  _M      :   decimation factor
//  _h      :   filter coefficients [size: _h_len x 1]
//  _h_len  :   filter coefficients length
FIRDECIM() FIRDECIM(_create)(unsigned int _M,
                             TC *         _h,
                             unsigned int _h_len)
{
    // validate input
    if (_h_len == 0) {
        fprintf(stderr,"error: decim_%s_create(), filter length must be greater than zero\n", EXTENSION_FULL);
        exit(1);
    } else if (_M == 0) {
        fprintf(stderr,"error: decim_%s_create(), decimation factor must be greater than zero\n", EXTENSION_FULL);
        exit(1);
    }

    FIRDECIM() q = (FIRDECIM()) malloc(sizeof(struct FIRDECIM(_s)));
    q->h_len = _h_len;
    q->M     = _M;

    // allocate memory for coefficients
    q->h = (TC*) malloc((q->h_len)*sizeof(TC));

    // load filter in reverse order
    unsigned int i;
    for (i=0; i<q->h_len; i++)
        q->h[i] = _h[_h_len-i-1];

    // create window (internal buffer)
    q->w = WINDOW(_create)(q->h_len);

    // create dot product object
    q->dp = DOTPROD(_create)(q->h, q->h_len);

    // reset filter state (clear buffer)
    FIRDECIM(_clear)(q);

    return q;
}
Ejemplo n.º 11
0
firpfbch firpfbch_create(unsigned int _num_channels,
                         unsigned int _m,
                         float _beta,
                         float _dt,
                         int _nyquist,
                         int _gradient)
{
    firpfbch c = (firpfbch) malloc(sizeof(struct firpfbch_s));
    c->num_channels = _num_channels;
    c->m            = _m;
    c->beta         = _beta;
    c->dt           = _dt;
    c->nyquist      = _nyquist;

    // validate inputs
    if (_m < 1) {
        printf("error: firpfbch_create(), invalid filter delay (must be greater than 0)\n");
        exit(1);
    }

    // create bank of filters
    c->dp   = (DOTPROD()*) malloc((c->num_channels)*sizeof(DOTPROD()));
    c->w    = (WINDOW()*) malloc((c->num_channels)*sizeof(WINDOW()));

    // design filter
    // TODO: use filter prototype object
    c->h_len = 2*(c->m)*(c->num_channels);
    c->h = (float*) malloc((c->h_len+1)*sizeof(float));

    if (c->nyquist == FIRPFBCH_NYQUIST) {
        float fc = 0.5f/(float)(c->num_channels);  // cutoff frequency
        liquid_firdes_kaiser(c->h_len+1, fc, c->beta, 0.0f, c->h);
    } else if (c->nyquist == FIRPFBCH_ROOTNYQUIST) {
        design_rkaiser_filter(c->num_channels, c->m, c->beta, c->dt, c->h);
    } else {
        printf("error: firpfbch_create(), unsupported nyquist flag: %d\n", _nyquist);
        exit(1);
    }
    
    unsigned int i;
    if (_gradient) {
        float dh[c->h_len];
        for (i=0; i<c->h_len; i++) {
            if (i==0) {
                dh[i] = c->h[i+1] - c->h[c->h_len-1];
            } else if (i==c->h_len-1) {
                dh[i] = c->h[0]   - c->h[i-1];
            } else {
                dh[i] = c->h[i+1] - c->h[i-1];
            }
        }
        memmove(c->h, dh, (c->h_len)*sizeof(float));
    }

    // generate bank of sub-samped filters
    unsigned int n;
    unsigned int h_sub_len = 2*(c->m);  // length of each sub-sampled filter
    float h_sub[h_sub_len];
    for (i=0; i<c->num_channels; i++) {
        // sub-sample prototype filter, loading coefficients in reverse order
        for (n=0; n<h_sub_len; n++) {
            h_sub[h_sub_len-n-1] = c->h[i + n*(c->num_channels)];
        }
        // create window buffer and dotprod object (coefficients
        // loaded in reverse order)
        c->dp[i] = DOTPROD(_create)(h_sub,h_sub_len);
        c->w[i]  = WINDOW(_create)(h_sub_len);

#if DEBUG_FIRPFBCH_PRINT
        printf("h_sub[%u] :\n", i);
        for (n=0; n<h_sub_len; n++)
            printf("  h[%3u] = %8.4f\n", n, h_sub[n]);
#endif
    }

#if DEBUG_FIRPFBCH_PRINT
    for (i=0; i<c->h_len+1; i++)
        printf("h(%4u) = %12.4e;\n", i+1, c->h[i]);
#endif

    // allocate memory for buffers
    // TODO : use fftw_malloc if HAVE_FFTW3_H
    c->x = (float complex*) malloc((c->num_channels)*sizeof(float complex));
    c->X = (float complex*) malloc((c->num_channels)*sizeof(float complex));
    c->X_prime = (float complex*) malloc((c->num_channels)*sizeof(float complex));
    firpfbch_clear(c);

    // create fft plan
    c->fft = FFT_CREATE_PLAN(c->num_channels, c->X, c->x, FFT_DIR_BACKWARD, FFT_METHOD);

    return c;
}
Ejemplo n.º 12
0
// create FIR polyphase filterbank channelizer object
//  _type   : channelizer type (LIQUID_ANALYZER | LIQUID_SYNTHESIZER)
//  _M      : number of channels
//  _p      : filter length (symbols)
//  _h      : filter coefficients, [size: _M*_p x 1]
FIRPFBCH() FIRPFBCH(_create)(int          _type,
                             unsigned int _M,
                             unsigned int _p,
                             TC *         _h)
{
    // validate input
    if (_type != LIQUID_ANALYZER && _type != LIQUID_SYNTHESIZER) {
        fprintf(stderr,"error: firpfbch_%s_create(), invalid type %d\n", EXTENSION_FULL, _type);
        exit(1);
    } else if (_M == 0) {
        fprintf(stderr,"error: firpfbch_%s_create(), number of channels must be greater than 0\n", EXTENSION_FULL);
        exit(1);
    } else if (_p == 0) {
        fprintf(stderr,"error: firpfbch_%s_create(), invalid filter size (must be greater than 0)\n", EXTENSION_FULL);
        exit(1);
    }

    // create main object
    FIRPFBCH() q = (FIRPFBCH()) malloc(sizeof(struct FIRPFBCH(_s)));

    // set user-defined properties
    q->type         = _type;
    q->num_channels = _M;
    q->p            = _p;

    // derived values
    q->h_len = q->num_channels * q->p;

    // create bank of filters
    q->dp = (DOTPROD()*) malloc((q->num_channels)*sizeof(DOTPROD()));
    q->w  = (WINDOW()*)  malloc((q->num_channels)*sizeof(WINDOW()));

    // copy filter coefficients
    q->h = (TC*) malloc((q->h_len)*sizeof(TC));
    unsigned int i;
    for (i=0; i<q->h_len; i++)
        q->h[i] = _h[i];

    // generate bank of sub-samped filters
    unsigned int n;
    unsigned int h_sub_len = q->p;
    TC h_sub[h_sub_len];
    for (i=0; i<q->num_channels; i++) {
        // sub-sample prototype filter, loading coefficients in reverse order
        for (n=0; n<h_sub_len; n++) {
            h_sub[h_sub_len-n-1] = q->h[i + n*(q->num_channels)];
        }
        // create window buffer and dotprod object (coefficients
        // loaded in reverse order)
        q->dp[i] = DOTPROD(_create)(h_sub,h_sub_len);
        q->w[i]  = WINDOW(_create)(h_sub_len);
    }

    // allocate memory for buffers
    // TODO : use fftw_malloc if HAVE_FFTW3_H
    q->x = (T*) malloc((q->num_channels)*sizeof(T));
    q->X = (T*) malloc((q->num_channels)*sizeof(T));

    // create fft plan
    if (q->type == LIQUID_ANALYZER)
        q->fft = FFT_CREATE_PLAN(q->num_channels, q->X, q->x, FFT_DIR_FORWARD, FFT_METHOD);
    else
        q->fft = FFT_CREATE_PLAN(q->num_channels, q->X, q->x, FFT_DIR_BACKWARD, FFT_METHOD);

    // reset filterbank object
    FIRPFBCH(_reset)(q);

    // return filterbank object
    return q;
}
Ejemplo n.º 13
0
// create FFT plan for regular DFT
//  _nfft   :   FFT size
//  _x      :   input array [size: _nfft x 1]
//  _y      :   output array [size: _nfft x 1]
//  _dir    :   fft direction: {LIQUID_FFT_FORWARD, LIQUID_FFT_BACKWARD}
//  _method :   fft method
FFT(plan) FFT(_create_plan_dft)(unsigned int _nfft,
                                TC *         _x,
                                TC *         _y,
                                int          _dir,
                                int          _flags)
{
    // allocate plan and initialize all internal arrays to NULL
    FFT(plan) q = (FFT(plan)) malloc(sizeof(struct FFT(plan_s)));

    q->nfft      = _nfft;
    q->x         = _x;
    q->y         = _y;
    q->flags     = _flags;
    q->type      = (_dir == LIQUID_FFT_FORWARD) ? LIQUID_FFT_FORWARD : LIQUID_FFT_BACKWARD;
    q->direction = (_dir == LIQUID_FFT_FORWARD) ? LIQUID_FFT_FORWARD : LIQUID_FFT_BACKWARD;
    q->method    = LIQUID_FFT_METHOD_DFT;
        
    q->data.dft.twiddle = NULL;
    q->data.dft.dotprod = NULL;

    // check size, use specific codelet for small DFTs
    if      (q->nfft == 2) q->execute = FFT(_execute_dft_2);
    else if (q->nfft == 3) q->execute = FFT(_execute_dft_3);
    else if (q->nfft == 4) q->execute = FFT(_execute_dft_4);
    else if (q->nfft == 5) q->execute = FFT(_execute_dft_5);
    else if (q->nfft == 6) q->execute = FFT(_execute_dft_6);
    else if (q->nfft == 7) q->execute = FFT(_execute_dft_7);
    else if (q->nfft == 8) q->execute = FFT(_execute_dft_8);
    else if (q->nfft == 16) q->execute = FFT(_execute_dft_16);
    else {
        q->execute = FFT(_execute_dft);

        // initialize twiddle factors
        q->data.dft.twiddle = (TC *) malloc(q->nfft * sizeof(TC));

        // create dotprod objects
        q->data.dft.dotprod = (DOTPROD()*) malloc(q->nfft * sizeof(DOTPROD()));
        
        // create dotprod objects
        // twiddles: exp(-j*2*pi*W/n), W=
        //  0   0   0   0   0...
        //  0   1   2   3   4...
        //  0   2   4   6   8...
        //  0   3   6   9   12...
        //  ...
        // Note that first row/column is zero, no multiplication necessary.
        // Create dotprod for first row anyway because it's still faster...
        unsigned int i;
        unsigned int k;
        T d = (q->direction == LIQUID_FFT_FORWARD) ? -1.0 : 1.0;
        for (i=0; i<q->nfft; i++) {
            // initialize twiddle factors
            // NOTE: no need to compute first twiddle because exp(-j*2*pi*0) = 1
            for (k=1; k<q->nfft; k++)
                q->data.dft.twiddle[k-1] = cexpf(_Complex_I*d*2*M_PI*(T)(k*i) / (T)(q->nfft));

            // create dotprod object
            q->data.dft.dotprod[i] = DOTPROD(_create)(q->data.dft.twiddle, q->nfft-1);
        }
    }

    return q;
}