// assemble frame // _q : frame generator object // _header : raw header // _payload : raw payload [size: _payload_len x 1] // _payload_len : raw payload length (bytes) // _check : data validity check // _fec0 : inner forward error correction // _fec1 : outer forward error correction void gmskframegen_assemble(gmskframegen _q, unsigned char * _header, unsigned char * _payload, unsigned int _payload_len, crc_scheme _check, fec_scheme _fec0, fec_scheme _fec1) { // re-create frame generator if properties don't match if (_q->dec_msg_len != _payload_len || _q->check != _check || _q->fec0 != _fec0 || _q->fec1 != _fec1) { // set properties _q->dec_msg_len = _payload_len; _q->check = _check; _q->fec0 = _fec0; _q->fec1 = _fec1; // re-create payload packetizer _q->p_payload = packetizer_recreate(_q->p_payload, _q->dec_msg_len, _q->check, _q->fec0, _q->fec1); // get packet length _q->enc_msg_len = packetizer_get_enc_msg_len(_q->p_payload); _q->payload_len = 8*_q->enc_msg_len; // re-allocate memory _q->payload_enc = (unsigned char*) realloc(_q->payload_enc, _q->enc_msg_len*sizeof(unsigned char)); } // set assembled flag _q->frame_assembled = 1; // encode header gmskframegen_encode_header(_q, _header); // encode payload packetizer_encode(_q->p_payload, _payload, _q->payload_enc); }
// 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; }
// decode header void ofdmflexframesync_decode_header(ofdmflexframesync _q) { #if OFDMFLEXFRAME_H_SOFT # if 0 unsigned int i; // copy soft bits for (i=0; i<8*OFDMFLEXFRAME_H_ENC; i++) _q->header_enc[i] = _q->header_mod[i]; # else // TODO: ensure lengths are the same memmove(_q->header_enc, _q->header_mod, 8*OFDMFLEXFRAME_H_ENC); # endif // unscramble header using soft bits unscramble_data_soft(_q->header_enc, OFDMFLEXFRAME_H_ENC); // run packet decoder _q->header_valid = packetizer_decode_soft(_q->p_header, _q->header_enc, _q->header); #else // pack 1-bit header symbols into 8-bit bytes unsigned int num_written; liquid_repack_bytes(_q->header_mod, OFDMFLEXFRAME_H_BPS, OFDMFLEXFRAME_H_SYM, _q->header_enc, 8, OFDMFLEXFRAME_H_ENC, &num_written); assert(num_written==OFDMFLEXFRAME_H_ENC); // unscramble header unscramble_data(_q->header_enc, OFDMFLEXFRAME_H_ENC); // run packet decoder _q->header_valid = packetizer_decode(_q->p_header, _q->header_enc, _q->header); #endif #if 0 // print header printf("header rx (enc) : "); for (i=0; i<OFDMFLEXFRAME_H_ENC; i++) printf("%.2X ", _q->header_enc[i]); printf("\n"); // print header printf("header rx (dec) : "); for (i=0; i<OFDMFLEXFRAME_H_DEC; i++) printf("%.2X ", _q->header[i]); printf("\n"); #endif #if DEBUG_OFDMFLEXFRAMESYNC printf("****** header extracted [%s]\n", _q->header_valid ? "valid" : "INVALID!"); #endif if (!_q->header_valid) return; unsigned int n = OFDMFLEXFRAME_H_USER; // first byte is for expansion/version validation if (_q->header[n+0] != OFDMFLEXFRAME_PROTOCOL) { fprintf(stderr,"warning: ofdmflexframesync_decode_header(), invalid framing version\n"); _q->header_valid = 0; } // strip off payload length unsigned int payload_len = (_q->header[n+1] << 8) | (_q->header[n+2]); // strip off modulation scheme/depth unsigned int mod_scheme = _q->header[n+3]; if (mod_scheme == 0 || mod_scheme >= LIQUID_MODEM_NUM_SCHEMES) { fprintf(stderr,"warning: ofdmflexframesync_decode_header(), invalid modulation scheme\n"); _q->header_valid = 0; return; } // strip off CRC, forward error-correction schemes // CRC : most-significant 3 bits of [n+4] // fec0 : least-significant 5 bits of [n+4] // fec1 : least-significant 5 bits of [n+5] unsigned int check = (_q->header[n+4] >> 5 ) & 0x07; unsigned int fec0 = (_q->header[n+4] ) & 0x1f; unsigned int fec1 = (_q->header[n+5] ) & 0x1f; // validate properties if (check >= LIQUID_CRC_NUM_SCHEMES) { fprintf(stderr,"warning: ofdmflexframesync_decode_header(), decoded CRC exceeds available\n"); check = LIQUID_CRC_UNKNOWN; _q->header_valid = 0; } if (fec0 >= LIQUID_FEC_NUM_SCHEMES) { fprintf(stderr,"warning: ofdmflexframesync_decode_header(), decoded FEC (inner) exceeds available\n"); fec0 = LIQUID_FEC_UNKNOWN; _q->header_valid = 0; } if (fec1 >= LIQUID_FEC_NUM_SCHEMES) { fprintf(stderr,"warning: ofdmflexframesync_decode_header(), decoded FEC (outer) exceeds available\n"); fec1 = LIQUID_FEC_UNKNOWN; _q->header_valid = 0; } // print results #if DEBUG_OFDMFLEXFRAMESYNC printf(" properties:\n"); printf(" * mod scheme : %s\n", modulation_types[mod_scheme].fullname); printf(" * fec (inner) : %s\n", fec_scheme_str[fec0][1]); printf(" * fec (outer) : %s\n", fec_scheme_str[fec1][1]); printf(" * CRC scheme : %s\n", crc_scheme_str[check][1]); printf(" * payload length : %u bytes\n", payload_len); #endif // configure payload receiver if (_q->header_valid) { // configure modem if (mod_scheme != _q->ms_payload) { // set new properties _q->ms_payload = mod_scheme; _q->bps_payload = modulation_types[mod_scheme].bps; // recreate modem (destroy/create) _q->mod_payload = modem_recreate(_q->mod_payload, _q->ms_payload); } // set new packetizer properties _q->payload_len = payload_len; _q->check = check; _q->fec0 = fec0; _q->fec1 = fec1; // recreate packetizer object _q->p_payload = packetizer_recreate(_q->p_payload, _q->payload_len, _q->check, _q->fec0, _q->fec1); // re-compute payload encoded message length _q->payload_enc_len = packetizer_get_enc_msg_len(_q->p_payload); #if DEBUG_OFDMFLEXFRAMESYNC printf(" * payload encoded : %u bytes\n", _q->payload_enc_len); #endif // re-allocate buffers accordingly _q->payload_enc = (unsigned char*) realloc(_q->payload_enc, _q->payload_enc_len*sizeof(unsigned char)); _q->payload_dec = (unsigned char*) realloc(_q->payload_dec, _q->payload_len*sizeof(unsigned char)); // re-compute number of modulated payload symbols div_t d = div(8*_q->payload_enc_len, _q->bps_payload); _q->payload_mod_len = d.quot + (d.rem ? 1 : 0); #if DEBUG_OFDMFLEXFRAMESYNC printf(" * payload mod syms: %u symbols\n", _q->payload_mod_len); #endif } }
// decode header and re-configure payload decoder void gmskframesync_decode_header(gmskframesync _q) { // pack each 1-bit header symbols into 8-bit bytes unsigned int num_written; liquid_pack_bytes(_q->header_mod, GMSKFRAME_H_SYM, _q->header_enc, GMSKFRAME_H_ENC, &num_written); assert(num_written==GMSKFRAME_H_ENC); // unscramble data unscramble_data(_q->header_enc, GMSKFRAME_H_ENC); // run packet decoder _q->header_valid = packetizer_decode(_q->p_header, _q->header_enc, _q->header_dec); #if DEBUG_GMSKFRAMESYNC_PRINT printf("****** header extracted [%s]\n", _q->header_valid ? "valid" : "INVALID!"); #endif if (!_q->header_valid) return; unsigned int n = GMSKFRAME_H_USER; // first byte is for expansion/version validation if (_q->header_dec[n+0] != GMSKFRAME_VERSION) { fprintf(stderr,"warning: gmskframesync_decode_header(), invalid framing version\n"); _q->header_valid = 0; return; } // strip off payload length unsigned int payload_dec_len = (_q->header_dec[n+1] << 8) | (_q->header_dec[n+2]); // strip off CRC, forward error-correction schemes // CRC : most-significant 3 bits of [n+3] // fec0 : least-significant 5 bits of [n+3] // fec1 : least-significant 5 bits of [n+4] unsigned int check = (_q->header_dec[n+3] >> 5 ) & 0x07; unsigned int fec0 = (_q->header_dec[n+3] ) & 0x1f; unsigned int fec1 = (_q->header_dec[n+4] ) & 0x1f; // validate properties if (check >= LIQUID_CRC_NUM_SCHEMES) { fprintf(stderr,"warning: gmskframesync_decode_header(), decoded CRC exceeds available\n"); check = LIQUID_CRC_UNKNOWN; _q->header_valid = 0; } if (fec0 >= LIQUID_FEC_NUM_SCHEMES) { fprintf(stderr,"warning: gmskframesync_decode_header(), decoded FEC (inner) exceeds available\n"); fec0 = LIQUID_FEC_UNKNOWN; _q->header_valid = 0; } if (fec1 >= LIQUID_FEC_NUM_SCHEMES) { fprintf(stderr,"warning: gmskframesync_decode_header(), decoded FEC (outer) exceeds available\n"); fec1 = LIQUID_FEC_UNKNOWN; _q->header_valid = 0; } // print results #if DEBUG_GMSKFRAMESYNC_PRINT printf(" properties:\n"); printf(" * fec (inner) : %s\n", fec_scheme_str[fec0][1]); printf(" * fec (outer) : %s\n", fec_scheme_str[fec1][1]); printf(" * CRC scheme : %s\n", crc_scheme_str[check][1]); printf(" * payload length : %u bytes\n", payload_dec_len); #endif // configure payload receiver if (_q->header_valid) { // set new packetizer properties _q->payload_dec_len = payload_dec_len; _q->check = check; _q->fec0 = fec0; _q->fec1 = fec1; // recreate packetizer object _q->p_payload = packetizer_recreate(_q->p_payload, _q->payload_dec_len, _q->check, _q->fec0, _q->fec1); // re-compute payload encoded message length _q->payload_enc_len = packetizer_get_enc_msg_len(_q->p_payload); #if DEBUG_GMSKFRAMESYNC_PRINT printf(" * payload encoded : %u bytes\n", _q->payload_enc_len); #endif // re-allocate buffers accordingly _q->payload_enc = (unsigned char*) realloc(_q->payload_enc, _q->payload_enc_len*sizeof(unsigned char)); _q->payload_dec = (unsigned char*) realloc(_q->payload_dec, _q->payload_dec_len*sizeof(unsigned char)); } // }
// create GMSK frame synchronizer // _callback : callback function // _userdata : user data pointer passed to callback function gmskframesync gmskframesync_create(framesync_callback _callback, void * _userdata) { gmskframesync q = (gmskframesync) malloc(sizeof(struct gmskframesync_s)); q->callback = _callback; q->userdata = _userdata; q->k = 2; // samples/symbol q->m = 3; // filter delay (symbols) q->BT = 0.5f; // filter bandwidth-time product #if GMSKFRAMESYNC_PREFILTER // create default low-pass Butterworth filter q->prefilter = iirfilt_crcf_create_lowpass(3, 0.5f*(1 + q->BT) / (float)(q->k)); #endif unsigned int i; // frame detector q->preamble_len = 63; q->preamble_pn = (float*)malloc(q->preamble_len*sizeof(float)); q->preamble_rx = (float*)malloc(q->preamble_len*sizeof(float)); float complex preamble_samples[q->preamble_len*q->k]; msequence ms = msequence_create(6, 0x6d, 1); gmskmod mod = gmskmod_create(q->k, q->m, q->BT); for (i=0; i<q->preamble_len + q->m; i++) { unsigned char bit = msequence_advance(ms); // save p/n sequence if (i < q->preamble_len) q->preamble_pn[i] = bit ? 1.0f : -1.0f; // modulate/interpolate if (i < q->m) gmskmod_modulate(mod, bit, &preamble_samples[0]); else gmskmod_modulate(mod, bit, &preamble_samples[(i-q->m)*q->k]); } gmskmod_destroy(mod); msequence_destroy(ms); #if 0 // print sequence for (i=0; i<q->preamble_len*q->k; i++) printf("preamble(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(preamble_samples[i]), cimagf(preamble_samples[i])); #endif // create frame detector float threshold = 0.5f; // detection threshold float dphi_max = 0.05f; // maximum carrier offset allowable q->frame_detector = detector_cccf_create(preamble_samples, q->preamble_len*q->k, threshold, dphi_max); q->buffer = windowcf_create(q->k*(q->preamble_len+q->m)); // create symbol timing recovery filters q->npfb = 32; // number of filters in the bank q->mf = firpfb_rrrf_create_rnyquist( LIQUID_FIRFILT_GMSKRX,q->npfb,q->k,q->m,q->BT); q->dmf = firpfb_rrrf_create_drnyquist(LIQUID_FIRFILT_GMSKRX,q->npfb,q->k,q->m,q->BT); // create down-coverters for carrier phase tracking q->nco_coarse = nco_crcf_create(LIQUID_NCO); // create/allocate header objects/arrays q->header_mod = (unsigned char*)malloc(GMSKFRAME_H_SYM*sizeof(unsigned char)); q->header_enc = (unsigned char*)malloc(GMSKFRAME_H_ENC*sizeof(unsigned char)); q->header_dec = (unsigned char*)malloc(GMSKFRAME_H_DEC*sizeof(unsigned char)); q->p_header = packetizer_create(GMSKFRAME_H_DEC, GMSKFRAME_H_CRC, GMSKFRAME_H_FEC, LIQUID_FEC_NONE); // create/allocate payload objects/arrays q->payload_dec_len = 1; q->check = LIQUID_CRC_32; q->fec0 = LIQUID_FEC_NONE; q->fec1 = LIQUID_FEC_NONE; q->p_payload = packetizer_create(q->payload_dec_len, q->check, q->fec0, q->fec1); q->payload_enc_len = packetizer_get_enc_msg_len(q->p_payload); q->payload_dec = (unsigned char*) malloc(q->payload_dec_len*sizeof(unsigned char)); q->payload_enc = (unsigned char*) malloc(q->payload_enc_len*sizeof(unsigned char)); #if DEBUG_GMSKFRAMESYNC // debugging structures q->debug_enabled = 0; q->debug_objects_created = 0; q->debug_x = NULL; q->debug_fi = NULL; q->debug_mf = NULL; q->debug_framesyms = NULL; #endif // reset synchronizer gmskframesync_reset(q); // return synchronizer object return q; }
// decode header void flexframesync_decode_header(flexframesync _q) { #if DEMOD_HEADER_SOFT // soft decoding operates on 'header_mod' array directly; // no need to pack bits #else // pack 256 1-bit header symbols into 32 8-bit bytes unsigned int num_written; liquid_pack_bytes(_q->header_mod, FLEXFRAME_H_SYM, _q->header_enc, FLEXFRAME_H_ENC, &num_written); assert(num_written==FLEXFRAME_H_ENC); #endif #if DEBUG_FLEXFRAMESYNC_PRINT unsigned int i; // print header (encoded) printf("header rx (enc) : "); for (i=0; i<FLEXFRAME_H_ENC; i++) printf("%.2X ", _q->header_enc[i]); printf("\n"); #endif // unscramble header and run packet decoder #if DEMOD_HEADER_SOFT // soft demodulation operates on header_mod directly unscramble_data_soft(_q->header_mod, FLEXFRAME_H_ENC); _q->header_valid = packetizer_decode_soft(_q->p_header, _q->header_mod, _q->header); #else unscramble_data(_q->header_enc, FLEXFRAME_H_ENC); _q->header_valid = packetizer_decode(_q->p_header, _q->header_enc, _q->header); #endif // return if header is invalid if (!_q->header_valid) return; // first several bytes of header are user-defined unsigned int n = FLEXFRAME_H_USER; // first byte is for expansion/version validation if (_q->header[n+0] != FLEXFRAME_VERSION) { fprintf(stderr,"warning: flexframesync_decode_header(), invalid framing version\n"); _q->header_valid = 0; return; } // strip off payload length unsigned int payload_dec_len = (_q->header[n+1] << 8) | (_q->header[n+2]); _q->payload_dec_len = payload_dec_len; // strip off modulation scheme/depth unsigned int mod_scheme = _q->header[n+3]; // strip off CRC, forward error-correction schemes // CRC : most-significant 3 bits of [n+4] // fec0 : least-significant 5 bits of [n+4] // fec1 : least-significant 5 bits of [n+5] unsigned int check = (_q->header[n+4] >> 5 ) & 0x07; unsigned int fec0 = (_q->header[n+4] ) & 0x1f; unsigned int fec1 = (_q->header[n+5] ) & 0x1f; // validate properties if (mod_scheme == 0 || mod_scheme >= LIQUID_MODEM_NUM_SCHEMES) { fprintf(stderr,"warning: flexframesync_decode_header(), invalid modulation scheme\n"); _q->header_valid = 0; return; } if (check >= LIQUID_CRC_NUM_SCHEMES) { fprintf(stderr,"warning: flexframesync_decode_header(), decoded CRC exceeds available\n"); _q->header_valid = 0; return; } if (fec0 >= LIQUID_FEC_NUM_SCHEMES) { fprintf(stderr,"warning: flexframesync_decode_header(), decoded FEC (inner) exceeds available\n"); _q->header_valid = 0; return; } if (fec1 >= LIQUID_FEC_NUM_SCHEMES) { fprintf(stderr,"warning: flexframesync_decode_header(), decoded FEC (outer) exceeds available\n"); _q->header_valid = 0; return; } // configure payload receiver if (_q->header_valid) { // recreate modem _q->ms_payload = mod_scheme; _q->bps_payload = modulation_types[mod_scheme].bps; _q->demod_payload = modem_recreate(_q->demod_payload, _q->ms_payload); // set new packetizer properties _q->check = check; _q->fec0 = fec0; _q->fec1 = fec1; // recreate packetizer object _q->p_payload = packetizer_recreate(_q->p_payload, _q->payload_dec_len, _q->check, _q->fec0, _q->fec1); // re-compute payload encoded message length _q->payload_enc_len = packetizer_get_enc_msg_len(_q->p_payload); // re-compute number of modulated payload symbols div_t d = div(8*_q->payload_enc_len, _q->bps_payload); _q->payload_mod_len = d.quot + (d.rem ? 1 : 0); // re-allocate buffers accordingly // (give encoded a few extra bytes to compensate for repacking) _q->payload_mod = (unsigned char*) realloc(_q->payload_mod, (_q->payload_mod_len )*sizeof(unsigned char)); _q->payload_enc = (unsigned char*) realloc(_q->payload_enc, (_q->payload_enc_len+8)*sizeof(unsigned char)); _q->payload_dec = (unsigned char*) realloc(_q->payload_dec, (_q->payload_dec_len )*sizeof(unsigned char)); if (_q->payload_mod == NULL || _q->payload_enc == NULL || _q->payload_dec == NULL) { fprintf(stderr,"error: flexframesync_decode_header(), could not re-allocate payload arrays\n"); _q->header_valid = 0; return; } } #if DEBUG_FLEXFRAMESYNC_PRINT // print results printf("flexframesync_decode_header():\n"); printf(" header crc : %s\n", _q->header_valid ? "pass" : "FAIL"); printf(" check : %s\n", crc_scheme_str[check][1]); printf(" fec (inner) : %s\n", fec_scheme_str[fec0][1]); printf(" fec (outer) : %s\n", fec_scheme_str[fec1][1]); printf(" mod scheme : %s\n", modulation_types[mod_scheme].name); printf(" payload dec len : %u\n", _q->payload_dec_len); printf(" payload enc len : %u\n", _q->payload_enc_len); printf(" payload mod len : %u\n", _q->payload_mod_len); printf(" user data :"); for (i=0; i<FLEXFRAME_H_USER; i++) printf(" %.2x", _q->header[i]); printf("\n"); #endif }
// create flexframesync object // _callback : callback function invoked when frame is received // _userdata : user-defined data object passed to callback flexframesync flexframesync_create(framesync_callback _callback, void * _userdata) { flexframesync q = (flexframesync) malloc(sizeof(struct flexframesync_s)); q->callback = _callback; q->userdata = _userdata; unsigned int i; // generate p/n sequence msequence ms = msequence_create(6, 0x005b, 1); for (i=0; i<64; i++) q->preamble_pn[i] = (msequence_advance(ms)) ? 1.0f : -1.0f; msequence_destroy(ms); // interpolate p/n sequence with matched filter q->k = 2; // samples/symbol q->m = 7; // filter delay (symbols) q->beta = 0.25f; // excess bandwidth factor float complex seq[q->k*64]; firinterp_crcf interp = firinterp_crcf_create_rnyquist(LIQUID_FIRFILT_ARKAISER,q->k,q->m,q->beta,0); for (i=0; i<64+q->m; i++) { // compensate for filter delay if (i < q->m) firinterp_crcf_execute(interp, q->preamble_pn[i], &seq[0]); else firinterp_crcf_execute(interp, q->preamble_pn[i%64], &seq[q->k*(i-q->m)]); } firinterp_crcf_destroy(interp); // create frame detector float threshold = 0.4f; // detection threshold float dphi_max = 0.05f; // maximum carrier offset allowable q->frame_detector = detector_cccf_create(seq, q->k*64, threshold, dphi_max); q->buffer = windowcf_create(q->k*(64+q->m)); // create symbol timing recovery filters q->npfb = 32; // number of filters in the bank q->mf = firpfb_crcf_create_rnyquist(LIQUID_FIRFILT_ARKAISER, q->npfb,q->k,q->m,q->beta); q->dmf = firpfb_crcf_create_drnyquist(LIQUID_FIRFILT_ARKAISER,q->npfb,q->k,q->m,q->beta); // create down-coverters for carrier phase tracking q->nco_coarse = nco_crcf_create(LIQUID_NCO); q->nco_fine = nco_crcf_create(LIQUID_VCO); nco_crcf_pll_set_bandwidth(q->nco_fine, 0.05f); // create header objects q->demod_header = modem_create(LIQUID_MODEM_BPSK); q->p_header = packetizer_create(FLEXFRAME_H_DEC, FLEXFRAME_H_CRC, FLEXFRAME_H_FEC0, FLEXFRAME_H_FEC1); assert(packetizer_get_enc_msg_len(q->p_header)==FLEXFRAME_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_dec_len = 1; q->check = LIQUID_CRC_NONE; q->fec0 = LIQUID_FEC_NONE; q->fec1 = LIQUID_FEC_NONE; // create payload objects (overridden by received properties) q->demod_payload = modem_create(LIQUID_MODEM_QPSK); q->p_payload = packetizer_create(q->payload_dec_len, q->check, q->fec0, q->fec1); q->payload_enc_len = packetizer_get_enc_msg_len(q->p_payload); q->payload_mod_len = 4 * q->payload_enc_len; q->payload_mod = (unsigned char*) malloc(q->payload_mod_len*sizeof(unsigned char)); q->payload_enc = (unsigned char*) malloc(q->payload_enc_len*sizeof(unsigned char)); q->payload_dec = (unsigned char*) malloc(q->payload_dec_len*sizeof(unsigned char)); #if DEBUG_FLEXFRAMESYNC // set debugging flags, objects to NULL q->debug_enabled = 0; q->debug_objects_created = 0; q->debug_x = NULL; #endif // reset state flexframesync_reset(q); return q; }
// 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; }