1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-25 01:18:38 -05:00

Created an internal FreeDV API library

This commit is contained in:
f4exb 2019-03-04 23:04:27 +01:00
parent 9411757515
commit 4deafb9893
25 changed files with 4905 additions and 0 deletions

View File

@ -363,6 +363,11 @@ if (BUILD_DEBIAN)
add_subdirectory(libsoapysdr)
endif (BUILD_DEBIAN)
find_package(Codec2)
if (CODEC2_FOUND)
add_subdirectory(libfreedv)
endif(CODEC2_FOUND)
add_subdirectory(devices)
if (BUILD_GUI)
add_subdirectory(plugins)

43
libfreedv/CMakeLists.txt Normal file
View File

@ -0,0 +1,43 @@
project(freedv)
set(freedv_SOURCES
freedv_api.cpp
)
set(freedv_HEADERS
codec2_fft.h
codec2_ofdm.h
defines.h
fdmdv_internal.h
fdv_arm_math.h
fmfsk.h
freedv_data_channel.h
freedv_filter.h
freedv_vhf_framing.h
gp_interleaver.h
interldpc.h
kiss_fft.h
kiss_fftr.h
lbfreedv.h
modem_probe.h
mpdecode_core.h
ofdm_internal.h
)
include_directories(
.
${CMAKE_CURRENT_BINARY_DIR}
${CODEC2_INCLUDE_DIR}
)
add_definitions(-DQT_SHARED)
add_library(freedv SHARED
${freedv_SOURCES}
)
target_link_libraries(freedv
${CODEC2_LIBRARIES}
)
install(TARGETS freedv DESTINATION lib)

76
libfreedv/codec2_cohpsk.h Normal file
View File

@ -0,0 +1,76 @@
/*---------------------------------------------------------------------------*\
FILE........: codec2_cohpsk.h
AUTHOR......: David Rowe
DATE CREATED: March 2015
Functions that implement a coherent PSK FDM modem.
\*---------------------------------------------------------------------------*/
/*
Copyright (C) 2015 David Rowe
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1, as
published by the Free Software Foundation. This program is
distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CODEC2_COHPSK__
#define __CODEC2_COHPSK__
#define COHPSK_BITS_PER_FRAME 56 /* hard coded for now */
#define COHPSK_NC 7 /* hard coded for now */
#define COHPSK_NOM_SAMPLES_PER_FRAME 600
#define COHPSK_MAX_SAMPLES_PER_FRAME 625
#define COHPSK_RS 75
#define COHPSK_FS 7500 /* note this is a wierd
value to get an integer
oversampling rate */
#define COHPSK_CLIP 6.5 /* hard clipping for Nc*Nc=14 to reduce PAPR */
#include "codec2/comp.h"
#include "modem_stats.h"
namespace FreeDV
{
struct COHPSK;
extern const int test_bits_coh[];
struct COHPSK *cohpsk_create(void);
void cohpsk_destroy(struct COHPSK *coh);
void cohpsk_mod(struct COHPSK *cohpsk, COMP tx_fdm[], int tx_bits[], int nbits);
void cohpsk_clip(COMP tx_fdm[], float clip_thresh, int n);
void cohpsk_demod(struct COHPSK *cohpsk, float rx_bits[], int *sync, COMP rx_fdm[], int *nin_frame);
void cohpsk_get_demod_stats(struct COHPSK *cohpsk, struct MODEM_STATS *stats);
void cohpsk_set_verbose(struct COHPSK *coh, int verbose);
void cohpsk_get_test_bits(struct COHPSK *coh, int rx_bits[]);
void cohpsk_put_test_bits(struct COHPSK *coh, int *state, short error_pattern[],
int *bit_errors, char rx_bits[], int channel);
int cohpsk_error_pattern_size(void);
void cohpsk_set_frame(struct COHPSK *coh, int frame);
void fdmdv_freq_shift_coh(COMP rx_fdm_fcorr[], COMP rx_fdm[], float foff, float Fs,
COMP *foff_phase_rect, int nin);
void cohpsk_set_freq_est_mode(struct COHPSK *coh, int used_simple_mode);
/* used for accessing upper and lower bits before diversity combination */
float *cohpsk_get_rx_bits_lower(struct COHPSK *coh);
float *cohpsk_get_rx_bits_upper(struct COHPSK *coh);
void cohpsk_set_carrier_ampl(struct COHPSK *coh, int c, float ampl);
} // FreeDV
#endif

110
libfreedv/codec2_fdmdv.h Normal file
View File

@ -0,0 +1,110 @@
/*---------------------------------------------------------------------------*\
FILE........: codec2_fdmdv.h
AUTHOR......: David Rowe
DATE CREATED: April 14 2012
A 1400 bit/s (nominal) Frequency Division Multiplexed Digital Voice
(FDMDV) modem. Used for digital audio over HF SSB. See
README_fdmdv.txt for more information, and fdmdv_mod.c and
fdmdv_demod.c for example usage.
The name codec2_fdmdv.h is used to make it unique when "make
installed".
References:
[1] http://n1su.com/fdmdv/FDMDV_Docs_Rel_1_4b.pdf
\*---------------------------------------------------------------------------*/
/*
Copyright (C) 2012 David Rowe
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1, as
published by the Free Software Foundation. This program is
distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FDMDV__
#define __FDMDV__
/* set up the calling convention for DLL function import/export for
WIN32 cross compiling */
#ifdef __CODEC2_WIN32__
#ifdef __CODEC2_BUILDING_DLL__
#define CODEC2_WIN32SUPPORT __declspec(dllexport) __stdcall
#else
#define CODEC2_WIN32SUPPORT __declspec(dllimport) __stdcall
#endif
#else
#define CODEC2_WIN32SUPPORT
#endif
#include "codec2/comp.h"
#include "modem_stats.h"
#define FDMDV_NC 14 /* default number of data carriers */
#define FDMDV_NC_MAX 20 /* maximum number of data carriers */
#define FDMDV_BITS_PER_FRAME 28 /* 20ms frames, for nominal 1400 bit/s */
#define FDMDV_NOM_SAMPLES_PER_FRAME 160 /* modulator output samples/frame and nominal demod samples/frame */
/* at 8000 Hz sample rate */
#define FDMDV_MAX_SAMPLES_PER_FRAME 200 /* max demod samples/frame, use this to allocate storage */
#define FDMDV_SCALE 1000 /* suggested scaling for 16 bit shorts */
#define FDMDV_FCENTRE 1500 /* Centre frequency, Nc/2 carriers below this, Nc/2 carriers above (Hz) */
/* 8 to 48 kHz sample rate conversion */
#define FDMDV_OS 2 /* oversampling rate */
#define FDMDV_OS_TAPS_16K 48 /* number of OS filter taps at 16kHz */
#define FDMDV_OS_TAPS_8K (FDMDV_OS_TAPS_16K/FDMDV_OS) /* number of OS filter taps at 8kHz */
namespace FreeDV
{
/* FDMDV states and stats structures */
struct FDMDV;
struct FDMDV * fdmdv_create(int Nc);
void fdmdv_destroy(struct FDMDV *fdmdv_state);
void fdmdv_use_old_qpsk_mapping(struct FDMDV *fdmdv_state);
int fdmdv_bits_per_frame(struct FDMDV *fdmdv_state);
float fdmdv_get_fsep(struct FDMDV *fdmdv_state);
void fdmdv_set_fsep(struct FDMDV *fdmdv_state, float fsep);
void fdmdv_mod(struct FDMDV *fdmdv_state, COMP tx_fdm[], int tx_bits[], int *sync_bit);
void fdmdv_demod(struct FDMDV *fdmdv_state, int rx_bits[], int *reliable_sync_bit, COMP rx_fdm[], int *nin);
void fdmdv_get_test_bits(struct FDMDV *fdmdv_state, int tx_bits[]);
int fdmdv_error_pattern_size(struct FDMDV *fdmdv_state);
void fdmdv_put_test_bits(struct FDMDV *f, int *sync, short error_pattern[], int *bit_errors, int *ntest_bits, int rx_bits[]);
void fdmdv_get_demod_stats(struct FDMDV *fdmdv_state, struct MODEM_STATS *stats);
void fdmdv_8_to_16(float out16k[], float in8k[], int n);
void fdmdv_8_to_16_short(short out16k[], short in8k[], int n);
void fdmdv_16_to_8(float out8k[], float in16k[], int n);
void fdmdv_16_to_8_short(short out8k[], short in16k[], int n);
void fdmdv_freq_shift(COMP rx_fdm_fcorr[], COMP rx_fdm[], float foff, COMP *foff_phase_rect, int nin);
/* debug/development function(s) */
void fdmdv_dump_osc_mags(struct FDMDV *f);
void fdmdv_simulate_channel(float *sig_pwr_av, COMP samples[], int nin, float target_snr);
} // FreeDV
#endif

108
libfreedv/codec2_fft.h Normal file
View File

