void LiquidOfdmModComponent::initialize() { // print capabilities of liquid if (debug_x) { liquid_print_modulation_schemes(); liquid_print_fec_schemes(); liquid_print_crc_schemes(); } // initialize subcarrier allocation unsigned char p[noSubcarriers_x]; ofdmframe_init_default_sctype(noSubcarriers_x, p); // create frame generator properties object and initialize to default ofdmflexframegenprops_s fgProps; ofdmflexframegenprops_init_default(&fgProps); modulation_scheme ms = liquid_getopt_str2mod(modulationScheme_x.c_str()); fec_scheme fec0 = liquid_getopt_str2fec(fecZero_x.c_str()); fec_scheme fec1 = liquid_getopt_str2fec(fecOne_x.c_str()); crc_scheme check = liquid_getopt_str2crc(crcScheme_x.c_str()); fgProps.mod_scheme = ms; fgProps.fec0 = fec0; fgProps.fec1 = fec1; fgProps.check = check; gain_factor_ = powf(10.0f, gain_x/20.0f); // create frame generator object try { frameGenerator_ = ofdmflexframegen_create(noSubcarriers_x, cyclicPrefixLength_x, taperLength_x, p, &fgProps); ofdmflexframegen_print(frameGenerator_); } catch(...) { LOG(LERROR) << "Unexpected exception caught during frame generator generation"; } }
// create OFDM framing synchronizer object // _M : number of subcarriers, >10 typical // _cp_len : cyclic prefix length // _taper_len : taper length (OFDM symbol overlap) // _p : subcarrier allocation (null, pilot, data), [size: _M x 1] // _callback : user-defined callback function // _userdata : user-defined data pointer ofdmframesync ofdmframesync_create(unsigned int _M, unsigned int _cp_len, unsigned int _taper_len, unsigned char * _p, ofdmframesync_callback _callback, void * _userdata) { ofdmframesync q = (ofdmframesync) malloc(sizeof(struct ofdmframesync_s)); // validate input if (_M < 8) { fprintf(stderr,"warning: ofdmframesync_create(), less than 8 subcarriers\n"); } else if (_M % 2) { fprintf(stderr,"error: ofdmframesync_create(), number of subcarriers must be even\n"); exit(1); } else if (_cp_len > _M) { fprintf(stderr,"error: ofdmframesync_create(), cyclic prefix length cannot exceed number of subcarriers\n"); exit(1); } q->M = _M; q->cp_len = _cp_len; // derived values q->M2 = _M/2; // subcarrier allocation q->p = (unsigned char*) malloc((q->M)*sizeof(unsigned char)); if (_p == NULL) { ofdmframe_init_default_sctype(q->M, q->p); } else { 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); if ( (q->M_pilot + q->M_data) == 0) { fprintf(stderr,"error: ofdmframesync_create(), must have at least one enabled subcarrier\n"); exit(1); } else if (q->M_data == 0) { fprintf(stderr,"error: ofdmframesync_create(), must have at least one data subcarriers\n"); exit(1); } else if (q->M_pilot < 2) { fprintf(stderr,"error: ofdmframesync_create(), must have at least two pilot subcarriers\n"); exit(1); } // create transform object q->X = (float complex*) malloc((q->M)*sizeof(float complex)); q->x = (float complex*) malloc((q->M)*sizeof(float complex)); q->fft = FFT_CREATE_PLAN(q->M, q->x, q->X, FFT_DIR_FORWARD, FFT_METHOD); // create input buffer the length of the transform q->input_buffer = windowcf_create(q->M + q->cp_len); // allocate memory for PLCP arrays q->S0 = (float complex*) malloc((q->M)*sizeof(float complex)); q->s0 = (float complex*) malloc((q->M)*sizeof(float complex)); q->S1 = (float complex*) malloc((q->M)*sizeof(float complex)); q->s1 = (float complex*) malloc((q->M)*sizeof(float complex)); ofdmframe_init_S0(q->p, q->M, q->S0, q->s0, &q->M_S0); ofdmframe_init_S1(q->p, q->M, q->S1, q->s1, &q->M_S1); // compute scaling factor q->g_data = sqrtf(q->M) / sqrtf(q->M_pilot + q->M_data); q->g_S0 = sqrtf(q->M) / sqrtf(q->M_S0); q->g_S1 = sqrtf(q->M) / sqrtf(q->M_S1); // gain q->g0 = 1.0f; q->G0 = (float complex*) malloc((q->M)*sizeof(float complex)); q->G1 = (float complex*) malloc((q->M)*sizeof(float complex)); q->G = (float complex*) malloc((q->M)*sizeof(float complex)); q->B = (float complex*) malloc((q->M)*sizeof(float complex)); q->R = (float complex*) malloc((q->M)*sizeof(float complex)); #if 1 memset(q->G0, 0x00, q->M*sizeof(float complex)); memset(q->G1, 0x00, q->M*sizeof(float complex)); memset(q->G , 0x00, q->M*sizeof(float complex)); memset(q->B, 0x00, q->M*sizeof(float complex)); #endif // timing backoff q->backoff = q->cp_len < 2 ? q->cp_len : 2; float phi = (float)(q->backoff)*2.0f*M_PI/(float)(q->M); unsigned int i; for (i=0; i<q->M; i++) q->B[i] = liquid_cexpjf(i*phi); // set callback data q->callback = _callback; q->userdata = _userdata; // // synchronizer objects // // numerically-controlled oscillator q->nco_rx = nco_crcf_create(LIQUID_NCO); // set pilot sequence q->ms_pilot = msequence_create_default(8); #if OFDMFRAMESYNC_ENABLE_SQUELCH // coarse detection q->squelch_threshold = -25.0f; q->squelch_enabled = 0; #endif // reset object ofdmframesync_reset(q); #if DEBUG_OFDMFRAMESYNC q->debug_enabled = 0; q->debug_objects_created = 0; q->debug_x = NULL; q->debug_rssi = NULL; q->debug_framesyms =NULL; q->G_hat = NULL; q->px = NULL; q->py = NULL; q->debug_pilot_0 = NULL; q->debug_pilot_1 = NULL; #endif // return object return q; }
// create OFDM framing generator object // _M : number of subcarriers, >10 typical // _cp_len : cyclic prefix length // _taper_len : taper length (OFDM symbol overlap) // _p : subcarrier allocation (null, pilot, data), [size: _M x 1] ofdmframegen ofdmframegen_create(unsigned int _M, unsigned int _cp_len, unsigned int _taper_len, unsigned char * _p) { // validate input if (_M < 2) { fprintf(stderr,"error: ofdmframegen_create(), number of subcarriers must be at least 2\n"); exit(1); } else if (_M % 2) { fprintf(stderr,"error: ofdmframegen_create(), number of subcarriers must be even\n"); exit(1); } else if (_cp_len > _M) { fprintf(stderr,"error: ofdmframegen_create(), cyclic prefix cannot exceed symbol length\n"); exit(1); } else if (_taper_len > _cp_len) { fprintf(stderr,"error: ofdmframegen_create(), taper length cannot exceed cyclic prefix\n"); exit(1); } ofdmframegen q = (ofdmframegen) malloc(sizeof(struct ofdmframegen_s)); q->M = _M; q->cp_len = _cp_len; q->taper_len = _taper_len; // 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); if ( (q->M_pilot + q->M_data) == 0) { fprintf(stderr,"error: ofdmframegen_create(), must have at least one enabled subcarrier\n"); exit(1); } else if (q->M_data == 0) { fprintf(stderr,"error: ofdmframegen_create(), must have at least one data subcarriers\n"); exit(1); } else if (q->M_pilot < 2) { fprintf(stderr,"error: ofdmframegen_create(), must have at least two pilot subcarriers\n"); exit(1); } unsigned int i; // allocate memory for transform objects q->X = (float complex*) malloc((q->M)*sizeof(float complex)); q->x = (float complex*) malloc((q->M)*sizeof(float complex)); q->ifft = FFT_CREATE_PLAN(q->M, q->X, q->x, FFT_DIR_BACKWARD, FFT_METHOD); // allocate memory for PLCP arrays q->S0 = (float complex*) malloc((q->M)*sizeof(float complex)); q->s0 = (float complex*) malloc((q->M)*sizeof(float complex)); q->S1 = (float complex*) malloc((q->M)*sizeof(float complex)); q->s1 = (float complex*) malloc((q->M)*sizeof(float complex)); ofdmframe_init_S0(q->p, q->M, q->S0, q->s0, &q->M_S0); ofdmframe_init_S1(q->p, q->M, q->S1, q->s1, &q->M_S1); // create tapering window and transition buffer q->taper = (float*) malloc(q->taper_len * sizeof(float)); q->postfix = (float complex*) malloc(q->taper_len * sizeof(float complex)); for (i=0; i<q->taper_len; i++) { float t = ((float)i + 0.5f) / (float)(q->taper_len); float g = sinf(M_PI_2*t); q->taper[i] = g*g; } #if 0 // validate window symmetry for (i=0; i<q->taper_len; i++) { printf(" taper[%2u] = %12.8f (%12.8f)\n", i, q->taper[i], q->taper[i] + q->taper[q->taper_len - i - 1]); } #endif // compute scaling factor q->g_data = 1.0f / sqrtf(q->M_pilot + q->M_data); // set pilot sequence q->ms_pilot = msequence_create_default(8); return q; }
// 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 // _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); }
int main(int argc, char*argv[]) { srand(time(NULL)); // options unsigned int M = 64; // number of subcarriers unsigned int cp_len = 16; // cyclic prefix length unsigned int taper_len = 4; // taper length unsigned int payload_len = 120; // length of payload (bytes) modulation_scheme ms = LIQUID_MODEM_QPSK; fec_scheme fec0 = LIQUID_FEC_NONE; fec_scheme fec1 = LIQUID_FEC_HAMMING128; crc_scheme check = LIQUID_CRC_32; float noise_floor = -30.0f; // noise floor [dB] float SNRdB = 20.0f; // signal-to-noise ratio [dB] float dphi = 0.02f; // carrier frequency offset int debug_enabled = 0; // enable debugging? // get options int dopt; while((dopt = getopt(argc,argv,"uhds:F:M:C:n:m:v:c:k:")) != EOF){ switch (dopt) { case 'u': case 'h': usage(); return 0; case 'd': debug_enabled = 1; break; case 's': SNRdB = atof(optarg); break; case 'F': dphi = atof(optarg); break; case 'M': M = atoi(optarg); break; case 'C': cp_len = atoi(optarg); break; case 'n': payload_len = atol(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 'v': // data integrity check check = liquid_getopt_str2crc(optarg); if (check == LIQUID_CRC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported CRC scheme \"%s\"\n\n",optarg); exit(1); } break; case 'c': // inner FEC scheme fec0 = liquid_getopt_str2fec(optarg); if (fec0 == LIQUID_FEC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported inner FEC scheme \"%s\"\n\n",optarg); exit(1); } break; case 'k': // outer FEC scheme fec1 = liquid_getopt_str2fec(optarg); if (fec1 == LIQUID_FEC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported outer FEC scheme \"%s\"\n\n",optarg); exit(1); } break; default: exit(-1); } } unsigned int i; // TODO : validate options // derived values unsigned int frame_len = M + cp_len; float complex buffer[frame_len]; // time-domain buffer float nstd = powf(10.0f, noise_floor/20.0f); float gamma = powf(10.0f, (SNRdB + noise_floor)/20.0f); // allocate memory for header, payload unsigned char header[8]; unsigned char payload[payload_len]; // initialize subcarrier allocation unsigned char p[M]; ofdmframe_init_default_sctype(M, p); // create frame generator ofdmflexframegenprops_s fgprops; ofdmflexframegenprops_init_default(&fgprops); fgprops.check = check; fgprops.fec0 = fec0; fgprops.fec1 = fec1; fgprops.mod_scheme = ms; ofdmflexframegen fg = ofdmflexframegen_create(M, cp_len, taper_len, p, &fgprops); // create frame synchronizer ofdmflexframesync fs = ofdmflexframesync_create(M, cp_len, taper_len, p, callback, (void*)payload); if (debug_enabled) ofdmflexframesync_debug_enable(fs); // initialize header/payload and assemble frame for (i=0; i<8; i++) header[i] = i & 0xff; for (i=0; i<payload_len; i++) payload[i] = rand() & 0xff; ofdmflexframegen_assemble(fg, header, payload, payload_len); ofdmflexframegen_print(fg); ofdmflexframesync_print(fs); // initialize frame synchronizer with noise for (i=0; i<1000; i++) { float complex noise = nstd*( randnf() + _Complex_I*randnf())*M_SQRT1_2; ofdmflexframesync_execute(fs, &noise, 1); } // generate frame, push through channel int last_symbol=0; nco_crcf nco = nco_crcf_create(LIQUID_VCO); nco_crcf_set_frequency(nco, dphi); while (!last_symbol) { // generate symbol last_symbol = ofdmflexframegen_writesymbol(fg, buffer); // apply channel for (i=0; i<frame_len; i++) { float complex noise = nstd*( randnf() + _Complex_I*randnf())*M_SQRT1_2; buffer[i] *= gamma; buffer[i] += noise; nco_crcf_mix_up(nco, buffer[i], &buffer[i]); nco_crcf_step(nco); } // receive symbol ofdmflexframesync_execute(fs, buffer, frame_len); } nco_crcf_destroy(nco); // export debugging file if (debug_enabled) ofdmflexframesync_debug_print(fs, "ofdmflexframesync_debug.m"); // destroy objects ofdmflexframegen_destroy(fg); ofdmflexframesync_destroy(fs); printf("done.\n"); return 0; }
int main(int argc, char*argv[]) { srand(time(NULL)); // options unsigned int M = 64; // number of subcarriers unsigned int cp_len = 16; // cyclic prefix length unsigned int taper_len = 0; // taper length unsigned int num_symbols = 1000; // number of data symbols modulation_scheme ms = LIQUID_MODEM_QPSK; // get options int dopt; while((dopt = getopt(argc,argv,"hM:C:T:N:")) != EOF){ switch (dopt) { case 'h': usage(); return 0; case 'M': M = atoi(optarg); break; case 'C': cp_len = atoi(optarg); break; case 'T': taper_len = atoi(optarg); break; case 'N': num_symbols = atoi(optarg); break; default: exit(1); } } unsigned int i; // derived values unsigned int frame_len = M + cp_len; // initialize subcarrier allocation unsigned char p[M]; ofdmframe_init_default_sctype(M, p); // create frame generator ofdmframegen fg = ofdmframegen_create(M, cp_len, taper_len, p); ofdmframegen_print(fg); modem mod = modem_create(ms); float complex X[M]; // channelized symbols float complex buffer[frame_len];// output time series float * PAPR = (float*) malloc(num_symbols*sizeof(float)); // histogram display float xmin = -1.29f + 0.70f*log2f(M); float xmax = 8.97f + 0.34f*log2f(M); unsigned int num_bins = 30; float bin_width = (xmax - xmin) / (num_bins); unsigned int hist[num_bins]; for (i=0; i<num_bins; i++) hist[i] = 0; // modulate data symbols unsigned int j; unsigned int s; float PAPR_min = 0.0f; float PAPR_max = 0.0f; float PAPR_mean = 0.0f; for (i=0; i<num_symbols; i++) { // data symbol for (j=0; j<M; j++) { s = modem_gen_rand_sym(mod); modem_modulate(mod,s,&X[j]); } // generate symbol ofdmframegen_writesymbol(fg, X, buffer); #if 0 // preamble if (i==0) ofdmframegen_write_S0a(fg, buffer); // S0 symbol (first) else if (i==1) ofdmframegen_write_S0b(fg, buffer); // S0 symbol (second) else if (i==2) ofdmframegen_write_S1( fg, buffer); // S1 symbol #endif // compute PAPR PAPR[i] = ofdmframe_PAPR(buffer, frame_len); // compute bin index unsigned int index; float ihat = num_bins * (PAPR[i] - xmin) / (xmax - xmin); if (ihat < 0.0f) index = 0; else index = (unsigned int)ihat; if (index >= num_bins) index = num_bins-1; hist[index]++; // save min/max PAPR values if (i==0 || PAPR[i] < PAPR_min) PAPR_min = PAPR[i]; if (i==0 || PAPR[i] > PAPR_max) PAPR_max = PAPR[i]; PAPR_mean += PAPR[i]; } PAPR_mean /= (float)num_symbols; // destroy objects ofdmframegen_destroy(fg); modem_destroy(mod); // print results to screen // find max(hist) unsigned int hist_max = 0; for (i=0; i<num_bins; i++) hist_max = hist[i] > hist_max ? hist[i] : hist_max; printf("%8s : %6s [%6s]\n", "PAPR[dB]", "count", "prob."); for (i=0; i<num_bins; i++) { printf("%8.2f : %6u [%6.4f]", xmin + i*bin_width, hist[i], (float)hist[i] / (float)num_symbols); unsigned int k; unsigned int n = round(60 * (float)hist[i] / (float)hist_max); for (k=0; k<n; k++) printf("#"); printf("\n"); } printf("\n"); printf("min PAPR: %12.4f dB\n", PAPR_min); printf("max PAPR: %12.4f dB\n", PAPR_max); printf("mean PAPR: %12.4f dB\n", PAPR_mean); // // export output file // // count subcarrier types unsigned int M_data = 0; unsigned int M_pilot = 0; unsigned int M_null = 0; ofdmframe_validate_sctype(p, M, &M_null, &M_pilot, &M_data); FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n\n"); fprintf(fid,"M = %u;\n", M); fprintf(fid,"M_data = %u;\n", M_data); fprintf(fid,"M_pilot = %u;\n", M_pilot); fprintf(fid,"M_null = %u;\n", M_null); fprintf(fid,"cp_len = %u;\n", cp_len); fprintf(fid,"num_symbols = %u;\n", num_symbols); fprintf(fid,"PAPR = zeros(1,num_symbols);\n"); for (i=0; i<num_symbols; i++) fprintf(fid," PAPR(%6u) = %12.4e;\n", i+1, PAPR[i]); fprintf(fid,"\n"); fprintf(fid,"figure;\n"); fprintf(fid,"hist(PAPR,25);\n"); fprintf(fid,"\n"); fprintf(fid,"figure;\n"); fprintf(fid,"cdf = [(1:num_symbols)-0.5]/num_symbols;\n"); fprintf(fid,"semilogy(sort(PAPR),1-cdf);\n"); fprintf(fid,"xlabel('PAPR [dB]');\n"); fprintf(fid,"ylabel('Complementary CDF');\n"); fclose(fid); printf("results written to %s\n", OUTPUT_FILENAME); // free allocated array free(PAPR); printf("done.\n"); return 0; }
// create OFDM flexible framing generator object // _M : number of subcarriers, >10 typical // _cp_len : cyclic prefix length // _taper_len : taper length (OFDM symbol overlap) // _p : subcarrier allocation (null, pilot, data), [size: _M x 1] // _fgprops : frame properties (modulation scheme, etc.) ofdmflexframegen ofdmflexframegen_create(unsigned int _M, unsigned int _cp_len, unsigned int _taper_len, unsigned char * _p, ofdmflexframegenprops_s * _fgprops) { // validate input if (_M < 2) { fprintf(stderr,"error: ofdmflexframegen_create(), number of subcarriers must be at least 2\n"); exit(1); } else if (_M % 2) { fprintf(stderr,"error: ofdmflexframegen_create(), number of subcarriers must be even\n"); exit(1); } ofdmflexframegen q = (ofdmflexframegen) malloc(sizeof(struct ofdmflexframegen_s)); q->M = _M; // number of subcarriers q->cp_len = _cp_len; // cyclic prefix length q->taper_len = _taper_len; // taper length // allocate memory for transform buffers q->X = (float complex*) malloc((q->M)*sizeof(float complex)); // 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 OFDM frame generator object q->fg = ofdmframegen_create(q->M, q->cp_len, q->taper_len, q->p); // 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); // compute number of header symbols div_t d = div(OFDMFLEXFRAME_H_SYM, q->M_data); q->num_symbols_header = d.quot + (d.rem ? 1 : 0); // initial memory allocation for payload q->payload_dec_len = 1; q->p_payload = packetizer_create(q->payload_dec_len, LIQUID_CRC_NONE, LIQUID_FEC_NONE, LIQUID_FEC_NONE); 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_mod_len = 1; q->payload_mod = (unsigned char*) malloc(q->payload_mod_len*sizeof(unsigned char)); // create payload modem (initially QPSK, overridden by properties) q->mod_payload = modem_create(LIQUID_MODEM_QPSK); // initialize properties ofdmflexframegen_setprops(q, _fgprops); // reset ofdmflexframegen_reset(q); // return pointer to main object return q; }