Ejemplo n.º 1
0
int main(int argc, char*argv[])
{
    srand(time(NULL));
    // options
    unsigned int k=2;                   // filter samples/symbol
    unsigned int m=4;                   // 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 data symbols
    float SNRdB = 30.0f;                // signal-to-noise ratio [dB]
    float dphi = 0.0f;                  // carrier frequency offset
    float phi  = 0.0f;                  // carrier phase offset
    
    unsigned int num_delay_symbols = 12;
    unsigned int num_dphi_hat = 21;     // number of frequency offset estimates
    float dphi_hat_step = 0.01f;        // frequency offset step size

    int dopt;
    while ((dopt = getopt(argc,argv,"uhk:m:n:b:t:F:P: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 't': dt    = atof(optarg); break;
        case 'F': dphi  = atof(optarg); break;
        case 'P': phi   = 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.5 || dt > 0.5) {
        fprintf(stderr,"error: %s, fractional sample offset must be in (0,1)\n", argv[0]);
        exit(1);
    }

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

    // arrays
    float complex seq[num_sync_symbols];    // data sequence (symbols)
    float complex s0[num_sync_samples];     // data sequence (interpolated samples)
    float complex x[num_samples];           // transmitted signal
    float complex y[num_samples];           // received signal
    float rxy[num_dphi_hat][num_samples];   // pre-demod output matrix

    // generate sequence
    for (i=0; i<num_sync_symbols; i++) {
        float sym_i = rand() % 2 ? M_SQRT1_2 : -M_SQRT1_2;
        float sym_q = rand() % 2 ? M_SQRT1_2 : -M_SQRT1_2;
        seq[i] = sym_i + _Complex_I*sym_q;
    }

    // create interpolated sequence, compensating for filter delay
    firinterp_crcf interp_seq = firinterp_crcf_create_rnyquist(LIQUID_RNYQUIST_RRC,k,m,beta,0.0f);
    for (i=0; i<num_sync_symbols+m; i++) {
        if      (i < m)                firinterp_crcf_execute(interp_seq, seq[i], &s0[0]);
        else if (i < num_sync_symbols) firinterp_crcf_execute(interp_seq, seq[i], &s0[k*(i-m)]);
        else                           firinterp_crcf_execute(interp_seq,      0, &s0[k*(i-m)]);
    }
    firinterp_crcf_destroy(interp_seq);
    
    // compute g = E{ |s0|^2 }
    float g = 0.0f;
    for (i=0; i<num_sync_samples; i++)
        g += crealf( s0[i]*conjf(s0[i]) );

    // create transmit interpolator and generate sequence
    firinterp_crcf interp_tx = firinterp_crcf_create_rnyquist(LIQUID_RNYQUIST_RRC,k,m,beta,dt);
    unsigned int n=0;
    for (i=0; i<num_delay_symbols; i++) {
        firinterp_crcf_execute(interp_tx, 0, &x[k*n]);
        n++;
    }
    for (i=0; i<num_sync_symbols; i++) {
        firinterp_crcf_execute(interp_tx, seq[i], &x[k*n]);
        n++;
    }
    for (i=0; i<2*m; i++) {
        firinterp_crcf_execute(interp_tx, 0, &x[k*n]);
        n++;
    }
    assert(n==num_symbols);
    firinterp_crcf_destroy(interp_tx);

    // add channel impairments
    for (i=0; i<num_samples; i++) {
        y[i] = x[i]*cexp(_Complex_I*(dphi*i + phi)) + nstd*( randnf() + _Complex_I*randnf() );
    }

    float complex z;    // filter output sample
    for (n=0; n<num_dphi_hat; n++) {
        float dphi_hat = ((float)n - 0.5*(float)(num_dphi_hat-1)) * dphi_hat_step;
        printf("  dphi_hat : %12.8f\n", dphi_hat);

        // create flipped, conjugated coefficients
        float complex s1[num_sync_samples];
        for (i=0; i<num_sync_samples; i++)
            s1[i] = conjf( s0[num_sync_samples-i-1]*cexpf(_Complex_I*(dphi_hat*i)) );

        // create matched filter and detect signal
        firfilt_cccf fsync = firfilt_cccf_create(s1, num_sync_samples);
        for (i=0; i<num_samples; i++) {
            firfilt_cccf_push(fsync, y[i]);
            firfilt_cccf_execute(fsync, &z);

            rxy[n][i] = cabsf(z) / g;
        }
        // destroy filter
        firfilt_cccf_destroy(fsync);
    }
    
    // print results
    //printf("rxy (max) : %12.8f\n", rxy_max);

    // 
    // 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,"k = %u;\n", k);
    fprintf(fid,"m = %u;\n", m);
    fprintf(fid,"beta = %f;\n", beta);
    fprintf(fid,"num_sync_symbols = %u;\n", num_sync_symbols);
    fprintf(fid,"num_sync_samples = k*num_sync_symbols;\n");
    fprintf(fid,"num_symbols = %u;\n", num_symbols);
    fprintf(fid,"num_samples = %u;\n", num_samples);
    fprintf(fid,"num_dphi_hat = %u;\n", num_dphi_hat);
    fprintf(fid,"dphi_hat_step = %f;\n", dphi_hat_step);

    // save sequence symbols
    fprintf(fid,"seq = zeros(1,num_sync_symbols);\n");
    for (i=0; i<num_sync_symbols; i++)
        fprintf(fid,"seq(%4u)   = %12.8f + j*%12.8f;\n", i+1, crealf(seq[i]), cimagf(seq[i]));

    // save interpolated sequence
    fprintf(fid,"s   = zeros(1,num_sync_samples);\n");
    for (i=0; i<num_sync_samples; i++)
        fprintf(fid,"s(%4u)     = %12.8f + j*%12.8f;\n", i+1, crealf(s0[i]), cimagf(s0[i]));

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

    // save cross-correlation output
    fprintf(fid,"rxy = zeros(num_dphi_hat,num_samples);\n");
    for (n=0; n<num_dphi_hat; n++) {
        for (i=0; i<num_samples; i++) {
            fprintf(fid,"rxy(%6u,%6u) = %12.8f;\n", n+1, i+1, rxy[n][i]);
        }
    }
    fprintf(fid,"t=[0:(num_samples-1)]/k;\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(1:length(s),real(s), 1:length(s),imag(s));\n");
    
    fprintf(fid,"dphi_hat = ( [0:(num_dphi_hat-1)] - (num_dphi_hat-1)/2 ) * dphi_hat_step;\n");
    fprintf(fid,"mesh(dphi_hat, t, rxy');\n");
    
#if 0
    fprintf(fid,"z = abs( z );\n");
    fprintf(fid,"[zmax i] = max(z);\n");
    fprintf(fid,"plot(1:length(z),z,'-x');\n");
    fprintf(fid,"axis([(i-8*k) (i+8*k) 0 zmax*1.2]);\n");
    fprintf(fid,"grid on\n");
#endif

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

    return 0;
}
int main(int argc, char*argv[]) {
    srand(time(NULL));

    // options
    unsigned int k           =   2;     // samples/symbol (input)
    unsigned int k_out       =   2;     // samples/symbol (output)
    unsigned int m           =   5;     // filter delay (symbols)
    float        beta        =   0.5f;  // filter excess bandwidth factor
    unsigned int num_filters =  32;     // number of filters in the bank
    unsigned int num_symbols = 400;     // number of data symbols
    float        SNRdB       =  30.0f;  // signal-to-noise ratio

    // transmit/receive filter types
    liquid_firfilt_type ftype_tx = LIQUID_FIRFILT_RRC;
    liquid_firfilt_type ftype_rx = LIQUID_FIRFILT_RRC;

    float bt    =  0.02f;       // loop filter bandwidth
    float tau   = -0.2f;        // fractional symbol offset
    float r     =    1.00f;     // resampled rate
    
    // use random data or 101010 phasing pattern
    int random_data=1;

    int dopt;
    while ((dopt = getopt(argc,argv,"hT:k:K:m:b:B:s:w:n:t:r:")) != EOF) {
        switch (dopt) {
        case 'h':   usage();                        return 0;
        case 'T':
            if (strcmp(optarg,"gmsk")==0) {
                ftype_tx = LIQUID_FIRFILT_GMSKTX;
                ftype_rx = LIQUID_FIRFILT_GMSKRX;
            } else {
                ftype_tx = liquid_getopt_str2firfilt(optarg);
                ftype_rx = liquid_getopt_str2firfilt(optarg);
            }
            if (ftype_tx == LIQUID_FIRFILT_UNKNOWN) {
                fprintf(stderr,"error: %s, unknown filter type '%s'\n", argv[0], optarg);
                exit(1);
            }
            break;
        case 'k':   k           = atoi(optarg);     break;
        case 'K':   k_out       = atoi(optarg);     break;
        case 'm':   m           = atoi(optarg);     break;
        case 'b':   beta        = atof(optarg);     break;
        case 'B':   num_filters = atoi(optarg);     break;
        case 's':   SNRdB       = atof(optarg);     break;
        case 'w':   bt          = atof(optarg);     break;
        case 'n':   num_symbols = atoi(optarg);     break;
        case 't':   tau         = atof(optarg);     break;
        case 'r':   r           = atof(optarg);     break;
        default:
            exit(1);
        }
    }

    // validate input
    if (k < 2) {
        fprintf(stderr,"error: k (samples/symbol) must be at least 2\n");
        exit(1);
    } else if (m < 1) {
        fprintf(stderr,"error: m (filter delay) must be greater than 0\n");
        exit(1);
    } else if (beta <= 0.0f || beta > 1.0f) {
        fprintf(stderr,"error: beta (excess bandwidth factor) must be in (0,1]\n");
        exit(1);
    } else if (num_filters == 0) {
        fprintf(stderr,"error: number of polyphase filters must be greater than 0\n");
        exit(1);
    } else if (bt <= 0.0f) {
        fprintf(stderr,"error: timing PLL bandwidth must be greater than 0\n");
        exit(1);
    } else if (num_symbols == 0) {
        fprintf(stderr,"error: number of symbols must be greater than 0\n");
        exit(1);
    } else if (tau < -1.0f || tau > 1.0f) {
        fprintf(stderr,"error: timing phase offset must be in [-1,1]\n");
        exit(1);
    } else if (r < 0.5f || r > 2.0f) {
        fprintf(stderr,"error: timing frequency offset must be in [0.5,2]\n");
        exit(1);
    }

    // compute delay
    while (tau < 0) tau += 1.0f;    // ensure positive tau
    float g = k*tau;                // number of samples offset
    int ds=floorf(g);               // additional symbol delay
    float dt = (g - (float)ds);     // fractional sample offset
    if (dt > 0.5f) {                // force dt to be in [0.5,0.5]
        dt -= 1.0f;
        ds++;
    }

    unsigned int i, n=0;

    unsigned int num_samples = k*num_symbols;
    unsigned int num_samples_resamp = (unsigned int) ceilf(num_samples*r*1.1f) + 4;
    float complex s[num_symbols];           // data symbols
    float complex x[num_samples];           // interpolated samples
    float complex y[num_samples_resamp];    // resampled data (resamp_crcf)
    float complex z[k_out*num_symbols + 64];// synchronized samples
    float complex sym_out[num_symbols + 64];// synchronized symbols

    for (i=0; i<num_symbols; i++) {
        if (random_data) {
            // random signal (QPSK)
            s[i]  = cexpf(_Complex_I*0.5f*M_PI*((rand() % 4) + 0.5f));
        } else {
            s[i] = (i%2) ? 1.0f : -1.0f;  // 101010 phasing pattern
        }
    }

    // 
    // create and run interpolator
    //

    // design interpolating filter
    unsigned int h_len = 2*k*m+1;
    float h[h_len];
    liquid_firdes_rnyquist(ftype_tx,k,m,beta,dt,h);
    firinterp_crcf q = firinterp_crcf_create(k,h,h_len);
    for (i=0; i<num_symbols; i++) {
        firinterp_crcf_execute(q, s[i], &x[n]);
        n+=k;
    }
    assert(n == num_samples);
    firinterp_crcf_destroy(q);

    // 
    // run resampler
    //
    unsigned int resamp_len = 10*k; // resampling filter semi-length (filter delay)
    float resamp_bw = 0.45f;        // resampling filter bandwidth
    float resamp_As = 60.0f;        // resampling filter stop-band attenuation
    unsigned int resamp_npfb = 64;  // number of filters in bank
    resamp_crcf f = resamp_crcf_create(r, resamp_len, resamp_bw, resamp_As, resamp_npfb);
    unsigned int num_samples_resampled = 0;
    unsigned int num_written;
    for (i=0; i<num_samples; i++) {
#if 0
        // bypass arbitrary resampler
        y[i] = x[i];
        num_samples_resampled = num_samples;
#else
        // TODO : compensate for resampler filter delay
        resamp_crcf_execute(f, x[i], &y[num_samples_resampled], &num_written);
        num_samples_resampled += num_written;
#endif
    }
    resamp_crcf_destroy(f);

    // 
    // add noise
    //
    float nstd = powf(10.0f, -SNRdB/20.0f);
    for (i=0; i<num_samples_resampled; i++)
        y[i] += nstd*(randnf() + _Complex_I*randnf());


    // 
    // create and run symbol synchronizer
    //

    symsync_crcf d = symsync_crcf_create_rnyquist(ftype_rx, k, m, beta, num_filters);
    symsync_crcf_set_lf_bw(d,bt);
    symsync_crcf_set_output_rate(d,k_out);

    unsigned int num_samples_sync=0;
    unsigned int nn;
    unsigned int num_symbols_sync = 0;
    float tau_hat[num_samples];
    for (i=ds; i<num_samples_resampled; i++) {
        tau_hat[num_samples_sync] = symsync_crcf_get_tau(d);
        symsync_crcf_execute(d, &y[i], 1, &z[num_samples_sync], &nn);

        // decimate
        unsigned int j;
        for (j=0; j<nn; j++) {
            if ( (num_samples_sync%k_out)==0 )
                sym_out[num_symbols_sync++] = z[num_samples_sync];
            num_samples_sync++;
        }
    }
    symsync_crcf_destroy(d);

    // print last several symbols to screen
    printf("output symbols:\n");
    printf("  ...\n");
    for (i=num_symbols_sync-10; i<num_symbols_sync; i++)
        printf("  sym_out(%2u) = %8.4f + j*%8.4f;\n", i+1, crealf(sym_out[i]), cimagf(sym_out[i]));

    //
    // export output file
    //

    FILE* fid = fopen(OUTPUT_FILENAME,"w");
    fprintf(fid,"%% %s, auto-generated file\n\n", OUTPUT_FILENAME);
    fprintf(fid,"close all;\nclear all;\n\n");

    fprintf(fid,"k=%u;\n",k);
    fprintf(fid,"m=%u;\n",m);
    fprintf(fid,"beta=%12.8f;\n",beta);
    fprintf(fid,"k_out=%u;\n",k_out);
    fprintf(fid,"num_filters=%u;\n",num_filters);
    fprintf(fid,"num_symbols=%u;\n",num_symbols);

    for (i=0; i<h_len; i++)
        fprintf(fid,"h(%3u) = %12.5f;\n", i+1, h[i]);

    for (i=0; i<num_symbols; i++)
        fprintf(fid,"s(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(s[i]), cimagf(s[i]));

    for (i=0; i<num_samples; i++)
        fprintf(fid,"x(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(x[i]), cimagf(x[i]));
        
    for (i=0; i<num_samples_resampled; i++)
        fprintf(fid,"y(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(y[i]), cimagf(y[i]));
        
    for (i=0; i<num_samples_sync; i++)
        fprintf(fid,"z(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(z[i]), cimagf(z[i]));
        
    for (i=0; i<num_symbols_sync; i++)
        fprintf(fid,"sym_out(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(sym_out[i]), cimagf(sym_out[i]));
        
    for (i=0; i<num_samples_sync; i++)
        fprintf(fid,"tau_hat(%3u) = %12.8f;\n", i+1, tau_hat[i]);


    fprintf(fid,"\n\n");
    fprintf(fid,"%% scale QPSK in-phase by sqrt(2)\n");
    fprintf(fid,"z = z*sqrt(2);\n");
    fprintf(fid,"\n\n");
    fprintf(fid,"tz = [0:length(z)-1]/k_out;\n");
    fprintf(fid,"iz = 1:k_out:length(z);\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(tz,     real(z),    '-',...\n");
    fprintf(fid,"     tz(iz), real(z(iz)),'or');\n");
    fprintf(fid,"xlabel('Time');\n");
    fprintf(fid,"ylabel('Output Signal (real)');\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"legend('output time series','optimum timing','location','northeast');\n");

    fprintf(fid,"iz0 = iz( 1:round(length(iz)*0.5) );\n");
    fprintf(fid,"iz1 = iz( round(length(iz)*0.5):length(iz) );\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"hold on;\n");
    fprintf(fid,"plot(real(z(iz0)),imag(z(iz0)),'x','MarkerSize',4,'Color',[0.6 0.6 0.6]);\n");
    fprintf(fid,"plot(real(z(iz1)),imag(z(iz1)),'o','MarkerSize',4,'Color',[0 0.25 0.5]);\n");
    fprintf(fid,"hold off;\n");
    fprintf(fid,"axis square;\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"axis([-1 1 -1 1]*2.0);\n");
    fprintf(fid,"xlabel('In-phase');\n");
    fprintf(fid,"ylabel('Quadrature');\n");
    fprintf(fid,"legend(['first 50%%'],['last 50%%'],'location','northeast');\n");

    fprintf(fid,"figure;\n");
    fprintf(fid,"tt = 0:(length(tau_hat)-1);\n");
    fprintf(fid,"b = floor(num_filters*tau_hat + 0.5);\n");
    fprintf(fid,"stairs(tt,tau_hat*num_filters);\n");
    fprintf(fid,"hold on;\n");
    fprintf(fid,"plot(tt,b,'-k','Color',[0 0 0]);\n");
    fprintf(fid,"hold off;\n");
    fprintf(fid,"xlabel('time');\n");
    fprintf(fid,"ylabel('filterbank index');\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"axis([0 length(tau_hat) -1 num_filters]);\n");

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

    // clean it up
    printf("done.\n");
    return 0;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
int main(int argc, char*argv[]) {
    // options
    unsigned int k=2;                   // samples/symbol
    unsigned int m=2;                   // filter delay
    float beta = 0.5f;                  // filter excess bandwidth
    unsigned int num_data_symbols=8;    // number of data symbols

    int dopt;
    while ((dopt = getopt(argc,argv,"uhk:m:b:n:")) != EOF) {
        switch (dopt) {
        case 'u':
        case 'h': usage();                          return 0;
        case 'k': k = atoi(optarg);                 break;
        case 'm': m = atoi(optarg);                 break;
        case 'b': beta = atof(optarg);              break;
        case 'n': num_data_symbols = atoi(optarg);  break;
        default:
            usage();
            return 1;
        }
    }

    // validate options
    if (k < 2) {
        fprintf(stderr,"error: %s, interp factor must be greater than 1\n", argv[0]);
        return 1;
    } else if (m < 1) {
        fprintf(stderr,"error: %s, filter delay must be greater than 0\n", argv[0]);
        return 1;
    } else if (beta <= 0.0 || beta > 1.0f) {
        fprintf(stderr,"error: %s, beta (excess bandwidth factor) must be in (0,1]\n", argv[0]);
        return 1;
    } else if (num_data_symbols < 1) {
        fprintf(stderr,"error: %s, must have at least one data symbol\n", argv[0]);
        return 1;
    }

    // derived values
    unsigned int h_len = 2*k*m+1;
    unsigned int num_symbols = num_data_symbols + 2*m;
    unsigned int num_samples = k*num_symbols;

    // design filter and create interpolator and decimator objects
    float h[h_len];     // transmit filter
    float g[h_len];     // receive filter (reverse of h)
    liquid_firdes_rrcos(k,m,beta,0.3f,h);
    unsigned int i;
    for (i=0; i<h_len; i++)
        g[i] = h[h_len-i-1];
    firinterp_crcf interp = firinterp_crcf_create(k,h,h_len);
    firdecim_crcf  decim  = firdecim_crcf_create(k,g,h_len);

    // allocate memory for buffers
    float complex x[num_symbols];   // input symbols
    float complex y[num_samples];   // interpolated sequence
    float complex z[num_symbols];   // decimated (received) symbols

    // generate input symbols, padded with zeros at the end
    for (i=0; i<num_data_symbols; i++) {
        x[i] = (rand() % 2 ? 1.0f : -1.0f) +
               (rand() % 2 ? 1.0f : -1.0f) * _Complex_I;
    }
    for ( ; i<num_symbols; i++)
        x[i] = 0.0f;

    // run interpolator
    for (i=0; i<num_symbols; i++) {
        firinterp_crcf_execute(interp, x[i], &y[k*i]);
    }

    // run decimator
    for (i=0; i<num_symbols; i++) {
        firdecim_crcf_execute(decim, &y[k*i], &z[i]);

        // normalize output by samples/symbol
        z[i] /= k;
    }

    // destroy objects
    firinterp_crcf_destroy(interp);
    firdecim_crcf_destroy(decim);

    // print results to screen
    printf("filter impulse response :\n");
    for (i=0; i<h_len; i++)
        printf("  [%4u] : %8.4f\n", i, h[i]);

    printf("input symbols\n");
    for (i=0; i<num_symbols; i++) {
        printf("  [%4u] : %8.4f + j*%8.4f", i, crealf(x[i]), cimagf(x[i]));

        // highlight actual data symbols
        if (i < num_data_symbols) printf(" *\n");
        else                      printf("\n");
    }

    printf("interpolator output samples:\n");
    for (i=0; i<num_samples; i++) {
        printf("  [%4u] : %8.4f + j*%8.4f", i, crealf(y[i]), cimagf(y[i]));

        if ( (i >= k*m) && ((i%k)==0))  printf(" **\n");
        else                            printf("\n");
    }

    printf("output symbols:\n");
    for (i=0; i<num_symbols; i++) {
        printf("  [%4u] : %8.4f + j*%8.4f", i, crealf(z[i]), cimagf(z[i]));

        // highlight symbols (compensate for filter delay)
        if ( i < 2*m ) printf("\n");
        else           printf(" *\n");
    }

    // open output file
    FILE * fid = fopen(OUTPUT_FILENAME,"w");
    fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME);
    fprintf(fid,"clear all;\n");
    fprintf(fid,"close all;\n");
    fprintf(fid,"k = %u;\n", k);
    fprintf(fid,"m = %u;\n", m);
    fprintf(fid,"h_len=%u;\n",h_len);
    fprintf(fid,"num_symbols = %u;\n", num_symbols);
    fprintf(fid,"num_samples = k*num_symbols;\n");
    fprintf(fid,"h = zeros(1,h_len);\n");
    fprintf(fid,"x = zeros(1,num_symbols);\n");
    fprintf(fid,"y = zeros(1,num_samples);\n");

    for (i=0; i<h_len; i++)
        fprintf(fid,"h(%4u) = %12.4e;\n", i+1, h[i]);

    for (i=0; i<num_symbols; i++)
        fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(x[i]), cimagf(x[i]));

    for (i=0; i<num_samples; i++)
        fprintf(fid,"y(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(y[i]), cimagf(y[i]));

    for (i=0; i<num_symbols; i++)
        fprintf(fid,"z(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(z[i]), cimagf(z[i]));

    fprintf(fid,"\n\n");
    fprintf(fid,"tx = [0:(num_symbols-1)];\n");
    fprintf(fid,"ty = [0:(num_samples-1)]/k - m;\n");
    fprintf(fid,"tz = [0:(num_symbols-1)] - 2*m;\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"subplot(2,1,1);\n");
    fprintf(fid,"    plot(ty,real(y),'-',tx,real(x),'s',tz,real(z),'x');\n");
    fprintf(fid,"    xlabel('time');\n");
    fprintf(fid,"    ylabel('real');\n");
    fprintf(fid,"    grid on;\n");
    fprintf(fid,"    legend('interp','data in','data out',0);\n");
    fprintf(fid,"subplot(2,1,2);\n");
    fprintf(fid,"    plot(ty,imag(y),'-',tx,imag(x),'s',tz,imag(z),'x');\n");
    fprintf(fid,"    xlabel('time');\n");
    fprintf(fid,"    ylabel('imag');\n");
    fprintf(fid,"    grid on;\n");

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

    printf("done.\n");
    return 0;
}
Ejemplo n.º 5
0
int main(int argc, char*argv[])
{
    // options
    float        noise_floor= -40.0f;   // noise floor [dB]
    float        SNRdB      = 20.0f;    // signal-to-noise ratio [dB]
    float        bt         = 0.05f;    // loop bandwidth
    unsigned int num_symbols= 100;      // number of iterations
    unsigned int d          = 5;        // print every d iterations

    unsigned int k          = 2;        // interpolation factor (samples/symbol)
    unsigned int m          = 3;        // filter delay (symbols)
    float        beta       = 0.3f;     // filter excess bandwidth factor
    float        dt         = 0.0f;     // filter fractional sample delay

    // derived values
    unsigned int num_samples=num_symbols*k;
    float gamma = powf(10.0f, (SNRdB+noise_floor)/20.0f);   // channel gain
    float nstd = powf(10.0f, noise_floor / 20.0f);

    // arrays
    float complex x[num_samples];
    float complex y[num_samples];
    float rssi[num_samples];

    // create objects
    modem mod = modem_create(LIQUID_MODEM_QPSK);
    firinterp_crcf interp = firinterp_crcf_create_prototype(LIQUID_FIRFILT_RRC,k,m,beta,dt);
    agc_crcf p = agc_crcf_create();
    agc_crcf_set_bandwidth(p, bt);

    unsigned int i;

    // print info
    printf("automatic gain control // loop bandwidth: %4.2e\n",bt);

    unsigned int sym;
    float complex s;
    for (i=0; i<num_symbols; i++) {
        // generate random symbol
        sym = modem_gen_rand_sym(mod);
        modem_modulate(mod, sym, &s);
        s *= gamma;

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

    // add noise
    for (i=0; i<num_samples; i++)
        x[i] += nstd*(randnf() + _Complex_I*randnf()) * M_SQRT1_2;

    // run agc
    for (i=0; i<num_samples; i++) {
        agc_crcf_execute(p, x[i], &y[i]);

        rssi[i] = agc_crcf_get_rssi(p);
    }

    // destroy objects
    modem_destroy(mod);
    agc_crcf_destroy(p);
    firinterp_crcf_destroy(interp);

    // print results to screen
    printf("received signal strength indication (rssi):\n");
    for (i=0; i<num_samples; i+=d) {
        printf("%4u : %8.2f\n", i, rssi[i]);
    }


    // 
    // export results
    //
    FILE* fid = fopen(OUTPUT_FILENAME,"w");
    if (!fid) {
        fprintf(stderr,"error: %s, could not open '%s' for writing\n", argv[0], OUTPUT_FILENAME);
        exit(1);
    }
    fprintf(fid,"%% %s: auto-generated file\n\n",OUTPUT_FILENAME);
    fprintf(fid,"n = %u;\n", num_samples);
    fprintf(fid,"clear all;\n");
    fprintf(fid,"close all;\n\n");
    for (i=0; i<num_samples; i++) {
        fprintf(fid,"   x(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(x[i]), cimagf(x[i]));
        fprintf(fid,"   y(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(y[i]), cimagf(y[i]));
        fprintf(fid,"rssi(%4u) = %12.4e;\n", i+1, rssi[i]);
    }
    fprintf(fid,"\n\n");
    fprintf(fid,"n = length(x);\n");
    fprintf(fid,"t = 0:(n-1);\n");
    fprintf(fid,"figure('position',[100 100 800 600]);\n");
    fprintf(fid,"subplot(2,1,1);\n");
    fprintf(fid,"  plot(t,rssi,'-k','LineWidth',2);\n");
    fprintf(fid,"  xlabel('sample index');\n");
    fprintf(fid,"  ylabel('rssi [dB]');\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"subplot(2,1,2);\n");
    fprintf(fid,"  plot(t,real(y),t,imag(y));\n");
    fprintf(fid,"  xlabel('sample index');\n");
    fprintf(fid,"  ylabel('agc output');\n");
    fprintf(fid,"  grid on;\n");
    fclose(fid);
    printf("results written to %s\n", OUTPUT_FILENAME);

    printf("done.\n");
    return 0;
}
int main(int argc, char*argv[])
{
    srand(time(NULL));

    // options
    unsigned int k           =   2;     // samples/symbol (input)
    unsigned int m           =   3;     // filter delay (symbols)
    float        beta        =   0.5f;  // filter excess bandwidth factor
    unsigned int num_filters =  32;     // number of filters in the bank
    float        SNRdB       =  30.0f;  // signal-to-noise ratio
    float        bt          =   0.02f; // loop filter bandwidth
    unsigned int num_symbols = 400;     // number of data symbols
    float        tau         =  -0.20f; // fractional symbol offset

    // Nyquist filter type
    liquid_firfilt_type ftype = LIQUID_FIRFILT_KAISER;
    
    int dopt;
    while ((dopt = getopt(argc,argv,"uhk:m:b:B:s:w:n:t:")) != EOF) {
        switch (dopt) {
        case 'h':   usage();                        return 0;
        case 'k':   k           = atoi(optarg);     break;
        case 'm':   m           = atoi(optarg);     break;
        case 'b':   beta        = atof(optarg);     break;
        case 'B':   num_filters = atoi(optarg);     break;
        case 's':   SNRdB       = atof(optarg);     break;
        case 'w':   bt          = atof(optarg);     break;
        case 'n':   num_symbols = atoi(optarg);     break;
        case 't':   tau         = atof(optarg);     break;
        default:
            exit(1);
        }
    }

    unsigned int i;

    // validate input
    if (k < 2) {
        fprintf(stderr,"error: k (samples/symbol) must be at least 2\n");
        exit(1);
    } else if (m < 1) {
        fprintf(stderr,"error: m (filter delay) must be greater than 0\n");
        exit(1);
    } else if (beta <= 0.0f || beta > 1.0f) {
        fprintf(stderr,"error: beta (excess bandwidth factor) must be in (0,1]\n");
        exit(1);
    } else if (num_filters == 0) {
        fprintf(stderr,"error: number of polyphase filters must be greater than 0\n");
        exit(1);
    } else if (bt <= 0.0f) {
        fprintf(stderr,"error: timing PLL bandwidth must be greater than 0\n");
        exit(1);
    } else if (num_symbols == 0) {
        fprintf(stderr,"error: number of symbols must be greater than 0\n");
        exit(1);
    } else if (tau < -1.0f || tau > 1.0f) {
        fprintf(stderr,"error: timing phase offset must be in [-1,1]\n");
        exit(1);
    }

    // derived values
    unsigned int num_samples = k*num_symbols;
    float complex x[num_samples];           // interpolated samples
    float complex y[num_samples];           // received signal (with noise)
    float         tau_hat[num_samples];     // instantaneous timing offset estimate
    float complex sym_out[num_symbols + 64];// synchronized symbols

    // create sequence of Nyquist-interpolated QPSK symbols
    firinterp_crcf interp = firinterp_crcf_create_nyquist(ftype,k,m,beta,tau);
    for (i=0; i<num_symbols; i++) {
        // generate random QPSK symbol
        float complex s = ( rand() % 2 ? M_SQRT1_2 : -M_SQRT1_2 ) +
                          ( rand() % 2 ? M_SQRT1_2 : -M_SQRT1_2 ) * _Complex_I;

        // interpolate symbol
        firinterp_crcf_execute(interp, s, &x[i*k]);
    }
    firinterp_crcf_destroy(interp);


    // add noise
    float nstd = powf(10.0f, -SNRdB/20.0f);
    for (i=0; i<num_samples; i++)
        y[i] = x[i] + nstd*(randnf() + _Complex_I*randnf());


    // create and run symbol synchronizer
    symsync_crcf decim = symsync_crcf_create_kaiser(k, m, beta, num_filters);
    symsync_crcf_set_lf_bw(decim,bt);   // set loop filter bandwidth

    // NOTE: we could just synchronize entire block (see following line);
    //       however we would like to save the instantaneous timing offset
    //       estimate for plotting purposes
    //symsync_crcf_execute(d, y, num_samples, sym_out, &num_symbols_sync);

    unsigned int num_symbols_sync = 0;
    unsigned int num_written=0;
    for (i=0; i<num_samples; i++) {
        // save instantaneous timing offset estimate
        tau_hat[i] = symsync_crcf_get_tau(decim);

        // execute one sample at a time
        symsync_crcf_execute(decim, &y[i], 1, &sym_out[num_symbols_sync], &num_written);

        // increment number of symbols synchronized
        num_symbols_sync += num_written;
    }
    symsync_crcf_destroy(decim);

    // print last several symbols to screen
    printf("output symbols:\n");
    for (i=num_symbols_sync-10; i<num_symbols_sync; i++)
        printf("  sym_out(%2u) = %8.4f + j*%8.4f;\n", i+1, crealf(sym_out[i]), cimagf(sym_out[i]));


    //
    // export output file
    //
    FILE* fid = fopen(OUTPUT_FILENAME,"w");
    fprintf(fid,"%% %s, auto-generated file\n\n", OUTPUT_FILENAME);
    fprintf(fid,"close all;\nclear all;\n\n");

    fprintf(fid,"k=%u;\n",k);
    fprintf(fid,"m=%u;\n",m);
    fprintf(fid,"beta=%12.8f;\n",beta);
    fprintf(fid,"num_filters=%u;\n",num_filters);
    fprintf(fid,"num_symbols=%u;\n",num_symbols);

    for (i=0; i<num_samples; i++)
        fprintf(fid,"x(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(x[i]), cimagf(x[i]));
        
    for (i=0; i<num_samples; i++)
        fprintf(fid,"y(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(y[i]), cimagf(y[i]));
        
    for (i=0; i<num_samples; i++)
        fprintf(fid,"tau_hat(%3u) = %12.8f;\n", i+1, tau_hat[i]);
        
    for (i=0; i<num_symbols_sync; i++)
        fprintf(fid,"sym_out(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(sym_out[i]), cimagf(sym_out[i]));
        
    fprintf(fid,"i0 = 1:round( 0.5*num_symbols );\n");
    fprintf(fid,"i1 = round( 0.5*num_symbols ):num_symbols;\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"hold on;\n");
    fprintf(fid,"plot(real(sym_out(i0)),imag(sym_out(i0)),'x','MarkerSize',4,'Color',[0.6 0.6 0.6]);\n");
    fprintf(fid,"plot(real(sym_out(i1)),imag(sym_out(i1)),'o','MarkerSize',4,'Color',[0 0.25 0.5]);\n");
    fprintf(fid,"hold off;\n");
    fprintf(fid,"axis square;\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"axis([-1 1 -1 1]*1.6);\n");
    fprintf(fid,"xlabel('In-phase');\n");
    fprintf(fid,"ylabel('Quadrature');\n");
    fprintf(fid,"legend(['first 50%%'],['last 50%%'],1);\n");

    fprintf(fid,"figure;\n");
    fprintf(fid,"tt = 0:(length(tau_hat)-1);\n");
    fprintf(fid,"b = floor(num_filters*tau_hat + 0.5);\n");
    fprintf(fid,"stairs(tt,tau_hat*num_filters);\n");
    fprintf(fid,"hold on;\n");
    fprintf(fid,"plot(tt,b,'-k','Color',[0 0 0]);\n");
    fprintf(fid,"hold off;\n");
    fprintf(fid,"xlabel('time');\n");
    fprintf(fid,"ylabel('filterbank index');\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"axis([0 length(tau_hat) -1 num_filters]);\n");

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

    // clean it up
    printf("done.\n");
    return 0;
}
Ejemplo n.º 7
0
int main(int argc, char*argv[]) {
    srand(time(NULL));

    // options
    unsigned int k=2;   // samples/symbol
    unsigned int m=3;   // filter delay (symbols)
    float beta=0.9f;    // filter excess bandwidth factor
    unsigned int order=2;
    unsigned int num_symbols=1024;
    float SNRdB = 30.0f;

    float bt=0.02f;     // loop filter bandwidth
    float tau=0.2f;     // fractional symbol offset
    float r = 1.00f;    // resampled rate
    
    // use random data or 101010 phasing pattern
    int random_data=1;

    int dopt;
    while ((dopt = getopt(argc,argv,"uhk:m:b:o:s:w:n:t:r:")) != EOF) {
        switch (dopt) {
        case 'u':
        case 'h':   usage();    return 0;
        case 'k':   k = atoi(optarg);               break;
        case 'm':   m = atoi(optarg);               break;
        case 'b':   beta = atof(optarg);            break;
        case 'o':   order = atoi(optarg);           break;
        case 's':   SNRdB = atof(optarg);           break;
        case 'w':   bt = atof(optarg);              break;
        case 'n':   num_symbols = atoi(optarg);     break;
        case 't':   tau = atof(optarg);             break;
        case 'r':   r = atof(optarg);               break;
        default:
            exit(1);
        }
    }

    // validate input
    if (k < 2) {
        fprintf(stderr,"error: k (samples/symbol) must be at least 2\n");
        return 1;
    } else if (m < 1) {
        fprintf(stderr,"error: m (filter delay) must be greater than 0\n");
        return 1;
    } else if (beta <= 0.0f || beta > 1.0f) {
        fprintf(stderr,"error: beta (excess bandwidth factor) must be in (0,1]\n");
        return 1;
    } else if (order == 0) {
        fprintf(stderr,"error: number of polyphase filters must be greater than 0\n");
        return 1;
    } else if (bt <= 0.0f) {
        fprintf(stderr,"error: timing PLL bandwidth must be greater than 0\n");
        return 1;
    } else if (num_symbols == 0) {
        fprintf(stderr,"error: number of symbols must be greater than 0\n");
        return 1;
    } else if (tau < -1.0f || tau > 1.0f) {
        fprintf(stderr,"error: timing phase offset must be in [-1,1]\n");
        return 1;
    } else if (r < 0.5f || r > 2.0f) {
        fprintf(stderr,"error: timing frequency offset must be in [0.5,2]\n");
        return 1;
    }

    // compute delay
    while (tau < 0) tau += 1.0f;    // ensure positive tau
    float g = k*tau;                // number of samples offset
    int ds=floorf(g);               // additional symbol delay
    float dt = (g - (float)ds);     // fractional sample offset

    unsigned int i, n=0;

    unsigned int num_samples = k*num_symbols;
    unsigned int num_samples_resamp = (unsigned int) ceilf(num_samples*r*1.1f) + 4;
    float complex s[num_symbols];           // data symbols
    float complex x[num_samples];           // interpolated samples
    float complex y[num_samples_resamp];    // resampled data (resamp_crcf)
    float complex z[num_symbols + 64];      // synchronized symbols

    for (i=0; i<num_symbols; i++) {
        if (random_data) {
            // random signal (QPSK)
            s[i]  = cexpf(_Complex_I*0.5f*M_PI*((rand() % 4) + 0.5f));
        } else {
            s[i] = (i%2) ? 1.0f : -1.0f;  // 101010 phasing pattern
        }
    }

    // 
    // create and run interpolator
    //

    // design interpolating filter
    unsigned int h_len = 2*k*m + 1;
    float h[h_len];
    liquid_firdes_rcos(k,m,beta,dt,h);
    firinterp_crcf q = firinterp_crcf_create(k,h,h_len);
    for (i=0; i<num_symbols; i++) {
        firinterp_crcf_execute(q, s[i], &x[n]);
        n+=k;
    }
    assert(n == num_samples);
    firinterp_crcf_destroy(q);

    // 
    // run resampler
    //
    unsigned int resamp_len = 10*k; // resampling filter semi-length (filter delay)
    float resamp_bw = 0.45f;        // resampling filter bandwidth
    float resamp_As = 60.0f;        // resampling filter stop-band attenuation
    unsigned int resamp_npfb = 64;  // number of filters in bank
    resamp_crcf f = resamp_crcf_create(r, resamp_len, resamp_bw, resamp_As, resamp_npfb);
    unsigned int num_samples_resampled = 0;
    unsigned int num_written;
    for (i=0; i<num_samples; i++) {
#if 0
        // bypass arbitrary resampler
        y[i] = x[i];
        num_samples_resampled = num_samples;
#else
        // TODO : compensate for resampler filter delay
        resamp_crcf_execute(f, x[i], &y[num_samples_resampled], &num_written);
        num_samples_resampled += num_written;
#endif
    }
    resamp_crcf_destroy(f);

    // 
    // add noise
    //
    float nstd = powf(10.0f, -SNRdB/20.0f) / sqrtf(2.0f);
    for (i=0; i<num_samples_resampled; i++)
        y[i] += nstd*(randnf() + _Complex_I*randnf());


    // 
    // create and run symbol synchronizer
    //

    // create symbol synchronizer
    symsynclp_crcf d = symsynclp_crcf_create(k, order);
    symsynclp_crcf_set_lf_bw(d,bt);

    unsigned int num_symbols_sync=0;
    unsigned int nn;
    float tau_hat[num_samples];
    for (i=ds; i<num_samples_resampled; i++) {
        tau_hat[num_symbols_sync] = symsynclp_crcf_get_tau(d);
        symsynclp_crcf_execute(d, &y[i], 1, &z[num_symbols_sync], &nn);
        num_symbols_sync += nn;
    }
    symsynclp_crcf_destroy(d);


    // print last several symbols to screen
    printf("z(t) :\n");
    for (i=num_symbols_sync-10; i<num_symbols_sync; i++)
        printf("  z(%2u) = %8.4f + j*%8.4f;\n", i+1, crealf(z[i]), cimagf(z[i]));

    //
    // export output file
    //

    FILE* fid = fopen(OUTPUT_FILENAME,"w");
    fprintf(fid,"%% %s, auto-generated file\n\n", OUTPUT_FILENAME);
    fprintf(fid,"close all;\nclear all;\n\n");

    fprintf(fid,"k=%u;\n",k);
    fprintf(fid,"m=%u;\n",m);
    fprintf(fid,"beta=%12.8f;\n",beta);
    fprintf(fid,"order=%u;\n",order);
    fprintf(fid,"num_symbols=%u;\n",num_symbols);

    for (i=0; i<h_len; i++)
        fprintf(fid,"h(%3u) = %12.5f;\n", i+1, h[i]);

    for (i=0; i<num_symbols; i++)
        fprintf(fid,"s(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(s[i]), cimagf(s[i]));

    for (i=0; i<num_samples; i++)
        fprintf(fid,"x(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(x[i]), cimagf(x[i]));
        
    for (i=0; i<num_samples_resampled; i++)
        fprintf(fid,"y(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(y[i]), cimagf(y[i]));
        
    for (i=0; i<num_symbols_sync; i++)
        fprintf(fid,"z(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(z[i]), cimagf(z[i]));
        
    for (i=0; i<num_symbols_sync; i++)
        fprintf(fid,"tau_hat(%3u) = %12.8f;\n", i+1, tau_hat[i]);


    fprintf(fid,"\n\n");
    fprintf(fid,"ms = 8; %% marker size\n");
    fprintf(fid,"zp = filter(h,1,y);\n");
    fprintf(fid,"figure;\nhold on;\n");
    fprintf(fid,"plot([0:length(s)-1],          real(s),    'ob', 'MarkerSize',ms);\n");
    fprintf(fid,"plot([0:length(y)-1]/k  -m,    real(y),    '-',  'MarkerSize',ms, 'Color',[0.8 0.8 0.8]);\n");
    fprintf(fid,"plot([0:length(zp)-1]/k -k*m,  real(zp/k), '-b', 'MarkerSize',ms);\n");
    fprintf(fid,"plot([0:length(z)-1]    -k*m+1,real(z),    'xr', 'MarkerSize',ms);\n");
    fprintf(fid,"hold off;\n");
    fprintf(fid,"xlabel('Symbol Index');\n");
    fprintf(fid,"ylabel('Output Signal');\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"legend('sym in','interp','mf','sym out',0);\n");

    fprintf(fid,"t0=1:floor(0.25*length(z));\n");
    fprintf(fid,"t1=ceil(0.25*length(z)):length(z);\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"hold on;\n");
    fprintf(fid,"plot(real(z(t0)),imag(z(t0)),'x','MarkerSize',ms,'Color',[0.6 0.6 0.6]);\n");
    fprintf(fid,"plot(real(z(t1)),imag(z(t1)),'x','MarkerSize',ms,'Color',[0 0.25 0.5]);\n");
    fprintf(fid,"hold off;\n");
    fprintf(fid,"axis square; grid on;\n");
    fprintf(fid,"axis([-1 1 -1 1]*1.2);\n");
    fprintf(fid,"xlabel('In-phase');\n");
    fprintf(fid,"ylabel('Quadrature');\n");
    fprintf(fid,"legend(['first 25%%'],['last 75%%'],1);\n");

    fprintf(fid,"figure;\n");
    fprintf(fid,"tt = 0:(length(tau_hat)-1);\n");
    fprintf(fid,"plot(tt,tau_hat,'-k','Color',[0 0 0]);\n");
    fprintf(fid,"xlabel('time');\n");
    fprintf(fid,"ylabel('tau-hat');\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"axis([0 length(tau_hat) 0 1]);\n");
    fclose(fid);

    printf("results written to %s.\n", OUTPUT_FILENAME);

    // clean it up
    printf("done.\n");
    return 0;
}
Ejemplo n.º 8
0
// create flexframesync object
//  _callback       :   callback function invoked when frame is received
//  _userdata       :   user-defined data object passed to callback
flexframesync flexframesync_create(framesync_callback _callback,
                                   void *             _userdata)
{
    flexframesync q = (flexframesync) malloc(sizeof(struct flexframesync_s));
    q->callback = _callback;
    q->userdata = _userdata;

    unsigned int i;

    // generate p/n sequence
    msequence ms = msequence_create(6, 0x005b, 1);
    for (i=0; i<64; i++)
        q->preamble_pn[i] = (msequence_advance(ms)) ? 1.0f : -1.0f;
    msequence_destroy(ms);

    // interpolate p/n sequence with matched filter
    q->k    = 2;        // samples/symbol
    q->m    = 7;        // filter delay (symbols)
    q->beta = 0.25f;    // excess bandwidth factor
    float complex seq[q->k*64];
    firinterp_crcf interp = firinterp_crcf_create_rnyquist(LIQUID_FIRFILT_ARKAISER,q->k,q->m,q->beta,0);
    for (i=0; i<64+q->m; i++) {
        // compensate for filter delay
        if (i < q->m) firinterp_crcf_execute(interp, q->preamble_pn[i],    &seq[0]);
        else          firinterp_crcf_execute(interp, q->preamble_pn[i%64], &seq[q->k*(i-q->m)]);
    }
    firinterp_crcf_destroy(interp);

    // create frame detector
    float threshold = 0.4f;     // detection threshold
    float dphi_max  = 0.05f;    // maximum carrier offset allowable
    q->frame_detector = detector_cccf_create(seq, q->k*64, threshold, dphi_max);
    q->buffer = windowcf_create(q->k*(64+q->m));

    // create symbol timing recovery filters
    q->npfb = 32;   // number of filters in the bank
    q->mf   = firpfb_crcf_create_rnyquist(LIQUID_FIRFILT_ARKAISER, q->npfb,q->k,q->m,q->beta);
    q->dmf  = firpfb_crcf_create_drnyquist(LIQUID_FIRFILT_ARKAISER,q->npfb,q->k,q->m,q->beta);

    // create down-coverters for carrier phase tracking
    q->nco_coarse = nco_crcf_create(LIQUID_NCO);
    q->nco_fine   = nco_crcf_create(LIQUID_VCO);
    nco_crcf_pll_set_bandwidth(q->nco_fine, 0.05f);
    
    // create header objects
    q->demod_header = modem_create(LIQUID_MODEM_BPSK);
    q->p_header   = packetizer_create(FLEXFRAME_H_DEC,
                                      FLEXFRAME_H_CRC,
                                      FLEXFRAME_H_FEC0,
                                      FLEXFRAME_H_FEC1);
    assert(packetizer_get_enc_msg_len(q->p_header)==FLEXFRAME_H_ENC);

    // frame properties (default values to be overwritten when frame
    // header is received and properly decoded)
    q->ms_payload      = LIQUID_MODEM_QPSK;
    q->bps_payload     = 2;
    q->payload_dec_len = 1;
    q->check           = LIQUID_CRC_NONE;
    q->fec0            = LIQUID_FEC_NONE;
    q->fec1            = LIQUID_FEC_NONE;

    // create payload objects (overridden by received properties)
    q->demod_payload   = modem_create(LIQUID_MODEM_QPSK);
    q->p_payload       = packetizer_create(q->payload_dec_len, q->check, q->fec0, q->fec1);
    q->payload_enc_len = packetizer_get_enc_msg_len(q->p_payload);
    q->payload_mod_len = 4 * q->payload_enc_len;
    q->payload_mod     = (unsigned char*) malloc(q->payload_mod_len*sizeof(unsigned char));
    q->payload_enc     = (unsigned char*) malloc(q->payload_enc_len*sizeof(unsigned char));
    q->payload_dec     = (unsigned char*) malloc(q->payload_dec_len*sizeof(unsigned char));

#if DEBUG_FLEXFRAMESYNC
    // set debugging flags, objects to NULL
    q->debug_enabled         = 0;
    q->debug_objects_created = 0;
    q->debug_x               = NULL;
#endif

    // reset state
    flexframesync_reset(q);

    return q;
}
Ejemplo n.º 9
0
int main(int argc, char*argv[]) {
    // options
    unsigned int k=4;                   // samples/symbol
    unsigned int m=3;                   // filter delay
    float As = 60.0f;                   // filter stop-band attenuation
    unsigned int num_data_symbols=16;   // number of data symbols

    int dopt;
    while ((dopt = getopt(argc,argv,"uhk:m:s:n:")) != EOF) {
        switch (dopt) {
        case 'u':
        case 'h': usage();                          return 0;
        case 'k': k = atoi(optarg);                 break;
        case 'm': m = atoi(optarg);                 break;
        case 's': As = atof(optarg);                break;
        case 'n': num_data_symbols = atoi(optarg);  break;
        default:
            exit(1);
        }
    }

    // validate options
    if (k < 2) {
        fprintf(stderr,"error: %s, interp factor must be greater than 1\n", argv[0]);
        exit(1);
    } else if (m < 1) {
        fprintf(stderr,"error: %s, filter delay must be greater than 0\n", argv[0]);
        exit(1);
    } else if (num_data_symbols < 1) {
        fprintf(stderr,"error: %s, must have at least one data symbol\n", argv[0]);
        usage();
        return 1;
    }

    // derived values
    unsigned int num_symbols = num_data_symbols + 2*m;  // compensate for filter delay
    unsigned int num_samples = k*num_symbols;

    // create interpolator from prototype
    firinterp_crcf q = firinterp_crcf_create_prototype(k,m,As);

    // generate input signal and interpolate
    float complex x[num_symbols];   // input symbols
    float complex y[num_samples];   // output samples
    unsigned int i;
    for (i=0; i<num_data_symbols; i++) {
        x[i] = (rand() % 2 ? 1.0f : -1.0f) +
               (rand() % 2 ? 1.0f : -1.0f) * _Complex_I;
    }

    // pad end of sequence with zeros
    for (i=num_data_symbols; i<num_symbols; i++)
        x[i] = 0.0f;

    // interpolate symbols
    for (i=0; i<num_symbols; i++)
        firinterp_crcf_execute(q, x[i], &y[k*i]);

    // destroy interpolator object
    firinterp_crcf_destroy(q);

    // print results to screen
    printf("x(t) :\n");
    for (i=0; i<num_symbols; i++)
        printf("  x(%4u) = %8.4f + j*%8.4f;\n", i, crealf(x[i]), cimagf(x[i]));

    printf("y(t) :\n");
    for (i=0; i<num_samples; i++) {
        printf("  y(%4u) = %8.4f + j*%8.4f;", i, crealf(y[i]), cimagf(y[i]));
        if ( (i >= k*m) && ((i%k)==0))
            printf(" **\n");
        else
            printf("\n");
    }

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

    for (i=0; i<num_symbols; i++)
        fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(x[i]), cimagf(x[i]));

    for (i=0; i<num_samples; i++)
        fprintf(fid,"y(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(y[i]), cimagf(y[i]));

    fprintf(fid,"\n\n");
    fprintf(fid,"tx = [0:(num_symbols-1)];\n");
    fprintf(fid,"ty = [0:(num_samples-1)]/k - m;\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"subplot(2,1,1);\n");
    fprintf(fid,"    plot(ty,real(y),'-',tx,real(x),'s');\n");
    fprintf(fid,"    xlabel('time');\n");
    fprintf(fid,"    ylabel('real');\n");
    fprintf(fid,"    grid on;\n");
    fprintf(fid,"subplot(2,1,2);\n");
    fprintf(fid,"    plot(ty,imag(y),'-',tx,imag(x),'s');\n");
    fprintf(fid,"    xlabel('time');\n");
    fprintf(fid,"    ylabel('imag');\n");
    fprintf(fid,"    grid on;\n");

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

    printf("done.\n");
    return 0;
}
int main(int argc, char*argv[])
{
    srand(time(NULL));

    // options
    unsigned int num_symbols=500;   // number of symbols to observe
    float SNRdB = 30.0f;            // signal-to-noise ratio [dB]
    unsigned int hc_len=5;          // channel filter length
    unsigned int k=2;               // matched filter samples/symbol
    unsigned int m=3;               // matched filter delay (symbols)
    float beta=0.3f;                // matched filter excess bandwidth factor
    unsigned int p=3;               // equalizer length (symbols, hp_len = 2*k*p+1)
    float mu = 0.08f;               // learning rate

    // modulation type/depth
    modulation_scheme ms = LIQUID_MODEM_QPSK;

    int dopt;
    while ((dopt = getopt(argc,argv,"hn:s:c:k:m:b:p:u:M:")) != EOF) {
        switch (dopt) {
        case 'h': usage();                      return 0;
        case 'n': num_symbols   = atoi(optarg); break;
        case 's': SNRdB         = atof(optarg); break;
        case 'c': hc_len        = atoi(optarg); break;
        case 'k': k             = atoi(optarg); break;
        case 'm': m             = atoi(optarg); break;
        case 'b': beta          = atof(optarg); break;
        case 'p': p             = atoi(optarg); break;
        case 'u': mu            = atof(optarg); break;
        case 'M':
            ms = liquid_getopt_str2mod(optarg);
            if (ms == LIQUID_MODEM_UNKNOWN) {
                fprintf(stderr,"error: %s, unknown/unsupported modulation scheme '%s'\n", argv[0], optarg);
                return 1;
            }
            break;
        default:
            exit(1);
        }
    }

    // validate input
    if (num_symbols == 0) {
        fprintf(stderr,"error: %s, number of symbols must be greater than zero\n", argv[0]);
        exit(1);
    } else if (hc_len == 0) {
        fprintf(stderr,"error: %s, channel must have at least 1 tap\n", argv[0]);
        exit(1);
    } else if (k < 2) {
        fprintf(stderr,"error: %s, samples/symbol must be at least 2\n", argv[0]);
        exit(1);
    } else if (m == 0) {
        fprintf(stderr,"error: %s, filter semi-length must be at least 1 symbol\n", argv[0]);
        exit(1);
    } else if (beta < 0.0f || beta > 1.0f) {
        fprintf(stderr,"error: %s, filter excess bandwidth must be in [0,1]\n", argv[0]);
        exit(1);
    } else if (p == 0) {
        fprintf(stderr,"error: %s, equalizer semi-length must be at least 1 symbol\n", argv[0]);
        exit(1);
    } else if (mu < 0.0f || mu > 1.0f) {
        fprintf(stderr,"error: %s, equalizer learning rate must be in [0,1]\n", argv[0]);
        exit(1);
    }

    // derived values
    unsigned int hm_len = 2*k*m+1;   // matched filter length
    unsigned int hp_len = 2*k*p+1;   // equalizer filter length
    unsigned int num_samples = k*num_symbols;

    // bookkeeping variables
    float complex sym_tx[num_symbols];  // transmitted data sequence
    float complex x[num_samples];       // interpolated time series
    float complex y[num_samples];       // channel output
    float complex z[num_samples];       // equalized output

    float hm[hm_len];                   // matched filter response
    float complex hc[hc_len];           // channel filter coefficients
    float complex hp[hp_len];           // equalizer filter coefficients

    unsigned int i;

    // generate matched filter response
    liquid_firdes_rnyquist(LIQUID_FIRFILT_RRC, k, m, beta, 0.0f, hm);
    firinterp_crcf interp = firinterp_crcf_create(k, hm, hm_len);

    // create the modem objects
    modem mod   = modem_create(ms);
    modem demod = modem_create(ms);
    unsigned int M = 1 << modem_get_bps(mod);

    // generate channel impulse response, filter
    hc[0] = 1.0f;
    for (i=1; i<hc_len; i++)
        hc[i] = 0.09f*(randnf() + randnf()*_Complex_I);
    firfilt_cccf fchannel = firfilt_cccf_create(hc, hc_len);

    // generate random symbols
    for (i=0; i<num_symbols; i++)
        modem_modulate(mod, rand()%M, &sym_tx[i]);

    // interpolate
    for (i=0; i<num_symbols; i++)
        firinterp_crcf_execute(interp, sym_tx[i], &x[i*k]);
    
    // push through channel
    float nstd = powf(10.0f, -SNRdB/20.0f);
    for (i=0; i<num_samples; i++) {
        firfilt_cccf_push(fchannel, x[i]);
        firfilt_cccf_execute(fchannel, &y[i]);

        // add noise
        y[i] += nstd*(randnf() + randnf()*_Complex_I)*M_SQRT1_2;
    }

    // push through equalizer
    // create equalizer, intialized with square-root Nyquist filter
    eqlms_cccf eq = eqlms_cccf_create_rnyquist(LIQUID_FIRFILT_RRC, k, p, beta, 0.0f);
    eqlms_cccf_set_bw(eq, mu);

    // get initialized weights
    eqlms_cccf_get_weights(eq, hp);

    // filtered error vector magnitude (emperical RMS error)
    float evm_hat = 0.03f;

    float complex d_hat = 0.0f;
    for (i=0; i<num_samples; i++) {
        // print filtered evm (emperical rms error)
        if ( ((i+1)%50)==0 )
            printf("%4u : rms error = %12.8f dB\n", i+1, 10*log10(evm_hat));

        eqlms_cccf_push(eq, y[i]);
        eqlms_cccf_execute(eq, &d_hat);

        // store output
        z[i] = d_hat;

        // decimate by k
        if ( (i%k) != 0 ) continue;

        // estimate transmitted signal
        unsigned int sym_out;   // output symbol
        float complex d_prime;  // estimated input sample
        modem_demodulate(demod, d_hat, &sym_out);
        modem_get_demodulator_sample(demod, &d_prime);

        // update equalizer
        eqlms_cccf_step(eq, d_prime, d_hat);

        // update filtered evm estimate
        float evm = crealf( (d_prime-d_hat)*conjf(d_prime-d_hat) );
        evm_hat = 0.98f*evm_hat + 0.02f*evm;
    }

    // get equalizer weights
    eqlms_cccf_get_weights(eq, hp);

    // destroy objects
    eqlms_cccf_destroy(eq);
    firinterp_crcf_destroy(interp);
    firfilt_cccf_destroy(fchannel);
    modem_destroy(mod);
    modem_destroy(demod);

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

    fprintf(fid,"k = %u;\n", k);
    fprintf(fid,"m = %u;\n", m);
    fprintf(fid,"num_symbols = %u;\n", num_symbols);
    fprintf(fid,"num_samples = num_symbols*k;\n");

    // save transmit matched-filter response
    fprintf(fid,"hm_len = 2*k*m+1;\n");
    fprintf(fid,"hm = zeros(1,hm_len);\n");
    for (i=0; i<hm_len; i++)
        fprintf(fid,"hm(%4u) = %12.4e;\n", i+1, hm[i]);

    // save channel impulse response
    fprintf(fid,"hc_len = %u;\n", hc_len);
    fprintf(fid,"hc = zeros(1,hc_len);\n");
    for (i=0; i<hc_len; i++)
        fprintf(fid,"hc(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(hc[i]), cimagf(hc[i]));

    // save equalizer response
    fprintf(fid,"hp_len = %u;\n", hp_len);
    fprintf(fid,"hp = zeros(1,hp_len);\n");
    for (i=0; i<hp_len; i++)
        fprintf(fid,"hp(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(hp[i]), cimagf(hp[i]));

    // save sample sets
    fprintf(fid,"x = zeros(1,num_samples);\n");
    fprintf(fid,"y = zeros(1,num_samples);\n");
    fprintf(fid,"z = zeros(1,num_samples);\n");
    for (i=0; i<num_samples; i++) {
        fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(x[i]), cimagf(x[i]));
        fprintf(fid,"y(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(y[i]), cimagf(y[i]));
        fprintf(fid,"z(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(z[i]), cimagf(z[i]));
    }

    // plot time response
    fprintf(fid,"t = 0:(num_samples-1);\n");
    fprintf(fid,"tsym = 1:k:num_samples;\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(t,real(z),...\n");
    fprintf(fid,"     t(tsym),real(z(tsym)),'x');\n");

    // plot constellation
    fprintf(fid,"tsym0 = tsym(1:(length(tsym)/2));\n");
    fprintf(fid,"tsym1 = tsym((length(tsym)/2):end);\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(real(z(tsym0)),imag(z(tsym0)),'x','Color',[1 1 1]*0.7,...\n");
    fprintf(fid,"     real(z(tsym1)),imag(z(tsym1)),'x','Color',[1 1 1]*0.0);\n");
    fprintf(fid,"xlabel('In-Phase');\n");
    fprintf(fid,"ylabel('Quadrature');\n");
    fprintf(fid,"axis([-1 1 -1 1]*1.5);\n");
    fprintf(fid,"axis square;\n");
    fprintf(fid,"grid on;\n");

    // compute composite response
    fprintf(fid,"g  = real(conv(conv(hm,hc),hp));\n");

    // plot responses
    fprintf(fid,"nfft = 1024;\n");
    fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n");
    fprintf(fid,"Hm = 20*log10(abs(fftshift(fft(hm/k,nfft))));\n");
    fprintf(fid,"Hc = 20*log10(abs(fftshift(fft(hc,  nfft))));\n");
    fprintf(fid,"Hp = 20*log10(abs(fftshift(fft(hp,  nfft))));\n");
    fprintf(fid,"G  = 20*log10(abs(fftshift(fft(g/k, nfft))));\n");

    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(f,Hm, f,Hc, f,Hp, f,G,'-k','LineWidth',2, [-0.5/k 0.5/k],[-6.026 -6.026],'or');\n");
    fprintf(fid,"xlabel('Normalized Frequency');\n");
    fprintf(fid,"ylabel('Power Spectral Density');\n");
    fprintf(fid,"legend('transmit','channel','equalizer','composite','half-power points',1);\n");
    fprintf(fid,"axis([-0.5 0.5 -12 8]);\n");
    fprintf(fid,"grid on;\n");
    
    fclose(fid);
    printf("results written to '%s'\n", OUTPUT_FILENAME);

    return 0;
}
Ejemplo n.º 11
0
void autotest_firinterp_crcf_generic()
{
    // h = [0, 0.25, 0.5, 0.75, 1.0, 0.75, 0.5, 0.25, 0];
    float h[9] = {
      -0.7393353832652201,
       0.1909821993029451,
      -1.7013834621383086,
      -0.6157406339062349,
       0.5806218191269317,
       0.0576963976148674,
      -1.0958217797368455,
      -0.6379821629743743,
       0.7019489165905530};

    unsigned int M = 4;     // firinterp factor
    firinterp_crcf q = firinterp_crcf_create(M,h,9);

    //  x = [1+j*0.2, -0.2+j*1.3, 0.5+j*0.3, 1.1-j*0.2]
    float complex x[4] = {
      1.0000e+00+  2.0000e-01*_Complex_I, 
     -2.0000e-01+  1.3000e+00*_Complex_I, 
      5.0000e-01+  3.0000e-01*_Complex_I, 
      1.1000e+00+ -2.0000e-01*_Complex_I
    };
        
    float complex y[16];

    // z = [x(1) 0 0 0 x(2) 0 0 0 x(3) 0 0 0 x(4) 0 0 0];
    // test = filter(h,1,z)
    float complex test[16] = {
      -0.7393353832652201 - 0.1478670766530440*_Complex_I,
       0.1909821993029451 + 0.0381964398605890*_Complex_I,
      -1.7013834621383086 - 0.3402766924276617*_Complex_I,
      -0.6157406339062349 - 0.1231481267812470*_Complex_I,
       0.7284888957799757 - 0.8450116344193997*_Complex_I,
       0.0194999577542784 + 0.2598161386168021*_Complex_I,
      -0.7555450873091838 - 2.4309628567271702*_Complex_I,
      -0.5148340361931273 - 0.9280592566729803*_Complex_I,
       0.2161568611325566 + 0.6733975332035558*_Complex_I,
       0.0839518201284991 + 0.1322999766902112*_Complex_I,
      -0.6315273751217851 - 1.9349833522993918*_Complex_I,
      -0.1802738843582426 - 1.0140990020385570*_Complex_I,
      -0.6633477953463869 + 1.2345872139588425*_Complex_I,
       0.2389286180406733 - 0.0208875205761288*_Complex_I,
      -2.4194326982205623 + 0.0115301585066081*_Complex_I,
      -0.9963057787840456 - 0.0682465221110653*_Complex_I };

    float tol = 1e-6;

    unsigned int i;
    for (i=0; i<4; i++)
        firinterp_crcf_execute(q, x[i], &y[i*M]);

    for (i=0; i<16; i++) {
        CONTEND_DELTA( crealf(y[i]), crealf(test[i]), tol);
        CONTEND_DELTA( cimagf(y[i]), cimagf(test[i]), tol);

        if (liquid_autotest_verbose)
            printf("  y(%u) = %8.4f + j%8.4f;\n", i+1, crealf(y[i]), cimagf(y[i]));
    }

    if (liquid_autotest_verbose)
        firinterp_crcf_print(q);

    // destroy interpolator object
    firinterp_crcf_destroy(q);
}
Ejemplo n.º 12
0
int main(int argc, char*argv[]) {
    srand(time(NULL));

    // options
    unsigned int k=2;               // samples/symbol (input)
    unsigned int m=3;               // filter delay (symbols)
    float beta=0.5f;                // filter excess bandwidth factor
    unsigned int npfb=32;    // number of filters in the bank
    unsigned int p=3;               // equalizer length (symbols, hp_len = 2*k*p+1)
    float mu = 0.05f;               // equalizer learning rate
    unsigned int num_symbols=500;   // number of data symbols
    unsigned int hc_len=5;          // channel filter length
    float SNRdB = 30.0f;            // signal-to-noise ratio
    liquid_firfilt_type ftype = LIQUID_FIRFILT_ARKAISER;

    float bt=0.05f;                 // symbol synchronizer loop filter bandwidth
    float tau=-0.1f;                // fractional symbol offset
    
    int dopt;
    while ((dopt = getopt(argc,argv,"uhk:m:b:n:B:w:p:W:s:c:t:")) != EOF) {
        switch (dopt) {
        case 'u':
        case 'h':   usage();                        return 0;
        // transmit filter properties
        case 'k':   k           = atoi(optarg);     break;
        case 'm':   m           = atoi(optarg);     break;
        case 'b':   beta        = atof(optarg);     break;
        case 'n':   num_symbols = atoi(optarg);     break;
        // symsync properties
        case 'B':   npfb        = atoi(optarg);     break;
        case 'w':   bt          = atof(optarg);     break;
        // equalizer properties
        case 'p':   p           = atoi(optarg);     break;
        case 'W':   mu          = atof(optarg);     break;
        // equalizer properties
        case 's':   SNRdB       = atof(optarg);     break;
        case 'c':   hc_len      = atoi(optarg);     break;
        case 't':   tau         = atof(optarg);     break;
        default:
            exit(1);
        }
    }

    // validate input
    if (k < 2) {
        fprintf(stderr,"error: %s,k (samples/symbol) must be at least 2\n", argv[0]);
        exit(1);
    } else if (m < 1) {
        fprintf(stderr,"error: %s,m (filter delay) must be greater than 0\n", argv[0]);
        exit(1);
    } else if (beta <= 0.0f || beta > 1.0f) {
        fprintf(stderr,"error: %s,beta (excess bandwidth factor) must be in (0,1]\n", argv[0]);
        exit(1);
    } else if (num_symbols == 0) {
        fprintf(stderr,"error: %s,number of symbols must be greater than 0\n", argv[0]);
        exit(1);
    } else if (npfb == 0) {
        fprintf(stderr,"error: %s,number of polyphase filters must be greater than 0\n", argv[0]);
        exit(1);
    } else if (bt < 0.0f) {
        fprintf(stderr,"error: %s,timing PLL bandwidth cannot be negative\n", argv[0]);
        exit(1);
    } else if (p == 0) {
        fprintf(stderr,"error: %s, equalizer order must be at least 1\n", argv[0]);
        exit(1);
    } else if (mu < 0.0f || mu > 1.0f) {
        fprintf(stderr,"error: %s, equalizer learning rate must be in [0,1]\n", argv[0]);
        exit(1);
    } else if (hc_len < 1) {
        fprintf(stderr,"error: %s, channel response must have at least 1 tap\n", argv[0]);
        exit(1);
    } else if (tau < -1.0f || tau > 1.0f) {
        fprintf(stderr,"error: %s,timing phase offset must be in [-1,1]\n", argv[0]);
        exit(1);
    }

    // derived values
    unsigned int ht_len = 2*k*m+1;  // transmit filter order
    unsigned int hp_len = 2*k*p+1;  // equalizer order
    float nstd = powf(10.0f, -SNRdB/20.0f);

    float dt = tau;                 // fractional sample offset
    unsigned int ds = 0;            // full sample delay

    unsigned int i;

    unsigned int num_samples = k*num_symbols;
    float complex s[num_symbols];               // data symbols
    float complex x[num_samples];               // interpolated samples
    float complex y[num_samples];               // channel output
    float complex z[k*num_symbols + 64];        // synchronized samples
    float complex sym_out[num_symbols + 64];    // synchronized symbols

    for (i=0; i<num_symbols; i++) {
        s[i] = (rand() % 2 ? M_SQRT1_2 : -M_SQRT1_2) +
               (rand() % 2 ? M_SQRT1_2 : -M_SQRT1_2) * _Complex_I;
    }

    // 
    // create and run interpolator
    //

    // design interpolating filter
    float ht[ht_len];
    liquid_firdes_prototype(ftype,k,m,beta,dt,ht);
    firinterp_crcf q = firinterp_crcf_create(k, ht, ht_len);
    for (i=0; i<num_symbols; i++)
        firinterp_crcf_execute(q, s[i], &x[i*k]);
    firinterp_crcf_destroy(q);


    // 
    // channel
    //

    // generate channel impulse response, filter
    float complex hc[hc_len];
    hc[0] = 1.0f;
    for (i=1; i<hc_len; i++)
        hc[i] = 0.07f*(randnf() + randnf()*_Complex_I);
    firfilt_cccf fchannel = firfilt_cccf_create(hc, hc_len);
    // push through channel
    for (i=0; i<num_samples; i++) {
        firfilt_cccf_push(fchannel, x[i]);
        firfilt_cccf_execute(fchannel, &y[i]);

        // add noise
        y[i] += nstd*(randnf() + randnf()*_Complex_I)*M_SQRT1_2;
    }
    firfilt_cccf_destroy(fchannel);


    // 
    // symbol timing recovery
    //

    // create symbol synchronizer
    symsync_crcf d = symsync_crcf_create_rnyquist(ftype, k, m, beta, npfb);
    symsync_crcf_set_lf_bw(d,bt);
    symsync_crcf_set_output_rate(d,k);

    unsigned int num_samples_sync=0;
    unsigned int nw;
    for (i=ds; i<num_samples; i++) {
        // push through symbol synchronizer
        symsync_crcf_execute(d, &y[i], 1, &z[num_samples_sync], &nw);
        num_samples_sync += nw;
    }
    printf("num samples : %6u (%6u synchronized)\n", num_samples, num_samples_sync);
    symsync_crcf_destroy(d);


    // 
    // equalizer/decimator
    //

    // create equalizer as low-pass filter
    float complex hp[hp_len];
    eqlms_cccf eq = eqlms_cccf_create_lowpass(hp_len, 0.4f);
    eqlms_cccf_set_bw(eq, mu);

    // push through equalizer and decimate
    unsigned int num_symbols_sync = 0;
    float complex d_hat = 0.0f;
    for (i=0; i<num_samples_sync; i++) {
        // push sample into equalizer
        eqlms_cccf_push(eq, z[i]);

        // decimate by k
        if ( (i%k) != 0) continue;

        // compute output
        eqlms_cccf_execute(eq, &d_hat);
        sym_out[num_symbols_sync++] = d_hat;

        // check if buffer is full
        if ( i < hp_len ) continue;

        // estimate transmitted signal
        float complex d_prime = (crealf(d_hat) > 0.0f ? M_SQRT1_2 : -M_SQRT1_2) +
                                (cimagf(d_hat) > 0.0f ? M_SQRT1_2 : -M_SQRT1_2) * _Complex_I;

        // update equalizer
        eqlms_cccf_step(eq, d_prime, d_hat);
    }

    // get equalizer weights
    eqlms_cccf_get_weights(eq, hp);

    // destroy equalizer object
    eqlms_cccf_destroy(eq);

    // print last several symbols to screen
    printf("output symbols:\n");
    for (i=num_symbols_sync-10; i<num_symbols_sync; i++)
        printf("  sym_out(%2u) = %8.4f + j*%8.4f;\n", i+1, crealf(sym_out[i]), cimagf(sym_out[i]));

    //
    // export output file
    //

    FILE* fid = fopen(OUTPUT_FILENAME,"w");
    fprintf(fid,"%% %s, auto-generated file\n\n", OUTPUT_FILENAME);
    fprintf(fid,"close all;\nclear all;\n\n");

    fprintf(fid,"k=%u;\n",k);
    fprintf(fid,"m=%u;\n",m);
    fprintf(fid,"beta=%12.8f;\n",beta);
    fprintf(fid,"npfb=%u;\n",npfb);
    fprintf(fid,"num_symbols=%u;\n",num_symbols);

    for (i=0; i<ht_len; i++)
        fprintf(fid,"ht(%3u) = %12.5f;\n", i+1, ht[i]);

    for (i=0; i<hc_len; i++)
        fprintf(fid,"hc(%3u) = %12.5f + j*%12.8f;\n", i+1, crealf(hc[i]), cimagf(hc[i]));

    for (i=0; i<hp_len; i++)
        fprintf(fid,"hp(%3u) = %12.5f + j*%12.8f;\n", i+1, crealf(hp[i]), cimagf(hp[i]));

    for (i=0; i<num_symbols; i++)
        fprintf(fid,"s(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(s[i]), cimagf(s[i]));

    for (i=0; i<num_samples; i++)
        fprintf(fid,"x(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(x[i]), cimagf(x[i]));
        
    for (i=0; i<num_samples; i++)
        fprintf(fid,"y(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(y[i]), cimagf(y[i]));
        
    for (i=0; i<num_samples_sync; i++)
        fprintf(fid,"z(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(z[i]), cimagf(z[i]));
        
    for (i=0; i<num_symbols_sync; i++)
        fprintf(fid,"sym_out(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(sym_out[i]), cimagf(sym_out[i]));
        
#if 0
    fprintf(fid,"\n\n");
    fprintf(fid,"%% scale QPSK in-phase by sqrt(2)\n");
    fprintf(fid,"z = z*sqrt(2);\n");
    fprintf(fid,"\n\n");
    fprintf(fid,"tz = [0:length(z)-1]/k;\n");
    fprintf(fid,"iz = 1:k:length(z);\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(tz,     real(z),    '-',...\n");
    fprintf(fid,"     tz(iz), real(z(iz)),'or');\n");
    fprintf(fid,"xlabel('Time');\n");
    fprintf(fid,"ylabel('Output Signal (real)');\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"legend('output time series','optimim timing',1);\n");
#endif

    // compute composite response
    fprintf(fid,"hd = real(conv(ht/k,conv(hc,hp)));\n");

    // plot frequency response
    fprintf(fid,"nfft = 1024;\n");
    fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n");
    fprintf(fid,"Ht = 20*log10(abs(fftshift(fft(ht/k,nfft))));\n");
    fprintf(fid,"Hc = 20*log10(abs(fftshift(fft(hc,  nfft))));\n");
    fprintf(fid,"Hp = 20*log10(abs(fftshift(fft(hp,  nfft))));\n");
    fprintf(fid,"Hd = 20*log10(abs(fftshift(fft(hd,  nfft))));\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(f,Ht, f,Hc, f,Hp, f,Hd,'-k','LineWidth',2);\n");
    fprintf(fid,"axis([-0.5 0.5 -20 10]);\n");
    fprintf(fid,"axis([-0.5 0.5 -6  6 ]);\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"legend('transmit','channel','equalizer','composite','location','northeast');\n");

    fprintf(fid,"i0 = [1:round(length(sym_out)/2)];\n");
    fprintf(fid,"i1 = [round(length(sym_out)/2):length(sym_out)];\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(real(sym_out(i0)),imag(sym_out(i0)),'x','MarkerSize',4,'Color',[0.60 0.60 0.60],...\n");
    fprintf(fid,"     real(sym_out(i1)),imag(sym_out(i1)),'x','MarkerSize',4,'Color',[0.00 0.25 0.50]);\n");
    fprintf(fid,"axis square;\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"axis([-1 1 -1 1]*1.2);\n");
    fprintf(fid,"xlabel('In-phase');\n");
    fprintf(fid,"ylabel('Quadrature');\n");
    fprintf(fid,"legend(['first 50%%'],['last 50%%'],'location','northeast');\n");

    fclose(fid);

    printf("results written to %s.\n", OUTPUT_FILENAME);

    // clean it up
    printf("done.\n");
    return 0;
}
Ejemplo n.º 13
0
int main() {
    // spectral periodogram options
    unsigned int nfft=512;              // spectral periodogram FFT size
    unsigned int num_samples = 4000;    // number of samples
    float beta = 10.0f;                 // Kaiser-Bessel window parameter
    float noise_floor = -60.0f;         // noise floor [dB]

    unsigned int i;

    // derived values
    float nstd = powf(10.0f, noise_floor/20.0f);

    // allocate memory for data arrays
    float complex X[nfft];              // output spectrum
    float psd[nfft];                    // power spectral density

    // initialize PSD estimate
    for (i=0; i<nfft; i++)
        psd[i] = 0.0f;

    // create spectral periodogram
    unsigned int window_size = nfft/2;  // spgram window size
    unsigned int delay       = nfft/8;  // samples between transforms
    spgram q = spgram_create_kaiser(nfft, window_size, beta);

    // generate signal (interpolated symbols with noise)
    unsigned int k = 4;     // interpolation rate
    unsigned int m = 7;     // filter delay (symbols)
    firinterp_crcf interp = firinterp_crcf_create_rnyquist(LIQUID_RNYQUIST_RKAISER, k, m, 0.3f, 0.0f);

    int spgram_timer = nfft;
    unsigned int n=0;
    float complex x[k]; // interpolator output
    unsigned int num_transforms = 0;
    while (n < num_samples) {
        // generate random symbol
        float complex s = ( rand() % 2 ? 0.707f : -0.707f ) +
                          ( rand() % 2 ? 0.707f : -0.707f ) * _Complex_I;

        // interpolate
        firinterp_crcf_execute(interp, s, x);

        // add noise
        for (i=0; i<k; i++)
            x[i] += nstd * ( randnf() + _Complex_I*randnf() ) * M_SQRT1_2;

        // push resulting samples through spgram
        spgram_push(q, x, k);

        // 
        spgram_timer -= k;
        n += k;

        //
        if (spgram_timer <= 0) {
            // update timer, counter
            spgram_timer += delay;
            num_transforms++;

            // run spectral periodogram
            spgram_execute(q, X);

            // accumulate PSD and FFT shift
            for (i=0; i<nfft; i++) {
                float complex X0 = X[(i+nfft/2)%nfft];
                psd[i] += crealf(X0*conjf(X0));
            }
        }
    }

    // destroy objects
    firinterp_crcf_destroy(interp);
    spgram_destroy(q);

    // normalize result
    printf("computed %u transforms\n", num_transforms);
    // TODO: ensure at least one transform was taken
    for (i=0; i<nfft; i++)
        psd[i] = 10*log10f( psd[i] / (float)(num_transforms) );

    // 
    // export output file
    //
    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\n");
    fprintf(fid,"nfft = %u;\n", nfft);
    fprintf(fid,"f    = [0:(nfft-1)]/nfft - 0.5;\n");
    fprintf(fid,"H    = zeros(1,nfft);\n");
    fprintf(fid,"noise_floor = %12.6f;\n", noise_floor);
    
    for (i=0; i<nfft; i++)
        fprintf(fid,"H(%6u) = %12.4e;\n", i+1, psd[i]);

    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(f, H, '-', 'LineWidth',1.5);\n");
    fprintf(fid,"xlabel('Normalized Frequency [f/F_s]');\n");
    fprintf(fid,"ylabel('Power Spectral Density [dB]');\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"ymin = 10*floor([noise_floor-20]/10);\n");
    fprintf(fid,"ymax = 10*floor([noise_floor+80]/10);\n");
    fprintf(fid,"axis([-0.5 0.5 ymin ymax]);\n");

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

    printf("done.\n");
    return 0;
}