// 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); }
// create ofdmflexframesync object // _M : number of subcarriers // _cp_len : length of cyclic prefix [samples] // _taper_len : taper length (OFDM symbol overlap) // _p : subcarrier allocation (PILOT/NULL/DATA) [size: _M x 1] // _callback : user-defined callback function // _userdata : user-defined data structure passed to callback ofdmflexframesync ofdmflexframesync_create(unsigned int _M, unsigned int _cp_len, unsigned int _taper_len, unsigned char * _p, framesync_callback _callback, void * _userdata) { ofdmflexframesync q = (ofdmflexframesync) malloc(sizeof(struct ofdmflexframesync_s)); // validate input if (_M < 8) { fprintf(stderr,"warning: ofdmflexframesync_create(), less than 8 subcarriers\n"); } else if (_M % 2) { fprintf(stderr,"error: ofdmflexframesync_create(), number of subcarriers must be even\n"); exit(1); } else if (_cp_len > _M) { fprintf(stderr,"error: ofdmflexframesync_create(), cyclic prefix length cannot exceed number of subcarriers\n"); exit(1); } // set internal properties q->M = _M; q->cp_len = _cp_len; q->taper_len = _taper_len; q->callback = _callback; q->userdata = _userdata; // allocate memory for subcarrier allocation IDs q->p = (unsigned char*) malloc((q->M)*sizeof(unsigned char)); if (_p == NULL) { // initialize default subcarrier allocation ofdmframe_init_default_sctype(q->M, q->p); } else { // copy user-defined subcarrier allocation memmove(q->p, _p, q->M*sizeof(unsigned char)); } // validate and count subcarrier allocation ofdmframe_validate_sctype(q->p, q->M, &q->M_null, &q->M_pilot, &q->M_data); // create internal framing object q->fs = ofdmframesync_create(_M, _cp_len, _taper_len, _p, ofdmflexframesync_internal_callback, (void*)q); // create header objects q->mod_header = modem_create(OFDMFLEXFRAME_H_MOD); q->p_header = packetizer_create(OFDMFLEXFRAME_H_DEC, OFDMFLEXFRAME_H_CRC, OFDMFLEXFRAME_H_FEC, LIQUID_FEC_NONE); assert(packetizer_get_enc_msg_len(q->p_header)==OFDMFLEXFRAME_H_ENC); // frame properties (default values to be overwritten when frame // header is received and properly decoded) q->ms_payload = LIQUID_MODEM_QPSK; q->bps_payload = 2; q->payload_len = 1; q->check = LIQUID_CRC_NONE; q->fec0 = LIQUID_FEC_NONE; q->fec1 = LIQUID_FEC_NONE; // create payload objects (initally QPSK, etc but overridden by received properties) q->mod_payload = modem_create(q->ms_payload); q->p_payload = packetizer_create(q->payload_len, q->check, q->fec0, q->fec1); q->payload_enc_len = packetizer_get_enc_msg_len(q->p_payload); q->payload_enc = (unsigned char*) malloc(q->payload_enc_len*sizeof(unsigned char)); q->payload_dec = (unsigned char*) malloc(q->payload_len*sizeof(unsigned char)); q->payload_mod_len = 0; // reset state ofdmflexframesync_reset(q); // return object return q; }
// 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); }