Example #1
0
// 
// AUTOTEST: count number of ones in an integer
//
void autotest_count_ones() {
    CONTEND_EQUALITY( liquid_count_ones(0x0000), 0 );
    CONTEND_EQUALITY( liquid_count_ones(0x0001), 1 );
    CONTEND_EQUALITY( liquid_count_ones(0x0003), 2 );
    CONTEND_EQUALITY( liquid_count_ones(0xFFFF), 16 );
    CONTEND_EQUALITY( liquid_count_ones(0x00FF), 8 );
    CONTEND_EQUALITY( liquid_count_ones(0x5555), 8 );
    CONTEND_EQUALITY( liquid_count_ones(0x0007), 3 );
    CONTEND_EQUALITY( liquid_count_ones(0x0037), 5 );
    CONTEND_EQUALITY( liquid_count_ones(0x0137), 6 );
    CONTEND_EQUALITY( liquid_count_ones(0xf137), 10 );
}
Example #2
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;
}
Example #3
0
int main(int argc, char*argv[])
{
    unsigned int i;
    
    // error vector [22 x 1]
    unsigned char err[3] = {0x00, 0x0000, 0x0001};

    // original message [16 x 1]
    unsigned char m[2] = {0x0000, 0x0001};
    m[0] = rand() & 0xffff;
    m[1] = rand() & 0xffff;

    // derived values
    unsigned char v[3];     // encoded/transmitted message
    unsigned char e[3];     // error vector
    unsigned char r[3];     // received vector
    unsigned char s;        // syndrome vector
    unsigned char e_hat[3] = {0,0,0};  // estimated error vector
    unsigned char v_hat[3]; // estimated transmitted message
    unsigned char m_hat[2]; // estimated original message

#if 0
    // print P matrix
    printf("P : \n");
    print_bitstring(&P[ 0],16);
    print_bitstring(&P[ 2],16);
    print_bitstring(&P[ 4],16);
    print_bitstring(&P[ 6],16);
    print_bitstring(&P[ 8],16);
    print_bitstring(&P[10],16);
#endif

    // original message
    printf("m (original message):   ");
    print_bitstring(m,16);

    // compute encoded/transmitted message: v = m*G
    v[0] = 0;
    for (i=0; i<6; i++) {
        v[0] <<= 1;

        unsigned int p = liquid_c_ones[P[2*i+0] & m[0]] +
                         liquid_c_ones[P[2*i+1] & m[1]];
        printf("p = %u\n", p);
        v[0] |= p & 0x01;
    }
    v[1] = m[0];
    v[2] = m[1];
    printf("v (encoded message):    ");
    print_bitstring(v,22);

    // use pre-determined error vector
    e[0] = err[0];
    e[1] = err[1];
    e[2] = err[2];
    printf("e (error vector):       ");
    print_bitstring(e,22);

    // compute received vector: r = v + e
    r[0] = v[0] ^ e[0];
    r[1] = v[1] ^ e[1];
    r[2] = v[2] ^ e[2];
    printf("r (received vector):    ");
    print_bitstring(r,22);

    // compute syndrome vector, s = r*H^T = ( H*r^T )^T
    s = 0;
    for (i=0; i<6; i++) {
        s <<= 1;

        unsigned int p =
            ( (r[0] & (1<<(6-i-1))) ? 1 : 0 )+
            liquid_count_ones(P[2*i+0] & r[1]) +
            liquid_count_ones(P[2*i+1] & r[2]);
        //printf("p = %u\n", p);

        s |= p & 0x01;
    }
    printf("s (syndrome vector):    ");
    print_bitstring(&s,6);

    // compute weight of s
    unsigned int ws = liquid_count_ones(s);
    printf("weight(s) = %u\n", ws);

    if (ws == 0) {
        printf("no errors detected\n");
    } else {
        // estimate error location
        unsigned char e_test[3]  = {0x00, 0x0000, 0x0001};
        int syndrome_match = 0;

        // TODO : these can be pre-computed
        unsigned int n;
        for (n=0; n<22; n++) {
            // compute syndrome
            unsigned int s_test = 0;

            for (i=0; i<6; i++) {
                s_test <<= 1;
                unsigned int p =
                    ( (e_test[0] & (1<<(6-i-1))) ? 1 : 0 )+
                    liquid_count_ones(P[2*i+0] & e_test[1]) +
                    liquid_count_ones(P[2*i+1] & e_test[2]);

                s_test |= p & 0x01;
            }

#if 1
            // print results
            //printf("e_test:"); print_bitstring(e_test, 72);
            printf("%3u : e = ", n);
            print_bitstring_short(e_test[0],6); printf(" ");
            print_bitstring_short(e_test[1],8); printf(" ");
            print_bitstring_short(e_test[2],8); printf(" ");
            printf(", s = ");
            print_bitstring_short(s_test,6);
            if (s == s_test) printf(" *");
            printf("\n");
#else
            // print output array (secded2216_syndrome_w1[])
            printf("0x%.2x\n", s_test);
#endif

            if (s == s_test) {
                memmove(e_hat, e_test, sizeof(e_test));
                syndrome_match = 1;
            }

            // shift e_test
            e_test[0] = (e_test[0] << 1) | ((e_test[1] & 0x80) ? 1 : 0);
            e_test[1] = (e_test[1] << 1) | ((e_test[2] & 0x80) ? 1 : 0);
            e_test[2] <<= 1;

        }

        if (syndrome_match) {
            printf("syndrome match!\n");
        } else {
            printf("no syndrome match; expected multiple errors\n");
        }
    }

    // compute estimated transmitted message: v_hat = r + e_hat
    printf("e-hat (estimated error):");
    print_bitstring(e_hat,22);

    printf("v-hat (estimated tx):   ");
    v_hat[0] = r[0] ^ e_hat[0];
    v_hat[1] = r[1] ^ e_hat[1];
    v_hat[2] = r[2] ^ e_hat[2];
    print_bitstring(v_hat,22);

    // compute estimated original message: (last 16 bits of encoded message)
    m_hat[0] = v_hat[1];
    m_hat[1] = v_hat[2];
    printf("m-hat (estimated orig.):");
    print_bitstring(m_hat,16);

    // compute errors between v, v_hat
    unsigned int num_errors_encoded = count_bit_errors(v[0], v_hat[0]) +
                                      count_bit_errors(v[1], v_hat[1]) +
                                      count_bit_errors(v[2], v_hat[2]);
    printf("decoding errors (encoded)  : %2u / 22\n", num_errors_encoded);

    // compute errors between m, m_hat
    unsigned int num_errors_decoded = count_bit_errors(m[0], m_hat[0]) +
                                      count_bit_errors(m[1], m_hat[1]);
    printf("decoding errors (original) : %2u / 16\n", num_errors_decoded);

    return 0;
}
int main(int argc, char*argv[])
{
    unsigned int i;
    
    // error vector [72 x 1]
    unsigned char e[9] = {0,0,0,0,0,0,0,0,2};

    // original message [64 x 1]
    unsigned char m[8] = {0,0,0,0,0,0,0,1};

    // derived values
    unsigned char v[9];     // encoded/transmitted message
    unsigned char r[9];     // received vector
    unsigned char s;        // syndrome vector
    unsigned char v_hat[9]; // estimated transmitted message
    unsigned char m_hat[8]; // estimated original message

    // original message
    printf("m (original message):\n         ");
    print_bitstring(m,64);

    // compute encoded/transmitted message: v = m*G
    v[0] = 0;
    for (i=0; i<8; i++) {
        v[0] <<= 1;

        unsigned int p = liquid_c_ones[ P[8*i+0] & m[0] ] +
                         liquid_c_ones[ P[8*i+1] & m[1] ] +
                         liquid_c_ones[ P[8*i+2] & m[2] ] +
                         liquid_c_ones[ P[8*i+3] & m[3] ] +
                         liquid_c_ones[ P[8*i+4] & m[4] ] +
                         liquid_c_ones[ P[8*i+5] & m[5] ] +
                         liquid_c_ones[ P[8*i+6] & m[6] ] +
                         liquid_c_ones[ P[8*i+7] & m[7] ];
        //printf("p = %u\n", p);
        v[0] |= p & 0x01;
    }
    for (i=0; i<8; i++)
        v[i+1] = m[i];
    printf("v (encoded/transmitted message):\n");
    print_bitstring(v,72);

    // use pre-determined error vector
    printf("e (error vector):\n");
    print_bitstring(e,72);

    // compute received vector: r = v + e
    for (i=0; i<9; i++)
        r[i] = v[i] ^ e[i];
    printf("r (received vector):\n");
    print_bitstring(r,72);

    // compute syndrome vector, s = r*H^T = ( H*r^T )^T
    s = 0;
    for (i=0; i<8; i++) {
        s <<= 1;
        unsigned int p =
            ( (r[0] & (1<<(8-i-1))) ? 1 : 0 )+
            liquid_c_ones[ P[8*i+0] & r[1] ] +
            liquid_c_ones[ P[8*i+1] & r[2] ] +
            liquid_c_ones[ P[8*i+2] & r[3] ] +
            liquid_c_ones[ P[8*i+3] & r[4] ] +
            liquid_c_ones[ P[8*i+4] & r[5] ] +
            liquid_c_ones[ P[8*i+5] & r[6] ] +
            liquid_c_ones[ P[8*i+6] & r[7] ] +
            liquid_c_ones[ P[8*i+7] & r[8] ];

        printf("p = %u\n", p);

        s |= p & 0x01;
    }
    printf("s (syndrome vector):\n");
    print_bitstring(&s,8);

    // compute weight of s
    unsigned int ws = liquid_count_ones(s);
    printf("w(s) = %u\n", ws);

    // estimated error vector
    unsigned char e_hat[9] = {0,0,0,0,0,0,0,0,0}; 

    if (ws == 0) {
        printf("no errors detected\n");
    } else {
        // estimate error location
        int syndrome_match = 0;

        // TODO : these can be pre-computed
        unsigned int n;
        for (n=0; n<72; n++) {
            // compute syndrome
            unsigned char e_test[9]  = {0,0,0,0,0,0,0,0,0};
            unsigned char s_hat = 0;

            div_t d = div(n,8);
            e_test[9-d.quot-1] = 1 << d.rem;

            for (i=0; i<8; i++) {
                s_hat <<= 1;
                unsigned int p =
                    ( (e_test[0] & (1<<(8-i-1))) ? 1 : 0 )+
                    liquid_c_ones[ P[8*i+0] & e_test[1] ] +
                    liquid_c_ones[ P[8*i+1] & e_test[2] ] +
                    liquid_c_ones[ P[8*i+2] & e_test[3] ] +
                    liquid_c_ones[ P[8*i+3] & e_test[4] ] +
                    liquid_c_ones[ P[8*i+4] & e_test[5] ] +
                    liquid_c_ones[ P[8*i+5] & e_test[6] ] +
                    liquid_c_ones[ P[8*i+6] & e_test[7] ] +
                    liquid_c_ones[ P[8*i+7] & e_test[8] ];

                s_hat |= p & 0x01;
            }

            // print results
            //printf("e_test:"); print_bitstring(e_test, 72);
            printf("%2u e=", n);
            for (i=0; i<9; i++) {
                print_bitstring_short(e_test[i],8);
                printf(" ");
            }
            printf("s=");
            print_bitstring_short(s_hat,8);
            if (s == s_hat) printf("*");
            printf("\n");

            if (s == s_hat) {
                memmove(e_hat, e_test, 9*sizeof(unsigned char));
                syndrome_match = 1;
            }
        }

        if (syndrome_match) {
            printf("syndrome match!\n");
        } else {
            printf("no syndrome match; expected multiple errors\n");
        }
    }

    // compute estimated transmitted message: v_hat = r + e_hat
    printf("e-hat (estimated error vector):\n");
    print_bitstring(e_hat,72);

    printf("v-hat (estimated transmitted vector):\n");
    for (i=0; i<9; i++)
        v_hat[i] = r[i] ^ e_hat[i];
    print_bitstring(v_hat,72);
    //print_bitstring(v,    72);

    // compute errors between v, v_hat
    unsigned int num_errors_encoded = count_bit_errors_array(v, v_hat, 9);
    printf("decoding errors (encoded)  : %2u / 72\n", num_errors_encoded);

    // compute estimated original message: (last 64 bits of encoded message)
    for (i=0; i<9; i++)
        m_hat[i] = v_hat[i+1];
    printf("m-hat (estimated original vector):\n         ");
    print_bitstring(m_hat,64);
    //print_bitstring(m,    64);

    // compute errors between m, m_hat
    unsigned int num_errors_decoded = count_bit_errors_array(m, m_hat, 8);
    printf("decoding errors (original) : %2u / 64\n", num_errors_decoded);

    return 0;
}