1 /*---------------------------------------------------------------------------*\
2
3 FILE........: freedv_api.c
4 AUTHOR......: David Rowe
5 DATE CREATED: August 2014
6
7 Library of API functions that implement FreeDV "modes", useful for
8 embedding FreeDV in other programs. Please see:
9
10 1. README_freedv.md
11 2. Notes function use in freedv_api.c
12 3. The sample freedv_tx.c and freedv_rx.c programs
13
14 \*---------------------------------------------------------------------------*/
15
16 /*
17 Copyright (C) 2014 David Rowe
18
19 All rights reserved.
20
21 This program is free software; you can redistribute it and/or modify
22 it under the terms of the GNU Lesser General Public License version 2.1, as
23 published by the Free Software Foundation. This program is
24 distributed in the hope that it will be useful, but WITHOUT ANY
25 WARRANTY; without even the implied warranty of MERCHANTABILITY or
26 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
27 License for more details.
28
29 You should have received a copy of the GNU Lesser General Public License
30 along with this program; if not, see <http://www.gnu.org/licenses/>.
31 */
32
33 #include <assert.h>
34 #include <stdlib.h>
35 #include <stdbool.h>
36 #include <stdint.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <math.h>
40
41 #include "fsk.h"
42 #include "fmfsk.h"
43 #include "codec2.h"
44 #include "codec2_fdmdv.h"
45 #include "fdmdv_internal.h"
46 #include "varicode.h"
47 #include "freedv_api.h"
48 #include "freedv_api_internal.h"
49 #include "freedv_vhf_framing.h"
50 #include "comp_prim.h"
51
52 #include "codec2_ofdm.h"
53 #include "ofdm_internal.h"
54 #include "mpdecode_core.h"
55 #include "gp_interleaver.h"
56 #include "interldpc.h"
57
58 #include "debug_alloc.h"
59
60 #define VERSION 14 /* The API version number. The first version
61 is 10. Increment if the API changes in a
62 way that would require changes by the API
63 user. */
64 /*
65 * Version 10 Initial version August 2, 2015.
66 * Version 11 September 2015
67 * Added: freedv_zero_total_bit_errors(), freedv_get_sync()
68 * Changed all input and output sample rates to 8000 sps. Rates for FREEDV_MODE_700 and 700B were 7500.
69 * Version 12 August 2018
70 * Added OFDM configuration switch structure
71 * Version 13 November 2019
72 * Removed 700 and 700B modes
73 * Version 14 May 2020
74 * Number of returned speech samples can vary, use freedv_get_n_max_speech_samples() to allocate
75 * buffers.
76 */
77
78 char *ofdm_statemode[] = {"search","trial","synced"};
79
80 char *rx_sync_flags_to_text[] = {
81 "----",
82 "---T",
83 "--S-",
84 "--ST",
85 "-B--",
86 "-B-T",
87 "-BS-",
88 "-BST",
89 "E---",
90 "E--T",
91 "E-S-",
92 "E-ST",
93 "EB--",
94 "EB-T",
95 "EBS-",
96 "EBST"};
97
98 /*---------------------------------------------------------------------------* \
99
100 FUNCTION....: freedv_open
101 AUTHOR......: David Rowe
102 DATE CREATED: 3 August 2014
103
104 Call this first to initialise. Returns NULL if initialisation
105 fails. If a malloc() or calloc() fails in general asserts() will
106 fire.
107
108 \*---------------------------------------------------------------------------*/
109
freedv_open(int mode)110 struct freedv *freedv_open(int mode) {
111 struct freedv_advanced adv = {0,2,100,8000,1000,200, "H_256_512_4"};
112 if (mode == FREEDV_MODE_FSK_LDPC)
113 return freedv_open_advanced(mode, &adv);
114 else
115 return freedv_open_advanced(mode, NULL);
116
117 }
118
freedv_open_advanced(int mode,struct freedv_advanced * adv)119 struct freedv *freedv_open_advanced(int mode, struct freedv_advanced *adv) {
120 struct freedv *f;
121
122 assert(FREEDV_PEAK == OFDM_PEAK);
123 assert(FREEDV_VARICODE_MAX_BITS == VARICODE_MAX_BITS);
124
125 if ((FDV_MODE_ACTIVE( FREEDV_MODE_1600, mode) ||
126 FDV_MODE_ACTIVE( FREEDV_MODE_700C, mode) ||
127 FDV_MODE_ACTIVE( FREEDV_MODE_700D, mode) ||
128 FDV_MODE_ACTIVE( FREEDV_MODE_700E, mode) ||
129 FDV_MODE_ACTIVE( FREEDV_MODE_2400A, mode) ||
130 FDV_MODE_ACTIVE( FREEDV_MODE_2400B, mode) ||
131 FDV_MODE_ACTIVE( FREEDV_MODE_800XA, mode) ||
132 FDV_MODE_ACTIVE( FREEDV_MODE_2020, mode) ||
133 FDV_MODE_ACTIVE( FREEDV_MODE_FSK_LDPC, mode) ||
134 FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, mode) ||
135 FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, mode) ||
136 FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, mode)) == false) return NULL;
137
138 /* set everything to zero just in case */
139 f = (struct freedv*)CALLOC(1, sizeof(struct freedv));
140 if (f == NULL) return NULL;
141
142 f->mode = mode;
143
144 if (FDV_MODE_ACTIVE( FREEDV_MODE_1600, mode)) freedv_1600_open(f);
145 if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, mode)) freedv_700c_open(f);
146 if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, mode)) freedv_ofdm_voice_open(f, "700D");
147 if (FDV_MODE_ACTIVE( FREEDV_MODE_700E, mode)) freedv_ofdm_voice_open(f, "700E");
148 #ifdef __LPCNET__
149 if (FDV_MODE_ACTIVE( FREEDV_MODE_2020, mode)) freedv_2020_open(f);
150 #endif
151 if (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, mode)) freedv_2400a_open(f);
152 if (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, mode)) freedv_2400b_open(f);
153 if (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, mode)) freedv_800xa_open(f);
154 if (FDV_MODE_ACTIVE( FREEDV_MODE_FSK_LDPC, mode)) freedv_fsk_ldpc_open(f, adv);
155 if (FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, mode)) freedv_ofdm_data_open(f);
156 if (FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, mode)) freedv_ofdm_data_open(f);
157 if (FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, mode)) freedv_ofdm_data_open(f);
158
159 varicode_decode_init(&f->varicode_dec_states, 1);
160
161 return f;
162 }
163
164 /*---------------------------------------------------------------------------*\
165
166 FUNCTION....: freedv_close
167 AUTHOR......: David Rowe
168 DATE CREATED: 3 August 2014
169
170 Call to shut down a freedv instance and free memory.
171
172 \*---------------------------------------------------------------------------*/
173
freedv_close(struct freedv * freedv)174 void freedv_close(struct freedv *freedv) {
175 assert(freedv != NULL);
176
177 FREE(freedv->tx_payload_bits);
178 FREE(freedv->rx_payload_bits);
179 if (freedv->codec2) codec2_destroy(freedv->codec2);
180
181 if (FDV_MODE_ACTIVE(FREEDV_MODE_1600, freedv->mode)) {
182 FREE(freedv->fdmdv_bits);
183 FREE(freedv->fdmdv_tx_bits);
184 FREE(freedv->fdmdv_rx_bits);
185 fdmdv_destroy(freedv->fdmdv);
186 }
187
188 if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, freedv->mode)) {
189 cohpsk_destroy(freedv->cohpsk);
190 quisk_filt_destroy(freedv->ptFilter8000to7500);
191 FREE(freedv->ptFilter8000to7500);
192 quisk_filt_destroy(freedv->ptFilter7500to8000);
193 FREE(freedv->ptFilter7500to8000);
194 }
195
196 if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, freedv->mode) ||
197 FDV_MODE_ACTIVE( FREEDV_MODE_700E, freedv->mode)) {
198 FREE(freedv->rx_syms);
199 FREE(freedv->rx_amps);
200 FREE(freedv->ldpc);
201 ofdm_destroy(freedv->ofdm);
202 }
203
204 if (FDV_MODE_ACTIVE( FREEDV_MODE_2020, freedv->mode)) {
205 FREE(freedv->codeword_symbols);
206 FREE(freedv->codeword_amps);
207 FREE(freedv->ldpc);
208 FREE(freedv->passthrough_2020);
209 ofdm_destroy(freedv->ofdm);
210 #ifdef __LPCNET__
211 lpcnet_freedv_destroy(freedv->lpcnet);
212 #endif
213 }
214
215 if (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, freedv->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_800XA, freedv->mode)){
216 fsk_destroy(freedv->fsk);
217 fvhff_destroy_deframer(freedv->deframer);
218 }
219
220 if (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, freedv->mode)) {
221 fmfsk_destroy(freedv->fmfsk);
222 fvhff_destroy_deframer(freedv->deframer);
223 }
224
225 if (FDV_MODE_ACTIVE( FREEDV_MODE_FSK_LDPC, freedv->mode)) {
226 fsk_destroy(freedv->fsk);
227 FREE(freedv->ldpc);
228 FREE(freedv->frame_llr);
229 FREE(freedv->twoframes_llr);
230 FREE(freedv->twoframes_hard);
231 }
232
233 if (FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, freedv->mode) ||
234 FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, freedv->mode) ||
235 FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, freedv->mode))
236 {
237 FREE(freedv->rx_syms);
238 FREE(freedv->rx_amps);
239 FREE(freedv->ldpc);
240 ofdm_destroy(freedv->ofdm);
241 }
242
243 FREE(freedv);
244 }
245
246
247 /* helper function, unpacked bits are much easier to work with inside the modem */
248
codec2_encode_upacked(struct freedv * f,uint8_t unpacked_bits[],short speech_in[])249 static void codec2_encode_upacked(struct freedv *f, uint8_t unpacked_bits[], short speech_in[]) {
250 int n_packed = (f->bits_per_codec_frame + 7) / 8;
251 uint8_t packed_codec_bits[n_packed];
252
253 codec2_encode(f->codec2, packed_codec_bits, speech_in);
254 freedv_unpack(unpacked_bits, packed_codec_bits, f->bits_per_codec_frame);
255 }
256
is_ofdm_mode(struct freedv * f)257 static int is_ofdm_mode(struct freedv *f) {
258 return FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) ||
259 FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) ||
260 FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode) ||
261 FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, f->mode) ||
262 FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, f->mode) ||
263 FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, f->mode);
264 }
265
is_ofdm_data_mode(struct freedv * f)266 static int is_ofdm_data_mode(struct freedv *f) {
267 return FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, f->mode) ||
268 FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, f->mode) ||
269 FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, f->mode);
270 }
271
272 /*---------------------------------------------------------------------------*\
273
274 FUNCTION....: freedv_tx
275 AUTHOR......: David Rowe
276 DATE CREATED: 3 August 2014
277
278 Takes a frame of input speech samples, encodes and modulates them to
279 produce a frame of modem samples that can be sent to the
280 transmitter. See freedv_tx.c for an example.
281
282 speech_in[] is sampled at freedv_get_speech_sample_rate() Hz, and the
283 user must supply a block of exactly
284 freedv_get_n_speech_samples(). The speech_in[] level should be such
285 that the peak speech level is between +/- 16384 and +/- 32767.
286
287 The FDM modem signal mod_out[] is sampled at
288 freedv_get_modem_sample_rate() and is always exactly
289 freedv_get_n_nom_modem_samples() long. mod_out[] will be scaled
290 such that the peak level is just less than +/-32767.
291
292 The FreeDV 1600/700C/700D/2020 waveforms have a crest factor of
293 around 10dB, similar to SSB. These modes are usually operated at a
294 "backoff" of 8dB. Adjust the power amplifier drive so that the
295 average power is 8dB less than the peak power of the PA. For
296 example, on a radio rated at 100W PEP for SSB, the average FreeDV
297 power is typically 20W.
298
299 Caution - some PAs cannot handle a high continuous power. A
300 conservative level is 20W average for a 100W PEP rated PA.
301
302 The FreeDV 2400A/800XA modes are constant amplitude, designed for
303 Class C PAs. They have a crest factor of 3dB. If using a SSB PA,
304 adjust the drive so you average power is within the limits of your PA
305 (e.g. 20W average for a 100W PA).
306
307 \*---------------------------------------------------------------------------*/
308
309 /* real-valued short output */
310
freedv_tx(struct freedv * f,short mod_out[],short speech_in[])311 void freedv_tx(struct freedv *f, short mod_out[], short speech_in[]) {
312 assert(f != NULL);
313 COMP tx_fdm[f->n_nom_modem_samples];
314 int i;
315
316 /* FSK and MEFSK/FMFSK modems work only on real samples. It's simpler to just
317 * stick them in the real sample tx/rx functions than to add a comp->real converter
318 * to comptx */
319
320 if ((FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode))){
321 /* 800XA has two codec frames per modem frame */
322 if(FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)){
323 codec2_encode(f->codec2, &f->tx_payload_bits[0], &speech_in[ 0]);
324 codec2_encode(f->codec2, &f->tx_payload_bits[4], &speech_in[320]);
325 }else{
326 codec2_encode(f->codec2, f->tx_payload_bits, speech_in);
327 }
328 freedv_tx_fsk_voice(f, mod_out);
329 } else {
330 freedv_comptx(f, tx_fdm, speech_in);
331 for(i=0; i<f->n_nom_modem_samples; i++)
332 mod_out[i] = tx_fdm[i].real;
333 }
334 }
335
336
337 /* complex float output samples version */
338
freedv_comptx(struct freedv * f,COMP mod_out[],short speech_in[])339 void freedv_comptx(struct freedv *f, COMP mod_out[], short speech_in[]) {
340 assert(f != NULL);
341
342 assert((FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) ||
343 (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)) ||
344 (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode)) ||
345 (FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode)));
346
347 if (FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode)) {
348 codec2_encode_upacked(f, f->tx_payload_bits, speech_in);
349 freedv_comptx_fdmdv_1600(f, mod_out);
350 }
351
352 /* all these modes need to pack a bunch of codec frames into one modem frame ... */
353
354 if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) {
355 for (int j=0; j<f->n_codec_frames; j++) {
356 codec2_encode_upacked(f, f->tx_payload_bits+j*f->bits_per_codec_frame, speech_in);
357 speech_in += codec2_samples_per_frame(f->codec2);
358 }
359 freedv_comptx_700c(f, mod_out);
360 }
361
362 if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode)) {
363
364 /* buffer up bits until we get enough encoded bits for interleaver */
365
366 for (int j=0; j<f->n_codec_frames; j++) {
367 int offset = j*f->bits_per_codec_frame;
368 codec2_encode_upacked(f, f->tx_payload_bits + offset, speech_in);
369 speech_in += codec2_samples_per_frame(f->codec2);
370 }
371
372 freedv_comptx_ofdm(f, mod_out);
373 }
374
375 #ifdef __LPCNET__
376 if (FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode)) {
377
378 /* buffer up bits until we get enough encoded bits for interleaver */
379
380 for (int j=0; j<f->n_codec_frames; j++) {
381 int offset = j*f->bits_per_codec_frame;
382 lpcnet_enc(f->lpcnet, speech_in, (char*)f->tx_payload_bits + offset);
383 speech_in += lpcnet_samples_per_frame(f->lpcnet);
384 }
385
386 freedv_comptx_2020(f, mod_out);
387 }
388 #endif
389
390 /* 2400 A and B are handled by the real-mode TX */
391 if(FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)){
392 codec2_encode(f->codec2, f->tx_payload_bits, speech_in);
393 freedv_comptx_fsk_voice(f, mod_out);
394 }
395 }
396
397
398 /* pack bits */
freedv_pack(uint8_t * bytes,uint8_t * bits,int nbits)399 void freedv_pack(uint8_t *bytes, uint8_t *bits, int nbits) {
400 memset(bytes, 0, (nbits+7)/8);
401 int bit = 7, byte = 0;
402 for(int i=0; i<nbits; i++) {
403 bytes[byte] |= bits[i] << bit;
404 bit--;
405 if (bit < 0) {
406 bit = 7;
407 byte++;
408 }
409 }
410 }
411
412 /* unpack bits, MSB first */
freedv_unpack(uint8_t * bits,uint8_t * bytes,int nbits)413 void freedv_unpack(uint8_t *bits, uint8_t *bytes, int nbits) {
414 int bit = 7, byte = 0;
415 for(int i=0; i<nbits; i++) {
416 bits[i] = (bytes[byte] >> bit) & 0x1;
417 bit--;
418 if (bit < 0) {
419 bit = 7;
420 byte++;
421 }
422 }
423 }
424
425 /* compute the CRC16 of a frame of unpacked bits */
freedv_crc16_unpacked(unsigned char unpacked_bits[],int nbits)426 unsigned short freedv_crc16_unpacked(unsigned char unpacked_bits[], int nbits) {
427 assert((nbits % 8) == 0);
428 int nbytes = nbits/8;
429 uint8_t packed_bytes[nbytes];
430 freedv_pack(packed_bytes, unpacked_bits, nbits);
431 return freedv_gen_crc16(packed_bytes, nbytes);
432 }
433
434 /* Return non-zero if CRC16 of a frame of unpacked bits is correct */
freedv_check_crc16_unpacked(unsigned char unpacked_bits[],int nbits)435 int freedv_check_crc16_unpacked(unsigned char unpacked_bits[], int nbits) {
436 assert((nbits % 8) == 0);
437 int nbytes = nbits/8;
438 uint8_t packed_bytes[nbytes];
439 freedv_pack(packed_bytes, unpacked_bits, nbits);
440 uint16_t tx_crc16 = (packed_bytes[nbytes-2] << 8) | packed_bytes[nbytes-1];
441 uint16_t rx_crc16 = freedv_crc16_unpacked(unpacked_bits, nbits - 16);
442 return tx_crc16 == rx_crc16;
443 }
444
445 /* send raw frames of bytes, or speech data that was compressed externally, complex float output */
freedv_rawdatacomptx(struct freedv * f,COMP mod_out[],unsigned char * packed_payload_bits)446 void freedv_rawdatacomptx(struct freedv *f, COMP mod_out[], unsigned char *packed_payload_bits) {
447 assert(f != NULL);
448
449 freedv_unpack(f->tx_payload_bits, packed_payload_bits, f->bits_per_modem_frame);
450
451 if (FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode)) freedv_comptx_fdmdv_1600(f, mod_out);
452 if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) freedv_comptx_700c(f, mod_out);
453 if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) ||
454 FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, f->mode) ||
455 FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, f->mode) ||
456 FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, f->mode)) freedv_comptx_ofdm(f, mod_out);
457
458 if (FDV_MODE_ACTIVE( FREEDV_MODE_FSK_LDPC, f->mode)) {
459 freedv_tx_fsk_ldpc_data(f, mod_out);
460 }
461 }
462
463
464 /* send raw frames of bytes, or speech data that was compressed externally, real short output */
freedv_rawdatatx(struct freedv * f,short mod_out[],unsigned char * packed_payload_bits)465 void freedv_rawdatatx(struct freedv *f, short mod_out[], unsigned char *packed_payload_bits) {
466 assert(f != NULL);
467 COMP mod_out_comp[f->n_nat_modem_samples];
468
469 /* Some FSK modes used packed bits, and coincidentally support real samples natively */
470 if(FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode) ||
471 FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode) ) {
472 freedv_codec_frames_from_rawdata(f, f->tx_payload_bits, packed_payload_bits);
473 freedv_tx_fsk_voice(f, mod_out);
474 return; /* output is already real */
475 }
476
477 freedv_rawdatacomptx(f, mod_out_comp, packed_payload_bits);
478
479 /* convert complex to real */
480 for(int i=0; i<f->n_nat_modem_samples; i++)
481 mod_out[i] = mod_out_comp[i].real;
482 }
483
freedv_rawdatapreamblecomptx(struct freedv * f,COMP mod_out[])484 int freedv_rawdatapreamblecomptx(struct freedv *f, COMP mod_out[]) {
485 assert(f != NULL);
486 int npreamble_samples = 0;
487
488 if (f->mode == FREEDV_MODE_FSK_LDPC) {
489 struct FSK *fsk = f->fsk;
490
491 int npreamble_symbols = 50*(fsk->mode>>1);
492 int npreamble_bits = npreamble_symbols*(fsk->mode>>1);
493 npreamble_samples = fsk->Ts*npreamble_symbols;
494 //fprintf(stderr, "npreamble_symbols: %d npreamble_bits: %d npreamble_samples: %d Nbits: %d N: %d\n",
495 //npreamble_symbols, npreamble_bits, npreamble_samples, fsk->Nbits, fsk->N);
496
497 assert(npreamble_samples < f->n_nom_modem_samples); /* caller probably using an array of this size */
498 freedv_tx_fsk_ldpc_data_preamble(f, mod_out, npreamble_bits, npreamble_samples);
499 } else if (is_ofdm_data_mode(f)) {
500 struct OFDM *ofdm = f->ofdm;
501 complex float *tx_preamble = (complex float*)mod_out;
502 memcpy(tx_preamble, ofdm->tx_preamble, sizeof(COMP)*ofdm->samplesperframe);
503 ofdm_hilbert_clipper(ofdm, tx_preamble, ofdm->samplesperframe);
504 npreamble_samples = ofdm->samplesperframe;
505 }
506
507 return npreamble_samples;
508 }
509
freedv_rawdatapreambletx(struct freedv * f,short mod_out[])510 int freedv_rawdatapreambletx(struct freedv *f, short mod_out[]) {
511 assert(f != NULL);
512 COMP mod_out_comp[f->n_nat_modem_samples];
513
514 int npreamble_samples = freedv_rawdatapreamblecomptx(f, mod_out_comp);
515 assert(npreamble_samples <= f->n_nat_modem_samples);
516
517 /* convert complex to real */
518 for(int i=0; i<npreamble_samples; i++)
519 mod_out[i] = mod_out_comp[i].real;
520
521 return npreamble_samples;
522 }
523
freedv_rawdatapostamblecomptx(struct freedv * f,COMP mod_out[])524 int freedv_rawdatapostamblecomptx(struct freedv *f, COMP mod_out[]) {
525 assert(f != NULL);
526 int npostamble_samples = 0;
527
528 if (is_ofdm_data_mode(f)) {
529 struct OFDM *ofdm = f->ofdm;
530 complex float *tx_postamble = (complex float*)mod_out;
531 memcpy(tx_postamble, ofdm->tx_postamble, sizeof(COMP)*ofdm->samplesperframe);
532 ofdm_hilbert_clipper(ofdm, tx_postamble, ofdm->samplesperframe);
533 npostamble_samples = ofdm->samplesperframe;
534 }
535
536 return npostamble_samples;
537 }
538
freedv_rawdatapostambletx(struct freedv * f,short mod_out[])539 int freedv_rawdatapostambletx(struct freedv *f, short mod_out[]) {
540 assert(f != NULL);
541 COMP mod_out_comp[f->n_nat_modem_samples];
542
543 int npostamble_samples = freedv_rawdatapostamblecomptx(f, mod_out_comp);
544 assert(npostamble_samples <= f->n_nat_modem_samples);
545
546 /* convert complex to real */
547 for(int i=0; i<npostamble_samples; i++)
548 mod_out[i] = mod_out_comp[i].real;
549
550 return npostamble_samples;
551 }
552
553 /* VHF packet data tx function */
freedv_datatx(struct freedv * f,short mod_out[])554 void freedv_datatx (struct freedv *f, short mod_out[]) {
555 assert(f != NULL);
556 if (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)) {
557 freedv_tx_fsk_data(f, mod_out);
558 }
559 }
560
561
562 /* VHF packet data: returns how many tx frames are queued up but not sent yet */
freedv_data_ntxframes(struct freedv * f)563 int freedv_data_ntxframes (struct freedv *f) {
564 assert(f != NULL);
565 if (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)) {
566 if (f->deframer->fdc)
567 return freedv_data_get_n_tx_frames(f->deframer->fdc, 8);
568 } else if (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)) {
569 if (f->deframer->fdc)
570 return freedv_data_get_n_tx_frames(f->deframer->fdc, 6);
571 }
572 return 0;
573 }
574
freedv_nin(struct freedv * f)575 int freedv_nin(struct freedv *f) {
576 if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode))
577 // For mode 700C, the input rate is 8000 sps, but the modem rate is 7500 sps
578 // For mode 700C, we request a larger number of Rx samples that will be decimated to f->nin samples
579 return (16 * f->nin + f->ptFilter8000to7500->decim_index) / 15;
580 else
581 return f->nin;
582 }
583
freedv_codec_frames_from_rawdata(struct freedv * f,unsigned char * codec_frames,unsigned char * rawdata)584 int freedv_codec_frames_from_rawdata(struct freedv *f, unsigned char *codec_frames, unsigned char *rawdata)
585 {
586 int cbit = 7;
587 int cbyte = 0;
588 int rbit = 7;
589 int rbyte = 0;
590 int modem_bits = freedv_get_bits_per_modem_frame(f);
591 int codec_bits = freedv_get_bits_per_codec_frame(f);
592 int nr_cbits = 0;
593 int i;
594
595 codec_frames[0] = 0;
596 for (i = 0; i < modem_bits; i++) {
597 codec_frames[cbyte] |= ((rawdata[rbyte] >> rbit) & 1) << cbit;
598
599 rbit--;
600 if (rbit < 0) {
601 rbit = 7;
602 rbyte++;
603 }
604
605 cbit--;
606 if (cbit < 0) {
607 cbit = 7;
608 cbyte++;
609 codec_frames[cbyte] = 0;
610 }
611 nr_cbits++;
612 if (nr_cbits == codec_bits) {
613 if (cbit) {
614 cbyte++;
615 codec_frames[cbyte] = 0;
616 }
617 cbit = 7;
618 nr_cbits = 0;
619 }
620 }
621 return f->n_codec_frames;
622 }
623
freedv_rawdata_from_codec_frames(struct freedv * f,unsigned char * rawdata,unsigned char * codec_frames)624 int freedv_rawdata_from_codec_frames(struct freedv *f, unsigned char *rawdata, unsigned char *codec_frames)
625 {
626 int cbit = 7;
627 int cbyte = 0;
628 int rbit = 7;
629 int rbyte = 0;
630 int modem_bits = freedv_get_bits_per_modem_frame(f);
631 int codec_bits = freedv_get_bits_per_codec_frame(f);
632 int nr_cbits = 0;
633 int i;
634
635 rawdata[rbyte] = 0;
636 for (i = 0; i < modem_bits; i++) {
637 rawdata[rbyte] |= ((codec_frames[cbyte] >> cbit) & 1) << rbit;
638
639 rbit--;
640 if (rbit < 0) {
641 rbit = 7;
642 rbyte++;
643 rawdata[rbyte] = 0;
644 }
645
646 cbit--;
647 if (cbit < 0) {
648 cbit = 7;
649 cbyte++;
650 }
651
652 nr_cbits++;
653 if (nr_cbits == codec_bits) {
654 if (cbit)
655 cbyte++;
656 cbit = 7;
657 nr_cbits = 0;
658 }
659 }
660 return f->n_codec_frames;
661 }
662
663
664 /*---------------------------------------------------------------------------*\
665
666 FUNCTION....: freedv_rx
667 AUTHOR......: David Rowe
668 DATE CREATED: 3 August 2014
669
670 Takes samples from the radio receiver, demodulates and FEC decodes
671 them, producing a frame of decoded speech samples. See freedv_rx.c
672 for an example.
673
674 demod_in[] is a block of received samples sampled at
675 freedv_get_modem_sample_rate(). To account for difference in the
676 transmit and receive sample clock frequencies, the number of
677 demod_in[] samples is time varying. You MUST call freedv_nin()
678 BEFORE EACH call to freedv_rx() and pass exactly that many samples
679 to this function:
680
681 short demod_in[freedv_get_n_max_modem_samples(f)];
682 short speech_out[freedv_get_n_max_speech_samples(f)];
683
684 nin = freedv_nin(f);
685 while(fread(demod_in, sizeof(short), nin, fin) == nin) {
686 nout = freedv_rx(f, speech_out, demod_in);
687 fwrite(speech_out, sizeof(short), nout, fout);
688 nin = freedv_nin(f);
689 }
690
691 To help set your buffer sizes, The maximum value of freedv_nin() is
692 freedv_get_n_max_modem_samples().
693
694 freedv_rx() returns the number of output speech samples available in
695 speech_out[], which is sampled at freedv_get_speech_sample_rate(f).
696 You should ALWAYS check the return value of freedv_rx(), and read
697 EXACTLY that number of speech samples from speech_out[].
698
699 Not every call to freedv_rx will return speech samples; in some
700 modes several modem frames are processed before speech samples are
701 returned. When squelch is active, zero samples may be returned.
702
703 1600 and 700D mode: When out of sync, the number of output speech
704 samples returned will be freedv_nin(). When in sync to a valid
705 FreeDV 1600 signal, the number of output speech samples will
706 alternate between freedv_get_n_speech_samples() and 0.
707
708 The peak level of demod_in[] is not critical, as the demod works
709 well over a wide range of amplitude scaling. However avoid clipping
710 (overload, or samples pinned to +/- 32767). speech_out[] will peak
711 at just less than +/-32767.
712
713 When squelch is disabled, this function echoes the demod_in[]
714 samples to speech_out[]. This allows the user to listen to the
715 channel, which is useful for tuning FreeDV signals or reception of
716 non-FreeDV signals.
717
718 \*---------------------------------------------------------------------------*/
719
freedv_rx(struct freedv * f,short speech_out[],short demod_in[])720 int freedv_rx(struct freedv *f, short speech_out[], short demod_in[]) {
721 assert(f != NULL);
722 int i;
723 int nin = freedv_nin(f);
724 f->nin_prev = nin;
725
726 assert(nin <= f->n_max_modem_samples);
727
728 /* FSK RX happens in real floats, so convert to those and call their demod here */
729 if( (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)) ){
730 float rx_float[f->n_max_modem_samples];
731 for(i=0; i<nin; i++) {
732 rx_float[i] = ((float)demod_in[i]);
733 }
734 return freedv_floatrx(f,speech_out,rx_float);
735 }
736
737 if ( (FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode))
738 || (FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode))) {
739
740 float gain = 1.0f;
741
742 assert(nin <= f->n_max_modem_samples);
743 COMP rx_fdm[f->n_max_modem_samples];
744
745 for(i=0; i<nin; i++) {
746 rx_fdm[i].real = gain*(float)demod_in[i];
747 rx_fdm[i].imag = 0.0f;
748 }
749 return freedv_comprx(f, speech_out, rx_fdm);
750 }
751
752 /* special low memory version for 700D, to help with stm32 port */
753 if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode)) {
754 float gain = 2.0f; /* keep levels the same as Octave simulations and C unit tests for real signals */
755 return freedv_shortrx(f, speech_out, demod_in, gain);
756 }
757
758 assert(1); /* should never get here */
759 return 0;
760 }
761
762 /* complex sample input version from the radio */
763
freedv_comprx(struct freedv * f,short speech_out[],COMP demod_in[])764 int freedv_comprx(struct freedv *f, short speech_out[], COMP demod_in[]) {
765 assert(f != NULL);
766 assert(f->nin <= f->n_max_modem_samples);
767 int rx_status = 0;
768 f->nin_prev = freedv_nin(f);
769
770 if (FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode)) {
771 rx_status = freedv_comprx_fdmdv_1600(f, demod_in);
772 }
773 if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) {
774 rx_status = freedv_comprx_700c(f, demod_in);
775 }
776
777 if( (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode))) {
778 rx_status = freedv_comprx_fsk(f, demod_in);
779 }
780
781 if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode)) {
782 rx_status = freedv_comp_short_rx_ofdm(f, (void*)demod_in, 0, 2.0f); // was 1.0 ??
783 }
784
785 if (FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode)) {
786 #ifdef __LPCNET__
787 rx_status = freedv_comprx_2020(f, demod_in);
788 #endif
789 }
790
791 short demod_in_short[f->nin_prev];
792
793 for(int i=0; i<f->nin_prev; i++)
794 demod_in_short[i] = demod_in[i].real;
795
796 return freedv_bits_to_speech(f, speech_out, demod_in_short, rx_status);
797 }
798
799 /* memory efficient real short version - just for 700D on the SM1000 */
800
freedv_shortrx(struct freedv * f,short speech_out[],short demod_in[],float gain)801 int freedv_shortrx(struct freedv *f, short speech_out[], short demod_in[], float gain) {
802 assert(f != NULL);
803 int rx_status = 0;
804 f->nin_prev = f->nin;
805
806 // At this stage short interface only supported for 700D, to help
807 // memory requirements on stm32
808 assert((f->mode == FREEDV_MODE_700D) || (f->mode == FREEDV_MODE_700E));
809 assert(f->nin <= f->n_max_modem_samples);
810
811 if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode)) {
812 rx_status = freedv_comp_short_rx_ofdm(f, (void*)demod_in, 1, gain);
813 }
814
815 return freedv_bits_to_speech(f, speech_out, demod_in, rx_status);
816 }
817
818
819 /* helper function, unpacked bits are much easier to work with inside the modem */
820
codec2_decode_upacked(struct freedv * f,short speech_out[],uint8_t unpacked_bits[])821 static void codec2_decode_upacked(struct freedv *f, short speech_out[], uint8_t unpacked_bits[]) {
822 int n_packed = (f->bits_per_codec_frame + 7) / 8;
823 uint8_t packed_codec_bits[n_packed];
824
825 freedv_pack(packed_codec_bits, unpacked_bits, f->bits_per_codec_frame);
826 codec2_decode(f->codec2, speech_out, packed_codec_bits);
827 }
828
829
830 /*---------------------------------------------------------------------------* \
831
832 FUNCTION....: freedv_rx_bits_to_speech
833 AUTHOR......: David Rowe
834 DATE CREATED: May 2020
835
836 The *_rx functions takes off air samples, demodulates and (for some
837 modes) FEC decodes, giving us a frame of bits.
838
839 This function captures a lot of tricky logic that has been distilled
840 through experience:
841
842 There may not be a frame of bits returned on every call freedv_*rx* call.
843 When there are valid bits we need to run the speech decoder.
844 We may not have demod sync, so various pass through options may happen
845 with the input samples.
846 We may squelch based on SNR.
847 Need to handle various codecs, and varying number of codec frames per modem frame
848 Squelch audio if test frames are being sent
849 Determine how many speech samples to return, which will vary if in sync/out of sync
850 Work with real and complex inputs (complex wrapper)
851 Attenuate audio on pass through
852 Deal with 700D first frame burble, and different sync states from OFDM modes like 700D
853 Output no samples if squelched, we assume it's OK for the audio sink to run dry
854 A FIFO required on output to smooth sample flow to audio sink
855 Don't decode when we are sending test frames
856
857 \*---------------------------------------------------------------------------*/
858
freedv_bits_to_speech(struct freedv * f,short speech_out[],short demod_in[],int rx_status)859 int freedv_bits_to_speech(struct freedv *f, short speech_out[], short demod_in[], int rx_status) {
860 int nout = 0;
861 int decode_speech = 0;
862 if ((rx_status & FREEDV_RX_SYNC) == 0) {
863
864 if (f->squelch_en == 0) {
865
866 /* pass through received samples so we can hear what's going on, e.g. during tuning */
867
868 if (f->mode == FREEDV_MODE_2020) {
869 /* 8kHz modem sample rate but 16 kHz speech sample
870 rate, so we need to resample */
871 nout = 2*f->nin_prev;
872 assert(nout <= freedv_get_n_max_speech_samples(f));
873 float tmp[nout];
874 for(int i=0; i<nout/2; i++)
875 f->passthrough_2020[FDMDV_OS_TAPS_16K+i] = demod_in[i];
876 fdmdv_8_to_16(tmp, &f->passthrough_2020[FDMDV_OS_TAPS_16K], nout/2);
877 for(int i=0; i<nout; i++)
878 speech_out[i] = f->passthrough_gain*tmp[i];
879 } else {
880 /* Speech and modem rates might be different */
881 int rate_factor = f->modem_sample_rate / f-> speech_sample_rate;
882 nout = f->nin_prev / rate_factor;
883 for(int i=0; i<nout; i++)
884 speech_out[i] = f->passthrough_gain*demod_in[i * rate_factor];
885 }
886 }
887 }
888
889 if ((rx_status & FREEDV_RX_SYNC) && (rx_status & FREEDV_RX_BITS) && !f->test_frames) {
890 /* following logic is tricky so spell it out clearly, see table
891 in: https://github.com/drowe67/codec2/pull/111 */
892
893 if (f->squelch_en == 0) {
894 decode_speech = 1;
895 } else {
896 /* squelch is enabled */
897
898 /* anti-burble case - don't decode on trial sync unless the
899 frame has no bit errors. This prevents short lived trial
900 sync cases generating random bursts of audio */
901 if (rx_status & FREEDV_RX_TRIAL_SYNC) {
902 if ((rx_status & FREEDV_RX_BIT_ERRORS) == 0)
903 decode_speech = 1;
904 }
905 else {
906 /* sync is solid - decode even through fades as there is still some speech info there */
907 if (f->snr_est > f->snr_squelch_thresh)
908 decode_speech = 1;
909 }
910 }
911 }
912
913 if (decode_speech) {
914 if(FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode)) {
915 #ifdef __LPCNET__
916 /* LPCNet decoder */
917
918 int bits_per_codec_frame = lpcnet_bits_per_frame(f->lpcnet);
919 int data_bits_per_frame = f->ldpc->data_bits_per_frame;
920 int frames = data_bits_per_frame/bits_per_codec_frame;
921
922 nout = f->n_speech_samples;
923 for (int i = 0; i < frames; i++) {
924 lpcnet_dec(f->lpcnet, (char*) f->rx_payload_bits + i*bits_per_codec_frame, speech_out);
925 speech_out += lpcnet_samples_per_frame(f->lpcnet);
926 }
927
928 #endif
929 } else {
930 /* codec 2 decoder */
931
932 if(FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode)) {
933 nout = f->n_speech_samples;
934 for (int i = 0; i < f->n_codec_frames; i++) {
935 codec2_decode_upacked(f, speech_out, f->rx_payload_bits + i*f->bits_per_codec_frame);
936 speech_out += codec2_samples_per_frame(f->codec2);
937 }
938 } else {
939 /* non-interleaved Codec 2 modes */
940
941 nout = f->n_speech_samples;
942 if ( (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)))
943 codec2_decode(f->codec2, speech_out, f->rx_payload_bits);
944 else if (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)) {
945 codec2_decode(f->codec2, &speech_out[ 0], &f->rx_payload_bits[0]);
946 codec2_decode(f->codec2, &speech_out[320], &f->rx_payload_bits[4]);
947 } else {
948 for (int i = 0; i <f->n_codec_frames; i++) {
949 codec2_decode_upacked(f, speech_out, f->rx_payload_bits + i*f->bits_per_codec_frame);
950 speech_out += codec2_samples_per_frame(f->codec2);
951 }
952 }
953 }
954 }
955 }
956
957 if (f->verbose == 3) {
958 fprintf(stderr, " sqen: %d nout: %d decsp: %d\n", f->squelch_en, nout, decode_speech);
959 }
960
961 f->rx_status= rx_status;
962 assert(nout <= freedv_get_n_max_speech_samples(f));
963 return nout;
964 }
965
966
967 /* a way to receive raw frames of bytes, or speech data that will be decompressed externally */
freedv_rawdatarx(struct freedv * f,unsigned char * packed_payload_bits,short demod_in[])968 int freedv_rawdatarx(struct freedv *f, unsigned char *packed_payload_bits, short demod_in[])
969 {
970 assert(f != NULL);
971 int nin = freedv_nin(f);
972 assert(nin <= f->n_max_modem_samples);
973 COMP demod_in_comp[f->n_max_modem_samples];
974
975 for(int i=0; i<nin; i++) {
976 demod_in_comp[i].real = (float)demod_in[i];
977 demod_in_comp[i].imag = 0.0;
978 }
979
980 return freedv_rawdatacomprx(f, packed_payload_bits, demod_in_comp);
981 }
982
983 /* a way to receive raw frames of bytes, or speech data that will be decompressed externally */
freedv_rawdatacomprx(struct freedv * f,unsigned char * packed_payload_bits,COMP demod_in[])984 int freedv_rawdatacomprx(struct freedv *f, unsigned char *packed_payload_bits, COMP demod_in[])
985 {
986 assert(f != NULL);
987 int ret = 0;
988 int rx_status = 0;
989
990 /* FSK modes used packed bits internally */
991 if (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)){
992 rx_status = freedv_comprx_fsk(f, demod_in);
993 f->rx_status = rx_status;
994 if (rx_status & FREEDV_RX_BITS) {
995 ret = (freedv_get_bits_per_modem_frame(f) + 7) / 8;
996 freedv_rawdata_from_codec_frames(f, packed_payload_bits, f->rx_payload_bits);
997 }
998 return ret;
999 }
1000
1001 if (FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode)) rx_status = freedv_comprx_fdmdv_1600(f, demod_in);
1002 if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) rx_status = freedv_comprx_700c(f, demod_in);
1003 if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) ||
1004 FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, f->mode) ||
1005 FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, f->mode) ||
1006 FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, f->mode)) rx_status = freedv_comp_short_rx_ofdm(f, (void*)demod_in, 0, 1.0f);
1007 if (FDV_MODE_ACTIVE( FREEDV_MODE_FSK_LDPC, f->mode)) {
1008 rx_status = freedv_rx_fsk_ldpc_data(f, demod_in);
1009 }
1010
1011 if (rx_status & FREEDV_RX_BITS) {
1012 ret = (f->bits_per_modem_frame+7)/8;
1013 freedv_pack(packed_payload_bits, f->rx_payload_bits, f->bits_per_modem_frame);
1014 }
1015
1016 /* might want to check this for errors, e.g. if reliable data is important */
1017 f->rx_status= rx_status;
1018
1019 return ret;
1020 }
1021
1022
1023 /*---------------------------------------------------------------------------* \
1024
1025 FUNCTION....: freedv_get_version
1026 AUTHOR......: Jim Ahlstrom
1027 DATE CREATED: 28 July 2015
1028
1029 Return the version of the FreeDV API. This is meant to help API
1030 users determine when incompatible changes have occurred.
1031
1032 \*---------------------------------------------------------------------------*/
1033
freedv_get_version(void)1034 int freedv_get_version(void)
1035 {
1036 return VERSION;
1037 }
1038
1039 /*---------------------------------------------------------------------------* \
1040
1041 FUNCTION....: freedv_get_hash
1042 AUTHOR......: David Rowe
1043 DATE CREATED: July 2020
1044
1045 Return the a string with the Git hash of the repo used to build this code.
1046
1047 \*---------------------------------------------------------------------------*/
1048
1049 static char git_hash[] = GIT_HASH;
freedv_get_hash(void)1050 char *freedv_get_hash(void)
1051 {
1052 return git_hash;
1053 }
1054
1055 /*---------------------------------------------------------------------------*\
1056
1057 FUNCTION....: freedv_set_callback_txt
1058 AUTHOR......: Jim Ahlstrom
1059 DATE CREATED: 28 July 2015
1060
1061 Set the callback functions and the callback state pointer that will
1062 be used for the aux txt channel. The freedv_callback_rx is a
1063 function pointer that will be called to return received characters.
1064 The freedv_callback_tx is a function pointer that will be called to
1065 send transmitted characters. The callback state is a user-defined
1066 void pointer that will be passed to the callback functions. Any or
1067 all can be NULL, and the default is all NULL.
1068
1069 The function signatures are:
1070 void receive_char(void *callback_state, char c);
1071 char transmit_char(void *callback_state);
1072
1073 \*---------------------------------------------------------------------------*/
1074
freedv_set_callback_txt(struct freedv * f,freedv_callback_rx rx,freedv_callback_tx tx,void * state)1075 void freedv_set_callback_txt(struct freedv *f, freedv_callback_rx rx, freedv_callback_tx tx, void *state)
1076 {
1077 if (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode) == false) {
1078 f->freedv_put_next_rx_char = rx;
1079 f->freedv_get_next_tx_char = tx;
1080 f->callback_state = state;
1081 }
1082 }
1083
1084 /*---------------------------------------------------------------------------*\
1085
1086 FUNCTION....: freedv_set_callback_txt_sym
1087 AUTHOR......: Mooneer Salem
1088 DATE CREATED: 19 August 2021
1089
1090 Set the callback functions and the callback state pointer that will
1091 be used to provide the raw symbols for the aux txt channel. The
1092 freedv_callback_rx_sym is a function pointer that will be called to
1093 return received symbols. The callback state is a user-defined
1094 void pointer that will be passed to the callback function. Any or
1095 all can be NULL, and the default is all NULL.
1096
1097 The function signature is:
1098 void receive_sym(void *callback_state, COMP sym, COMP amp);
1099
1100 Note: Active for OFDM modes only (700D/E, 2020).
1101 \*---------------------------------------------------------------------------*/
1102
freedv_set_callback_txt_sym(struct freedv * f,freedv_callback_rx_sym rx,void * state)1103 void freedv_set_callback_txt_sym(struct freedv *f, freedv_callback_rx_sym rx, void *state)
1104 {
1105 if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode ) ||
1106 FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode ) ||
1107 FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode ) ) {
1108 f->freedv_put_next_rx_symbol = rx;
1109 f->callback_state_sym = state;
1110 }
1111 }
1112
1113 /*---------------------------------------------------------------------------*\
1114
1115 FUNCTION....: freedv_set_callback_protocol
1116 AUTHOR......: Brady OBrien
1117 DATE CREATED: 21 February 2016
1118
1119 VHF packet data function.
1120
1121 Set the callback functions and callback pointer that will be used
1122 for the protocol data channel. freedv_callback_protorx will be
1123 called when a frame containing protocol data
1124 arrives. freedv_callback_prototx will be called when a frame
1125 containing protocol information is being generated. Protocol
1126 information is intended to be used to develop protocols and fancy
1127 features atop VHF freedv, much like those present in DMR. Protocol
1128 bits are to be passed in an msb-first char array The number of
1129 protocol bits are findable with freedv_get_protocol_bits
1130
1131 \*---------------------------------------------------------------------------*/
1132
freedv_set_callback_protocol(struct freedv * f,freedv_callback_protorx rx,freedv_callback_prototx tx,void * callback_state)1133 void freedv_set_callback_protocol(struct freedv *f, freedv_callback_protorx rx, freedv_callback_prototx tx, void *callback_state){
1134 if (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode) == false) {
1135 f->freedv_put_next_proto = rx;
1136 f->freedv_get_next_proto = tx;
1137 f->proto_callback_state = callback_state;
1138 }
1139 }
1140
1141 /*---------------------------------------------------------------------------*\
1142
1143 FUNCTION....: freedv_set_callback_datarx / freedv_set_callback_datatx
1144 AUTHOR......: Jeroen Vreeken
1145 DATE CREATED: 04 March 2016
1146
1147 VHF packet data function.
1148
1149 Set the callback functions and callback pointer that will be used
1150 for the data channel. freedv_callback_datarx will be called when a
1151 packet has been successfully received. freedv_callback_data_tx will
1152 be called when transmission of a new packet can begin. If the
1153 returned size of the datatx callback is zero the data frame is still
1154 generated, but will contain only a header update.
1155
1156 \*---------------------------------------------------------------------------*/
1157
freedv_set_callback_data(struct freedv * f,freedv_callback_datarx datarx,freedv_callback_datatx datatx,void * callback_state)1158 void freedv_set_callback_data(struct freedv *f, freedv_callback_datarx datarx, freedv_callback_datatx datatx, void *callback_state) {
1159 if ((FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode))){
1160 if (!f->deframer->fdc)
1161 f->deframer->fdc = freedv_data_channel_create();
1162 if (!f->deframer->fdc)
1163 return;
1164
1165 freedv_data_set_cb_rx(f->deframer->fdc, datarx, callback_state);
1166 freedv_data_set_cb_tx(f->deframer->fdc, datatx, callback_state);
1167 }
1168 }
1169
1170 /*---------------------------------------------------------------------------*\
1171
1172 FUNCTION....: freedv_set_data_header
1173 AUTHOR......: Jeroen Vreeken
1174 DATE CREATED: 04 March 2016
1175
1176 VHF packet data function.
1177
1178 Set the data header for the data channel. Header compression will
1179 be used whenever packets from this header are sent. The header will
1180 also be used for fill packets when a data frame is requested without
1181 a packet available.
1182
1183 \*---------------------------------------------------------------------------*/
1184
freedv_set_data_header(struct freedv * f,unsigned char * header)1185 void freedv_set_data_header(struct freedv *f, unsigned char *header)
1186 {
1187 if ((FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode))){
1188 if (!f->deframer->fdc)
1189 f->deframer->fdc = freedv_data_channel_create();
1190 if (!f->deframer->fdc)
1191 return;
1192
1193 freedv_data_set_header(f->deframer->fdc, header);
1194 }
1195 }
1196
1197 /*---------------------------------------------------------------------------*\
1198
1199 FUNCTION....: freedv_get_modem_stats
1200 AUTHOR......: Jim Ahlstrom
1201 DATE CREATED: 28 July 2015
1202
1203 Return data from the modem. The arguments are pointers to the data
1204 items. The pointers can be NULL if the data item is not wanted.
1205
1206 \*---------------------------------------------------------------------------*/
1207
freedv_get_modem_stats(struct freedv * f,int * sync,float * snr_est)1208 void freedv_get_modem_stats(struct freedv *f, int *sync, float *snr_est)
1209 {
1210 if (FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode))
1211 fdmdv_get_demod_stats(f->fdmdv, &f->stats);
1212 if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode))
1213 cohpsk_get_demod_stats(f->cohpsk, &f->stats);
1214 if (sync) *sync = f->sync;
1215 if (snr_est) *snr_est = f->snr_est;
1216 }
1217
1218 /*---------------------------------------------------------------------------*\
1219
1220 FUNCTIONS...: freedv_set_*
1221 AUTHOR......: Jim Ahlstrom
1222 DATE CREATED: 28 July 2015
1223
1224 Set some parameters used by FreeDV. It is possible to write a macro
1225 using ## for this, but I wasn't sure it would be 100% portable.
1226
1227 \*---------------------------------------------------------------------------*/
1228
freedv_set_test_frames(struct freedv * f,int val)1229 void freedv_set_test_frames (struct freedv *f, int val) {f->test_frames = val;}
freedv_set_test_frames_diversity(struct freedv * f,int val)1230 void freedv_set_test_frames_diversity (struct freedv *f, int val) {f->test_frames_diversity = val;}
freedv_set_squelch_en(struct freedv * f,int val)1231 void freedv_set_squelch_en (struct freedv *f, int val) {f->squelch_en = val;}
freedv_set_total_bit_errors(struct freedv * f,int val)1232 void freedv_set_total_bit_errors (struct freedv *f, int val) {f->total_bit_errors = val;}
freedv_set_total_bits(struct freedv * f,int val)1233 void freedv_set_total_bits (struct freedv *f, int val) {f->total_bits = val;}
freedv_set_total_bit_errors_coded(struct freedv * f,int val)1234 void freedv_set_total_bit_errors_coded (struct freedv *f, int val) {f->total_bit_errors_coded = val;}
freedv_set_total_bits_coded(struct freedv * f,int val)1235 void freedv_set_total_bits_coded (struct freedv *f, int val) {f->total_bits_coded = val;}
freedv_set_total_packet_errors(struct freedv * f,int val)1236 void freedv_set_total_packet_errors (struct freedv *f, int val) {f->total_packet_errors = val;}
freedv_set_total_packets(struct freedv * f,int val)1237 void freedv_set_total_packets (struct freedv *f, int val) {f->total_packets = val;}
freedv_set_varicode_code_num(struct freedv * f,int val)1238 void freedv_set_varicode_code_num (struct freedv *f, int val) {varicode_set_code_num(&f->varicode_dec_states, val);}
freedv_set_ext_vco(struct freedv * f,int val)1239 void freedv_set_ext_vco (struct freedv *f, int val) {f->ext_vco = val;}
freedv_set_snr_squelch_thresh(struct freedv * f,float val)1240 void freedv_set_snr_squelch_thresh (struct freedv *f, float val) {f->snr_squelch_thresh = val;}
freedv_set_tx_amp(struct freedv * f,float amp)1241 void freedv_set_tx_amp (struct freedv *f, float amp) {f->tx_amp = amp;}
freedv_passthrough_gain(struct freedv * f,float g)1242 void freedv_passthrough_gain (struct freedv *f, float g) {f->passthrough_gain = g;}
1243
1244 /* supported by 700C, 700D, 700E */
1245
freedv_set_clip(struct freedv * f,int val)1246 void freedv_set_clip(struct freedv *f, int val) {
1247 f->clip_en = val;
1248 if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode)
1249 || FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, f->mode)) {
1250 f->ofdm->clip_en = val;
1251 /* really should have BPF if we clip */
1252 if (val) ofdm_set_tx_bpf(f->ofdm, true);
1253 }
1254 }
1255
1256 /* Band Pass Filter to cleanup OFDM tx waveform, only supported by some modes */
1257
freedv_set_tx_bpf(struct freedv * f,int val)1258 void freedv_set_tx_bpf(struct freedv *f, int val) {
1259 if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode)
1260 || FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, f->mode)) {
1261 ofdm_set_tx_bpf(f->ofdm, val);
1262 }
1263 }
1264
1265 /* DPSK option for OFDM modem, useful for high SNR, fast fading */
freedv_set_dpsk(struct freedv * f,int val)1266 void freedv_set_dpsk(struct freedv *f, int val) {
1267 if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode)) {
1268 ofdm_set_dpsk(f->ofdm, val);
1269 }
1270 }
1271
freedv_set_phase_est_bandwidth_mode(struct freedv * f,int val)1272 void freedv_set_phase_est_bandwidth_mode(struct freedv *f, int val) {
1273 if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode)) {
1274 ofdm_set_phase_est_bandwidth_mode(f->ofdm, val);
1275 }
1276 }
1277
1278 // For those FreeDV modes using the codec 2 700C vocoder 700C/D/E/800XA
freedv_set_eq(struct freedv * f,int val)1279 void freedv_set_eq(struct freedv *f, int val) {
1280 if (f->codec2 != NULL) {
1281 codec2_700c_eq(f->codec2, val);
1282 }
1283 }
1284
freedv_set_verbose(struct freedv * f,int verbosity)1285 void freedv_set_verbose(struct freedv *f, int verbosity) {
1286 f->verbose = verbosity;
1287 if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) {
1288 cohpsk_set_verbose(f->cohpsk, f->verbose);
1289 }
1290 if (is_ofdm_mode(f)) {
1291 ofdm_set_verbose(f->ofdm, f->verbose-1);
1292 }
1293 }
1294
freedv_set_callback_error_pattern(struct freedv * f,freedv_calback_error_pattern cb,void * state)1295 void freedv_set_callback_error_pattern(struct freedv *f, freedv_calback_error_pattern cb, void *state)
1296 {
1297 f->freedv_put_error_pattern = cb;
1298 f->error_pattern_callback_state = state;
1299 }
1300
freedv_set_carrier_ampl(struct freedv * f,int c,float ampl)1301 void freedv_set_carrier_ampl(struct freedv *f, int c, float ampl) {
1302 if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode))
1303 {
1304 cohpsk_set_carrier_ampl(f->cohpsk, c, ampl);
1305 }
1306 }
1307
1308 /*---------------------------------------------------------------------------* \
1309
1310 FUNCTIONS...: freedv_set_sync
1311 AUTHOR......: David Rowe
1312 DATE CREATED: May 2018
1313
1314 Extended control of sync state machines for OFDM modes.
1315
1316 Ensure this is called in the same thread as freedv_rx().
1317
1318 \*---------------------------------------------------------------------------*/
1319
freedv_set_sync(struct freedv * freedv,int sync_cmd)1320 void freedv_set_sync(struct freedv *freedv, int sync_cmd) {
1321 assert (freedv != NULL);
1322
1323 if (freedv->ofdm != NULL) {
1324 ofdm_set_sync(freedv->ofdm, sync_cmd);
1325 }
1326 }
1327
1328 // this also selects burst mode
freedv_set_frames_per_burst(struct freedv * freedv,int framesperburst)1329 void freedv_set_frames_per_burst(struct freedv *freedv, int framesperburst) {
1330 assert (freedv != NULL);
1331 if (freedv->ofdm != NULL) {
1332 // change of nomenclature as we cross into the OFDM modem layer. In the
1333 // OFDM modem we have packets that contain multiple "modem frames"
1334 ofdm_set_packets_per_burst(freedv->ofdm, framesperburst);
1335 }
1336 }
1337
freedv_get_fsk(struct freedv * f)1338 struct FSK * freedv_get_fsk(struct freedv *f){
1339 return f->fsk;
1340 }
1341
1342 /*---------------------------------------------------------------------------*\
1343
1344 FUNCTIONS...: freedv_get_*
1345 AUTHOR......: Jim Ahlstrom
1346 DATE CREATED: 28 July 2015
1347
1348 Get some parameters from FreeDV.
1349
1350 \*---------------------------------------------------------------------------*/
1351
freedv_get_protocol_bits(struct freedv * f)1352 int freedv_get_protocol_bits (struct freedv *f) {return f->n_protocol_bits;}
freedv_get_mode(struct freedv * f)1353 int freedv_get_mode (struct freedv *f) {return f->mode;}
freedv_get_test_frames(struct freedv * f)1354 int freedv_get_test_frames (struct freedv *f) {return f->test_frames;}
freedv_get_speech_sample_rate(struct freedv * f)1355 int freedv_get_speech_sample_rate (struct freedv *f) {return f-> speech_sample_rate;}
freedv_get_n_speech_samples(struct freedv * f)1356 int freedv_get_n_speech_samples (struct freedv *f) {return f->n_speech_samples;}
freedv_get_modem_sample_rate(struct freedv * f)1357 int freedv_get_modem_sample_rate (struct freedv *f) {return f->modem_sample_rate;}
freedv_get_modem_symbol_rate(struct freedv * f)1358 int freedv_get_modem_symbol_rate (struct freedv *f) {return f->modem_symbol_rate;}
freedv_get_n_max_modem_samples(struct freedv * f)1359 int freedv_get_n_max_modem_samples (struct freedv *f) {return f->n_max_modem_samples;}
freedv_get_n_nom_modem_samples(struct freedv * f)1360 int freedv_get_n_nom_modem_samples (struct freedv *f) {return f->n_nom_modem_samples;}
freedv_get_n_tx_modem_samples(struct freedv * f)1361 int freedv_get_n_tx_modem_samples (struct freedv *f) {return f->n_nat_modem_samples;}
freedv_get_total_bits(struct freedv * f)1362 int freedv_get_total_bits (struct freedv *f) {return f->total_bits;}
freedv_get_total_bit_errors(struct freedv * f)1363 int freedv_get_total_bit_errors (struct freedv *f) {return f->total_bit_errors;}
freedv_get_total_bits_coded(struct freedv * f)1364 int freedv_get_total_bits_coded (struct freedv *f) {return f->total_bits_coded;}
freedv_get_total_bit_errors_coded(struct freedv * f)1365 int freedv_get_total_bit_errors_coded (struct freedv *f) {return f->total_bit_errors_coded;}
freedv_get_total_packets(struct freedv * f)1366 int freedv_get_total_packets (struct freedv *f) {return f->total_packets;}
freedv_get_total_packet_errors(struct freedv * f)1367 int freedv_get_total_packet_errors (struct freedv *f) {return f->total_packet_errors;}
freedv_get_sync(struct freedv * f)1368 int freedv_get_sync (struct freedv *f) {return f->sync;}
freedv_get_codec2(struct freedv * f)1369 struct CODEC2 *freedv_get_codec2 (struct freedv *f) {return f->codec2;}
freedv_get_bits_per_codec_frame(struct freedv * f)1370 int freedv_get_bits_per_codec_frame (struct freedv *f) {return f->bits_per_codec_frame;}
freedv_get_bits_per_modem_frame(struct freedv * f)1371 int freedv_get_bits_per_modem_frame (struct freedv *f) {return f->bits_per_modem_frame;}
freedv_get_rx_status(struct freedv * f)1372 int freedv_get_rx_status (struct freedv *f) {return f->rx_status;}
freedv_get_fsk_S_and_N(struct freedv * f,float * S,float * N)1373 void freedv_get_fsk_S_and_N (struct freedv *f, float *S, float *N) { *S = f->fsk_S[0]; *N = f->fsk_N[0]; }
1374
freedv_get_n_max_speech_samples(struct freedv * f)1375 int freedv_get_n_max_speech_samples(struct freedv *f) {
1376 /* When "passing through" demod samples to the speech output
1377 (e.g. no sync and squelch off) f->nin bounces around with
1378 timing variations. So we may return
1379 freedv_get_n_max_modem_samples() via the speech_output[]
1380 array */
1381 int max_output_passthrough_samples;
1382 if (FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode))
1383 // In 2020 we oversample the input modem samples from 8->16 kHz
1384 max_output_passthrough_samples = 2*freedv_get_n_max_modem_samples(f);
1385 else
1386 max_output_passthrough_samples = freedv_get_n_max_modem_samples(f);
1387
1388 if (max_output_passthrough_samples > f->n_speech_samples)
1389 return max_output_passthrough_samples;
1390 else
1391 return f->n_speech_samples;
1392 }
1393
1394 // Now dummy obsolete call
freedv_get_sync_interleaver(struct freedv * f)1395 int freedv_get_sync_interleaver(struct freedv *f) {
1396 return 1;
1397 }
1398
freedv_get_sz_error_pattern(struct freedv * f)1399 int freedv_get_sz_error_pattern(struct freedv *f)
1400 {
1401 if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) {
1402 /* if diversity disabled callback sends error pattern for upper and lower carriers */
1403 return f->sz_error_pattern * (2 - f->test_frames_diversity);
1404 } else {
1405 return f->sz_error_pattern;
1406 }
1407 }
1408
1409 // Get modem status, scatter/eye diagram for plotting, other goodies
freedv_get_modem_extended_stats(struct freedv * f,struct MODEM_STATS * stats)1410 void freedv_get_modem_extended_stats(struct freedv *f, struct MODEM_STATS *stats)
1411 {
1412 if (FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode))
1413 fdmdv_get_demod_stats(f->fdmdv, stats);
1414
1415 if (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)) {
1416 fsk_get_demod_stats(f->fsk, stats); /* eye diagram samples, clock offset etc */
1417 stats->snr_est = f->snr_est; /* estimated when fsk_demod() called in freedv_fsk.c */
1418 stats->sync = f->sync; /* sync indicator comes from framing layer */
1419 }
1420
1421 if (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)) {
1422 fmfsk_get_demod_stats(f->fmfsk, stats);
1423 stats->snr_est = f->snr_est;
1424 stats->sync = f->sync;
1425 }
1426
1427 if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) {
1428 cohpsk_get_demod_stats(f->cohpsk, stats);
1429 }
1430
1431 if (is_ofdm_mode(f)) {
1432 // OFDM modem stats updated when demod runs, so copy last update
1433 // We need to avoid over writing the FFT states which are updated by a different function
1434 // TODO we need a better design here: Issue #182
1435 #ifndef __EMBEDDED__
1436 size_t ncopy = (void*)stats->rx_eye - (void*)stats;
1437 memcpy(stats, &f->stats, ncopy);
1438 #endif
1439 stats->snr_est = f->snr_est;
1440 stats->sync = f->sync;
1441 }
1442 }
1443
freedv_get_n_tx_preamble_modem_samples(struct freedv * f)1444 int freedv_get_n_tx_preamble_modem_samples(struct freedv *f) {
1445 if (f->mode == FREEDV_MODE_FSK_LDPC) {
1446 struct FSK *fsk = f->fsk;
1447 int npreamble_symbols = 50*(fsk->mode>>1);
1448 return fsk->Ts*npreamble_symbols;
1449 } else if (is_ofdm_data_mode(f)) {
1450 return f->ofdm->samplesperframe;
1451 }
1452
1453 return 0;
1454 }
1455
freedv_get_n_tx_postamble_modem_samples(struct freedv * f)1456 int freedv_get_n_tx_postamble_modem_samples(struct freedv *f) {
1457 if (is_ofdm_data_mode(f)) {
1458 return f->ofdm->samplesperframe;
1459 }
1460
1461 return 0;
1462 }
1463
1464 // from http://stackoverflow.com/questions/10564491/function-to-calculate-a-crc16-checksum
1465
freedv_gen_crc16(unsigned char * data_p,int length)1466 unsigned short freedv_gen_crc16(unsigned char* data_p, int length) {
1467 unsigned char x;
1468 unsigned short crc = 0xFFFF;
1469
1470 while (length--) {
1471 x = crc >> 8 ^ *data_p++;
1472 x ^= x>>4;
1473 crc = (crc << 8) ^ ((unsigned short)(x << 12)) ^ ((unsigned short)(x <<5)) ^ ((unsigned short)x);
1474 }
1475
1476 return crc;
1477 }
1478