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 // Packetizer
25 //
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "liquid.internal.h"
32
33 // reallocate memory for buffers
34 void packetizer_realloc_buffers(packetizer _p, unsigned int _len);
35
36 // computes the number of encoded bytes after packetizing
37 //
38 // _n : number of uncoded input bytes
39 // _crc : error-detecting scheme
40 // _fec0 : inner forward error-correction code
41 // _fec1 : outer forward error-correction code
packetizer_compute_enc_msg_len(unsigned int _n,int _crc,int _fec0,int _fec1)42 unsigned int packetizer_compute_enc_msg_len(unsigned int _n,
43 int _crc,
44 int _fec0,
45 int _fec1)
46 {
47 unsigned int k = _n + crc_get_length(_crc);
48 unsigned int n0 = fec_get_enc_msg_length(_fec0, k);
49 unsigned int n1 = fec_get_enc_msg_length(_fec1, n0);
50
51 return n1;
52 }
53
54 // computes the number of decoded bytes before packetizing
55 //
56 // _k : number of encoded bytes
57 // _crc : error-detecting scheme
58 // _fec0 : inner forward error-correction code
59 // _fec1 : outer forward error-correction code
packetizer_compute_dec_msg_len(unsigned int _k,int _crc,int _fec0,int _fec1)60 unsigned int packetizer_compute_dec_msg_len(unsigned int _k,
61 int _crc,
62 int _fec0,
63 int _fec1)
64 {
65 unsigned int n_hat = 0;
66 unsigned int k_hat = 0;
67
68 // check for zero-length packet
69 // TODO : implement faster method
70 while (k_hat < _k) {
71 // compute encoded packet length
72 k_hat = packetizer_compute_enc_msg_len(n_hat, _crc, _fec0, _fec1);
73
74 //
75 if (k_hat == _k)
76 return n_hat;
77 else if (k_hat > _k)
78 return n_hat; // TODO : check this special condition
79 else
80 n_hat++;
81 }
82
83 return 0;
84 }
85
86
87 // create packetizer object
88 //
89 // _n : number of uncoded intput bytes
90 // _crc : error-detecting scheme
91 // _fec0 : inner forward error-correction code
92 // _fec1 : outer forward error-correction code
packetizer_create(unsigned int _n,int _crc,int _fec0,int _fec1)93 packetizer packetizer_create(unsigned int _n,
94 int _crc,
95 int _fec0,
96 int _fec1)
97 {
98 packetizer p = (packetizer) malloc(sizeof(struct packetizer_s));
99
100 p->msg_len = _n;
101 p->packet_len = packetizer_compute_enc_msg_len(_n, _crc, _fec0, _fec1);
102 p->check = _crc;
103 p->crc_length = crc_get_length(p->check);
104
105 // allocate memory for buffers (scale by 8 for soft decoding)
106 p->buffer_len = p->packet_len;
107 p->buffer_0 = (unsigned char*) malloc(8*p->buffer_len);
108 p->buffer_1 = (unsigned char*) malloc(8*p->buffer_len);
109
110 // create plan
111 p->plan_len = 2;
112 p->plan = (struct fecintlv_plan*) malloc((p->plan_len)*sizeof(struct fecintlv_plan));
113
114 // set schemes
115 unsigned int i;
116 unsigned int n0 = _n + p->crc_length;
117 for (i=0; i<p->plan_len; i++) {
118 // set schemes
119 p->plan[i].fs = (i==0) ? _fec0 : _fec1;
120
121 // compute lengths
122 p->plan[i].dec_msg_len = n0;
123 p->plan[i].enc_msg_len = fec_get_enc_msg_length(p->plan[i].fs,
124 p->plan[i].dec_msg_len);
125
126 // create objects
127 p->plan[i].f = fec_create(p->plan[i].fs, NULL);
128 p->plan[i].q = interleaver_create(p->plan[i].enc_msg_len);
129
130 // set interleaver depth to zero if no error correction scheme
131 // is applied to this plan
132 if (p->plan[i].fs == LIQUID_FEC_NONE)
133 interleaver_set_depth(p->plan[i].q, 0);
134
135 // update length
136 n0 = p->plan[i].enc_msg_len;
137 }
138
139 return p;
140 }
141
142 // re-create packetizer object
143 //
144 // _p : initialz packetizer object
145 // _n : number of uncoded intput bytes
146 // _crc : error-detecting scheme
147 // _fec0 : inner forward error-correction code
148 // _fec1 : outer forward error-correction code
packetizer_recreate(packetizer _p,unsigned int _n,int _crc,int _fec0,int _fec1)149 packetizer packetizer_recreate(packetizer _p,
150 unsigned int _n,
151 int _crc,
152 int _fec0,
153 int _fec1)
154 {
155 if (_p == NULL) {
156 // packetizer was never created
157 return packetizer_create(_n, _crc, _fec0, _fec1);
158 }
159
160 // check values
161 if (_p->msg_len == _n &&
162 _p->check == _crc &&
163 _p->plan[0].fs == _fec0 &&
164 _p->plan[1].fs == _fec1 )
165 {
166 // no change; return input pointer
167 return _p;
168 }
169
170 // something has changed; destroy old object and create new one
171 // TODO : rather than completely destroying object, only change values that are necessary
172 packetizer_destroy(_p);
173 return packetizer_create(_n,_crc,_fec0,_fec1);
174 }
175
176 // destroy packetizer object
packetizer_destroy(packetizer _p)177 void packetizer_destroy(packetizer _p)
178 {
179 if (!_p) {
180 return;
181 }
182
183 // free fec, interleaver objects
184 unsigned int i;
185 for (i=0; i<_p->plan_len; i++) {
186 fec_destroy(_p->plan[i].f);
187 interleaver_destroy(_p->plan[i].q);
188 };
189
190 // free plan
191 free(_p->plan);
192
193 // free buffers
194 free(_p->buffer_0);
195 free(_p->buffer_1);
196
197 // free packetizer object
198 free(_p);
199 }
200
201 // print packetizer object internals
packetizer_print(packetizer _p)202 void packetizer_print(packetizer _p)
203 {
204 printf("packetizer [dec: %u, enc: %u]\n", _p->msg_len, _p->packet_len);
205 printf(" : crc %-10u %-10u %-16s\n",
206 _p->msg_len,
207 _p->msg_len + _p->crc_length,
208 crc_scheme_str[_p->check][0]);
209 unsigned int i;
210 for (i=0; i<_p->plan_len; i++) {
211 printf("%4u : fec %-10u %-10u %-16s\n",
212 i,
213 _p->plan[i].dec_msg_len,
214 _p->plan[i].enc_msg_len,
215 fec_scheme_str[_p->plan[i].fs][1]);
216 }
217 }
218
219 // get decoded message length
packetizer_get_dec_msg_len(packetizer _p)220 unsigned int packetizer_get_dec_msg_len(packetizer _p)
221 {
222 return _p->msg_len;
223 }
224
225 // get encoded message length
packetizer_get_enc_msg_len(packetizer _p)226 unsigned int packetizer_get_enc_msg_len(packetizer _p)
227 {
228 return _p->packet_len;
229 }
230
packetizer_get_crc(packetizer _p)231 crc_scheme packetizer_get_crc(packetizer _p)
232 {
233 return _p->check;
234 }
235
packetizer_get_fec0(packetizer _p)236 fec_scheme packetizer_get_fec0(packetizer _p)
237 {
238 return _p->plan[0].fs;
239 }
240
packetizer_get_fec1(packetizer _p)241 fec_scheme packetizer_get_fec1(packetizer _p)
242 {
243 return _p->plan[1].fs;
244 }
245
246 // Execute the packetizer on an input message
247 //
248 // _p : packetizer object
249 // _msg : input message (uncoded bytes)
250 // _pkt : encoded output message
packetizer_encode(packetizer _p,const unsigned char * _msg,unsigned char * _pkt)251 void packetizer_encode(packetizer _p,
252 const unsigned char * _msg,
253 unsigned char * _pkt)
254 {
255 unsigned int i;
256
257 // copy input message to internal buffer[0] (or initialize to zeros)
258 if (_msg != NULL) {
259 // copy user-defined input
260 memmove(_p->buffer_0, _msg, _p->msg_len);
261 } else {
262 // initialize with zeros
263 memset(_p->buffer_0, 0x00, _p->msg_len);
264 }
265
266 // compute crc, append to buffer
267 unsigned int key = crc_generate_key(_p->check, _p->buffer_0, _p->msg_len);
268 for (i=0; i<_p->crc_length; i++) {
269 // append byte to buffer
270 _p->buffer_0[_p->msg_len+_p->crc_length-i-1] = key & 0xff;
271
272 // shift key by 8 bits
273 key >>= 8;
274 }
275
276 // whiten input sequence
277 scramble_data(_p->buffer_0, _p->msg_len + _p->crc_length);
278
279 // execute fec/interleaver plans
280 for (i=0; i<_p->plan_len; i++) {
281 // run the encoder: buffer[0] > buffer[1]
282 fec_encode(_p->plan[i].f,
283 _p->plan[i].dec_msg_len,
284 _p->buffer_0,
285 _p->buffer_1);
286
287 // run the interleaver: buffer[1] > buffer[0]
288 interleaver_encode(_p->plan[i].q,
289 _p->buffer_1,
290 _p->buffer_0);
291 }
292
293 // copy result to output
294 memmove(_pkt, _p->buffer_0, _p->packet_len);
295 }
296
297 // Execute the packetizer to decode an input message, return validity
298 // check of resulting data
299 //
300 // _p : packetizer object
301 // _pkt : input message (coded bytes)
302 // _msg : decoded output message
packetizer_decode(packetizer _p,const unsigned char * _pkt,unsigned char * _msg)303 int packetizer_decode(packetizer _p,
304 const unsigned char * _pkt,
305 unsigned char * _msg)
306 {
307 // copy coded message to internal buffer[0]
308 memmove(_p->buffer_0, _pkt, _p->packet_len);
309
310 // execute fec/interleaver plans
311 unsigned int i;
312 for (i=_p->plan_len; i>0; i--) {
313 // run the de-interleaver: buffer[0] > buffer[1]
314 interleaver_decode(_p->plan[i-1].q,
315 _p->buffer_0,
316 _p->buffer_1);
317
318 // run the decoder: buffer[1] > buffer[0]
319 fec_decode(_p->plan[i-1].f,
320 _p->plan[i-1].dec_msg_len,
321 _p->buffer_1,
322 _p->buffer_0);
323 }
324
325 // remove sequence whitening
326 unscramble_data(_p->buffer_0, _p->msg_len + _p->crc_length);
327
328 // strip crc, validate message
329 unsigned int key = 0;
330 for (i=0; i<_p->crc_length; i++) {
331 key <<= 8;
332
333 key |= _p->buffer_0[_p->msg_len+i];
334 }
335
336 // copy result to output
337 memmove(_msg, _p->buffer_0, _p->msg_len);
338
339 // return crc validity
340 return crc_validate_message(_p->check,
341 _p->buffer_0,
342 _p->msg_len,
343 key);
344 }
345
346 // Execute the packetizer to decode an input message, return validity
347 // check of resulting data
348 //
349 // _p : packetizer object
350 // _pkt : input message (coded soft bits)
351 // _msg : decoded output message
packetizer_decode_soft(packetizer _p,const unsigned char * _pkt,unsigned char * _msg)352 int packetizer_decode_soft(packetizer _p,
353 const unsigned char * _pkt,
354 unsigned char * _msg)
355 {
356 // copy coded message to internal buffer[0]
357 memmove(_p->buffer_0, _pkt, 8*_p->packet_len);
358
359 //
360 // decode outer level using soft decoding
361 //
362
363 // run the de-interleaver: buffer[0] > buffer[1]
364 interleaver_decode_soft(_p->plan[1].q,
365 _p->buffer_0,
366 _p->buffer_1);
367
368 // run the decoder: buffer[1] > buffer[0]
369 fec_decode_soft(_p->plan[1].f,
370 _p->plan[1].dec_msg_len,
371 _p->buffer_1,
372 _p->buffer_0);
373
374 //
375 // decode inner level using hard decoding
376 //
377
378 // run the de-interleaver: buffer[0] > buffer[1]
379 interleaver_decode(_p->plan[0].q,
380 _p->buffer_0,
381 _p->buffer_1);
382
383 // run the decoder: buffer[1] > buffer[0]
384 fec_decode(_p->plan[0].f,
385 _p->plan[0].dec_msg_len,
386 _p->buffer_1,
387 _p->buffer_0);
388
389 // remove sequence whitening
390 unscramble_data(_p->buffer_0, _p->msg_len + _p->crc_length);
391
392 // strip crc, validate message
393 unsigned int key = 0;
394 unsigned int i;
395 for (i=0; i<_p->crc_length; i++) {
396 key <<= 8;
397
398 key |= _p->buffer_0[_p->msg_len+i];
399 }
400
401 // copy result to output
402 memmove(_msg, _p->buffer_0, _p->msg_len);
403
404 // return crc validity
405 return crc_validate_message(_p->check,
406 _p->buffer_0,
407 _p->msg_len,
408 key);
409 }
410
packetizer_set_scheme(packetizer _p,int _fec0,int _fec1)411 void packetizer_set_scheme(packetizer _p, int _fec0, int _fec1)
412 {
413 //
414 }
415
416 //
417 // internal methods
418 //
419
packetizer_realloc_buffers(packetizer _p,unsigned int _len)420 void packetizer_realloc_buffers(packetizer _p, unsigned int _len)
421 {
422 _p->buffer_len = _len;
423 _p->buffer_0 = (unsigned char*) realloc(_p->buffer_0, _p->buffer_len);
424 _p->buffer_1 = (unsigned char*) realloc(_p->buffer_1, _p->buffer_len);
425 }
426
427