Beispiel #1
0
// Design root-Nyquist harris-Moerder filter using Parks-McClellan
// algorithm
//
//  _k      :   filter over-sampling rate (samples/symbol)
//  _m      :   filter delay (symbols)
//  _beta   :   filter excess bandwidth factor (0,1)
//  _dt     :   filter fractional sample delay
//  _h      :   resulting filter [size: 2*_k*_m+1]
void liquid_firdes_hM3(unsigned int _k,
                       unsigned int _m,
                       float _beta,
                       float _dt,
                       float * _h)
{
    if ( _k < 2 ) {
        fprintf(stderr,"error: liquid_firdes_hM3(): k must be greater than 1\n");
        exit(1);
    } else if ( _m < 1 ) {
        fprintf(stderr,"error: liquid_firdes_hM3(): m must be greater than 0\n");
        exit(1);
    } else if ( (_beta < 0.0f) || (_beta > 1.0f) ) {
        fprintf(stderr,"error: liquid_firdes_hM3(): beta must be in [0,1]\n");
        exit(1);
    } else;

    unsigned int n=2*_k*_m+1;       // filter length

    //
    float fc = 1.0 / (float)(2*_k); // filter cutoff
    float fp = fc*(1.0 - _beta);    // pass-band
    float fs = fc*(1.0 + _beta);    // stop-band

    // root nyquist
    unsigned int num_bands = 3;
    float bands[6]   = {0.0f, fp, fc, fc, fs, 0.5f};
    float des[3]     = {1.0f, 1.0f/sqrtf(2.0f), 0.0f};
    float weights[3] = {1.0f, 1.0f, 1.0f};

    liquid_firdespm_btype btype = LIQUID_FIRDESPM_BANDPASS;
    liquid_firdespm_wtype wtype[3] = {LIQUID_FIRDESPM_FLATWEIGHT,
                                      LIQUID_FIRDESPM_FLATWEIGHT,
                                      LIQUID_FIRDESPM_EXPWEIGHT};

    //unsigned int i;
    float h[n];
    firdespm_run(n,num_bands,bands,des,weights,wtype,btype,h);
    // copy results
    memmove(_h, h, n*sizeof(float));

    float isi_max;
    float isi_rms;
    liquid_filter_isi(h,_k,_m,&isi_rms,&isi_max);

    // iterate...
    float isi_rms_min = isi_rms;
    unsigned int p, pmax=100;
    for (p=0; p<pmax; p++) {
        // increase pass-band edge
        fp = fc*(1.0 - _beta * p / (float)(pmax) );
        bands[1] = fp;

        // execute filter design
        firdespm_run(n,num_bands,bands,des,weights,wtype,btype,h);

        // compute inter-symbol interference (MSE, max)
        liquid_filter_isi(h,_k,_m,&isi_rms,&isi_max);

#if DEBUG_hM3
        printf("  isi mse : %20.8e (min: %20.8e)\n", isi_rms, isi_rms_min);
#endif
        if (isi_rms > isi_rms_min) {
            // search complete
            break;
        } else {
            isi_rms_min = isi_rms;
            // copy results
            memmove(_h, h, n*sizeof(float));
        }
    };

    // normalize
    float e2 = 0.0f;
    unsigned int i;
    for (i=0; i<n; i++) e2 += _h[i]*_h[i];
    for (i=0; i<n; i++) _h[i] *= sqrtf(_k/e2);
}
Beispiel #2
0
// Design (root-)Nyquist filter from prototype
//  _type   : filter type (e.g. LIQUID_FIRFILT_RRRC)
//  _k      : samples/symbol
//  _m      : symbol delay
//  _beta   : excess bandwidth factor, _beta in [0,1]
//  _dt     : fractional sample delay
//  _h      : output coefficient buffer (length: 2*k*m+1)
void liquid_firdes_prototype(liquid_firfilt_type _type,
                             unsigned int        _k,
                             unsigned int        _m,
                             float               _beta,
                             float               _dt,
                             float *             _h)
{
    // compute filter parameters
    unsigned int h_len = 2*_k*_m + 1;   // length
    float fc = 0.5f / (float)_k;        // cut-off frequency
    float df = _beta / (float)_k;       // transition bandwidth
    float As = estimate_req_filter_As(df,h_len);   // stop-band attenuation

    // Parks-McClellan algorithm parameters
    float bands[6] = {  0.0f,       fc-0.5f*df,
                        fc,         fc,
                        fc+0.5f*df, 0.5f};
    float des[3] = { (float)_k, 0.5f*_k, 0.0f };
    float weights[3] = {1.0f, 1.0f, 1.0f};
    liquid_firdespm_wtype wtype[3] = {  LIQUID_FIRDESPM_FLATWEIGHT,
                                        LIQUID_FIRDESPM_FLATWEIGHT,
                                        LIQUID_FIRDESPM_FLATWEIGHT};

    switch (_type) {
    
    // Nyquist filter prototypes

    case LIQUID_FIRFILT_KAISER:
        liquid_firdes_kaiser(h_len, fc, As, _dt, _h);
        break;
    case LIQUID_FIRFILT_PM:
        // WARNING: input timing offset is ignored here
        firdespm_run(h_len, 3, bands, des, weights, wtype, LIQUID_FIRDESPM_BANDPASS, _h);
        break;
    case LIQUID_FIRFILT_RCOS:
        liquid_firdes_rcos(_k, _m, _beta, _dt, _h);
        break;
    case LIQUID_FIRFILT_FEXP:
        liquid_firdes_fexp(_k, _m, _beta, _dt, _h);
        break;
    case LIQUID_FIRFILT_FSECH:
        liquid_firdes_fsech(_k, _m, _beta, _dt, _h);
        break;
    case LIQUID_FIRFILT_FARCSECH:
        liquid_firdes_farcsech(_k, _m, _beta, _dt, _h);
        break;

    // root-Nyquist filter prototypes

    case LIQUID_FIRFILT_ARKAISER:
        liquid_firdes_arkaiser(_k, _m, _beta, _dt, _h);
        break;
    case LIQUID_FIRFILT_RKAISER:
        liquid_firdes_rkaiser(_k, _m, _beta, _dt, _h);
        break;
    case LIQUID_FIRFILT_RRC:
        liquid_firdes_rrcos(_k, _m, _beta, _dt, _h);
        break;
    case LIQUID_FIRFILT_hM3:
        liquid_firdes_hM3(_k, _m, _beta, _dt, _h);
        break;
    case LIQUID_FIRFILT_GMSKTX:
        liquid_firdes_gmsktx(_k, _m, _beta, _dt, _h);
        break;
    case LIQUID_FIRFILT_GMSKRX:
        liquid_firdes_gmskrx(_k, _m, _beta, _dt, _h);
        break;
    case LIQUID_FIRFILT_RFEXP:
        liquid_firdes_rfexp(_k, _m, _beta, _dt, _h);
        break;
    case LIQUID_FIRFILT_RFSECH:
        liquid_firdes_rfsech(_k, _m, _beta, _dt, _h);
        break;
    case LIQUID_FIRFILT_RFARCSECH:
        liquid_firdes_rfarcsech(_k, _m, _beta, _dt, _h);
        break;
    default:
        fprintf(stderr,"error: liquid_firdes_prototype(), invalid root-Nyquist filter type '%d'\n", _type);
        exit(1);
    }
}