@ -0,0 +1,108 @@
/*
* codec2_fft.h
*
* Created on: 17.09.2016
* Author: danilo
*/
#ifndef DRIVERS_FREEDV_CODEC2_FFT_H_
#define DRIVERS_FREEDV_CODEC2_FFT_H_
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
namespace FreeDV
{
#ifdef FDV_ARM_MATH
#include "fdv_arm_math.h"
#else
#define USE_KISS_FFT
#endif
#include "defines.h"
#include "codec2/comp.h"
typedef COMP codec2_fft_cpx;
#include "kiss_fftr.h"
#ifdef USE_KISS_FFT
#include "kiss_fft.h"
typedef kiss_fftr_cfg codec2_fftr_cfg;
typedef kiss_fft_cfg codec2_fft_cfg;
typedef kiss_fft_scalar codec2_fft_scalar;
#else
typedef float32_t codec2_fft_scalar;
typedef struct {
arm_rfft_fast_instance_f32* instance;
int inverse;
} codec2_fftr_struct;
typedef codec2_fftr_struct* codec2_fftr_cfg;
typedef struct {
const arm_cfft_instance_f32* instance;
int inverse;
} codec2_fft_struct;
typedef codec2_fft_struct* codec2_fft_cfg;
#endif
static inline void codec2_fftr(codec2_fftr_cfg cfg, codec2_fft_scalar* in, codec2_fft_cpx* out)
{
#ifdef USE_KISS_FFT
kiss_fftr(cfg, in, (kiss_fft_cpx*)out);
#else
arm_rfft_fast_f32(cfg->instance,in,(float*)out,cfg->inverse);
out->imag = 0; // remove out[FFT_ENC/2]->real stored in out[0].imag
#endif
}
static inline void codec2_fftri(codec2_fftr_cfg cfg, codec2_fft_cpx* in, codec2_fft_scalar* out)
{
#ifdef USE_KISS_FFT
kiss_fftri(cfg, (kiss_fft_cpx*)in, out);
#else
arm_rfft_fast_f32(cfg->instance,(float*)in,out,cfg->inverse);
// arm_scale_f32(out,cfg->instance->fftLenRFFT,out,cfg->instance->fftLenRFFT);
#endif
}
codec2_fft_cfg codec2_fft_alloc(int nfft, int inverse_fft, void* mem, size_t* lenmem);
codec2_fftr_cfg codec2_fftr_alloc(int nfft, int inverse_fft, void* mem, size_t* lenmem);
void codec2_fft_free(codec2_fft_cfg cfg);
void codec2_fftr_free(codec2_fftr_cfg cfg);
static inline void codec2_fft(codec2_fft_cfg cfg, codec2_fft_cpx* in, codec2_fft_cpx* out)
{
#ifdef USE_KISS_FFT
kiss_fft(cfg, (kiss_fft_cpx*)in, (kiss_fft_cpx*)out);
#else
memcpy(out,in,cfg->instance->fftLen*2*sizeof(float));
arm_cfft_f32(cfg->instance,(float*)out,cfg->inverse,0);
// TODO: this is not nice, but for now required to keep changes minimal
// however, since main goal is to reduce the memory usage
// we should convert to an in place interface
// on PC like platforms the overhead of using the "inplace" kiss_fft calls
// is neglectable compared to the gain in memory usage on STM32 platforms
if (cfg->inverse)
{
arm_scale_f32((float*)out,cfg->instance->fftLen,(float*)out,cfg->instance->fftLen*2);
}
#endif
}
void codec2_fft_inplace(codec2_fft_cfg cfg, codec2_fft_cpx* inout);
} // FreeDV
#endif

101
libfreedv/codec2_ofdm.h Normal file
View File

@ -0,0 +1,101 @@
/*---------------------------------------------------------------------------*\
FILE........: codec2_ofdm.h
AUTHORS.....: David Rowe & Steve Sampson
DATE CREATED: June 2017
External user references to the modem library.
\*---------------------------------------------------------------------------*/
/*
Copyright (C) 2017 David Rowe
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1, as
published by the Free Software Foundation. This program is
distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CODEC2_OFDM_H
#define CODEC2_OFDM_H
/* Includes */
#include <complex.h>
#include <stdbool.h>
#include <stdint.h>
#include "codec2/comp.h"
#include "modem_stats.h"
/* Defines */
#define OFDM_AMP_SCALE (2E5*1.1491/1.06) /* use to scale to 16 bit short */
#define OFDM_CLIP (32767*0.35) /* experimentally derived constant to reduce PAPR to about 8dB */
namespace FreeDV
{
struct OFDM_CONFIG;
struct OFDM;
typedef enum {
search,
trial,
synced
} State;
typedef enum {
unsync, /* force sync state machine to lose sync, and search for new sync */
autosync, /* falls out of sync automatically */
manualsync /* fall out of sync only under operator control */
} Sync;
/* create and destroy modem states */
struct OFDM *ofdm_create(const struct OFDM_CONFIG * config);
void ofdm_destroy(struct OFDM *);
/* signal processing */
void ofdm_mod(struct OFDM *, COMP *, const int *);
void ofdm_demod(struct OFDM *, int *, COMP *);
void ofdm_demod_shorts(struct OFDM *, int *, short *, float);
int ofdm_sync_search(struct OFDM *, COMP *);
int ofdm_sync_search_shorts(struct OFDM *, short *, float);
void ofdm_sync_state_machine(struct OFDM *, uint8_t *);
/* getters */
struct OFDM_CONFIG *ofdm_get_config_param(void);
int ofdm_get_nin(struct OFDM *);
int ofdm_get_samples_per_frame(void);
int ofdm_get_max_samples_per_frame(void);
int ofdm_get_bits_per_frame(void);
void ofdm_get_demod_stats(struct OFDM *ofdm, struct MODEM_STATS *stats);
/* option setters */
void ofdm_set_verbose(struct OFDM *, int);
void ofdm_set_timing_enable(struct OFDM *, bool);
void ofdm_set_foff_est_enable(struct OFDM *, bool);
void ofdm_set_phase_est_enable(struct OFDM *, bool);
void ofdm_set_off_est_hz(struct OFDM *, float);
void ofdm_set_sync(struct OFDM *, Sync);
void ofdm_set_tx_bpf(struct OFDM *, bool);
void ofdm_print_info(struct OFDM *);
} // FreeDV
#endif

120
libfreedv/defines.h Normal file
View File

@ -0,0 +1,120 @@
/*---------------------------------------------------------------------------*\
FILE........: defines.h
AUTHOR......: David Rowe
DATE CREATED: 23/4/93
Defines and structures used throughout the codec.
\*---------------------------------------------------------------------------*/
/*
Copyright (C) 2009 David Rowe
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1, as
published by the Free Software Foundation. This program is
distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __DEFINES__
#define __DEFINES__
/*---------------------------------------------------------------------------*\
DEFINES
\*---------------------------------------------------------------------------*/
/* General defines */
#define N_S 0.01 /* internal proc frame length in secs */
#define TW_S 0.005 /* trapezoidal synth window overlap */
#define MAX_AMP 160 /* maximum number of harmonics */
#ifndef PI
#define PI 3.141592654 /* mathematical constant */
#endif
#define TWO_PI 6.283185307 /* mathematical constant */
#define MAX_STR 2048 /* maximum string size */
#define FFT_ENC 512 /* size of FFT used for encoder */
#define FFT_DEC 512 /* size of FFT used in decoder */
#define V_THRESH 6.0 /* voicing threshold in dB */
#define LPC_ORD 10 /* LPC order */
#define LPC_ORD_LOW 6 /* LPC order for lower rates */
/* Pitch estimation defines */
#define M_PITCH_S 0.0400 /* pitch analysis window in s */
#define P_MIN_S 0.0025 /* minimum pitch period in s */
#define P_MAX_S 0.0200 /* maximum pitch period in s */
namespace FreeDV
{
/*---------------------------------------------------------------------------*\
TYPEDEFS
\*---------------------------------------------------------------------------*/
/* Structure to hold constants calculated at run time based on sample rate */
typedef struct {
int Fs; /* sample rate of this instance */
int n_samp; /* number of samples per 10ms frame at Fs */
int max_amp; /* maximum number of harmonics */
int m_pitch; /* pitch estimation window size in samples */
int p_min; /* minimum pitch period in samples */
int p_max; /* maximum pitch period in samples */
float Wo_min;
float Wo_max;
int nw; /* analysis window size in samples */
int tw; /* trapezoidal synthesis window overlap */
} C2CONST;
/* Structure to hold model parameters for one frame */
typedef struct {
float Wo; /* fundamental frequency estimate in radians */
int L; /* number of harmonics */
float A[MAX_AMP+1]; /* amplitiude of each harmonic */
float phi[MAX_AMP+1]; /* phase of each harmonic */
int voiced; /* non-zero if this frame is voiced */
} MODEL;
/* describes each codebook */
struct lsp_codebook {
int k; /* dimension of vector */
int log2m; /* number of bits in m */
int m; /* elements in codebook */
const float * cb; /* The elements */
};
extern const struct lsp_codebook lsp_cb[];
extern const struct lsp_codebook lsp_cbd[];
extern const struct lsp_codebook lsp_cbvq[];
extern const struct lsp_codebook lsp_cbjnd[];
extern const struct lsp_codebook lsp_cbdt[];
extern const struct lsp_codebook lsp_cbjvm[];
extern const struct lsp_codebook lsp_cbvqanssi[];
extern const struct lsp_codebook mel_cb[];
extern const struct lsp_codebook ge_cb[];
extern const struct lsp_codebook lspmelvq_cb[];
extern const struct lsp_codebook newamp1vq_cb[];
extern const struct lsp_codebook newamp1_energy_cb[];
extern const struct lsp_codebook newamp2vq_cb[];
extern const struct lsp_codebook newamp2_energy_cb[];
} // FreeDV
#endif

