Exemplo n.º 1
0
int main(int argc, char*argv[])
{
    srand(time(NULL));

    // options
    unsigned int k=2;                   // filter samples/symbol
    unsigned int m=5;                   // filter delay (symbols)
    float beta=0.3f;                    // bandwidth-time product
    float dt = 0.0f;                    // fractional sample timing offset
    unsigned int num_sync_symbols = 64; // number of synchronization symbols
    float SNRdB = 20.0f;                // signal-to-noise ratio [dB]
    float dphi = 0.02f;                 // carrier frequency offset
    float phi  = 2*M_PI*randf();        // carrier phase offset

    int dopt;
    while ((dopt = getopt(argc,argv,"uhk:m:n:b:t:F:t:S:")) != EOF) {
        switch (dopt) {
        case 'h': usage();                          return 0;
        case 'k': k = atoi(optarg);                 break;
        case 'm': m = atoi(optarg);                 break;
        case 'n': num_sync_symbols = atoi(optarg);  break;
        case 'b': beta = atof(optarg);              break;
        case 'F': dphi = atof(optarg);              break;
        case 't': dt = atof(optarg);                break;
        case 'S': SNRdB = atof(optarg);             break;
        default:
            exit(1);
        }
    }

    unsigned int i;

    // validate input
    if (beta <= 0.0f || beta >= 1.0f) {
        fprintf(stderr,"error: %s, bandwidth-time product must be in (0,1)\n", argv[0]);
        exit(1);
    } else if (dt < -0.5f || dt > 0.5f) {
        fprintf(stderr,"error: %s, fractional sample offset must be in [-0.5,0.5]\n", argv[0]);
        exit(1);
    }

    // derived values
    unsigned int num_symbols = num_sync_symbols + 2*m + 10;
    unsigned int num_samples = k*num_symbols;
    float nstd = powf(10.0f, -SNRdB/20.0f);

    // arrays
    float complex seq[num_sync_symbols];    // synchronization pattern (symbols)
    float complex s0[k*num_sync_symbols];   // synchronization pattern (samples)
    float complex x[num_samples];           // transmitted signal
    float complex y[num_samples];           // received signal
    float complex rxy[num_samples];         // pre-demod correlation output
    float dphi_hat[num_samples];            // carrier offset estimate

    // create transmit/receive interpolator/decimator
    firinterp_crcf interp = firinterp_crcf_create_prototype(LIQUID_FIRFILT_RRC,k,m,beta,dt);

    // generate synchronization pattern (BPSK) and interpolate
    for (i=0; i<num_sync_symbols + 2*m; i++) {
        float complex sym = 0.0f;
    
        if (i < num_sync_symbols) {
            sym = rand() % 2 ? -1.0f : 1.0f;
            seq[i] = sym;
        }

        if (i < 2*m) firinterp_crcf_execute(interp, sym, s0);
        else         firinterp_crcf_execute(interp, sym, &s0[k*(i-2*m)]);
    }

    // reset interpolator
    firinterp_crcf_reset(interp);

    // interpolate input
    for (i=0; i<num_symbols; i++) {
        float complex sym = i < num_sync_symbols ? seq[i] : 0.0f;

        firinterp_crcf_execute(interp, sym, &x[k*i]);
    }

    // push through channel
    for (i=0; i<num_samples; i++)
        y[i] = x[i]*cexpf(_Complex_I*(dphi*i + phi)) + nstd*(randnf() + _Complex_I*randnf())*M_SQRT1_2;

    // create cross-correlator
    bpresync_cccf sync = bpresync_cccf_create(s0, k*num_sync_symbols, 0.05f, 11);
    bpresync_cccf_print(sync);

    // push signal through cross-correlator
    float rxy_max  = 0.0f;  // maximum cross-correlation
    float dphi_est = 0.0f;  // carrier frequency offset estimate
    int delay_est  = 0;     // delay estimate
    for (i=0; i<num_samples; i++) {
        
        // correlate
        bpresync_cccf_push(sync, y[i]);
        bpresync_cccf_execute(sync, &rxy[i], &dphi_hat[i]);

        // detect...
        if (cabsf(rxy[i]) > 0.6f) {
            printf("****** preamble found, rxy = %12.8f (dphi-hat: %12.8f), i=%3u ******\n",
                    cabsf(rxy[i]), dphi_hat[i], i);
        }
        
        // retain maximum
        if (cabsf(rxy[i]) > rxy_max) {
            rxy_max   = cabsf(rxy[i]);
            dphi_est  = dphi_hat[i];
            delay_est = (int)i - (int)2*k*m + 1;
        }
    }

    // destroy objects
    firinterp_crcf_destroy(interp);
    bpresync_cccf_destroy(sync);
    
    // print results
    printf("\n");
    printf("rxy (max) : %12.8f\n", rxy_max);
    printf("dphi est. : %12.8f ,error=%12.8f\n",      dphi_est, dphi-dphi_est);
    printf("delay est.: %12d ,error=%3d sample(s)\n", delay_est, k*num_sync_symbols - delay_est);
    printf("\n");

    // 
    // export results
    //
    FILE * fid = fopen(OUTPUT_FILENAME,"w");
    fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME);
    fprintf(fid,"clear all\n");
    fprintf(fid,"close all\n");
    fprintf(fid,"num_samples = %u;\n", num_samples);
    fprintf(fid,"num_symbols = %u;\n", num_symbols);
    fprintf(fid,"k           = %u;\n", k);

    fprintf(fid,"x   = zeros(1,num_samples);\n");
    fprintf(fid,"y   = zeros(1,num_samples);\n");
    fprintf(fid,"rxy = zeros(1,num_samples);\n");
    for (i=0; i<num_samples; i++) {
        fprintf(fid,"x(%4u)     = %12.8f + j*%12.8f;\n", i+1, crealf(x[i]),   cimagf(x[i]));
        fprintf(fid,"y(%4u)     = %12.8f + j*%12.8f;\n", i+1, crealf(y[i]),   cimagf(y[i]));
        fprintf(fid,"rxy(%4u)   = %12.8f + j*%12.8f;\n", i+1, crealf(rxy[i]), cimagf(rxy[i]));
    }

    fprintf(fid,"t=[0:(num_samples-1)]/k;\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"subplot(2,1,1);\n");
    fprintf(fid,"  plot(t,real(y), t,imag(y));\n");
    fprintf(fid,"  axis([0 num_symbols -2 2]);\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"  xlabel('time');\n");
    fprintf(fid,"  ylabel('received signal');\n");
    fprintf(fid,"subplot(2,1,2);\n");
    fprintf(fid,"  plot(t,abs(rxy));\n");
    fprintf(fid,"  axis([0 num_symbols 0 1.5]);\n");
    fprintf(fid,"  xlabel('time');\n");
    fprintf(fid,"  ylabel('correlator output');\n");
    fprintf(fid,"  grid on;\n");

    fclose(fid);
    printf("results written to '%s'\n", OUTPUT_FILENAME);

    return 0;
}
Exemplo n.º 2
0
void bpresync_test(bpresync_cccf   _q,
                   float complex * _x,
                   unsigned int    _n,
                   float           _SNRdB,
                   float           _dphi_max,
                   float *         _rxy_max,
                   float *         _dphi_err,
                   float *         _delay_err,
                   unsigned int    _num_trials,
                   unsigned int    _verbosity)
{
    unsigned int max_delay = 64;
    float gamma = powf(10.0f, _SNRdB/20.0f);
    float nstd  = 1.0f;

    // Farrow filter (for facilitating delay)
    unsigned int h_len = 49;
    unsigned int order = 4;
    float        fc    = 0.45f;
    float        As    = 60.0f;
    firfarrow_crcf fdelay = firfarrow_crcf_create(h_len, order, fc, As);

    unsigned int num_samples = _n + max_delay + (h_len-1)/2;
    float complex y[num_samples];

    unsigned int t;
    for (t=0; t<_num_trials; t++) {
        unsigned int delay = rand() % max_delay;    // sample delay
        float        dt    = randf() - 0.5f;        // fractional sample delay
        float dphi = (2.0f*randf() - 1.0f) * _dphi_max; // carrier frequency offset
        float phi   = 2*M_PI*randf();                   // carrier phase offset

        // reset binary pre-demod synchronizer
        bpresync_cccf_reset(_q);

        // reset farrow filter
        firfarrow_crcf_clear(fdelay);
        firfarrow_crcf_set_delay(fdelay, dt);

        unsigned int i;
        unsigned int n=0;

        // generate signal: delay
        for (i=0; i<delay; i++) {
            firfarrow_crcf_push(fdelay, 0.0f);
            firfarrow_crcf_execute(fdelay, &y[n++]);
        }

        // generate signal: input sequence
        for (i=0; i<_n; i++) {
            firfarrow_crcf_push(fdelay, _x[i]);
            firfarrow_crcf_execute(fdelay, &y[n++]);
        }

        // generate signal: flush filter
        while (n < num_samples) {
            firfarrow_crcf_push(fdelay, 0.0f);
            firfarrow_crcf_execute(fdelay, &y[n++]);
        }

        // add channel gain, carrier offset, noise
        for (i=0; i<num_samples; i++) {
            y[i] *= gamma;
            y[i] *= cexpf(_Complex_I*(phi + i*dphi));
            y[i] += nstd*( randnf() + randnf()*_Complex_I )*M_SQRT1_2;
        }

        // push through synchronizer
        _rxy_max[t]   = 0.0f;
        _dphi_err[t]  = 0.0f;
        _delay_err[t] = 0.0f;
        for (i=0; i<num_samples; i++) {
            // push through correlator
            float complex rxy;
            float         dphi_est;
            bpresync_cccf_push(_q, y[i]);
            bpresync_cccf_correlate(_q, &rxy, &dphi_est);

            // retain maximum
            if ( cabsf(rxy) > _rxy_max[t] ) {
                _rxy_max[t]   = cabsf(rxy);
                _dphi_err[t]  = dphi_est - dphi;
                _delay_err[t] = (float)i - (float)(_n + delay + (h_len-1)/2) + 1.0f + dt;
            }
        }

        if (_verbosity == 0) {
            // do nothing
        } else if (_verbosity == 1) {
            // print progress bar
            if ( (t%100)==0 || t==_num_trials-1 ) {
                float percent = (float)(t+1) / (float)_num_trials;
                unsigned int bars = (unsigned int) (percent*60);
                printf("[");
                for (i=0; i<60; i++)
                    printf("%c", i < bars ? '#' : ' ');
                printf("] %5.1f%%\r", percent*100);
                fflush(stdout);
            }
        } else {
            // print every trial
            printf("  %6u:  rxy_max=%12.8f, dphi-err=%12.8f, delay-err=%12.8f\n",
                    t, _rxy_max[t], _dphi_err[t], _delay_err[t]);
        }

    }

    // destroy Farrow filter
    firfarrow_crcf_destroy(fdelay);
}