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