200
libfreedv/fdmdv_internal.h Normal file
View File

@ -0,0 +1,200 @@
/*---------------------------------------------------------------------------*\
FILE........: fdmdv_internal.h
AUTHOR......: David Rowe
DATE CREATED: April 16 2012
Header file for FDMDV internal functions, exposed via this header
file for testing.
\*---------------------------------------------------------------------------*/
/*
Copyright (C) 2012 David Rowe
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1, as
published by the Free Software Foundation. This program is
distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FDMDV_INTERNAL__
#define __FDMDV_INTERNAL__
#include "codec2/comp.h"
#include "codec2_fdmdv.h"
#include "codec2_fft.h"
/*---------------------------------------------------------------------------*\
DEFINES
\*---------------------------------------------------------------------------*/
#ifndef PI
#define PI 3.141592654
#endif
#define FS 8000 /* sample rate in Hz */
#define T (1.0/FS) /* sample period in seconds */
#define RS 50 /* symbol rate in Hz */
#define NC 20 /* max number of data carriers (plus one pilot in the centre) */
#define NB 2 /* Bits/symbol for QPSK modulation */
#define RB (NC*RS*NB) /* bit rate */
#define M_FAC (FS/RS) /* oversampling factor */
#define NSYM 6 /* number of symbols to filter over */
#define NFILTER (NSYM*M_FAC) /* size of tx/rx filters at sample rate M */
#define FSEP 75 /* Default separation between carriers (Hz) */
#define NT 5 /* number of symbols we estimate timing over */
#define P 4 /* oversample factor used for initial rx symbol filtering output */
#define Q (M_FAC/4) /* oversample factor used for initial rx symbol filtering input */
#define NRXDEC 31 /* number of taps in the rx decimation filter */
#define NPILOT_LUT (4*M_FAC) /* number of pilot look up table samples */
#define NPILOTCOEFF 30 /* number of FIR filter coeffs in LP filter */
#define NPILOTBASEBAND (NPILOTCOEFF+M_FAC+M_FAC/P) /* number of pilot baseband samples reqd for pilot LPF */
#define NPILOTLPF (4*M_FAC) /* number of samples we DFT pilot over, pilot est window */
#define MPILOTFFT 256
#define NSYNC_MEM 6
#define NRX_FDM_MEM (NFILTER+M_FAC+M_FAC/P) /* size of rx filter memory */
#define NRXDECMEM (NRXDEC+M_FAC+M_FAC/P) /* size of rx decimation filter memory */
/* averaging filter coeffs */
#define TRACK_COEFF 0.5
#define SNR_COEFF 0.9 /* SNR est averaging filter coeff */
namespace FreeDV
{
/*---------------------------------------------------------------------------*\
STRUCT for States
\*---------------------------------------------------------------------------*/
struct FDMDV {
int Nc;
float fsep;
/* test data (test frame) states */
int ntest_bits;
int current_test_bit;
int *rx_test_bits_mem;
/* Modulator */
int old_qpsk_mapping;
int tx_pilot_bit;
COMP prev_tx_symbols[NC+1];
COMP tx_filter_memory[NC+1][NSYM];
COMP phase_tx[NC+1];
COMP freq[NC+1];
float freq_pol[NC+1];
/* Pilot generation at demodulator */
COMP pilot_lut[NPILOT_LUT];
int pilot_lut_index;
int prev_pilot_lut_index;
/* freq offset estimation states */
codec2_fft_cfg fft_pilot_cfg;
COMP pilot_baseband1[NPILOTBASEBAND];
COMP pilot_baseband2[NPILOTBASEBAND];
COMP pilot_lpf1[NPILOTLPF];
COMP pilot_lpf2[NPILOTLPF];
COMP S1[MPILOTFFT];
COMP S2[MPILOTFFT];
/* baseband to low IF carrier states */
COMP fbb_rect;
float fbb_pol;
COMP fbb_phase_tx;
COMP fbb_phase_rx;
/* freq offset correction states */
float foff;
COMP foff_phase_rect;
float foff_filt;
/* Demodulator */
COMP rxdec_lpf_mem[NRXDECMEM];
COMP rx_fdm_mem[NRX_FDM_MEM];
COMP phase_rx[NC+1];
COMP rx_filter_mem_timing[NC+1][NT*P];
float rx_timing;
COMP phase_difference[NC+1];
COMP prev_rx_symbols[NC+1];
/* sync state machine */
int sync_mem[NSYNC_MEM];
int fest_state;
int sync;
int timer;
/* SNR estimation states */
float sig_est[NC+1];
float noise_est[NC+1];
/* channel simulation */
float sig_pwr_av;
};
/*---------------------------------------------------------------------------*\
FUNCTION PROTOTYPES
\*---------------------------------------------------------------------------*/
void bits_to_dqpsk_symbols(COMP tx_symbols[], int Nc, COMP prev_tx_symbols[], int tx_bits[], int *pilot_bit, int old_qpsk_mapping);
void tx_filter(COMP tx_baseband[NC+1][M_FAC], int Nc, COMP tx_symbols[], COMP tx_filter_memory[NC+1][NSYM]);
void fdm_upconvert(COMP tx_fdm[], int Nc, COMP tx_baseband[NC+1][M_FAC], COMP phase_tx[], COMP freq_tx[],
COMP *fbb_phase, COMP fbb_rect);
void tx_filter_and_upconvert(COMP tx_fdm[], int Nc, COMP tx_symbols[],
COMP tx_filter_memory[NC+1][NSYM],
COMP phase_tx[], COMP freq[], COMP *fbb_phase, COMP fbb_rect);
void generate_pilot_fdm(COMP *pilot_fdm, int *bit, float *symbol, float *filter_mem, COMP *phase, COMP *freq);
void generate_pilot_lut(COMP pilot_lut[], COMP *pilot_freq);
float rx_est_freq_offset(struct FDMDV *f, COMP rx_fdm[], int nin, int do_fft);
void lpf_peak_pick(float *foff, float *max, COMP pilot_baseband[], COMP pilot_lpf[], codec2_fft_cfg fft_pilot_cfg, COMP S[], int nin, int do_fft);
void fdm_downconvert(COMP rx_baseband[NC+1][M_FAC+M_FAC/P], int Nc, COMP rx_fdm[], COMP phase_rx[], COMP freq[], int nin);
void rxdec_filter(COMP rx_fdm_filter[], COMP rx_fdm[], COMP rxdec_lpf_mem[], int nin);
void rx_filter(COMP rx_filt[NC+1][P+1], int Nc, COMP rx_baseband[NC+1][M_FAC+M_FAC/P], COMP rx_filter_memory[NC+1][NFILTER], int nin);
void down_convert_and_rx_filter(COMP rx_filt[NC+1][P+1], int Nc, COMP rx_fdm[],
COMP rx_fdm_mem[], COMP phase_rx[], COMP freq[],
float freq_pol[], int nin, int dec_rate);
float rx_est_timing(COMP rx_symbols[], int Nc,
COMP rx_filt[NC+1][P+1],
COMP rx_filter_mem_timing[NC+1][NT*P],
float env[],
int nin,
int m);
float qpsk_to_bits(int rx_bits[], int *sync_bit, int Nc, COMP phase_difference[], COMP prev_rx_symbols[], COMP rx_symbols[], int old_qpsk_mapping);
void snr_update(float sig_est[], float noise_est[], int Nc, COMP phase_difference[]);
int freq_state(int *reliable_sync_bit, int sync_bit, int *state, int *timer, int *sync_mem);
float calc_snr(int Nc, float sig_est[], float noise_est[]);
} // FreeDV
#endif

41
libfreedv/fdv_arm_math.h Normal file
View File

