// reconfigure internal buffers, objects, etc. void ofdmflexframegen_reconfigure(ofdmflexframegen _q) { // re-create payload packetizer _q->p_payload = packetizer_recreate(_q->p_payload, _q->payload_dec_len, _q->props.check, _q->props.fec0, _q->props.fec1); // re-allocate memory for encoded message _q->payload_enc_len = packetizer_get_enc_msg_len(_q->p_payload); _q->payload_enc = (unsigned char*) realloc(_q->payload_enc, _q->payload_enc_len*sizeof(unsigned char)); #if DEBUG_OFDMFLEXFRAMEGEN printf(">>>> payload : %u (%u encoded)\n", _q->props.payload_len, _q->payload_enc_len); #endif // re-create modem // TODO : only do this if necessary _q->mod_payload = modem_recreate(_q->mod_payload, _q->props.mod_scheme); // re-allocate memory for payload modem symbols unsigned int bps = modulation_types[_q->props.mod_scheme].bps; div_t d = div(8*_q->payload_enc_len, bps); _q->payload_mod_len = d.quot + (d.rem ? 1 : 0); _q->payload_mod = (unsigned char*)realloc(_q->payload_mod, _q->payload_mod_len*sizeof(unsigned char)); // re-compute number of payload OFDM symbols d = div(_q->payload_mod_len, _q->M_data); _q->num_symbols_payload = d.quot + (d.rem ? 1 : 0); }
// 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 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 }
// decode header void flexframesync_decode_header(flexframesync _q) { // recover data symbols from pilots qpilotsync_execute(_q->header_pilotsync, _q->header_sym, _q->header_mod); // decode payload _q->header_valid = qpacketmodem_decode(_q->header_decoder, _q->header_mod, _q->header_dec); if (!_q->header_valid) return; // set fine carrier frequency and phase float dphi_hat = qpilotsync_get_dphi(_q->header_pilotsync); float phi_hat = qpilotsync_get_phi (_q->header_pilotsync); //printf("residual offset: dphi=%12.8f, phi=%12.8f\n", dphi_hat, phi_hat); nco_crcf_set_frequency(_q->pll, dphi_hat); nco_crcf_set_phase (_q->pll, phi_hat + dphi_hat * _q->header_sym_len); // first several bytes of header are user-defined unsigned int n = FLEXFRAME_H_USER; // first byte is for expansion/version validation unsigned int protocol = _q->header_dec[n+0]; if (protocol != FLEXFRAME_PROTOCOL) { fprintf(stderr,"warning: flexframesync_decode_header(), invalid framing protocol %u (expected %u)\n", protocol, FLEXFRAME_PROTOCOL); _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]); _q->payload_dec_len = payload_dec_len; // strip off modulation scheme/depth unsigned int mod_scheme = _q->header_dec[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_dec[n+4] >> 5 ) & 0x07; unsigned int fec0 = (_q->header_dec[n+4] ) & 0x1f; unsigned int fec1 = (_q->header_dec[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; } else if (check == LIQUID_CRC_UNKNOWN || check >= LIQUID_CRC_NUM_SCHEMES) { fprintf(stderr,"warning: flexframesync_decode_header(), decoded CRC exceeds available\n"); _q->header_valid = 0; return; } else if (fec0 == LIQUID_FEC_UNKNOWN || fec0 >= LIQUID_FEC_NUM_SCHEMES) { fprintf(stderr,"warning: flexframesync_decode_header(), decoded FEC (inner) exceeds available\n"); _q->header_valid = 0; return; } else if (fec1 == LIQUID_FEC_UNKNOWN || fec1 >= LIQUID_FEC_NUM_SCHEMES) { fprintf(stderr,"warning: flexframesync_decode_header(), decoded FEC (outer) exceeds available\n"); _q->header_valid = 0; return; } // re-create payload demodulator for phase-locked loop _q->payload_demod = modem_recreate(_q->payload_demod, mod_scheme); // reconfigure payload demodulator/decoder qpacketmodem_configure(_q->payload_decoder, payload_dec_len, check, fec0, fec1, mod_scheme); // set length appropriately _q->payload_sym_len = qpacketmodem_get_frame_len(_q->payload_decoder); // re-allocate buffers accordingly _q->payload_sym = (float complex*) realloc(_q->payload_sym, (_q->payload_sym_len)*sizeof(float complex)); _q->payload_dec = (unsigned char*) realloc(_q->payload_dec, (_q->payload_dec_len)*sizeof(unsigned char)); if (_q->payload_sym == 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 sym len : %u\n", _q->payload_sym_len); printf(" payload dec len : %u\n", _q->payload_dec_len); printf(" user data :"); unsigned int i; for (i=0; i<FLEXFRAME_H_USER; i++) printf(" %.2x", _q->header_dec[i]); printf("\n"); #endif }