Beispiel #1
0
// 
// Test AC gain control
//
void autotest_agc_crcf_ac_gain_control()
{
    // set paramaters
    float gamma = 0.1f;             // nominal signal level
    float bt    = 0.1f;             // bandwidth-time product
    float tol   = 0.001f;           // error tolerance
    float dphi  = 0.1f;             // NCO frequency

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

    unsigned int i;
    float complex x;
    float complex y;
    for (i=0; i<256; i++) {
        x = gamma * cexpf(_Complex_I*i*dphi);
        agc_crcf_execute(q, x, &y);
    }

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

    // Check results
    CONTEND_DELTA( agc_crcf_get_gain(q), 1.0f/gamma, tol);

    // destroy AGC object
    agc_crcf_destroy(q);
}
Beispiel #2
0
// helper function to keep code base small
void benchmark_agc_crcf(struct rusage *     _start,
                        struct rusage *     _finish,
                        unsigned long int * _num_iterations)
{
    unsigned int i;

    // initialize AGC object
    agc_crcf q = agc_crcf_create();
    agc_crcf_set_bandwidth(q,0.05f);

    float complex x = 1e-6f;    // input sample
    float complex y;            // output sample

    getrusage(RUSAGE_SELF, _start);
    for (i=0; i<(*_num_iterations); i++) {
        agc_crcf_execute(q, x, &y);
        agc_crcf_execute(q, x, &y);
        agc_crcf_execute(q, x, &y);
        agc_crcf_execute(q, x, &y);
        agc_crcf_execute(q, x, &y);
        agc_crcf_execute(q, x, &y);
        agc_crcf_execute(q, x, &y);
        agc_crcf_execute(q, x, &y);
    }
    getrusage(RUSAGE_SELF, _finish);

    *_num_iterations *= 8;

    // destroy object
    agc_crcf_destroy(q);
}
Beispiel #3
0
// 
// Test DC gain control
//
void autotest_agc_crcf_dc_gain_control()
{
    // set paramaters
    float gamma = 0.1f;     // nominal signal level
    float bt    = 0.1f;     // bandwidth-time product
    float tol   = 0.001f;   // error tolerance

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

    unsigned int i;
    float complex x = gamma;    // input sample
    float complex y;            // output sample
    for (i=0; i<256; i++)
        agc_crcf_execute(q, x, &y);
    
    // Check results
    CONTEND_DELTA( crealf(y), 1.0f, tol );
    CONTEND_DELTA( cimagf(y), 0.0f, tol );
    CONTEND_DELTA( agc_crcf_get_gain(q), 1.0f/gamma, tol );

    // destroy AGC object
    agc_crcf_destroy(q);
}
Beispiel #4
0
void wlanframesync_debug_enable(wlanframesync _q)
{
    // create debugging objects if necessary
#if DEBUG_WLANFRAMESYNC
    // agc, rssi
    if (_q->agc_rx == NULL)
        _q->agc_rx = agc_crcf_create();
    agc_crcf_set_bandwidth(_q->agc_rx,  1e-2f);
    agc_crcf_set_gain_limits(_q->agc_rx, 1.0f, 1e7f);

    if (_q->debug_x == NULL)
        _q->debug_x = windowcf_create(DEBUG_WLANFRAMESYNC_BUFFER_LEN);

    if (_q->debug_rssi == NULL)
        _q->debug_rssi = windowf_create(DEBUG_WLANFRAMESYNC_BUFFER_LEN);

    if (_q->debug_framesyms == NULL)
        _q->debug_framesyms = windowcf_create(DEBUG_WLANFRAMESYNC_BUFFER_LEN);

    _q->debug_enabled = 1;
#else
    fprintf(stderr,"wlanframesync_debug_enable(): compile-time debugging disabled\n");
#endif
}
Beispiel #5
0
// 
// Test RSSI on sinusoidal input
//
void autotest_agc_crcf_rssi_sinusoid()
{
    // set paramaters
    float gamma = 0.3f;         // nominal signal level
    float bt    = 0.05f;        // agc bandwidth
    float tol   = 0.001f;       // error tolerance

    // signal properties
    float dphi = 0.1f;          // signal frequency

    // 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<512; i++) {
        // generate sample (complex sinusoid)
        x = gamma * cexpf(_Complex_I*dphi*i);

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

    // get received signal strength indication
    float rssi = agc_crcf_get_signal_level(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);
}
Beispiel #6
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);
}
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;
}
ofdmoqamframe64sync ofdmoqamframe64sync_create(unsigned int _m,
                                               float _beta,
                                               ofdmoqamframe64sync_callback _callback,
                                               void * _userdata)
{
    ofdmoqamframe64sync q = (ofdmoqamframe64sync) malloc(sizeof(struct ofdmoqamframe64sync_s));
    q->num_subcarriers = 64;

    // validate input
    if (_m < 1) {
        fprintf(stderr,"error: ofdmoqamframe64sync_create(), filter delay must be > 0\n");
        exit(1);
    } else if (_beta < 0.0f) {
        fprintf(stderr,"error: ofdmoqamframe64sync_create(), filter excess bandwidth must be > 0\n");
        exit(1);
    }
    q->m = _m;
    q->beta = _beta;

    // synchronizer parameters
    q->rxx_thresh = 0.60f;  // auto-correlation threshold
    q->rxy_thresh = 0.60f;  // cross-correlation threshold

    q->zeta = 64.0f/sqrtf(52.0f);   // scaling factor
    
    // create analysis filter banks
    q->ca0 = firpfbch_create(q->num_subcarriers, q->m, q->beta, 0.0f /*dt*/,FIRPFBCH_ROOTNYQUIST,0/*gradient*/);
    q->ca1 = firpfbch_create(q->num_subcarriers, q->m, q->beta, 0.0f /*dt*/,FIRPFBCH_ROOTNYQUIST,0/*gradient*/);
    q->X0 = (float complex*) malloc((q->num_subcarriers)*sizeof(float complex));
    q->X1 = (float complex*) malloc((q->num_subcarriers)*sizeof(float complex));
    q->Y0 = (float complex*) malloc((q->num_subcarriers)*sizeof(float complex));
    q->Y1 = (float complex*) malloc((q->num_subcarriers)*sizeof(float complex));
 
    // allocate memory for PLCP arrays
    q->S0 = (float complex*) malloc((q->num_subcarriers)*sizeof(float complex));
    q->S1 = (float complex*) malloc((q->num_subcarriers)*sizeof(float complex));
    q->S2 = (float complex*) malloc((q->num_subcarriers)*sizeof(float complex));
    ofdmoqamframe64_init_S0(q->S0);
    ofdmoqamframe64_init_S1(q->S1);
    ofdmoqamframe64_init_S2(q->S2);
    unsigned int i;
    for (i=0; i<q->num_subcarriers; i++) {
        q->S0[i] *= q->zeta;
        q->S1[i] *= q->zeta;
        q->S2[i] *= q->zeta;
    }
    q->S1a = (float complex*) malloc((q->num_subcarriers)*sizeof(float complex));
    q->S1b = (float complex*) malloc((q->num_subcarriers)*sizeof(float complex));

    // set pilot sequence
    q->ms_pilot = msequence_create_default(8);
    q->x_phase[0] = -21.0f;
    q->x_phase[1] =  -7.0f;
    q->x_phase[2] =   7.0f;
    q->x_phase[3] =  21.0f;

    // create NCO for pilots
    q->nco_pilot = nco_crcf_create(LIQUID_VCO);
    q->pll_pilot = pll_create();
    pll_set_bandwidth(q->pll_pilot,0.01f);
    pll_set_damping_factor(q->pll_pilot,4.0f);

    // create agc | signal detection object
    q->sigdet = agc_crcf_create();
    agc_crcf_set_bandwidth(q->sigdet,0.1f);

    // create NCO for CFO compensation
    q->nco_rx = nco_crcf_create(LIQUID_VCO);

    // create auto-correlator objects
    q->autocorr_length = OFDMOQAMFRAME64SYNC_AUTOCORR_LEN;
    q->autocorr_delay = q->num_subcarriers / 4;
    q->autocorr = autocorr_cccf_create(q->autocorr_length, q->autocorr_delay);

    // create cross-correlator object
    q->hxy = (float complex*) malloc((q->num_subcarriers)*sizeof(float complex));
    ofdmoqam cs = ofdmoqam_create(q->num_subcarriers,q->m,q->beta,
                                  0.0f,   // dt
                                  OFDMOQAM_SYNTHESIZER,
                                  0);     // gradient
    for (i=0; i<2*(q->m); i++)
        ofdmoqam_execute(cs,q->S1,q->hxy);
    // time reverse, complex conjugate (same as fftshift for
    // this particular sequence)
    memmove(q->X0, q->hxy, 64*sizeof(float complex));
    for (i=0; i<64; i++)
        q->hxy[i] = conjf(q->X0[64-i-1]);
    // fftshift
    //fft_shift(q->hxy,64);
    q->crosscorr = firfilt_cccf_create(q->hxy, q->num_subcarriers);
    ofdmoqam_destroy(cs);

    // input buffer
    q->input_buffer = windowcf_create((q->num_subcarriers));

    // gain
    q->g = 1.0f;
    q->G0 = (float complex*) malloc((q->num_subcarriers)*sizeof(float complex));
    q->G1 = (float complex*) malloc((q->num_subcarriers)*sizeof(float complex));
    q->G  = (float complex*) malloc((q->num_subcarriers)*sizeof(float complex));

    q->data = (float complex*) malloc((q->num_subcarriers)*sizeof(float complex));

    // reset object
    ofdmoqamframe64sync_reset(q);

#if DEBUG_OFDMOQAMFRAME64SYNC
    q->debug_x =        windowcf_create(DEBUG_OFDMOQAMFRAME64SYNC_BUFFER_LEN);
    q->debug_rxx=       windowcf_create(DEBUG_OFDMOQAMFRAME64SYNC_BUFFER_LEN);
    q->debug_rxy=       windowcf_create(DEBUG_OFDMOQAMFRAME64SYNC_BUFFER_LEN);
    q->debug_framesyms= windowcf_create(DEBUG_OFDMOQAMFRAME64SYNC_BUFFER_LEN);
    q->debug_pilotphase= windowf_create(DEBUG_OFDMOQAMFRAME64SYNC_BUFFER_LEN);
    q->debug_pilotphase_hat= windowf_create(DEBUG_OFDMOQAMFRAME64SYNC_BUFFER_LEN);
    q->debug_rssi=       windowf_create(DEBUG_OFDMOQAMFRAME64SYNC_BUFFER_LEN);
#endif

    q->callback = _callback;
    q->userdata = _userdata;

    return q;
}