@ -0,0 +1,41 @@
/*---------------------------------------------------------------------------*\
FILE........: fdv_arm_math.h
AUTHOR......: David Rowe
DATE CREATED: Feb 13 2019
Bundles access to ARM CORTEX M specific functions which are enabled by
defining FDV_ARM_MATH
\*---------------------------------------------------------------------------*/
/*
Copyright (C) 2012 David Rowe
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1, as
published by the Free Software Foundation. This program is
distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FDV_ARM_MATH__
#define __FDV_ARM_MATH__
#ifdef FDV_ARM_MATH
#include "arm_const_structs.h"
#define SINF(a) arm_sin_f32(a)
#define COSF(a) arm_cos_f32(a)
#else
#define SINF(a) sinf(a)
#define COSF(a) cosf(a)
#endif
#endif

116
libfreedv/fmfsk.h Normal file
View File

@ -0,0 +1,116 @@
/*---------------------------------------------------------------------------*\
FILE........: fmfsk.h
AUTHOR......: Brady O'Brien
DATE CREATED: 6 February 2016
C Implementation of 2FSK+Manchester over FM modulator/demodulator, based
on mancyfsk.m and fmfsk.m
\*---------------------------------------------------------------------------*/
/*
Copyright (C) 2016 David Rowe
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1, as
published by the Free Software Foundation. This program is
distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __C2FMFSK_H
#define __C2FMFSK_H
#include <stdint.h>
#include "codec2/comp.h"
#include "modem_stats.h"
#define FMFSK_SCALE 16383
namespace FreeDV
{
/*
* fm-me-2fsk state
*/
struct FMFSK{
/* Static fmfsk parameters */
int Rb; /* Manchester-encoded bitrate */
int Rs; /* Raw modem symbol rate */
int Fs; /* Sample rate */
int Ts; /* Samples-per-symbol */
int N; /* Sample processing buffer size */
int nsym; /* Number of raw modem symbols processed per demod call */
int nbit; /* Number of bits spit out per demod call */
int nmem; /* Number of samples kept around between demod calls */
/* State kept by demod */
int nin; /* Number of samples to be demod-ed the next cycle */
int lodd; /* Last integrated sample for odd bitstream generation */
float * oldsamps; /* Memory of old samples to make clock-offset-tolerance possible */
/* Stats generated by demod */
float norm_rx_timing; /* RX Timing, used to calculate clock offset */
int ppm; /* Clock offset in parts-per-million */
float snr_mean;
/* Modem stat structure */
struct MODEM_STATS * stats;
};
/*
* Create a new fmfsk modem instance.
*
* int Fs - sample rate
* int Rb - non-manchester bitrate
* returns - new struct FMFSK on sucess, NULL on failure
*/
struct FMFSK * fmfsk_create(int Fs,int Rb);
/*
* Destroys an fmfsk modem and deallocates memory
*/
void fmfsk_destroy(struct FMFSK *fmfsk);
/*
* Deposit demod statistics into a MODEM_STATS struct
*/
void fmfsk_get_demod_stats(struct FMFSK *fmfsk,struct MODEM_STATS *stats);
/*
* Returns the number of samples that must be fed to fmfsk_demod the next
* cycle
*/
uint32_t fmfsk_nin(struct FMFSK *fmfsk);
/*
* Modulates nbit bits into N samples to be sent through an FM radio
*
* struct FSK *fsk - FSK config/state struct, set up by fsk_create
* float mod_out[] - Buffer for N samples of modulated FMFSK
* uint8_t tx_bits[] - Buffer containing Nbits unpacked bits
*/
void fmfsk_mod(struct FMFSK *fmfsk, float fmfsk_out[],uint8_t bits_in[]);
/*
* Demodulate some number of FMFSK samples. The number of samples to be
* demodulated can be found by calling fmfsk_nin().
*
* struct FMFSK *fsk - FMFSK config/state struct, set up by fsk_create
* uint8_t rx_bits[] - Buffer for nbit unpacked bits to be written
* float fsk_in[] - nin samples of modualted FMFSK from an FM radio
*/
void fmfsk_demod(struct FMFSK *fmfsk, uint8_t rx_bits[],float fmfsk_in[]);
} // FreeDV
#endif

2538
libfreedv/freedv_api.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,154 @@
/*---------------------------------------------------------------------------*\
FILE........: freedv_api_internal.h
AUTHOR......: David Rowe
DATE CREATED: August 2014
This declares the structure freedv. A pointer to this structure is
returned by the FreeDV API freedv_open() function. The pointer is used
by the other FreeDV API functions declared in freedv_api.h. This
structure is intended to be internal to the FreeDV API. The public
functions are declared in freedv_api.h. Changes to this structure
are expected. Changes (except additions) to freedv_api.h are
discouraged.
\*---------------------------------------------------------------------------*/
/*
Copyright (C) 2014 David Rowe
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1, as
published by the Free Software Foundation. This program is
distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FREEDV_API_INTERNAL__
#define __FREEDV_API_INTERNAL__
#include "codec2/varicode.h"
#include "fsk.h"
#include "fmfsk.h"
#include "codec2_cohpsk.h"
#include "codec2_fdmdv.h"
namespace FreeDV
{
struct freedv {
int mode;
/* states for various modems we support */
struct CODEC2 *codec2;
struct FDMDV *fdmdv;
struct COHPSK *cohpsk;
struct FSK *fsk;
struct FMFSK *fmfsk;
struct OFDM *ofdm;
struct LDPC *ldpc;
struct MODEM_STATS stats;
struct freedv_vhf_deframer * deframer; // Extracts frames from VHF stream
struct quisk_cfFilter * ptFilter7500to8000; // Filters to change to/from 7500 and 8000 sps for 700 .... 700C
struct quisk_cfFilter * ptFilter8000to7500;
int n_speech_samples; // number of speech samples we need for each freedv_tx() call
// num of speech samples output by freedv_rx() call
int n_nom_modem_samples; // size of tx and most rx modem sample buffers
int n_max_modem_samples; // make your rx modem sample buffers this big
int n_nat_modem_samples; // tx modem sample block length as used by the modem before interpolation to output
// usually the same as n_nom_modem_samples, except for 700..700C
int modem_sample_rate; // Caller is responsible for meeting this
int modem_symbol_rate; // Useful for ext_vco operation on 2400A and 800XA
int clip; // non-zero for cohpsk modem output clipping for low PAPR
unsigned char *packed_codec_bits;
unsigned char *packed_codec_bits_tx; // for 700D we separate packed bits to maintain state due to interleaving
int nbyte_packed_codec_bits; // keep track of size of above arrays in 700D
int *codec_bits;
int *tx_bits;
int *fdmdv_bits;
int *rx_bits;
int n_codec_bits; // number of codec bits in a frame
int tx_sync_bit;
int smooth_symbols;
int frames;
/* test frame states -------------------------------------------------------------------------*/
int *ptest_bits_coh;
int *ptest_bits_coh_end;
int test_frames; // set this baby for 1 to tx/rx test frames to look at bit error stats
int test_frames_diversity; // 1 -> used combined carriers for error counting on 700 waveforms
int test_frame_sync_state;
int test_frame_sync_state_upper; // when test_frames_diveristy==0 we need extra states for upper carriers
int test_frame_count;
int total_bits;
int total_bit_errors;
int total_bits_coded;
int total_bit_errors_coded;
int sz_error_pattern;
/* optional user defined function to pass error pattern when a test frame is received */
void *error_pattern_callback_state;
void (*freedv_put_error_pattern)(void *error_pattern_callback_state, short error_pattern[], int sz_error_pattern);
/* Misc ---------------------------------------------------------------------------------------------*/
int sync;
int evenframe;
float snr_est;
float snr_squelch_thresh;
int squelch_en;
int nin;
int verbose;
int ext_vco; /* 2400A/800XA use external VCO flag */
/* Varicode txt channel states ----------------------------------------------------------------------*/
struct VARICODE_DEC varicode_dec_states;
short tx_varicode_bits[VARICODE_MAX_BITS];
int nvaricode_bits;
int varicode_bit_index;
/* interleaved LDPC OFDM states ---------------------------------------------------------------------*/
int interleave_frames; // number of OFDM modem frames in interleaver, e.g. 1,2,4,8,16
COMP *codeword_symbols;
float *codeword_amps;
int modem_frame_count_tx; // modem frame counter for tx side
int modem_frame_count_rx; // modem frame counter for rx side
COMP *mod_out; // output buffer of intereaved frames
/* user defined function ptrs to produce and consume ASCII
characters using aux txt channel */
char (*freedv_get_next_tx_char)(void *callback_state);
void (*freedv_put_next_rx_char)(void *callback_state, char c);
void *callback_state;
/* user defined functions to produce and consume protocol bits */
/* Protocol bits are packed MSB-first */
void (*freedv_put_next_proto)(void *callback_state, char *proto_bits_packed);
void (*freedv_get_next_proto)(void *callback_state, char *proto_bits_packed);
void *proto_callback_state;
int n_protocol_bits;
};
} // FreeDV
#endif

View File

@ -0,0 +1,75 @@
/*---------------------------------------------------------------------------*\
FILE........: freedv_data_channel.h
AUTHOR......: Jeroen Vreeken
DATE CREATED: 03 March 2016
Data channel for ethernet like packets in freedv VHF frames.
Currently designed for-
* 2 control bits per frame
* 4 byte counter bits per frame
* 64 bits of data per frame
\*---------------------------------------------------------------------------*/
/*
Copyright (C) 2016 Jeroen Vreeken
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1, as
published by the Free Software Foundation. This program is
distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _FREEDV_DATA_CHANNEL_H
#define _FREEDV_DATA_CHANNEL_H
#include <stdlib.h>
#define FREEDV_DATA_CHANNEL_PACKET_MAX 2048
namespace FreeDV
{
typedef void (*freedv_data_callback_rx)(void *, unsigned char *packet, size_t size);
typedef void (*freedv_data_callback_tx)(void *, unsigned char *packet, size_t *size);
struct freedv_data_channel {
freedv_data_callback_rx cb_rx;
void *cb_rx_state;
freedv_data_callback_tx cb_tx;
void *cb_tx_state;
unsigned char rx_header[8];
unsigned char packet_rx[FREEDV_DATA_CHANNEL_PACKET_MAX + 2];
int packet_rx_cnt;
unsigned char tx_header[8];
unsigned char packet_tx[FREEDV_DATA_CHANNEL_PACKET_MAX + 2];
int packet_tx_cnt;
size_t packet_tx_size;
};
struct freedv_data_channel *freedv_data_channel_create(void);
void freedv_data_channel_destroy(struct freedv_data_channel *fdc);
void freedv_data_set_cb_rx(struct freedv_data_channel *fdc, freedv_data_callback_rx cb, void *state);
void freedv_data_set_cb_tx(struct freedv_data_channel *fdc, freedv_data_callback_tx cb, void *state);
void freedv_data_channel_rx_frame(struct freedv_data_channel *fdc, unsigned char *data, size_t size, int from_bit, int bcast_bit, int crc_bit, int end_bits);
void freedv_data_channel_tx_frame(struct freedv_data_channel *fdc, unsigned char *data, size_t size, int *from_bit, int *bcast_bit, int *crc_bit, int *end_bits);
void freedv_data_set_header(struct freedv_data_channel *fdc, unsigned char *header);
int freedv_data_get_n_tx_frames(struct freedv_data_channel *fdc, size_t size);
} // FreeDV
#endif /* _FREEDV_DATA_CHANNEL_H */

