// Help function to keep code base small void modem_test_demodsoft(modulation_scheme _ms) { // generate mod/demod modem mod = modem_create(_ms); modem demod = modem_create(_ms); // unsigned int bps = modem_get_bps(demod); // run the test unsigned int i, s, M=1<<bps; unsigned int sym_soft; unsigned char soft_bits[bps]; float complex x; for (i=0; i<M; i++) { // modulate symbol modem_modulate(mod, i, &x); // demodulate using soft-decision modem_demodulate_soft(demod, x, &s, soft_bits); // check hard-decision output CONTEND_EQUALITY(s, i); // check soft bits liquid_pack_soft_bits(soft_bits, bps, &sym_soft); CONTEND_EQUALITY(sym_soft, i); // check phase error, evm, etc. //CONTEND_DELTA( modem_get_demodulator_phase_error(demod), 0.0f, 1e-3f); //CONTEND_DELTA( modem_get_demodulator_evm(demod), 0.0f, 1e-3f); } // clean it up modem_destroy(mod); modem_destroy(demod); }
// receive header data void ofdmflexframesync_rxheader(ofdmflexframesync _q, float complex * _X) { #if DEBUG_OFDMFLEXFRAMESYNC printf(" ofdmflexframesync extracting header...\n"); #endif // demodulate header symbols unsigned int i; int sctype; for (i=0; i<_q->M; i++) { // subcarrier type (PILOT/NULL/DATA) sctype = _q->p[i]; // ignore pilot and null subcarriers if (sctype == OFDMFRAME_SCTYPE_DATA) { // unload header symbols // demodulate header symbol unsigned int sym; #if OFDMFLEXFRAME_H_SOFT modem_demodulate_soft(_q->mod_header, _X[i], &sym, &_q->header_mod[OFDMFLEXFRAME_H_BPS*_q->header_symbol_index]); #else modem_demodulate(_q->mod_header, _X[i], &sym); _q->header_mod[_q->header_symbol_index] = sym; #endif _q->header_symbol_index++; //printf(" extracting symbol %3u / %3u (x = %8.5f + j%8.5f)\n", _q->header_symbol_index, OFDMFLEXFRAME_H_SYM, crealf(_X[i]), cimagf(_X[i])); // get demodulator error vector magnitude float evm = modem_get_demodulator_evm(_q->mod_header); _q->evm_hat += evm*evm; // header extracted if (_q->header_symbol_index == OFDMFLEXFRAME_H_SYM) { // decode header ofdmflexframesync_decode_header(_q); // compute error vector magnitude estimate _q->framestats.evm = 10*log10f( _q->evm_hat/OFDMFLEXFRAME_H_SYM ); // invoke callback if header is invalid if (_q->header_valid) _q->state = OFDMFLEXFRAMESYNC_STATE_PAYLOAD; else { //printf("**** header invalid!\n"); // set framestats internals _q->framestats.rssi = ofdmframesync_get_rssi(_q->fs); _q->framestats.cfo = ofdmframesync_get_cfo(_q->fs); _q->framestats.framesyms = NULL; _q->framestats.num_framesyms = 0; _q->framestats.mod_scheme = LIQUID_MODEM_UNKNOWN; _q->framestats.mod_bps = 0; _q->framestats.check = LIQUID_CRC_UNKNOWN; _q->framestats.fec0 = LIQUID_FEC_UNKNOWN; _q->framestats.fec1 = LIQUID_FEC_UNKNOWN; // invoke callback method _q->callback(_q->header, _q->header_valid, NULL, 0, 0, _q->framestats, _q->userdata); ofdmflexframesync_reset(_q); } break; } } } }
// execute synchronizer, receiving header // _q : frame synchronizer object // _x : input sample void flexframesync_execute_rxheader(flexframesync _q, float complex _x) { // mix signal down float complex y; nco_crcf_mix_down(_q->nco_coarse, _x*0.5f/_q->gamma_hat, &y); nco_crcf_step(_q->nco_coarse); // update symbol synchronizer float complex mf_out = 0.0f; int sample_available = flexframesync_update_symsync(_q, y, &mf_out); // compute output if timeout if (sample_available) { // push through fine-tuned nco nco_crcf_mix_down(_q->nco_fine, mf_out, &mf_out); #if DEBUG_FLEXFRAMESYNC if (_q->debug_enabled) _q->header_sym[_q->header_counter] = mf_out; #endif // demodulate unsigned int sym_out = 0; #if DEMOD_HEADER_SOFT unsigned char bpsk_soft_bit = 0; modem_demodulate_soft(_q->demod_header, mf_out, &sym_out, &bpsk_soft_bit); _q->header_mod[_q->header_counter] = bpsk_soft_bit; #else modem_demodulate(_q->demod_header, mf_out, &sym_out); _q->header_mod[_q->header_counter] = (unsigned char)sym_out; #endif // update phase-locked loop and fine-tuned NCO float phase_error = modem_get_demodulator_phase_error(_q->demod_header); nco_crcf_pll_step(_q->nco_fine, phase_error); nco_crcf_step(_q->nco_fine); // update error vector magnitude float evm = modem_get_demodulator_evm(_q->demod_header); _q->framestats.evm += evm*evm; // increment counter _q->header_counter++; if (_q->header_counter == FLEXFRAME_H_SYM) { // decode header and invoke callback flexframesync_decode_header(_q); // invoke callback if header is invalid if (!_q->header_valid && _q->callback != NULL) { // set framestats internals _q->framestats.evm = 20*log10f(sqrtf(_q->framestats.evm / FLEXFRAME_H_SYM)); _q->framestats.rssi = 20*log10f(_q->gamma_hat); _q->framestats.cfo = nco_crcf_get_frequency(_q->nco_coarse) + nco_crcf_get_frequency(_q->nco_fine) / 2.0f; //(float)(_q->k); _q->framestats.framesyms = NULL; _q->framestats.num_framesyms = 0; _q->framestats.mod_scheme = LIQUID_MODEM_UNKNOWN; _q->framestats.mod_bps = 0; _q->framestats.check = LIQUID_CRC_UNKNOWN; _q->framestats.fec0 = LIQUID_FEC_UNKNOWN; _q->framestats.fec1 = LIQUID_FEC_UNKNOWN; // invoke callback method _q->callback(_q->header, _q->header_valid, NULL, 0, 0, _q->framestats, _q->userdata); } if (!_q->header_valid) { flexframesync_reset(_q); return; } // update state _q->state = STATE_RXPAYLOAD; } } }