void ofdmflexframesync_destroy(ofdmflexframesync _q) { // destroy internal objects ofdmframesync_destroy(_q->fs); packetizer_destroy(_q->p_header); modem_destroy(_q->mod_header); packetizer_destroy(_q->p_payload); modem_destroy(_q->mod_payload); // free internal buffers/arrays free(_q->p); free(_q->payload_enc); free(_q->payload_dec); // free main object memory free(_q); }
void ofdmframesync_execute_S1(ofdmframesync _q) { _q->timer--; if (_q->timer > 0) return; // increment number of symbols observed _q->num_symbols++; // run fft float complex * rc; windowcf_read(_q->input_buffer, &rc); // estimate S1 gain // TODO : add backoff in gain estimation ofdmframesync_estimate_gain_S1(_q, &rc[_q->cp_len], _q->G); // compute detector output float complex g_hat = 0.0f; unsigned int i; for (i=0; i<_q->M; i++) { //g_hat += _q->G[(i+1+_q->M)%_q->M]*conjf(_q->G[(i+_q->M)%_q->M]); g_hat += _q->G[(i+1)%_q->M]*conjf(_q->G[i]); } g_hat /= _q->M_S1; // normalize output g_hat *= _q->g0; // rotate by complex phasor relative to timing backoff g_hat *= liquid_cexpjf((float)(_q->backoff)*2.0f*M_PI/(float)(_q->M)); #if DEBUG_OFDMFRAMESYNC_PRINT printf(" g_hat : %12.4f <%12.8f>\n", cabsf(g_hat), cargf(g_hat)); #endif // check conditions for g_hat: // 1. magnitude should be large (near unity) when aligned // 2. phase should be very near zero (time aligned) if (cabsf(g_hat) > _q->plcp_sync_thresh && fabsf(cargf(g_hat)) < 0.1f*M_PI ) { //printf(" acquisition\n"); _q->state = OFDMFRAMESYNC_STATE_RXSYMBOLS; // reset timer _q->timer = _q->M + _q->cp_len + _q->backoff; _q->num_symbols = 0; // normalize gain by subcarriers, apply timing backoff correction float g = (float)(_q->M) / sqrtf(_q->M_pilot + _q->M_data); for (i=0; i<_q->M; i++) { _q->G[i] *= g; // gain due to relative subcarrier allocation _q->G[i] *= _q->B[i]; // timing backoff correction } #if 0 // TODO : choose number of taps more appropriately //unsigned int ntaps = _q->M / 4; unsigned int ntaps = (_q->M < 8) ? 2 : 8; // FIXME : this is by far the most computationally complex part of synchronization ofdmframesync_estimate_eqgain(_q, ntaps); #else unsigned int poly_order = 4; if (poly_order >= _q->M_pilot + _q->M_data) poly_order = _q->M_pilot + _q->M_data - 1; ofdmframesync_estimate_eqgain_poly(_q, poly_order); #endif #if 1 // compute composite gain unsigned int i; for (i=0; i<_q->M; i++) _q->R[i] = _q->B[i] / _q->G[i]; #endif return; #if 0 printf("exiting prematurely\n"); ofdmframesync_destroy(_q); exit(1); #endif } // check if we are stuck searching for the S1 symbol if (_q->num_symbols == 16) { #if DEBUG_OFDMFRAMESYNC_PRINT printf("could not find S1 symbol. bailing...\n"); #endif ofdmframesync_reset(_q); } // 'reset' timer (wait another half symbol) _q->timer = _q->M2; }
// Helper function to keep code base small // _num_subcarriers : number of subcarriers // _cp_len : cyclic prefix lenght // _taper_len : taper length void ofdmframesync_acquire_test(unsigned int _num_subcarriers, unsigned int _cp_len, unsigned int _taper_len) { // options unsigned int M = _num_subcarriers; // number of subcarriers unsigned int cp_len = _cp_len; // cyclic prefix lenght unsigned int taper_len = _taper_len; // taper length float tol = 1e-2f; // error tolerance // float dphi = 1.0f / (float)M; // carrier frequency offset // subcarrier allocation (initialize to default) unsigned char p[M]; ofdmframe_init_default_sctype(M, p); // derived values unsigned int num_samples = (3 + 1)*(M + cp_len); // create synthesizer/analyzer objects ofdmframegen fg = ofdmframegen_create(M, cp_len, taper_len, p); //ofdmframegen_print(fg); float complex X[M]; // original data sequence float complex X_test[M]; // recovered data sequence ofdmframesync fs = ofdmframesync_create(M,cp_len,taper_len,p,ofdmframesync_autotest_callback,(void*)X_test); unsigned int i; float complex s0[M]; // short PLCP sequence float complex s1[M]; // long PLCP sequence float complex y[num_samples]; // frame samples // assemble full frame unsigned int n=0; // write first S0 symbol ofdmframegen_write_S0a(fg, &y[n]); n += M + cp_len; // write second S0 symbol ofdmframegen_write_S0b(fg, &y[n]); n += M + cp_len; // write S1 symbol ofdmframegen_write_S1( fg, &y[n]); n += M + cp_len; // generate data symbol (random) for (i=0; i<M; i++) { X[i] = cexpf(_Complex_I*2*M_PI*randf()); X_test[i] = 0.0f; } // write data symbol ofdmframegen_writesymbol(fg, X, &y[n]); n += M + cp_len; // validate frame length assert(n == num_samples); // add carrier offset for (i=0; i<num_samples; i++) y[i] *= cexpf(_Complex_I*dphi*i); // run receiver ofdmframesync_execute(fs,y,num_samples); // check output for (i=0; i<M; i++) { if (p[i] == OFDMFRAME_SCTYPE_DATA) { float e = crealf( (X[i] - X_test[i])*conjf(X[i] - X_test[i]) ); CONTEND_DELTA( cabsf(e), 0.0f, tol ); } } // destroy objects ofdmframegen_destroy(fg); ofdmframesync_destroy(fs); }
// Helper function to keep code base small void ofdmframesync_rxsymbol_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _num_subcarriers, unsigned int _cp_len) { // options modulation_scheme ms = LIQUID_MODEM_QPSK; unsigned int M = _num_subcarriers; unsigned int cp_len = _cp_len; unsigned int taper_len = 0; // create synthesizer/analyzer objects ofdmframegen fg = ofdmframegen_create(M, cp_len, taper_len, NULL); //ofdmframegen_print(fg); modem mod = modem_create(ms); ofdmframesync fs = ofdmframesync_create(M,cp_len,taper_len,NULL,NULL,NULL); unsigned int i; float complex X[M]; // channelized symbol float complex x[M+cp_len]; // time-domain symbol // synchronize short sequence (first) ofdmframegen_write_S0a(fg, x); ofdmframesync_execute(fs, x, M+cp_len); // synchronize short sequence (second) ofdmframegen_write_S0b(fg, x); ofdmframesync_execute(fs, x, M+cp_len); // synchronize long sequence ofdmframegen_write_S1(fg, x); ofdmframesync_execute(fs, x, M+cp_len); // modulate data symbols (use same symbol, ignore pilot phase) unsigned int s; for (i=0; i<M; i++) { s = modem_gen_rand_sym(mod); modem_modulate(mod,s,&X[i]); } ofdmframegen_writesymbol(fg, X, x); // add noise for (i=0; i<M+cp_len; i++) x[i] += 0.02f*randnf()*cexpf(_Complex_I*2*M_PI*randf()); // normalize number of iterations *_num_iterations /= M; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { // receive data symbols (ignoring pilots) ofdmframesync_execute(fs, x, M+cp_len); ofdmframesync_execute(fs, x, M+cp_len); ofdmframesync_execute(fs, x, M+cp_len); ofdmframesync_execute(fs, x, M+cp_len); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; // destroy objects ofdmframegen_destroy(fg); ofdmframesync_destroy(fs); modem_destroy(mod); }