48
libfreedv/freedv_filter.h Normal file
View File

@ -0,0 +1,48 @@
/*
Copyright (C) 2018 James C. Ahlstrom
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1, as
published by the Free Software Foundation. This program is
distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FILTER__
#define __FILTER__
#include <complex>
namespace FreeDV
{
struct quisk_cfFilter { // Structure to hold the static data for FIR filters
float * dCoefs; // real filter coefficients
std::complex<float> * cpxCoefs; // complex filter coefficients
int nBuf; // dimension of cBuf
int nTaps; // dimension of dSamples, cSamples, dCoefs
int decim_index; // index of next sample for decimation
std::complex<float> * cSamples; // storage for old samples
std::complex<float> * ptcSamp; // next available position in cSamples
std::complex<float> * cBuf; // auxillary buffer for interpolation
} ;
extern int quisk_cfInterpDecim(std::complex<float> *, int, struct quisk_cfFilter *, int, int);
extern void quisk_filt_cfInit(struct quisk_cfFilter *, float *, int);
extern void quisk_filt_destroy(struct quisk_cfFilter *);
extern void quisk_cfTune(struct quisk_cfFilter *, float);
extern void quisk_ccfFilter(std::complex<float> *, std::complex<float> *, int, struct quisk_cfFilter *);
extern float quiskFilt120t480[480];
extern float filtP550S750[160];
} // FreeDV
#endif

View File

@ -0,0 +1,103 @@
/*---------------------------------------------------------------------------*\
FILE........: freedv_vhf_framing.h
AUTHOR......: Brady O'Brien
DATE CREATED: 11 February 2016
Framer and deframer for VHF FreeDV modes 'A' and 'B'
Currently designed for-
* 40ms ota modem frames
* 40ms Codec2 1300 frames
* 52 bits of Codec2 per frame
* 16 bits of unique word per frame
* 28 'spare' bits per frame
* - 4 spare bits at front and end of frame (8 total) for padding
* - 20 'protocol' bits, either for higher layers of 'protocol' or
* - 18 'protocol' bits and 2 vericode sidechannel bits
\*---------------------------------------------------------------------------*/
/*
Copyright (C) 2016 David Rowe
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1, as
published by the Free Software Foundation. This program is
distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _FREEDV_VHF_FRAMING_H
#define _FREEDV_VHF_FRAMING_H
#include "freedv_data_channel.h"
/* Standard frame type */
#define FREEDV_VHF_FRAME_A 1 /* 2400A/B Frame */
#define FREEDV_HF_FRAME_B 2 /* 800XA Frame */
#define FREEDV_VHF_FRAME_AT 3 /* 4800T Frame */
namespace FreeDV
{
struct freedv_vhf_deframer {
int ftype; /* Type of frame to be looking for */
int state; /* State of deframer */
uint8_t * bits; /* Bits currently being decanted */
uint8_t * invbits; /* Inversion of bits currently being decanted, for FMFSK */
int bitptr; /* Pointer into circular bit buffer */
int miss_cnt; /* How many UWs have been missed */
int last_uw; /* How many bits since the last UW? */
int frame_size; /* How big is a frame? */
int uw_size; /* How big is the UW */
int on_inv_bits; /* Are we using the inverted bits? */
int sym_size; /* How many bits in a modem symbol */
float ber_est; /* Bit error rate estimate */
int total_uw_bits; /* Total RX-ed bits of UW */
int total_uw_err; /* Total errors in UW bits */
struct freedv_data_channel *fdc;
};
/* Init and allocate memory for a freedv-vhf framer/deframer */
struct freedv_vhf_deframer * fvhff_create_deframer(uint8_t frame_type,int enable_bit_flip);
/* Get size of various frame parameters */
/* Frame size in bits */
int fvhff_get_frame_size(struct freedv_vhf_deframer * def);
/* Codec2 size in bytes */
int fvhff_get_codec2_size(struct freedv_vhf_deframer * def);
/* Protocol bits in bits */
int fvhff_get_proto_size(struct freedv_vhf_deframer * def);
/* Varicode bits in bits */
int fvhff_get_varicode_size(struct freedv_vhf_deframer * def);
/* Free the memory used by a freedv-vhf framer/deframer */
void fvhff_destroy_deframer(struct freedv_vhf_deframer * def);
/* Place codec and other bits into a frame */
void fvhff_frame_bits(int frame_type,uint8_t bits_out[],uint8_t codec2_in[],uint8_t proto_in[],uint8_t vc_in[]);
void fvhff_frame_data_bits(struct freedv_vhf_deframer * def, int frame_type,uint8_t bits_out[]);
/* Find and extract frames from a stream of bits */
int fvhff_deframe_bits(struct freedv_vhf_deframer * def,uint8_t codec2_out[],uint8_t proto_out[],uint8_t vc_out[],uint8_t bits_in[]);
/* Is the de-framer synchronized? */
int fvhff_synchronized(struct freedv_vhf_deframer * def);
/* Search for a complete UW in a buffer of bits */
std::size_t fvhff_search_uw(const uint8_t bits[],size_t nbits,
const uint8_t uw[], std::size_t uw_len,
std::size_t * delta_out, std::size_t bits_per_sym);
} // FreeDV
#endif //_FREEDV_VHF_FRAMING_H

209
libfreedv/fsk.h Normal file
View File

@ -0,0 +1,209 @@
/*---------------------------------------------------------------------------*\
FILE........: fsk.h
AUTHOR......: Brady O'Brien
DATE CREATED: 6 January 2016
C Implementation of 2FSK/4FSK modulator/demodulator, based on octave/fsk_horus.m
\*---------------------------------------------------------------------------*/
/*
Copyright (C) 2016 David Rowe
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1, as
published by the Free Software Foundation. This program is
distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __C2FSK_H
#define __C2FSK_H
#include <stdint.h>
#include "codec2/comp.h"
#include "kiss_fftr.h"
#include "modem_stats.h"
#define MODE_2FSK 2
#define MODE_4FSK 4
#define MODE_M_MAX 4
#define FSK_SCALE 16383
namespace FreeDV
{
struct FSK {
/* Static parameters set up by fsk_init */
int Ndft; /* buffer size for freq offset est fft */
int Fs; /* sample freq */
int N; /* processing buffer size */
int Rs; /* symbol rate */
int Ts; /* samples per symbol */
int Nmem; /* size of extra mem for timing adj */
int P; /* oversample rate for timing est/adj */
int Nsym; /* Number of symbols spat out in a processing frame */
int Nbits; /* Number of bits spat out in a processing frame */
int f1_tx; /* f1 for modulator */
int fs_tx; /* Space between TX freqs for modulatosr */
int mode; /* 2FSK or 4FSK */
int est_min; /* Minimum frequency for freq. estimator */
int est_max; /* Maximum frequency for freq. estimaotr */
int est_space; /* Minimum frequency spacing for freq. estimator */
float* hann_table; /* Precomputed or runtime computed hann window table */
/* Parameters used by demod */
COMP phi_c[MODE_M_MAX];
kiss_fft_cfg fft_cfg; /* Config for KISS FFT, used in freq est */
float norm_rx_timing; /* Normalized RX timing */
COMP* samp_old; /* Tail end of last batch of samples */
int nstash; /* How many elements are in there */
float* fft_est; /* Freq est FFT magnitude */
/* Memory used by demod but not important between demod frames */
/* Parameters used by mod */
COMP tx_phase_c; /* TX phase, but complex */
/* Statistics generated by demod */
float EbNodB; /* Estimated EbNo in dB */
float f_est[MODE_M_MAX];/* Estimated frequencies */
float ppm; /* Estimated PPM clock offset */
/* Parameters used by mod/demod and driving code */
int nin; /* Number of samples to feed the next demod cycle */
int burst_mode; /* enables/disables 'burst' mode */
/* modem statistic struct */
struct MODEM_STATS *stats;
int normalise_eye; /* enables/disables normalisation of eye diagram */
};
/*
* Create an FSK config/state struct from a set of config parameters
*
* int Fs - Sample frequency
* int Rs - Symbol rate
* int tx_f1 - '0' frequency
* int tx_fs - frequency spacing
*/
struct FSK * fsk_create(int Fs, int Rs, int M, int tx_f1, int tx_fs);
/*
* Create an FSK config/state struct from a set of config parameters
*
* int Fs - Sample frequency
* int Rs - Symbol rate
* int tx_f1 - '0' frequency
* int tx_fs - frequency spacing
*/
struct FSK * fsk_create_hbr(int Fs, int Rs, int P, int M, int tx_f1, int tx_fs);
/*
* Set a new number of symbols per processing frame
*/
void fsk_set_nsym(struct FSK *fsk,int nsym);
/*
* Set the minimum and maximum frequencies at which the freq. estimator can find tones
*/
void fsk_set_est_limits(struct FSK *fsk,int fmin, int fmax);
/*
* Clear the estimator states
*/
void fsk_clear_estimators(struct FSK *fsk);
/*
* Fills MODEM_STATS struct with demod statistics
*/
void fsk_get_demod_stats(struct FSK *fsk, struct MODEM_STATS *stats);
/*
* Destroy an FSK state struct and free it's memory
*
* struct FSK *fsk - FSK config/state struct to be destroyed
*/
void fsk_destroy(struct FSK *fsk);
/*
* Modulates Nsym bits into N samples
*
* struct FSK *fsk - FSK config/state struct, set up by fsk_create
* float fsk_out[] - Buffer for N samples of modulated FSK
* uint8_t tx_bits[] - Buffer containing Nbits unpacked bits
*/
void fsk_mod(struct FSK *fsk, float fsk_out[], uint8_t tx_bits[]);
/*
* Modulates Nsym bits into N samples
*
* struct FSK *fsk - FSK config/state struct, set up by fsk_create
* float fsk_out[] - Buffer for N samples of "voltage" used to modulate an external VCO
* uint8_t tx_bits[] - Buffer containing Nbits unpacked bits
*/
void fsk_mod_ext_vco(struct FSK *fsk, float vco_out[], uint8_t tx_bits[]);
/*
* Modulates Nsym bits into N complex samples
*
* struct FSK *fsk - FSK config/state struct, set up by fsk_create
* comp fsk_out[] - Buffer for N samples of modulated FSK
* uint8_t tx_bits[] - Buffer containing Nbits unpacked bits
*/
void fsk_mod_c(struct FSK *fsk, COMP fsk_out[], uint8_t tx_bits[]);
/*
* Returns the number of samples needed for the next fsk_demod() cycle
*
* struct FSK *fsk - FSK config/state struct, set up by fsk_create
* returns - number of samples to be fed into fsk_demod next cycle
*/
uint32_t fsk_nin(struct FSK *fsk);
/*
* Demodulate some number of FSK samples. The number of samples to be
* demodulated can be found by calling fsk_nin().
*
* struct FSK *fsk - FSK config/state struct, set up by fsk_create
* uint8_t rx_bits[] - Buffer for Nbits unpacked bits to be written
* float fsk_in[] - nin samples of modualted FSK
*/
void fsk_demod(struct FSK *fsk, uint8_t rx_bits[],COMP fsk_in[]);
/*
* Demodulate some number of FSK samples. The number of samples to be
* demodulated can be found by calling fsk_nin().
*
* struct FSK *fsk - FSK config/state struct, set up by fsk_create
* float rx_bits[] - Buffer for Nbits soft decision bits to be written
* float fsk_in[] - nin samples of modualted FSK
*/
void fsk_demod_sd(struct FSK *fsk, float rx_bits[],COMP fsk_in[]);
/* enables/disables normalisation of eye diagram samples */
void fsk_stats_normalise_eye(struct FSK *fsk, int normalise_enable);
/* Set the FSK modem into burst demod mode */
void fsk_enable_burst_mode(struct FSK *fsk,int nsyms);
} // FreeSV
#endif

