1 /*
2 * Copyright (c) 2007 - 2015 Joseph Gaeddert
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23 //
24 // ofdmflexframesync.c
25 //
26 // OFDM frame synchronizer
27 //
28
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <math.h>
33 #include <assert.h>
34
35 #include "liquid.internal.h"
36
37 #define DEBUG_OFDMFLEXFRAMESYNC 0
38
39 #define OFDMFLEXFRAME_P_SOFT (1)
40
41 //
42 // ofdmflexframesync
43 //
44
45 // internal callback
46 int ofdmflexframesync_internal_callback(float complex * _X,
47 unsigned char * _p,
48 unsigned int _M,
49 void * _userdata);
50
51 // receive header data
52 void ofdmflexframesync_rxheader(ofdmflexframesync _q,
53 float complex * _X);
54
55 // decode header
56 void ofdmflexframesync_decode_header(ofdmflexframesync _q);
57
58 // receive payload data
59 void ofdmflexframesync_rxpayload(ofdmflexframesync _q,
60 float complex * _X);
61
62 static ofdmflexframegenprops_s ofdmflexframesyncprops_header_default = {
63 OFDMFLEXFRAME_H_CRC,
64 OFDMFLEXFRAME_H_FEC0,
65 OFDMFLEXFRAME_H_FEC1,
66 OFDMFLEXFRAME_H_MOD,
67 };
68
69 struct ofdmflexframesync_s {
70 unsigned int M; // number of subcarriers
71 unsigned int cp_len; // cyclic prefix length
72 unsigned int taper_len; // taper length
73 unsigned char * p; // subcarrier allocation (null, pilot, data)
74
75 // constants
76 unsigned int M_null; // number of null subcarriers
77 unsigned int M_pilot; // number of pilot subcarriers
78 unsigned int M_data; // number of data subcarriers
79 unsigned int M_S0; // number of enabled subcarriers in S0
80 unsigned int M_S1; // number of enabled subcarriers in S1
81
82 // header
83 int header_soft; // perform soft demod of header
84 modem mod_header; // header modulator
85 packetizer p_header; // header packetizer
86 unsigned char * header; // header data (uncoded)
87 unsigned char * header_enc; // header data (encoded)
88 unsigned char * header_mod; // header symbols
89 unsigned int header_user_len; // header length (user)
90 unsigned int header_dec_len; // header length (uncoded)
91 unsigned int header_enc_len; // header length (encoded)
92 unsigned int header_sym_len; // header length (symbols)
93 int header_valid; // valid header flag
94
95 ofdmflexframegenprops_s header_props; // header properties
96
97 // header properties
98 modulation_scheme ms_payload; // payload modulation scheme
99 unsigned int bps_payload; // payload modulation depth (bits/symbol)
100 unsigned int payload_len; // payload length (number of bytes)
101 crc_scheme check; // payload validity check
102 fec_scheme fec0; // payload FEC (inner)
103 fec_scheme fec1; // payload FEC (outer)
104
105 // payload
106 int payload_soft; // perform soft demod of payload
107 packetizer p_payload; // payload packetizer
108 modem mod_payload; // payload demodulator
109 unsigned char * payload_enc; // payload data (encoded bytes)
110 unsigned char * payload_dec; // payload data (decoded bytes)
111 unsigned int payload_enc_len; // length of encoded payload
112 unsigned int payload_mod_len; // number of payload modem symbols
113 int payload_valid; // valid payload flag
114 float complex * payload_syms; // received payload symbols
115
116 // callback
117 framesync_callback callback; // user-defined callback function
118 void * userdata; // user-defined data structure
119 framesyncstats_s framestats; // frame statistic object
120 float evm_hat; // average error vector magnitude
121
122 // internal synchronizer objects
123 ofdmframesync fs; // internal OFDM frame synchronizer
124
125 // counters/states
126 unsigned int symbol_counter; // received symbol number
127 enum {
128 OFDMFLEXFRAMESYNC_STATE_HEADER, // extract header
129 OFDMFLEXFRAMESYNC_STATE_PAYLOAD // extract payload symbols
130 } state;
131 unsigned int header_symbol_index; // number of header symbols received
132 unsigned int payload_symbol_index; // number of payload symbols received
133 unsigned int payload_buffer_index; // bit-level index of payload (pack array)
134 };
135
136 // create ofdmflexframesync object
137 // _M : number of subcarriers
138 // _cp_len : length of cyclic prefix [samples]
139 // _taper_len : taper length (OFDM symbol overlap)
140 // _p : subcarrier allocation (PILOT/NULL/DATA) [size: _M x 1]
141 // _callback : user-defined callback function
142 // _userdata : user-defined data structure passed to callback
ofdmflexframesync_create(unsigned int _M,unsigned int _cp_len,unsigned int _taper_len,unsigned char * _p,framesync_callback _callback,void * _userdata)143 ofdmflexframesync ofdmflexframesync_create(unsigned int _M,
144 unsigned int _cp_len,
145 unsigned int _taper_len,
146 unsigned char * _p,
147 framesync_callback _callback,
148 void * _userdata)
149 {
150 ofdmflexframesync q = (ofdmflexframesync) malloc(sizeof(struct ofdmflexframesync_s));
151
152 // validate input
153 if (_M < 8) {
154 fprintf(stderr,"warning: ofdmflexframesync_create(), less than 8 subcarriers\n");
155 } else if (_M % 2) {
156 fprintf(stderr,"error: ofdmflexframesync_create(), number of subcarriers must be even\n");
157 exit(1);
158 } else if (_cp_len > _M) {
159 fprintf(stderr,"error: ofdmflexframesync_create(), cyclic prefix length cannot exceed number of subcarriers\n");
160 exit(1);
161 }
162
163 // set internal properties
164 q->M = _M;
165 q->cp_len = _cp_len;
166 q->taper_len = _taper_len;
167 q->callback = _callback;
168 q->userdata = _userdata;
169
170 // allocate memory for subcarrier allocation IDs
171 q->p = (unsigned char*) malloc((q->M)*sizeof(unsigned char));
172 if (_p == NULL) {
173 // initialize default subcarrier allocation
174 ofdmframe_init_default_sctype(q->M, q->p);
175 } else {
176 // copy user-defined subcarrier allocation
177 memmove(q->p, _p, q->M*sizeof(unsigned char));
178 }
179
180 // validate and count subcarrier allocation
181 ofdmframe_validate_sctype(q->p, q->M, &q->M_null, &q->M_pilot, &q->M_data);
182
183 // create internal framing object
184 q->fs = ofdmframesync_create(_M, _cp_len, _taper_len, _p, ofdmflexframesync_internal_callback, (void*)q);
185
186 // create header objects
187 q->header = NULL;
188 q->p_header = NULL;
189 q->header_enc = NULL;
190 q->header_mod = NULL;
191 q->mod_header = NULL;
192 q->header_user_len = OFDMFLEXFRAME_H_USER_DEFAULT;
193 q->header_soft = 0;
194 ofdmflexframesync_set_header_props(q, NULL);
195
196 // frame properties (default values to be overwritten when frame
197 // header is received and properly decoded)
198 q->ms_payload = LIQUID_MODEM_QPSK;
199 q->bps_payload = 2;
200 q->payload_len = 1;
201 q->check = LIQUID_CRC_NONE;
202 q->fec0 = LIQUID_FEC_NONE;
203 q->fec1 = LIQUID_FEC_NONE;
204
205 // create payload objects (initally QPSK, etc but overridden by received properties)
206 q->mod_payload = modem_create(q->ms_payload);
207 q->payload_soft = 0;
208 q->p_payload = packetizer_create(q->payload_len, q->check, q->fec0, q->fec1);
209 q->payload_enc_len = packetizer_get_enc_msg_len(q->p_payload);
210 q->payload_enc = (unsigned char*) malloc(q->payload_enc_len*sizeof(unsigned char));
211 q->payload_dec = (unsigned char*) malloc(q->payload_len*sizeof(unsigned char));
212 q->payload_syms = (float complex *) malloc(q->payload_len*sizeof(float complex));
213 q->payload_mod_len = 0;
214
215 // reset state
216 ofdmflexframesync_reset(q);
217
218 // return object
219 return q;
220 }
221
ofdmflexframesync_destroy(ofdmflexframesync _q)222 void ofdmflexframesync_destroy(ofdmflexframesync _q)
223 {
224 // destroy internal objects
225 ofdmframesync_destroy(_q->fs);
226 packetizer_destroy(_q->p_header);
227 modem_destroy(_q->mod_header);
228 packetizer_destroy(_q->p_payload);
229 modem_destroy(_q->mod_payload);
230
231 // free internal buffers/arrays
232 free(_q->p);
233 free(_q->payload_enc);
234 free(_q->payload_dec);
235 free(_q->payload_syms);
236 free(_q->header);
237 free(_q->header_enc);
238 free(_q->header_mod);
239
240 // free main object memory
241 free(_q);
242 }
243
ofdmflexframesync_print(ofdmflexframesync _q)244 void ofdmflexframesync_print(ofdmflexframesync _q)
245 {
246 printf("ofdmflexframesync:\n");
247 printf(" num subcarriers : %-u\n", _q->M);
248 printf(" * NULL : %-u\n", _q->M_null);
249 printf(" * pilot : %-u\n", _q->M_pilot);
250 printf(" * data : %-u\n", _q->M_data);
251 printf(" cyclic prefix len : %-u\n", _q->cp_len);
252 printf(" taper len : %-u\n", _q->taper_len);
253 }
254
ofdmflexframesync_set_header_len(ofdmflexframesync _q,unsigned int _len)255 void ofdmflexframesync_set_header_len(ofdmflexframesync _q,
256 unsigned int _len)
257 {
258 _q->header_user_len = _len;
259 _q->header_dec_len = OFDMFLEXFRAME_H_DEC + _q->header_user_len;
260 _q->header = realloc(_q->header, _q->header_dec_len*sizeof(unsigned char));
261
262 if (_q->p_header) {
263 packetizer_destroy(_q->p_header);
264 }
265 _q->p_header = packetizer_create(_q->header_dec_len,
266 _q->header_props.check,
267 _q->header_props.fec0,
268 _q->header_props.fec1);
269 if (_q->header_soft) {
270 _q->header_enc_len = 8*packetizer_get_enc_msg_len(_q->p_header);
271 _q->header_sym_len = _q->header_enc_len;
272 } else {
273 _q->header_enc_len = packetizer_get_enc_msg_len(_q->p_header);
274 unsigned int bps = modulation_types[_q->header_props.mod_scheme].bps;
275 div_t bps_d = div(_q->header_enc_len*8, bps);
276 _q->header_sym_len = bps_d.quot + (bps_d.rem ? 1 : 0);
277 }
278 _q->header_enc = realloc(_q->header_enc, _q->header_enc_len*sizeof(unsigned char));
279
280 _q->header_mod = realloc(_q->header_mod, _q->header_sym_len*sizeof(unsigned char));
281 // create header objects
282 if (_q->mod_header) {
283 modem_destroy(_q->mod_header);
284 }
285 _q->mod_header = modem_create(_q->header_props.mod_scheme);
286 }
287
ofdmflexframesync_decode_header_soft(ofdmflexframesync _q,int _soft)288 void ofdmflexframesync_decode_header_soft(ofdmflexframesync _q,
289 int _soft) {
290 _q->header_soft = _soft;
291 ofdmflexframesync_set_header_len(_q, _q->header_user_len);
292 }
293
ofdmflexframesync_decode_payload_soft(ofdmflexframesync _q,int _soft)294 void ofdmflexframesync_decode_payload_soft(ofdmflexframesync _q,
295 int _soft) {
296 _q->payload_soft = _soft;
297 }
298
ofdmflexframesync_set_header_props(ofdmflexframesync _q,ofdmflexframegenprops_s * _props)299 void ofdmflexframesync_set_header_props(ofdmflexframesync _q,
300 ofdmflexframegenprops_s * _props)
301 {
302 // if properties object is NULL, initialize with defaults
303 if (_props == NULL) {
304 _props = &ofdmflexframesyncprops_header_default;
305 }
306
307 // validate input
308 if (_props->check == LIQUID_CRC_UNKNOWN || _props->check >= LIQUID_CRC_NUM_SCHEMES) {
309 fprintf(stderr, "error: ofdmflexframesync_set_header_props(), invalid/unsupported CRC scheme\n");
310 exit(1);
311 } else if (_props->fec0 == LIQUID_FEC_UNKNOWN || _props->fec1 == LIQUID_FEC_UNKNOWN) {
312 fprintf(stderr, "error: ofdmflexframesync_set_header_props(), invalid/unsupported FEC scheme\n");
313 exit(1);
314 } else if (_props->mod_scheme == LIQUID_MODEM_UNKNOWN ) {
315 fprintf(stderr, "error: ofdmflexframesync_set_header_props(), invalid/unsupported modulation scheme\n");
316 exit(1);
317 }
318
319 // copy properties to internal structure
320 memmove(&_q->header_props, _props, sizeof(ofdmflexframegenprops_s));
321
322 // reconfigure internal buffers, objects, etc.
323 ofdmflexframesync_set_header_len(_q, _q->header_user_len);
324 }
325
ofdmflexframesync_reset(ofdmflexframesync _q)326 void ofdmflexframesync_reset(ofdmflexframesync _q)
327 {
328 // reset internal state
329 _q->state = OFDMFLEXFRAMESYNC_STATE_HEADER;
330
331 // reset internal counters
332 _q->symbol_counter=0;
333 _q->header_symbol_index=0;
334 _q->payload_symbol_index=0;
335 _q->payload_buffer_index=0;
336
337 // reset error vector magnitude estimate
338 _q->evm_hat = 1e-12f; // slight offset to ensure no log(0)
339
340 // reset framestats object
341 framesyncstats_init_default(&_q->framestats);
342
343 // reset internal OFDM frame synchronizer object
344 ofdmframesync_reset(_q->fs);
345 }
346
ofdmflexframesync_is_frame_open(ofdmflexframesync _q)347 int ofdmflexframesync_is_frame_open(ofdmflexframesync _q)
348 {
349 return ofdmframesync_is_frame_open(_q->fs);
350 }
351
352 // execute synchronizer object on buffer of samples
ofdmflexframesync_execute(ofdmflexframesync _q,float complex * _x,unsigned int _n)353 void ofdmflexframesync_execute(ofdmflexframesync _q,
354 float complex * _x,
355 unsigned int _n)
356 {
357 // push samples through ofdmframesync object
358 ofdmframesync_execute(_q->fs, _x, _n);
359 }
360
361 //
362 // query methods
363 //
364
365 // received signal strength indication
ofdmflexframesync_get_rssi(ofdmflexframesync _q)366 float ofdmflexframesync_get_rssi(ofdmflexframesync _q)
367 {
368 return ofdmframesync_get_rssi(_q->fs);
369 }
370
371 // received carrier frequency offset
ofdmflexframesync_get_cfo(ofdmflexframesync _q)372 float ofdmflexframesync_get_cfo(ofdmflexframesync _q)
373 {
374 return ofdmframesync_get_cfo(_q->fs);
375 }
376
377 //
378 // set methods
379 //
380
381 // received carrier frequency offset
ofdmflexframesync_set_cfo(ofdmflexframesync _q,float _cfo)382 void ofdmflexframesync_set_cfo(ofdmflexframesync _q, float _cfo)
383 {
384 return ofdmframesync_set_cfo(_q->fs, _cfo);
385 }
386
387 //
388 // debugging methods
389 //
390
391 // enable debugging for internal ofdm frame synchronizer
ofdmflexframesync_debug_enable(ofdmflexframesync _q)392 void ofdmflexframesync_debug_enable(ofdmflexframesync _q)
393 {
394 ofdmframesync_debug_enable(_q->fs);
395 }
396
397 // disable debugging for internal ofdm frame synchronizer
ofdmflexframesync_debug_disable(ofdmflexframesync _q)398 void ofdmflexframesync_debug_disable(ofdmflexframesync _q)
399 {
400 ofdmframesync_debug_disable(_q->fs);
401 }
402
403 // print debugging file for internal ofdm frame synchronizer
ofdmflexframesync_debug_print(ofdmflexframesync _q,const char * _filename)404 void ofdmflexframesync_debug_print(ofdmflexframesync _q,
405 const char * _filename)
406 {
407 ofdmframesync_debug_print(_q->fs, _filename);
408 }
409
410 //
411 // internal methods
412 //
413
414 // internal callback
415 // _X : subcarrier symbols
416 // _p : subcarrier allocation
417 // _M : number of subcarriers
418 // _userdata : user-defined data structure
ofdmflexframesync_internal_callback(float complex * _X,unsigned char * _p,unsigned int _M,void * _userdata)419 int ofdmflexframesync_internal_callback(float complex * _X,
420 unsigned char * _p,
421 unsigned int _M,
422 void * _userdata)
423 {
424 #if DEBUG_OFDMFLEXFRAMESYNC
425 printf("******* ofdmflexframesync callback invoked!\n");
426 #endif
427 // type-cast userdata as ofdmflexframesync object
428 ofdmflexframesync _q = (ofdmflexframesync) _userdata;
429
430 _q->symbol_counter++;
431
432 #if DEBUG_OFDMFLEXFRAMESYNC
433 printf("received symbol %u\n", _q->symbol_counter);
434 #endif
435
436 // extract symbols
437 switch (_q->state) {
438 case OFDMFLEXFRAMESYNC_STATE_HEADER:
439 ofdmflexframesync_rxheader(_q, _X);
440 break;
441 case OFDMFLEXFRAMESYNC_STATE_PAYLOAD:
442 ofdmflexframesync_rxpayload(_q, _X);
443 break;
444 default:
445 fprintf(stderr,"error: ofdmflexframesync_internal_callback(), unknown/unsupported internal state\n");
446 exit(1);
447 }
448
449 // return
450 return 0;
451 }
452
453 // receive header data
ofdmflexframesync_rxheader(ofdmflexframesync _q,float complex * _X)454 void ofdmflexframesync_rxheader(ofdmflexframesync _q,
455 float complex * _X)
456 {
457 #if DEBUG_OFDMFLEXFRAMESYNC
458 printf(" ofdmflexframesync extracting header...\n");
459 #endif
460
461 // demodulate header symbols
462 unsigned int i;
463 int sctype;
464 for (i=0; i<_q->M; i++) {
465 // subcarrier type (PILOT/NULL/DATA)
466 sctype = _q->p[i];
467
468 // ignore pilot and null subcarriers
469 if (sctype == OFDMFRAME_SCTYPE_DATA) {
470 // unload header symbols
471 // demodulate header symbol
472 unsigned int sym;
473 if (_q->header_soft) {
474 unsigned int bps = modulation_types[_q->header_props.mod_scheme].bps;
475 modem_demodulate_soft(_q->mod_header, _X[i], &sym, &_q->header_mod[bps*_q->header_symbol_index]);
476 } else {
477 modem_demodulate(_q->mod_header, _X[i], &sym);
478 _q->header_mod[_q->header_symbol_index] = sym;
479 }
480 _q->header_symbol_index++;
481 //printf(" extracting symbol %3u / %3u (x = %8.5f + j%8.5f)\n", _q->header_symbol_index, _q->header_sym_len, crealf(_X[i]), cimagf(_X[i]));
482
483 // get demodulator error vector magnitude
484 float evm = modem_get_demodulator_evm(_q->mod_header);
485 _q->evm_hat += evm*evm;
486
487 // header extracted
488 if (_q->header_symbol_index == _q->header_sym_len) {
489 // decode header
490 ofdmflexframesync_decode_header(_q);
491
492 // compute error vector magnitude estimate
493 _q->framestats.evm = 10*log10f( _q->evm_hat/_q->header_sym_len );
494
495 // invoke callback if header is invalid
496 if (_q->header_valid)
497 _q->state = OFDMFLEXFRAMESYNC_STATE_PAYLOAD;
498 else {
499 //printf("**** header invalid!\n");
500 // set framestats internals
501 _q->framestats.rssi = ofdmframesync_get_rssi(_q->fs);
502 _q->framestats.cfo = ofdmframesync_get_cfo(_q->fs);
503 _q->framestats.framesyms = NULL;
504 _q->framestats.num_framesyms = 0;
505 _q->framestats.mod_scheme = LIQUID_MODEM_UNKNOWN;
506 _q->framestats.mod_bps = 0;
507 _q->framestats.check = LIQUID_CRC_UNKNOWN;
508 _q->framestats.fec0 = LIQUID_FEC_UNKNOWN;
509 _q->framestats.fec1 = LIQUID_FEC_UNKNOWN;
510
511 // invoke callback method
512 _q->callback(_q->header,
513 _q->header_valid,
514 NULL,
515 0,
516 0,
517 _q->framestats,
518 _q->userdata);
519
520 ofdmflexframesync_reset(_q);
521 }
522 break;
523 }
524 }
525 }
526 }
527
528 // decode header
ofdmflexframesync_decode_header(ofdmflexframesync _q)529 void ofdmflexframesync_decode_header(ofdmflexframesync _q)
530 {
531 if (_q->header_soft) {
532 // TODO: ensure lengths are the same
533 memmove(_q->header_enc, _q->header_mod, _q->header_enc_len);
534
535 // unscramble header using soft bits
536 unscramble_data_soft(_q->header_enc, _q->header_enc_len/8);
537
538 // run packet decoder
539 _q->header_valid = packetizer_decode_soft(_q->p_header, _q->header_enc, _q->header);
540 } else {
541 // pack 1-bit header symbols into 8-bit bytes
542 unsigned int num_written;
543 unsigned int bps = modulation_types[_q->header_props.mod_scheme].bps;
544 liquid_repack_bytes(_q->header_mod, bps, _q->header_sym_len,
545 _q->header_enc, 8, _q->header_enc_len,
546 &num_written);
547 assert(num_written==_q->header_enc_len);
548
549 // unscramble header
550 unscramble_data(_q->header_enc, _q->header_enc_len);
551
552 // run packet decoder
553 _q->header_valid = packetizer_decode(_q->p_header, _q->header_enc, _q->header);
554 }
555
556 #if 0
557 // print header
558 printf("header rx (enc) : ");
559 for (i=0; i<_q->header_enc_len; i++)
560 printf("%.2X ", _q->header_enc[i]);
561 printf("\n");
562
563 // print header
564 printf("header rx (dec) : ");
565 for (i=0; i<_q->header_dec_len; i++)
566 printf("%.2X ", _q->header[i]);
567 printf("\n");
568 #endif
569
570 #if DEBUG_OFDMFLEXFRAMESYNC
571 printf("****** header extracted [%s]\n", _q->header_valid ? "valid" : "INVALID!");
572 #endif
573 if (!_q->header_valid)
574 return;
575
576 unsigned int n = _q->header_user_len;
577
578 // first byte is for expansion/version validation
579 if (_q->header[n+0] != OFDMFLEXFRAME_PROTOCOL) {
580 fprintf(stderr,"warning: ofdmflexframesync_decode_header(), invalid framing version\n");
581 _q->header_valid = 0;
582 }
583
584 // strip off payload length
585 unsigned int payload_len = (_q->header[n+1] << 8) | (_q->header[n+2]);
586
587 // strip off modulation scheme/depth
588 unsigned int mod_scheme = _q->header[n+3];
589 if (mod_scheme == 0 || mod_scheme >= LIQUID_MODEM_NUM_SCHEMES) {
590 fprintf(stderr,"warning: ofdmflexframesync_decode_header(), invalid modulation scheme\n");
591 _q->header_valid = 0;
592 return;
593 }
594
595 // strip off CRC, forward error-correction schemes
596 // CRC : most-significant 3 bits of [n+4]
597 // fec0 : least-significant 5 bits of [n+4]
598 // fec1 : least-significant 5 bits of [n+5]
599 unsigned int check = (_q->header[n+4] >> 5 ) & 0x07;
600 unsigned int fec0 = (_q->header[n+4] ) & 0x1f;
601 unsigned int fec1 = (_q->header[n+5] ) & 0x1f;
602
603 // validate properties
604 if (check >= LIQUID_CRC_NUM_SCHEMES) {
605 fprintf(stderr,"warning: ofdmflexframesync_decode_header(), decoded CRC exceeds available\n");
606 check = LIQUID_CRC_UNKNOWN;
607 _q->header_valid = 0;
608 }
609 if (fec0 >= LIQUID_FEC_NUM_SCHEMES) {
610 fprintf(stderr,"warning: ofdmflexframesync_decode_header(), decoded FEC (inner) exceeds available\n");
611 fec0 = LIQUID_FEC_UNKNOWN;
612 _q->header_valid = 0;
613 }
614 if (fec1 >= LIQUID_FEC_NUM_SCHEMES) {
615 fprintf(stderr,"warning: ofdmflexframesync_decode_header(), decoded FEC (outer) exceeds available\n");
616 fec1 = LIQUID_FEC_UNKNOWN;
617 _q->header_valid = 0;
618 }
619
620 // print results
621 #if DEBUG_OFDMFLEXFRAMESYNC
622 printf(" properties:\n");
623 printf(" * mod scheme : %s\n", modulation_types[mod_scheme].fullname);
624 printf(" * fec (inner) : %s\n", fec_scheme_str[fec0][1]);
625 printf(" * fec (outer) : %s\n", fec_scheme_str[fec1][1]);
626 printf(" * CRC scheme : %s\n", crc_scheme_str[check][1]);
627 printf(" * payload length : %u bytes\n", payload_len);
628 #endif
629
630 // configure payload receiver
631 if (_q->header_valid) {
632 // configure modem
633 if (mod_scheme != _q->ms_payload) {
634 // set new properties
635 _q->ms_payload = mod_scheme;
636 _q->bps_payload = modulation_types[mod_scheme].bps;
637
638 // recreate modem (destroy/create)
639 _q->mod_payload = modem_recreate(_q->mod_payload, _q->ms_payload);
640 }
641
642 // set new packetizer properties
643 _q->payload_len = payload_len;
644 _q->check = check;
645 _q->fec0 = fec0;
646 _q->fec1 = fec1;
647
648 // recreate packetizer object
649 _q->p_payload = packetizer_recreate(_q->p_payload,
650 _q->payload_len,
651 _q->check,
652 _q->fec0,
653 _q->fec1);
654
655 // re-compute payload encoded message length
656 if (_q->payload_soft) {
657 int packetizer_msg_len = packetizer_get_enc_msg_len(_q->p_payload);
658 div_t d = div((int)8*packetizer_msg_len, (int)_q->bps_payload);
659 _q->payload_mod_len = d.quot + (d.rem ? 1 : 0);
660 _q->payload_enc_len = _q->bps_payload*_q->payload_mod_len;
661 } else {
662 _q->payload_enc_len = packetizer_get_enc_msg_len(_q->p_payload);
663 // re-compute number of modulated payload symbols
664 div_t d = div(8*_q->payload_enc_len, _q->bps_payload);
665 _q->payload_mod_len = d.quot + (d.rem ? 1 : 0);
666 }
667
668 #if DEBUG_OFDMFLEXFRAMESYNC
669 printf(" * payload encoded : %u bytes\n", _q->payload_enc_len);
670 #endif
671
672 // re-allocate buffers accordingly
673 _q->payload_enc = (unsigned char*) realloc(_q->payload_enc, _q->payload_enc_len*sizeof(unsigned char));
674 _q->payload_dec = (unsigned char*) realloc(_q->payload_dec, _q->payload_len*sizeof(unsigned char));
675 _q->payload_syms = (float complex*) realloc(_q->payload_syms, _q->payload_mod_len*sizeof(float complex));
676 #if DEBUG_OFDMFLEXFRAMESYNC
677 printf(" * payload mod syms: %u symbols\n", _q->payload_mod_len);
678 #endif
679 }
680 }
681
682 // receive payload data
ofdmflexframesync_rxpayload(ofdmflexframesync _q,float complex * _X)683 void ofdmflexframesync_rxpayload(ofdmflexframesync _q,
684 float complex * _X)
685 {
686 // demodulate paylod symbols
687 unsigned int i;
688 int sctype;
689 for (i=0; i<_q->M; i++) {
690 // subcarrier type (PILOT/NULL/DATA)
691 sctype = _q->p[i];
692
693 // ignore pilot and null subcarriers
694 if (sctype == OFDMFRAME_SCTYPE_DATA) {
695 // unload payload symbols
696 unsigned int sym;
697 // store received symbol
698 _q->payload_syms[_q->payload_symbol_index] = _X[i];
699
700 if (_q->payload_soft) {
701 modem_demodulate_soft(_q->mod_payload, _X[i], &sym, &_q->payload_enc[_q->bps_payload*_q->payload_symbol_index]);
702 } else {
703 modem_demodulate(_q->mod_payload, _X[i], &sym);
704
705 // pack decoded symbol into array
706 liquid_pack_array(_q->payload_enc,
707 _q->payload_enc_len,
708 _q->payload_buffer_index,
709 _q->bps_payload,
710 sym);
711
712 // increment...
713 _q->payload_buffer_index += _q->bps_payload;
714 }
715
716 // increment symbol counter
717 _q->payload_symbol_index++;
718
719 if (_q->payload_symbol_index == _q->payload_mod_len) {
720 // payload extracted
721 if (_q->payload_soft) {
722 _q->payload_valid = packetizer_decode_soft(_q->p_payload, _q->payload_enc, _q->payload_dec);
723 } else {
724 // decode payload
725 _q->payload_valid = packetizer_decode(_q->p_payload, _q->payload_enc, _q->payload_dec);
726 }
727 #if DEBUG_OFDMFLEXFRAMESYNC
728 printf("****** payload extracted [%s]\n", _q->payload_valid ? "valid" : "INVALID!");
729 #endif
730
731 // ignore callback if set to NULL
732 if (_q->callback == NULL) {
733 ofdmflexframesync_reset(_q);
734 break;
735 }
736
737 // set framestats internals
738 _q->framestats.rssi = ofdmframesync_get_rssi(_q->fs);
739 _q->framestats.cfo = ofdmframesync_get_cfo(_q->fs);
740 _q->framestats.framesyms = _q->payload_syms;
741 _q->framestats.num_framesyms = _q->payload_mod_len;
742 _q->framestats.mod_scheme = _q->ms_payload;
743 _q->framestats.mod_bps = _q->bps_payload;
744 _q->framestats.check = _q->check;
745 _q->framestats.fec0 = _q->fec0;
746 _q->framestats.fec1 = _q->fec1;
747
748 // invoke callback method
749 _q->callback(_q->header,
750 _q->header_valid,
751 _q->payload_dec,
752 _q->payload_len,
753 _q->payload_valid,
754 _q->framestats,
755 _q->userdata);
756
757
758 // reset object
759 ofdmflexframesync_reset(_q);
760 break;
761 }
762 }
763 }
764 }
765
766
767
768