aboutsummaryrefslogtreecommitdiff
path: root/src/freedv_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/freedv_api.c')
-rw-r--r--src/freedv_api.c1968
1 files changed, 1024 insertions, 944 deletions
diff --git a/src/freedv_api.c b/src/freedv_api.c
index 516d604..5172959 100644
--- a/src/freedv_api.c
+++ b/src/freedv_api.c
@@ -31,72 +31,61 @@
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "freedv_api.h"
+
#include <assert.h>
-#include <stdlib.h>
+#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-#include <math.h>
-#include "fsk.h"
-#include "fmfsk.h"
#include "codec2.h"
#include "codec2_fdmdv.h"
+#include "codec2_ofdm.h"
+#include "comp_prim.h"
+#include "debug_alloc.h"
#include "fdmdv_internal.h"
-#include "varicode.h"
-#include "freedv_api.h"
+#include "fmfsk.h"
#include "freedv_api_internal.h"
#include "freedv_vhf_framing.h"
-#include "comp_prim.h"
-
-#include "codec2_ofdm.h"
-#include "ofdm_internal.h"
-#include "mpdecode_core.h"
+#include "fsk.h"
#include "gp_interleaver.h"
#include "interldpc.h"
+#include "mpdecode_core.h"
+#include "ofdm_internal.h"
+#include "varicode.h"
-#include "debug_alloc.h"
+/* The API version number. The first version is 10. Increment if the API
+ changes in a way that would require changes by the API user. */
+
+#define VERSION 15
-#define VERSION 15 /* The API version number. The first version
- is 10. Increment if the API changes in a
- way that would require changes by the API
- user. */
/*
- * Version 10 Initial version August 2, 2015.
- * Version 11 September 2015
- * Added: freedv_zero_total_bit_errors(), freedv_get_sync()
- * Changed all input and output sample rates to 8000 sps. Rates for FREEDV_MODE_700 and 700B were 7500.
- * Version 12 August 2018
- * Added OFDM configuration switch structure
- * Version 13 November 2019
- * Removed 700 and 700B modes
- * Version 14 May 2020
- * Number of returned speech samples can vary, use freedv_get_n_max_speech_samples() to allocate
- * buffers.
- * Version 15 December 2022
- * Removing rarely used DPSK support which is not needed given fast fading modes
+ Version 10 Initial version August 2, 2015.
+
+ Version 11 September 2015
+ Added: freedv_zero_total_bit_errors(), freedv_get_sync()
+ Changed all input and output sample rates to 8000 sps. Rates
+ for FREEDV_MODE_700 and 700B were 7500.
+
+ Version 12 August 2018 Added OFDM configuration switch structure
+
+ Version 13 November 2019 Removed 700 and 700B modes
+
+ Version 14 May 2020 Number of returned speech samples can vary, use
+ freedv_get_n_max_speech_samples() to allocate buffers.
+
+ Version 15 December 2022 Removing rarely used DPSK support which is not
+ needed given fast fading modes
*/
-char *ofdm_statemode[] = {"search","trial","synced"};
-
-char *rx_sync_flags_to_text[] = {
- "----",
- "---T",
- "--S-",
- "--ST",
- "-B--",
- "-B-T",
- "-BS-",
- "-BST",
- "E---",
- "E--T",
- "E-S-",
- "E-ST",
- "EB--",
- "EB-T",
- "EBS-",
- "EBST"};
+char *ofdm_statemode[] = {"search", "trial", "synced"};
+
+char *rx_sync_flags_to_text[] = {"----", "---T", "--S-", "--ST", "-B--", "-B-T",
+ "-BS-", "-BST", "E---", "E--T", "E-S-", "E-ST",
+ "EB--", "EB-T", "EBS-", "EBST"};
/*---------------------------------------------------------------------------* \
@@ -111,63 +100,64 @@ char *rx_sync_flags_to_text[] = {
\*---------------------------------------------------------------------------*/
struct freedv *freedv_open(int mode) {
- // defaults for those modes that support the use of adv
- struct freedv_advanced adv = {0,2,100,8000,1000,200, "H_256_512_4"};
- return freedv_open_advanced(mode, &adv);
+ // defaults for those modes that support the use of adv
+ struct freedv_advanced adv = {0, 2, 100, 8000, 1000, 200, "H_256_512_4"};
+ return freedv_open_advanced(mode, &adv);
}
struct freedv *freedv_open_advanced(int mode, struct freedv_advanced *adv) {
- struct freedv *f;
-
- assert(FREEDV_PEAK == OFDM_PEAK);
- assert(FREEDV_VARICODE_MAX_BITS == VARICODE_MAX_BITS);
-
- if ((FDV_MODE_ACTIVE( FREEDV_MODE_1600, mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_700C, mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_700D, mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_700E, mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2400A, mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2400B, mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_800XA, mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2020, mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2020B, mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2020C, mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_FSK_LDPC, mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC4, mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC13, mode)) == false) return NULL;
-
- /* set everything to zero just in case */
- f = (struct freedv*)CALLOC(1, sizeof(struct freedv));
- if (f == NULL) return NULL;
-
- f->mode = mode;
-
- if (FDV_MODE_ACTIVE( FREEDV_MODE_1600, mode)) freedv_1600_open(f);
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, mode)) freedv_700c_open(f);
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, mode)) freedv_ofdm_voice_open(f, "700D");
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700E, mode)) freedv_ofdm_voice_open(f, "700E");
+ struct freedv *f;
+
+ assert(FREEDV_PEAK == OFDM_PEAK);
+ assert(FREEDV_VARICODE_MAX_BITS == VARICODE_MAX_BITS);
+
+ if ((FDV_MODE_ACTIVE(FREEDV_MODE_1600, mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_700C, mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_700D, mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_700E, mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_2400A, mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_2400B, mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_800XA, mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_2020, mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_2020B, mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_FSK_LDPC, mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC0, mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC1, mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC3, mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC4, mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC13, mode)) == false)
+ return NULL;
+
+ /* set everything to zero just in case */
+ f = (struct freedv *)CALLOC(1, sizeof(struct freedv));
+ if (f == NULL) return NULL;
+
+ f->mode = mode;
+
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_1600, mode)) freedv_1600_open(f);
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, mode)) freedv_700c_open(f);
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700D, mode))
+ freedv_ofdm_voice_open(f, "700D");
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700E, mode))
+ freedv_ofdm_voice_open(f, "700E");
#ifdef __LPCNET__
- if (FDV_MODE_ACTIVE( FREEDV_MODE_2020, mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2020B, mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2020C, mode))
- freedv_2020x_open(f);
-#endif
- if (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, mode)) freedv_2400a_open(f);
- if (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, mode)) freedv_2400b_open(f);
- if (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, mode)) freedv_800xa_open(f);
- if (FDV_MODE_ACTIVE( FREEDV_MODE_FSK_LDPC, mode)) freedv_fsk_ldpc_open(f, adv);
- if (FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, mode)) freedv_ofdm_data_open(f);
- if (FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, mode)) freedv_ofdm_data_open(f);
- if (FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, mode)) freedv_ofdm_data_open(f);
- if (FDV_MODE_ACTIVE( FREEDV_MODE_DATAC4, mode)) freedv_ofdm_data_open(f);
- if (FDV_MODE_ACTIVE( FREEDV_MODE_DATAC13, mode)) freedv_ofdm_data_open(f);
-
- varicode_decode_init(&f->varicode_dec_states, 1);
-
- return f;
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_2020, mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_2020B, mode))
+ freedv_2020x_open(f);
+#endif
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_2400A, mode)) freedv_2400a_open(f);
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_2400B, mode)) freedv_2400b_open(f);
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_800XA, mode)) freedv_800xa_open(f);
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_FSK_LDPC, mode)) freedv_fsk_ldpc_open(f, adv);
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC0, mode)) freedv_ofdm_data_open(f);
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC1, mode)) freedv_ofdm_data_open(f);
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC3, mode)) freedv_ofdm_data_open(f);
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC4, mode)) freedv_ofdm_data_open(f);
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC13, mode)) freedv_ofdm_data_open(f);
+
+ varicode_decode_init(&f->varicode_dec_states, 1);
+
+ return f;
}
/*---------------------------------------------------------------------------*\
@@ -181,113 +171,112 @@ struct freedv *freedv_open_advanced(int mode, struct freedv_advanced *adv) {
\*---------------------------------------------------------------------------*/
void freedv_close(struct freedv *freedv) {
- assert(freedv != NULL);
+ assert(freedv != NULL);
- FREE(freedv->tx_payload_bits);
- FREE(freedv->rx_payload_bits);
- if (freedv->codec2) codec2_destroy(freedv->codec2);
+ FREE(freedv->tx_payload_bits);
+ FREE(freedv->rx_payload_bits);
+ if (freedv->codec2) codec2_destroy(freedv->codec2);
- if (FDV_MODE_ACTIVE(FREEDV_MODE_1600, freedv->mode)) {
- FREE(freedv->fdmdv_bits);
- FREE(freedv->fdmdv_tx_bits);
- FREE(freedv->fdmdv_rx_bits);
- fdmdv_destroy(freedv->fdmdv);
- }
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_1600, freedv->mode)) {
+ FREE(freedv->fdmdv_bits);
+ FREE(freedv->fdmdv_tx_bits);
+ FREE(freedv->fdmdv_rx_bits);
+ fdmdv_destroy(freedv->fdmdv);
+ }
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, freedv->mode)) {
- cohpsk_destroy(freedv->cohpsk);
- quisk_filt_destroy(freedv->ptFilter8000to7500);
- FREE(freedv->ptFilter8000to7500);
- quisk_filt_destroy(freedv->ptFilter7500to8000);
- FREE(freedv->ptFilter7500to8000);
- }
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, freedv->mode)) {
+ cohpsk_destroy(freedv->cohpsk);
+ quisk_filt_destroy(freedv->ptFilter8000to7500);
+ FREE(freedv->ptFilter8000to7500);
+ quisk_filt_destroy(freedv->ptFilter7500to8000);
+ FREE(freedv->ptFilter7500to8000);
+ }
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, freedv->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_700E, freedv->mode)) {
- FREE(freedv->rx_syms);
- FREE(freedv->rx_amps);
- FREE(freedv->ldpc);
- ofdm_destroy(freedv->ofdm);
- }
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700D, freedv->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_700E, freedv->mode)) {
+ FREE(freedv->rx_syms);
+ FREE(freedv->rx_amps);
+ FREE(freedv->ldpc);
+ ofdm_destroy(freedv->ofdm);
+ }
- if (FDV_MODE_ACTIVE( FREEDV_MODE_2020, freedv->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2020B, freedv->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2020C, freedv->mode)) {
- FREE(freedv->codeword_symbols);
- FREE(freedv->codeword_amps);
- FREE(freedv->ldpc);
- FREE(freedv->passthrough_2020);
- ofdm_destroy(freedv->ofdm);
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_2020, freedv->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_2020B, freedv->mode)) {
+ FREE(freedv->codeword_symbols);
+ FREE(freedv->codeword_amps);
+ FREE(freedv->ldpc);
+ FREE(freedv->passthrough_2020);
+ ofdm_destroy(freedv->ofdm);
#ifdef __LPCNET__
- lpcnet_freedv_destroy(freedv->lpcnet);
+ lpcnet_freedv_destroy(freedv->lpcnet);
#endif
- }
+ }
- if (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, freedv->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_800XA, freedv->mode)){
- fsk_destroy(freedv->fsk);
- fvhff_destroy_deframer(freedv->deframer);
- }
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_2400A, freedv->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_800XA, freedv->mode)) {
+ fsk_destroy(freedv->fsk);
+ fvhff_destroy_deframer(freedv->deframer);
+ }
- if (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, freedv->mode)) {
- fmfsk_destroy(freedv->fmfsk);
- fvhff_destroy_deframer(freedv->deframer);
- }
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_2400B, freedv->mode)) {
+ fmfsk_destroy(freedv->fmfsk);
+ fvhff_destroy_deframer(freedv->deframer);
+ }
- if (FDV_MODE_ACTIVE( FREEDV_MODE_FSK_LDPC, freedv->mode)) {
- fsk_destroy(freedv->fsk);
- FREE(freedv->ldpc);
- FREE(freedv->frame_llr);
- FREE(freedv->twoframes_llr);
- FREE(freedv->twoframes_hard);
- }
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_FSK_LDPC, freedv->mode)) {
+ fsk_destroy(freedv->fsk);
+ FREE(freedv->ldpc);
+ FREE(freedv->frame_llr);
+ FREE(freedv->twoframes_llr);
+ FREE(freedv->twoframes_hard);
+ }
- if (FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, freedv->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, freedv->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, freedv->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC4, freedv->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC13, freedv->mode))
- {
- FREE(freedv->rx_syms);
- FREE(freedv->rx_amps);
- FREE(freedv->ldpc);
- ofdm_destroy(freedv->ofdm);
- }
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC0, freedv->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC1, freedv->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC3, freedv->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC4, freedv->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC13, freedv->mode)) {
+ FREE(freedv->rx_syms);
+ FREE(freedv->rx_amps);
+ FREE(freedv->ldpc);
+ ofdm_destroy(freedv->ofdm);
+ }
- FREE(freedv);
+ FREE(freedv);
}
+/* helper function, unpacked bits are much easier to work with inside the modem
+ */
-/* helper function, unpacked bits are much easier to work with inside the modem */
-
-static void codec2_encode_upacked(struct freedv *f, uint8_t unpacked_bits[], short speech_in[]) {
- int n_packed = (f->bits_per_codec_frame + 7) / 8;
- uint8_t packed_codec_bits[n_packed];
+static void codec2_encode_upacked(struct freedv *f, uint8_t unpacked_bits[],
+ short speech_in[]) {
+ int n_packed = (f->bits_per_codec_frame + 7) / 8;
+ uint8_t packed_codec_bits[n_packed];
- codec2_encode(f->codec2, packed_codec_bits, speech_in);
- freedv_unpack(unpacked_bits, packed_codec_bits, f->bits_per_codec_frame);
+ codec2_encode(f->codec2, packed_codec_bits, speech_in);
+ freedv_unpack(unpacked_bits, packed_codec_bits, f->bits_per_codec_frame);
}
static int is_ofdm_mode(struct freedv *f) {
- return FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2020B, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2020C, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC4, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC13, f->mode);
-}
-
+ return FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_2020B, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_700D, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_700E, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC0, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC1, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC3, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC4, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC13, f->mode);
+}
+
static int is_ofdm_data_mode(struct freedv *f) {
- return FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC4, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC13, f->mode);
+ return FDV_MODE_ACTIVE(FREEDV_MODE_DATAC0, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC1, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC3, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC4, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC13, f->mode);
}
-
+
/*---------------------------------------------------------------------------*\
FUNCTION....: freedv_tx
@@ -317,362 +306,383 @@ static int is_ofdm_data_mode(struct freedv *f) {
/* real-valued short output */
void freedv_tx(struct freedv *f, short mod_out[], short speech_in[]) {
- assert(f != NULL);
- COMP tx_fdm[f->n_nom_modem_samples];
- int i;
-
- /* FSK and MEFSK/FMFSK modems work only on real samples. It's simpler to just
- * stick them in the real sample tx/rx functions than to add a comp->real converter
- * to comptx */
-
- 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))){
- /* 800XA has two codec frames per modem frame */
- if(FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)){
- codec2_encode(f->codec2, &f->tx_payload_bits[0], &speech_in[ 0]);
- codec2_encode(f->codec2, &f->tx_payload_bits[4], &speech_in[320]);
- }else{
- codec2_encode(f->codec2, f->tx_payload_bits, speech_in);
- }
- freedv_tx_fsk_voice(f, mod_out);
+ assert(f != NULL);
+ COMP tx_fdm[f->n_nom_modem_samples];
+ int i;
+
+ /* FSK and MEFSK/FMFSK modems work only on real samples. It's simpler to just
+ * stick them in the real sample tx/rx functions than to add a comp->real
+ * converter to comptx */
+
+ 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))) {
+ /* 800XA has two codec frames per modem frame */
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode)) {
+ codec2_encode(f->codec2, &f->tx_payload_bits[0], &speech_in[0]);
+ codec2_encode(f->codec2, &f->tx_payload_bits[4], &speech_in[320]);
} else {
- freedv_comptx(f, tx_fdm, speech_in);
- for(i=0; i<f->n_nom_modem_samples; i++)
- mod_out[i] = tx_fdm[i].real;
+ codec2_encode(f->codec2, f->tx_payload_bits, speech_in);
}
+ freedv_tx_fsk_voice(f, mod_out);
+ } else {
+ freedv_comptx(f, tx_fdm, speech_in);
+ for (i = 0; i < f->n_nom_modem_samples; i++) mod_out[i] = tx_fdm[i].real;
+ }
}
-
/* complex float output version of freedv_tx() */
void freedv_comptx(struct freedv *f, COMP mod_out[], short speech_in[]) {
- assert(f != NULL);
+ assert(f != NULL);
+
+ assert(FDV_MODE_ACTIVE(FREEDV_MODE_1600, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_700D, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_700E, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_2020B, f->mode));
+
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_1600, f->mode)) {
+ codec2_encode_upacked(f, f->tx_payload_bits, speech_in);
+ freedv_comptx_fdmdv_1600(f, mod_out);
+ }
- assert( FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2020B, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2020C, f->mode));
+ /* all these modes need to pack a bunch of codec frames into one modem frame
+ * ... */
- if (FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode)) {
- codec2_encode_upacked(f, f->tx_payload_bits, speech_in);
- freedv_comptx_fdmdv_1600(f, mod_out);
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode)) {
+ for (int j = 0; j < f->n_codec_frames; j++) {
+ codec2_encode_upacked(f, f->tx_payload_bits + j * f->bits_per_codec_frame,
+ speech_in);
+ speech_in += codec2_samples_per_frame(f->codec2);
}
+ freedv_comptx_700c(f, mod_out);
+ }
- /* all these modes need to pack a bunch of codec frames into one modem frame ... */
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700D, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_700E, f->mode)) {
+ /* buffer up bits until we get enough encoded bits for interleaver */
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) {
- for (int j=0; j<f->n_codec_frames; j++) {
- codec2_encode_upacked(f, f->tx_payload_bits+j*f->bits_per_codec_frame, speech_in);
- speech_in += codec2_samples_per_frame(f->codec2);
- }
- freedv_comptx_700c(f, mod_out);
+ for (int j = 0; j < f->n_codec_frames; j++) {
+ int offset = j * f->bits_per_codec_frame;
+ codec2_encode_upacked(f, f->tx_payload_bits + offset, speech_in);
+ speech_in += codec2_samples_per_frame(f->codec2);
}
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode)) {
-
- /* buffer up bits until we get enough encoded bits for interleaver */
-
- for (int j=0; j<f->n_codec_frames; j++) {
- int offset = j*f->bits_per_codec_frame;
- codec2_encode_upacked(f, f->tx_payload_bits + offset, speech_in);
- speech_in += codec2_samples_per_frame(f->codec2);
- }
-
- freedv_comptx_ofdm(f, mod_out);
- }
+ freedv_comptx_ofdm(f, mod_out);
+ }
#ifdef __LPCNET__
- if (FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2020B, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2020C, f->mode)) {
-
- /* buffer up bits until we get enough encoded bits for interleaver */
-
- for (int j=0; j<f->n_codec_frames; j++) {
- int offset = j*f->bits_per_codec_frame;
- lpcnet_enc(f->lpcnet, speech_in, (char*)f->tx_payload_bits + offset);
- speech_in += lpcnet_samples_per_frame(f->lpcnet);
- }
-
- freedv_comptx_2020(f, mod_out);
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_2020B, f->mode)) {
+ /* buffer up bits until we get enough encoded bits for interleaver */
+
+ for (int j = 0; j < f->n_codec_frames; j++) {
+ int offset = j * f->bits_per_codec_frame;
+ lpcnet_enc(f->lpcnet, speech_in, (char *)f->tx_payload_bits + offset);
+ speech_in += lpcnet_samples_per_frame(f->lpcnet);
}
+
+ freedv_comptx_2020(f, mod_out);
+ }
#endif
- /* 2400 A and B are handled by the real-mode TX */
- if(FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)){
- codec2_encode(f->codec2, f->tx_payload_bits, speech_in);
- freedv_comptx_fsk_voice(f, mod_out);
- }
+ /* 2400 A and B are handled by the real-mode TX */
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode)) {
+ codec2_encode(f->codec2, f->tx_payload_bits, speech_in);
+ freedv_comptx_fsk_voice(f, mod_out);
+ }
}
-
/* pack bits */
void freedv_pack(uint8_t *bytes, uint8_t *bits, int nbits) {
- memset(bytes, 0, (nbits+7)/8);
- int bit = 7, byte = 0;
- for(int i=0; i<nbits; i++) {
- bytes[byte] |= bits[i] << bit;
- bit--;
- if (bit < 0) {
- bit = 7;
- byte++;
- }
+ memset(bytes, 0, (nbits + 7) / 8);
+ int bit = 7, byte = 0;
+ for (int i = 0; i < nbits; i++) {
+ bytes[byte] |= bits[i] << bit;
+ bit--;
+ if (bit < 0) {
+ bit = 7;
+ byte++;
}
+ }
}
/* unpack bits, MSB first */
void freedv_unpack(uint8_t *bits, uint8_t *bytes, int nbits) {
- int bit = 7, byte = 0;
- for(int i=0; i<nbits; i++) {
- bits[i] = (bytes[byte] >> bit) & 0x1;
- bit--;
- if (bit < 0) {
- bit = 7;
- byte++;
- }
+ int bit = 7, byte = 0;
+ for (int i = 0; i < nbits; i++) {
+ bits[i] = (bytes[byte] >> bit) & 0x1;
+ bit--;
+ if (bit < 0) {
+ bit = 7;
+ byte++;
}
+ }
}
/* compute the CRC16 of a frame of unpacked bits */
unsigned short freedv_crc16_unpacked(unsigned char unpacked_bits[], int nbits) {
- assert((nbits % 8) == 0);
- int nbytes = nbits/8;
- uint8_t packed_bytes[nbytes];
- freedv_pack(packed_bytes, unpacked_bits, nbits);
- return freedv_gen_crc16(packed_bytes, nbytes);
+ assert((nbits % 8) == 0);
+ int nbytes = nbits / 8;
+ uint8_t packed_bytes[nbytes];
+ freedv_pack(packed_bytes, unpacked_bits, nbits);
+ return freedv_gen_crc16(packed_bytes, nbytes);
}
/* Return non-zero if CRC16 of a frame of unpacked bits is correct */
int freedv_check_crc16_unpacked(unsigned char unpacked_bits[], int nbits) {
- assert((nbits % 8) == 0);
- int nbytes = nbits/8;
- uint8_t packed_bytes[nbytes];
- freedv_pack(packed_bytes, unpacked_bits, nbits);
- uint16_t tx_crc16 = (packed_bytes[nbytes-2] << 8) | packed_bytes[nbytes-1];
- uint16_t rx_crc16 = freedv_crc16_unpacked(unpacked_bits, nbits - 16);
- return tx_crc16 == rx_crc16;
-}
-
-/* send raw frames of bytes, or speech data that was compressed externally, complex float output */
-void freedv_rawdatacomptx(struct freedv *f, COMP mod_out[], unsigned char *packed_payload_bits) {
- assert(f != NULL);
-
- freedv_unpack(f->tx_payload_bits, packed_payload_bits, f->bits_per_modem_frame);
-
- if (FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode)) freedv_comptx_fdmdv_1600(f, mod_out);
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) freedv_comptx_700c(f, mod_out);
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC4, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC13, f->mode)) freedv_comptx_ofdm(f, mod_out);
-
- if (FDV_MODE_ACTIVE( FREEDV_MODE_FSK_LDPC, f->mode)) {
- freedv_tx_fsk_ldpc_data(f, mod_out);
- }
+ assert((nbits % 8) == 0);
+ int nbytes = nbits / 8;
+ uint8_t packed_bytes[nbytes];
+ freedv_pack(packed_bytes, unpacked_bits, nbits);
+ uint16_t tx_crc16 =
+ (packed_bytes[nbytes - 2] << 8) | packed_bytes[nbytes - 1];
+ uint16_t rx_crc16 = freedv_crc16_unpacked(unpacked_bits, nbits - 16);
+ return tx_crc16 == rx_crc16;
}
+/* send raw frames of bytes, or speech data that was compressed externally,
+ * complex float output */
+void freedv_rawdatacomptx(struct freedv *f, COMP mod_out[],
+ unsigned char *packed_payload_bits) {
+ assert(f != NULL);
+
+ freedv_unpack(f->tx_payload_bits, packed_payload_bits,
+ f->bits_per_modem_frame);
+
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_1600, f->mode))
+ freedv_comptx_fdmdv_1600(f, mod_out);
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode))
+ freedv_comptx_700c(f, mod_out);
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700D, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC0, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC1, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC3, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC4, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC13, f->mode))
+ freedv_comptx_ofdm(f, mod_out);
+
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_FSK_LDPC, f->mode)) {
+ freedv_tx_fsk_ldpc_data(f, mod_out);
+ }
+}
-/* send raw frames of bytes, or speech data that was compressed externally, real short output */
-void freedv_rawdatatx(struct freedv *f, short mod_out[], unsigned char *packed_payload_bits) {
- assert(f != NULL);
- COMP mod_out_comp[f->n_nat_modem_samples];
-
- /* Some FSK modes used packed bits, and coincidentally support real samples natively */
- 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) ) {
- freedv_codec_frames_from_rawdata(f, f->tx_payload_bits, packed_payload_bits);
- freedv_tx_fsk_voice(f, mod_out);
- return; /* output is already real */
- }
+/* send raw frames of bytes, or speech data that was compressed externally, real
+ * short output */
+void freedv_rawdatatx(struct freedv *f, short mod_out[],
+ unsigned char *packed_payload_bits) {
+ assert(f != NULL);
+ COMP mod_out_comp[f->n_nat_modem_samples];
+
+ /* Some FSK modes used packed bits, and coincidentally support real samples
+ * natively */
+ 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)) {
+ freedv_codec_frames_from_rawdata(f, f->tx_payload_bits,
+ packed_payload_bits);
+ freedv_tx_fsk_voice(f, mod_out);
+ return; /* output is already real */
+ }
- freedv_rawdatacomptx(f, mod_out_comp, packed_payload_bits);
+ freedv_rawdatacomptx(f, mod_out_comp, packed_payload_bits);
- /* convert complex to real */
- for(int i=0; i<f->n_nat_modem_samples; i++)
- mod_out[i] = mod_out_comp[i].real;
+ /* convert complex to real */
+ for (int i = 0; i < f->n_nat_modem_samples; i++)
+ mod_out[i] = mod_out_comp[i].real;
}
int freedv_rawdatapreamblecomptx(struct freedv *f, COMP mod_out[]) {
- assert(f != NULL);
- int npreamble_samples = 0;
-
- if (f->mode == FREEDV_MODE_FSK_LDPC) {
- struct FSK *fsk = f->fsk;
-
- int npreamble_symbols = 50*(fsk->mode>>1);
- int npreamble_bits = npreamble_symbols*(fsk->mode>>1);
- npreamble_samples = fsk->Ts*npreamble_symbols;
- //fprintf(stderr, "npreamble_symbols: %d npreamble_bits: %d npreamble_samples: %d Nbits: %d N: %d\n",
- //npreamble_symbols, npreamble_bits, npreamble_samples, fsk->Nbits, fsk->N);
-
- assert(npreamble_samples < f->n_nom_modem_samples); /* caller probably using an array of this size */
- freedv_tx_fsk_ldpc_data_preamble(f, mod_out, npreamble_bits, npreamble_samples);
- } else if (is_ofdm_data_mode(f)) {
- struct OFDM *ofdm = f->ofdm;
- complex float *tx_preamble = (complex float*)mod_out;
- memcpy(tx_preamble, ofdm->tx_preamble, sizeof(COMP)*ofdm->samplesperframe);
- ofdm_hilbert_clipper(ofdm, tx_preamble, ofdm->samplesperframe);
- npreamble_samples = ofdm->samplesperframe;
- }
+ assert(f != NULL);
+ int npreamble_samples = 0;
+
+ if (f->mode == FREEDV_MODE_FSK_LDPC) {
+ struct FSK *fsk = f->fsk;
+
+ int npreamble_symbols = 50 * (fsk->mode >> 1);
+ int npreamble_bits = npreamble_symbols * (fsk->mode >> 1);
+ npreamble_samples = fsk->Ts * npreamble_symbols;
+ // fprintf(stderr, "npreamble_symbols: %d npreamble_bits: %d
+ // npreamble_samples: %d Nbits: %d N: %d\n", npreamble_symbols,
+ // npreamble_bits, npreamble_samples, fsk->Nbits, fsk->N);
+
+ assert(npreamble_samples <
+ f->n_nom_modem_samples); /* caller probably using an array of this
+ size */
+ freedv_tx_fsk_ldpc_data_preamble(f, mod_out, npreamble_bits,
+ npreamble_samples);
+ } else if (is_ofdm_data_mode(f)) {
+ struct OFDM *ofdm = f->ofdm;
+ complex float *tx_preamble = (complex float *)mod_out;
+ memcpy(tx_preamble, ofdm->tx_preamble,
+ sizeof(COMP) * ofdm->samplesperframe);
+ ofdm_hilbert_clipper(ofdm, tx_preamble, ofdm->samplesperframe);
+ npreamble_samples = ofdm->samplesperframe;
+ }
- return npreamble_samples;
+ return npreamble_samples;
}
int freedv_rawdatapreambletx(struct freedv *f, short mod_out[]) {
- assert(f != NULL);
- COMP mod_out_comp[f->n_nat_modem_samples];
+ assert(f != NULL);
+ COMP mod_out_comp[f->n_nat_modem_samples];
- int npreamble_samples = freedv_rawdatapreamblecomptx(f, mod_out_comp);
- assert(npreamble_samples <= f->n_nat_modem_samples);
+ int npreamble_samples = freedv_rawdatapreamblecomptx(f, mod_out_comp);
+ assert(npreamble_samples <= f->n_nat_modem_samples);
- /* convert complex to real */
- for(int i=0; i<npreamble_samples; i++)
- mod_out[i] = mod_out_comp[i].real;
+ /* convert complex to real */
+ for (int i = 0; i < npreamble_samples; i++) mod_out[i] = mod_out_comp[i].real;
- return npreamble_samples;
+ return npreamble_samples;
}
int freedv_rawdatapostamblecomptx(struct freedv *f, COMP mod_out[]) {
- assert(f != NULL);
- int npostamble_samples = 0;
-
- if (is_ofdm_data_mode(f)) {
- struct OFDM *ofdm = f->ofdm;
- complex float *tx_postamble = (complex float*)mod_out;
- memcpy(tx_postamble, ofdm->tx_postamble, sizeof(COMP)*ofdm->samplesperframe);
- ofdm_hilbert_clipper(ofdm, tx_postamble, ofdm->samplesperframe);
- npostamble_samples = ofdm->samplesperframe;
- }
+ assert(f != NULL);
+ int npostamble_samples = 0;
+
+ if (is_ofdm_data_mode(f)) {
+ struct OFDM *ofdm = f->ofdm;
+ complex float *tx_postamble = (complex float *)mod_out;
+ memcpy(tx_postamble, ofdm->tx_postamble,
+ sizeof(COMP) * ofdm->samplesperframe);
+ ofdm_hilbert_clipper(ofdm, tx_postamble, ofdm->samplesperframe);
+ npostamble_samples = ofdm->samplesperframe;
+ }
- return npostamble_samples;
+ return npostamble_samples;
}
int freedv_rawdatapostambletx(struct freedv *f, short mod_out[]) {
- assert(f != NULL);
- COMP mod_out_comp[f->n_nat_modem_samples];
+ assert(f != NULL);
+ COMP mod_out_comp[f->n_nat_modem_samples];
- int npostamble_samples = freedv_rawdatapostamblecomptx(f, mod_out_comp);
- assert(npostamble_samples <= f->n_nat_modem_samples);
+ int npostamble_samples = freedv_rawdatapostamblecomptx(f, mod_out_comp);
+ assert(npostamble_samples <= f->n_nat_modem_samples);
- /* convert complex to real */
- for(int i=0; i<npostamble_samples; i++)
- mod_out[i] = mod_out_comp[i].real;
+ /* convert complex to real */
+ for (int i = 0; i < npostamble_samples; i++)
+ mod_out[i] = mod_out_comp[i].real;
- return npostamble_samples;
+ return npostamble_samples;
}
/* VHF packet data tx function */
-void freedv_datatx (struct freedv *f, short mod_out[]) {
- assert(f != NULL);
- 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)) {
- freedv_tx_fsk_data(f, mod_out);
- }
+void freedv_datatx(struct freedv *f, short mod_out[]) {
+ assert(f != NULL);
+ 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)) {
+ freedv_tx_fsk_data(f, mod_out);
+ }
}
-
/* VHF packet data: returns how many tx frames are queued up but not sent yet */
-int freedv_data_ntxframes (struct freedv *f) {
- assert(f != NULL);
- if (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)) {
- if (f->deframer->fdc)
- return freedv_data_get_n_tx_frames(f->deframer->fdc, 8);
- } else if (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)) {
- if (f->deframer->fdc)
- return freedv_data_get_n_tx_frames(f->deframer->fdc, 6);
- }
- return 0;
+int freedv_data_ntxframes(struct freedv *f) {
+ assert(f != NULL);
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode)) {
+ if (f->deframer->fdc)
+ return freedv_data_get_n_tx_frames(f->deframer->fdc, 8);
+ } else if (FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode)) {
+ if (f->deframer->fdc)
+ return freedv_data_get_n_tx_frames(f->deframer->fdc, 6);
+ }
+ return 0;
}
int freedv_nin(struct freedv *f) {
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode))
- // For mode 700C, the input rate is 8000 sps, but the modem rate is 7500 sps
- // For mode 700C, we request a larger number of Rx samples that will be decimated to f->nin samples
- return (16 * f->nin + f->ptFilter8000to7500->decim_index) / 15;
- else
- return f->nin;
-}
-
-int freedv_codec_frames_from_rawdata(struct freedv *f, unsigned char *codec_frames, unsigned char *rawdata)
-{
- int cbit = 7;
- int cbyte = 0;
- int rbit = 7;
- int rbyte = 0;
- int modem_bits = freedv_get_bits_per_modem_frame(f);
- int codec_bits = freedv_get_bits_per_codec_frame(f);
- int nr_cbits = 0;
- int i;
-
- codec_frames[0] = 0;
- for (i = 0; i < modem_bits; i++) {
- codec_frames[cbyte] |= ((rawdata[rbyte] >> rbit) & 1) << cbit;
-
- rbit--;
- if (rbit < 0) {
- rbit = 7;
- rbyte++;
- }
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode))
+ // For mode 700C, the input rate is 8000 sps, but the modem rate is 7500 sps
+ // For mode 700C, we request a larger number of Rx samples that will be
+ // decimated to f->nin samples
+ return (16 * f->nin + f->ptFilter8000to7500->decim_index) / 15;
+ else
+ return f->nin;
+}
- cbit--;
- if (cbit < 0) {
- cbit = 7;
- cbyte++;
- codec_frames[cbyte] = 0;
- }
- nr_cbits++;
- if (nr_cbits == codec_bits) {
- if (cbit) {
- cbyte++;
- codec_frames[cbyte] = 0;
- }
- cbit = 7;
- nr_cbits = 0;
- }
+int freedv_codec_frames_from_rawdata(struct freedv *f,
+ unsigned char *codec_frames,
+ unsigned char *rawdata) {
+ int cbit = 7;
+ int cbyte = 0;
+ int rbit = 7;
+ int rbyte = 0;
+ int modem_bits = freedv_get_bits_per_modem_frame(f);
+ int codec_bits = freedv_get_bits_per_codec_frame(f);
+ int nr_cbits = 0;
+ int i;
+
+ codec_frames[0] = 0;
+ for (i = 0; i < modem_bits; i++) {
+ codec_frames[cbyte] |= ((rawdata[rbyte] >> rbit) & 1) << cbit;
+
+ rbit--;
+ if (rbit < 0) {
+ rbit = 7;
+ rbyte++;
}
- return f->n_codec_frames;
-}
-
-int freedv_rawdata_from_codec_frames(struct freedv *f, unsigned char *rawdata, unsigned char *codec_frames)
-{
- int cbit = 7;
- int cbyte = 0;
- int rbit = 7;
- int rbyte = 0;
- int modem_bits = freedv_get_bits_per_modem_frame(f);
- int codec_bits = freedv_get_bits_per_codec_frame(f);
- int nr_cbits = 0;
- int i;
-
- rawdata[rbyte] = 0;
- for (i = 0; i < modem_bits; i++) {
- rawdata[rbyte] |= ((codec_frames[cbyte] >> cbit) & 1) << rbit;
-
- rbit--;
- if (rbit < 0) {
- rbit = 7;
- rbyte++;
- rawdata[rbyte] = 0;
- }
- cbit--;
- if (cbit < 0) {
- cbit = 7;
- cbyte++;
- }
-
- nr_cbits++;
- if (nr_cbits == codec_bits) {
- if (cbit)
- cbyte++;
- cbit = 7;
- nr_cbits = 0;
- }
+ cbit--;
+ if (cbit < 0) {
+ cbit = 7;
+ cbyte++;
+ codec_frames[cbyte] = 0;
+ }
+ nr_cbits++;
+ if (nr_cbits == codec_bits) {
+ if (cbit) {
+ cbyte++;
+ codec_frames[cbyte] = 0;
+ }
+ cbit = 7;
+ nr_cbits = 0;
}
- return f->n_codec_frames;
+ }
+ return f->n_codec_frames;
}
+int freedv_rawdata_from_codec_frames(struct freedv *f, unsigned char *rawdata,
+ unsigned char *codec_frames) {
+ int cbit = 7;
+ int cbyte = 0;
+ int rbit = 7;
+ int rbyte = 0;
+ int modem_bits = freedv_get_bits_per_modem_frame(f);
+ int codec_bits = freedv_get_bits_per_codec_frame(f);
+ int nr_cbits = 0;
+ int i;
+
+ rawdata[rbyte] = 0;
+ for (i = 0; i < modem_bits; i++) {
+ rawdata[rbyte] |= ((codec_frames[cbyte] >> cbit) & 1) << rbit;
+
+ rbit--;
+ if (rbit < 0) {
+ rbit = 7;
+ rbyte++;
+ rawdata[rbyte] = 0;
+ }
+
+ cbit--;
+ if (cbit < 0) {
+ cbit = 7;
+ cbyte++;
+ }
+
+ nr_cbits++;
+ if (nr_cbits == codec_bits) {
+ if (cbit) cbyte++;
+ cbit = 7;
+ nr_cbits = 0;
+ }
+ }
+ return f->n_codec_frames;
+}
/*---------------------------------------------------------------------------*\
@@ -726,119 +736,127 @@ int freedv_rawdata_from_codec_frames(struct freedv *f, unsigned char *rawdata, u
\*---------------------------------------------------------------------------*/
int freedv_rx(struct freedv *f, short speech_out[], short demod_in[]) {
- assert(f != NULL);
- int i;
- int nin = freedv_nin(f);
- f->nin_prev = nin;
-
- assert(nin <= f->n_max_modem_samples);
-
- /* FSK Rx happens in real floats, so convert to those and call their demod here */
- 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) ){
- float rx_float[f->n_max_modem_samples];
- for(i=0; i<nin; i++) {
- rx_float[i] = ((float)demod_in[i]);
- }
- return freedv_floatrx(f,speech_out,rx_float);
+ assert(f != NULL);
+ int i;
+ int nin = freedv_nin(f);
+ f->nin_prev = nin;
+
+ assert(nin <= f->n_max_modem_samples);
+
+ /* FSK Rx happens in real floats, so convert to those and call their demod
+ * here */
+ 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)) {
+ float rx_float[f->n_max_modem_samples];
+ for (i = 0; i < nin; i++) {
+ rx_float[i] = ((float)demod_in[i]);
}
+ return freedv_floatrx(f, speech_out, rx_float);
+ }
- if ( FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2020B, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2020C, f->mode)) {
-
- float gain = 1.0f;
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_1600, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_2020B, f->mode)) {
+ float gain = 1.0f;
- assert(nin <= f->n_max_modem_samples);
- COMP rx_fdm[f->n_max_modem_samples];
+ assert(nin <= f->n_max_modem_samples);
+ COMP rx_fdm[f->n_max_modem_samples];
- for(i=0; i<nin; i++) {
- rx_fdm[i].real = gain*(float)demod_in[i];
- rx_fdm[i].imag = 0.0f;
- }
- return freedv_comprx(f, speech_out, rx_fdm);
+ for (i = 0; i < nin; i++) {
+ rx_fdm[i].real = gain * (float)demod_in[i];
+ rx_fdm[i].imag = 0.0f;
}
+ return freedv_comprx(f, speech_out, rx_fdm);
+ }
- /* special low memory version for 700D, to help with stm32 port */
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode)) {
- float gain = 2.0f; /* keep levels the same as Octave simulations and C unit tests for real signals */
- return freedv_shortrx(f, speech_out, demod_in, gain);
- }
+ /* special low memory version for 700D, to help with stm32 port */
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700D, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_700E, f->mode)) {
+ float gain = 2.0f; /* keep levels the same as Octave simulations and C unit
+ tests for real signals */
+ return freedv_shortrx(f, speech_out, demod_in, gain);
+ }
- assert(1); /* should never get here */
- return 0;
+ assert(1); /* should never get here */
+ return 0;
}
/* complex sample input version of freedv_rx() */
int freedv_comprx(struct freedv *f, short speech_out[], COMP demod_in[]) {
- assert(f != NULL);
- assert(f->nin <= f->n_max_modem_samples);
- int rx_status = 0;
- f->nin_prev = freedv_nin(f);
+ assert(f != NULL);
+ assert(f->nin <= f->n_max_modem_samples);
+ int rx_status = 0;
+ f->nin_prev = freedv_nin(f);
- if (FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode)) {
- rx_status = freedv_comprx_fdmdv_1600(f, demod_in);
- }
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) {
- rx_status = freedv_comprx_700c(f, demod_in);
- }
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_1600, f->mode)) {
+ rx_status = freedv_comprx_fdmdv_1600(f, demod_in);
+ }
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode)) {
+ rx_status = freedv_comprx_700c(f, demod_in);
+ }
- 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))) {
- rx_status = freedv_comprx_fsk(f, demod_in);
- }
+ 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))) {
+ rx_status = freedv_comprx_fsk(f, demod_in);
+ }
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode)) {
- rx_status = freedv_comp_short_rx_ofdm(f, (void*)demod_in, 0, 2.0f); // was 1.0 ??
- }
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700D, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_700E, f->mode)) {
+ rx_status =
+ freedv_comp_short_rx_ofdm(f, (void *)demod_in, 0, 2.0f); // was 1.0 ??
+ }
- if (FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2020B, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2020C, f->mode)) {
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_2020B, f->mode)) {
#ifdef __LPCNET__
- rx_status = freedv_comprx_2020(f, demod_in);
+ rx_status = freedv_comprx_2020(f, demod_in);
#endif
- }
+ }
- short demod_in_short[f->nin_prev];
+ short demod_in_short[f->nin_prev];
- for(int i=0; i<f->nin_prev; i++)
- demod_in_short[i] = demod_in[i].real;
+ for (int i = 0; i < f->nin_prev; i++) demod_in_short[i] = demod_in[i].real;
- return freedv_bits_to_speech(f, speech_out, demod_in_short, rx_status);
+ return freedv_bits_to_speech(f, speech_out, demod_in_short, rx_status);
}
/* memory efficient real short version - just for 700D on the SM1000 */
-int freedv_shortrx(struct freedv *f, short speech_out[], short demod_in[], float gain) {
- assert(f != NULL);
- int rx_status = 0;
- f->nin_prev = f->nin;
+int freedv_shortrx(struct freedv *f, short speech_out[], short demod_in[],
+ float gain) {
+ assert(f != NULL);
+ int rx_status = 0;
+ f->nin_prev = f->nin;
- // At this stage short interface only supported for 700D, to help
- // memory requirements on stm32
- assert((f->mode == FREEDV_MODE_700D) || (f->mode == FREEDV_MODE_700E));
- assert(f->nin <= f->n_max_modem_samples);
+ // At this stage short interface only supported for 700D, to help
+ // memory requirements on stm32
+ assert((f->mode == FREEDV_MODE_700D) || (f->mode == FREEDV_MODE_700E));
+ assert(f->nin <= f->n_max_modem_samples);
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode)) {
- rx_status = freedv_comp_short_rx_ofdm(f, (void*)demod_in, 1, gain);
- }
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700D, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_700E, f->mode)) {
+ rx_status = freedv_comp_short_rx_ofdm(f, (void *)demod_in, 1, gain);
+ }
- return freedv_bits_to_speech(f, speech_out, demod_in, rx_status);
+ return freedv_bits_to_speech(f, speech_out, demod_in, rx_status);
}
+/* helper function, unpacked bits are much easier to work with inside the modem
+ */
-/* helper function, unpacked bits are much easier to work with inside the modem */
-
-static void codec2_decode_upacked(struct freedv *f, short speech_out[], uint8_t unpacked_bits[]) {
- int n_packed = (f->bits_per_codec_frame + 7) / 8;
- uint8_t packed_codec_bits[n_packed];
+static void codec2_decode_upacked(struct freedv *f, short speech_out[],
+ uint8_t unpacked_bits[]) {
+ int n_packed = (f->bits_per_codec_frame + 7) / 8;
+ uint8_t packed_codec_bits[n_packed];
- freedv_pack(packed_codec_bits, unpacked_bits, f->bits_per_codec_frame);
- codec2_decode(f->codec2, speech_out, packed_codec_bits);
+ freedv_pack(packed_codec_bits, unpacked_bits, f->bits_per_codec_frame);
+ codec2_decode(f->codec2, speech_out, packed_codec_bits);
}
-
/*---------------------------------------------------------------------------* \
FUNCTION....: freedv_rx_bits_to_speech
@@ -856,197 +874,213 @@ static void codec2_decode_upacked(struct freedv *f, short speech_out[], uint8_t
We may not have demod sync, so various pass through options may happen
with the input samples.
We may squelch based on SNR.
- Need to handle various codecs, and varying number of codec frames per modem frame
- Squelch audio if test frames are being sent
- Determine how many speech samples to return, which will vary if in sync/out of sync
- Work with real and complex inputs (complex wrapper)
- Attenuate audio on pass through
- Deal with 700D first frame burble, and different sync states from OFDM modes like 700D
- Output no samples if squelched, we assume it's OK for the audio sink to run dry
- A FIFO required on output to smooth sample flow to audio sink
+ Need to handle various codecs, and varying number of codec frames per modem
+ frame.
+ Squelch audio if test frames are being sent.
+ Determine how many speech samples to return, which will vary if in
+ sync/out of sync Work with real and complex inputs (complex wrapper)
+ Attenuate audio on pass through.
+ Deal with 700D first frame burble, and different sync states from OFDM
+ modes like 700D.
+ Output no samples if squelched, we assume it's OK for the audio sink to run
+ dry.
+ A FIFO is required on output to smooth sample flow to audio sink.
Don't decode when we are sending test frames
\*---------------------------------------------------------------------------*/
-int freedv_bits_to_speech(struct freedv *f, short speech_out[], short demod_in[], int rx_status) {
- int nout = 0;
- int decode_speech = 0;
- if ((rx_status & FREEDV_RX_SYNC) == 0) {
-
- if (!f->squelch_en) {
-
- /* pass through received samples so we can hear what's going on, e.g. during tuning */
-
- if ((f->mode == FREEDV_MODE_2020) || (f->mode == FREEDV_MODE_2020B) ||
- (f->mode == FREEDV_MODE_2020C)) {
- /* 8kHz modem sample rate but 16 kHz speech sample
- rate, so we need to resample */
- nout = 2*f->nin_prev;
- assert(nout <= freedv_get_n_max_speech_samples(f));
- float tmp[nout];
- for(int i=0; i<nout/2; i++)
- f->passthrough_2020[FDMDV_OS_TAPS_16K+i] = demod_in[i];
- fdmdv_8_to_16(tmp, &f->passthrough_2020[FDMDV_OS_TAPS_16K], nout/2);
- for(int i=0; i<nout; i++)
- speech_out[i] = f->passthrough_gain*tmp[i];
- } else {
- /* Speech and modem rates might be different */
- int rate_factor = f->modem_sample_rate / f-> speech_sample_rate;
- nout = f->nin_prev / rate_factor;
- for(int i=0; i<nout; i++)
- speech_out[i] = f->passthrough_gain*demod_in[i * rate_factor];
- }
- }
+int freedv_bits_to_speech(struct freedv *f, short speech_out[],
+ short demod_in[], int rx_status) {
+ int nout = 0;
+ int decode_speech = 0;
+ if ((rx_status & FREEDV_RX_SYNC) == 0) {
+ if (!f->squelch_en) {
+ /* pass through received samples so we can hear what's going on, e.g.
+ * during tuning */
+
+ if ((f->mode == FREEDV_MODE_2020) || (f->mode == FREEDV_MODE_2020B)) {
+ /* 8kHz modem sample rate but 16 kHz speech sample
+ rate, so we need to resample */
+ nout = 2 * f->nin_prev;
+ assert(nout <= freedv_get_n_max_speech_samples(f));
+ float tmp[nout];
+ for (int i = 0; i < nout / 2; i++)
+ f->passthrough_2020[FDMDV_OS_TAPS_16K + i] = demod_in[i];
+ fdmdv_8_to_16(tmp, &f->passthrough_2020[FDMDV_OS_TAPS_16K], nout / 2);
+ for (int i = 0; i < nout; i++)
+ speech_out[i] = f->passthrough_gain * tmp[i];
+ } else {
+ /* Speech and modem rates might be different */
+ int rate_factor = f->modem_sample_rate / f->speech_sample_rate;
+ nout = f->nin_prev / rate_factor;
+ for (int i = 0; i < nout; i++)
+ speech_out[i] = f->passthrough_gain * demod_in[i * rate_factor];
+ }
}
+ }
- if ((rx_status & FREEDV_RX_SYNC) && (rx_status & FREEDV_RX_BITS) && !f->test_frames) {
- /* following logic is tricky so spell it out clearly, see table
- in: https://github.com/drowe67/codec2/pull/111 */
-
- if (!f->squelch_en) {
- decode_speech = 1;
- } else {
- /* squelch is enabled */
-
- /* anti-burble case - don't decode on trial sync unless the
- frame has no bit errors. This prevents short lived trial
- sync cases generating random bursts of audio */
- if (rx_status & FREEDV_RX_TRIAL_SYNC) {
- if ((rx_status & FREEDV_RX_BIT_ERRORS) == 0)
- decode_speech = 1;
- }
- else {
- /* sync is solid - decode even through fades as there is still some speech info there */
- if (f->snr_est > f->snr_squelch_thresh)
- decode_speech = 1;
- }
- }
-
+ if ((rx_status & FREEDV_RX_SYNC) && (rx_status & FREEDV_RX_BITS) &&
+ !f->test_frames) {
+ /* following logic is tricky so spell it out clearly, see table
+ in: https://github.com/drowe67/codec2/pull/111 */
+
+ if (!f->squelch_en) {
+ decode_speech = 1;
+ } else {
+ /* squelch is enabled */
+
+ /* anti-burble case - don't decode on trial sync unless the
+ frame has no bit errors. This prevents short lived trial
+ sync cases generating random bursts of audio */
+ if (rx_status & FREEDV_RX_TRIAL_SYNC) {
+ if ((rx_status & FREEDV_RX_BIT_ERRORS) == 0) decode_speech = 1;
+ } else {
+ /* sync is solid - decode even through fades as there is still some
+ * speech info there */
+ if (f->snr_est > f->snr_squelch_thresh) decode_speech = 1;
+ }
}
+ }
- if (decode_speech) {
- if(FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2020B, f->mode)||
- FDV_MODE_ACTIVE( FREEDV_MODE_2020C, f->mode)) {
+ if (decode_speech) {
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_2020B, f->mode)) {
#ifdef __LPCNET__
- /* LPCNet decoder */
-
- int bits_per_codec_frame = lpcnet_bits_per_frame(f->lpcnet);
- int data_bits_per_frame = f->ldpc->data_bits_per_frame;
- int frames = data_bits_per_frame/bits_per_codec_frame;
-
- nout = f->n_speech_samples;
- for (int i = 0; i < frames; i++) {
- lpcnet_dec(f->lpcnet, (char*) f->rx_payload_bits + i*bits_per_codec_frame, speech_out);
- /* ear protection: on frames with errors and clipping, reduce level by 12dB */
- if (rx_status & FREEDV_RX_BIT_ERRORS) {
- int max = 0.0;
- for (int j=0; j<lpcnet_samples_per_frame(f->lpcnet); j++)
- if (abs(speech_out[j]) > max) max = abs(speech_out[j]);
- if (max == 32767)
- for (int j=0; j<lpcnet_samples_per_frame(f->lpcnet); j++) speech_out[j] *= 0.25;
- }
-
- speech_out += lpcnet_samples_per_frame(f->lpcnet);
- }
+ /* LPCNet decoder */
+
+ int bits_per_codec_frame = lpcnet_bits_per_frame(f->lpcnet);
+ int data_bits_per_frame = f->ldpc->data_bits_per_frame;
+ int frames = data_bits_per_frame / bits_per_codec_frame;
+
+ nout = f->n_speech_samples;
+ for (int i = 0; i < frames; i++) {
+ lpcnet_dec(f->lpcnet,
+ (char *)f->rx_payload_bits + i * bits_per_codec_frame,
+ speech_out);
+ /* ear protection: on frames with errors and clipping, reduce level by
+ * 12dB */
+ if (rx_status & FREEDV_RX_BIT_ERRORS) {
+ int max = 0.0;
+ for (int j = 0; j < lpcnet_samples_per_frame(f->lpcnet); j++)
+ if (abs(speech_out[j]) > max) max = abs(speech_out[j]);
+ if (max == 32767)
+ for (int j = 0; j < lpcnet_samples_per_frame(f->lpcnet); j++)
+ speech_out[j] *= 0.25;
+ }
+
+ speech_out += lpcnet_samples_per_frame(f->lpcnet);
+ }
#endif
+ } else {
+ /* codec 2 decoder */
+
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700D, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_700E, f->mode)) {
+ nout = f->n_speech_samples;
+ for (int i = 0; i < f->n_codec_frames; i++) {
+ codec2_decode_upacked(
+ f, speech_out, f->rx_payload_bits + i * f->bits_per_codec_frame);
+ speech_out += codec2_samples_per_frame(f->codec2);
+ }
+ } else {
+ /* non-interleaved Codec 2 modes */
+
+ nout = f->n_speech_samples;
+ if ((FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode)) ||
+ (FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode)))
+ codec2_decode(f->codec2, speech_out, f->rx_payload_bits);
+ else if (FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode)) {
+ codec2_decode(f->codec2, &speech_out[0], &f->rx_payload_bits[0]);
+ codec2_decode(f->codec2, &speech_out[320], &f->rx_payload_bits[4]);
} else {
- /* codec 2 decoder */
-
- if(FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode)) {
- nout = f->n_speech_samples;
- for (int i = 0; i < f->n_codec_frames; i++) {
- codec2_decode_upacked(f, speech_out, f->rx_payload_bits + i*f->bits_per_codec_frame);
- speech_out += codec2_samples_per_frame(f->codec2);
- }
- } else {
- /* non-interleaved Codec 2 modes */
-
- nout = f->n_speech_samples;
- if ( (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode)) || (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)))
- codec2_decode(f->codec2, speech_out, f->rx_payload_bits);
- else if (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)) {
- codec2_decode(f->codec2, &speech_out[ 0], &f->rx_payload_bits[0]);
- codec2_decode(f->codec2, &speech_out[320], &f->rx_payload_bits[4]);
- } else {
- for (int i = 0; i <f->n_codec_frames; i++) {
- codec2_decode_upacked(f, speech_out, f->rx_payload_bits + i*f->bits_per_codec_frame);
- speech_out += codec2_samples_per_frame(f->codec2);
- }
- }
- }
+ for (int i = 0; i < f->n_codec_frames; i++) {
+ codec2_decode_upacked(
+ f, speech_out,
+ f->rx_payload_bits + i * f->bits_per_codec_frame);
+ speech_out += codec2_samples_per_frame(f->codec2);
+ }
}
+ }
}
+ }
- if (f->verbose == 3) {
- fprintf(stderr, " sqen: %d nout: %d decsp: %d\n", f->squelch_en, nout, decode_speech);
- }
+ if (f->verbose == 3) {
+ fprintf(stderr, " sqen: %d nout: %d decsp: %d\n", f->squelch_en, nout,
+ decode_speech);
+ }
- f->rx_status= rx_status;
- assert(nout <= freedv_get_n_max_speech_samples(f));
- return nout;
+ f->rx_status = rx_status;
+ assert(nout <= freedv_get_n_max_speech_samples(f));
+ return nout;
}
+/* a way to receive raw frames of bytes, or speech data that will be
+ * decompressed externally */
+int freedv_rawdatarx(struct freedv *f, unsigned char *packed_payload_bits,
+ short demod_in[]) {
+ assert(f != NULL);
+ int nin = freedv_nin(f);
+ assert(nin <= f->n_max_modem_samples);
+ COMP demod_in_comp[f->n_max_modem_samples];
+
+ for (int i = 0; i < nin; i++) {
+ demod_in_comp[i].real = (float)demod_in[i];
+ demod_in_comp[i].imag = 0.0;
+ }
-/* a way to receive raw frames of bytes, or speech data that will be decompressed externally */
-int freedv_rawdatarx(struct freedv *f, unsigned char *packed_payload_bits, short demod_in[])
-{
- assert(f != NULL);
- int nin = freedv_nin(f);
- assert(nin <= f->n_max_modem_samples);
- COMP demod_in_comp[f->n_max_modem_samples];
-
- for(int i=0; i<nin; i++) {
- demod_in_comp[i].real = (float)demod_in[i];
- demod_in_comp[i].imag = 0.0;
- }
-
- return freedv_rawdatacomprx(f, packed_payload_bits, demod_in_comp);
+ return freedv_rawdatacomprx(f, packed_payload_bits, demod_in_comp);
}
-/* a way to receive raw frames of bytes, or speech data that will be decompressed externally */
-int freedv_rawdatacomprx(struct freedv *f, unsigned char *packed_payload_bits, COMP demod_in[])
-{
- assert(f != NULL);
- int ret = 0;
- int rx_status = 0;
-
- /* FSK modes used packed bits internally */
- 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)){
- rx_status = freedv_comprx_fsk(f, demod_in);
- f->rx_status = rx_status;
- if (rx_status & FREEDV_RX_BITS) {
- ret = (freedv_get_bits_per_modem_frame(f) + 7) / 8;
- freedv_rawdata_from_codec_frames(f, packed_payload_bits, f->rx_payload_bits);
- }
- return ret;
+/* a way to receive raw frames of bytes, or speech data that will be
+ * decompressed externally */
+int freedv_rawdatacomprx(struct freedv *f, unsigned char *packed_payload_bits,
+ COMP demod_in[]) {
+ assert(f != NULL);
+ int ret = 0;
+ int rx_status = 0;
+
+ /* FSK modes used packed bits internally */
+ 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)) {
+ rx_status = freedv_comprx_fsk(f, demod_in);
+ f->rx_status = rx_status;
+ if (rx_status & FREEDV_RX_BITS) {
+ ret = (freedv_get_bits_per_modem_frame(f) + 7) / 8;
+ freedv_rawdata_from_codec_frames(f, packed_payload_bits,
+ f->rx_payload_bits);
}
+ return ret;
+ }
- if (FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode)) rx_status = freedv_comprx_fdmdv_1600(f, demod_in);
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) rx_status = freedv_comprx_700c(f, demod_in);
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC4, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_DATAC13, f->mode)) rx_status = freedv_comp_short_rx_ofdm(f, (void*)demod_in, 0, 1.0f);
- if (FDV_MODE_ACTIVE( FREEDV_MODE_FSK_LDPC, f->mode)) {
- rx_status = freedv_rx_fsk_ldpc_data(f, demod_in);
- }
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_1600, f->mode))
+ rx_status = freedv_comprx_fdmdv_1600(f, demod_in);
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode))
+ rx_status = freedv_comprx_700c(f, demod_in);
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700D, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC0, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC1, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC3, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC4, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_DATAC13, f->mode))
+ rx_status = freedv_comp_short_rx_ofdm(f, (void *)demod_in, 0, 1.0f);
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_FSK_LDPC, f->mode)) {
+ rx_status = freedv_rx_fsk_ldpc_data(f, demod_in);
+ }
- if (rx_status & FREEDV_RX_BITS) {
- ret = (f->bits_per_modem_frame+7)/8;
- freedv_pack(packed_payload_bits, f->rx_payload_bits, f->bits_per_modem_frame);
- }
+ if (rx_status & FREEDV_RX_BITS) {
+ ret = (f->bits_per_modem_frame + 7) / 8;
+ freedv_pack(packed_payload_bits, f->rx_payload_bits,
+ f->bits_per_modem_frame);
+ }
- /* might want to check this for errors, e.g. if reliable data is important */
- f->rx_status= rx_status;
+ /* might want to check this for errors, e.g. if reliable data is important */
+ f->rx_status = rx_status;
- return ret;
+ return ret;
}
-
/*---------------------------------------------------------------------------* \
FUNCTION....: freedv_get_version
@@ -1058,10 +1092,7 @@ int freedv_rawdatacomprx(struct freedv *f, unsigned char *packed_payload_bits, C
\*---------------------------------------------------------------------------*/
-int freedv_get_version(void)
-{
- return VERSION;
-}
+int freedv_get_version(void) { return VERSION; }
/*---------------------------------------------------------------------------* \
@@ -1074,10 +1105,7 @@ int freedv_get_version(void)
\*---------------------------------------------------------------------------*/
static char git_hash[] = GIT_HASH;
-char *freedv_get_hash(void)
-{
- return git_hash;
-}
+char *freedv_get_hash(void) { return git_hash; }
/*---------------------------------------------------------------------------*\
@@ -1099,13 +1127,13 @@ char *freedv_get_hash(void)
\*---------------------------------------------------------------------------*/
-void freedv_set_callback_txt(struct freedv *f, freedv_callback_rx rx, freedv_callback_tx tx, void *state)
-{
- if (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode) == false) {
- f->freedv_put_next_rx_char = rx;
- f->freedv_get_next_tx_char = tx;
- f->callback_state = state;
- }
+void freedv_set_callback_txt(struct freedv *f, freedv_callback_rx rx,
+ freedv_callback_tx tx, void *state) {
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode) == false) {
+ f->freedv_put_next_rx_char = rx;
+ f->freedv_get_next_tx_char = tx;
+ f->callback_state = state;
+ }
}
/*---------------------------------------------------------------------------*\
@@ -1115,8 +1143,8 @@ void freedv_set_callback_txt(struct freedv *f, freedv_callback_rx rx, freedv_cal
DATE CREATED: 19 August 2021
Set the callback functions and the callback state pointer that will
- be used to provide the raw symbols for the aux txt channel. The
- freedv_callback_rx_sym is a function pointer that will be called to
+ be used to provide the raw symbols for the aux txt channel. The
+ freedv_callback_rx_sym is a function pointer that will be called to
return received symbols. The callback state is a user-defined
void pointer that will be passed to the callback function. Any or
all can be NULL, and the default is all NULL.
@@ -1127,16 +1155,15 @@ void freedv_set_callback_txt(struct freedv *f, freedv_callback_rx rx, freedv_cal
Note: Active for OFDM modes only (700D/E, 2020).
\*---------------------------------------------------------------------------*/
-void freedv_set_callback_txt_sym(struct freedv *f, freedv_callback_rx_sym rx, void *state)
-{
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode ) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode ) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode ) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2020B, f->mode) ||
- FDV_MODE_ACTIVE( FREEDV_MODE_2020C, f->mode)) {
- f->freedv_put_next_rx_symbol = rx;
- f->callback_state_sym = state;
- }
+void freedv_set_callback_txt_sym(struct freedv *f, freedv_callback_rx_sym rx,
+ void *state) {
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700D, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_700E, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_2020B, f->mode)) {
+ f->freedv_put_next_rx_symbol = rx;
+ f->callback_state_sym = state;
+ }
}
/*---------------------------------------------------------------------------*\
@@ -1159,12 +1186,14 @@ void freedv_set_callback_txt_sym(struct freedv *f, freedv_callback_rx_sym rx, vo
\*---------------------------------------------------------------------------*/
-void freedv_set_callback_protocol(struct freedv *f, freedv_callback_protorx rx, freedv_callback_prototx tx, void *callback_state){
- if (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode) == false) {
- f->freedv_put_next_proto = rx;
- f->freedv_get_next_proto = tx;
- f->proto_callback_state = callback_state;
- }
+void freedv_set_callback_protocol(struct freedv *f, freedv_callback_protorx rx,
+ freedv_callback_prototx tx,
+ void *callback_state) {
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode) == false) {
+ f->freedv_put_next_proto = rx;
+ f->freedv_get_next_proto = tx;
+ f->proto_callback_state = callback_state;
+ }
}
/*---------------------------------------------------------------------------*\
@@ -1184,16 +1213,18 @@ void freedv_set_callback_protocol(struct freedv *f, freedv_callback_protorx rx,
\*---------------------------------------------------------------------------*/
-void freedv_set_callback_data(struct freedv *f, freedv_callback_datarx datarx, freedv_callback_datatx datatx, void *callback_state) {
- 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))){
- if (!f->deframer->fdc)
- f->deframer->fdc = freedv_data_channel_create();
- if (!f->deframer->fdc)
- return;
-
- freedv_data_set_cb_rx(f->deframer->fdc, datarx, callback_state);
- freedv_data_set_cb_tx(f->deframer->fdc, datatx, callback_state);
- }
+void freedv_set_callback_data(struct freedv *f, freedv_callback_datarx datarx,
+ freedv_callback_datatx datatx,
+ void *callback_state) {
+ 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))) {
+ if (!f->deframer->fdc) f->deframer->fdc = freedv_data_channel_create();
+ if (!f->deframer->fdc) return;
+
+ freedv_data_set_cb_rx(f->deframer->fdc, datarx, callback_state);
+ freedv_data_set_cb_tx(f->deframer->fdc, datatx, callback_state);
+ }
}
/*---------------------------------------------------------------------------*\
@@ -1211,16 +1242,15 @@ void freedv_set_callback_data(struct freedv *f, freedv_callback_datarx datarx, f
\*---------------------------------------------------------------------------*/
-void freedv_set_data_header(struct freedv *f, unsigned char *header)
-{
- 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))){
- if (!f->deframer->fdc)
- f->deframer->fdc = freedv_data_channel_create();
- if (!f->deframer->fdc)
- return;
+void freedv_set_data_header(struct freedv *f, unsigned char *header) {
+ 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))) {
+ if (!f->deframer->fdc) f->deframer->fdc = freedv_data_channel_create();
+ if (!f->deframer->fdc) return;
- freedv_data_set_header(f->deframer->fdc, header);
- }
+ freedv_data_set_header(f->deframer->fdc, header);
+ }
}
/*---------------------------------------------------------------------------*\
@@ -1234,14 +1264,13 @@ void freedv_set_data_header(struct freedv *f, unsigned char *header)
\*---------------------------------------------------------------------------*/
-void freedv_get_modem_stats(struct freedv *f, int *sync, float *snr_est)
-{
- if (FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode))
- fdmdv_get_demod_stats(f->fdmdv, &f->stats);
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode))
- cohpsk_get_demod_stats(f->cohpsk, &f->stats);
- if (sync) *sync = f->sync;
- if (snr_est) *snr_est = f->snr_est;
+void freedv_get_modem_stats(struct freedv *f, int *sync, float *snr_est) {
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_1600, f->mode))
+ fdmdv_get_demod_stats(f->fdmdv, &f->stats);
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode))
+ cohpsk_get_demod_stats(f->cohpsk, &f->stats);
+ if (sync) *sync = f->sync;
+ if (snr_est) *snr_est = f->snr_est;
}
/*---------------------------------------------------------------------------*\
@@ -1255,75 +1284,93 @@ void freedv_get_modem_stats(struct freedv *f, int *sync, float *snr_est)
\*---------------------------------------------------------------------------*/
-void freedv_set_test_frames (struct freedv *f, int val) {f->test_frames = val;}
-void freedv_set_test_frames_diversity (struct freedv *f, int val) {f->test_frames_diversity = val;}
-void freedv_set_squelch_en (struct freedv *f, bool val) {f->squelch_en = val;}
-void freedv_set_total_bit_errors (struct freedv *f, int val) {f->total_bit_errors = val;}
-void freedv_set_total_bits (struct freedv *f, int val) {f->total_bits = val;}
-void freedv_set_total_bit_errors_coded (struct freedv *f, int val) {f->total_bit_errors_coded = val;}
-void freedv_set_total_bits_coded (struct freedv *f, int val) {f->total_bits_coded = val;}
-void freedv_set_total_packet_errors (struct freedv *f, int val) {f->total_packet_errors = val;}
-void freedv_set_total_packets (struct freedv *f, int val) {f->total_packets = val;}
-void freedv_set_varicode_code_num (struct freedv *f, int val) {varicode_set_code_num(&f->varicode_dec_states, val);}
-void freedv_set_ext_vco (struct freedv *f, int val) {f->ext_vco = val;}
-void freedv_set_snr_squelch_thresh (struct freedv *f, float val) {f->snr_squelch_thresh = val;}
-void freedv_set_tx_amp (struct freedv *f, float amp) {f->tx_amp = amp;}
-void freedv_passthrough_gain (struct freedv *f, float g) {f->passthrough_gain = g;}
+void freedv_set_test_frames(struct freedv *f, int val) { f->test_frames = val; }
+void freedv_set_test_frames_diversity(struct freedv *f, int val) {
+ f->test_frames_diversity = val;
+}
+void freedv_set_squelch_en(struct freedv *f, bool val) { f->squelch_en = val; }
+void freedv_set_total_bit_errors(struct freedv *f, int val) {
+ f->total_bit_errors = val;
+}
+void freedv_set_total_bits(struct freedv *f, int val) { f->total_bits = val; }
+void freedv_set_total_bit_errors_coded(struct freedv *f, int val) {
+ f->total_bit_errors_coded = val;
+}
+void freedv_set_total_bits_coded(struct freedv *f, int val) {
+ f->total_bits_coded = val;
+}
+void freedv_set_total_packet_errors(struct freedv *f, int val) {
+ f->total_packet_errors = val;
+}
+void freedv_set_total_packets(struct freedv *f, int val) {
+ f->total_packets = val;
+}
+void freedv_set_varicode_code_num(struct freedv *f, int val) {
+ varicode_set_code_num(&f->varicode_dec_states, val);
+}
+void freedv_set_ext_vco(struct freedv *f, int val) { f->ext_vco = val; }
+void freedv_set_snr_squelch_thresh(struct freedv *f, float val) {
+ f->snr_squelch_thresh = val;
+}
+void freedv_set_tx_amp(struct freedv *f, float amp) { f->tx_amp = amp; }
+void freedv_passthrough_gain(struct freedv *f, float g) {
+ f->passthrough_gain = g;
+}
/* supported by 700C, 700D, 700E */
void freedv_set_clip(struct freedv *f, bool val) {
- f->clip_en = val;
- if (is_ofdm_mode(f)) {
- f->ofdm->clip_en = val;
- /* really should have BPF if we clip */
- if (val)
- ofdm_set_tx_bpf(f->ofdm, true);
- }
+ f->clip_en = val;
+ if (is_ofdm_mode(f)) {
+ f->ofdm->clip_en = val;
+ /* really should have BPF if we clip */
+ if (val) ofdm_set_tx_bpf(f->ofdm, true);
+ }
}
/* Band Pass Filter to cleanup OFDM tx waveform, only supported by some modes */
void freedv_set_tx_bpf(struct freedv *f, int val) {
- if (is_ofdm_mode(f)) {
- ofdm_set_tx_bpf(f->ofdm, val);
- }
+ if (is_ofdm_mode(f)) {
+ ofdm_set_tx_bpf(f->ofdm, val);
+ }
}
void freedv_set_phase_est_bandwidth_mode(struct freedv *f, int val) {
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode)) {
- ofdm_set_phase_est_bandwidth_mode(f->ofdm, val);
- }
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700D, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode)) {
+ ofdm_set_phase_est_bandwidth_mode(f->ofdm, val);
+ }
}
// For those FreeDV modes using the codec 2 700C vocoder 700C/D/E/800XA
void freedv_set_eq(struct freedv *f, bool val) {
- if (f->codec2 != NULL) {
- codec2_700c_eq(f->codec2, val);
- }
+ if (f->codec2 != NULL) {
+ codec2_700c_eq(f->codec2, val);
+ }
}
void freedv_set_verbose(struct freedv *f, int verbosity) {
- f->verbose = verbosity;
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) {
- cohpsk_set_verbose(f->cohpsk, f->verbose);
- }
- if (is_ofdm_mode(f)) {
- ofdm_set_verbose(f->ofdm, f->verbose-1);
- }
+ f->verbose = verbosity;
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode)) {
+ cohpsk_set_verbose(f->cohpsk, f->verbose);
+ }
+ if (is_ofdm_mode(f)) {
+ ofdm_set_verbose(f->ofdm, f->verbose - 1);
+ }
}
-void freedv_set_callback_error_pattern(struct freedv *f, freedv_calback_error_pattern cb, void *state)
-{
- f->freedv_put_error_pattern = cb;
- f->error_pattern_callback_state = state;
+void freedv_set_callback_error_pattern(struct freedv *f,
+ freedv_calback_error_pattern cb,
+ void *state) {
+ f->freedv_put_error_pattern = cb;
+ f->error_pattern_callback_state = state;
}
void freedv_set_carrier_ampl(struct freedv *f, int c, float ampl) {
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode))
- {
- cohpsk_set_carrier_ampl(f->cohpsk, c, ampl);
- }
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode)) {
+ cohpsk_set_carrier_ampl(f->cohpsk, c, ampl);
+ }
}
/*---------------------------------------------------------------------------* \
@@ -1333,31 +1380,31 @@ void freedv_set_carrier_ampl(struct freedv *f, int c, float ampl) {
DATE CREATED: May 2018
Extended control of sync state machines for OFDM modes.
-
+
Ensure this is called in the same thread as freedv_rx().
\*---------------------------------------------------------------------------*/
void freedv_set_sync(struct freedv *freedv, int sync_cmd) {
- assert (freedv != NULL);
+ assert(freedv != NULL);
- if (freedv->ofdm != NULL) {
- ofdm_set_sync(freedv->ofdm, sync_cmd);
- }
+ if (freedv->ofdm != NULL) {
+ ofdm_set_sync(freedv->ofdm, sync_cmd);
+ }
}
// this also selects burst mode
void freedv_set_frames_per_burst(struct freedv *freedv, int framesperburst) {
- assert (freedv != NULL);
- if (freedv->ofdm != NULL) {
- // change of nomenclature as we cross into the OFDM modem layer. In the
- // OFDM modem we have packets that contain multiple "modem frames"
- ofdm_set_packets_per_burst(freedv->ofdm, framesperburst);
- }
+ assert(freedv != NULL);
+ if (freedv->ofdm != NULL) {
+ // change of nomenclature as we cross into the OFDM modem layer. In the
+ // OFDM modem we have packets that contain multiple "modem frames"
+ ofdm_set_packets_per_burst(freedv->ofdm, framesperburst);
+ }
}
-struct FSK * freedv_get_fsk(struct freedv *f){
- return f->fsk;
+struct FSK *freedv_get_fsk(struct freedv *f) {
+ return f->fsk;
}
/*---------------------------------------------------------------------------*\
@@ -1370,29 +1417,59 @@ struct FSK * freedv_get_fsk(struct freedv *f){
\*---------------------------------------------------------------------------*/
-int freedv_get_protocol_bits (struct freedv *f) {return f->n_protocol_bits;}
-int freedv_get_mode (struct freedv *f) {return f->mode;}
-int freedv_get_test_frames (struct freedv *f) {return f->test_frames;}
-int freedv_get_speech_sample_rate (struct freedv *f) {return f-> speech_sample_rate;}
-int freedv_get_n_speech_samples (struct freedv *f) {return f->n_speech_samples;}
-int freedv_get_modem_sample_rate (struct freedv *f) {return f->modem_sample_rate;}
-int freedv_get_modem_symbol_rate (struct freedv *f) {return f->modem_symbol_rate;}
-int freedv_get_n_max_modem_samples (struct freedv *f) {return f->n_max_modem_samples;}
-int freedv_get_n_nom_modem_samples (struct freedv *f) {return f->n_nom_modem_samples;}
-int freedv_get_n_tx_modem_samples (struct freedv *f) {return f->n_nat_modem_samples;}
-int freedv_get_total_bits (struct freedv *f) {return f->total_bits;}
-int freedv_get_total_bit_errors (struct freedv *f) {return f->total_bit_errors;}
-int freedv_get_total_bits_coded (struct freedv *f) {return f->total_bits_coded;}
-int freedv_get_total_bit_errors_coded (struct freedv *f) {return f->total_bit_errors_coded;}
-int freedv_get_total_packets (struct freedv *f) {return f->total_packets;}
-int freedv_get_total_packet_errors (struct freedv *f) {return f->total_packet_errors;}
-int freedv_get_sync (struct freedv *f) {return f->sync;}
-struct CODEC2 *freedv_get_codec2 (struct freedv *f) {return f->codec2;}
-int freedv_get_bits_per_codec_frame (struct freedv *f) {return f->bits_per_codec_frame;}
-int freedv_get_bits_per_modem_frame (struct freedv *f) {return f->bits_per_modem_frame;}
-int freedv_get_rx_status (struct freedv *f) {return f->rx_status;}
-void freedv_get_fsk_S_and_N (struct freedv *f, float *S, float *N) { *S = f->fsk_S[0]; *N = f->fsk_N[0]; }
-
+int freedv_get_protocol_bits(struct freedv *f) { return f->n_protocol_bits; }
+int freedv_get_mode(struct freedv *f) { return f->mode; }
+int freedv_get_test_frames(struct freedv *f) { return f->test_frames; }
+int freedv_get_speech_sample_rate(struct freedv *f) {
+ return f->speech_sample_rate;
+}
+int freedv_get_n_speech_samples(struct freedv *f) {
+ return f->n_speech_samples;
+}
+int freedv_get_modem_sample_rate(struct freedv *f) {
+ return f->modem_sample_rate;
+}
+int freedv_get_modem_symbol_rate(struct freedv *f) {
+ return f->modem_symbol_rate;
+}
+int freedv_get_n_max_modem_samples(struct freedv *f) {
+ return f->n_max_modem_samples;
+}
+int freedv_get_n_nom_modem_samples(struct freedv *f) {
+ return f->n_nom_modem_samples;
+}
+int freedv_get_n_tx_modem_samples(struct freedv *f) {
+ return f->n_nat_modem_samples;
+}
+int freedv_get_total_bits(struct freedv *f) { return f->total_bits; }
+int freedv_get_total_bit_errors(struct freedv *f) {
+ return f->total_bit_errors;
+}
+int freedv_get_total_bits_coded(struct freedv *f) {
+ return f->total_bits_coded;
+}
+int freedv_get_total_bit_errors_coded(struct freedv *f) {
+ return f->total_bit_errors_coded;
+}
+int freedv_get_total_packets(struct freedv *f) { return f->total_packets; }
+int freedv_get_total_packet_errors(struct freedv *f) {
+ return f->total_packet_errors;
+}
+int freedv_get_sync(struct freedv *f) { return f->sync; }
+struct CODEC2 *freedv_get_codec2(struct freedv *f) {
+ return f->codec2;
+}
+int freedv_get_bits_per_codec_frame(struct freedv *f) {
+ return f->bits_per_codec_frame;
+}
+int freedv_get_bits_per_modem_frame(struct freedv *f) {
+ return f->bits_per_modem_frame;
+}
+int freedv_get_rx_status(struct freedv *f) { return f->rx_status; }
+void freedv_get_fsk_S_and_N(struct freedv *f, float *S, float *N) {
+ *S = f->fsk_S[0];
+ *N = f->fsk_N[0];
+}
/*---------------------------------------------------------------------------*\
@@ -1401,127 +1478,130 @@ void freedv_get_fsk_S_and_N (struct freedv *f, float *S, float *N)
DATE CREATED: 18 feb 2022
DEFAULT.....: fmin: -50.0Hz fmax: 50.0Hz
DESCRIPTION.:
-
+
|<---fmin - | rx centre frequency | + fmax--->|
-
- Useful for handling frequency offsets,
- e.g. caused by an imprecise VFO, the trade off is more CPU power is required.
-
-\*---------------------------------------------------------------------------*/
-int freedv_set_tuning_range(struct freedv *freedv, float val_fmin, float val_fmax) {
- if (is_ofdm_data_mode(freedv) && (strcmp(freedv->ofdm->data_mode, "burst") == 0)) {
- freedv->ofdm->fmin = val_fmin;
- freedv->ofdm->fmax = val_fmax;
- return 1;
- } else {
- return 0;
- }
-}
+ Useful for handling frequency offsets,
+ e.g. caused by an imprecise VFO, the trade off is more CPU power is required.
+\*---------------------------------------------------------------------------*/
+int freedv_set_tuning_range(struct freedv *freedv, float val_fmin,
+ float val_fmax) {
+ if (is_ofdm_data_mode(freedv) &&
+ (strcmp(freedv->ofdm->data_mode, "burst") == 0)) {
+ freedv->ofdm->fmin = val_fmin;
+ freedv->ofdm->fmax = val_fmax;
+ return 1;
+ } else {
+ return 0;
+ }
+}
int freedv_get_n_max_speech_samples(struct freedv *f) {
- /* When "passing through" demod samples to the speech output
- (e.g. no sync and squelch off) f->nin bounces around with
- timing variations. So we may return
- freedv_get_n_max_modem_samples() via the speech_output[]
- array */
- int max_output_passthrough_samples;
- if (FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode) ||
- FDV_MODE_ACTIVE(FREEDV_MODE_2020B, f->mode) ||
- FDV_MODE_ACTIVE(FREEDV_MODE_2020C, f->mode))
- // In 2020 we oversample the input modem samples from 8->16 kHz
- max_output_passthrough_samples = 2*freedv_get_n_max_modem_samples(f);
- else
- max_output_passthrough_samples = freedv_get_n_max_modem_samples(f);
-
- if (max_output_passthrough_samples > f->n_speech_samples)
- return max_output_passthrough_samples;
- else
- return f->n_speech_samples;
+ /* When "passing through" demod samples to the speech output
+ (e.g. no sync and squelch off) f->nin bounces around with
+ timing variations. So we may return
+ freedv_get_n_max_modem_samples() via the speech_output[]
+ array */
+ int max_output_passthrough_samples;
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_2020B, f->mode))
+ // In 2020 we oversample the input modem samples from 8->16 kHz
+ max_output_passthrough_samples = 2 * freedv_get_n_max_modem_samples(f);
+ else
+ max_output_passthrough_samples = freedv_get_n_max_modem_samples(f);
+
+ if (max_output_passthrough_samples > f->n_speech_samples)
+ return max_output_passthrough_samples;
+ else
+ return f->n_speech_samples;
}
// Now dummy obsolete call
-int freedv_get_sync_interleaver(struct freedv *f) {
- return 1;
-}
-
-int freedv_get_sz_error_pattern(struct freedv *f)
-{
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) {
- /* if diversity disabled callback sends error pattern for upper and lower carriers */
- return f->sz_error_pattern * (2 - f->test_frames_diversity);
- } else {
- return f->sz_error_pattern;
- }
+int freedv_get_sync_interleaver(struct freedv *f) { return 1; }
+
+int freedv_get_sz_error_pattern(struct freedv *f) {
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode)) {
+ /* if diversity disabled callback sends error pattern for upper and lower
+ * carriers */
+ return f->sz_error_pattern * (2 - f->test_frames_diversity);
+ } else {
+ return f->sz_error_pattern;
+ }
}
// Get modem status, scatter/eye diagram for plotting, other goodies
-void freedv_get_modem_extended_stats(struct freedv *f, struct MODEM_STATS *stats)
-{
- if (FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode))
- fdmdv_get_demod_stats(f->fdmdv, stats);
-
- if (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)) {
- fsk_get_demod_stats(f->fsk, stats); /* eye diagram samples, clock offset etc */
- stats->snr_est = f->snr_est; /* estimated when fsk_demod() called in freedv_fsk.c */
- stats->sync = f->sync; /* sync indicator comes from framing layer */
- }
+void freedv_get_modem_extended_stats(struct freedv *f,
+ struct MODEM_STATS *stats) {
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_1600, f->mode))
+ fdmdv_get_demod_stats(f->fdmdv, stats);
+
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode) ||
+ FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode)) {
+ fsk_get_demod_stats(f->fsk,
+ stats); /* eye diagram samples, clock offset etc */
+ stats->snr_est =
+ f->snr_est; /* estimated when fsk_demod() called in freedv_fsk.c */
+ stats->sync = f->sync; /* sync indicator comes from framing layer */
+ }
- if (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)) {
- fmfsk_get_demod_stats(f->fmfsk, stats);
- stats->snr_est = f->snr_est;
- stats->sync = f->sync;
- }
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode)) {
+ fmfsk_get_demod_stats(f->fmfsk, stats);
+ stats->snr_est = f->snr_est;
+ stats->sync = f->sync;
+ }
- if (FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode)) {
- cohpsk_get_demod_stats(f->cohpsk, stats);
- }
+ if (FDV_MODE_ACTIVE(FREEDV_MODE_700C, f->mode)) {
+ cohpsk_get_demod_stats(f->cohpsk, stats);
+ }
- if (is_ofdm_mode(f)) {
- // OFDM modem stats updated when demod runs, so copy last update
- // We need to avoid over writing the FFT states which are updated by a different function
- // TODO we need a better design here: Issue #182
+ if (is_ofdm_mode(f)) {
+ // OFDM modem stats updated when demod runs, so copy last update
+ // We need to avoid over writing the FFT states which are updated by a
+ // different function
+ // TODO we need a better design here: Issue #182
#ifndef __EMBEDDED__
- size_t ncopy = (void*)stats->rx_eye - (void*)stats;
- memcpy(stats, &f->stats, ncopy);
+ size_t ncopy = (void *)stats->rx_eye - (void *)stats;
+ memcpy(stats, &f->stats, ncopy);
#endif
- stats->snr_est = f->snr_est;
- stats->sync = f->sync;
+ stats->snr_est = f->snr_est;
+ stats->sync = f->sync;
}
}
int freedv_get_n_tx_preamble_modem_samples(struct freedv *f) {
- if (f->mode == FREEDV_MODE_FSK_LDPC) {
- struct FSK *fsk = f->fsk;
- int npreamble_symbols = 50*(fsk->mode>>1);
- return fsk->Ts*npreamble_symbols;
- } else if (is_ofdm_data_mode(f)) {
- return f->ofdm->samplesperframe;
- }
-
- return 0;
+ if (f->mode == FREEDV_MODE_FSK_LDPC) {
+ struct FSK *fsk = f->fsk;
+ int npreamble_symbols = 50 * (fsk->mode >> 1);
+ return fsk->Ts * npreamble_symbols;
+ } else if (is_ofdm_data_mode(f)) {
+ return f->ofdm->samplesperframe;
+ }
+
+ return 0;
}
int freedv_get_n_tx_postamble_modem_samples(struct freedv *f) {
- if (is_ofdm_data_mode(f)) {
- return f->ofdm->samplesperframe;
- }
-
- return 0;
+ if (is_ofdm_data_mode(f)) {
+ return f->ofdm->samplesperframe;
+ }
+
+ return 0;
}
-// from http://stackoverflow.com/questions/10564491/function-to-calculate-a-crc16-checksum
+// from
+// http://stackoverflow.com/questions/10564491/function-to-calculate-a-crc16-checksum
-unsigned short freedv_gen_crc16(unsigned char* data_p, int length) {
- unsigned char x;
- unsigned short crc = 0xFFFF;
+unsigned short freedv_gen_crc16(unsigned char *data_p, int length) {
+ unsigned char x;
+ unsigned short crc = 0xFFFF;
- while (length--) {
- x = crc >> 8 ^ *data_p++;
- x ^= x>>4;
- crc = (crc << 8) ^ ((unsigned short)(x << 12)) ^ ((unsigned short)(x <<5)) ^ ((unsigned short)x);
- }
+ while (length--) {
+ x = crc >> 8 ^ *data_p++;
+ x ^= x >> 4;
+ crc = (crc << 8) ^ ((unsigned short)(x << 12)) ^
+ ((unsigned short)(x << 5)) ^ ((unsigned short)x);
+ }
- return crc;
+ return crc;
}