View File

@ -0,0 +1,46 @@
/*---------------------------------------------------------------------------*\
FILE........: gp_interleaver.h
AUTHOR......: David Rowe
DATE CREATED: April 2018
Golden Prime Interleaver. My interprestation of "On the Analysis and
Design of Good Algebraic Interleavers", Xie et al,eq (5).
See also octvae/gp_interleaver.m
\*---------------------------------------------------------------------------*/
/*
Copyright (C) 2018 David Rowe
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1, as
published by the Free Software Foundation. This program is
distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GP_INTERLEAVER__
#define __GP_INTERLEAVER__
#include "codec2/comp.h"
namespace FreeDV
{
void gp_interleave_comp(COMP interleaved_frame[], COMP frame[], int Nbits);
void gp_deinterleave_comp(COMP frame[], COMP interleaved_frame[], int Nbits);
void gp_interleave_float(float frame[], float interleaved_frame[], int Nbits);
void gp_deinterleave_float(float interleaved_frame[], float frame[], int Nbits);
} // FreeDV
#endif

59
libfreedv/interldpc.h Normal file
View File

@ -0,0 +1,59 @@
/*---------------------------------------------------------------------------*\
FILE........: interldpc.h
AUTHOR......: David Rowe
DATE CREATED: April 2018
Helper functions for interleaved LDPC modems.
\*---------------------------------------------------------------------------*/
/*
Copyright (C) 2018 David Rowe
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1, as
published by the Free Software Foundation. This program is
distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __INTERLDPC__
#define __INTERLDPC__
#include <stdint.h>
#include "codec2/comp.h"
#include "mpdecode_core.h"
#include "ofdm_internal.h"
namespace FreeDV
{
/* CRC type function, used to compare QPSK vectors when debugging */
COMP test_acc(COMP v[], int n);
void printf_n(COMP v[], int n);
void set_up_hra_112_112(struct LDPC *ldpc, struct OFDM_CONFIG *);
void ldpc_encode_frame(struct LDPC *ldpc, int codeword[], unsigned char tx_bits_char[]);
void qpsk_modulate_frame(COMP tx_symbols[], int codeword[], int n);
void interleaver_sync_state_machine(struct OFDM *ofdm, struct LDPC *ldpc, struct OFDM_CONFIG *config,
COMP codeword_symbols_de[],
float codeword_amps_de[],
float EsNo, int interleave_frames,
int *inter, int *parityCheckCount, int *Nerrs_coded);
int count_uncoded_errors(struct LDPC *ldpc, struct OFDM_CONFIG *config, int Nerrs_raw[], int interleave_frames, COMP codeword_symbols_de[]);
int count_errors(uint8_t tx_bits[], uint8_t rx_bits[], int n);
void ofdm_ldpc_interleave_tx(struct OFDM *ofdm, struct LDPC *ldpc, std::complex<float> tx_sams[], uint8_t tx_bits[], uint8_t txt_bits[], int interleave_frames, struct OFDM_CONFIG *config);
void build_modulated_uw(struct OFDM *ofdm, std::complex<float> tx_symbols[], uint8_t txt_bits[], struct OFDM_CONFIG *config);
} // FreeDV
#endif

122
libfreedv/kiss_fft.h Normal file
View File

@ -0,0 +1,122 @@
#ifndef FREEDV_KISS_FFT_H
#define FREEDV_KISS_FFT_H
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
/*
ATTENTION!
If you would like a :
-- a utility that will handle the caching of fft objects
-- real-only (no imaginary time component ) FFT
-- a multi-dimensional FFT
-- a command-line utility to perform ffts
-- a command-line utility to perform fast-convolution filtering
Then see kfc.h kiss_fftr.h kiss_fftnd.h fftutil.c kiss_fastfir.c
in the tools/ directory.
*/
#ifdef USE_SIMD
# include <xmmintrin.h>
# define kiss_fft_scalar __m128
#define KISS_FFT_MALLOC(nbytes) _mm_malloc(nbytes,16)
#define KISS_FFT_FREE _mm_free
#else
#define KISS_FFT_MALLOC malloc
#define KISS_FFT_FREE free
#endif
#ifdef FIXED_POINT
#include <sys/types.h>
# if (FIXED_POINT == 32)
# define kiss_fft_scalar int32_t
# else
# define kiss_fft_scalar int16_t
# endif
#else
# ifndef kiss_fft_scalar
/* default is float */
# define kiss_fft_scalar float
# endif
#endif
namespace FreeDV
{
typedef struct {
kiss_fft_scalar r;
kiss_fft_scalar i;
}kiss_fft_cpx;
typedef struct kiss_fft_state* kiss_fft_cfg;
/*
* kiss_fft_alloc
*
* Initialize a FFT (or IFFT) algorithm's cfg/state buffer.
*
* typical usage: kiss_fft_cfg mycfg=kiss_fft_alloc(1024,0,NULL,NULL);
*
* The return value from fft_alloc is a cfg buffer used internally
* by the fft routine or NULL.
*
* If lenmem is NULL, then kiss_fft_alloc will allocate a cfg buffer using malloc.
* The returned value should be free()d when done to avoid memory leaks.
*
* The state can be placed in a user supplied buffer 'mem':
* If lenmem is not NULL and mem is not NULL and *lenmem is large enough,
* then the function places the cfg in mem and the size used in *lenmem
* and returns mem.
*
* If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough),
* then the function returns NULL and places the minimum cfg
* buffer size in *lenmem.
* */
kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem);
/*
* kiss_fft(cfg,in_out_buf)
*
* Perform an FFT on a complex input buffer.
* for a forward FFT,
* fin should be f[0] , f[1] , ... ,f[nfft-1]
* fout will be F[0] , F[1] , ... ,F[nfft-1]
* Note that each element is complex and can be accessed like
f[k].r and f[k].i
* */
void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout);
/*
A more generic version of the above function. It reads its input from every Nth sample.
* */
void kiss_fft_stride(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int fin_stride);
/* If kiss_fft_alloc allocated a buffer, it is one contiguous
buffer and can be simply free()d when no longer needed*/
#define kiss_fft_free free
/*
Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up
your compiler output to call this before you exit.
*/
void kiss_fft_cleanup(void);
/*
* Returns the smallest integer k, such that k>=n and k has only "fast" factors (2,3,5)
*/
int kiss_fft_next_fast_size(int n);
/* for real ffts, we need an even size */
#define kiss_fftr_next_fast_size_real(n) \
(kiss_fft_next_fast_size( ((n)+1)>>1)<<1)
} // FreeDV
#endif // FREEDV_KISS_FFT_H

