コード例 #1
0
ファイル: crc_autotest.c プロジェクト: Clivia/liquid-dsp
// 
// autotest helper function
//
void validate_crc(crc_scheme _check,
                  unsigned int _n)
{
    unsigned int i;

    // generate pseudo-random data
    unsigned char data[_n];
    msequence ms = msequence_create_default(9);
    for (i=0; i<_n; i++)
        data[i] = msequence_generate_symbol(ms,8);
    msequence_destroy(ms);

    // generate key
    unsigned int key = crc_generate_key(_check, data, _n);

    // contend data/key are valid
    CONTEND_EXPRESSION(crc_validate_message(_check, data, _n, key));

    //
    unsigned char data_corrupt[_n];
    unsigned int j;
    for (i=0; i<_n; i++) {
        for (j=0; j<8; j++) {
            // copy original data sequence
            memmove(data_corrupt, data, _n*sizeof(unsigned char));

            // flip bit j at byte i
            data[i] ^= (1 << j);

            // contend data/key are invalid
            CONTEND_EXPRESSION(crc_validate_message(_check, data, _n, key)==0);
        }
    }
}
コード例 #2
0
// helper function to keep code base small
void liquid_scramble_test(unsigned int _n)
{
    unsigned char x[_n];    // input data
    unsigned char y[_n];    // scrambled data
    unsigned char z[_n];    // unscrambled data

    unsigned int i;

    // initialize data array
    for (i=0; i<_n; i++)
        x[i] = 0x00;

    // scramble input
    memmove(y,x,_n);
    scramble_data(y,_n);

    // unscramble result
    memmove(z,y,_n);
    unscramble_data(z,_n);

    // ensure data are equivalent
    CONTEND_SAME_DATA(x,z,_n*sizeof(unsigned char));

    // compute entropy metric
    float H = liquid_scramble_test_entropy(y,_n);
    CONTEND_EXPRESSION( H > 0.8f );
}
コード例 #3
0
// Helper function to keep code base small
void modem_test_demodstats(modulation_scheme _ms)
{
    // generate mod/demod
    modem mod   = modem_create(_ms);
    modem demod = modem_create(_ms);

    // run the test
    unsigned int i, s, M = 1 << modem_get_bps(mod);
    float complex x;
    float complex x_hat;    // rotated symbol
    float demodstats;
    float phi = 0.01f;

    for (i=0; i<M; i++) {
        // reset modem objects
        modem_reset(mod);
        modem_reset(demod);

        // modulate symbol
        modem_modulate(mod, i, &x);

        // ignore rare condition where modulated symbol is (0,0)
        // (e.g. APSK-8)
        if (cabsf(x) < 1e-3f) continue;

        // add phase offsets
        x_hat = x * cexpf( phi*_Complex_I);

        // demod positive phase signal, and ensure demodulator
        // maps to appropriate symbol
        modem_demodulate(demod, x_hat, &s);
        if (s != i)
            AUTOTEST_WARN("modem_test_demodstats(), output symbol does not match");

        demodstats = modem_get_demodulator_phase_error(demod);
        CONTEND_EXPRESSION(demodstats > 0.0f);
    }

    // repeat with negative phase error
    for (i=0; i<M; i++) {
        // reset modem objects
        modem_reset(mod);
        modem_reset(demod);

        // modulate symbol
        modem_modulate(mod, i, &x);

        // ignore rare condition where modulated symbol is (0,0)
        // (e.g. APSK-8)
        if (cabsf(x) < 1e-3f) continue;

        // add phase offsets
        x_hat = x * cexpf(-phi*_Complex_I);

        // demod positive phase signal, and ensure demodulator
        // maps to appropriate symbol
        modem_demodulate(demod, x_hat, &s);
        if (s != i)
            AUTOTEST_WARN("modem_test_demodstats(), output symbol does not match");

        demodstats = modem_get_demodulator_phase_error(demod);
        CONTEND_EXPRESSION(demodstats < 0.0f);
    }

    // clean up allocated objects up
    modem_destroy(mod);
    modem_destroy(demod);
}
コード例 #4
0
ファイル: cbuffer_autotest.c プロジェクト: Clivia/liquid-dsp
// floating point
void autotest_cbufferf()
{
    // input array of values
    float v[] = {1, 2, 3, 4, 5, 6, 7, 8};

    // output test arrays
    float test1[] = {1, 2, 3, 4};
    float test2[] = {3, 4, 1, 2, 3, 4, 5, 6, 7, 8};
    float test3[] = {3, 4, 5, 6, 7, 8};
    float test4[] = {3, 4, 5, 6, 7, 8, 1, 2, 3};
    float *r;                   // output read pointer
    unsigned int num_requested; // number of samples requested
    unsigned int num_read;      // number of samples read

    // create new circular buffer with 10 elements
    cbufferf q = cbufferf_create(10);
    // cbuffer: { <empty> }

    // part 1: write 4 elements to the buffer
    cbufferf_write(q, v, 4);
    // cbuffer: {1 2 3 4}

    // part 2: try to read 4 elements
    num_requested = 4;
    cbufferf_read(q, num_requested, &r, &num_read);
    CONTEND_EQUALITY(num_read,4);
    CONTEND_SAME_DATA(r,test1,4*sizeof(float));

    // part 3: release two elements, write 8 more, read 10
    cbufferf_release(q, 2);
    // cbuffer: {3 4}
    cbufferf_write(q, v, 8);
    // cbuffer: {3 4 1 2 3 4 5 6 7 8}
    num_requested = 10;
    cbufferf_read(q, num_requested, &r, &num_read);
    CONTEND_EQUALITY(num_read,10);
    CONTEND_SAME_DATA(r,test2,10*sizeof(float));

    // part 4: pop single element from buffer
    CONTEND_EQUALITY( cbufferf_size(q), 10    );
    cbufferf_pop(q, r);
    // cbuffer: {4 1 2 3 4 5 6 7 8}
    CONTEND_EQUALITY( cbufferf_size(q),  9    );
    CONTEND_EQUALITY( *r,                3.0f );

    // part 5: release three elements, and try reading 10
    cbufferf_release(q, 3);
    // cbuffer: {3 4 5 6 7 8}
    num_requested = 10;
    cbufferf_read(q, num_requested, &r, &num_read);
    CONTEND_EQUALITY(num_read,6);
    CONTEND_SAME_DATA(r,test3,6*sizeof(float));

    // part 6: test pushing multiple elements
    cbufferf_push(q, 1);
    cbufferf_push(q, 2);
    cbufferf_push(q, 3);
    // cbuffer: {3 4 5 6 7 8 1 2 3}
    num_requested = 10;
    cbufferf_read(q, num_requested, &r, &num_read);
    CONTEND_EQUALITY(num_read,9);
    CONTEND_SAME_DATA(r,test4,9*sizeof(float));

    // part 7: add one more element; buffer should be full
    CONTEND_EXPRESSION( cbufferf_is_full(q)==0 );
    cbufferf_push(q, 1);
    // cbuffer: {3 4 5 6 7 8 1 2 3 1}
    CONTEND_EXPRESSION( cbufferf_is_full(q)==1 );

    // memory leaks are evil
    cbufferf_destroy(q);
}
コード例 #5
0
ファイル: cbuffer_autotest.c プロジェクト: Clivia/liquid-dsp
// test general flow
void autotest_cbufferf_flow()
{
    // options
    unsigned int max_size     =   48; // maximum number of elements in buffer
    unsigned int max_read     =   17; // maximum number of elements to read
    unsigned int num_elements = 1200; // total number of elements for run

    // flag to indicate if test was successful
    int success = 1;

    // temporary buffer to write samples before sending to cbuffer
    float write_buffer[max_size];

    // create new circular buffer
    cbufferf q = cbufferf_create_max(max_size, max_read);

    //
    unsigned i;
    unsigned write_id = 0;  // running total number of values written
    unsigned read_id  = 0;  // running total number of values read

    // continue running until
    while (1) {
        // write some values
        unsigned int num_available_to_write = cbufferf_space_available(q);

        // write samples if space is available
        if (num_available_to_write > 0) {
            // number of elements to write
            unsigned int num_to_write = (rand() % num_available_to_write) + 1;

            // generate samples to write
            for (i=0; i<num_to_write; i++) {
                write_buffer[i] = (float)(write_id);
                write_id++;
            }

            // write samples
            cbufferf_write(q, write_buffer, num_to_write);
        }

        // read some values
        unsigned int num_available_to_read = cbufferf_size(q);
        
        // read samples if available
        if (num_available_to_read > 0) {
            // number of elements to read
            unsigned int num_to_read = rand() % num_available_to_read;

            // read samples
            float *r;               // output read pointer
            unsigned int num_read;  // number of samples read
            cbufferf_read(q, num_to_read, &r, &num_read);

            // compare results
            for (i=0; i<num_read; i++) {
                if (liquid_autotest_verbose)
                    printf(" %s read %12.0f, expected %12u\n", r[i] == (float)read_id ? " " : "*", r[i], read_id);

                if (r[i] != (float)read_id)
                    success = 0;
                read_id++;
            }

            // release all the samples that were read
            cbufferf_release(q, num_read);
        }

        // stop on fail or upon completion
        if (!success || read_id >= num_elements)
            break;
    }
    
    // ensure test was successful
    CONTEND_EXPRESSION(success == 1);

    // destroy object
    cbufferf_destroy(q);
}
コード例 #6
0
ファイル: detector_autotest.c プロジェクト: Clivia/liquid-dsp
// autotest helper function
//  _n      :   sequence length
//  _dt     :   fractional sample offset
//  _dphi   :   carrier frequency offset
void detector_cccf_runtest(unsigned int _n,
                           float        _dt,
                           float        _dphi)
{
    // TODO: validate input

    unsigned int i;

    // fixed values
    float noise_floor = -80.0f;     // noise floor [dB]
    float SNRdB       =  30.0f;     // signal-to-noise ratio [dB]
    unsigned int m    =  11;        // resampling filter semi-length
    float threshold   =  0.3f;      // detection threshold

    // derived values
    unsigned int num_samples = _n + 2*m + 1;
    float nstd = powf(10.0f, noise_floor/20.0f);
    float gamma = powf(10.0f, (SNRdB + noise_floor)/20.0f);
    float delay = (float)(_n + m) + _dt;    // expected delay

    // arrays
    float complex s[_n];            // synchronization pattern (samples)
    float complex x[num_samples];   // resampled signal with noise and offsets

    // generate synchronization pattern (two samples per symbol)
    unsigned int n2 = (_n - (_n%2)) / 2;    // n2 = floor(n/2)
    unsigned int mm = liquid_nextpow2(n2);  // mm = ceil( log2(n2) )
    msequence ms = msequence_create_default(mm);
    float complex v = 0.0f;
    for (i=0; i<_n; i++) {
        if ( (i%2)==0 )
            v = msequence_advance(ms) ? 1.0f : -1.0f;
        s[i] = v;
    }
    msequence_destroy(ms);

    // create fractional sample interpolator
    firfilt_crcf finterp = firfilt_crcf_create_kaiser(2*m+1, 0.45f, 40.0f, _dt);

    // generate sequence
    for (i=0; i<num_samples; i++) {
        // add fractional sample timing offset
        if (i < _n) firfilt_crcf_push(finterp, s[i]);
        else        firfilt_crcf_push(finterp, 0.0f);

        // compute output
        firfilt_crcf_execute(finterp, &x[i]);

        // add channel gain
        x[i] *= gamma;

        // add carrier offset
        x[i] *= cexpf(_Complex_I*_dphi*i);

        // add noise
        x[i] += nstd * ( randnf() + _Complex_I*randnf() ) * M_SQRT1_2;
    }
    
    // destroy fractional sample interpolator
    firfilt_crcf_destroy(finterp);

    // create detector
    detector_cccf sync = detector_cccf_create(s, _n, threshold, 2*_dphi);
    
    // push signal through detector
    float tau_hat   = 0.0f;     // fractional sample offset estimate
    float dphi_hat  = 0.0f;     // carrier offset estimate
    float gamma_hat = 1.0f;     // signal level estimate (linear)
    float delay_hat = 0.0f;     // total delay offset estimate
    int signal_detected = 0;    // signal detected flag
    for (i=0; i<num_samples; i++) {
        
        // correlate
        int detected = detector_cccf_correlate(sync, x[i], &tau_hat, &dphi_hat, &gamma_hat);

        if (detected) {
            signal_detected = 1;
            delay_hat = (float)i + (float)tau_hat;
            if (liquid_autotest_verbose) {
                printf("****** preamble found, tau_hat=%8.6f, dphi_hat=%8.6f, gamma_hat=%8.6f\n",
                        tau_hat, dphi_hat, gamma_hat);
            }
        }
    }
    
    // destroy objects
    detector_cccf_destroy(sync);

    // 
    // run tests
    //
    
    // convert to dB
    gamma     = 20*log10f(gamma);
    gamma_hat = 20*log10f(gamma_hat);

    if (liquid_autotest_verbose) {
        printf("detector autotest [%3u]: signal detected? %s\n", _n, signal_detected ? "yes" : "no");
        printf("    dphi    :   estimate = %12.6f (expected %12.6f)\n", dphi_hat,  _dphi);
        printf("    delay   :   estimate = %12.6f (expected %12.6f)\n", delay_hat, delay);
        printf("    gamma   :   estimate = %12.6f (expected %12.6f)\n", gamma_hat, gamma);
    }

    // ensure signal was detected
    CONTEND_EXPRESSION( signal_detected );

    // check carrier offset estimate
    CONTEND_DELTA( dphi_hat, _dphi, 0.01f );
    
    // check delay estimate
    CONTEND_DELTA( delay_hat, delay, 0.2f );
    
    // check signal level estimate
    CONTEND_DELTA( gamma_hat, gamma, 2.0f );
}