// generate short sequence symbols // _p : subcarrier allocation array // _M : total number of subcarriers // _S0 : output symbol (freq) // _s0 : output symbol (time) // _M_S0 : total number of enabled subcarriers in S0 void ofdmframe_init_S0(unsigned char * _p, unsigned int _M, float complex * _S0, float complex * _s0, unsigned int * _M_S0) { unsigned int i; // compute m-sequence length unsigned int m = liquid_nextpow2(_M); if (m < 4) m = 4; else if (m > 8) m = 8; // generate m-sequence generator object msequence ms = msequence_create_default(m); unsigned int s; unsigned int M_S0 = 0; // short sequence for (i=0; i<_M; i++) { // generate symbol //s = msequence_generate_symbol(ms,1); s = msequence_generate_symbol(ms,3) & 0x01; if (_p[i] == OFDMFRAME_SCTYPE_NULL) { // NULL subcarrier _S0[i] = 0.0f; } else { if ( (i%2) == 0 ) { // even subcarrer _S0[i] = s ? 1.0f : -1.0f; M_S0++; } else { // odd subcarrer (ignore) _S0[i] = 0.0f; } } } // destroy objects msequence_destroy(ms); // ensure at least one subcarrier was enabled if (M_S0 == 0) { fprintf(stderr,"error: ofdmframe_init_S0(), no subcarriers enabled; check allocation\n"); exit(1); } // set return value(s) *_M_S0 = M_S0; // run inverse fft to get time-domain sequence fft_run(_M, _S0, _s0, FFT_REVERSE, 0); // normalize time-domain sequence level float g = 1.0f / sqrtf(M_S0); for (i=0; i<_M; i++) _s0[i] *= g; }
// // 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); } } }
// generate long sequence symbols // _p : subcarrier allocation array // _M : total number of subcarriers // _S1 : output symbol (freq) // _s1 : output symbol (time) // _M_S1 : total number of enabled subcarriers in S1 void ofdmframe_init_S1(unsigned char * _p, unsigned int _M, float complex * _S1, float complex * _s1, unsigned int * _M_S1) { unsigned int i; // compute m-sequence length unsigned int m = liquid_nextpow2(_M); if (m < 4) m = 4; else if (m > 8) m = 8; // increase m such that the resulting S1 sequence will // differ significantly from S0 with the same subcarrier // allocation array m++; // generate m-sequence generator object msequence ms = msequence_create_default(m); unsigned int s; unsigned int M_S1 = 0; // long sequence for (i=0; i<_M; i++) { // generate symbol //s = msequence_generate_symbol(ms,1); s = msequence_generate_symbol(ms,3) & 0x01; if (_p[i] == OFDMFRAME_SCTYPE_NULL) { // NULL subcarrier _S1[i] = 0.0f; } else { _S1[i] = s ? 1.0f : -1.0f; M_S1++; } } // destroy objects msequence_destroy(ms); // ensure at least one subcarrier was enabled if (M_S1 == 0) { fprintf(stderr,"error: ofdmframe_init_S1(), no subcarriers enabled; check allocation\n"); exit(1); } // set return value(s) *_M_S1 = M_S1; // run inverse fft to get time-domain sequence fft_run(_M, _S1, _s1, FFT_REVERSE, 0); // normalize time-domain sequence level float g = 1.0f / sqrtf(M_S1); for (i=0; i<_M; i++) _s1[i] *= g; }
// generate long sequence symbols // _p : subcarrier allocation array // _num_subcarriers : total number of subcarriers // _S1 : output symbol // _M_S1 : total number of enabled subcarriers in S1 void ofdmoqamframe_init_S1(unsigned char * _p, unsigned int _num_subcarriers, float complex * _S1, unsigned int * _M_S1) { unsigned int i; // compute m-sequence length unsigned int m = liquid_nextpow2(_num_subcarriers); if (m < 4) m = 4; else if (m > 8) m = 8; // increase m such that the resulting S1 sequence will // differ significantly from S0 with the same subcarrier // allocation array m++; // generate m-sequence generator object msequence ms = msequence_create_default(m); unsigned int s; unsigned int M_S1 = 0; // long sequence for (i=0; i<_num_subcarriers; i++) { // generate symbol //s = msequence_generate_symbol(ms,1); s = msequence_generate_symbol(ms,3) & 0x01; if (_p[i] == OFDMOQAMFRAME_SCTYPE_NULL) { // NULL subcarrier _S1[i] = 0.0f; } else { _S1[i] = s ? 1.0f : -1.0f; M_S1++; // rotate by pi/2 on odd subcarriers _S1[i] *= (i%2)==0 ? 1.0f : _Complex_I; } } // destroy objects msequence_destroy(ms); // ensure at least one subcarrier was enabled if (M_S1 == 0) { fprintf(stderr,"error: ofdmoqamframe_init_S1(), no subcarriers enabled; check allocation\n"); exit(1); } // set return value(s) *_M_S1 = M_S1; }
// generate short sequence symbols // _p : subcarrier allocation array // _num_subcarriers : total number of subcarriers // _S0 : output symbol // _M_S0 : total number of enabled subcarriers in S0 void ofdmoqamframe_init_S0(unsigned char * _p, unsigned int _num_subcarriers, float complex * _S0, unsigned int * _M_S0) { unsigned int i; // compute m-sequence length unsigned int m = liquid_nextpow2(_num_subcarriers); if (m < 4) m = 4; else if (m > 8) m = 8; // generate m-sequence generator object msequence ms = msequence_create_default(m); unsigned int s; unsigned int M_S0 = 0; // short sequence for (i=0; i<_num_subcarriers; i++) { // generate symbol //s = msequence_generate_symbol(ms,1); s = msequence_generate_symbol(ms,3) & 0x01; if (_p[i] == OFDMOQAMFRAME_SCTYPE_NULL) { // NULL subcarrier _S0[i] = 0.0f; } else { if ( (i%2) == 0 ) { // even subcarrer _S0[i] = s ? 1.0f : -1.0f; M_S0++; } else { // odd subcarrer (ignore) _S0[i] = 0.0f; } } } // destroy objects msequence_destroy(ms); // ensure at least one subcarrier was enabled if (M_S0 == 0) { fprintf(stderr,"error: ofdmoqamframe_init_S0(), no subcarriers enabled; check allocation\n"); exit(1); } // set return value(s) *_M_S0 = M_S0; }
// Helper function to keep code base small void symsync_crcf_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _k, unsigned int _m) { unsigned long int i; unsigned int npfb = 16; // number of filters in bank unsigned int k = _k; // samples/symbol unsigned int m = _m; // filter delay [symbols] float beta = 0.3f; // filter excess bandwidth factor // create symbol synchronizer symsync_crcf q = symsync_crcf_create_rnyquist(LIQUID_RNYQUIST_RRC, k, m, beta, npfb); // unsigned int num_samples = 64; *_num_iterations /= num_samples; unsigned int num_written; float complex x[num_samples]; float complex y[num_samples]; // generate pseudo-random data msequence ms = msequence_create_default(6); for (i=0; i<num_samples; i++) x[i] = ((float)msequence_generate_symbol(ms, 6) - 31.5) / 24.0f; msequence_destroy(ms); // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { symsync_crcf_execute(q, x, num_samples, y, &num_written); symsync_crcf_execute(q, x, num_samples, y, &num_written); symsync_crcf_execute(q, x, num_samples, y, &num_written); symsync_crcf_execute(q, x, num_samples, y, &num_written); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4 * num_samples; symsync_crcf_destroy(q); }