44
libfreedv/kiss_fftr.h Normal file
View File

@ -0,0 +1,44 @@
#ifndef KISS_FTR_H
#define KISS_FTR_H
#include "kiss_fft.h"
namespace FreeDV
{
/*
Real optimized version can save about 45% cpu time vs. complex fft of a real seq.
*/
typedef struct kiss_fftr_state *kiss_fftr_cfg;
kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem, size_t * lenmem);
/*
nfft must be even
If you don't care to allocate space, use mem = lenmem = NULL
*/
void kiss_fftr(kiss_fftr_cfg cfg,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata);
/*
input timedata has nfft scalar points
output freqdata has nfft/2+1 complex points
*/
void kiss_fftri(kiss_fftr_cfg cfg,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata);
/*
input freqdata has nfft/2+1 complex points
output timedata has nfft scalar points
*/
} // FreeDV
#define kiss_fftr_free free
#endif

186
libfreedv/libfreedv.h Normal file
View File

@ -0,0 +1,186 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB //
// //
// freedv_api.h replacement //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
/*---------------------------------------------------------------------------*\
FILE........: freedv_api.h
AUTHOR......: David Rowe
DATE CREATED: August 2014
Library of API functions that implement FreeDV "modes", useful for
embedding FreeDV in other programs. Please see the documentation
for each function in freedv_api.c, and the sample freedv_tx.c and
freedv_rx.c programs.
\*---------------------------------------------------------------------------*/
/*
Copyright (C) 2014 David Rowe
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1, as
published by the Free Software Foundation. This program is
distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIBFREEDV_LIBFREEDV_H_
#define LIBFREEDV_LIBFREEDV_H_
// This declares a single-precision (float) complex number
#include <cstddef>
#include <sys/types.h>
#include "codec2/comp.h"
#include "codec2_ofdm.h"
#define FREEDV_MODE_1600 0
#define FREEDV_MODE_700 1
#define FREEDV_MODE_700B 2
#define FREEDV_MODE_2400A 3
#define FREEDV_MODE_2400B 4
#define FREEDV_MODE_800XA 5
#define FREEDV_MODE_700C 6
#define FREEDV_MODE_700D 7
/* operator control of 700D state machine */
#define FREEDV_SYNC_UNSYNC 0 /* force sync state machine to lose sync, and search for new sync */
#define FREEDV_SYNC_AUTO 1 /* falls out of sync automatically */
#define FREEDV_SYNC_MANUAL 2 /* fall out of sync only under operator control */
namespace FreeDV
{
struct freedv;
/* advanced freedv open options rqd by some modes */
struct freedv_advanced {
int interleave_frames;
};
/* Called when text message char is decoded */
typedef void (*freedv_callback_rx)(void *, char);
/* Called when new text message char is needed */
typedef char (*freedv_callback_tx)(void *);
typedef void (*freedv_calback_error_pattern)
(void *error_pattern_callback_state, short error_pattern[], int sz_error_pattern);
/* Protocol bits are packed MSB-first */
/* Called when a frame containing protocol data is decoded */
typedef void (*freedv_callback_protorx)(void *, char *);
/* Called when a frame containing protocol data is to be sent */
typedef void (*freedv_callback_prototx)(void *, char *);
/* Data packet callbacks */
/* Called when a packet has been received */
typedef void (*freedv_callback_datarx)(void *, unsigned char *packet, std::size_t size);
/* Called when a new packet can be send */
typedef void (*freedv_callback_datatx)(void *, unsigned char *packet, std::size_t *size);
/*---------------------------------------------------------------------------*\
FreeDV API functions
\*---------------------------------------------------------------------------*/
// open, close ----------------------------------------------------------------
struct freedv *freedv_open(int mode);
struct freedv *freedv_open_advanced(int mode, struct freedv_advanced *adv);
void freedv_close (struct freedv *freedv);
// Transmit -------------------------------------------------------------------
void freedv_tx (struct freedv *freedv, short mod_out[], short speech_in[]);
void freedv_comptx (struct freedv *freedv, COMP mod_out[], short speech_in[]);
void freedv_codectx (struct freedv *f, short mod_out[], unsigned char *packed_codec_bits);
void freedv_datatx (struct freedv *f, short mod_out[]);
int freedv_data_ntxframes (struct freedv *freedv);
// Receive -------------------------------------------------------------------
int freedv_nin (struct freedv *freedv);
int freedv_rx (struct freedv *freedv, short speech_out[], short demod_in[]);
int freedv_shortrx (struct freedv *freedv, short speech_out[], short demod_in[], float gain);
int freedv_floatrx (struct freedv *freedv, short speech_out[], float demod_in[]);
int freedv_comprx (struct freedv *freedv, short speech_out[], COMP demod_in[]);
int freedv_codecrx (struct freedv *freedv, unsigned char *packed_codec_bits, short demod_in[]);
// Set parameters ------------------------------------------------------------
void freedv_set_callback_txt (struct freedv *freedv, freedv_callback_rx rx, freedv_callback_tx tx, void *callback_state);
void freedv_set_callback_protocol (struct freedv *freedv, freedv_callback_protorx rx, freedv_callback_prototx tx, void *callback_state);
void freedv_set_callback_data (struct freedv *freedv, freedv_callback_datarx datarx, freedv_callback_datatx datatx, void *callback_state);
void freedv_set_test_frames (struct freedv *freedv, int test_frames);
void freedv_set_test_frames_diversity (struct freedv *freedv, int test_frames_diversity);
void freedv_set_smooth_symbols (struct freedv *freedv, int smooth_symbols);
void freedv_set_squelch_en (struct freedv *freedv, int squelch_en);
void freedv_set_snr_squelch_thresh (struct freedv *freedv, float snr_squelch_thresh);
void freedv_set_clip (struct freedv *freedv, int val);
void freedv_set_total_bit_errors (struct freedv *freedv, int val);
void freedv_set_total_bits (struct freedv *freedv, int val);
void freedv_set_callback_error_pattern (struct freedv *freedv, freedv_calback_error_pattern cb, void *state);
void freedv_set_varicode_code_num (struct freedv *freedv, int val);
void freedv_set_data_header (struct freedv *freedv, unsigned char *header);
int freedv_set_alt_modem_samp_rate (struct freedv *freedv, int samp_rate);
void freedv_set_carrier_ampl (struct freedv *freedv, int c, float ampl);
void freedv_set_sync (struct freedv *freedv, Sync sync_cmd);
void freedv_set_verbose (struct freedv *freedv, int verbosity);
void freedv_set_tx_bpf (struct freedv *freedv, int val);
void freedv_set_ext_vco (struct freedv *f, int val);
// Get parameters -------------------------------------------------------------------------
struct MODEM_STATS;
int freedv_get_version(void);
int freedv_get_mode (struct freedv *freedv);
void freedv_get_modem_stats (struct freedv *freedv, int *sync, float *snr_est);
void freedv_get_modem_extended_stats(struct freedv *freedv, struct MODEM_STATS *stats);
int freedv_get_test_frames (struct freedv *freedv);
int freedv_get_n_speech_samples (struct freedv *freedv);
int freedv_get_modem_sample_rate (struct freedv *freedv);
int freedv_get_modem_symbol_rate (struct freedv *freedv);
int freedv_get_n_max_modem_samples (struct freedv *freedv);
int freedv_get_n_nom_modem_samples (struct freedv *freedv);
int freedv_get_total_bits (struct freedv *freedv);
int freedv_get_total_bit_errors (struct freedv *freedv);
int freedv_get_total_bits_coded (struct freedv *freedv);
int freedv_get_total_bit_errors_coded(struct freedv *freedv);
int freedv_get_sync (struct freedv *freedv);
int freedv_get_sync_interleaver (struct freedv *freedv);
struct FSK * freedv_get_fsk (struct freedv *f);
struct CODEC2 *freedv_get_codec2 (struct freedv *freedv);
int freedv_get_n_codec_bits (struct freedv *freedv);
int freedv_get_sz_error_pattern (struct freedv *freedv);
int freedv_get_protocol_bits (struct freedv *freedv);
} // namespace FreeDV
#endif /* LIBFREEDV_LIBFREEDV_H_ */

134
libfreedv/modem_probe.h Normal file
View File

