Ejemplo n.º 1
0
// Helper function to keep code base small
void matrixf_linsolve_bench(struct rusage *     _start,
                            struct rusage *     _finish,
                            unsigned long int * _num_iterations,
                            unsigned int        _n)
{
    // normalize number of iterations
    // time ~ _n ^ 2
    *_num_iterations /= _n * _n;
    if (*_num_iterations < 1) *_num_iterations = 1;

    unsigned long int i;

    float A[_n*_n];
    float b[_n];
    float x[_n];
    for (i=0; i<_n*_n; i++)
        A[i] = randnf();
    for (i=0; i<_n; i++)
        b[i] = randnf();
    
    // start trials
    getrusage(RUSAGE_SELF, _start);
    for (i=0; i<(*_num_iterations); i++) {
        matrixf_linsolve(A,_n,b,x,NULL);
        matrixf_linsolve(A,_n,b,x,NULL);
        matrixf_linsolve(A,_n,b,x,NULL);
        matrixf_linsolve(A,_n,b,x,NULL);
    }
    getrusage(RUSAGE_SELF, _finish);
    *_num_iterations *= 4;
}
Ejemplo n.º 2
0
// Helper function to keep code base small
void polyf_fit_bench(struct rusage *_start,
                     struct rusage *_finish,
                     unsigned long int *_num_iterations,
                     unsigned int _Q,
                     unsigned int _N)
{
    // normalize number of iterations
    // time ~ 0.2953 + 0.03381 * _N
    *_num_iterations /= 0.2953 + 0.03381 * _N;
    if (*_num_iterations < 1) *_num_iterations = 1;

    float p[_Q+1];

    float x[_N];
    float y[_N];
    unsigned int i;
    for (i=0; i<_N; i++) {
        x[i] = randnf();
        y[i] = randnf();
    }
    
    // start trials
    getrusage(RUSAGE_SELF, _start);
    for (i=0; i<(*_num_iterations); i++) {
        polyf_fit(x,y,_N, p,_Q+1);
        polyf_fit(x,y,_N, p,_Q+1);
        polyf_fit(x,y,_N, p,_Q+1);
        polyf_fit(x,y,_N, p,_Q+1);
    }
    getrusage(RUSAGE_SELF, _finish);
    *_num_iterations *= 4;
}
Ejemplo n.º 3
0
// Helper function to keep code base small
void matrixf_mul_bench(struct rusage *_start,
                       struct rusage *_finish,
                       unsigned long int *_num_iterations,
                       unsigned int _n)
{
    // normalize number of iterations
    // time ~ _n ^ 2
    *_num_iterations /= _n * _n;
    if (*_num_iterations < 1) *_num_iterations = 1;

    float a[_n*_n];
    float b[_n*_n];
    float c[_n*_n];
    unsigned int i;
    for (i=0; i<_n*_n; i++) {
        a[i] = randnf();
        b[i] = randnf();
    }
    
    // start trials
    getrusage(RUSAGE_SELF, _start);
    for (i=0; i<(*_num_iterations); i++) {
        matrixf_mul(a,_n,_n,  b,_n,_n,  c,_n,_n);
        matrixf_mul(a,_n,_n,  b,_n,_n,  c,_n,_n);
        matrixf_mul(a,_n,_n,  b,_n,_n,  c,_n,_n);
        matrixf_mul(a,_n,_n,  b,_n,_n,  c,_n,_n);
    }
    getrusage(RUSAGE_SELF, _finish);
    *_num_iterations *= 4;
}
Ejemplo n.º 4
0
// helper function (compare structured object to ordinal computation)
void runtest_dotprod_cccf(unsigned int _n)
{
    float tol = 1e-3;
    float complex h[_n];
    float complex x[_n];

    // generate random coefficients
    unsigned int i;
    for (i=0; i<_n; i++) {
        h[i] = randnf() + randnf() * _Complex_I;
        x[i] = randnf() + randnf() * _Complex_I;
    }
    
    // compute expected value (ordinal computation)
    float complex y_test;
    dotprod_cccf_run(h, x, _n, &y_test);

    // create and run dot product object
    float complex y;
    dotprod_cccf dp;
    dp = dotprod_cccf_create(h,_n);
    dotprod_cccf_execute(dp, x, &y);
    dotprod_cccf_destroy(dp);

    // print results
    if (liquid_autotest_verbose) {
        printf("  dotprod-cccf-%-4u : %12.8f + j%12.8f (expected %12.8f + j%12.8f)\n",
                _n, crealf(y), cimagf(y), crealf(y_test), cimagf(y_test));
    }

    // validate result
    CONTEND_DELTA(crealf(y), crealf(y_test), tol);
    CONTEND_DELTA(cimagf(y), cimagf(y_test), tol);
}
Ejemplo n.º 5
0
// Helper function to keep code base small
void benchmark_framesync64(
    struct rusage *_start,
    struct rusage *_finish,
    unsigned long int *_num_iterations)
{
    *_num_iterations /= 128;
    unsigned long int i;

    framegen64 fg = framegen64_create();
    framegen64_print(fg);

    // frame data
    unsigned char header[8] = {0, 1, 2, 3, 4, 5, 6, 7};
    unsigned char payload[64];
    // initialize payload
    for (i=0; i<64; i++)
        payload[i] = rand() & 0xff;
    framedata fd = {0, 0, 0};

    // create framesync64 object
    framesync64 fs = framesync64_create(callback,(void*)&fd);
    framesync64_print(fs);

    // generate the frame
    //unsigned int frame_len = framegen64_getframelen(fg);
    unsigned int frame_len = LIQUID_FRAME64_LEN;
    float complex frame[frame_len];
    framegen64_execute(fg, header, payload, frame);

    // add some noise
    for (i=0; i<frame_len; i++)
        frame[i] += 0.01f*(randnf() + _Complex_I*randnf()) * M_SQRT1_2;

    // 
    // start trials
    //
    getrusage(RUSAGE_SELF, _start);
    for (i=0; i<(*_num_iterations); i++) {
        framesync64_execute(fs, frame, frame_len);
    }
    getrusage(RUSAGE_SELF, _finish);


    fd.num_frames_tx = *_num_iterations;
    printf("  frames detected/valid/transmitted  :   %6u / %6u / %6u\n",
            fd.num_frames_detected,
            fd.num_frames_valid,
            fd.num_frames_tx);

    framegen64_destroy(fg);
    framesync64_destroy(fs);
}
Ejemplo n.º 6
0
void benchmark_gmskmodem_demodulate(struct rusage *_start,
                                    struct rusage *_finish,
                                    unsigned long int *_num_iterations)
{
    // options
    unsigned int k=2;   // filter samples/symbol
    unsigned int m=3;   // filter delay (symbols)
    float BT=0.3f;      // bandwidth-time product

    // create modem object
    gmskdem demod = gmskdem_create(k, m, BT);

    float complex x[k];
    unsigned int symbol_out = 0;
    
    unsigned long int i;
    for (i=0; i<k; i++)
        x[i] = randnf()*cexpf(_Complex_I*2*M_PI*randf());

    // start trials
    getrusage(RUSAGE_SELF, _start);
    for (i=0; i<(*_num_iterations); i++) {
        gmskdem_demodulate(demod, x, &symbol_out);
        gmskdem_demodulate(demod, x, &symbol_out);
        gmskdem_demodulate(demod, x, &symbol_out);
        gmskdem_demodulate(demod, x, &symbol_out);
    }
    getrusage(RUSAGE_SELF, _finish);
    *_num_iterations *= 4;

    // destroy modem objects
    gmskdem_destroy(demod);
}
Ejemplo n.º 7
0
// Helper function to keep code base small
void eqrls_cccf_train_bench(struct rusage *_start,
                            struct rusage *_finish,
                            unsigned long int *_num_iterations,
                            unsigned int _h_len)
{
    // scale number of iterations appropriately
    // log(cycles/trial) ~ 5.57 + 2.74*log(_h_len)
    *_num_iterations *= 2400;
    *_num_iterations /= (unsigned int) expf(5.57f + 2.64f*logf(_h_len));
    *_num_iterations = (*_num_iterations < 4) ? 4 : *_num_iterations;

    eqrls_cccf eq = eqrls_cccf_create(NULL,_h_len);
    
    unsigned long int i;

    // set up initial arrays to 'randomize' inputs/outputs
    float complex y[11];
    for (i=0; i<11; i++)
        y[i] = randnf() + _Complex_I*randnf();

    float complex d[13];
    for (i=0; i<13; i++)
        d[i] = randnf() + _Complex_I*randnf();

    unsigned int iy=0;
    unsigned int id=0;

    float complex z;

    // start trials
    getrusage(RUSAGE_SELF, _start);
    for (i=0; i<(*_num_iterations); i++) {
        eqrls_cccf_push(eq, y[iy]);     // push input into equalizer
        eqrls_cccf_execute(eq, &z);     // compute equalizer output
        eqrls_cccf_step(eq, d[id], z);  // step equalizer internals

        // update counters
        iy = (iy+1)%11;
        id = (id+1)%13;
    }
    getrusage(RUSAGE_SELF, _finish);

    eqrls_cccf_destroy(eq);
}
Ejemplo n.º 8
0
// Helper function to keep code base small
void dotprod_crcf_bench(struct rusage *_start,
                        struct rusage *_finish,
                        unsigned long int *_num_iterations,
                        unsigned int _n)
{
    // normalize number of iterations
    *_num_iterations *= 100;
    *_num_iterations /= _n;
    if (*_num_iterations < 1) *_num_iterations = 1;

    float complex x[_n];
    float h[_n];
    float complex y[8];
    unsigned int i;
    for (i=0; i<_n; i++) {
        x[i] = randnf() + _Complex_I*randnf();
        h[i] = randnf();
    }

    // create dotprod structure;
    dotprod_crcf dp = dotprod_crcf_create(h,_n);

    // start trials
    getrusage(RUSAGE_SELF, _start);
    for (i=0; i<(*_num_iterations); i++) {
        dotprod_crcf_execute(dp, x, &y[0]);
        dotprod_crcf_execute(dp, x, &y[1]);
        dotprod_crcf_execute(dp, x, &y[2]);
        dotprod_crcf_execute(dp, x, &y[3]);
        dotprod_crcf_execute(dp, x, &y[4]);
        dotprod_crcf_execute(dp, x, &y[5]);
        dotprod_crcf_execute(dp, x, &y[6]);
        dotprod_crcf_execute(dp, x, &y[7]);
    }
    getrusage(RUSAGE_SELF, _finish);
    *_num_iterations *= 8;

    // clean up objects
    dotprod_crcf_destroy(dp);
}
Ejemplo n.º 9
0
// Helper function to keep code base small
void firfilt_crcf_bench(struct rusage *_start,
                        struct rusage *_finish,
                        unsigned long int *_num_iterations,
                        unsigned int _n)
{
    // adjust number of iterations:
    // cycles/trial ~ 107 + 4.3*_n
    *_num_iterations *= 1000;
    *_num_iterations /= (unsigned int)(107+4.3*_n);

    // generate coefficients
    float h[_n];
    unsigned long int i;
    for (i=0; i<_n; i++)
        h[i] = randnf();

    // create filter object
    firfilt_crcf f = firfilt_crcf_create(h,_n);

    // generate input vector
    float complex x[4];
    for (i=0; i<4; i++)
        x[i] = randnf() + _Complex_I*randnf();

    // output vector
    float complex y[4];

    // start trials
    getrusage(RUSAGE_SELF, _start);
    for (i=0; i<(*_num_iterations); i++) {
        firfilt_crcf_push(f, x[0]); firfilt_crcf_execute(f, &y[0]);
        firfilt_crcf_push(f, x[1]); firfilt_crcf_execute(f, &y[1]);
        firfilt_crcf_push(f, x[2]); firfilt_crcf_execute(f, &y[2]);
        firfilt_crcf_push(f, x[3]); firfilt_crcf_execute(f, &y[3]);
    }
    getrusage(RUSAGE_SELF, _finish);
    *_num_iterations *= 4;

    firfilt_crcf_destroy(f);
}
Ejemplo n.º 10
0
int main() {
    // options
    unsigned int order=4;   // filter order
    float fc=0.1f;          // cutoff frequency
    float f0=0.25f;         // center frequency (bandpass|bandstop)
    float Ap=1.0f;          // pass-band ripple [dB]
    float As=40.0f;         // stop-band attenuation [dB]
    liquid_iirdes_filtertype ftype  = LIQUID_IIRDES_ELLIP;
    liquid_iirdes_bandtype   btype  = LIQUID_IIRDES_BANDPASS;
    liquid_iirdes_format     format = LIQUID_IIRDES_SOS;

    // CREATE filter object (and print to stdout)
    iirfilt_crcf myfilter;
    myfilter = iirfilt_crcf_create_prototype(ftype,
                                             btype,
                                             format,
                                             order,
                                             fc, f0,
                                             Ap, As);
    iirfilt_crcf_print(myfilter);

    // allocate memory for data arrays
    unsigned int n=128; // number of samples
    float complex x[n]; // input samples array
    float complex y[n]; // output samples array

    // run filter
    unsigned int i;
    for (i=0; i<n; i++) {
        // initialize input
        x[i] = randnf() + _Complex_I*randnf();

        // EXECUTE filter (repeat as many times as desired)
        iirfilt_crcf_execute(myfilter, x[i], &y[i]);
    }

    // DESTROY filter object
    iirfilt_crcf_destroy(myfilter);
}
Ejemplo n.º 11
0
// benchmark regular frame synchronizer with noise; essentially test
// complexity when no signal is present
void benchmark_gmskframesync_noise(struct rusage *     _start,
                                   struct rusage *     _finish,
                                   unsigned long int * _num_iterations)
{
    *_num_iterations /= 400;
    unsigned long int i;

    // options
    float SNRdB = 20.0f;                // SNR

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

    // create frame synchronizer
    gmskframesync fs = gmskframesync_create(NULL, NULL);

    // allocate memory for noise buffer and initialize
    unsigned int num_samples = 1024;
    float complex y[num_samples];
    for (i=0; i<num_samples; i++)
        y[i] = nstd*(randnf() + randnf()*_Complex_I)*M_SQRT1_2;

    // 
    // start trials
    //
    getrusage(RUSAGE_SELF, _start);
    for (i=0; i<(*_num_iterations); i++) {
        // push samples through synchronizer
        gmskframesync_execute(fs, y, num_samples);
    }
    getrusage(RUSAGE_SELF, _finish);

    // scale result by number of samples in buffer
    *_num_iterations *= num_samples;

    // destroy framing objects
    gmskframesync_destroy(fs);
}
Ejemplo n.º 12
0
// Helper function to keep code base small
void fft_runbench(struct rusage *     _start,
                  struct rusage *     _finish,
                  unsigned long int * _num_iterations,
                  unsigned int        _nfft,
                  int                 _direction)
{
    // initialize arrays, plan
    float complex * x = (float complex *) malloc(_nfft*sizeof(float complex));
    float complex * y = (float complex *) malloc(_nfft*sizeof(float complex));
    int _method = 0;
    fftplan q = fft_create_plan(_nfft, x, y, _direction, _method);
    
    unsigned long int i;

    // initialize input with random values
    for (i=0; i<_nfft; i++)
        x[i] = randnf() + randnf()*_Complex_I;

    // scale number of iterations to keep execution time
    // relatively linear
    *_num_iterations /= _nfft;

    // start trials
    getrusage(RUSAGE_SELF, _start);
    for (i=0; i<(*_num_iterations); i++) {
        fft_execute(q);
        fft_execute(q);
        fft_execute(q);
        fft_execute(q);
    }
    getrusage(RUSAGE_SELF, _finish);
    *_num_iterations *= 4;

    fft_destroy_plan(q);
    free(x);
    free(y);
}
Ejemplo n.º 13
0
// 
// Test RSSI on noise input
//
void autotest_agc_crcf_rssi_noise()
{
    // set paramaters
    float gamma = -30.0f;   // nominal signal level [dB]
    float bt    =  0.01f;   // agc bandwidth
    float tol   =  0.2f;    // error tolerance [dB]

    // signal properties
    float nstd = powf(10.0f, gamma/20);

    // create AGC object and initialize
    agc_crcf q = agc_crcf_create();
    agc_crcf_set_bandwidth(q, bt);

    unsigned int i;
    float complex x, y;
    for (i=0; i<2000; i++) {
        // generate sample (circular complex noise)
        x = nstd*(randnf() + _Complex_I*randnf())*M_SQRT1_2;

        // execute agc
        agc_crcf_execute(q, x, &y);
    }

    // get received signal strength indication
    float rssi = agc_crcf_get_rssi(q);

    if (liquid_autotest_verbose)
        printf("gamma : %12.8f, rssi : %12.8f\n", gamma, rssi);

    // Check results
    CONTEND_DELTA( rssi, gamma, tol );

    // destroy agc object
    agc_crcf_destroy(q);
}
Ejemplo n.º 14
0
int main() {
    // options
    unsigned int nfft        =   64;    // transform size
    unsigned int num_frames  =  200;    // total number of frames
    unsigned int msdelay     =   50;    // delay between transforms [ms]
    float        noise_floor = -40.0f;  // noise floor

    // initialize objects
    asgramf q = asgramf_create(nfft);
    asgramf_set_scale(q, noise_floor+15.0f, 5.0f);

    unsigned int i;
    unsigned int n;
    float theta  = 0.0f;    // current instantaneous phase
    float dtheta = 0.0f;    // current instantaneous frequency
    float phi    = 0.0f;    // phase of sinusoidal frequency drift
    float dphi   = 0.003f;  // frequency of sinusoidal frequency drift

    float nstd = powf(10.0f,noise_floor/20.0f);  // noise standard deviation
    for (n=0; n<num_frames; n++) {
        // generate a frame of data samples
        for (i=0; i<nfft; i++) {
            // cosine wave of time-varying frequency with noise
            float x = cosf(theta) + nstd*randnf();

            // push sample into spectrogram object
            asgramf_push(q, x);

            // adjust frequency and phase
            theta  += dtheta;
            dtheta =  0.5f*M_PI + 0.4f*M_PI*sinf(phi) * hamming(n, num_frames);
            phi    += dphi;
        }

        // print the spectrogram to stdout
        asgramf_print(q);

        // sleep for some time before generating the next frame
        usleep(msdelay*1000);
    }

    asgramf_destroy(q);
    printf("done.\n");
    return 0;
}
// 
// AUTOTEST: polycf_findroots (random roots)
//
void xautotest_polycf_findroots_rand()
{
    unsigned int n=5;
    float tol=1e-4f;

    float complex p[n];
    float complex roots[n-1];

    float complex p_hat[n];

    unsigned int i;
    for (i=0; i<n; i++)
        p[i] = i == n-1 ? 1 : 3.0f * randnf();

    polycf_findroots(p,n,roots);

    float complex roots_hat[n-1];
    // convert form...
    for (i=0; i<n-1; i++)
        roots_hat[i] = -roots[i];

    polycf_expandroots(roots_hat,n-1,p_hat);

    if (liquid_autotest_verbose) {
        printf("poly:\n");
        for (i=0; i<n; i++)
            printf("  p[%3u] = %12.8f + j*%12.8f\n", i, crealf(p[i]), cimagf(p[i]));

        printf("roots:\n");
        for (i=0; i<n-1; i++)
            printf("  r[%3u] = %12.8f + j*%12.8f\n", i, crealf(roots[i]), cimagf(roots[i]));

        printf("poly (expanded roots):\n");
        for (i=0; i<n; i++)
            printf("  p[%3u] = %12.8f + j*%12.8f\n", i, crealf(p_hat[i]), cimagf(p_hat[i]));
    }

    for (i=0; i<n; i++) {
        CONTEND_DELTA(crealf(p[i]), crealf(p_hat[i]), tol);
        CONTEND_DELTA(cimagf(p[i]), cimagf(p_hat[i]), tol);
    }
}
Ejemplo n.º 16
0
// Helper function to keep code base small
void fft_r2r_bench(struct rusage *_start,
                   struct rusage *_finish,
                   unsigned long int *_num_iterations,
                   unsigned int _n,
                   int _kind)
{
    // initialize arrays, plan
    float x[_n], y[_n];
    int _flags = 0;
    fftplan p = fft_create_plan_r2r_1d(_n, x, y, _kind, _flags);
    
    unsigned long int i;

    // initialize input with random values
    for (i=0; i<_n; i++)
        x[i] = randnf();

    // scale number of iterations to keep execution time
    // relatively linear
    *_num_iterations /= _n * _n;
    *_num_iterations *= 10;
    *_num_iterations += 1;

    // start trials
    getrusage(RUSAGE_SELF, _start);
    for (i=0; i<(*_num_iterations); i++) {
        fft_execute(p);
        fft_execute(p);
        fft_execute(p);
        fft_execute(p);
    }
    getrusage(RUSAGE_SELF, _finish);
    *_num_iterations *= 4;

    fft_destroy_plan(p);
}
Ejemplo n.º 17
0
int main(int argc, char*argv[])
{
    // options
    unsigned int    bps         = 1;        // number of bits/symbol
    float           h           = 0.5f;     // modulation index (h=1/2 for MSK)
    unsigned int    k           = 4;        // filter samples/symbol
    unsigned int    m           = 3;        // filter delay (symbols)
    float           beta        = 0.35f;    // GMSK bandwidth-time factor
    unsigned int    num_symbols = 20;       // number of data symbols
    float           SNRdB       = 40.0f;    // signal-to-noise ratio [dB]
    float           cfo         = 0.0f;     // carrier frequency offset
    float           cpo         = 0.0f;     // carrier phase offset
    float           tau         = 0.0f;     // fractional symbol timing offset
    int             filter_type = LIQUID_CPFSK_SQUARE;

    int dopt;
    while ((dopt = getopt(argc,argv,"ht:p:H:k:m:b:n:s:F:P:T:")) != EOF) {
        switch (dopt) {
        case 'h': usage();                      return 0;
        case 't':
            if (strcmp(optarg,"square")==0) {
                filter_type = LIQUID_CPFSK_SQUARE;
            } else if (strcmp(optarg,"rcos-full")==0) {
                filter_type = LIQUID_CPFSK_RCOS_FULL;
            } else if (strcmp(optarg,"rcos-half")==0) {
                filter_type = LIQUID_CPFSK_RCOS_PARTIAL;
            } else if (strcmp(optarg,"gmsk")==0) {
                filter_type = LIQUID_CPFSK_GMSK;
            } else {
                fprintf(stderr,"error: %s, unknown filter type '%s'\n", argv[0], optarg);
                exit(1);
            }
            break;
        case 'p': bps   = atoi(optarg);         break;
        case 'H': h     = atof(optarg);         break;
        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;
        case 's': SNRdB = atof(optarg);         break;
        case 'F': cfo    = atof(optarg);        break;
        case 'P': cpo    = atof(optarg);        break;
        case 'T': tau    = atof(optarg);        break;
        default:
            exit(1);
        }
    }

    unsigned int i;

    // derived values
    unsigned int num_samples = k*num_symbols;
    unsigned int M = 1 << bps;              // constellation size
    float nstd = powf(10.0f, -SNRdB/20.0f);

    // arrays
    unsigned int sym_in[num_symbols];       // input symbols
    float complex x[num_samples];           // transmitted signal
    float complex y[num_samples];           // received signal
    unsigned int sym_out[num_symbols];      // output symbols

    // create modem objects
    cpfskmod mod = cpfskmod_create(bps, h, k, m, beta, filter_type);
    cpfskdem dem = cpfskdem_create(bps, h, k, m, beta, filter_type);

    // print modulator
    cpfskmod_print(mod);

    // generate message signal
    for (i=0; i<num_symbols; i++)
        sym_in[i] = rand() % M;

    // modulate signal
    for (i=0; i<num_symbols; i++)
        cpfskmod_modulate(mod, sym_in[i], &x[k*i]);

    // push through channel
    float sample_offset = -tau * k;
    int   sample_delay  = (int)roundf(sample_offset);
    float dt            = sample_offset - (float)sample_delay;
    printf("symbol delay    :   %f\n", tau);
    printf("sample delay    :   %f = %d + %f\n", sample_offset, sample_delay, dt);
    firfilt_crcf fchannel = firfilt_crcf_create_kaiser(8*k+2*sample_delay+1, 0.45f, 40.0f, dt);
    for (i=0; i<num_samples; i++) {
        // push through channel delay
        firfilt_crcf_push(fchannel, x[i]);
        firfilt_crcf_execute(fchannel, &y[i]);

        // add carrier frequency/phase offset
        y[i] *= cexpf(_Complex_I*(cfo*i + cpo));

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

    // demodulate signal
    unsigned int nw=0;
    cpfskdem_demodulate(dem, y, num_samples, sym_out, &nw);
    printf("demodulator wrote %u symbols\n", nw);

    // destroy modem objects
    cpfskmod_destroy(mod);
    cpfskdem_destroy(dem);

    // compute power spectral density of transmitted signal
    unsigned int nfft = 1024;
    float psd[nfft];
    spgramcf periodogram = spgramcf_create_kaiser(nfft, nfft/2, 8.0f);
    spgramcf_estimate_psd(periodogram, x, num_samples, psd);
    spgramcf_destroy(periodogram);

    // 
    // 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,"h = %f;\n", h);
    fprintf(fid,"num_symbols = %u;\n", num_symbols);
    fprintf(fid,"num_samples = %u;\n", num_samples);
    fprintf(fid,"nfft        = %u;\n", nfft);
    fprintf(fid,"delay       = %u; %% receive filter delay\n", m);

    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(%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]));
    }
    // save power spectral density
    fprintf(fid,"psd = zeros(1,nfft);\n");
    for (i=0; i<nfft; i++)
        fprintf(fid,"psd(%4u) = %12.8f;\n", i+1, psd[i]);

    fprintf(fid,"t=[0:(num_samples-1)]/k;\n");
    fprintf(fid,"i = 1:k:num_samples;\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"subplot(3,4,1:3);\n");
    fprintf(fid,"  plot(t,real(x),'-', t(i),real(x(i)),'ob',...\n");
    fprintf(fid,"       t,imag(x),'-', t(i),imag(x(i)),'og');\n");
    fprintf(fid,"  axis([0 num_symbols -1.2 1.2]);\n");
    fprintf(fid,"  xlabel('time');\n");
    fprintf(fid,"  ylabel('x(t)');\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"subplot(3,4,5:7);\n");
    fprintf(fid,"  plot(t,real(y),'-', t(i),real(y(i)),'ob',...\n");
    fprintf(fid,"       t,imag(y),'-', t(i),imag(y(i)),'og');\n");
    fprintf(fid,"  axis([0 num_symbols -1.2 1.2]);\n");
    fprintf(fid,"  xlabel('time');\n");
    fprintf(fid,"  ylabel('y(t)');\n");
    fprintf(fid,"  grid on;\n");
    // plot I/Q constellations
    fprintf(fid,"subplot(3,4,4);\n");
    fprintf(fid,"  plot(real(x),imag(x),'-',real(x(i)),imag(x(i)),'rs','MarkerSize',4);\n");
    fprintf(fid,"  xlabel('I');\n");
    fprintf(fid,"  ylabel('Q');\n");
    fprintf(fid,"  axis([-1 1 -1 1]*1.2);\n");
    fprintf(fid,"  axis square;\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"subplot(3,4,8);\n");
    fprintf(fid,"  plot(real(y),imag(y),'-',real(y(i)),imag(y(i)),'rs','MarkerSize',4);\n");
    fprintf(fid,"  xlabel('I');\n");
    fprintf(fid,"  ylabel('Q');\n");
    fprintf(fid,"  axis([-1 1 -1 1]*1.2);\n");
    fprintf(fid,"  axis square;\n");
    fprintf(fid,"  grid on;\n");
    // plot PSD
    fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n");
    fprintf(fid,"subplot(3,4,9:12);\n");
    fprintf(fid,"  plot(f,psd,'LineWidth',1.5);\n");
    fprintf(fid,"  axis([-0.5 0.5 -60 20]);\n");
    fprintf(fid,"  xlabel('Normalized Frequency [f/F_s]');\n");
    fprintf(fid,"  ylabel('PSD [dB]');\n");
    fprintf(fid,"  grid on;\n");

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

    return 0;
}
Ejemplo n.º 18
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;
}
Ejemplo n.º 19
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;
}
Ejemplo n.º 20
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);
    interp_crcf q = interp_crcf_create(k,h,h_len);
    for (i=0; i<num_symbols; i++) {
        interp_crcf_execute(q, s[i], &x[n]);
        n+=k;
    }
    assert(n == num_samples);
    interp_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.º 21
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.º 22
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.º 23
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);
}
Ejemplo n.º 24
0
int main(int argc, char *argv[])
{
    //srand( time(NULL) );

    // options
    modulation_scheme ms     =  LIQUID_MODEM_QPSK; // mod. scheme
    crc_scheme check         =  LIQUID_CRC_32;     // data validity check
    fec_scheme fec0          =  LIQUID_FEC_NONE;   // fec (inner)
    fec_scheme fec1          =  LIQUID_FEC_NONE;   // fec (outer)
    unsigned int payload_len =  120;               // payload length
    int debug_enabled        =  0;                 // enable debugging?
    float noise_floor        = -60.0f;             // noise floor
    float SNRdB              =  20.0f;             // signal-to-noise ratio
    float dphi               =  0.01f;             // carrier frequency offset

    // get options
    int dopt;
    while((dopt = getopt(argc,argv,"uhs:F:n:m:v:c:k:d")) != EOF){
        switch (dopt) {
        case 'u':
        case 'h': usage();                                       return 0;
        case 's': SNRdB         = atof(optarg);                  break;
        case 'F': dphi          = atof(optarg);                  break;
        case 'n': payload_len   = atol(optarg);                  break;
        case 'm': ms            = liquid_getopt_str2mod(optarg); break;
        case 'v': check         = liquid_getopt_str2crc(optarg); break;
        case 'c': fec0          = liquid_getopt_str2fec(optarg); break;
        case 'k': fec1          = liquid_getopt_str2fec(optarg); break;
        case 'd': debug_enabled = 1;                             break;
        default:
            exit(-1);
        }
    }

    // derived values
    unsigned int i;
    float nstd  = powf(10.0f, noise_floor/20.0f);         // noise std. dev.
    float gamma = powf(10.0f, (SNRdB+noise_floor)/20.0f); // channel gain

    // create flexframegen object
    flexframegenprops_s fgprops;
    flexframegenprops_init_default(&fgprops);
    fgprops.mod_scheme  = ms;
    fgprops.check       = check;
    fgprops.fec0        = fec0;
    fgprops.fec1        = fec1;
    flexframegen fg = flexframegen_create(&fgprops);

    // frame data (header and payload)
    unsigned char header[14];
    unsigned char payload[payload_len];

    // create flexframesync object
    flexframesync fs = flexframesync_create(callback,NULL);
    if (debug_enabled)
        flexframesync_debug_enable(fs);

    // initialize header, payload
    for (i=0; i<14; i++)
        header[i] = i;
    for (i=0; i<payload_len; i++)
        payload[i] = rand() & 0xff;

    // assemble the frame
    flexframegen_assemble(fg, header, payload, payload_len);
    flexframegen_print(fg);

    // generate the frame in blocks
    unsigned int  buf_len = 256;
    float complex x[buf_len];
    float complex y[buf_len];

    int frame_complete = 0;
    float phi = 0.0f;
    while (!frame_complete) {
        // write samples to buffer
        frame_complete = flexframegen_write_samples(fg, x, buf_len);

        // add noise and push through synchronizer
        for (i=0; i<buf_len; i++) {
            // apply channel gain and carrier offset to input
            y[i] = gamma * x[i] * cexpf(_Complex_I*phi);
            phi += dphi;

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

        // run through frame synchronizer
        flexframesync_execute(fs, y, buf_len);
    }

    // export debugging file
    if (debug_enabled)
        flexframesync_debug_print(fs, "flexframesync_debug.m");

    flexframesync_print(fs);
    // destroy allocated objects
    flexframegen_destroy(fg);
    flexframesync_destroy(fs);

    printf("done.\n");
    return 0;
}
Ejemplo n.º 25
0
int main(int argc, char*argv[])
{
    // set random number generator seed
    srand(time(NULL));

    // options
    unsigned int M = 64;                // number of subcarriers
    unsigned int cp_len = 16;           // cyclic prefix length
    modulation_scheme ms = LIQUID_MODEM_BPSK;
    float SNRdB = 6.5f;                 // signal-to-noise ratio [dB]
    unsigned int hc_len = 1;            // channel impulse response length
    unsigned int num_symbols = 40;      // number of OFDM symbols

    // get options
    int dopt;
    while((dopt = getopt(argc,argv,"hs:M:C:m:n:c:")) != EOF){
        switch (dopt) {
        case 'h': usage(); return 0;
        case 's': SNRdB  = atof(optarg); break;
        case 'M': M      = atoi(optarg); break;
        case 'C': cp_len = atoi(optarg); break;
        case 'm':
            ms = liquid_getopt_str2mod(optarg);
            if (ms == LIQUID_MODEM_UNKNOWN) {
                fprintf(stderr,"error: %s, unknown/unsupported mod. scheme: %s\n", argv[0], optarg);
                exit(-1);
            }
            break;
        case 'n': num_symbols = atoi(optarg); break;
        case 'c': hc_len      = atoi(optarg); break;
        default:
            exit(-1);
        }
    }

    unsigned int i;

    // validate options
    if (M < 4) {
        fprintf(stderr,"error: %s, must have at least 4 subcarriers\n", argv[0]);
        exit(1);
    } else if (hc_len == 0) {
        fprintf(stderr,"error: %s, must have at least 1 channel tap\n", argv[0]);
        exit(1);
    }

    // derived values
    unsigned int symbol_len = M + cp_len;
    float nstd = powf(10.0f, -SNRdB/20.0f);
    float fft_gain = 1.0f / sqrtf(M);   // 'gain' due to taking FFT
    
    // buffers
    unsigned int sym_in[M];             // input data symbols
    unsigned int sym_out[M];            // output data symbols
    float complex x[M];                 // time-domain buffer
    float complex X[M];                 // freq-domain buffer
    float complex buffer[symbol_len];   // 

    // create modulator/demodulator objects
    modem mod   = modem_create(ms);
    modem demod = modem_create(ms);
    unsigned int bps = modem_get_bps(mod);  // modem bits/symbol

    // create channel filter (random taps)
    float complex hc[hc_len];
    hc[0] = 1.0f;
    for (i=1; i<hc_len; i++)
        hc[i] = 0.1f * (randnf() + _Complex_I*randnf());
    firfilt_cccf fchannel = firfilt_cccf_create(hc, hc_len);

    //
    unsigned int n;
    unsigned int num_bit_errors = 0;
    for (n=0; n<num_symbols; n++) {
        // generate random data symbols and modulate onto subcarriers
        for (i=0; i<M; i++) {
            sym_in[i] = rand() % (1<<bps);

            modem_modulate(mod, sym_in[i], &X[i]);
        }

        // run inverse transform
        fft_run(M, X, x, LIQUID_FFT_BACKWARD, 0);

        // scale by FFT gain so E{|x|^2} = 1
        for (i=0; i<M; i++)
            x[i] *= fft_gain;

        // apply channel impairments
        for (i=0; i<M + cp_len; i++) {
            // push samples through channel filter, starting with cyclic prefix
            firfilt_cccf_push(fchannel, x[(M-cp_len+i)%M]);

            // compute output
            firfilt_cccf_execute(fchannel, &buffer[i]);

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

        // run forward transform
        fft_run(M, &buffer[cp_len], X, LIQUID_FFT_FORWARD, 0);

        // TODO : apply equalizer to 'X' here

        // demodulate and compute bit errors
        for (i=0; i<M; i++) {
            // scale by fft size
            X[i] *= fft_gain;

            modem_demodulate(demod, X[i], &sym_out[i]);

            num_bit_errors += liquid_count_ones(sym_in[i] ^ sym_out[i]);
        }
    }

    // destroy objects
    modem_destroy(mod);
    modem_destroy(demod);
    firfilt_cccf_destroy(fchannel);

    // print results
    unsigned int total_bits = M*bps*num_symbols;
    float ber = (float)num_bit_errors / (float)total_bits;
    printf("  bit errors : %6u / %6u (%12.4e)\n", num_bit_errors, total_bits, ber);

    printf("done.\n");
    return 0;
}
Ejemplo n.º 26
0
int main() {
    // options
    unsigned int num_channels=4;    // number of channels
    unsigned int p=3;               // filter length (symbols)
    unsigned int num_symbols=6;     // number of symbols

    // derived values
    unsigned int num_samples = num_channels * num_symbols;

    unsigned int i;
    unsigned int j;

    // generate synthesis filter
    // NOTE : these coefficients can be random; the purpose of this
    //        exercise is to demonstrate mathematical equivalence
    unsigned int h_len = p*num_channels;
    float h[h_len];
    for (i=0; i<h_len; i++) h[i] = randnf();

    // generate analysis filter
    unsigned int g_len = p*num_channels;
    float g[g_len];
    for (i=0; i<g_len; i++)
        g[i] = h[g_len-i-1];

    // create synthesis/analysis filter objects
    firfilt_crcf fs = firfilt_crcf_create(h, h_len);
    firfilt_crcf fa = firfilt_crcf_create(g, g_len);

    // create synthesis/analysis filterbank channelizer objects
    firpfbch_crcf qs = firpfbch_crcf_create(LIQUID_SYNTHESIZER, num_channels, p, h);
    firpfbch_crcf qa = firpfbch_crcf_create(LIQUID_ANALYZER,    num_channels, p, g);

    float complex x[num_samples];                   // random input (noise)
    float complex Y0[num_symbols][num_channels];    // channelized output (filterbank)
    float complex Y1[num_symbols][num_channels];    // channelized output
    float complex z0[num_samples];                  // time-domain output (filterbank)
    float complex z1[num_samples];                  // time-domain output

    // generate input sequence (complex noise)
    for (i=0; i<num_samples; i++)
        x[i] = randnf() * cexpf(_Complex_I*randf()*2*M_PI);

    // 
    // ANALYZERS
    //
    
    // 
    // run analysis filter bank
    //
    for (i=0; i<num_symbols; i++)
        firpfbch_crcf_analyzer_execute(qa, &x[i*num_channels], &Y0[i][0]);


    // 
    // run traditional down-converter (inefficient)
    //
    float dphi; // carrier frequency
    unsigned int n=0;
    for (i=0; i<num_channels; i++) {

        // reset filter
        firfilt_crcf_clear(fa);

        // set center frequency
        dphi = 2.0f * M_PI * (float)i / (float)num_channels;

        // reset symbol counter
        n=0;

        for (j=0; j<num_samples; j++) {
            // push down-converted sample into filter
            firfilt_crcf_push(fa, x[j]*cexpf(-_Complex_I*j*dphi));

            // compute output at the appropriate sample time
            assert(n<num_symbols);
            if ( ((j+1)%num_channels)==0 ) {
                firfilt_crcf_execute(fa, &Y1[n][i]);
                n++;
            }
        }
        assert(n==num_symbols);

    }


    // 
    // SYNTHESIZERS
    //

    // 
    // run synthesis filter bank
    //
    for (i=0; i<num_symbols; i++)
        firpfbch_crcf_synthesizer_execute(qs, &Y0[i][0], &z0[i*num_channels]);

    // 
    // run traditional up-converter (inefficient)
    //

    // clear output array
    for (i=0; i<num_samples; i++)
        z1[i] = 0.0f;

    float complex y_hat;
    for (i=0; i<num_channels; i++) {
        // reset filter
        firfilt_crcf_clear(fs);

        // set center frequency
        dphi = 2.0f * M_PI * (float)i / (float)num_channels;

        // reset input symbol counter
        n=0;

        for (j=0; j<num_samples; j++) {

            // interpolate sequence
            if ( (j%num_channels)==0 ) {
                assert(n<num_symbols);
                firfilt_crcf_push(fs, Y1[n][i]);
                n++;
            } else {
                firfilt_crcf_push(fs, 0);
            }
            firfilt_crcf_execute(fs, &y_hat);

            // accumulate up-converted sample
            z1[j] += y_hat * cexpf(_Complex_I*j*dphi);
        }
        assert(n==num_symbols);
    }

    // destroy objects
    firfilt_crcf_destroy(fs);
    firfilt_crcf_destroy(fa);
    firpfbch_crcf_destroy(qs);
    firpfbch_crcf_destroy(qa);


    //
    // RESULTS
    //

    // 
    // analyzers
    //

    // print filterbank channelizer
    printf("\n");
    printf("filterbank channelizer:\n");
    for (i=0; i<num_symbols; i++) {
        printf("%3u: ", i);
        for (j=0; j<num_channels; j++) {
            printf("  %8.5f+j%8.5f, ", crealf(Y0[i][j]), cimagf(Y0[i][j]));
        }
        printf("\n");
    }

    // print traditional channelizer
    printf("\n");
    printf("traditional channelizer:\n");
    for (i=0; i<num_symbols; i++) {
        printf("%3u: ", i);
        for (j=0; j<num_channels; j++) {
            printf("  %8.5f+j%8.5f, ", crealf(Y1[i][j]), cimagf(Y1[i][j]));
        }
        printf("\n");
    }


    float mse_analyzer[num_channels];
    float complex d;
    for (i=0; i<num_channels; i++) {
        mse_analyzer[i] = 0.0f;
        for (j=0; j<num_symbols; j++) {
            d = Y0[j][i] - Y1[j][i];
            mse_analyzer[i] += crealf(d*conjf(d));
        }

        mse_analyzer[i] /= num_symbols;
    }
    printf("\n");
    printf("rmse: ");
    for (i=0; i<num_channels; i++)
        printf("%12.4e          ", sqrt(mse_analyzer[i]));
    printf("\n");


    // 
    // synthesizers
    //

    printf("\n");
    printf("output: filterbank:             traditional:\n");
    for (i=0; i<num_samples; i++) {
        printf("%3u: %10.5f+%10.5fj  %10.5f+%10.5fj\n",
            i,
            crealf(z0[i]), cimagf(z0[i]),
            crealf(z1[i]), cimagf(z1[i]));
    }

    float mse_synthesizer = 0.0f;
    for (i=0; i<num_samples; i++) {
        d = z0[i] - z1[i];
        mse_synthesizer += crealf(d*conjf(d));
    }
    mse_synthesizer /= num_samples;
    printf("\n");
    printf("rmse: %12.4e\n", sqrtf(mse_synthesizer));

    //
    // EXPORT DATA TO 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,"num_channels=%u;\n", num_channels);
    fprintf(fid,"num_symbols=%u;\n", num_symbols);
    fprintf(fid,"num_samples = num_channels*num_symbols;\n");

    fprintf(fid,"x  = zeros(1,num_samples);\n");
    fprintf(fid,"y0 = zeros(num_symbols,num_channels);\n");
    fprintf(fid,"y1 = zeros(num_symbols,num_channels);\n");
    fprintf(fid,"z0 = zeros(1,num_samples);\n");
    fprintf(fid,"z1 = zeros(1,num_samples);\n");

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

    // analysis
    for (i=0; i<num_symbols; i++) {
        for (j=0; j<num_channels; j++) {
            fprintf(fid,"y0(%4u,%4u) = %12.4e + j*%12.4e;\n", i+1, j+1, crealf(Y0[i][j]), cimag(Y0[i][j]));
            fprintf(fid,"y1(%4u,%4u) = %12.4e + j*%12.4e;\n", i+1, j+1, crealf(Y1[i][j]), cimag(Y1[i][j]));
        }
    }

    // synthesis
    for (i=0; i<num_samples; i++) {
        fprintf(fid,"z0(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(z0[i]), cimag(z0[i]));
        fprintf(fid,"z1(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(z1[i]), cimag(z1[i]));
    }
    fprintf(fid,"z0 = z0 / num_channels;\n");
    fprintf(fid,"z1 = z1 / num_channels;\n");

    // plot results
    fprintf(fid,"\n\n");
    fprintf(fid,"ts = 0:(num_symbols-1);\n");
    fprintf(fid,"for i=1:num_channels,\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"title(['channel ' num2str(i)]);\n");
    fprintf(fid,"subplot(2,1,1);\n");
    fprintf(fid,"    plot(ts,real(y0(:,i)),'-x', ts,real(y1(:,i)),'s');\n");
    //fprintf(fid,"    axis([0 (num_symbols-1) -2 2]);\n");
    fprintf(fid,"subplot(2,1,2);\n");
    fprintf(fid,"    plot(ts,imag(y0(:,i)),'-x', ts,imag(y1(:,i)),'s');\n");
    //fprintf(fid,"    axis([0 (num_symbols-1) -2 2]);\n");
    fprintf(fid,"end;\n");

    fprintf(fid,"t  = 0:(num_samples-1);\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"title('composite');\n");
    fprintf(fid,"subplot(2,1,1);\n");
    fprintf(fid,"    plot(t,real(z0),'-x', t,real(z1),'s');\n");
    fprintf(fid,"subplot(2,1,2);\n");
    fprintf(fid,"    plot(t,imag(z0),'-x', t,imag(z1),'s');\n");


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

    printf("done.\n");
    return 0;
}
Ejemplo n.º 27
0
int main(int argc, char*argv[]) {
    // options
    unsigned int k=4;                   // filter samples/symbol
    unsigned int m=3;                   // filter delay (symbols)
    float BT=0.3f;                      // bandwidth-time product
    unsigned int num_data_symbols=200;  // number of data symbols
    float SNRdB = 30.0f;                // signal-to-noise ratio [dB]
    float phi = 0.0f;                   // carrier phase offset
    float dphi = 0.0f;                  // carrier frequency offset

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

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

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

    // create modulator
    gmskmod mod   = gmskmod_create(k, m, BT);
    gmskmod_print(mod);

    // create demodulator
    gmskdem demod = gmskdem_create(k, m, BT);
    gmskdem_set_eq_bw(demod, 0.01f);
    gmskdem_print(demod);

    unsigned int i;
    unsigned int s[num_symbols];
    float complex x[num_samples];
    float complex y[num_samples];
    unsigned int sym_out[num_symbols];

    // generate random data sequence
    for (i=0; i<num_symbols; i++)
        s[i] = rand() % 2;

    // modulate signal
    for (i=0; i<num_symbols; i++)
        gmskmod_modulate(mod, s[i], &x[k*i]);

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

    // demodulate signal
    for (i=0; i<num_symbols; i++)
        gmskdem_demodulate(demod, &y[k*i], &sym_out[i]);

    // destroy modem objects
    gmskmod_destroy(mod);
    gmskdem_destroy(demod);

    // print results to screen
    unsigned int delay = 2*m;
    unsigned int num_errors=0;
    for (i=delay; i<num_symbols; i++) {
        //printf("  %4u : %2u (%2u)\n", i, s[i-delay], sym_out[i]);
        num_errors += (s[i-delay] == sym_out[i]) ? 0 : 1;
    }
    printf("symbol errors : %4u / %4u\n", num_errors, num_data_symbols);

    // write results to 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");
    fprintf(fid,"k = %u;\n", k);
    fprintf(fid,"m = %u;\n", m);
    fprintf(fid,"BT = %f;\n", BT);
    fprintf(fid,"num_symbols = %u;\n", num_symbols);
    fprintf(fid,"num_samples = %u;\n", num_samples);

    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(%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,"t=[0:(num_samples-1)]/k;\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(t,real(y),t,imag(y));\n");

    // artificially demodulate (generate receive filter, etc.)
    float hr[2*k*m+1];
    liquid_firdes_gmskrx(k,m,BT,0,hr);
    for (i=0; i<2*k*m+1; i++)
        fprintf(fid,"hr(%3u) = %12.8f;\n", i+1, hr[i]);
    fprintf(fid,"z = filter(hr,1,arg( ([y(2:end) 0]).*conj(y) ))/k;\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(t,z,t(k:k:end),z(k:k:end),'or');\n");
    fprintf(fid,"grid on;\n");

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

    return 0;
}
Ejemplo n.º 28
0
int main(int argc, char*argv[])
{
    // options
    unsigned int m           =   3;     // number of bits/symbol
    unsigned int k           =   0;     // filter samples/symbol
    unsigned int num_symbols = 8000;    // number of data symbols
    float        SNRdB       = 40.0f;   // signal-to-noise ratio [dB]
    float        bandwidth   = 0.20;    // frequency spacing
    unsigned int nfft        = 1200;    // FFT size for compute spectrum
    float        alpha       = 0.01f;   // PSD accumulation constant

    int dopt;
    while ((dopt = getopt(argc,argv,"hm:k:b:n:s:")) != EOF) {
        switch (dopt) {
        case 'h': usage();                      return 0;
        case 'm': m           = atoi(optarg);   break;
        case 'k': k           = atoi(optarg);   break;
        case 'b': bandwidth   = atof(optarg);   break;
        case 'n': num_symbols = atoi(optarg);   break;
        case 's': SNRdB       = atof(optarg);   break;
        default:
            exit(1);
        }
    }

    unsigned int i;
    unsigned int j;

    // derived values
    if (k == 0)
        k = 2 << m; // set samples per symbol if not otherwise specified
    unsigned int M    = 1 << m;
    float        nstd = powf(10.0f, -SNRdB/20.0f);

    // validate input
    if (k < M) {
        fprintf(stderr,"errors: %s, samples/symbol must be at least modulation size (M=%u)\n", __FILE__,M);
        exit(1);
    } else if (k > 2048) {
        fprintf(stderr,"errors: %s, samples/symbol exceeds maximum (2048)\n", __FILE__);
        exit(1);
    } else if (M > 1024) {
        fprintf(stderr,"errors: %s, modulation size (M=%u) exceeds maximum (1024)\n", __FILE__, M);
        exit(1);
    } else if (bandwidth <= 0.0f || bandwidth >= 0.5f) {
        fprintf(stderr,"errors: %s, bandwidht must be in (0,0.5)\n", __FILE__);
        exit(1);
    }

    // create modulator/demodulator pair
    fskmod mod = fskmod_create(m,k,bandwidth);
    fskdem dem = fskdem_create(m,k,bandwidth);
    fskdem_print(dem);

    // 
    float complex buf_tx[k];    // transmit buffer
    float complex buf_rx[k];    // transmit buffer
    
    // spectral periodogram
    spgramcf periodogram = spgramcf_create_kaiser(nfft, nfft/2, 8.0f);

    // modulate, demodulate, count errors
    unsigned int num_symbol_errors = 0;
    for (i=0; i<num_symbols; i++) {
        // generate random symbol
        unsigned int sym_in = rand() % M;

        // modulate
        fskmod_modulate(mod, sym_in, buf_tx);

        // add noise
        for (j=0; j<k; j++)
            buf_rx[j] = buf_tx[j] + nstd*(randnf() + _Complex_I*randnf())*M_SQRT1_2;

        // demodulate
        unsigned int sym_out = fskdem_demodulate(dem, buf_rx);

        // count errors
        num_symbol_errors += (sym_in == sym_out) ? 0 : 1;

        // estimate power spectral density
        spgramcf_accumulate_psd(periodogram, buf_rx, alpha, k);
    }

    printf("symbol errors: %u / %u\n", num_symbol_errors, num_symbols);

    // compute power spectral density of received signal
    float psd[nfft];
    spgramcf_write_accumulation(periodogram, psd);
    spgramcf_destroy(periodogram);

    // 
    // 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,"num_symbols = %u;\n", num_symbols);
    fprintf(fid,"nfft        = %u;\n", nfft);

    // save power spectral density
    fprintf(fid,"psd = zeros(1,nfft);\n");
    for (i=0; i<nfft; i++)
        fprintf(fid,"psd(%4u) = %12.8f;\n", i+1, psd[i]);

    // plot PSD
    fprintf(fid,"figure('Color','white');\n");
    fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n");
    fprintf(fid,"plot(f,psd,'LineWidth',1.5,'Color',[0.5 0 0]);\n");
    fprintf(fid,"axis([-0.5 0.5 -40 20]);\n");
    fprintf(fid,"xlabel('Normalized Frequency [f/F_s]');\n");
    fprintf(fid,"ylabel('PSD [dB]');\n");
    fprintf(fid,"grid on;\n");

    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;
}
int main() {
    // options
    unsigned int num_samples = 400;     // number of samples
    float sig = 0.1f;                   // noise variance
    unsigned int num_iterations = 1000; // number of iterations to run

    float v[3] = {1, 1, 1};
    unsigned int i;

    // range
    float xmin = 0.0f;
    float xmax = 6.0f;
    float dx = (xmax - xmin) / (num_samples-1);

    // generate data set
    float x[num_samples];
    float y[num_samples];
    for (i=0; i<num_samples; i++) {
        x[i] = xmin + i*dx;
        y[i] = sincf(x[i]) + randnf()*sig;
    }
    struct gsdataset q = {x, y, num_samples};

    // create gradsearch object
    gradsearchprops_s gsprops;
    gradsearchprops_init_default(&gsprops);
    gsprops.delta = 1e-6f;  // gradient approximation step size
    gsprops.gamma = 0.002f; // vector step size
    gsprops.alpha = 0.1f;   // momentum parameter
    gsprops.mu    = 0.999f; // decremental gamma paramter (best if not exactly 1.0)

    gradsearch gs = gradsearch_create((void*)&q, v, 3, gserror, LIQUID_OPTIM_MINIMIZE, &gsprops);

    float rmse;

    // execute search
    //rmse = gradsearch_run(gs, num_iterations, -1e-6f);

     // open 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");

   // execute search one iteration at a time
    fprintf(fid,"u = zeros(1,%u);\n", num_iterations);
    for (i=0; i<num_iterations; i++) {
        rmse = gserror((void*)&q,v,3);
        fprintf(fid,"u(%3u) = %12.4e;\n", i+1, rmse);

        gradsearch_step(gs);

        if (((i+1)%100)==0)
            gradsearch_print(gs);
    }

    // print results
    printf("\n");
    gradsearch_print(gs);
    printf("  c0 = %12.8f, opt = 1\n", v[0]);
    printf("  c1 = %12.8f, opt = 0\n", v[1]);
    printf("  c2 = %12.8f, opt = 1\n", v[2]);
    printf("  rmse = %12.4e\n", rmse);

    fprintf(fid,"figure;\n");
    fprintf(fid,"semilogy(u);\n");
    fprintf(fid,"xlabel('iteration');\n");
    fprintf(fid,"ylabel('error');\n");
    fprintf(fid,"title('gradient search results');\n");
    fprintf(fid,"grid on;\n");

    // save sampled data set
    for (i=0; i<num_samples; i++) {
        fprintf(fid,"  x(%4u) = %12.8f;\n", i+1, x[i]);
        fprintf(fid,"  y(%4u) = %12.8f;\n", i+1, y[i]);
        fprintf(fid,"  y_hat(%4u) = %12.8f;\n", i+1, gsfunc(x[i],v));
    }
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(x,y,'x', x,y_hat,'-');\n");
    fprintf(fid,"xlabel('x');\n");
    fprintf(fid,"ylabel('f(x)');\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"legend('data','fit',1);\n");


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

    gradsearch_destroy(gs);

    return 0;
}