// TODO : test this method BSYNC() BSYNC(_create_msequence)(unsigned int _g, unsigned int _k) { // validate input if (_k == 0) { fprintf(stderr,"bsync_xxxt_create_msequence(), samples/symbol must be greater than zero\n"); exit(1); } unsigned int m = liquid_msb_index(_g) - 1; // create/initialize msequence msequence ms = msequence_create(m, _g, 1); BSYNC() fs = (BSYNC()) malloc(sizeof(struct BSYNC(_s))); unsigned int n = msequence_get_length(ms); fs->sync_i = bsequence_create(n * _k); #ifdef TC_COMPLEX fs->sync_q = bsequence_create(n * _k); #endif fs->sym_i = bsequence_create(n * _k); #ifdef TI_COMPLEX fs->sym_q = bsequence_create(n * _k); #endif msequence_reset(ms); #if 0 bsequence_init_msequence(fs->sync_i,ms); #ifdef TC_COMPLEX msequence_reset(ms); bsequence_init_msequence(fs->sync_q,ms); #endif #else unsigned int i; unsigned int j; for (i=0; i<n; i++) { unsigned int bit = msequence_advance(ms); for (j=0; j<_k; j++) { bsequence_push(fs->sync_i, bit); #ifdef TC_COMPLEX bsequence_push(fs->sync_q, bit); #endif } } #endif msequence_destroy(ms); fs->n = _k*n; return fs; }
// create gmskframegen object gmskframegen gmskframegen_create() { gmskframegen q = (gmskframegen) malloc(sizeof(struct gmskframegen_s)); // set internal properties q->k = 2; // samples/symbol q->m = 3; // filter delay (symbols) q->BT = 0.5f; // filter bandwidth-time product // internal/derived values q->preamble_len = 63; // number of preamble symbols q->payload_len = 0; // number of payload symbols q->tail_len = 2*q->m; // number of tail symbols (flush interp) // create modulator q->mod = gmskmod_create(q->k, q->m, q->BT); // preamble objects/arrays q->ms_preamble = msequence_create(6, 0x6d, 1); // header objects/arrays q->header_dec = (unsigned char*)malloc(GMSKFRAME_H_DEC*sizeof(unsigned char)); q->header_enc = (unsigned char*)malloc(GMSKFRAME_H_ENC*sizeof(unsigned char)); q->header_len = GMSKFRAME_H_ENC * 8; q->p_header = packetizer_create(GMSKFRAME_H_DEC, GMSKFRAME_H_CRC, GMSKFRAME_H_FEC, LIQUID_FEC_NONE); // payload objects/arrays q->dec_msg_len = 0; q->check = LIQUID_CRC_32; q->fec0 = LIQUID_FEC_NONE; q->fec1 = LIQUID_FEC_NONE; q->p_payload = packetizer_create(q->dec_msg_len, q->check, q->fec0, q->fec1); q->enc_msg_len = packetizer_get_enc_msg_len(q->p_payload); q->payload_len = 8*q->enc_msg_len; // allocate memory for encoded packet q->payload_enc = (unsigned char*) malloc(q->enc_msg_len*sizeof(unsigned char)); // reset framing object gmskframegen_reset(q); // return object return q; }
// create a maximal-length sequence (m-sequence) object from a generator polynomial msequence msequence_create_genpoly(unsigned int _g) { unsigned int t = liquid_msb_index(_g); // validate input if (t < 2) { fprintf(stderr,"error: msequence_create_genpoly(), invalid generator polynomial: 0x%x\n", _g); exit(1); } // compute derived values unsigned int m = t - 1; // m-sequence shift register length unsigned int a = 1; // m-sequence initial state // generate object and return return msequence_create(m,_g,a); }
// 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; }
// 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 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; q->m = 7; // filter delay (symbols) q->beta = 0.3f; // excess bandwidth factor unsigned int i; // generate p/n sequence q->preamble_pn = (float complex*) malloc(64*sizeof(float complex)); q->preamble_rx = (float complex*) malloc(64*sizeof(float complex)); msequence ms = msequence_create(7, 0x0089, 1); for (i=0; i<64; i++) { q->preamble_pn[i] = (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2) + (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2)*_Complex_I; } msequence_destroy(ms); // create frame detector unsigned int k = 2; // samples/symbol q->detector = qdetector_cccf_create_linear(q->preamble_pn, 64, LIQUID_FIRFILT_ARKAISER, k, q->m, q->beta); qdetector_cccf_set_threshold(q->detector, 0.5f); // 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,k,q->m,q->beta); #if FLEXFRAMESYNC_ENABLE_EQ // create equalizer unsigned int p = 3; q->equalizer = eqlms_cccf_create_lowpass(2*k*p+1, 0.4f); eqlms_cccf_set_bw(q->equalizer, 0.05f); #endif // create down-coverters for carrier phase tracking q->mixer = nco_crcf_create(LIQUID_NCO); q->pll = nco_crcf_create(LIQUID_NCO); nco_crcf_pll_set_bandwidth(q->pll, 1e-4f); // very low bandwidth // header demodulator/decoder q->header_dec = (unsigned char *) malloc(FLEXFRAME_H_DEC*sizeof(unsigned char)); q->header_decoder = qpacketmodem_create(); qpacketmodem_configure(q->header_decoder, FLEXFRAME_H_DEC, FLEXFRAME_H_CRC, FLEXFRAME_H_FEC0, FLEXFRAME_H_FEC1, LIQUID_MODEM_QPSK); q->header_mod_len = qpacketmodem_get_frame_len(q->header_decoder); q->header_mod = (float complex*) malloc(q->header_mod_len*sizeof(float complex)); // header pilot synchronizer q->header_pilotsync = qpilotsync_create(q->header_mod_len, 16); q->header_sym_len = qpilotsync_get_frame_len(q->header_pilotsync); q->header_sym = (float complex*) malloc(q->header_sym_len*sizeof(float complex)); // payload demodulator for phase recovery q->payload_demod = modem_create(LIQUID_MODEM_QPSK); // create payload demodulator/decoder object q->payload_dec_len = 64; int check = LIQUID_CRC_24; int fec0 = LIQUID_FEC_NONE; int fec1 = LIQUID_FEC_GOLAY2412; int mod_scheme = LIQUID_MODEM_QPSK; q->payload_decoder = qpacketmodem_create(); qpacketmodem_configure(q->payload_decoder, q->payload_dec_len, check, fec0, fec1, mod_scheme); //qpacketmodem_print(q->payload_decoder); //assert( qpacketmodem_get_frame_len(q->payload_decoder)==600 ); q->payload_sym_len = qpacketmodem_get_frame_len(q->payload_decoder); // allocate memory for payload symbols and recovered data bytes q->payload_sym = (float complex*) malloc(q->payload_sym_len*sizeof(float complex)); q->payload_dec = (unsigned char*) malloc(q->payload_dec_len*sizeof(unsigned char)); // reset global data counters flexframesync_reset_framedatastats(q); #if DEBUG_FLEXFRAMESYNC // set debugging flags, objects to NULL q->debug_enabled = 0; q->debug_objects_created = 0; q->debug_qdetector_flush = 0; q->debug_x = NULL; #endif // reset state and return flexframesync_reset(q); return q; }