@ -0,0 +1,134 @@
/*---------------------------------------------------------------------------*\
FILE........: modem_probe.h
AUTHOR......: Brady O'Brien
DATE CREATED: 9 January 2016
Library to easily extract debug traces from modems during development
\*---------------------------------------------------------------------------*/
/*
Copyright (C) 2016 David Rowe
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1, as
published by the Free Software Foundation. This program is
distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __MODEMPROBE_H
#define __MODEMPROBE_H
#include <stdint.h>
#include <stdlib.h>
#include <complex.h>
#include "comp.h"
namespace FreeDV
{
#ifdef MODEMPROBE_ENABLE
/* Internal functions */
void modem_probe_init_int(char *modname, char *runname);
void modem_probe_close_int();
void modem_probe_samp_i_int(char * tracename,int samp[],size_t cnt);
void modem_probe_samp_f_int(char * tracename,float samp[],size_t cnt);
void modem_probe_samp_c_int(char * tracename,COMP samp[],size_t cnt);
/*
* Init the probe library.
* char *modname - Name of the modem under test
* char *runname - Name/path of the file data is dumped to
*/
static inline void modem_probe_init(char *modname,char *runname){
modem_probe_init_int(modname,runname);
}
/*
* Dump traces to a file and clean up
*/
static inline void modem_probe_close(){
modem_probe_close_int();
}
/*
* Save some number of int samples to a named trace
* char *tracename - name of trace being saved to
* int samp[] - int samples
* size_t cnt - how many samples to save
*/
static inline void modem_probe_samp_i(char *tracename,int samp[],size_t cnt){
modem_probe_samp_i_int(tracename,samp,cnt);
}
/*
* Save some number of float samples to a named trace
* char *tracename - name of trace being saved to
* float samp[] - int samples
* size_t cnt - how many samples to save
*/
static inline void modem_probe_samp_f(char *tracename,float samp[],size_t cnt){
modem_probe_samp_f_int(tracename,samp,cnt);
}
/*
* Save some number of complex samples to a named trace
* char *tracename - name of trace being saved to
* COMP samp[] - int samples
* size_t cnt - how many samples to save
*/
static inline void modem_probe_samp_c(char *tracename,COMP samp[],size_t cnt){
modem_probe_samp_c_int(tracename,samp,cnt);
}
/*
* Save some number of complex samples to a named trace
* char *tracename - name of trace being saved to
* float complex samp[] - int samples
* size_t cnt - how many samples to save
*/
static inline void modem_probe_samp_cft(char *tracename,complex float samp[],size_t cnt){
modem_probe_samp_c_int(tracename,(COMP*)samp,cnt);
}
#else
static inline void modem_probe_init(char *modname,char *runname){
return;
}
static inline void modem_probe_close(){
return;
}
static inline void modem_probe_samp_i(char *name,int samp[],size_t sampcnt){
return;
}
static inline void modem_probe_samp_f(char *name,float samp[],size_t cnt){
return;
}
static inline void modem_probe_samp_c(char *name,COMP samp[],size_t cnt){
return;
}
static inline void modem_probe_samp_cft(char *name,complex float samp[],size_t cnt){
return;
}
#endif
} // FreeDV
#endif

79
libfreedv/modem_stats.h Normal file
View File

@ -0,0 +1,79 @@
/*---------------------------------------------------------------------------*\
FILE........: modem_stats.h
AUTHOR......: David Rowe
DATE CREATED: June 2015
Common structure for returning demod stats from fdmdv and cohpsk modems.
\*---------------------------------------------------------------------------*/
/*
Copyright (C) 2015 David Rowe
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1, as
published by the Free Software Foundation. This program is
distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FREEDV_MODEM_STATS__
#define __FREEDV_MODEM_STATS__
#include "codec2/comp.h"
#include "kiss_fft.h"
#define MODEM_STATS_NC_MAX 20
#define MODEM_STATS_NR_MAX 8
#define MODEM_STATS_ET_MAX 8
#define MODEM_STATS_EYE_IND_MAX 160
#define MODEM_STATS_NSPEC 512
#define MODEM_STATS_MAX_F_HZ 4000
#define MODEM_STATS_MAX_F_EST 4
namespace FreeDV
{
struct MODEM_STATS {
int Nc;
float snr_est; /* estimated SNR of rx signal in dB (3 kHz noise BW) */
COMP rx_symbols[MODEM_STATS_NR_MAX][MODEM_STATS_NC_MAX+1];
/* latest received symbols, for scatter plot */
int nr; /* number of rows in rx_symbols */
int sync; /* demod sync state */
float foff; /* estimated freq offset in Hz */
float rx_timing; /* estimated optimum timing offset in samples */
float clock_offset; /* Estimated tx/rx sample clock offset in ppm */
float sync_metric; /* number between 0 and 1 indicating quality of sync */
/* eye diagram traces */
/* Eye diagram plot -- first dim is trace number, second is the trace idx */
float rx_eye[MODEM_STATS_ET_MAX][MODEM_STATS_EYE_IND_MAX];
int neyetr; /* How many eye traces are plotted */
int neyesamp; /* How many samples in the eye diagram */
/* optional for FSK modems - est tone freqs */
float f_est[MODEM_STATS_MAX_F_EST];
/* Buf for FFT/waterfall */
float fft_buf[2*MODEM_STATS_NSPEC];
kiss_fft_cfg fft_cfg;
};
void modem_stats_open(struct MODEM_STATS *f);
void modem_stats_close(struct MODEM_STATS *f);
void modem_stats_get_rx_spectrum(struct MODEM_STATS *f, float mag_spec_dB[], COMP rx_fdm[], int nin);
} // FreeDV
#endif

51
libfreedv/mpdecode_core.h Normal file
View File

@ -0,0 +1,51 @@
/*
FILE...: mpdecode_core.h
AUTHOR.: David Rowe
CREATED: Sep 2016
C-callable core functions for MpDecode, so they can be used for
Octave and C programs. Also some convenience functions to help use
the C-callable LDPC decoder in C programs.
*/
#ifndef __MPDECODE_CORE__
#define __MPDECODE_CORE__
#include <stdint.h>
#include "codec2/comp.h"
namespace FreeDV
{
struct LDPC {
int max_iter;
int dec_type;
int q_scale_factor;
int r_scale_factor;
int CodeLength;
int NumberParityBits;
int NumberRowsHcols;
int max_row_weight;
int max_col_weight;
int data_bits_per_frame;
int coded_bits_per_frame;
int coded_syms_per_frame;
uint16_t *H_rows;
uint16_t *H_cols;
};
void encode(struct LDPC *ldpc, unsigned char ibits[], unsigned char pbits[]);
int run_ldpc_decoder(struct LDPC *ldpc, uint8_t out_char[], float input[], int *parityCheckCount);
void sd_to_llr(float llr[], double sd[], int n);
void Demod2D(float symbol_likelihood[], COMP r[], COMP S_matrix[], float EsNo, float fading[], float mean_amp, int number_symbols);
void Somap(float bit_likelihood[], float symbol_likelihood[], int number_symbols);
void symbols_to_llrs(float llr[], COMP rx_qpsk_symbols[], float rx_amps[], float EsNo, float mean_amp, int nsyms);
void ldpc_print_info(struct LDPC *ldpc);
} // FreeDV
#endif

137
libfreedv/ofdm_internal.h Normal file
View File

@ -0,0 +1,137 @@
/*---------------------------------------------------------------------------*\
FILE........: ofdm_internal.h
AUTHORS.....: David Rowe & Steve Sampson
DATE CREATED: June 2017
OFDM Internal definitions.
\*---------------------------------------------------------------------------*/
/*
Copyright (C) 2017 David Rowe
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1, as
published by the Free Software Foundation. This program is
distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OFDM_INTERNAL_H
#define OFDM_INTERNAL_H
#include <complex.h>
#include <stdbool.h>
#include <stdint.h>
#include "codec2_ofdm.h"
#include "freedv_filter.h"
#include "fdv_arm_math.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846f
#endif
#define TAU (2.0f * M_PI)
#define ROT45 (M_PI / 4.0f)
#define cmplx(value) (COSF(value) + SINF(value) * I)
#define cmplxconj(value) (COSF(value) + SINF(value) * -I)
namespace FreeDV
{
/*
* Contains user configuration for OFDM modem
*/
struct OFDM_CONFIG {
float tx_centre; /* TX Centre Audio Frequency */
float rx_centre; /* RX Centre Audio Frequency */
float fs; /* Sample Frequency */
float rs; /* Modulation Symbol Rate */
float ts; /* symbol duration */
float tcp; /* Cyclic Prefix duration */
float ofdm_timing_mx_thresh;
int nc; /* Number of carriers */
int ns; /* Number of Symbol frames */
int bps; /* Bits per Symbol */
int txtbits; /* number of auxiliary data bits */
int ftwindowwidth;
};
struct OFDM {
std::complex<float> *pilot_samples;
std::complex<float> *rxbuf;
std::complex<float> *pilots;
std::complex<float> **rx_sym;
std::complex<float> *rx_np;
float *rx_amp;
float *aphase_est_pilot_log;
uint8_t *tx_uw;
State sync_state;
State last_sync_state;
State sync_state_interleaver;
State last_sync_state_interleaver;
Sync sync_mode;
struct quisk_cfFilter *ofdm_tx_bpf;
std::complex<float> foff_metric;
float foff_est_gain;
float foff_est_hz;
float timing_mx;
float coarse_foff_est_hz;
float timing_norm;
float sig_var;
float noise_var;
float mean_amp;
int clock_offset_counter;
int verbose;
int sample_point;
int timing_est;
int timing_valid;
int nin;
int uw_errors;
int sync_counter;
int frame_count;
int frame_count_interleaver;
bool sync_start;
bool sync_end;
bool timing_en;
bool foff_est_en;
bool phase_est_en;
bool tx_bpf_en;
};
/* function headers exposed for LDPC work */
std::complex<float> qpsk_mod(int *);
void qpsk_demod(std::complex<float>, int *);
void ofdm_txframe(struct OFDM *, std::complex<float> *, std::complex<float> []);
void ofdm_assemble_modem_frame(struct OFDM *, uint8_t [], uint8_t [], uint8_t []);
void ofdm_assemble_modem_frame_symbols(std::complex<float> [], COMP [], uint8_t []);
void ofdm_disassemble_modem_frame(struct OFDM *, uint8_t [], COMP [], float [], short []);
void ofdm_rand(uint16_t [], int);
void ofdm_generate_payload_data_bits(uint8_t payload_data_bits[], int data_bits_per_frame);
} // FreeDV
#endif