// // 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 ); }
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; }
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; }