FreeDV: use mainstream freeDV modem from codec2 instead of internal library. Updated git checkout SHA1 to latest. Updated version and changelogs.

This commit is contained in:
f4exb 2019-06-15 10:58:55 +02:00
parent 68e4eaac68
commit aa0290bd19
69 changed files with 82 additions and 19473 deletions

View File

@ -1,3 +1,11 @@
sdrangel (4.10.1-1) unstable; urgency=medium
* Implemented device user arguments
* PVS-Studio static analysis corrections (5)
* FreeDV demod: use mainstream library from codec2 instead of internal
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sat, 15 Jun 2019 06:44:06 +0100
sdrangel (4.10.0-1) unstable; urgency=medium
* Support for KiwiSDR

View File

@ -18,7 +18,7 @@ set(CMAKE_CXX_EXTENSIONS OFF)
# configure version
set(sdrangel_VERSION_MAJOR "4")
set(sdrangel_VERSION_MINOR "10")
set(sdrangel_VERSION_PATCH "0")
set(sdrangel_VERSION_PATCH "1")
set(sdrangel_VERSION_SUFFIX "")
# SDRAngel cmake options
@ -374,10 +374,6 @@ if(ENABLE_XTRX)
find_package(LibXTRX)
endif()
if (CODEC2_FOUND)
add_subdirectory(libfreedv)
endif(CODEC2_FOUND)
if(ENABLE_FUNCUBE AND UNIX AND LIBUSB_FOUND)
add_subdirectory(fcdlib)
add_subdirectory(fcdhid)

8
debian/changelog vendored
View File

@ -1,3 +1,11 @@
sdrangel (4.10.1-1) unstable; urgency=medium
* Implemented device user arguments
* PVS-Studio static analysis corrections (5)
* FreeDV demod: use mainstream library from codec2 instead of internal
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sat, 15 Jun 2019 06:44:06 +0100
sdrangel (4.10.0-1) unstable; urgency=medium
* Support for KiwiSDR

View File

@ -8,7 +8,7 @@
# but make the configuration dirty
# which version/tag/checkout to use
set(CODEC2_TAG 7a0187da3ffb06fd90c081216b50bab94d02d046)
set(CODEC2_TAG 76a20416d715ee06f8b36a9953506876689a3bd2)
set(CM256CC_TAG f21e8bc1e9afdb0b28672743dcec111aec1d32d9)
set(MBELIB_TAG "debian/1.3.0")
set(SERIALDV_TAG abd65a0fc2d5339808194862d14119b0cba70424)

View File

@ -1,83 +0,0 @@
project(freedv)
set(freedv_SOURCES
codec2_fft.cpp
cohpsk.cpp
fdmdv.cpp
freedv_api.cpp
freedv_data_channel.cpp
freedv_filter.cpp
freedv_vhf_framing.cpp
fmfsk.cpp
fsk.cpp
gp_interleaver.cpp
HRA_112_112.cpp
interldpc.cpp
kiss_fft.cpp
kiss_fftr.cpp
linreg.cpp
mpdecode_core.cpp
ofdm.cpp
phi0.cpp
)
set(freedv_HEADERS
codec2_cohpsk.h
codec2_fdmdv.h
codec2_fft.h
codec2_ofdm.h
cohpsk_defs.h
cohpsk_internal.h
comp_prim.h
defines.h
fdmdv_internal.h
fdv_arm_math.h
fmfsk.h
freedv_api_internal.h
freedv_data_channel.h
freedv_filter_coef.h
freedv_filter.h
freedv_vhf_framing.h
fsk.h
gp_interleaver.h
hanning.h
HRA_112_112.h
interldpc.h
_kiss_fft_guts.h
kiss_fft.h
kiss_fftr.h
libfreedv.h
linreg.h
machdep.h
modem_probe.h
modem_stats.h
mpdecode_core.h
ofdm_internal.h
os.h
phi0.h
pilot_coeff.h
pilots_coh.h
rn_coh.h
rn.h
rxdec_coeff.h
test_bits_coh.h
test_bits.h
)
include_directories(
${CODEC2_INCLUDE_DIR}
)
add_library(freedv SHARED
${freedv_SOURCES}
)
if(ENABLE_EXTERNAL_LIBRARIES)
add_dependencies(freedv codec2)
endif()
target_link_libraries(freedv
${CODEC2_LIBRARIES}
)
install(TARGETS freedv DESTINATION ${INSTALL_LIB_DIR})

View File

@ -1,27 +0,0 @@
/*
FILE....: HRA_112_112.c
Static arrays for LDPC codec HRA_112_112, generated by ldpc_gen_c_h_file.m.
*/
#include <stdint.h>
#include "HRA_112_112.h"
namespace FreeDV
{
const uint16_t HRA_112_112_H_rows[] = {
22, 18, 15, 63, 16, 13, 1, 2, 29, 25, 28, 4, 36, 10, 38, 7, 60, 23, 11, 38, 28, 1, 12, 31, 57, 45, 57, 30, 23, 59, 67, 14, 16, 4, 14, 62, 15, 50, 7, 70, 64, 6, 42, 48, 9, 31, 19, 40, 49, 2, 25, 3, 41, 49, 36, 9, 29, 39, 31, 5, 17, 1, 29, 25, 11, 21, 18, 2, 8, 22, 39, 15, 8, 22, 13, 3, 19, 4, 21, 62, 34, 43, 6, 24, 17, 60, 8, 74, 6, 44, 60, 10, 33, 12, 26, 24, 45, 81, 69, 80, 41, 28, 23, 5, 10, 20, 52, 18, 13, 86, 3, 7, 59, 21, 65, 72, 34, 37, 26, 55, 47, 48, 34, 5, 44, 47, 68, 96, 82, 111, 61, 74, 30, 17, 55, 98, 81, 66, 89, 35, 74, 82, 91, 51, 55, 51, 30, 89, 61, 75, 40, 71, 73, 11, 56, 54, 19, 47, 94, 69, 64, 20, 64, 12, 54, 77, 42, 88, 36, 52, 90, 63, 70, 27, 32, 73, 91, 32, 56, 46, 9, 78, 51, 68, 88, 67, 20, 43, 40, 14, 66, 86, 39, 97, 38, 27, 50, 84, 54, 92, 61, 46, 67, 24, 58, 35, 58, 37, 98, 85, 73, 84, 48, 35, 57, 16, 26, 37, 65, 32, 72, 95, 107, 33, 77, 33, 85, 105, 106, 75, 56, 71, 79, 59, 52, 105, 79, 90, 93, 100, 88, 112, 86, 80, 65, 42, 106, 100, 93, 94, 99, 97, 93, 101, 111, 99, 83, 53, 85, 95, 108, 107, 41, 109, 84, 78, 104, 101, 69, 110, 98, 103, 80, 83, 77, 71, 76, 78, 87, 102, 104, 95, 96, 83, 87, 50, 110, 103, 112, 45, 58, 70, 94, 91, 89, 81, 101, 82, 63, 72, 100, 97, 76, 112, 53, 105, 49, 75, 109, 102, 66, 111, 68, 87, 92, 79, 96, 43, 90, 44, 110, 99, 102, 92, 103, 106, 62, 53, 27, 46, 108, 104, 107, 108, 109, 76
};
const uint16_t HRA_112_112_H_cols[] = {
7, 8, 52, 12, 12, 42, 16, 69, 45, 14, 19, 23, 6, 32, 3, 5, 22, 2, 45, 50, 2, 1, 18, 84, 10, 7, 62, 11, 9, 21, 24, 63, 2, 5, 28, 13, 6, 15, 58, 39, 39, 22, 76, 13, 26, 68, 9, 10, 49, 38, 32, 11, 34, 44, 8, 7, 25, 67, 1, 17, 19, 36, 4, 41, 3, 26, 31, 15, 45, 40, 8, 4, 41, 20, 6, 53, 1, 42, 9, 20, 25, 17, 33, 41, 3, 19, 55, 17, 27, 14, 31, 88, 15, 26, 36, 16, 28, 24, 27, 16, 30, 56, 48, 43, 4, 5, 38, 37, 40, 46, 18, 18, 22, 50, 76, 34, 60, 83, 39, 73, 56, 92, 42, 52, 75, 35, 37, 33, 61, 67, 47, 75, 66, 70, 29, 92, 51, 95, 84, 21, 57, 28, 46, 66, 93, 11, 94, 55, 96, 20, 71, 48, 53, 43, 82, 90, 66, 90, 14, 44, 54, 62, 34, 58, 81, 53, 23, 43, 27, 93, 10, 86, 37, 80, 60, 49, 21, 79, 74, 72, 48, 61, 40, 76, 64, 29, 38, 79, 51, 54, 13, 49, 72, 30, 50, 86, 35, 80, 61, 56, 36, 59, 65, 91, 25, 47, 58, 59, 78, 47, 32, 24, 44, 86, 64, 57, 12, 23, 109, 107, 85, 63, 31, 65, 62, 68, 111, 78, 104, 89, 112, 87, 69, 105, 65, 94, 109, 78, 72, 104, 85, 108, 77, 106, 79, 74, 103, 96, 64, 105, 105, 102, 63, 35, 59, 108, 112, 81, 102, 57, 106, 83, 81, 77, 101, 55, 94, 96, 97, 106, 46, 101, 83, 85, 71, 107, 104, 87, 33, 67, 103, 95, 30, 91, 89, 103, 75, 51, 107, 87, 91, 89, 99, 68, 52, 109, 99, 88, 84, 112, 54, 70, 92, 100, 98, 74, 60, 100, 98, 110, 90, 73, 71, 95, 70, 100, 29, 69, 110, 93, 82, 97, 98, 77, 73, 99, 101, 108, 82, 102, 111, 110, 111, 97, 88, 80
};
const float HRA_112_112_input[] = {
-3.7496794787890972, 14.372112019392226, -7.5640452729302359, 6.9426063455159657, 5.3103644888713299, -6.9203550501252273, 8.4296575778653775, 13.495087143587781, 18.111520666852243, -9.9125748623510912, 10.601298534930972, -10.468591112149715, -9.0757329437720475, -14.471433733514324, 5.2048820572852641, -11.353785810284556, -9.4511008284496416, -9.5255219979484025, -2.0499245561876696, -9.8739646459388748, 22.03442141444015, -9.9745566449839878, -8.4276711655946226, -4.9811962116476307, -13.018434575859896, -5.3358535334627293, -5.6704294937789648, 14.243964608060018, -11.417925510314507, 9.1332657371467878, -14.380214782394296, 14.090409878618974, 6.5602278279998272, 15.53025696352436, -9.1752771765906616, -11.384503450560766, 12.240329442222599, -12.640059450058276, -11.824715154614376, -13.487656131954735, 15.38073452845444, -13.816294924566529, 6.3461114450644454, -2.5192445130977559, -11.916088712873863, 5.4360722876642518, 0.038031547223147381, -12.367220238860654, -2.747864039796549, -14.920508782249289, 16.487336720060863, -13.290002442259247, 19.142698450560925, -0.39443060583296108, 11.723442316413736, -3.6131702833965047, -4.6196487103817017, -11.794290650694531, -14.342351103186955, 2.8079943208330334, -15.290175151123936, 9.0801740558512414, 10.184385069676226, 8.400722260237572, 9.3504690108712936, -14.223531676384166, 11.752768386971752, 11.36995822251677, -15.285021241405444, -13.070613695054403, -11.869191325617697, 4.3191750845563401, 2.0836933404582791, -16.363829786416495, -5.7778094839806595, 11.06389861779129, 13.285433846434705, 9.2552396418849021, -11.065999403824057, -10.167040394420443, -7.0107225044503565, 2.3886881673282474, 5.0014484787306932, -9.2464083853314278, -12.043309174487364, -11.638411967211738, -16.302815497922911, 13.347129717938067, -4.1390259986125226, 0.7947480277507295, 11.538620744796759, -7.4410706619926028, 14.572449028311253, 12.392747919231169, -3.3027890746379289, -9.8431096813736687, 11.582657487369399, -7.85736442083219, -7.3780721969188443, -7.4006260265172212, -8.3937994980934327, -6.6804071011469555, 19.656301355404196, 1.1084340389939762, 3.6028635453146465, -4.5409495140900562, 7.3831459854578982, -5.5905999874445662, -13.852328482738232, 8.9999210644983041, 8.4742375282492315, 16.989947243749878, 7.5590035165610168, -6.154674423116183, 4.1119120658251855, 12.351217703790844, 11.070972687846792, 11.182587746846833, -4.9345619923565645, 9.0054892370887334, -10.841725474869696, 13.902796293412067, -6.7575171884905396, -5.8196703210757335, 1.9284357540668857, 9.9905382141440455, -13.983067199220674, -4.9130522479706453, -8.2369300184767908, 6.8953565265629644, 2.9285103862640871, -2.6303471135655325, -8.3563361642086047, 9.5712349244763715, 4.9728623009661161, -11.045088919587242, -5.7781337596219604, -17.732999074602972, 8.1353860976076646, -11.066240843831284, -1.7079574457159534, -16.411685365171998, -9.0471090651358299, -10.959376227315447, 8.5840398495674126, 6.6373658260736024, 11.422094029020409, 14.85785089306844, 13.185747281780415, 4.2063935223916191, -6.9166135608899282, 10.843153262137262, 5.3913075109409441, -10.744469667642237, -12.491640291445655, 14.141118162062066, 16.425476099516025, 9.8833761863476042, 2.8719064151687883, 14.982021915112442, 1.3588165304065343, -11.657839635726177, 11.066314862965077, -3.0565490195476204, 1.7820159270701772, -13.535333311782074, 4.4026933190218367, -11.097334550496313, -11.322820869044248, 16.418516996530371, 5.8239202459876136, 15.054905601216154, -9.3058742038490152, 8.48902767802557, -8.3853534273227748, -7.9255089736435176, -9.6156735881618811, 11.502594413898008, -6.0542015398269911, 7.1229229147355149, 0.31483632310264387, -11.482093481730768, -9.3225703551629309, 5.8001228713062831, -9.3515917458791051, 7.9778737065172969, 9.7095180444854847, -14.060064536791135, 4.9797253221020545, -6.9210799657794224, 6.6736460552213845, -7.7636429824024606, 10.233132490278882, 8.401747393605044, -10.861100567451366, 13.631509744686715, -15.723791754613185, -8.7931294115815923, -9.9520037489001609, -10.312792052906007, -8.0681893911111917, -15.411052087079765, 10.938779471602952, -8.751795633239853, -9.1302029882284419, -2.3357314769649777, -7.9130658335895596, 2.7508172894969509, -9.1666780515772324, 12.793063537524359, -13.39091818112591, 7.2827402370664842, -10.400778532411657, -1.90854156128735, -4.1272702472088971, 12.696932922959466, -4.0180403457213805, 10.828999052972396, 14.720617452742685, -8.3763729074389719, 3.955093172344033, 0.90932711822659873, -5.6696817865337819, -5.8822086115513805
};
const char HRA_112_112_detected_data[] = {
1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1
};
} // FreeDV

View File

@ -1,23 +0,0 @@
/*
FILE....: HRA_112_112.h
Static arrays for LDPC codec HRA_112_112, generated by ldpc_gen_c_h_file.m.
*/
#define HRA_112_112_NUMBERPARITYBITS 112
#define HRA_112_112_MAX_ROW_WEIGHT 3
#define HRA_112_112_CODELENGTH 224
#define HRA_112_112_NUMBERROWSHCOLS 112
#define HRA_112_112_MAX_COL_WEIGHT 3
#define HRA_112_112_DEC_TYPE 0
#define HRA_112_112_MAX_ITER 100
namespace FreeDV
{
extern const uint16_t HRA_112_112_H_rows[];
extern const uint16_t HRA_112_112_H_cols[];
extern const float HRA_112_112_input[];
extern const char HRA_112_112_detected_data[];
} // FreeDV

View File

@ -1,159 +0,0 @@
/*
Copyright (c) 2003-2010, Mark Borgerding
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* kiss_fft.h
defines kiss_fft_scalar as either short or a float type
and defines
typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */
#include "kiss_fft.h"
#include <limits.h>
#define MAXFACTORS 32
/* e.g. an fft of length 128 has 4 factors
as far as kissfft is concerned
4*4*4*2
*/
namespace FreeDV
{
struct kiss_fft_state{
int nfft;
int inverse;
int factors[2*MAXFACTORS];
kiss_fft_cpx twiddles[1];
};
/*
Explanation of macros dealing with complex math:
C_MUL(m,a,b) : m = a*b
C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise
C_SUB( res, a,b) : res = a - b
C_SUBFROM( res , a) : res -= a
C_ADDTO( res , a) : res += a
* */
#ifdef FIXED_POINT
#if (FIXED_POINT==32)
# define FRACBITS 31
# define SAMPPROD int64_t
#define SAMP_MAX 2147483647
#else
# define FRACBITS 15
# define SAMPPROD int32_t
#define SAMP_MAX 32767
#endif
#define SAMP_MIN -SAMP_MAX
#if defined(CHECK_OVERFLOW)
# define CHECK_OVERFLOW_OP(a,op,b) \
if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \
fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) ); }
#endif
# define smul(a,b) ( (SAMPPROD)(a)*(b) )
# define sround( x ) (kiss_fft_scalar)( ( (x) + (1<<(FRACBITS-1)) ) >> FRACBITS )
# define S_MUL(a,b) sround( smul(a,b) )
# define C_MUL(m,a,b) \
do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \
(m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0)
# define DIVSCALAR(x,k) \
(x) = sround( smul( x, SAMP_MAX/k ) )
# define C_FIXDIV(c,div) \
do { DIVSCALAR( (c).r , div); \
DIVSCALAR( (c).i , div); }while (0)
# define C_MULBYSCALAR( c, s ) \
do{ (c).r = sround( smul( (c).r , s ) ) ;\
(c).i = sround( smul( (c).i , s ) ) ; }while(0)
#else /* not FIXED_POINT*/
# define S_MUL(a,b) ( (a)*(b) )
#define C_MUL(m,a,b) \
do{ (m).r = (a).r*(b).r - (a).i*(b).i;\
(m).i = (a).r*(b).i + (a).i*(b).r; }while(0)
# define C_FIXDIV(c,div) /* NOOP */
# define C_MULBYSCALAR( c, s ) \
do{ (c).r *= (s);\
(c).i *= (s); }while(0)
#endif
#ifndef CHECK_OVERFLOW_OP
# define CHECK_OVERFLOW_OP(a,op,b) /* noop */
#endif
#define C_ADD( res, a,b)\
do { \
CHECK_OVERFLOW_OP((a).r,+,(b).r)\
CHECK_OVERFLOW_OP((a).i,+,(b).i)\
(res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \
}while(0)
#define C_SUB( res, a,b)\
do { \
CHECK_OVERFLOW_OP((a).r,-,(b).r)\
CHECK_OVERFLOW_OP((a).i,-,(b).i)\
(res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \
}while(0)
#define C_ADDTO( res , a)\
do { \
CHECK_OVERFLOW_OP((res).r,+,(a).r)\
CHECK_OVERFLOW_OP((res).i,+,(a).i)\
(res).r += (a).r; (res).i += (a).i;\
}while(0)
#define C_SUBFROM( res , a)\
do {\
CHECK_OVERFLOW_OP((res).r,-,(a).r)\
CHECK_OVERFLOW_OP((res).i,-,(a).i)\
(res).r -= (a).r; (res).i -= (a).i; \
}while(0)
#ifdef FIXED_POINT
# define KISS_FFT_COS(phase) floorf(.5+SAMP_MAX * cosf (phase))
# define KISS_FFT_SIN(phase) floorf(.5+SAMP_MAX * sinf (phase))
# define HALF_OF(x) ((x)>>1)
#elif defined(USE_SIMD)
# define KISS_FFT_COS(phase) _mm_set1_ps( cosf(phase) )
# define KISS_FFT_SIN(phase) _mm_set1_ps( sinf(phase) )
# define HALF_OF(x) ((x)*_mm_set1_ps(.5))
#else
# define KISS_FFT_COS(phase) (kiss_fft_scalar) cosf(phase)
# define KISS_FFT_SIN(phase) (kiss_fft_scalar) sinf(phase)
# define HALF_OF(x) ((x)*.5)
#endif
#define kf_cexp(x,phase) \
do{ \
(x)->r = KISS_FFT_COS(phase);\
(x)->i = KISS_FFT_SIN(phase);\
}while(0)
/* a debugging function */
#define pcpx(c)\
fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) )
#define KISS_FFT_TMP_ALLOC(nbytes) KISS_FFT_MALLOC(nbytes)
#define KISS_FFT_TMP_FREE(ptr) KISS_FFT_FREE(ptr)
} // FreeDV

View File

@ -1,76 +0,0 @@
/*---------------------------------------------------------------------------*\
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

View File

@ -1,110 +0,0 @@
/*---------------------------------------------------------------------------*\
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

View File

@ -1,163 +0,0 @@
/*
* codec2_fft.c
*
* Created on: 24.09.2016
* Author: danilo
*/
#include "codec2_fft.h"
#ifdef USE_KISS_FFT
#include "_kiss_fft_guts.h"
#endif
namespace FreeDV
{
#ifdef USE_KISS_FFT
#else
#if 0
// caching constants in RAM did not seem to have an effect on performance
// TODO: Decide what to with this code
#define FFT_INIT_CACHE_SIZE 4
const arm_cfft_instance_f32* fft_init_cache[FFT_INIT_CACHE_SIZE];
static const arm_cfft_instance_f32* arm_fft_instance2ram(const arm_cfft_instance_f32* in)
{
arm_cfft_instance_f32* out = malloc(sizeof(arm_cfft_instance_f32));
if (out) {
memcpy(out,in,sizeof(arm_cfft_instance_f32));
out->pBitRevTable = malloc(out->bitRevLength * sizeof(uint16_t));
out->pTwiddle = malloc(out->fftLen * sizeof(float32_t));
memcpy((void*)out->pBitRevTable,in->pBitRevTable,out->bitRevLength * sizeof(uint16_t));
memcpy((void*)out->pTwiddle,in->pTwiddle,out->fftLen * sizeof(float32_t));
}
return out;
}
static const arm_cfft_instance_f32* arm_fft_cache_get(const arm_cfft_instance_f32* romfft)
{
const arm_cfft_instance_f32* retval = NULL;
static int used = 0;
for (int i = 0; fft_init_cache[i] != NULL && i < used; i++)
{
if (romfft->fftLen == fft_init_cache[i]->fftLen)
{
retval = fft_init_cache[i];
break;
}
}
if (retval == NULL && used < FFT_INIT_CACHE_SIZE)
{
retval = arm_fft_instance2ram(romfft);
fft_init_cache[used++] = retval;
}
if (retval == NULL)
{
retval = romfft;
}
return retval;
}
#endif
#endif
void codec2_fft_free(codec2_fft_cfg cfg)
{
#ifdef USE_KISS_FFT
KISS_FFT_FREE(cfg);
#else
FREE(cfg);
#endif
}
codec2_fft_cfg codec2_fft_alloc(int nfft, int inverse_fft, void* mem, std::size_t* lenmem)
{
codec2_fft_cfg retval;
#ifdef USE_KISS_FFT
retval = kiss_fft_alloc(nfft, inverse_fft, mem, lenmem);
#else
retval = MALLOC(sizeof(codec2_fft_struct));
retval->inverse = inverse_fft;
switch(nfft)
{
case 128:
retval->instance = &arm_cfft_sR_f32_len128;
break;
case 256:
retval->instance = &arm_cfft_sR_f32_len256;
break;
case 512:
retval->instance = &arm_cfft_sR_f32_len512;
break;
// case 1024:
// retval->instance = &arm_cfft_sR_f32_len1024;
// break;
default:
abort();
}
// retval->instance = arm_fft_cache_get(retval->instance);
#endif
return retval;
}
codec2_fftr_cfg codec2_fftr_alloc(int nfft, int inverse_fft, void* mem, std::size_t* lenmem)
{
codec2_fftr_cfg retval;
#ifdef USE_KISS_FFT
retval = kiss_fftr_alloc(nfft, inverse_fft, mem, lenmem);
#else
retval = MALLOC(sizeof(codec2_fftr_struct));
retval->inverse = inverse_fft;
retval->instance = MALLOC(sizeof(arm_rfft_fast_instance_f32));
arm_rfft_fast_init_f32(retval->instance,nfft);
// memcpy(&retval->instance->Sint,arm_fft_cache_get(&retval->instance->Sint),sizeof(arm_cfft_instance_f32));
#endif
return retval;
}
void codec2_fftr_free(codec2_fftr_cfg cfg)
{
#ifdef USE_KISS_FFT
KISS_FFT_FREE(cfg);
#else
FREE(cfg->instance);
FREE(cfg);
#endif
}
// there is a little overhead for inplace kiss_fft but this is
// on the powerful platforms like the Raspberry or even x86 PC based ones
// not noticeable
// the reduced usage of RAM and increased performance on STM32 platforms
// should be worth it.
void codec2_fft_inplace(codec2_fft_cfg cfg, codec2_fft_cpx* inout)
{
#ifdef USE_KISS_FFT
kiss_fft_cpx in[512];
// decide whether to use the local stack based buffer for in
// or to allow kiss_fft to allocate RAM
// second part is just to play safe since first method
// is much faster and uses less RAM
if (cfg->nfft <= 512)
{
memcpy(in,inout,cfg->nfft*sizeof(kiss_fft_cpx));
kiss_fft(cfg, in, (kiss_fft_cpx*)inout);
}
else
{
kiss_fft(cfg, (kiss_fft_cpx*)inout, (kiss_fft_cpx*)inout);
}
#else
arm_cfft_f32(cfg->instance,(float*)inout,cfg->inverse,1);
if (cfg->inverse)
{
arm_scale_f32((float*)inout,cfg->instance->fftLen,(float*)inout,cfg->instance->fftLen*2);
}
#endif
}
} // FreeDV

View File

@ -1,108 +0,0 @@
/*
* 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>
#include <cstddef>
#include "codec2/comp.h"
#include "defines.h"
#include "kiss_fftr.h"
#ifdef FDV_ARM_MATH
#include "fdv_arm_math.h"
#else
#define USE_KISS_FFT
#endif
#ifdef USE_KISS_FFT
#include "kiss_fft.h"
#endif
namespace FreeDV
{
typedef COMP codec2_fft_cpx;
#ifdef USE_KISS_FFT
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, std::size_t* lenmem);
codec2_fftr_cfg codec2_fftr_alloc(int nfft, int inverse_fft, void* mem, std::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

View File

@ -1,101 +0,0 @@
/*---------------------------------------------------------------------------*\
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

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +0,0 @@
/* Generated by write_pilot_file() Octave function */
#define NSYMROW 4 /* number of data symbols per carrier (number of rows) */
#define NS 4 /* number of data symbols between pilots */
#define NPILOTSFRAME 2 /* number of pilot symbols per carrier */
#define PILOTS_NC 7 /* number of carriers */
#define NSYMROWPILOT 6 /* number of rows after pilots inserted */

View File

@ -1,131 +0,0 @@
/*---------------------------------------------------------------------------*\
FILE........: cohpsk_internal.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 __COHPSK_INTERNAL__
#define __COHPSK_INTERNAL__
#define NCT_SYMB_BUF (2*NSYMROWPILOT+2)
#define ND 2 /* diversity factor ND 1 is no diveristy, ND we have orginal plus
one copy */
#define NSW 4 /* number of sync window frames */
#define COHPSK_ND 2 /* diversity factor */
#define COHPSK_M 100 /* oversampling rate */
#define COHPSK_NSYM 6
#define COHPSK_NFILTER (COHPSK_NSYM*COHPSK_M)
#define COHPSK_EXCESS_BW 0.5 /* excess BW factor of root nyq filter */
#define COHPSK_NT 5 /* number of symbols we estimate timing over */
#include "fdmdv_internal.h"
#include "kiss_fft.h"
namespace FreeDV
{
struct COHPSK {
COMP ch_fdm_frame_buf[NSW*NSYMROWPILOT*COHPSK_M]; /* buffer of several frames of symbols from channel */
float pilot2[2*NPILOTSFRAME][COHPSK_NC];
float phi_[NSYMROWPILOT][COHPSK_NC*ND]; /* phase estimates for this frame of rx data symbols */
float amp_[NSYMROW][COHPSK_NC*ND]; /* amplitude estimates for this frame of rx data symbols */
COMP rx_symb[NSYMROWPILOT][COHPSK_NC*ND]; /* demodulated symbols */
float f_est;
COMP rx_filter_memory[COHPSK_NC*ND][COHPSK_NFILTER];
COMP ct_symb_buf[NCT_SYMB_BUF][COHPSK_NC*ND];
int ct; /* coarse timing offset in symbols */
float rx_timing; /* fine timing for last symbol in frame */
int nin; /* number of samples to input for next symbol */
float f_fine_est;
COMP ff_rect;
COMP ff_phase;
COMP ct_symb_ff_buf[NSYMROWPILOT+2][COHPSK_NC*ND];
int sync;
int sync_timer;
int frame;
float ratio;
float sig_rms;
float noise_rms;
struct FDMDV *fdmdv;
int verbose;
int *ptest_bits_coh_tx;
int *ptest_bits_coh_rx[2];
int *ptest_bits_coh_end;
/* counting bit errors using pilots */
int npilotbits;
int npilotbiterrors;
/* optional log variables used for testing Octave to C port */
COMP *rx_baseband_log;
int rx_baseband_log_col_index;
int rx_baseband_log_col_sz;
COMP *rx_filt_log;
int rx_filt_log_col_index;
int rx_filt_log_col_sz;
COMP *ch_symb_log;
int ch_symb_log_r;
int ch_symb_log_col_sz;
float *rx_timing_log;
int rx_timing_log_index;
/* demodulated bits before diversity combination for test/instrumentation purposes */
float rx_bits_lower[COHPSK_BITS_PER_FRAME];
float rx_bits_upper[COHPSK_BITS_PER_FRAME];
/* tx amplitude weights for each carrier for test/instrumentation */
float carrier_ampl[COHPSK_NC*ND];
/* Flag enabling simple freq est mode */
int freq_est_mode_reduced;
};
void bits_to_qpsk_symbols(COMP tx_symb[][COHPSK_NC*COHPSK_ND], int tx_bits[], int nbits);
void qpsk_symbols_to_bits(struct COHPSK *coh, float rx_bits[], COMP ct_symb_buf[][COHPSK_NC*COHPSK_ND]);
void tx_filter_and_upconvert_coh(COMP tx_fdm[], int Nc, const COMP tx_symbols[],
COMP tx_filter_memory[COHPSK_NC][COHPSK_NSYM],
COMP phase_tx[], COMP freq[],
COMP *fbb_phase, COMP fbb_rect);
void fdm_downconvert_coh(COMP rx_baseband[COHPSK_NC][COHPSK_M+COHPSK_M/P], int Nc, COMP rx_fdm[], COMP phase_rx[], COMP freq[], int nin);
void rx_filter_coh(COMP rx_filt[COHPSK_NC+1][P+1], int Nc, COMP rx_baseband[COHPSK_NC+1][COHPSK_M+COHPSK_M/P], COMP rx_filter_memory[COHPSK_NC+1][COHPSK_NFILTER], int nin);
void frame_sync_fine_freq_est(struct COHPSK *coh, COMP ch_symb[][COHPSK_NC*COHPSK_ND], int sync, int *next_sync);
void fine_freq_correct(struct COHPSK *coh, int sync, int next_sync);
int sync_state_machine(struct COHPSK *coh, int sync, int next_sync);
int cohpsk_fs_offset(COMP out[], COMP in[], int n, float sample_rate_ppm);
} // FreeDV
#endif

View File

@ -1,149 +0,0 @@
/*---------------------------------------------------------------------------*\
FILE........: comp_prim.h
AUTHOR......: David Rowe
DATE CREATED: Marh 2015
Complex number maths primitives.
\*---------------------------------------------------------------------------*/
/*
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 __COMP_PRIM__
#define __COMP_PRIM__
#include <math.h>
#include "codec2/comp.h"
namespace FreeDV
{
/*---------------------------------------------------------------------------*\
FUNCTIONS
\*---------------------------------------------------------------------------*/
inline static COMP cneg(COMP a)
{
COMP res;
res.real = -a.real;
res.imag = -a.imag;
return res;
}
inline static COMP cconj(COMP a)
{
COMP res;
res.real = a.real;
res.imag = -a.imag;
return res;
}
inline static COMP cmult(COMP a, COMP b)
{
COMP res;
res.real = a.real*b.real - a.imag*b.imag;
res.imag = a.real*b.imag + a.imag*b.real;
return res;
}
inline static COMP fcmult(float a, COMP b)
{
COMP res;
res.real = a*b.real;
res.imag = a*b.imag;
return res;
}
inline static COMP cadd(COMP a, COMP b)
{
COMP res;
res.real = a.real + b.real;
res.imag = a.imag + b.imag;
return res;
}
inline static float cabsolute(COMP a)
{
return sqrt(pow(a.real, 2.0) + pow(a.imag, 2.0));
}
/*
* Euler's formula in a new convenient function
*/
inline static COMP comp_exp_j(float phi){
COMP res;
res.real = cosf(phi);
res.imag = sinf(phi);
return res;
}
/*
* Quick and easy complex 0
*/
inline static COMP comp0(){
COMP res;
res.real = 0;
res.imag = 0;
return res;
}
/*
* Quick and easy complex subtract
*/
inline static COMP csub(COMP a, COMP b){
COMP res;
res.real = a.real-b.real;
res.imag = a.imag-b.imag;
return res;
}
/*
* Compare the magnitude of a and b. if |a|>|b|, return true, otw false.
* This needs no square roots
*/
inline static int comp_mag_gt(COMP a,COMP b){
return ((a.real*a.real)+(a.imag*a.imag)) > ((b.real*b.real)+(b.imag*b.imag));
}
/*
* Normalize a complex number's magnitude to 1
*/
inline static COMP comp_normalize(COMP a){
COMP b;
float av = cabsolute(a);
b.real = a.real/av;
b.imag = a.imag/av;
return b;
}
} // FreeDV
#endif

View File

@ -1,120 +0,0 @@
/*---------------------------------------------------------------------------*\
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

File diff suppressed because it is too large Load Diff

View File

@ -1,200 +0,0 @@
/*---------------------------------------------------------------------------*\
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

View File

@ -1,41 +0,0 @@
/*---------------------------------------------------------------------------*\
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

View File

@ -1,373 +0,0 @@
/*---------------------------------------------------------------------------*\
FILE........: fmfsk.c
AUTHOR......: Brady O'Brien
DATE CREATED: 6 February 2016
C Implementation of a FM+ME+FSK modem for FreeDV mode B and other applications
(better APRS, anyone?)
\*---------------------------------------------------------------------------*/
/*
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/>.
*/
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include "fmfsk.h"
#include "modem_probe.h"
#include "comp_prim.h"
#define STD_PROC_BITS 96
namespace FreeDV
{
/*
* 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){
assert( Fs % (Rb*2) == 0 ); /* Sample freq must be divisible by symbol rate */
int nbits = STD_PROC_BITS;
/* Allocate the struct */
struct FMFSK *fmfsk = (struct FMFSK *) malloc(sizeof(struct FMFSK));
if(fmfsk==NULL) return NULL;
/* Set up static parameters */
fmfsk->Rb = Rb;
fmfsk->Rs = Rb*2;
fmfsk->Fs = Fs;
fmfsk->Ts = Fs/fmfsk->Rs;
fmfsk->N = nbits*2*fmfsk->Ts;
fmfsk->nmem = fmfsk->N+(fmfsk->Ts*4);
fmfsk->nsym = nbits*2;
fmfsk->nbit = nbits;
/* Set up demod state */
fmfsk->lodd = 0;
fmfsk->nin = fmfsk->N;
fmfsk->snr_mean = 0;
float *oldsamps = (float*) malloc(sizeof(float)*fmfsk->nmem);
if(oldsamps == NULL){
free(fmfsk);
return NULL;
}
fmfsk->oldsamps = oldsamps;
fmfsk->stats = (struct MODEM_STATS*)malloc(sizeof(struct MODEM_STATS));
if (fmfsk->stats == NULL) {
free(oldsamps);
free(fmfsk);
return NULL;
}
return fmfsk;
}
/*
* Destroys an fmfsk modem and deallocates memory
*/
void fmfsk_destroy(struct FMFSK *fmfsk){
free(fmfsk->oldsamps);
free(fmfsk);
}
/*
* Returns the number of samples that must be fed to fmfsk_demod the next
* cycle
*/
uint32_t fmfsk_nin(struct FMFSK *fmfsk){
return (uint32_t)fmfsk->nin;
}
void fmfsk_get_demod_stats(struct FMFSK *fmfsk,struct MODEM_STATS *stats){
/* copy from internal stats, note we can't overwrite stats completely
as it has other states rqd by caller, also we want a consistent
interface across modem types for the freedv_api.
*/
stats->clock_offset = fmfsk->stats->clock_offset;
stats->snr_est = fmfsk->stats->snr_est; // TODO: make this SNR not Eb/No
stats->rx_timing = fmfsk->stats->rx_timing;
stats->foff = fmfsk->stats->foff;
stats->neyesamp = fmfsk->stats->neyesamp;
stats->neyetr = fmfsk->stats->neyetr;
memcpy(stats->rx_eye, fmfsk->stats->rx_eye, sizeof(stats->rx_eye));
/* these fields not used for FSK so set to something sensible */
stats->sync = 0;
stats->nr = fmfsk->stats->nr;
stats->Nc = fmfsk->stats->Nc;
}
/*
* 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[]){
int i,j;
int nbit = fmfsk->nbit;
int Ts = fmfsk->Ts;
for(i=0; i<nbit; i++){
/* Save a manchester-encoded 0 */
if(bits_in[i] == 0){
for(j=0; j<Ts; j++)
fmfsk_out[ j+i*Ts*2] = -1;
for(j=0; j<Ts; j++)
fmfsk_out[Ts+j+i*Ts*2] = 1;
} else {
/* Save a manchester-encoded 1 */
for(j=0; j<Ts; j++)
fmfsk_out[ j+i*Ts*2] = 1;
for(j=0; j<Ts; j++)
fmfsk_out[Ts+j+i*Ts*2] = -1;
}
}
}
/*
* 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[]){
int i,j,k;
int Ts = fmfsk->Ts;
int Fs = fmfsk->Fs;
int Rs = fmfsk->Rs;
int nin = fmfsk->nin;
int N = fmfsk->N;
int nsym = fmfsk->nsym;
int nbit = fmfsk->nbit;
int nmem = fmfsk->nmem;
float *oldsamps = fmfsk->oldsamps;
int nold = nmem-nin;
COMP phi_ft,dphi_ft; /* Phase and delta-phase for fine timing estimator */
float t;
COMP x; /* Magic fine timing angle */
float norm_rx_timing,old_norm_rx_timing,d_norm_rx_timing,appm;
int rx_timing,sample_offset;
int next_nin;
float apeven,apodd; /* Approx. prob of even or odd stream being correct */
float currv,mdiff,lastv;
int neyesamp;
int neyeoffset;
float eye_max;
uint8_t mbit;
float var_signal = 0, var_noise = 0, lastFabsV;
/* Shift in nin samples */
memmove(&oldsamps[0] , &oldsamps[nmem-nold], sizeof(float)*nold);
memcpy (&oldsamps[nold], &fmfsk_in[0] , sizeof(float)*nin );
/* Allocate memory for filtering */
float *rx_filt = (float*) malloc(sizeof(float)*(nsym+1)*Ts);
/* Integrate over Ts input symbols at every offset */
for(i=0; i<(nsym+1)*Ts; i++){
t=0;
/* Integrate over some samples */
for(j=i;j<i+Ts;j++){
t += oldsamps[j];
}
rx_filt[i] = t;
}
/*
* Fine timing estimation
*
* Estimate fine timing using line at Rs/2 that Manchester encoding provides
* We need this to sync up to Manchester codewords.
*/
/* init fine timing extractor */
phi_ft.real = 1;
phi_ft.imag = 0;
/* Set up delta-phase */
dphi_ft.real = cosf(2*M_PI*((float)Rs)/((float)Fs));
dphi_ft.imag = sinf(2*M_PI*((float)Rs)/((float)Fs));
x.real = 0;
x.imag = 0;
for(i=0; i<(nsym+1)*Ts; i++){
/* Apply non-linearity */
t = rx_filt[i]*rx_filt[i];
/* Shift Rs/2 down to DC and accumulate */
x = cadd(x,fcmult(t,phi_ft));
/* Spin downshift oscillator */
phi_ft = cmult(dphi_ft,phi_ft);
modem_probe_samp_c("t_phi_ft",&phi_ft,1);
}
/* Figure out the normalized RX timing, using David's magic number */
norm_rx_timing = atan2f(x.imag,x.real)/(2*M_PI) - .42;
rx_timing = (int)lroundf(norm_rx_timing*(float)Ts);
old_norm_rx_timing = fmfsk->norm_rx_timing;
fmfsk->norm_rx_timing = norm_rx_timing;
/* Estimate sample clock offset */
d_norm_rx_timing = norm_rx_timing - old_norm_rx_timing;
/* Filter out big jumps in due to nin change */
if(fabsf(d_norm_rx_timing) < .2){
appm = 1e6*d_norm_rx_timing/(float)nsym;
fmfsk->ppm = .9*fmfsk->ppm + .1*appm;
}
/* Figure out how far offset the sample points are */
sample_offset = (Ts/2)+Ts+rx_timing-1;
/* Request fewer or greater samples next time, if fine timing is far
* enough off. This also makes it possible to tolerate clock offsets */
next_nin = N;
if(norm_rx_timing > -.2)
next_nin += Ts/2;
if(norm_rx_timing < -.65)
next_nin -= Ts/2;
fmfsk->nin = next_nin;
/* Make first diff of this round the last sample of the last round,
* for the odd stream */
lastv = fmfsk->lodd;
lastFabsV = fabs(lastv);
apeven = 0;
apodd = 0;
for(i=0; i<nsym; i++){
/* Sample a filtered value */
currv = rx_filt[sample_offset+(i*Ts)];
modem_probe_samp_f("t_symsamp",&currv,1);
mdiff = lastv - currv;
mbit = mdiff>0 ? 1 : 0;
lastv = currv;
// Calculate the signal variance. Note that the mean is zero
var_signal += currv * currv;
/* Calculate the variance of the noise between samples (symbols). A quick variance estimate
* without calculating mean can be done by differentiating (remove mean) and then
* dividing by 2. Fabs the samples as we are looking at how close the samples are to each
* other as if they were all the same polarity/symbol. */
currv = fabs(currv);
var_noise += (currv - lastFabsV) * (currv - lastFabsV);
lastFabsV = currv;
mdiff = mdiff>0 ? mdiff : 0-mdiff;
/* Put bit in it's stream */
if((i%2)==1){
apeven += mdiff;
/* Even stream goes in LSB */
rx_bits[i>>1] |= mbit ? 0x1 : 0x0;
}else{
apodd += mdiff;
/* Odd in second-to-LSB */
rx_bits[i>>1] = mbit ? 0x2 : 0x0;
}
}
/* Div by 2 to correct variance when doing via differentiation.*/
var_noise *= 0.5;
if(apeven>apodd){
/* Zero out odd bits from output bitstream */
for(i=0;i<nbit;i++)
rx_bits[i] &= 0x1;
}else{
/* Shift odd bits into LSB and even bits out of existence */
for(i=0;i<nbit;i++)
rx_bits[i] = (rx_bits[i]&0x2)>>1;
}
/* Save last sample of int stream for next demod round */
fmfsk->lodd = lastv;
/* Save demod statistics */
fmfsk->stats->Nc = 0;
fmfsk->stats->nr = 0;
/* Clock offset and RX timing are all we know here */
fmfsk->stats->clock_offset = fmfsk->ppm;
fmfsk->stats->rx_timing = (float)rx_timing;
/* Zero out all of the other things */
fmfsk->stats->foff = 0;
/* Use moving average to smooth SNR display */
if(fmfsk->snr_mean < 0.1)
fmfsk->snr_mean = (10.0 * log10f(var_signal / var_noise));
else
fmfsk->snr_mean = 0.9 * fmfsk->snr_mean + 0.1 * (10.0 * log10f(var_signal / var_noise));
fmfsk->stats->snr_est = fmfsk->snr_mean;
/* Collect an eye diagram */
/* Take a sample for the eye diagrams */
neyesamp = fmfsk->stats->neyesamp = Ts*4;
neyeoffset = sample_offset+(Ts*2*28);
fmfsk->stats->neyetr = 8;
for(k=0; k<fmfsk->stats->neyetr; k++)
for(j=0; j<neyesamp; j++)
fmfsk->stats->rx_eye[k][j] = rx_filt[k*neyesamp+neyeoffset+j];
//fmfsk->stats->rx_eye[k][j] = fmfsk_in[k*neyesamp+neyeoffset+j];
eye_max = 0;
/* Normalize eye to +/- 1 */
for(i=0; i<fmfsk->stats->neyetr; i++)
for(j=0; j<neyesamp; j++)
if(fabsf(fmfsk->stats->rx_eye[i][j])>eye_max)
eye_max = fabsf(fmfsk->stats->rx_eye[i][j]);
for(i=0; i<fmfsk->stats->neyetr; i++)
for(j=0; j<neyesamp; j++)
fmfsk->stats->rx_eye[i][j] = (fmfsk->stats->rx_eye[i][j]/(2*eye_max))+.5;
modem_probe_samp_f("t_norm_rx_timing",&norm_rx_timing,1);
modem_probe_samp_f("t_rx_filt",rx_filt,(nsym+1)*Ts);
free(rx_filt);
}
} // FreeDV

View File

@ -1,116 +0,0 @@
/*---------------------------------------------------------------------------*\
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

File diff suppressed because it is too large Load Diff

View File

@ -1,154 +0,0 @@
/*---------------------------------------------------------------------------*\
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

@ -1,353 +0,0 @@
/*---------------------------------------------------------------------------*\
FILE........: freedv_data_channel.c
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/>.
*/
#include "freedv_data_channel.h"
#include <stdlib.h>
#include <string.h>
#include <cstddef>
namespace FreeDV
{
static unsigned char fdc_header_bcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
/* CCIT CRC table (0x1201 polynomal) */
static unsigned short fdc_crc_table[256] = {
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
};
static unsigned short fdc_crc(unsigned char *buffer, std::size_t len)
{
unsigned short crc = 0xffff;
std::size_t i;
for (i = 0; i < len; i++, buffer++) {
crc = (crc >> 8) ^ fdc_crc_table[(crc ^ *buffer) & 0xff];
}
return crc ^ 0xffff;
}
/* CRC4 0x03 polynomal */
static unsigned char fdc_crc4(unsigned char *buffer, std::size_t len)
{
unsigned char crc = 0x0f;
std::size_t i;
for (i = 0; i < len; i++, buffer++)
{
int shift;
for (shift = 7; shift >= 0; shift--)
{
crc <<= 1;
if ((*buffer >> shift) & 0x1) {
crc |= 1;
}
if (crc & 0x10) {
crc ^= 0x03;
}
}
}
return crc & 0x0f;
}
struct freedv_data_channel *freedv_data_channel_create(void)
{
struct freedv_data_channel *fdc;
fdc = (freedv_data_channel*) malloc(sizeof(struct freedv_data_channel));
if (!fdc)
return nullptr;
fdc->cb_rx = nullptr;
fdc->cb_tx = nullptr;
fdc->packet_tx_size = 0;
freedv_data_set_header(fdc, fdc_header_bcast);
memcpy(fdc->rx_header, fdc->tx_header, 8);
return fdc;
}
void freedv_data_channel_destroy(struct freedv_data_channel *fdc)
{
free(fdc);
}
void freedv_data_set_cb_rx(struct freedv_data_channel *fdc, freedv_data_callback_rx cb, void *state)
{
fdc->cb_rx = cb;
fdc->cb_rx_state = state;
}
void freedv_data_set_cb_tx(struct freedv_data_channel *fdc, freedv_data_callback_tx cb, void *state)
{
fdc->cb_tx = cb;
fdc->cb_tx_state = state;
}
void freedv_data_channel_rx_frame(struct freedv_data_channel *fdc, unsigned char *data, std::size_t size, int from_bit, int bcast_bit, int crc_bit, int end_bits)
{
int copy_bits;
if (end_bits) {
copy_bits = end_bits;
} else {
copy_bits = size;
}
/* New packet? */
if (fdc->packet_rx_cnt == 0)
{
/* Does the packet have a compressed from field? */
if (from_bit) {
/* Compressed from: take the previously received header */
memcpy(fdc->packet_rx + fdc->packet_rx_cnt, fdc->rx_header, 6);
fdc->packet_rx_cnt += 6;
}
if (bcast_bit)
{
if (!from_bit)
{
/* Copy from header and modify size and end_bits accordingly */
memcpy(fdc->packet_rx + fdc->packet_rx_cnt, data, 6);
fdc->packet_rx_cnt += 6;
copy_bits -= 6;
if (copy_bits < 0) {
copy_bits = 0;
}
data += 6;
}
/* Compressed to: fill in broadcast address */
memcpy(fdc->packet_rx + fdc->packet_rx_cnt, fdc_header_bcast, sizeof(fdc_header_bcast));
fdc->packet_rx_cnt += 6;
}
if (crc_bit)
{
unsigned char calc_crc = fdc_crc4(data, size);
if (calc_crc == end_bits)
{
/* It is a single header field, remember it for later */
memcpy(fdc->packet_rx + 6, data, 6);
memcpy(fdc->packet_rx, fdc_header_bcast, 6);
if (fdc->cb_rx) {
fdc->cb_rx(fdc->cb_rx_state, fdc->packet_rx, 12);
}
}
fdc->packet_rx_cnt = 0;
return;
}
}
if (fdc->packet_rx_cnt + copy_bits >= FREEDV_DATA_CHANNEL_PACKET_MAX)
{
// Something went wrong... this can not be a real packet
fdc->packet_rx_cnt = 0;
return;
}
else if (fdc->packet_rx_cnt < 0)
{
// This is wrong too...
fdc->packet_rx_cnt = 0;
return;
}
memcpy(fdc->packet_rx + fdc->packet_rx_cnt, data, copy_bits);
fdc->packet_rx_cnt += copy_bits;
if (end_bits != 0 && fdc->packet_rx_cnt >= 2)
{
unsigned short calc_crc = fdc_crc(fdc->packet_rx, fdc->packet_rx_cnt - 2);
unsigned short rx_crc;
rx_crc = fdc->packet_rx[fdc->packet_rx_cnt - 1] << 8;
rx_crc |= fdc->packet_rx[fdc->packet_rx_cnt - 2];
if (rx_crc == calc_crc)
{
if ((std::size_t) fdc->packet_rx_cnt == size) {
/* It is a single header field, remember it for later */
memcpy(fdc->rx_header, fdc->packet_rx, 6);
}
/* callback */
if (fdc->cb_rx)
{
unsigned char tmp[6];
memcpy(tmp, fdc->packet_rx, 6);
memcpy(fdc->packet_rx, fdc->packet_rx + 6, 6);
memcpy(fdc->packet_rx + 6, tmp, 6);
std::size_t size = fdc->packet_rx_cnt - 2;
if (size < 12) {
size = 12;
}
fdc->cb_rx(fdc->cb_rx_state, fdc->packet_rx, size);
}
}
fdc->packet_rx_cnt = 0;
}
}
void freedv_data_channel_tx_frame(struct freedv_data_channel *fdc, unsigned char *data, std::size_t size, int *from_bit, int *bcast_bit, int *crc_bit, int *end_bits)
{
*from_bit = 0;
*bcast_bit = 0;
*crc_bit = 0;
if (!fdc->packet_tx_size) {
fdc->packet_tx_cnt = 0;
if (fdc->cb_tx) {
fdc->packet_tx_size = FREEDV_DATA_CHANNEL_PACKET_MAX;
fdc->cb_tx(fdc->cb_tx_state, fdc->packet_tx, &fdc->packet_tx_size);
}
if (!fdc->packet_tx_size) {
/* Nothing to send, insert a header frame */
memcpy(fdc->packet_tx, fdc->tx_header, size);
if (size < 8) {
*end_bits = fdc_crc4(fdc->tx_header, size);
*crc_bit = 1;
memcpy(data, fdc->tx_header, size);
return;
} else {
fdc->packet_tx_size = size;
}
} else {
/* new packet */
unsigned short crc;
unsigned char tmp[6];
*from_bit = !memcmp(fdc->packet_tx + 6, fdc->tx_header, 6);
*bcast_bit = !memcmp(fdc->packet_tx, fdc_header_bcast, 6);
memcpy(tmp, fdc->packet_tx, 6);
memcpy(fdc->packet_tx, fdc->packet_tx + 6, 6);
memcpy(fdc->packet_tx + 6, tmp, 6);
crc = fdc_crc(fdc->packet_tx, fdc->packet_tx_size);
fdc->packet_tx[fdc->packet_tx_size] = crc & 0xff;
fdc->packet_tx_size++;
fdc->packet_tx[fdc->packet_tx_size] = (crc >> 8) & 0xff;
fdc->packet_tx_size++;
if (*from_bit) {
fdc->packet_tx_cnt = 6;
} else {
if (*bcast_bit) {
memcpy(fdc->packet_tx + 6, fdc->packet_tx, 6);
}
}
if (*bcast_bit) {
fdc->packet_tx_cnt += 6;
}
}
}
if (fdc->packet_tx_size) {
std::size_t copy = fdc->packet_tx_size - fdc->packet_tx_cnt;
if (copy > size) {
copy = size;
*end_bits = 0;
} else {
*end_bits = copy;
fdc->packet_tx_size = 0;
}
memcpy(data, fdc->packet_tx + fdc->packet_tx_cnt, copy);
fdc->packet_tx_cnt += copy;
}
}
void freedv_data_set_header(struct freedv_data_channel *fdc, unsigned char *header)
{
unsigned short crc = fdc_crc(header, 6);
memcpy(fdc->tx_header, header, 6);
fdc->tx_header[6] = crc & 0xff;
fdc->tx_header[7] = (crc >> 8) & 0xff;
}
int freedv_data_get_n_tx_frames(struct freedv_data_channel *fdc, std::size_t size)
{
if (fdc->packet_tx_size == 0)
return 0;
/* packet will be send in 'size' byte frames */
return (fdc->packet_tx_size - fdc->packet_tx_cnt + size-1) / size;
}
} // FreeDV

View File

@ -1,75 +0,0 @@
/*---------------------------------------------------------------------------*\
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 */

View File

@ -1,293 +0,0 @@
/*
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/>.
*/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <complex.h>
#include <algorithm>
#include "freedv_filter.h"
#include "freedv_filter_coef.h"
#include "fdv_arm_math.h"
#define cmplx(value) (COSF(value) + SINF(value) * std::complex<float>(0.0f, 1.0f))
namespace FreeDV
{
/*
* This is a library of filter functions. They were copied from Quisk and converted to single precision.
*/
/*---------------------------------------------------------------------------*\
FUNCTIONS...: quisk_filt_cfInit
AUTHOR......: Jim Ahlstrom
DATE CREATED: 27 August 2015
MODIFIED: 4 June 2018
Initialize a FIR filter that has complex samples, and either real or complex coefficients.
\*---------------------------------------------------------------------------*/
void quisk_filt_cfInit(struct quisk_cfFilter * filter, float * coefs, int taps)
{
// Prepare a new filter using coefs and taps. Samples are complex. Coefficients can
// be real or complex.
filter->dCoefs = coefs;
filter->cpxCoefs = nullptr;
filter->cSamples = new std::complex<float>[taps];
std::fill(filter->cSamples, filter->cSamples + taps, std::complex<float>{0.0, 0.0});
filter->ptcSamp = filter->cSamples;
filter->nTaps = taps;
filter->cBuf = nullptr;
filter->nBuf = 0;
filter->decim_index = 0;
}
/*---------------------------------------------------------------------------*\
FUNCTIONS...: quisk_filt_destroy
AUTHOR......: Jim Ahlstrom
DATE CREATED: 27 August 2015
MODIFIED: 4 June 2018
Destroy the FIR filter and free all resources.
\*---------------------------------------------------------------------------*/
void quisk_filt_destroy(struct quisk_cfFilter * filter)
{
if (filter->cSamples)
{
delete[] filter->cSamples;
filter->cSamples = nullptr;
}
if (filter->cBuf)
{
delete[] filter->cBuf;
filter->cBuf = nullptr;
}
if (filter->cpxCoefs)
{
delete[] filter->cpxCoefs;
filter->cpxCoefs = nullptr;
}
}
/*---------------------------------------------------------------------------*\
FUNCTIONS...: quisk_cfInterpDecim
AUTHOR......: Jim Ahlstrom
DATE CREATED: 27 August 2015
MODIFIED: 4 June 2018
Take an array of samples cSamples of length count, multiply the sample rate
by interp, and then divide the sample rate by decim. Return the new number
of samples. Each specific interp and decim will require its own custom
low pass FIR filter with real coefficients.
\*---------------------------------------------------------------------------*/
int quisk_cfInterpDecim(std::complex<float> * cSamples, int count, struct quisk_cfFilter * filter, int interp, int decim) {
// Interpolate by interp, and then decimate by decim.
// This uses the float coefficients of filter (not the complex). Samples are complex.
int i, k, nOut;
float * ptCoef;
std::complex<float> *ptSample;
std::complex<float> csample;
if (count > filter->nBuf) { // increase size of sample buffer
filter->nBuf = count * 2;
if (filter->cBuf)
free(filter->cBuf);
filter->cBuf = new std::complex<float>[filter->nBuf];
}
memcpy(filter->cBuf, cSamples, count * sizeof(std::complex<float>));
nOut = 0;
for (i = 0; i < count; i++) {
// Put samples into buffer left to right. Use samples right to left.
*filter->ptcSamp = filter->cBuf[i];
while (filter->decim_index < interp) {
ptSample = filter->ptcSamp;
ptCoef = filter->dCoefs + filter->decim_index;
csample = 0;
for (k = 0; k < filter->nTaps / interp; k++, ptCoef += interp) {
csample += *ptSample * *ptCoef;
if (--ptSample < filter->cSamples)
ptSample = filter->cSamples + filter->nTaps - 1;
}
cSamples[nOut] = csample * (float) interp;
nOut++;
filter->decim_index += decim;
}
if (++filter->ptcSamp >= filter->cSamples + filter->nTaps)
filter->ptcSamp = filter->cSamples;
filter->decim_index = filter->decim_index - interp;
}
return nOut;
}
/*---------------------------------------------------------------------------*\
FUNCTIONS...: quisk_ccfInterpDecim
AUTHOR......: Jim Ahlstrom
DATE CREATED: 7 June 2018
Take an array of samples cSamples of length count, multiply the sample rate
by interp, and then divide the sample rate by decim. Return the new number
of samples. Each specific interp and decim will require its own custom
low pass FIR filter with complex coefficients. This filter can be tuned.
This filter is not currently used.
\*---------------------------------------------------------------------------*/
#if 0
int quisk_ccfInterpDecim(complex float * cSamples, int count, struct quisk_cfFilter * filter, int interp, int decim) {
// Interpolate by interp, and then decimate by decim.
// This uses the complex coefficients of filter (not the real). Samples are complex.
int i, k, nOut;
complex float * ptCoef;
complex float * ptSample;
complex float csample;
if (count > filter->nBuf) { // increase size of sample buffer
filter->nBuf = count * 2;
if (filter->cBuf)
FREE(filter->cBuf);
filter->cBuf = (complex float *)MALLOC(filter->nBuf * sizeof(complex float));
}
memcpy(filter->cBuf, cSamples, count * sizeof(complex float));
nOut = 0;
for (i = 0; i < count; i++) {
// Put samples into buffer left to right. Use samples right to left.
*filter->ptcSamp = filter->cBuf[i];
while (filter->decim_index < interp) {
ptSample = filter->ptcSamp;
ptCoef = filter->cpxCoefs + filter->decim_index;
csample = 0;
for (k = 0; k < filter->nTaps / interp; k++, ptCoef += interp) {
csample += *ptSample * *ptCoef;
if (--ptSample < filter->cSamples)
ptSample = filter->cSamples + filter->nTaps - 1;
}
cSamples[nOut] = csample * interp;
nOut++;
filter->decim_index += decim;
}
if (++filter->ptcSamp >= filter->cSamples + filter->nTaps)
filter->ptcSamp = filter->cSamples;
filter->decim_index = filter->decim_index - interp;
}
return nOut;
}
#endif
/*---------------------------------------------------------------------------*\
FUNCTIONS...: quisk_cfTune
AUTHOR......: Jim Ahlstrom
DATE CREATED: 4 June 2018
Tune a low pass filter with float coefficients into an analytic I/Q bandpass filter
with complex coefficients. The "freq" is the center frequency / sample rate.
If the float coefs represent a low pass filter with bandwidth 1 kHz, the new bandpass
filter has width 2 kHz. The filter can be re-tuned repeatedly.
\*---------------------------------------------------------------------------*/
void quisk_cfTune(struct quisk_cfFilter * filter, float freq) {
float D, tune;
int i;
if ( ! filter->cpxCoefs) {
filter->cpxCoefs = new std::complex<float>[filter->nTaps];
}
tune = 2.0 * M_PI * freq;
D = (filter->nTaps - 1.0) / 2.0;
for (i = 0; i < filter->nTaps; i++) {
float tval = tune * (i - D);
filter->cpxCoefs[i] = cmplx(tval) * filter->dCoefs[i];
}
}
/*---------------------------------------------------------------------------*\
FUNCTIONS...: quisk_ccfFilter
AUTHOR......: Jim Ahlstrom
DATE CREATED: 4 June 2018
Filter complex samples using complex coefficients. The inSamples and outSamples may be
the same array. The loop runs forward over coefficients but backwards over samples.
Therefore, the coefficients must be reversed unless they are created by quisk_cfTune.
Low pass filter coefficients are symmetrical, so this does not usually matter.
\*---------------------------------------------------------------------------*/
void quisk_ccfFilter(std::complex<float> *inSamples, std::complex<float> *outSamples, int count, struct quisk_cfFilter * filter) {
int i, k;
std::complex<float> *ptSample;
std::complex<float> *ptCoef;
std::complex<float> accum;
for (i = 0; i < count; i++) {
*filter->ptcSamp = inSamples[i];
accum = 0;
ptSample = filter->ptcSamp;
ptCoef = filter->cpxCoefs;
for (k = 0; k < filter->nTaps; k++, ptCoef++) {
accum += *ptSample * *ptCoef;
if (--ptSample < filter->cSamples)
ptSample = filter->cSamples + filter->nTaps - 1;
}
outSamples[i] = accum;
if (++filter->ptcSamp >= filter->cSamples + filter->nTaps)
filter->ptcSamp = filter->cSamples;
}
}
} // freeDV

View File

@ -1,48 +0,0 @@
/*
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

@ -1,166 +0,0 @@
/*
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/>.
*/
/*
These are the coefficients for various FIR filters. A declaration of these filter coefficients is in filter.h.
Multiple filters can use these coefficients because they are read-only.
Although a sample rate is specified, the filters may be used at other sample rates. For example, if
filtP750S1040 is used at 48000 sps, the pass and stop frequencies are 4500 and 6240 hz.
*/
namespace FreeDV
{
// Low pass filter, sample rate 8000 hz, 0.2 dB ripple, 100 dB atten, pass 550 hz, stop 750 hz.
float filtP550S750[160]={
0.000001500540125945, 0.000020553368071006, 0.000052842049763802, 0.000112071233638701,
0.000202565299657164, 0.000325476960438197, 0.000474396686568771, 0.000633746562372497, 0.000778858561033731,
0.000878592697224500, 0.000900611877226272, 0.000818750000130019, 0.000621157718914443, 0.000317269738067462,
-0.000058614729046822, -0.000448959090901751, -0.000780751290682747, -0.000978953969922609, -0.000983534965413392,
-0.000766540799920385, -0.000344938705664714, 0.000214927788687815, 0.000804118320944653, 0.001289527679116282,
0.001541598437149897, 0.001466078039230554, 0.001032493743140772, 0.000291727467744814, -0.000623607913580581,
-0.001518948630011706, -0.002175907515711935, -0.002402252989524116, -0.002082876981631170, -0.001219318501019004,
0.000053915753894017, 0.001483599323867600, 0.002743518309691092, 0.003504691193108974, 0.003515993126242027,
0.002676486805582815, 0.001080325423865147, -0.000980649349095093, -0.003062866925046052, -0.004660487490214220,
-0.005321805637618908, -0.004767235761853469, -0.002979877569160189, -0.000242864453416682, 0.002892365745006815,
0.005707645107750651, 0.007473145256589892, 0.007624527169837005, 0.005921569713871673, 0.002547381438730890,
-0.001883079571618079, -0.006418195698900790, -0.009958090016198632, -0.011502199858687428, -0.010403943660694560,
-0.006572745274759415, -0.000569370325758693, 0.006440667006225166, 0.012881777376768124, 0.017083918451421990,
0.017661533458054445, 0.013877952730549446, 0.005912685575826365, -0.005037640104142052, -0.016864250576905999,
-0.026855876467499887, -0.032168177048912679, -0.030370760878632559, -0.019967289813872333, -0.000782327027950076,
0.025871098651626040, 0.057290144048617792, 0.089743290905422241, 0.119038289777397190, 0.141198609990722840,
0.153125933205703250, 0.153125933205703250, 0.141198609990722840, 0.119038289777397190, 0.089743290905422241,
0.057290144048617792, 0.025871098651626040, -0.000782327027950076, -0.019967289813872333, -0.030370760878632559,
-0.032168177048912679, -0.026855876467499887, -0.016864250576905999, -0.005037640104142052, 0.005912685575826365,
0.013877952730549446, 0.017661533458054445, 0.017083918451421990, 0.012881777376768124, 0.006440667006225166,
-0.000569370325758693, -0.006572745274759415, -0.010403943660694560, -0.011502199858687428, -0.009958090016198632,
-0.006418195698900790, -0.001883079571618079, 0.002547381438730890, 0.005921569713871673, 0.007624527169837005,
0.007473145256589892, 0.005707645107750651, 0.002892365745006815, -0.000242864453416682, -0.002979877569160189,
-0.004767235761853469, -0.005321805637618908, -0.004660487490214220, -0.003062866925046052, -0.000980649349095093,
0.001080325423865147, 0.002676486805582815, 0.003515993126242027, 0.003504691193108974, 0.002743518309691092,
0.001483599323867600, 0.000053915753894017, -0.001219318501019004, -0.002082876981631170, -0.002402252989524116,
-0.002175907515711935, -0.001518948630011706, -0.000623607913580581, 0.000291727467744814, 0.001032493743140772,
0.001466078039230554, 0.001541598437149897, 0.001289527679116282, 0.000804118320944653, 0.000214927788687815,
-0.000344938705664714, -0.000766540799920385, -0.000983534965413392, -0.000978953969922609, -0.000780751290682747,
-0.000448959090901751, -0.000058614729046822, 0.000317269738067462, 0.000621157718914443, 0.000818750000130019,
0.000900611877226272, 0.000878592697224500, 0.000778858561033731, 0.000633746562372497, 0.000474396686568771,
0.000325476960438197, 0.000202565299657164, 0.000112071233638701, 0.000052842049763802, 0.000020553368071006,
0.000001500540125945
};
// FIR filter suitable for changing rates 7500 to/from 8000
// Sample 120000 Hz, pass 2700, stop 3730, ripple 0.1dB, atten 100 dB. Stop 0.03108.
float quiskFilt120t480[480] = { -0.000005050567303837, -0.000000267011791999, 0.000000197734700398, 0.000001038946634000,
0.000002322193058869, 0.000004115682735322, 0.000006499942123311, 0.000009551098482930, 0.000013350669444763,
0.000017966192635412, 0.000023463361155584, 0.000029885221425020, 0.000037271082107518, 0.000045630720487935,
0.000054970017069384, 0.000065233162392019, 0.000076360900545177, 0.000088271373315159, 0.000100818605854714,
0.000113853476544409, 0.000127174196746337, 0.000140558396336177, 0.000153744508371709, 0.000166450784469067,
0.000178368313347299, 0.000189176709991702, 0.000198541881389953, 0.000206128795372885, 0.000211604878787747,
0.000214655997661182, 0.000214994859281552, 0.000212358734245594, 0.000206539880117977, 0.000197379393194548,
0.000184780318878738, 0.000168719942655099, 0.000149250512353807, 0.000126511346757621, 0.000100726393185629,
0.000072210925236429, 0.000041365841965015, 0.000008680571408025, -0.000025277165852799, -0.000059865389594949,
-0.000094384355854646, -0.000128080670195777, -0.000160170174848483, -0.000189854272533545, -0.000216333899003825,
-0.000238836419299503, -0.000256632149501508, -0.000269058714331757, -0.000275541485292432, -0.000275614059005332,
-0.000268937472718753, -0.000255317038867589, -0.000234717772155001, -0.000207273956099563, -0.000173297342436372,
-0.000133280012107173, -0.000087895370243821, -0.000037986085678081, 0.000015440388211825, 0.000071232572821451,
0.000128114399130489, 0.000184710477990398, 0.000239577162514028, 0.000291234779803098, 0.000338204791740229,
0.000379047713684221, 0.000412403761615261, 0.000437031818051652, 0.000451848709179591, 0.000455966225408344,
0.000448726371643413, 0.000429729020814434, 0.000398857326863837, 0.000356297600912998, 0.000302547334727027,
0.000238422248479072, 0.000165048886226905, 0.000083853091464077, -0.000003462782744354, -0.000094949813106744,
-0.000188451833293202, -0.000281651282503015, -0.000372121907291206, -0.000457387566635848, -0.000534985542936898,
-0.000602532044011899, -0.000657788245032425, -0.000698728981427767, -0.000723604675185869, -0.000731002305621048,
-0.000719899536922384, -0.000689709694056092, -0.000640319946685634, -0.000572115873292030, -0.000485996080304965,
-0.000383371840261246, -0.000266155252511831, -0.000136731311264191, 0.000002082667095075, 0.000147092077716480,
0.000294790953130229, 0.000441441918072383, 0.000583164190168290, 0.000716029226064227, 0.000836164238172957,
0.000939856052624227, 0.001023657909064450, 0.001084492755093968, 0.001119751426837743, 0.001127383039339373,
0.001105974243787613, 0.001054815583369999, 0.000973950761085690, 0.000864209315714227, 0.000727219011746881,
0.000565398080608305, 0.000381924396468366, 0.000180685902835315, -0.000033793183292569, -0.000256444114966522,
-0.000481764526566339, -0.000703946352348464, -0.000917016099829735, -0.001114986581270253, -0.001292014799874503,
-0.001442563411804926, -0.001561559957317790, -0.001644551048567398, -0.001687846581475964, -0.001688649703502788,
-0.001645167889846890, -0.001556702802350076, -0.001423714708648073, -0.001247857669697092, -0.001031986722557201,
-0.000780131048444402, -0.000497436825078657, -0.000190077210351809, 0.000134868279325909, 0.000469563533327739,
0.000805591531546815, 0.001134152328775355, 0.001446279849797673, 0.001733071409562941, 0.001985924997799762,
0.002196778054604388, 0.002358342626407065, 0.002464328098407475, 0.002509648218888532, 0.002490604086803692,
0.002405037734357425, 0.002252452724297770, 0.002034094661603120, 0.001752990365583534, 0.001413941154886139,
0.001023470495638453, 0.000589723521647734, 0.000122320866350319, -0.000367832138027160, -0.000868777013398284,
-0.001367771151677059, -0.001851587344265625, -0.002306838088978190, -0.002720317947026380, -0.003079353614002113,
-0.003372155891804708, -0.003588162376578369, -0.003718362558663737, -0.003755596511143005, -0.003694818131674599,
-0.003533315298404129, -0.003270878754553819, -0.002909914962857412, -0.002455496391464944, -0.001915346645364514,
-0.001299757227227888, -0.000621437066532776, 0.000104706515738248, 0.000861849931067767, 0.001631595707499856,
0.002394368911341672, 0.003129858565588139, 0.003817496679992245, 0.004436963307209760, 0.004968707287606522,
0.005394469536085115, 0.005697797543539088, 0.005864537618023589, 0.005883292537600076, 0.005745832319314692,
0.005447447099071761, 0.004987231255534477, 0.004368289529377007, 0.003597859022418248, 0.002687338851256991,
0.001652226293162047, 0.000511956075882180, -0.000710356149138656, -0.001988263330091648, -0.003292424566049982,
-0.004591123342747130, -0.005850857852106148, -0.007036991266043732, -0.008114450164977267, -0.009048456200082230,
-0.009805276478965942, -0.010352975302354198, -0.010662152577592631, -0.010706650669328861, -0.010464214075017983,
-0.009917087295446811, -0.009052534679222271, -0.007863270920348924, -0.006347789704693751, -0.004510582323649121,
-0.002362238055733795, 0.000080576968834213, 0.002795265196543707, 0.005753566158586979, 0.008921944932552510,
0.012262093950265378, 0.015731539846483594, 0.019284344624007944, 0.022871886384520687, 0.026443706729191677,
0.029948406200633094, 0.033334570666910354, 0.036551709955124537, 0.039551189200810140, 0.042287133974308874,
0.044717290029466283, 0.046803820535016104, 0.048514022996355009, 0.049820951883635139, 0.050703932928426454,
0.051148959210315710, 0.051148959210315710, 0.050703932928426454, 0.049820951883635139, 0.048514022996355009,
0.046803820535016104, 0.044717290029466283, 0.042287133974308874, 0.039551189200810140, 0.036551709955124537,
0.033334570666910354, 0.029948406200633094, 0.026443706729191677, 0.022871886384520687, 0.019284344624007944,
0.015731539846483594, 0.012262093950265378, 0.008921944932552510, 0.005753566158586979, 0.002795265196543707,
0.000080576968834213, -0.002362238055733795, -0.004510582323649121, -0.006347789704693751, -0.007863270920348924,
-0.009052534679222271, -0.009917087295446811, -0.010464214075017983, -0.010706650669328861, -0.010662152577592631,
-0.010352975302354198, -0.009805276478965942, -0.009048456200082230, -0.008114450164977267, -0.007036991266043732,
-0.005850857852106148, -0.004591123342747130, -0.003292424566049982, -0.001988263330091648, -0.000710356149138656,
0.000511956075882180, 0.001652226293162047, 0.002687338851256991, 0.003597859022418248, 0.004368289529377007,
0.004987231255534477, 0.005447447099071761, 0.005745832319314692, 0.005883292537600076, 0.005864537618023589,
0.005697797543539088, 0.005394469536085115, 0.004968707287606522, 0.004436963307209760, 0.003817496679992245,
0.003129858565588139, 0.002394368911341672, 0.001631595707499856, 0.000861849931067767, 0.000104706515738248,
-0.000621437066532776, -0.001299757227227888, -0.001915346645364514, -0.002455496391464944, -0.002909914962857412,
-0.003270878754553819, -0.003533315298404129, -0.003694818131674599, -0.003755596511143005, -0.003718362558663737,
-0.003588162376578369, -0.003372155891804708, -0.003079353614002113, -0.002720317947026380, -0.002306838088978190,
-0.001851587344265625, -0.001367771151677059, -0.000868777013398284, -0.000367832138027160, 0.000122320866350319,
0.000589723521647734, 0.001023470495638453, 0.001413941154886139, 0.001752990365583534, 0.002034094661603120,
0.002252452724297770, 0.002405037734357425, 0.002490604086803692, 0.002509648218888532, 0.002464328098407475,
0.002358342626407065, 0.002196778054604388, 0.001985924997799762, 0.001733071409562941, 0.001446279849797673,
0.001134152328775355, 0.000805591531546815, 0.000469563533327739, 0.000134868279325909, -0.000190077210351809,
-0.000497436825078657, -0.000780131048444402, -0.001031986722557201, -0.001247857669697092, -0.001423714708648073,
-0.001556702802350076, -0.001645167889846890, -0.001688649703502788, -0.001687846581475964, -0.001644551048567398,
-0.001561559957317790, -0.001442563411804926, -0.001292014799874503, -0.001114986581270253, -0.000917016099829735,
-0.000703946352348464, -0.000481764526566339, -0.000256444114966522, -0.000033793183292569, 0.000180685902835315,
0.000381924396468366, 0.000565398080608305, 0.000727219011746881, 0.000864209315714227, 0.000973950761085690,
0.001054815583369999, 0.001105974243787613, 0.001127383039339373, 0.001119751426837743, 0.001084492755093968,
0.001023657909064450, 0.000939856052624227, 0.000836164238172957, 0.000716029226064227, 0.000583164190168290,
0.000441441918072383, 0.000294790953130229, 0.000147092077716480, 0.000002082667095075, -0.000136731311264191,
-0.000266155252511831, -0.000383371840261246, -0.000485996080304965, -0.000572115873292030, -0.000640319946685634,
-0.000689709694056092, -0.000719899536922384, -0.000731002305621048, -0.000723604675185869, -0.000698728981427767,
-0.000657788245032425, -0.000602532044011899, -0.000534985542936898, -0.000457387566635848, -0.000372121907291206,
-0.000281651282503015, -0.000188451833293202, -0.000094949813106744, -0.000003462782744354, 0.000083853091464077,
0.000165048886226905, 0.000238422248479072, 0.000302547334727027, 0.000356297600912998, 0.000398857326863837,
0.000429729020814434, 0.000448726371643413, 0.000455966225408344, 0.000451848709179591, 0.000437031818051652,
0.000412403761615261, 0.000379047713684221, 0.000338204791740229, 0.000291234779803098, 0.000239577162514028,
0.000184710477990398, 0.000128114399130489, 0.000071232572821451, 0.000015440388211825, -0.000037986085678081,
-0.000087895370243821, -0.000133280012107173, -0.000173297342436372, -0.000207273956099563, -0.000234717772155001,
-0.000255317038867589, -0.000268937472718753, -0.000275614059005332, -0.000275541485292432, -0.000269058714331757,
-0.000256632149501508, -0.000238836419299503, -0.000216333899003825, -0.000189854272533545, -0.000160170174848483,
-0.000128080670195777, -0.000094384355854646, -0.000059865389594949, -0.000025277165852799, 0.000008680571408025,
0.000041365841965015, 0.000072210925236429, 0.000100726393185629, 0.000126511346757621, 0.000149250512353807,
0.000168719942655099, 0.000184780318878738, 0.000197379393194548, 0.000206539880117977, 0.000212358734245594,
0.000214994859281552, 0.000214655997661182, 0.000211604878787747, 0.000206128795372885, 0.000198541881389953,
0.000189176709991702, 0.000178368313347299, 0.000166450784469067, 0.000153744508371709, 0.000140558396336177,
0.000127174196746337, 0.000113853476544409, 0.000100818605854714, 0.000088271373315159, 0.000076360900545177,
0.000065233162392019, 0.000054970017069384, 0.000045630720487935, 0.000037271082107518, 0.000029885221425020,
0.000023463361155584, 0.000017966192635412, 0.000013350669444763, 0.000009551098482930, 0.000006499942123311,
0.000004115682735322, 0.000002322193058869, 0.000001038946634000, 0.000000197734700398, -0.000000267011791999,
-0.000005050567303837 };
} // FreeDV

View File

@ -1,886 +0,0 @@
/*---------------------------------------------------------------------------*\
FILE........: fsk.c
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/>.
*/
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "freedv_vhf_framing.h"
namespace FreeDV
{
/* The voice UW of the VHF type A frame */
static const uint8_t A_uw_v[] = {0,1,1,0,0,1,1,1,
1,0,1,0,1,1,0,1};
/* The data UW of the VHF type A frame */
static const uint8_t A_uw_d[] = {1,1,1,1,0,0,0,1,
1,1,1,1,1,1,0,0};
/* Blank VHF type A frame */
static const uint8_t A_blank[] = {1,0,1,0,0,1,1,1, /* Padding[0:3] Proto[0:3] */
1,0,1,0,0,1,1,1, /* Proto[4:11] */
0,0,0,0,0,0,0,0, /* Voice[0:7] */
0,0,0,0,0,0,0,0, /* Voice[8:15] */
0,0,0,0,0,0,0,0, /* Voice[16:23] */
0,1,1,0,0,1,1,1, /* UW[0:7] */
1,0,1,0,1,1,0,1, /* UW[8:15] */
0,0,0,0,0,0,0,0, /* Voice[24:31] */
0,0,0,0,0,0,0,0, /* Voice[32:39] */
0,0,0,0,0,0,0,0, /* Voice[40:47] */
0,0,0,0,0,0,1,0, /* Voice[48:51] Proto[12:15] */
0,1,1,1,0,0,1,0};/* Proto[16:19] Padding[4:7] */
/* Blank VHF type AT (A for TDMA; padding bits not transmitted) frame */
static const uint8_t AT_blank[] = { 0,1,1,1, /* Proto[0:3] */
1,0,1,0,0,1,1,1, /* Proto[4:11] */
0,0,0,0,0,0,0,0, /* Voice[0:7] */
0,0,0,0,0,0,0,0, /* Voice[8:15] */
0,0,0,0,0,0,0,0, /* Voice[16:23] */
0,1,1,0,0,1,1,1, /* UW[0:7] */
1,0,1,0,1,1,0,1, /* UW[8:15] */
0,0,0,0,0,0,0,0, /* Voice[24:31] */
0,0,0,0,0,0,0,0, /* Voice[32:39] */
0,0,0,0,0,0,0,0, /* Voice[40:47] */
0,0,0,0,0,0,1,0, /* Voice[48:51] Proto[12:15] */
0,1,1,1 };/* Proto[16:19] */
/* HF Type B voice UW */
static const uint8_t B_uw_v[] = {0,1,1,0,0,1,1,1};
/* HF Type B data UW */
static const uint8_t B_uw_d[] = {1,1,1,1,0,0,1,0};
/* Blank HF type B frame */
static const uint8_t B_blank[] = {0,1,1,0,0,1,1,1, /* UW[0:7] */
0,0,0,0,0,0,0,0, /* Voice1[0:7] */
0,0,0,0,0,0,0,0, /* Voice1[8:15] */
0,0,0,0,0,0,0,0, /* Voice1[16:23] */
0,0,0,0,0,0,0,0, /* Voice1[24:28] Voice2[0:3] */
0,0,0,0,0,0,0,0, /* Voice2[4:11] */
0,0,0,0,0,0,0,0, /* Voice2[12:19] */
0,0,0,0,0,0,0,0};/* Voice2[20:28] */
/* States */
#define ST_NOSYNC 0 /* Not synchronized */
#define ST_SYNC 1 /* Synchronized */
/* Get a single bit out of an MSB-first packed byte array */
#define UNPACK_BIT_MSBFIRST(bytes,bitidx) ((bytes)[(bitidx)>>3]>>(7-((bitidx)&0x7)))&0x1
enum frame_payload_type {
FRAME_PAYLOAD_TYPE_VOICE,
FRAME_PAYLOAD_TYPE_DATA,
};
/* 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[]){
int i,ibit;
if(frame_type == FREEDV_VHF_FRAME_A){
/* Fill out frame with blank frame prototype */
for(i=0; i<96; i++)
bits_out[i] = A_blank[i];
/* Fill in protocol bits, if present */
if(proto_in!=NULL){
ibit = 0;
/* First half of protocol bits */
/* Extract and place in frame, MSB first */
for(i=4 ; i<16; i++){
bits_out[i] = UNPACK_BIT_MSBFIRST(proto_in,ibit);
ibit++;
}
/* Last set of protocol bits */
for(i=84; i<92; i++){
bits_out[i] = UNPACK_BIT_MSBFIRST(proto_in,ibit);
ibit++;
}
}
/* Fill in varicode bits, if present */
if(vc_in!=NULL){
bits_out[90] = vc_in[0];
bits_out[91] = vc_in[1];
}
/* Fill in codec2 bits, present or not */
ibit = 0;
for(i=16; i<40; i++){ /* First half */
bits_out[i] = UNPACK_BIT_MSBFIRST(codec2_in,ibit);
ibit++;
}
for(i=56; i<84; i++){ /* Second half */
bits_out[i] = UNPACK_BIT_MSBFIRST(codec2_in,ibit);
ibit++;
}
}else if(frame_type == FREEDV_HF_FRAME_B){
/* Pointers to both c2 frames so the bit unpack macro works */
uint8_t * codec2_in1 = &codec2_in[0];
uint8_t * codec2_in2 = &codec2_in[4];
/* Fill out frame with blank prototype */
for(i=0; i<64; i++)
bits_out[i] = B_blank[i];
/* Fill out first codec2 block */
ibit=0;
for(i=8; i<36; i++){
bits_out[i] = UNPACK_BIT_MSBFIRST(codec2_in1,ibit);
ibit++;
}
/* Fill out second codec2 block */
ibit=0;
for(i=36; i<64; i++){
bits_out[i] = UNPACK_BIT_MSBFIRST(codec2_in2,ibit);
ibit++;
}
}else if(frame_type == FREEDV_VHF_FRAME_AT){
/* Fill out frame with blank frame prototype */
for(i=0; i<88; i++)
bits_out[i] = AT_blank[i];
/* Fill in protocol bits, if present */
if(proto_in!=NULL){
ibit = 0;
/* First half of protocol bits */
/* Extract and place in frame, MSB first */
for(i=0 ; i<12; i++){
bits_out[i] = UNPACK_BIT_MSBFIRST(proto_in,ibit);
ibit++;
}
/* Last set of protocol bits */
for(i=80; i<88; i++){
bits_out[i] = UNPACK_BIT_MSBFIRST(proto_in,ibit);
ibit++;
}
}
/* Fill in varicode bits, if present */
if(vc_in!=NULL){
bits_out[86] = vc_in[0];
bits_out[87] = vc_in[1];
}
/* Fill in codec2 bits, present or not */
ibit = 0;
for(i=12; i<36; i++){ /* First half */
bits_out[i] = UNPACK_BIT_MSBFIRST(codec2_in,ibit);
ibit++;
}
for(i=52; i<80; i++){ /* Second half */
bits_out[i] = UNPACK_BIT_MSBFIRST(codec2_in,ibit);
ibit++;
}
}
}
/* Place data and other bits into a frame */
void fvhff_frame_data_bits(struct freedv_vhf_deframer * def, int frame_type,
uint8_t bits_out[]){
int i,ibit;
if(frame_type == FREEDV_VHF_FRAME_A){
uint8_t data[8];
int end_bits;
int from_bit;
int bcast_bit;
int crc_bit;
/* Fill out frame with blank frame prototype */
for(i=0; i<4; i++)
bits_out[i] = A_blank[i];
for(i=92; i<96; i++)
bits_out[i] = A_blank[i];
/* UW data */
for (i=0; i < 16; i++)
bits_out[40 + i] = A_uw_d[i];
if (def->fdc)
freedv_data_channel_tx_frame(def->fdc, data, 8, &from_bit, &bcast_bit, &crc_bit, &end_bits);
else
return;
bits_out[4] = from_bit;
bits_out[5] = bcast_bit;
bits_out[6] = 0; /* unused */
bits_out[7] = 0; /* unused */
/* Fill in data bits */
ibit = 0;
for(i=8; i<40; i++){ /* First half */
bits_out[i] = UNPACK_BIT_MSBFIRST(data,ibit);
ibit++;
}
for(i=56; i<88; i++){ /* Second half */
bits_out[i] = UNPACK_BIT_MSBFIRST(data,ibit);
ibit++;
}
for (i = 0; i < 4; i++)
bits_out[88 + i] = (end_bits >> (3-i)) & 0x1;
} else if (frame_type == FREEDV_HF_FRAME_B){
uint8_t data[6];
int end_bits;
int from_bit;
int bcast_bit;
int crc_bit;
/* Fill out frame with blank prototype */
for(i=0; i<64; i++)
bits_out[i] = B_blank[i];
/* UW data */
for (i=0; i < 8; i++)
bits_out[0 + i] = B_uw_d[i];
if (def->fdc)
freedv_data_channel_tx_frame(def->fdc, data, 6, &from_bit, &bcast_bit, &crc_bit, &end_bits);
else
return;
bits_out[56] = from_bit;
bits_out[57] = bcast_bit;
bits_out[58] = crc_bit;
bits_out[59] = 0; /* unused */
/* Fill in data bits */
ibit = 0;
for(i=8; i<56; i++){ /* First half */
bits_out[i] = UNPACK_BIT_MSBFIRST(data,ibit);
ibit++;
}
for (i = 0; i < 4; i++)
bits_out[60 + i] = (end_bits >> (3-i)) & 0x1;
}
}
/* 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)
{
struct freedv_vhf_deframer * deframer;
uint8_t *bits,*invbits;
int frame_size;
int uw_size;
assert((frame_type == FREEDV_VHF_FRAME_A) || (frame_type == FREEDV_HF_FRAME_B));
/* It's a Type A frame */
if (frame_type == FREEDV_VHF_FRAME_A)
{
frame_size = 96;
uw_size = 16;
}
else if (frame_type == FREEDV_HF_FRAME_B)
{
frame_size = 64;
uw_size = 8;
}
else
{
return nullptr;
}
/* Allocate memory for the thing */
deframer = (freedv_vhf_deframer*) malloc(sizeof(struct freedv_vhf_deframer));
if (deframer == nullptr) {
return nullptr;
}
/* Allocate the not-bit buffer */
if (enable_bit_flip)
{
invbits = (uint8_t*) malloc(sizeof(uint8_t)*frame_size);
if (invbits == nullptr)
{
free(deframer);
return nullptr;
}
}
else
{
invbits = nullptr;
}
/* Allocate the bit buffer */
bits = (uint8_t*) malloc(sizeof(uint8_t)*frame_size);
if (bits == nullptr)
{
if (invbits) {
free(invbits);
}
free(deframer);
return nullptr;
}
deframer->bits = bits;
deframer->invbits = invbits;
deframer->ftype = frame_type;
deframer->state = ST_NOSYNC;
deframer->bitptr = 0;
deframer->last_uw = 0;
deframer->miss_cnt = 0;
deframer->frame_size = frame_size;
deframer->uw_size = uw_size;
deframer->on_inv_bits = 0;
deframer->sym_size = 1;
deframer->ber_est = 0;
deframer->total_uw_bits = 0;
deframer->total_uw_err = 0;
deframer->fdc = NULL;
return deframer;
}
/* Get size of frame in bits */
int fvhff_get_frame_size(struct freedv_vhf_deframer * def){
return def->frame_size;
}
/* Codec2 size in bytes */
int fvhff_get_codec2_size(struct freedv_vhf_deframer * def){
if(def->ftype == FREEDV_VHF_FRAME_A){
return 7;
} else if(def->ftype == FREEDV_HF_FRAME_B){
return 8;
} else{
return 0;
}
}
/* Protocol bits in bits */
int fvhff_get_proto_size(struct freedv_vhf_deframer * def){
if(def->ftype == FREEDV_VHF_FRAME_A){
return 20;
} else if(def->ftype == FREEDV_HF_FRAME_B){
return 0;
} else{
return 0;
}
}
/* Varicode bits in bits */
int fvhff_get_varicode_size(struct freedv_vhf_deframer * def){
if(def->ftype == FREEDV_VHF_FRAME_A){
return 2;
} else if(def->ftype == FREEDV_HF_FRAME_B){
return 0;
} else{
return 0;
}
}
void fvhff_destroy_deframer(struct freedv_vhf_deframer * def){
freedv_data_channel_destroy(def->fdc);
free(def->bits);
free(def);
}
int fvhff_synchronized(struct freedv_vhf_deframer * def){
return (def->state) == ST_SYNC;
}
/* Search for a complete UW in a buffer of bits */
std::size_t fvhff_search_uw(const uint8_t bits[], std::size_t nbits,
const uint8_t uw[], std::size_t uw_len,
std::size_t * delta_out, std::size_t bits_per_sym){
std::size_t ibits,iuw;
std::size_t delta_min = uw_len;
std::size_t delta;
std::size_t offset_min = 0;
/* Walk through buffer bits */
for(ibits = 0; ibits < nbits-uw_len; ibits+=bits_per_sym){
delta = 0;
for(iuw = 0; iuw < uw_len; iuw++){
if(bits[ibits+iuw] != uw[iuw]) delta++;
}
if( delta < delta_min ){
delta_min = delta;
offset_min = ibits;
}
}
if(delta_out != NULL) *delta_out = delta_min;
return offset_min;
}
/* See if the UW is where it should be, to within a tolerance, in a bit buffer */
static int fvhff_match_uw(struct freedv_vhf_deframer * def,uint8_t bits[],int tol,int *rdiff, enum frame_payload_type *pt){
int frame_type = def->ftype;
int bitptr = def->bitptr;
int frame_size = def->frame_size;
int uw_len = def->uw_size;
int iuw,ibit;
const uint8_t * uw[2];
int uw_offset;
int diff[2] = { 0, 0 };
int i;
int match[2];
int r;
/* defaults to make compiler happy on -O3 */
*pt = FRAME_PAYLOAD_TYPE_VOICE;
*rdiff = 0;
/* Set up parameters for the standard type of frame */
if(frame_type == FREEDV_VHF_FRAME_A){
uw[0] = A_uw_v;
uw[1] = A_uw_d;
uw_len = 16;
uw_offset = 40;
} else if(frame_type == FREEDV_HF_FRAME_B){
uw[0] = B_uw_v;
uw[1] = B_uw_d;
uw_len = 8;
uw_offset = 0;
} else {
return 0;
}
/* Check both the voice and data UWs */
for (i = 0; i < 2; i++) {
/* Start bit pointer where UW should be */
ibit = bitptr + uw_offset;
if(ibit >= frame_size) ibit -= frame_size;
/* Walk through and match bits in frame with bits of UW */
for(iuw=0; iuw<uw_len; iuw++){
if(bits[ibit] != uw[i][iuw]) diff[i]++;
ibit++;
if(ibit >= frame_size) ibit = 0;
}
match[i] = diff[i] <= tol;
}
/* Pick the best matching UW */
if (diff[0] < diff[1]) {
r = match[0];
*rdiff = diff[0];
*pt = FRAME_PAYLOAD_TYPE_VOICE;
} else {
r = match[1];
*rdiff = diff[1];
*pt = FRAME_PAYLOAD_TYPE_DATA;
}
return r;
}
static void fvhff_extract_frame_voice(struct freedv_vhf_deframer * def,uint8_t bits[],
uint8_t codec2_out[],uint8_t proto_out[],uint8_t vc_out[]){
int frame_type = def->ftype;
int bitptr = def->bitptr;
int frame_size = def->frame_size;
int iframe,ibit;
if(frame_type == FREEDV_VHF_FRAME_A){
/* Extract codec2 bits */
memset(codec2_out,0,7);
ibit = 0;
/* Extract and pack first half, MSB first */
iframe = bitptr+16;
if(iframe >= frame_size) iframe-=frame_size;
for(;ibit<24;ibit++){
codec2_out[ibit>>3] |= (bits[iframe]&0x1)<<(7-(ibit&0x7));
iframe++;
if(iframe >= frame_size) iframe=0;
}
/* Extract and pack last half, MSB first */
iframe = bitptr+56;
if(iframe >= frame_size) iframe-=frame_size;
for(;ibit<52;ibit++){
codec2_out[ibit>>3] |= (bits[iframe]&0x1)<<(7-(ibit&0x7));
iframe++;
if(iframe >= frame_size) iframe=0;
}
/* Extract varicode bits, if wanted */
if(vc_out!=NULL){
iframe = bitptr+90;
if(iframe >= frame_size) iframe-=frame_size;
vc_out[0] = bits[iframe];
iframe++;
vc_out[1] = bits[iframe];
}
/* Extract protocol bits, if proto is passed through */
if(proto_out!=NULL){
/* Clear protocol bit array */
memset(proto_out,0,3);
ibit = 0;
/* Extract and pack first half, MSB first */
iframe = bitptr+4;
if(iframe >= frame_size) iframe-=frame_size;
for(;ibit<12;ibit++){
proto_out[ibit>>3] |= (bits[iframe]&0x1)<<(7-(ibit&0x7));
iframe++;
if(iframe >= frame_size) iframe=0;
}
/* Extract and pack last half, MSB first */
iframe = bitptr+84;
if(iframe >= frame_size) iframe-=frame_size;
for(;ibit<20;ibit++){
proto_out[ibit>>3] |= (bits[iframe]&0x1)<<(7-(ibit&0x7));
iframe++;
if(iframe >= frame_size) iframe=0;
}
}
}else if(frame_type == FREEDV_HF_FRAME_B){
/* Pointers to both c2 frames */
uint8_t * codec2_out1 = &codec2_out[0];
uint8_t * codec2_out2 = &codec2_out[4];
/* Extract codec2 bits */
memset(codec2_out,0,8);
ibit = 0;
/* Extract and pack first c2 frame, MSB first */
iframe = bitptr+8;
if(iframe >= frame_size) iframe-=frame_size;
for(;ibit<28;ibit++){
codec2_out1[ibit>>3] |= (bits[iframe]&0x1)<<(7-(ibit&0x7));
iframe++;
if(iframe >= frame_size) iframe=0;
}
/* Extract and pack second c2 frame, MSB first */
iframe = bitptr+36;
ibit = 0;
if(iframe >= frame_size) iframe-=frame_size;
for(;ibit<28;ibit++){
codec2_out2[ibit>>3] |= (bits[iframe]&0x1)<<(7-(ibit&0x7));
iframe++;
if(iframe >= frame_size) iframe=0;
}
}else if(frame_type == FREEDV_VHF_FRAME_AT){
/* Extract codec2 bits */
memset(codec2_out,0,7);
ibit = 0;
/* Extract and pack first half, MSB first */
iframe = bitptr+12;
if(iframe >= frame_size) iframe-=frame_size;
for(;ibit<24;ibit++){
codec2_out[ibit>>3] |= (bits[iframe]&0x1)<<(7-(ibit&0x7));
iframe++;
if(iframe >= frame_size) iframe=0;
}
/* Extract and pack last half, MSB first */
iframe = bitptr+52;
if(iframe >= frame_size) iframe-=frame_size;
for(;ibit<52;ibit++){
codec2_out[ibit>>3] |= (bits[iframe]&0x1)<<(7-(ibit&0x7));
iframe++;
if(iframe >= frame_size) iframe=0;
}
/* Extract varicode bits, if wanted */
if(vc_out!=NULL){
iframe = bitptr+86;
if(iframe >= frame_size) iframe-=frame_size;
vc_out[0] = bits[iframe];
iframe++;
vc_out[1] = bits[iframe];
}
/* Extract protocol bits, if proto is passed through */
if(proto_out!=NULL){
/* Clear protocol bit array */
memset(proto_out,0,3);
ibit = 0;
/* Extract and pack first half, MSB first */
iframe = bitptr+4;
if(iframe >= frame_size) iframe-=frame_size;
for(;ibit<12;ibit++){
proto_out[ibit>>3] |= (bits[iframe]&0x1)<<(7-(ibit&0x7));
iframe++;
if(iframe >= frame_size) iframe=0;
}
/* Extract and pack last half, MSB first */
iframe = bitptr+84;
if(iframe >= frame_size) iframe-=frame_size;
for(;ibit<20;ibit++){
proto_out[ibit>>3] |= (bits[iframe]&0x1)<<(7-(ibit&0x7));
iframe++;
if(iframe >= frame_size) iframe=0;
}
}
}
}
static void fvhff_extract_frame_data(struct freedv_vhf_deframer * def,uint8_t bits[]){
int frame_type = def->ftype;
int bitptr = def->bitptr;
int frame_size = def->frame_size;
int iframe,ibit;
if(frame_type == FREEDV_VHF_FRAME_A){
uint8_t data[8];
int end_bits = 0;
int from_bit;
int bcast_bit;
iframe = bitptr+4;
if(iframe >= frame_size) iframe-=frame_size;
from_bit = bits[iframe];
iframe++;
if(iframe >= frame_size) iframe-=frame_size;
bcast_bit = bits[iframe];
/* Extract data bits */
memset(data,0,8);
ibit = 0;
/* Extract and pack first half, MSB first */
iframe = bitptr+8;
if(iframe >= frame_size) iframe-=frame_size;
for(;ibit<32;ibit++){
data[ibit>>3] |= (bits[iframe]&0x1)<<(7-(ibit&0x7));
iframe++;
if(iframe >= frame_size) iframe=0;
}
/* Extract and pack last half, MSB first */
iframe = bitptr+56;
if(iframe >= frame_size) iframe-=frame_size;
for(;ibit<64;ibit++){
data[ibit>>3] |= (bits[iframe]&0x1)<<(7-(ibit&0x7));
iframe++;
if(iframe >= frame_size) iframe=0;
}
/* Extract endbits value, MSB first*/
iframe = bitptr+88;
ibit = 0;
if(iframe >= frame_size) iframe-=frame_size;
for(;ibit<4;ibit++){
end_bits |= (bits[iframe]&0x1)<<(3-(ibit));
iframe++;
if(iframe >= frame_size) iframe=0;
}
if (def->fdc) {
freedv_data_channel_rx_frame(def->fdc, data, 8, from_bit, bcast_bit, 0, end_bits);
}
} else if(frame_type == FREEDV_HF_FRAME_B){
uint8_t data[6];
int end_bits = 0;
int from_bit;
int bcast_bit;
int crc_bit;
ibit = 0;
memset(data,0,6);
/* Extract and pack first c2 frame, MSB first */
iframe = bitptr+8;
if(iframe >= frame_size) iframe-=frame_size;
for(;ibit<48;ibit++){
data[ibit>>3] |= (bits[iframe]&0x1)<<(7-(ibit&0x7));
iframe++;
if(iframe >= frame_size) iframe=0;
}
iframe = bitptr+56;
if(iframe >= frame_size) iframe-=frame_size;
from_bit = bits[iframe];
iframe++;
if(iframe >= frame_size) iframe-=frame_size;
bcast_bit = bits[iframe];
iframe++;
if(iframe >= frame_size) iframe-=frame_size;
crc_bit = bits[iframe];
/* Extract endbits value, MSB first*/
iframe = bitptr+60;
ibit = 0;
if(iframe >= frame_size) iframe-=frame_size;
for(;ibit<4;ibit++){
end_bits |= (bits[iframe]&0x1)<<(3-(ibit));
iframe++;
if(iframe >= frame_size) iframe=0;
}
if (def->fdc) {
freedv_data_channel_rx_frame(def->fdc, data, 6, from_bit, bcast_bit, crc_bit, end_bits);
}
}
}
static void fvhff_extract_frame(struct freedv_vhf_deframer * def,uint8_t bits[],uint8_t codec2_out[],
uint8_t proto_out[],uint8_t vc_out[],enum frame_payload_type pt){
switch (pt) {
case FRAME_PAYLOAD_TYPE_VOICE:
fvhff_extract_frame_voice(def, bits, codec2_out, proto_out, vc_out);
break;
case FRAME_PAYLOAD_TYPE_DATA:
fvhff_extract_frame_data(def, bits);
break;
}
}
/*
* Try to find the UW and extract codec/proto/vc bits in def->frame_size 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[]){
uint8_t * strbits = def->bits;
uint8_t * invbits = def->invbits;
uint8_t * bits;
int on_inv_bits = def->on_inv_bits;
int frame_type = def->ftype;
int state = def->state;
int bitptr = def->bitptr;
int last_uw = def->last_uw;
int miss_cnt = def->miss_cnt;
int frame_size = def->frame_size;
int uw_size = def->uw_size;
int uw_diff;
int i;
int uw_first_tol;
int uw_sync_tol;
int miss_tol;
int extracted_frame = 0;
enum frame_payload_type pt = FRAME_PAYLOAD_TYPE_VOICE;
/* Possibly set up frame-specific params here */
if(frame_type == FREEDV_VHF_FRAME_A){
uw_first_tol = 1; /* The UW bit-error tolerance for the first frame */
uw_sync_tol = 3; /* The UW bit error tolerance for frames after sync */
miss_tol = 4; /* How many UWs may be missed before going into the de-synced state */
}else if(frame_type == FREEDV_HF_FRAME_B){
uw_first_tol = 0; /* The UW bit-error tolerance for the first frame */
uw_sync_tol = 1; /* The UW bit error tolerance for frames after sync */
miss_tol = 3; /* How many UWs may be missed before going into the de-synced state */
}else{
return 0;
}
/* Skip N bits for multi-bit symbol modems */
for(i=0; i<frame_size; i++){
/* Put a bit in the buffer */
strbits[bitptr] = bits_in[i];
/* If we're checking the inverted bitstream, put a bit in it */
if(invbits!=NULL)
invbits[bitptr] = bits_in[i]?0:1;
bitptr++;
if(bitptr >= frame_size) bitptr -= frame_size;
def->bitptr = bitptr;
/* Enter state machine */
if(state==ST_SYNC){
/* Already synchronized, just wait till UW is back where it should be */
last_uw++;
if(invbits!=NULL){
if(on_inv_bits)
bits = invbits;
else
bits = strbits;
}else{
bits=strbits;
}
/* UW should be here. We're sunk, so deframe anyway */
if(last_uw == frame_size){
last_uw = 0;
if(!fvhff_match_uw(def,bits,uw_sync_tol,&uw_diff, &pt))
miss_cnt++;
else
miss_cnt=0;
/* If we go over the miss tolerance, go into no-sync */
if(miss_cnt>miss_tol){
state = ST_NOSYNC;
}
/* Extract the bits */
extracted_frame = 1;
fvhff_extract_frame(def,bits,codec2_out,proto_out,vc_out,pt);
/* Update BER estimate */
def->ber_est = (.995*def->ber_est) + (.005*((float)uw_diff)/((float)uw_size));
def->total_uw_bits += uw_size;
def->total_uw_err += uw_diff;
}
/* Not yet sunk */
}else{
/* It's a sync!*/
if(invbits!=NULL){
if(fvhff_match_uw(def,invbits,uw_first_tol, &uw_diff, &pt)){
state = ST_SYNC;
last_uw = 0;
miss_cnt = 0;
extracted_frame = 1;
on_inv_bits = 1;
fvhff_extract_frame(def,invbits,codec2_out,proto_out,vc_out,pt);
/* Update BER estimate */
def->ber_est = (.995*def->ber_est) + (.005*((float)uw_diff)/((float)uw_size));
def->total_uw_bits += uw_size;
def->total_uw_err += uw_diff;
}
}
if(fvhff_match_uw(def,strbits,uw_first_tol, &uw_diff, &pt)){
state = ST_SYNC;
last_uw = 0;
miss_cnt = 0;
extracted_frame = 1;
on_inv_bits = 0;
fvhff_extract_frame(def,strbits,codec2_out,proto_out,vc_out,pt);
/* Update BER estimate */
def->ber_est = (.995*def->ber_est) + (.005*((float)uw_diff)/((float)uw_size));
def->total_uw_bits += uw_size;
def->total_uw_err += uw_diff;
}
}
}
def->state = state;
def->last_uw = last_uw;
def->miss_cnt = miss_cnt;
def->on_inv_bits = on_inv_bits;
/* return zero for data frames, they are already handled by callback */
return extracted_frame && pt == FRAME_PAYLOAD_TYPE_VOICE;
}
} // FreeDV

View File

@ -1,104 +0,0 @@
/*---------------------------------------------------------------------------*\
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 <cstddef>
#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

File diff suppressed because it is too large Load Diff

View File

@ -1,209 +0,0 @@
/*---------------------------------------------------------------------------*\
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

@ -1,123 +0,0 @@
/*---------------------------------------------------------------------------*\
FILE........: gp_interleaver.c
AUTHOR......: David Rowe
DATE CREATED: April 2018
Golden Prime Interleaver. My interpretation 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/>.
*/
#include <assert.h>
#include <stdio.h>
#include "gp_interleaver.h"
namespace FreeDV
{
/*
Choose b for Golden Prime Interleaver. b is chosen to be the
closest integer, which is relatively prime to N, to the Golden
section of N.
Implemented with a LUT in C for convenience, Octave version
has a more complete implementation.
*/
int b_table[] = {
112,71,
224,139,
448,277,
672,419,
896,557,
1120,701,
1344,839,
1568,971,
1792,1109,
2016,1249,
2240,1399,
2464,1523,
2688,1663,
2912,1801,
3136,1949,
3360,2081,
3584,2213
};
int choose_interleaver_b(int Nbits)
{
unsigned int i;
for (i = 0; i < sizeof(b_table)/(2*sizeof(int)); i += 2)
{
if (b_table[i] == Nbits) {
return b_table[i+1];
}
}
/* if we get it means a Nbits we dont have in our table so choke */
fprintf(stderr, "FreeDV::choose_interleaver_b: Nbits not in table return 0 as default");
return 0;
}
void gp_interleave_comp(COMP interleaved_frame[], COMP frame[], int Nbits) {
int b = choose_interleaver_b(Nbits);
int i,j;
for (i=0; i<Nbits; i++) {
j = (b*i) % Nbits;
interleaved_frame[j] = frame[i];
}
}
void gp_deinterleave_comp(COMP frame[], COMP interleaved_frame[], int Nbits) {
int b = choose_interleaver_b(Nbits);
int i,j;
for (i=0; i<Nbits; i++) {
j = (b*i) % Nbits;
frame[i] = interleaved_frame[j];
}
}
void gp_interleave_float(float interleaved_frame[], float frame[], int Nbits) {
int b = choose_interleaver_b(Nbits);
int i,j;
for (i=0; i<Nbits; i++) {
j = (b*i) % Nbits;
interleaved_frame[j] = frame[i];
}
}
void gp_deinterleave_float(float frame[], float interleaved_frame[], int Nbits) {
int b = choose_interleaver_b(Nbits);
int i,j;
for (i=0; i<Nbits; i++) {
j = (b*i) % Nbits;
frame[i] = interleaved_frame[j];
}
}
} // FreeDV

View File

@ -1,46 +0,0 @@
/*---------------------------------------------------------------------------*\
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

View File

@ -1,649 +0,0 @@
/* Generated by hanning_file() Octave function */
namespace FreeDV
{
const float hanning[]={
0,
2.4171e-05,
9.66816e-05,
0.000217525,
0.000386689,
0.000604158,
0.00086991,
0.00118392,
0.00154616,
0.00195659,
0.00241517,
0.00292186,
0.00347661,
0.00407937,
0.00473008,
0.00542867,
0.00617507,
0.00696922,
0.00781104,
0.00870045,
0.00963736,
0.0106217,
0.0116533,
0.0127322,
0.0138581,
0.0150311,
0.0162509,
0.0175175,
0.0188308,
0.0201906,
0.0215968,
0.0230492,
0.0245478,
0.0260923,
0.0276826,
0.0293186,
0.0310001,
0.032727,
0.034499,
0.036316,
0.0381779,
0.0400844,
0.0420354,
0.0440307,
0.04607,
0.0481533,
0.0502802,
0.0524506,
0.0546643,
0.056921,
0.0592206,
0.0615627,
0.0639473,
0.0663741,
0.0688427,
0.0713531,
0.0739048,
0.0764978,
0.0791318,
0.0818064,
0.0845214,
0.0872767,
0.0900718,
0.0929066,
0.0957807,
0.0986939,
0.101646,
0.104636,
0.107665,
0.110732,
0.113836,
0.116978,
0.120156,
0.123372,
0.126624,
0.129912,
0.133235,
0.136594,
0.139989,
0.143418,
0.146881,
0.150379,
0.153911,
0.157476,
0.161074,
0.164705,
0.168368,
0.172063,
0.17579,
0.179549,
0.183338,
0.187158,
0.191008,
0.194888,
0.198798,
0.202737,
0.206704,
0.2107,
0.214724,
0.218775,
0.222854,
0.226959,
0.231091,
0.235249,
0.239432,
0.243641,
0.247874,
0.252132,
0.256414,
0.260719,
0.265047,
0.269398,
0.273772,
0.278167,
0.282584,
0.287021,
0.29148,
0.295958,
0.300456,
0.304974,
0.30951,
0.314065,
0.318638,
0.323228,
0.327835,
0.332459,
0.3371,
0.341756,
0.346427,
0.351113,
0.355814,
0.360528,
0.365256,
0.369997,
0.374751,
0.379516,
0.384293,
0.389082,
0.393881,
0.398691,
0.40351,
0.408338,
0.413176,
0.418022,
0.422876,
0.427737,
0.432605,
0.43748,
0.44236,
0.447247,
0.452138,
0.457034,
0.461935,
0.466839,
0.471746,
0.476655,
0.481568,
0.486481,
0.491397,
0.496313,
0.501229,
0.506145,
0.511061,
0.515976,
0.520889,
0.5258,
0.530708,
0.535614,
0.540516,
0.545414,
0.550308,
0.555197,
0.560081,
0.564958,
0.56983,
0.574695,
0.579552,
0.584402,
0.589244,
0.594077,
0.598901,
0.603715,
0.60852,
0.613314,
0.618097,
0.622868,
0.627628,
0.632375,
0.63711,
0.641831,
0.646538,
0.651232,
0.655911,
0.660574,
0.665222,
0.669855,
0.67447,
0.679069,
0.683651,
0.688215,
0.69276,
0.697287,
0.701795,
0.706284,
0.710752,
0.7152,
0.719627,
0.724033,
0.728418,
0.73278,
0.73712,
0.741437,
0.74573,
0.75,
0.754246,
0.758467,
0.762663,
0.766833,
0.770978,
0.775097,
0.779189,
0.783254,
0.787291,
0.791301,
0.795283,
0.799236,
0.80316,
0.807055,
0.810921,
0.814756,
0.81856,
0.822334,
0.826077,
0.829788,
0.833468,
0.837115,
0.840729,
0.844311,
0.847859,
0.851374,
0.854855,
0.858301,
0.861713,
0.86509,
0.868431,
0.871737,
0.875007,
0.87824,
0.881437,
0.884598,
0.887721,
0.890806,
0.893854,
0.896864,
0.899835,
0.902768,
0.905661,
0.908516,
0.911331,
0.914106,
0.916841,
0.919536,
0.92219,
0.924804,
0.927376,
0.929907,
0.932397,
0.934845,
0.93725,
0.939614,
0.941935,
0.944213,
0.946448,
0.94864,
0.950789,
0.952894,
0.954955,
0.956972,
0.958946,
0.960874,
0.962759,
0.964598,
0.966393,
0.968142,
0.969846,
0.971505,
0.973118,
0.974686,
0.976207,
0.977683,
0.979112,
0.980495,
0.981832,
0.983122,
0.984365,
0.985561,
0.986711,
0.987813,
0.988868,
0.989876,
0.990837,
0.99175,
0.992616,
0.993434,
0.994204,
0.994927,
0.995601,
0.996228,
0.996807,
0.997337,
0.99782,
0.998255,
0.998641,
0.998979,
0.999269,
0.999511,
0.999704,
0.999849,
0.999946,
0.999994,
0.999994,
0.999946,
0.999849,
0.999704,
0.999511,
0.999269,
0.998979,
0.998641,
0.998255,
0.99782,
0.997337,
0.996807,
0.996228,
0.995601,
0.994927,
0.994204,
0.993434,
0.992616,
0.99175,
0.990837,
0.989876,
0.988868,
0.987813,
0.986711,
0.985561,
0.984365,
0.983122,
0.981832,
0.980495,
0.979112,
0.977683,
0.976207,
0.974686,
0.973118,
0.971505,
0.969846,
0.968142,
0.966393,
0.964598,
0.962759,
0.960874,
0.958946,
0.956972,
0.954955,
0.952894,
0.950789,
0.94864,
0.946448,
0.944213,
0.941935,
0.939614,
0.93725,
0.934845,
0.932397,
0.929907,
0.927376,
0.924804,
0.92219,
0.919536,
0.916841,
0.914106,
0.911331,
0.908516,
0.905661,
0.902768,
0.899835,
0.896864,
0.893854,
0.890806,
0.887721,
0.884598,
0.881437,
0.87824,
0.875007,
0.871737,
0.868431,
0.86509,
0.861713,
0.858301,
0.854855,
0.851374,
0.847859,
0.844311,
0.840729,
0.837115,
0.833468,
0.829788,
0.826077,
0.822334,
0.81856,
0.814756,
0.810921,
0.807055,
0.80316,
0.799236,
0.795283,
0.791301,
0.787291,
0.783254,
0.779189,
0.775097,
0.770978,
0.766833,
0.762663,
0.758467,
0.754246,
0.75,
0.74573,
0.741437,
0.73712,
0.73278,
0.728418,
0.724033,
0.719627,
0.7152,
0.710752,
0.706284,
0.701795,
0.697287,
0.69276,
0.688215,
0.683651,
0.679069,
0.67447,
0.669855,
0.665222,
0.660574,
0.655911,
0.651232,
0.646538,
0.641831,
0.63711,
0.632375,
0.627628,
0.622868,
0.618097,
0.613314,
0.60852,
0.603715,
0.598901,
0.594077,
0.589244,
0.584402,
0.579552,
0.574695,
0.56983,
0.564958,
0.560081,
0.555197,
0.550308,
0.545414,
0.540516,
0.535614,
0.530708,
0.5258,
0.520889,
0.515976,
0.511061,
0.506145,
0.501229,
0.496313,
0.491397,
0.486481,
0.481568,
0.476655,
0.471746,
0.466839,
0.461935,
0.457034,
0.452138,
0.447247,
0.44236,
0.43748,
0.432605,
0.427737,
0.422876,
0.418022,
0.413176,
0.408338,
0.40351,
0.398691,
0.393881,
0.389082,
0.384293,
0.379516,
0.374751,
0.369997,
0.365256,
0.360528,
0.355814,
0.351113,
0.346427,
0.341756,
0.3371,
0.332459,
0.327835,
0.323228,
0.318638,
0.314065,
0.30951,
0.304974,
0.300456,
0.295958,
0.29148,
0.287021,
0.282584,
0.278167,
0.273772,
0.269398,
0.265047,
0.260719,
0.256414,
0.252132,
0.247874,
0.243641,
0.239432,
0.235249,
0.231091,
0.226959,
0.222854,
0.218775,
0.214724,
0.2107,
0.206704,
0.202737,
0.198798,
0.194888,
0.191008,
0.187158,
0.183338,
0.179549,
0.17579,
0.172063,
0.168368,
0.164705,
0.161074,
0.157476,
0.153911,
0.150379,
0.146881,
0.143418,
0.139989,
0.136594,
0.133235,
0.129912,
0.126624,
0.123372,
0.120156,
0.116978,
0.113836,
0.110732,
0.107665,
0.104636,
0.101646,
0.0986939,
0.0957807,
0.0929066,
0.0900718,
0.0872767,
0.0845214,
0.0818064,
0.0791318,
0.0764978,
0.0739048,
0.0713531,
0.0688427,
0.0663741,
0.0639473,
0.0615627,
0.0592206,
0.056921,
0.0546643,
0.0524506,
0.0502802,
0.0481533,
0.04607,
0.0440307,
0.0420354,
0.0400844,
0.0381779,
0.036316,
0.034499,
0.032727,
0.0310001,
0.0293186,
0.0276826,
0.0260923,
0.0245478,
0.0230492,
0.0215968,
0.0201906,
0.0188308,
0.0175175,
0.0162509,
0.0150311,
0.0138581,
0.0127322,
0.0116533,
0.0106217,
0.00963736,
0.00870045,
0.00781104,
0.00696922,
0.00617507,
0.00542867,
0.00473008,
0.00407937,
0.00347661,
0.00292186,
0.00241517,
0.00195659,
0.00154616,
0.00118392,
0.00086991,
0.000604158,
0.000386689,
0.000217525,
9.66816e-05,
2.4171e-05,
0
};
} // FreeDV

View File

@ -1,260 +0,0 @@
/*---------------------------------------------------------------------------*\
FILE........: interldpc.c
AUTHOR......: David Rowe
DATE CREATED: April 2018
Helper functions for interleaved LDPC waveforms.
\*---------------------------------------------------------------------------*/
/*
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/>.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include "interldpc.h"
#include "codec2_ofdm.h"
#include "mpdecode_core.h"
#include "gp_interleaver.h"
#include "HRA_112_112.h"
namespace FreeDV
{
/* CRC type function, used to compare QPSK vectors when debugging */
COMP test_acc(COMP v[], int n) {
COMP acc = {0.0f, 0.0f};
int i;
for (i = 0; i < n; i++) {
acc.real += roundf(v[i].real);
acc.imag += roundf(v[i].imag);
}
return acc;
}
void printf_n(COMP v[], int n) {
int i;
for (i = 0; i < n; i++) {
fprintf(stderr, "%d %10f %10f\n", i, round(v[i].real), round(v[i].imag));
}
}
void set_up_hra_112_112(struct LDPC *ldpc, struct OFDM_CONFIG *config) {
ldpc->max_iter = HRA_112_112_MAX_ITER;
ldpc->dec_type = 0;
ldpc->q_scale_factor = 1;
ldpc->r_scale_factor = 1;
ldpc->CodeLength = HRA_112_112_CODELENGTH;
ldpc->NumberParityBits = HRA_112_112_NUMBERPARITYBITS;
ldpc->NumberRowsHcols = HRA_112_112_NUMBERROWSHCOLS;
ldpc->max_row_weight = HRA_112_112_MAX_ROW_WEIGHT;
ldpc->max_col_weight = HRA_112_112_MAX_COL_WEIGHT;
ldpc->H_rows = (uint16_t *) HRA_112_112_H_rows;
ldpc->H_cols = (uint16_t *) HRA_112_112_H_cols;
/* provided for convenience and to match Octave vaiable names */
ldpc->data_bits_per_frame = HRA_112_112_CODELENGTH - HRA_112_112_NUMBERPARITYBITS;
ldpc->coded_bits_per_frame = HRA_112_112_CODELENGTH;
ldpc->coded_syms_per_frame = ldpc->coded_bits_per_frame / config->bps;
}
void ldpc_encode_frame(struct LDPC *ldpc, int codeword[], unsigned char tx_bits_char[]) {
unsigned char *pbits = new unsigned char[ldpc->NumberParityBits];
int i, j;
encode(ldpc, tx_bits_char, pbits);
for (i = 0; i < ldpc->data_bits_per_frame; i++) {
codeword[i] = tx_bits_char[i];
}
for (j = 0; i < ldpc->coded_bits_per_frame; i++, j++) {
codeword[i] = pbits[j];
}
delete[] pbits;
}
void qpsk_modulate_frame(COMP tx_symbols[], int codeword[], int n) {
int s, i;
int dibit[2];
std::complex<float> qpsk_symb;
for (s = 0, i = 0; i < n; s += 2, i++) {
dibit[0] = codeword[s + 1] & 0x1;
dibit[1] = codeword[s] & 0x1;
qpsk_symb = qpsk_mod(dibit);
tx_symbols[i].real = std::real(qpsk_symb);
tx_symbols[i].imag = std::imag(qpsk_symb);
}
}
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 *iter, int *parityCheckCount, int *Nerrs_coded)
{
(void) config;
int coded_syms_per_frame = ldpc->coded_syms_per_frame;
int coded_bits_per_frame = ldpc->coded_bits_per_frame;
int data_bits_per_frame = ldpc->data_bits_per_frame;
float *llr = new float[coded_bits_per_frame];
uint8_t *out_char = new uint8_t[coded_bits_per_frame];
State next_sync_state_interleaver;
next_sync_state_interleaver = ofdm->sync_state_interleaver;
if ((ofdm->sync_state_interleaver == search) && (ofdm->frame_count >= (interleave_frames - 1))) {
symbols_to_llrs(llr, codeword_symbols_de, codeword_amps_de, EsNo, ofdm->mean_amp, coded_syms_per_frame);
iter[0] = run_ldpc_decoder(ldpc, out_char, llr, parityCheckCount);
Nerrs_coded[0] = data_bits_per_frame - parityCheckCount[0];
if ((Nerrs_coded[0] == 0) || (interleave_frames == 1)) {
/* sucessful decode! */
next_sync_state_interleaver = synced;
ofdm->frame_count_interleaver = interleave_frames;
}
}
ofdm->sync_state_interleaver = next_sync_state_interleaver;
delete[] out_char;
delete[] llr;
}
/* measure uncoded (raw) bit errors over interleaver frame, note we
don't include txt bits as this is done after we dissassemmble the
frame */
int count_uncoded_errors(struct LDPC *ldpc, struct OFDM_CONFIG *config, int Nerrs_raw[], int interleave_frames, COMP codeword_symbols_de[]) {
int i, j, Nerrs, Terrs;
int coded_syms_per_frame = ldpc->coded_syms_per_frame;
int coded_bits_per_frame = ldpc->coded_bits_per_frame;
int data_bits_per_frame = ldpc->data_bits_per_frame;
int *rx_bits_raw = new int[coded_bits_per_frame];
/* generate test codeword from known payload data bits */
int *test_codeword = new int[coded_bits_per_frame];
uint16_t *r = new uint16_t[data_bits_per_frame];
uint8_t *tx_bits = new uint8_t[data_bits_per_frame];
ofdm_rand(r, data_bits_per_frame);
for (i = 0; i < data_bits_per_frame; i++) {
tx_bits[i] = r[i] > 16384;
}
ldpc_encode_frame(ldpc, test_codeword, tx_bits);
Terrs = 0;
for (j = 0; j < interleave_frames; j++) {
for (i = 0; i < coded_syms_per_frame; i++) {
int bits[2];
std::complex<float> s = std::complex<float>{codeword_symbols_de[j * coded_syms_per_frame + i].real, codeword_symbols_de[j * coded_syms_per_frame + i].imag};
qpsk_demod(s, bits);
rx_bits_raw[config->bps * i] = bits[1];
rx_bits_raw[config->bps * i + 1] = bits[0];
}
Nerrs = 0;
for (i = 0; i < coded_bits_per_frame; i++) {
if (test_codeword[i] != rx_bits_raw[i]) {
Nerrs++;
}
}
Nerrs_raw[j] = Nerrs;
Terrs += Nerrs;
}
delete[] tx_bits;
delete[] r;
delete[] test_codeword;
delete[] rx_bits_raw;
return Terrs;
}
int count_errors(uint8_t tx_bits[], uint8_t rx_bits[], int n) {
int i;
int Nerrs = 0;
for (i = 0; i < n; i++) {
if (tx_bits[i] != rx_bits[i]) {
Nerrs++;
}
}
return Nerrs;
}
/*
Given an array of tx_bits, LDPC encodes, interleaves, and OFDM
modulates.
Note this could be refactored to save memory, e.g. for embedded
applications we could call ofdm_txframe on a frame by frame
basis
*/
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) {
int coded_syms_per_frame = ldpc->coded_syms_per_frame;
int coded_bits_per_frame = ldpc->coded_bits_per_frame;
int data_bits_per_frame = ldpc->data_bits_per_frame;
int ofdm_bitsperframe = ofdm_get_bits_per_frame();
int *codeword = new int[coded_bits_per_frame];
COMP *coded_symbols = new COMP[interleave_frames * coded_syms_per_frame];
COMP *coded_symbols_inter = new COMP[interleave_frames * coded_syms_per_frame];
int Nsamperframe = ofdm_get_samples_per_frame();
std::complex<float> *tx_symbols = new std::complex<float>[ofdm_bitsperframe / config->bps];
int j;
for (j = 0; j < interleave_frames; j++) {
ldpc_encode_frame(ldpc, codeword, &tx_bits[j * data_bits_per_frame]);
qpsk_modulate_frame(&coded_symbols[j * coded_syms_per_frame], codeword, coded_syms_per_frame);
}
gp_interleave_comp(coded_symbols_inter, coded_symbols, interleave_frames * coded_syms_per_frame);
for (j = 0; j < interleave_frames; j++) {
ofdm_assemble_modem_frame_symbols(tx_symbols, &coded_symbols_inter[j * coded_syms_per_frame], &txt_bits[config->txtbits * j]);
ofdm_txframe(ofdm, &tx_sams[j * Nsamperframe], tx_symbols);
}
delete[] tx_symbols;
delete[] coded_symbols_inter;
delete[] coded_symbols;
delete[] codeword;
}
} // FreeDV

View File

@ -1,59 +0,0 @@
/*---------------------------------------------------------------------------*\
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

View File

@ -1,416 +0,0 @@
/*
Copyright (c) 2003-2010, Mark Borgerding
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// fix gcc >= 4.6
// see https://gcc.gnu.org/gcc-4.6/porting_to.html
#include <cstddef>
#include "_kiss_fft_guts.h"
/* The guts header contains all the multiplication and addition macros that are defined for
fixed or floating point complex numbers. It also delares the kf_ internal functions.
*/
namespace FreeDV
{
static void kf_bfly2(
kiss_fft_cpx * Fout,
const std::size_t fstride,
const kiss_fft_cfg st,
int m
)
{
kiss_fft_cpx * Fout2;
kiss_fft_cpx * tw1 = st->twiddles;
kiss_fft_cpx t;
Fout2 = Fout + m;
do{
C_FIXDIV(*Fout,2); C_FIXDIV(*Fout2,2);
C_MUL (t, *Fout2 , *tw1);
tw1 += fstride;
C_SUB( *Fout2 , *Fout , t );
C_ADDTO( *Fout , t );
++Fout2;
++Fout;
}while (--m);
}
static void kf_bfly4(
kiss_fft_cpx * Fout,
const std::size_t fstride,
const kiss_fft_cfg st,
const std::size_t m
)
{
kiss_fft_cpx *tw1,*tw2,*tw3;
kiss_fft_cpx scratch[6];
std::size_t k=m;
const std::size_t m2=2*m;
const std::size_t m3=3*m;
tw3 = tw2 = tw1 = st->twiddles;
do {
C_FIXDIV(*Fout,4); C_FIXDIV(Fout[m],4); C_FIXDIV(Fout[m2],4); C_FIXDIV(Fout[m3],4);
C_MUL(scratch[0],Fout[m] , *tw1 );
C_MUL(scratch[1],Fout[m2] , *tw2 );
C_MUL(scratch[2],Fout[m3] , *tw3 );
C_SUB( scratch[5] , *Fout, scratch[1] );
C_ADDTO(*Fout, scratch[1]);
C_ADD( scratch[3] , scratch[0] , scratch[2] );
C_SUB( scratch[4] , scratch[0] , scratch[2] );
C_SUB( Fout[m2], *Fout, scratch[3] );
tw1 += fstride;
tw2 += fstride*2;
tw3 += fstride*3;
C_ADDTO( *Fout , scratch[3] );
if(st->inverse) {
Fout[m].r = scratch[5].r - scratch[4].i;
Fout[m].i = scratch[5].i + scratch[4].r;
Fout[m3].r = scratch[5].r + scratch[4].i;
Fout[m3].i = scratch[5].i - scratch[4].r;
}else{
Fout[m].r = scratch[5].r + scratch[4].i;
Fout[m].i = scratch[5].i - scratch[4].r;
Fout[m3].r = scratch[5].r - scratch[4].i;
Fout[m3].i = scratch[5].i + scratch[4].r;
}
++Fout;
}while(--k);
}
static void kf_bfly3(
kiss_fft_cpx * Fout,
const std::size_t fstride,
const kiss_fft_cfg st,
std::size_t m
)
{
std::size_t k=m;
const std::size_t m2 = 2*m;
kiss_fft_cpx *tw1,*tw2;
kiss_fft_cpx scratch[5];
kiss_fft_cpx epi3;
epi3 = st->twiddles[fstride*m];
tw1=tw2=st->twiddles;
do{
C_FIXDIV(*Fout,3); C_FIXDIV(Fout[m],3); C_FIXDIV(Fout[m2],3);
C_MUL(scratch[1],Fout[m] , *tw1);
C_MUL(scratch[2],Fout[m2] , *tw2);
C_ADD(scratch[3],scratch[1],scratch[2]);
C_SUB(scratch[0],scratch[1],scratch[2]);
tw1 += fstride;
tw2 += fstride*2;
Fout[m].r = Fout->r - HALF_OF(scratch[3].r);
Fout[m].i = Fout->i - HALF_OF(scratch[3].i);
C_MULBYSCALAR( scratch[0] , epi3.i );
C_ADDTO(*Fout,scratch[3]);
Fout[m2].r = Fout[m].r + scratch[0].i;
Fout[m2].i = Fout[m].i - scratch[0].r;
Fout[m].r -= scratch[0].i;
Fout[m].i += scratch[0].r;
++Fout;
}while(--k);
}
static void kf_bfly5(
kiss_fft_cpx * Fout,
const std::size_t fstride,
const kiss_fft_cfg st,
int m
)
{
kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
int u;
kiss_fft_cpx scratch[13];
kiss_fft_cpx * twiddles = st->twiddles;
kiss_fft_cpx *tw;
kiss_fft_cpx ya,yb;
ya = twiddles[fstride*m];
yb = twiddles[fstride*2*m];
Fout0=Fout;
Fout1=Fout0+m;
Fout2=Fout0+2*m;
Fout3=Fout0+3*m;
Fout4=Fout0+4*m;
tw=st->twiddles;
for ( u=0; u<m; ++u ) {
C_FIXDIV( *Fout0,5); C_FIXDIV( *Fout1,5); C_FIXDIV( *Fout2,5); C_FIXDIV( *Fout3,5); C_FIXDIV( *Fout4,5);
scratch[0] = *Fout0;
C_MUL(scratch[1] ,*Fout1, tw[u*fstride]);
C_MUL(scratch[2] ,*Fout2, tw[2*u*fstride]);
C_MUL(scratch[3] ,*Fout3, tw[3*u*fstride]);
C_MUL(scratch[4] ,*Fout4, tw[4*u*fstride]);
C_ADD( scratch[7],scratch[1],scratch[4]);
C_SUB( scratch[10],scratch[1],scratch[4]);
C_ADD( scratch[8],scratch[2],scratch[3]);
C_SUB( scratch[9],scratch[2],scratch[3]);
Fout0->r += scratch[7].r + scratch[8].r;
Fout0->i += scratch[7].i + scratch[8].i;
scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r);
scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r);
scratch[6].r = S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i);
scratch[6].i = -S_MUL(scratch[10].r,ya.i) - S_MUL(scratch[9].r,yb.i);
C_SUB(*Fout1,scratch[5],scratch[6]);
C_ADD(*Fout4,scratch[5],scratch[6]);
scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r);
scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r);
scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i);
scratch[12].i = S_MUL(scratch[10].r,yb.i) - S_MUL(scratch[9].r,ya.i);
C_ADD(*Fout2,scratch[11],scratch[12]);
C_SUB(*Fout3,scratch[11],scratch[12]);
++Fout0;++Fout1;++Fout2;++Fout3;++Fout4;
}
}
/* perform the butterfly for one stage of a mixed radix FFT */
static void kf_bfly_generic(
kiss_fft_cpx * Fout,
const std::size_t fstride,
const kiss_fft_cfg st,
int m,
int p
)
{
int u,k,q1,q;
kiss_fft_cpx * twiddles = st->twiddles;
kiss_fft_cpx t;
int Norig = st->nfft;
kiss_fft_cpx * scratch = (kiss_fft_cpx*)KISS_FFT_TMP_ALLOC(sizeof(kiss_fft_cpx)*p);
for ( u=0; u<m; ++u ) {
k=u;
for ( q1=0 ; q1<p ; ++q1 ) {
scratch[q1] = Fout[ k ];
C_FIXDIV(scratch[q1],p);
k += m;
}
k=u;
for ( q1=0 ; q1<p ; ++q1 ) {
int twidx=0;
Fout[ k ] = scratch[0];
for (q=1;q<p;++q ) {
twidx += fstride * k;
if (twidx>=Norig) twidx-=Norig;
C_MUL(t,scratch[q] , twiddles[twidx] );
C_ADDTO( Fout[ k ] ,t);
}
k += m;
}
}
KISS_FFT_TMP_FREE(scratch);
}
static
void kf_work(
kiss_fft_cpx * Fout,
const kiss_fft_cpx * f,
const std::size_t fstride,
int in_stride,
int * factors,
const kiss_fft_cfg st
)
{
kiss_fft_cpx * Fout_beg=Fout;
const int p=*factors++; /* the radix */
const int m=*factors++; /* stage's fft length/p */
const kiss_fft_cpx * Fout_end = Fout + p*m;
#ifdef _OPENMP
// use openmp extensions at the
// top-level (not recursive)
if (fstride==1 && p<=5)
{
int k;
// execute the p different work units in different threads
# pragma omp parallel for
for (k=0;k<p;++k)
kf_work( Fout +k*m, f+ fstride*in_stride*k,fstride*p,in_stride,factors,st);
// all threads have joined by this point
switch (p) {
case 2: kf_bfly2(Fout,fstride,st,m); break;
case 3: kf_bfly3(Fout,fstride,st,m); break;
case 4: kf_bfly4(Fout,fstride,st,m); break;
case 5: kf_bfly5(Fout,fstride,st,m); break;
default: kf_bfly_generic(Fout,fstride,st,m,p); break;
}
return;
}
#endif
if (m==1) {
do{
*Fout = *f;
f += fstride*in_stride;
}while(++Fout != Fout_end );
}else{
do{
// recursive call:
// DFT of size m*p performed by doing
// p instances of smaller DFTs of size m,
// each one takes a decimated version of the input
kf_work( Fout , f, fstride*p, in_stride, factors,st);
f += fstride*in_stride;
}while( (Fout += m) != Fout_end );
}
Fout=Fout_beg;
// recombine the p smaller DFTs
switch (p) {
case 2: kf_bfly2(Fout,fstride,st,m); break;
case 3: kf_bfly3(Fout,fstride,st,m); break;
case 4: kf_bfly4(Fout,fstride,st,m); break;
case 5: kf_bfly5(Fout,fstride,st,m); break;
default: kf_bfly_generic(Fout,fstride,st,m,p); break;
}
}
/* facbuf is populated by p1,m1,p2,m2, ...
where
p[i] * m[i] = m[i-1]
m0 = n */
static
void kf_factor(int n,int * facbuf)
{
int p=4;
double floor_sqrt;
floor_sqrt = floorf( sqrtf((double)n) );
/*factor out powers of 4, powers of 2, then any remaining primes */
do {
while (n % p) {
switch (p) {
case 4: p = 2; break;
case 2: p = 3; break;
default: p += 2; break;
}
if (p > floor_sqrt)
p = n; /* no more factors, skip to end */
}
n /= p;
*facbuf++ = p;
*facbuf++ = n;
} while (n > 1);
}
/*
*
* User-callable function to allocate all necessary storage space for the fft.
*
* The return value is a contiguous block of memory, allocated with malloc. As such,
* It can be freed with free(), rather than a kiss_fft-specific function.
* */
kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem, std::size_t * lenmem )
{
kiss_fft_cfg st=NULL;
std::size_t memneeded = sizeof(struct kiss_fft_state)
+ sizeof(kiss_fft_cpx)*(nfft-1); /* twiddle factors*/
if ( lenmem==NULL ) {
st = ( kiss_fft_cfg)KISS_FFT_MALLOC( memneeded );
}else{
if (mem != NULL && *lenmem >= memneeded)
st = (kiss_fft_cfg)mem;
*lenmem = memneeded;
}
if (st) {
int i;
st->nfft=nfft;
st->inverse = inverse_fft;
for (i=0;i<nfft;++i) {
const double pi=3.141592653589793238462643383279502884197169399375105820974944;
double phase = -2*pi*i / nfft;
if (st->inverse)
phase *= -1;
kf_cexp(st->twiddles+i, phase );
}
kf_factor(nfft,st->factors);
}
return st;
}
void kiss_fft_stride(kiss_fft_cfg st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride)
{
if (fin == fout) {
//NOTE: this is not really an in-place FFT algorithm.
//It just performs an out-of-place FFT into a temp buffer
kiss_fft_cpx * tmpbuf = (kiss_fft_cpx*)KISS_FFT_TMP_ALLOC( sizeof(kiss_fft_cpx)*st->nfft);
kf_work(tmpbuf,fin,1,in_stride, st->factors,st);
memcpy(fout,tmpbuf,sizeof(kiss_fft_cpx)*st->nfft);
KISS_FFT_TMP_FREE(tmpbuf);
}else{
kf_work( fout, fin, 1,in_stride, st->factors,st );
}
}
void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
{
kiss_fft_stride(cfg,fin,fout,1);
}
void kiss_fft_cleanup(void)
{
// nothing needed any more
}
int kiss_fft_next_fast_size(int n)
{
while(1) {
int m=n;
while ( (m%2) == 0 ) m/=2;
while ( (m%3) == 0 ) m/=3;
while ( (m%5) == 0 ) m/=5;
if (m<=1)
break; /* n is completely factorable by twos, threes, and fives */
n++;
}
return n;
}
} // FreeDV

View File

@ -1,123 +0,0 @@
#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.
*/
namespace FreeDV
{
#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
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

View File

@ -1,163 +0,0 @@
/*
Copyright (c) 2003-2004, Mark Borgerding
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// fix gcc >= 4.6
// see https://gcc.gnu.org/gcc-4.6/porting_to.html
#include <cstddef>
#include "kiss_fftr.h"
#include "_kiss_fft_guts.h"
#include "assert.h"
namespace FreeDV
{
struct kiss_fftr_state{
kiss_fft_cfg substate;
kiss_fft_cpx * tmpbuf;
kiss_fft_cpx * super_twiddles;
#ifdef USE_SIMD
void * pad;
#endif
};
kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem, std::size_t * lenmem)
{
int i;
kiss_fftr_cfg st = NULL;
std::size_t subsize, memneeded;
if (nfft & 1) {
fprintf(stderr,"Real FFT optimization must be even.\n");
return NULL;
}
nfft >>= 1;
kiss_fft_alloc (nfft, inverse_fft, NULL, &subsize);
memneeded = sizeof(struct kiss_fftr_state) + subsize + sizeof(kiss_fft_cpx) * ( nfft * 3 / 2);
if (lenmem == NULL) {
st = (kiss_fftr_cfg) KISS_FFT_MALLOC (memneeded);
} else {
if (*lenmem >= memneeded)
st = (kiss_fftr_cfg) mem;
*lenmem = memneeded;
}
if (!st)
return NULL;
st->substate = (kiss_fft_cfg) (st + 1); /*just beyond kiss_fftr_state struct */
st->tmpbuf = (kiss_fft_cpx *) (((char *) st->substate) + subsize);
st->super_twiddles = st->tmpbuf + nfft;
kiss_fft_alloc(nfft, inverse_fft, st->substate, &subsize);
for (i = 0; i < nfft/2; ++i) {
float phase =
-3.14159265358979323846264338327 * ((float) (i+1) / nfft + .5);
if (inverse_fft)
phase *= -1;
kf_cexp (st->super_twiddles+i,phase);
}
return st;
}
void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata)
{
/* input buffer timedata is stored row-wise */
int k,ncfft;
kiss_fft_cpx fpnk,fpk,f1k,f2k,tw,tdc;
assert(st->substate->inverse==0);
ncfft = st->substate->nfft;
/*perform the parallel fft of two real signals packed in real,imag*/
kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf );
/* The real part of the DC element of the frequency spectrum in st->tmpbuf
* contains the sum of the even-numbered elements of the input time sequence
* The imag part is the sum of the odd-numbered elements
*
* The sum of tdc.r and tdc.i is the sum of the input time sequence.
* yielding DC of input time sequence
* The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1...
* yielding Nyquist bin of input time sequence
*/
tdc.r = st->tmpbuf[0].r;
tdc.i = st->tmpbuf[0].i;
C_FIXDIV(tdc,2);
CHECK_OVERFLOW_OP(tdc.r ,+, tdc.i);
CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i);
freqdata[0].r = tdc.r + tdc.i;
freqdata[ncfft].r = tdc.r - tdc.i;
#ifdef USE_SIMD
freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps(0);
#else
freqdata[ncfft].i = freqdata[0].i = 0;
#endif
for ( k=1;k <= ncfft/2 ; ++k ) {
fpk = st->tmpbuf[k];
fpnk.r = st->tmpbuf[ncfft-k].r;
fpnk.i = - st->tmpbuf[ncfft-k].i;
C_FIXDIV(fpk,2);
C_FIXDIV(fpnk,2);
C_ADD( f1k, fpk , fpnk );
C_SUB( f2k, fpk , fpnk );
C_MUL( tw , f2k , st->super_twiddles[k-1]);
freqdata[k].r = HALF_OF(f1k.r + tw.r);
freqdata[k].i = HALF_OF(f1k.i + tw.i);
freqdata[ncfft-k].r = HALF_OF(f1k.r - tw.r);
freqdata[ncfft-k].i = HALF_OF(tw.i - f1k.i);
}
}
void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata)
{
/* input buffer timedata is stored row-wise */
int k, ncfft;
assert(st->substate->inverse == 1);
ncfft = st->substate->nfft;
st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r;
st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r;
C_FIXDIV(st->tmpbuf[0],2);
for (k = 1; k <= ncfft / 2; ++k) {
kiss_fft_cpx fk, fnkc, fek, fok, tmp;
fk = freqdata[k];
fnkc.r = freqdata[ncfft - k].r;
fnkc.i = -freqdata[ncfft - k].i;
C_FIXDIV( fk , 2 );
C_FIXDIV( fnkc , 2 );
C_ADD (fek, fk, fnkc);
C_SUB (tmp, fk, fnkc);
C_MUL (fok, tmp, st->super_twiddles[k-1]);
C_ADD (st->tmpbuf[k], fek, fok);
C_SUB (st->tmpbuf[ncfft - k], fek, fok);
#ifdef USE_SIMD
st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0);
#else
st->tmpbuf[ncfft - k].i *= -1;
#endif
}
kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata);
}
} // FreeDV

View File

@ -1,44 +0,0 @@
#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

View File

@ -1,187 +0,0 @@
///////////////////////////////////////////////////////////////////////////////////
// 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 //
// (at your option) any later version. //
// //
// 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_ */

View File

@ -1,110 +0,0 @@
/*---------------------------------------------------------------------------*\
FILE........: linreg.c
AUTHOR......: David Rowe
DATE CREATED: April 2015
Linear regression C module based on:
http://stackoverflow.com/questions/5083465/fast-efficient-least-squares-fit-algorithm-in-c
Use:
$ gcc linreg.c -o linreg -D__UNITTEST__ -Wall
$ ./linreg
Then compare yfit results with octave/tlinreg.m
\*---------------------------------------------------------------------------*/
/*
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/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "linreg.h"
#include "comp_prim.h"
namespace FreeDV
{
void linreg(COMP *m, COMP *b, float x[], COMP y[], int n)
{
float sumx = 0.0; /* sum of x */
float sumx2 = 0.0; /* sum of x^2 */
COMP sumxy = {0.0,0.0}; /* sum of x * y */
COMP sumy = {0.0,0.0}; /* sum of y */
COMP sumy2 = {0.0,0.0}; /* sum of y**2 */
float denom;
COMP zero;
int i;
for (i=0; i<n; i++) {
sumx += x[i];
sumx2 += x[i]*x[i];
sumxy = cadd(sumxy, fcmult(x[i], y[i]));
sumy = cadd(sumy, y[i]);
sumy2 = cadd(sumy2, cmult(y[i],y[i]));
}
denom = (n * sumx2 - sumx*sumx);
if (denom == 0) {
/* singular matrix. can't solve the problem */
zero.real = 0.0; zero.imag = 0.0;
*m = zero;
*b = zero;
} else {
*m = fcmult(1.0/denom, cadd(fcmult(n, sumxy), cneg(fcmult(sumx,sumy))));
*b = fcmult(1.0/denom, cadd(fcmult(sumx2,sumy), cneg(fcmult(sumx, sumxy))));
}
}
#ifdef __UNITTEST__
static float x[] = {1, 2, 7, 8};
static COMP y[] = {
{-0.70702, 0.70708},
{-0.77314, 0.63442},
{-0.98083, 0.19511},
{-0.99508, 0.09799}
};
int main(void) {
float x1;
COMP m,b,yfit;
linreg(&m, &b, x, y, sizeof(x)/sizeof(float));
for (x1=1; x1<=8; x1++) {
yfit = cadd(fcmult(x1, m),b);
printf("%f %f\n", yfit.real, yfit.imag);
}
return 0;
}
#endif
} // FreeDV

View File

@ -1,40 +0,0 @@
/*---------------------------------------------------------------------------*\
FILE........: linreg.h
AUTHOR......: David Rowe
DATE CREATED: April 2015
Linear regression C module based
\*---------------------------------------------------------------------------*/
/*
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 __LINREG__
#define __LINREG__
#include "codec2/comp.h"
namespace FreeDV
{
void linreg(COMP *m, COMP *b, float x[], COMP y[], int n);
} // FreeDV
#endif

View File

@ -1,57 +0,0 @@
/*---------------------------------------------------------------------------*\
FILE........: machdep.h
AUTHOR......: David Rowe
DATE CREATED: May 2 2013
Machine dependant functions, e.g. profiling that requires access to a clock
counter register.
\*---------------------------------------------------------------------------*/
/*
Copyright (C) 2013 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 __MACHDEP__
#define __MACHDEP__
namespace FreeDV
{
#ifdef PROFILE
#define PROFILE_VAR(...) unsigned int __VA_ARGS__
#define PROFILE_SAMPLE(timestamp) timestamp = machdep_profile_sample()
#define PROFILE_SAMPLE_AND_LOG(timestamp, prev_timestamp, label) \
timestamp = machdep_profile_sample_and_log(prev_timestamp, label)
#define PROFILE_SAMPLE_AND_LOG2(prev_timestamp, label) \
machdep_profile_sample_and_log(prev_timestamp, label)
#else
#define PROFILE_VAR(...)
#define PROFILE_SAMPLE(timestamp)
#define PROFILE_SAMPLE_AND_LOG(timestamp, prev_timestamp, label)
#define PROFILE_SAMPLE_AND_LOG2(prev_timestamp, label)
#endif
void machdep_profile_init(void);
void machdep_profile_reset(void);
unsigned int machdep_profile_sample(void);
unsigned int machdep_profile_sample_and_log(unsigned int start, char s[]);
void machdep_profile_print_logged_samples(void);
} // FreeDV
#endif

View File

@ -1,153 +0,0 @@
/*---------------------------------------------------------------------------*\
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>
#include "codec2/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(const char *modname, char *runname)
{
(void) modname;
(void) runname;
return;
}
static inline void modem_probe_close() {
return;
}
static inline void modem_probe_samp_i(const char *name, int samp[], std::size_t sampcnt)
{
(void) name;
(void) samp;
(void) sampcnt;
return;
}
static inline void modem_probe_samp_f(const char *name, float samp[], std::size_t cnt)
{
(void) name;
(void) samp;
(void) cnt;
return;
}
static inline void modem_probe_samp_c(const char *name, COMP samp[], std::size_t cnt)
{
(void) name;
(void) samp;
(void) cnt;
return;
}
static inline void modem_probe_samp_cft(const char *name, std::complex<float> samp[], std::size_t cnt)
{
(void) name;
(void) samp;
(void) cnt;
return;
}
#endif
} // FreeDV
#endif

View File

@ -1,79 +0,0 @@
/*---------------------------------------------------------------------------*\
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

View File

@ -1,726 +0,0 @@
/*
FILE...: mpdecode_core.c
AUTHOR.: Matthew C. Valenti, Rohit Iyer Seshadri, David Rowe
CREATED: Sep 2016
C-callable core functions moved from MpDecode.c, so they can be used for
Octave and C programs.
*/
#include <math.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <assert.h>
#include "mpdecode_core.h"
#ifndef USE_ORIGINAL_PHI0
#include "phi0.h"
#endif
#ifdef __EMBEDDED__
#include "machdep.h"
#endif
#define QPSK_CONSTELLATION_SIZE 4
#define QPSK_BITS_PER_SYMBOL 2
namespace FreeDV
{
/* QPSK constellation for symbol likelihood calculations */
static COMP S_matrix[] = {
{ 1.0f, 0.0f},
{ 0.0f, 1.0f},
{ 0.0f, -1.0f},
{-1.0f, 0.0f}
};
// c_nodes will be an array of NumberParityBits of struct c_node
// Each c_node contains an array of <degree> c_sub_node elements
// This structure reduces the indexing caluclations in SumProduct()
struct c_sub_node { // Order is important here to keep total size small.
uint16_t index; // Values from H_rows (except last 2 entries)
uint16_t socket; // The socket number at the v_node
float message; // modified during operation!
};
struct c_node {
int degree; // A count of elements in the following arrays
struct c_sub_node *subs;
};
// v_nodes will be an array of CodeLength of struct v_node
struct v_sub_node {
uint16_t index; // the index of a c_node it is connected to
// Filled with values from H_cols (except last 2 entries)
uint16_t socket; // socket number at the c_node
float message; // Loaded with input data
// modified during operation!
uint8_t sign; // 1 if input is negative
// modified during operation!
};
struct v_node {
int degree; // A count of ???
float initial_value;
struct v_sub_node *subs;
};
void encode(struct LDPC *ldpc, unsigned char ibits[], unsigned char pbits[]) {
unsigned int tmp, par, prev=0;
int i, p, ind;
uint16_t *H_rows = ldpc->H_rows;
for (p=0; p<ldpc->NumberParityBits; p++) {
par = 0;
for (i=0; i<ldpc->max_row_weight; i++) {
ind = H_rows[p + i*ldpc->NumberParityBits];
par = par + ibits[ind-1];
}
tmp = par + prev;
tmp &= 1; // only retain the lsb
prev = tmp;
pbits[p] = tmp;
}
}
#ifdef USE_ORIGINAL_PHI0
/* Phi function */
static float phi0(
float x )
{
float z;
if (x>10)
return( 0 );
else if (x< 9.08e-5 )
return( 10 );
else if (x > 9)
return( 1.6881e-4 );
/* return( 1.4970e-004 ); */
else if (x > 8)
return( 4.5887e-4 );
/* return( 4.0694e-004 ); */
else if (x > 7)
return( 1.2473e-3 );
/* return( 1.1062e-003 ); */
else if (x > 6)
return( 3.3906e-3 );
/* return( 3.0069e-003 ); */
else if (x > 5)
return( 9.2168e-3 );
/* return( 8.1736e-003 ); */
else {
z = (float) exp(x);
return( (float) log( (z+1)/(z-1) ) );
}
}
#endif
/* Values for linear approximation (DecoderType=5) */
#define AJIAN -0.24904163195436
#define TJIAN 2.50681740420944
/* The linear-log-MAP algorithm */
static float max_star0(
float delta1,
float delta2 )
{
float diff;
diff = delta2 - delta1;
if ( diff > TJIAN )
return( delta2 );
else if ( diff < -TJIAN )
return( delta1 );
else if ( diff > 0 )
return( delta2 + AJIAN*(diff-TJIAN) );
else
return( delta1 - AJIAN*(diff+TJIAN) );
}
void init_c_v_nodes(struct c_node *c_nodes,
int shift,
int NumberParityBits,
int max_row_weight,
uint16_t *H_rows,
int H1,
int CodeLength,
struct v_node *v_nodes,
int NumberRowsHcols,
uint16_t *H_cols,
int max_col_weight,
int dec_type,
float *input)
{
int i, j, k, count, cnt, c_index, v_index;
/* first determine the degree of each c-node */
if (shift ==0){
for (i=0;i<NumberParityBits;i++) {
count = 0;
for (j=0;j<max_row_weight;j++) {
if ( H_rows[i+j*NumberParityBits] > 0 ) {
count++;
}
}
c_nodes[i].degree = count;
if (H1){
if (i==0){
c_nodes[i].degree=count+1;
}
else{
c_nodes[i].degree=count+2;
}
}
}
}
else{
cnt=0;
for (i=0;i<(NumberParityBits/shift);i++) {
for (k=0;k<shift;k++){
count = 0;
for (j=0;j<max_row_weight;j++) {
if ( H_rows[cnt+j*NumberParityBits] > 0 ) {
count++;
}
}
c_nodes[cnt].degree = count;
if ((i==0)||(i==(NumberParityBits/shift)-1)){
c_nodes[cnt].degree=count+1;
}
else{
c_nodes[cnt].degree=count+2;
}
cnt++;
}
}
}
if (H1){
if (shift ==0){
for (i=0;i<NumberParityBits;i++) {
// Allocate sub nodes
c_nodes[i].subs = (struct c_sub_node*) calloc(c_nodes[i].degree, sizeof(struct c_sub_node));
assert(c_nodes[i].subs);
// Populate sub nodes
for (j=0;j<c_nodes[i].degree-2;j++) {
c_nodes[i].subs[j].index = (H_rows[i+j*NumberParityBits] - 1);
}
j=c_nodes[i].degree-2;
if (i==0){
c_nodes[i].subs[j].index = (H_rows[i+j*NumberParityBits] - 1);
}
else {
c_nodes[i].subs[j].index = (CodeLength-NumberParityBits)+i-1;
}
j=c_nodes[i].degree-1;
c_nodes[i].subs[j].index = (CodeLength-NumberParityBits)+i;
}
}
if (shift >0){
cnt=0;
for (i=0;i<(NumberParityBits/shift);i++){
for (k =0;k<shift;k++){
// Allocate sub nodes
c_nodes[cnt].subs = (struct c_sub_node*) calloc(c_nodes[cnt].degree, sizeof(struct c_sub_node));
assert(c_nodes[cnt].subs);
// Populate sub nodes
for (j=0;j<c_nodes[cnt].degree-2;j++) {
c_nodes[cnt].subs[j].index = (H_rows[cnt+j*NumberParityBits] - 1);
}
j=c_nodes[cnt].degree-2;
if ((i ==0)||(i==(NumberParityBits/shift-1))){
c_nodes[cnt].subs[j].index = (H_rows[cnt+j*NumberParityBits] - 1);
}
else{
c_nodes[cnt].subs[j].index = (CodeLength-NumberParityBits)+k+shift*(i);
}
j=c_nodes[cnt].degree-1;
c_nodes[cnt].subs[j].index = (CodeLength-NumberParityBits)+k+shift*(i+1);
if (i== (NumberParityBits/shift-1))
{
c_nodes[cnt].subs[j].index = (CodeLength-NumberParityBits)+k+shift*(i);
}
cnt++;
}
}
}
} else {
for (i=0;i<NumberParityBits;i++) {
// Allocate sub nodes
c_nodes[i].subs = (struct c_sub_node*) calloc(c_nodes[i].degree, sizeof(struct c_sub_node));
assert(c_nodes[i].subs);
// Populate sub nodes
for (j=0;j<c_nodes[i].degree;j++){
c_nodes[i].subs[j].index = (H_rows[i+j*NumberParityBits] - 1);
}
}
}
/* determine degree of each v-node */
for(i=0;i<(CodeLength-NumberParityBits+shift);i++){
count=0;
for (j=0;j<max_col_weight;j++) {
if ( H_cols[i+j*NumberRowsHcols] > 0 ) {
count++;
}
}
v_nodes[i].degree = count;
}
for(i=CodeLength-NumberParityBits+shift;i<CodeLength;i++){
count=0;
if (H1){
if(i!=CodeLength-1){
v_nodes[i].degree=2;
} else{
v_nodes[i].degree=1;
}
} else{
for (j=0;j<max_col_weight;j++) {
if ( H_cols[i+j*NumberRowsHcols] > 0 ) {
count++;
}
}
v_nodes[i].degree = count;
}
}
if (shift>0){
v_nodes[CodeLength-1].degree =v_nodes[CodeLength-1].degree+1;
}
/* set up v_nodes */
for (i=0;i<CodeLength;i++) {
// Allocate sub nodes
v_nodes[i].subs = (struct v_sub_node*) calloc(v_nodes[i].degree, sizeof(struct v_sub_node));
assert(v_nodes[i].subs);
// Populate sub nodes
/* index tells which c-nodes this v-node is connected to */
v_nodes[i].initial_value = input[i];
count=0;
for (j=0;j<v_nodes[i].degree;j++) {
if ((H1)&& (i>=CodeLength-NumberParityBits+shift)){
v_nodes[i].subs[j].index=i-(CodeLength-NumberParityBits+shift)+count;
if (shift ==0){
count=count+1;
}
else{
count=count+shift;
}
} else {
v_nodes[i].subs[j].index = (H_cols[i+j*NumberRowsHcols] - 1);
}
/* search the connected c-node for the proper message value */
for (c_index=0;c_index<c_nodes[ v_nodes[i].subs[j].index ].degree;c_index++)
if ( c_nodes[ v_nodes[i].subs[j].index ].subs[c_index].index == i ) {
v_nodes[i].subs[j].socket = c_index;
break;
}
/* initialize v-node with received LLR */
if ( dec_type == 1)
v_nodes[i].subs[j].message = fabs(input[i]);
else
v_nodes[i].subs[j].message = phi0( fabs(input[i]) );
if (input[i] < 0)
v_nodes[i].subs[j].sign = 1;
}
}
/* now finish setting up the c_nodes */
for (i=0;i<NumberParityBits;i++) {
/* index tells which v-nodes this c-node is connected to */
for (j=0;j<c_nodes[i].degree;j++) {
/* search the connected v-node for the proper message value */
for (v_index=0;v_index<v_nodes[ c_nodes[i].subs[j].index ].degree;v_index++)
if (v_nodes[ c_nodes[i].subs[j].index ].subs[v_index].index == i ) {
c_nodes[i].subs[j].socket = v_index;
break;
}
}
}
}
///////////////////////////////////////
/* function for doing the MP decoding */
// Returns the iteration count
int SumProduct( int *parityCheckCount,
char DecodedBits[],
struct c_node c_nodes[],
struct v_node v_nodes[],
int CodeLength,
int NumberParityBits,
int max_iter,
float r_scale_factor,
float q_scale_factor,
int data[] )
{
(void) r_scale_factor;
(void) q_scale_factor;
int result;
int bitErrors;
int i,j, iter;
float phi_sum;
int sign;
float temp_sum;
float Qi;
int ssum;
result = max_iter;
for (iter=0;iter<max_iter;iter++) {
for(i=0; i<CodeLength; i++) DecodedBits[i] = 0; // Clear each pass!
bitErrors = 0;
/* update r */
ssum = 0;
for (j=0;j<NumberParityBits;j++) {
sign = v_nodes[ c_nodes[j].subs[0].index ].subs[ c_nodes[j].subs[0].socket ].sign;
phi_sum = v_nodes[ c_nodes[j].subs[0].index ].subs[ c_nodes[j].subs[0].socket ].message;
for (i=1;i<c_nodes[j].degree;i++) {
// Compiler should optomize this but write the best we can to start from.
struct c_sub_node *cp = &c_nodes[j].subs[i];
struct v_sub_node *vp = &v_nodes[ cp->index ].subs[ cp->socket ];
phi_sum += vp->message;
sign ^= vp->sign;
}
if (sign==0) ssum++;
for (i=0;i<c_nodes[j].degree;i++) {
struct c_sub_node *cp = &c_nodes[j].subs[i];
struct v_sub_node *vp = &v_nodes[ cp->index ].subs[ cp->socket ];
if ( sign ^ vp->sign ) {
cp->message = -phi0( phi_sum - vp->message ); // *r_scale_factor;
} else
cp->message = phi0( phi_sum - vp->message ); // *r_scale_factor;
}
}
/* update q */
for (i=0;i<CodeLength;i++) {
/* first compute the LLR */
Qi = v_nodes[i].initial_value;
for (j=0;j<v_nodes[i].degree;j++) {
struct v_sub_node *vp = &v_nodes[i].subs[j];
Qi += c_nodes[ vp->index ].subs[ vp->socket ].message;
}
/* make hard decision */
if (Qi < 0) {
DecodedBits[i] = 1;
}
/* now subtract to get the extrinsic information */
for (j=0;j<v_nodes[i].degree;j++) {
struct v_sub_node *vp = &v_nodes[i].subs[j];
temp_sum = Qi - c_nodes[ vp->index ].subs[ vp->socket ].message;
vp->message = phi0( fabs( temp_sum ) ); // *q_scale_factor;
if (temp_sum > 0)
vp->sign = 0;
else
vp->sign = 1;
}
}
/* count data bit errors, assuming that it is systematic */
for (i=0;i<CodeLength-NumberParityBits;i++)
if ( DecodedBits[i] != data[i] )
bitErrors++;
/* Halt if zero errors */
if (bitErrors == 0) {
result = iter + 1;
break;
}
// count the number of PC satisfied and exit if all OK
*parityCheckCount = ssum;
if (ssum==NumberParityBits) {
result = iter + 1;
break;
}
}
return(result);
}
/* Convenience function to call LDPC decoder from C programs */
int run_ldpc_decoder(struct LDPC *ldpc, uint8_t out_char[], float input[], int *parityCheckCount) {
int max_iter, dec_type;
float q_scale_factor, r_scale_factor;
int max_row_weight, max_col_weight;
int CodeLength, NumberParityBits, NumberRowsHcols, shift, H1;
int i;
struct c_node *c_nodes;
struct v_node *v_nodes;
/* default values */
max_iter = ldpc->max_iter;
dec_type = ldpc->dec_type;
q_scale_factor = ldpc->q_scale_factor;
r_scale_factor = ldpc->r_scale_factor;
CodeLength = ldpc->CodeLength; /* length of entire codeword */
NumberParityBits = ldpc->NumberParityBits;
NumberRowsHcols = ldpc->NumberRowsHcols;
char *DecodedBits = (char*) calloc( CodeLength, sizeof( char ) );
assert(DecodedBits);
/* derive some parameters */
shift = (NumberParityBits + NumberRowsHcols) - CodeLength;
if (NumberRowsHcols == CodeLength) {
H1=0;
shift=0;
} else {
H1=1;
}
max_row_weight = ldpc->max_row_weight;
max_col_weight = ldpc->max_col_weight;
/* initialize c-node and v-node structures */
c_nodes = (struct c_node*) calloc( NumberParityBits, sizeof( struct c_node ) );
assert(c_nodes);
v_nodes = (struct v_node*) calloc( CodeLength, sizeof( struct v_node));
assert(v_nodes);
init_c_v_nodes(c_nodes, shift, NumberParityBits, max_row_weight, ldpc->H_rows, H1, CodeLength,
v_nodes, NumberRowsHcols, ldpc->H_cols, max_col_weight, dec_type, input);
int DataLength = CodeLength - NumberParityBits;
int *data_int = (int*) calloc( DataLength, sizeof(int) );
/* need to clear these on each call */
for(i=0; i<CodeLength; i++) DecodedBits[i] = 0;
/* Call function to do the actual decoding */
int iter = SumProduct( parityCheckCount, DecodedBits, c_nodes, v_nodes,
CodeLength, NumberParityBits, max_iter,
r_scale_factor, q_scale_factor, data_int );
for (i=0; i<CodeLength; i++) out_char[i] = DecodedBits[i];
/* Clean up memory */
free(DecodedBits);
free( data_int );
for (i=0;i<NumberParityBits;i++) {
free( c_nodes[i].subs );
}
free( c_nodes );
for (i=0;i<CodeLength;i++) {
free( v_nodes[i].subs);
}
free( v_nodes );
return iter;
}
void sd_to_llr(float llr[], double sd[], int n) {
double sum, mean, sign, sumsq, estvar, estEsN0, x;
int i;
/* convert SD samples to LLRs -------------------------------*/
sum = 0.0;
for(i=0; i<n; i++)
sum += fabs(sd[i]);
mean = sum/n;
/* find variance from +/-1 symbol position */
sum = sumsq = 0.0;
for(i=0; i<n; i++) {
sign = (sd[i] > 0.0L) - (sd[i] < 0.0L);
x = (sd[i]/mean - sign);
sum += x;
sumsq += x*x;
}
estvar = (n * sumsq - sum * sum) / (n * (n - 1));
//fprintf(stderr, "mean: %f var: %f\n", mean, estvar);
estEsN0 = 1.0/(2.0L * estvar + 1E-3);
for(i=0; i<n; i++)
llr[i] = 4.0L * estEsN0 * sd[i];
}
/*
Determine symbol likelihood from received QPSK symbols.
Notes:
1) We assume fading[] is real, it is also possible to compute
with complex fading, see CML library Demod2D.c source code.
2) Using floats instead of doubles, for stm32.
Testing shows good BERs with floats.
*/
void Demod2D(float symbol_likelihood[], /* output, M*number_symbols */
COMP r[], /* received QPSK symbols, number_symbols */
COMP S_matrix[], /* constellation of size M */
float EsNo,
float fading[], /* real fading values, number_symbols */
float mean_amp,
int number_symbols)
{
int M=QPSK_CONSTELLATION_SIZE;
int i,j;
float tempsr, tempsi, Er, Ei;
/* determine output */
for (i=0;i<number_symbols;i++) { /* go through each received symbol */
for (j=0;j<M;j++) { /* each postulated symbol */
tempsr = fading[i]*S_matrix[j].real/mean_amp;
tempsi = fading[i]*S_matrix[j].imag/mean_amp;
Er = r[i].real/mean_amp - tempsr;
Ei = r[i].imag/mean_amp - tempsi;
symbol_likelihood[i*M+j] = -EsNo*(Er*Er+Ei*Ei);
//printf("symbol_likelihood[%d][%d] = %f\n", i,j,symbol_likelihood[i*M+j]);
}
//exit(0);
}
}
void Somap(float bit_likelihood[], /* number_bits, bps*number_symbols */
float symbol_likelihood[], /* M*number_symbols */
int number_symbols)
{
int M=QPSK_CONSTELLATION_SIZE, bps = QPSK_BITS_PER_SYMBOL;
int n,i,j,k,mask;
float *num = new float[bps];
float *den = new float[bps];
float metric;
for (n=0; n<number_symbols; n++) { /* loop over symbols */
for (k=0;k<bps;k++) {
/* initialize */
num[k] = -1000000;
den[k] = -1000000;
}
for (i=0;i<M;i++) {
metric = symbol_likelihood[n*M+i]; /* channel metric for this symbol */
mask = 1 << (bps - 1);
for (j=0;j<bps;j++) {
mask = mask >> 1;
}
mask = 1 << (bps - 1);
for (k=0;k<bps;k++) { /* loop over bits */
if (mask&i) {
/* this bit is a one */
num[k] = max_star0( num[k], metric );
} else {
/* this bit is a zero */
den[k] = max_star0( den[k], metric );
}
mask = mask >> 1;
}
}
for (k=0;k<bps;k++) {
bit_likelihood[bps*n+k] = num[k] - den[k];
}
}
delete[] den;
delete[] num;
}
void symbols_to_llrs(float llr[], COMP rx_qpsk_symbols[], float rx_amps[], float EsNo, float mean_amp, int nsyms) {
int i;
float *symbol_likelihood = new float[nsyms*QPSK_CONSTELLATION_SIZE];
float *bit_likelihood = new float[nsyms*QPSK_BITS_PER_SYMBOL];
Demod2D(symbol_likelihood, rx_qpsk_symbols, S_matrix, EsNo, rx_amps, mean_amp, nsyms);
Somap(bit_likelihood, symbol_likelihood, nsyms);
for(i=0; i<nsyms*QPSK_BITS_PER_SYMBOL; i++) {
llr[i] = -bit_likelihood[i];
}
delete[] bit_likelihood;
delete[] symbol_likelihood;
}
void ldpc_print_info(struct LDPC *ldpc) {
fprintf(stderr, "ldpc->max_iter = %d\n", ldpc->max_iter);
fprintf(stderr, "ldpc->dec_type = %d\n", ldpc->dec_type);
fprintf(stderr, "ldpc->q_scale_factor = %d\n", ldpc->q_scale_factor);
fprintf(stderr, "ldpc->r_scale_factor = %d\n", ldpc->r_scale_factor);
fprintf(stderr, "ldpc->CodeLength = %d\n", ldpc->CodeLength);
fprintf(stderr, "ldpc->NumberParityBits = %d\n", ldpc->NumberParityBits);
fprintf(stderr, "ldpc->NumberRowsHcols = %d\n", ldpc->NumberRowsHcols);
fprintf(stderr, "ldpc->max_row_weight = %d\n", ldpc->max_row_weight);
fprintf(stderr, "ldpc->max_col_weight = %d\n", ldpc->max_col_weight);
fprintf(stderr, "ldpc->data_bits_per_frame = %d\n", ldpc->data_bits_per_frame);
fprintf(stderr, "ldpc->coded_bits_per_frame = %d\n", ldpc->coded_bits_per_frame);
fprintf(stderr, "ldpc->coded_syms_per_frame = %d\n", ldpc->coded_syms_per_frame);
}
} // FreeDV
/* vi:set ts=4 et sts=4: */

View File

@ -1,51 +0,0 @@
/*
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

File diff suppressed because it is too large Load Diff

View File

@ -1,137 +0,0 @@
/*---------------------------------------------------------------------------*\
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 float(M_PI / 4.0f)
#define cmplx(value) (std::complex<float>{cosf(value), sinf(value)})
#define cmplxconj(value) (std::complex<float>{cosf(value), -sinf(value)})
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

View File

@ -1,57 +0,0 @@
/* Generate using fir1(47,1/2) in Octave */
namespace FreeDV
{
static const float fdmdv_os_filter[]= {
-0.0008215855034550382,
-0.0007833023901802921,
0.001075563790768233,
0.001199092367787555,
-0.001765309502928316,
-0.002055372115328064,
0.002986877604154257,
0.003462567920638414,
-0.004856570111126334,
-0.005563143845031497,
0.007533613299748122,
0.008563932468880897,
-0.01126857129039911,
-0.01280782411693687,
0.01651443896361847,
0.01894875110322284,
-0.02421604439474981,
-0.02845107338464062,
0.03672973563400258,
0.04542046150312214,
-0.06189165826716491,
-0.08721876380763803,
0.1496157094199961,
0.4497962274137046,
0.4497962274137046,
0.1496157094199961,
-0.08721876380763803,
-0.0618916582671649,
0.04542046150312216,
0.03672973563400257,
-0.02845107338464062,
-0.02421604439474984,
0.01894875110322284,
0.01651443896361848,
-0.01280782411693687,
-0.0112685712903991,
0.008563932468880899,
0.007533613299748123,
-0.005563143845031501,
-0.004856570111126346,
0.003462567920638419,
0.002986877604154259,
-0.002055372115328063,
-0.001765309502928318,
0.001199092367787557,
0.001075563790768233,
-0.0007833023901802925,
-0.0008215855034550383
};
} // FreeDV

View File

@ -1,223 +0,0 @@
// phi0.c
//
// An approximation of the function
//
// This file is generated by the gen_phi0 scritps
// Any changes should be made to that file, not this one
#include <stdint.h>
#define SI16(f) ((int32_t)(f * (1<<16)))
namespace FreeDV
{
float phi0( float xf ) {
int32_t x = SI16(xf);
if (x >= SI16(10.0f)) return(0.0f);
else {
if (x >= SI16(5.0f)) {
int i = 19 - (x >> 15);
switch (i) {
case 0: return(0.000116589f); // (9.5)
case 1: return(0.000192223f); // (9.0)
case 2: return(0.000316923f); // (8.5)
case 3: return(0.000522517f); // (8.0)
case 4: return(0.000861485f); // (7.5)
case 5: return(0.001420349f); // (7.0)
case 6: return(0.002341760f); // (6.5)
case 7: return(0.003860913f); // (6.0)
case 8: return(0.006365583f); // (5.5)
case 9: return(0.010495133f); // (5.0)
}
}
else {
if (x >= SI16(1.0f)) {
int i = 79 - (x >> 12);
switch (i) {
case 0: return(0.013903889f); // (4.9375)
case 1: return(0.014800644f); // (4.8750)
case 2: return(0.015755242f); // (4.8125)
case 3: return(0.016771414f); // (4.7500)
case 4: return(0.017853133f); // (4.6875)
case 5: return(0.019004629f); // (4.6250)
case 6: return(0.020230403f); // (4.5625)
case 7: return(0.021535250f); // (4.5000)
case 8: return(0.022924272f); // (4.4375)
case 9: return(0.024402903f); // (4.3750)
case 10: return(0.025976926f); // (4.3125)
case 11: return(0.027652501f); // (4.2500)
case 12: return(0.029436184f); // (4.1875)
case 13: return(0.031334956f); // (4.1250)
case 14: return(0.033356250f); // (4.0625)
case 15: return(0.035507982f); // (4.0000)
case 16: return(0.037798579f); // (3.9375)
case 17: return(0.040237016f); // (3.8750)
case 18: return(0.042832850f); // (3.8125)
case 19: return(0.045596260f); // (3.7500)
case 20: return(0.048538086f); // (3.6875)
case 21: return(0.051669874f); // (3.6250)
case 22: return(0.055003924f); // (3.5625)
case 23: return(0.058553339f); // (3.5000)
case 24: return(0.062332076f); // (3.4375)
case 25: return(0.066355011f); // (3.3750)
case 26: return(0.070637993f); // (3.3125)
case 27: return(0.075197917f); // (3.2500)
case 28: return(0.080052790f); // (3.1875)
case 29: return(0.085221814f); // (3.1250)
case 30: return(0.090725463f); // (3.0625)
case 31: return(0.096585578f); // (3.0000)
case 32: return(0.102825462f); // (2.9375)
case 33: return(0.109469985f); // (2.8750)
case 34: return(0.116545700f); // (2.8125)
case 35: return(0.124080967f); // (2.7500)
case 36: return(0.132106091f); // (2.6875)
case 37: return(0.140653466f); // (2.6250)
case 38: return(0.149757747f); // (2.5625)
case 39: return(0.159456024f); // (2.5000)
case 40: return(0.169788027f); // (2.4375)
case 41: return(0.180796343f); // (2.3750)
case 42: return(0.192526667f); // (2.3125)
case 43: return(0.205028078f); // (2.2500)
case 44: return(0.218353351f); // (2.1875)
case 45: return(0.232559308f); // (2.1250)
case 46: return(0.247707218f); // (2.0625)
case 47: return(0.263863255f); // (2.0000)
case 48: return(0.281099022f); // (1.9375)
case 49: return(0.299492155f); // (1.8750)
case 50: return(0.319127030f); // (1.8125)
case 51: return(0.340095582f); // (1.7500)
case 52: return(0.362498271f); // (1.6875)
case 53: return(0.386445235f); // (1.6250)
case 54: return(0.412057648f); // (1.5625)
case 55: return(0.439469363f); // (1.5000)
case 56: return(0.468828902f); // (1.4375)
case 57: return(0.500301872f); // (1.3750)
case 58: return(0.534073947f); // (1.3125)
case 59: return(0.570354566f); // (1.2500)
case 60: return(0.609381573f); // (1.1875)
case 61: return(0.651427083f); // (1.1250)
case 62: return(0.696805010f); // (1.0625)
case 63: return(0.745880827f); // (1.0000)
}
}
else {
if (x > SI16(0.007812f)) {
if (x > SI16(0.088388f)) {
if (x > SI16(0.250000f)) {
if (x > SI16(0.500000f)) {
if (x > SI16(0.707107f)) {
return(0.922449644f);
} else {
return(1.241248638f);
}
} else {
if (x > SI16(0.353553f)) {
return(1.573515241f);
} else {
return(1.912825912f);
}
}
} else {
if (x > SI16(0.125000f)) {
if (x > SI16(0.176777f)) {
return(2.255740095f);
} else {
return(2.600476919f);
}
} else {
return(2.946130351f);
}
}
} else {
if (x > SI16(0.022097f)) {
if (x > SI16(0.044194f)) {
if (x > SI16(0.062500f)) {
return(3.292243417f);
} else {
return(3.638586634f);
}
} else {
if (x > SI16(0.031250f)) {
return(3.985045009f);
} else {
return(4.331560985f);
}
}
} else {
if (x > SI16(0.011049f)) {
if (x > SI16(0.015625f)) {
return(4.678105767f);
} else {
return(5.024664952f);
}
} else {
return(5.371231340f);
}
}
}
} else {
if (x > SI16(0.000691f)) {
if (x > SI16(0.001953f)) {
if (x > SI16(0.003906f)) {
if (x > SI16(0.005524f)) {
return(5.717801329f);
} else {
return(6.064373119f);
}
} else {
if (x > SI16(0.002762f)) {
return(6.410945809f);
} else {
return(6.757518949f);
}
}
} else {
if (x > SI16(0.000977f)) {
if (x > SI16(0.001381f)) {
return(7.104092314f);
} else {
return(7.450665792f);
}
} else {
return(7.797239326f);
}
}
} else {
if (x > SI16(0.000173f)) {
if (x > SI16(0.000345f)) {
if (x > SI16(0.000488f)) {
return(8.143812888f);
} else {
return(8.490386464f);
}
} else {
if (x > SI16(0.000244f)) {
return(8.836960047f);
} else {
return(9.183533634f);
}
}
} else {
if (x > SI16(0.000086f)) {
if (x > SI16(0.000122f)) {
return(9.530107222f);
} else {
return(9.876680812f);
}
} else {
return(10.000000000f);
}
}
}
}
}
}
}
return(10.0f);
}
} // FreeDV

View File

@ -1,11 +0,0 @@
// phi0.h
#ifndef PHI0_H
#define PHI0_H
namespace FreeDV {
extern float phi0( float xf );
} // FreeDV
#endif

View File

@ -1,46 +0,0 @@
/* Generated by pilot_coeff_file() Octave function */
// const removed since this provides gain
// on the STM32F4 platform
namespace FreeDV
{
#ifdef CORTEX_M4
/* const */ float pilot_coeff[]={
#else
const float pilot_coeff[]={
#endif
0.00223001,
0.00301037,
0.00471258,
0.0075934,
0.0118145,
0.0174153,
0.0242969,
0.0322204,
0.0408199,
0.0496286,
0.0581172,
0.0657392,
0.0719806,
0.0764066,
0.0787022,
0.0787022,
0.0764066,
0.0719806,
0.0657392,
0.0581172,
0.0496286,
0.0408199,
0.0322204,
0.0242969,
0.0174153,
0.0118145,
0.0075934,
0.00471258,
0.00301037,
0.00223001
};
} // FreeDV

View File

@ -1,11 +0,0 @@
/* Generated by write_pilot_file() Octave function */
namespace FreeDV
{
float pilots_coh[][PILOTS_NC]={
{ 1.000000, -1.000000, 1.000000, -1.000000, 1.000000, -1.000000, -1.000000},
{ -1.000000, 1.000000, 1.000000, -1.000000, 1.000000, 1.000000, 1.000000}
};
} // FreeDV

View File

@ -1,969 +0,0 @@
/* Generated by rn_file() Octave function */
namespace FreeDV
{
const float gt_alpha5_root[]={
2.86997e-05,
2.2286e-05,
1.82863e-05,
1.42303e-05,
1.04905e-05,
6.70859e-06,
3.05918e-06,
-6.22187e-07,
-4.22748e-06,
-7.85603e-06,
-1.14317e-05,
-1.50227e-05,
-1.85712e-05,
-2.21275e-05,
-2.56455e-05,
-2.91642e-05,
-3.26453e-05,
-3.61199e-05,
-3.95556e-05,
-4.29778e-05,
-4.63581e-05,
-4.97179e-05,
-5.3032e-05,
-5.63184e-05,
-5.95548e-05,
-6.27565e-05,
-6.59032e-05,
-6.90085e-05,
-7.20538e-05,
-7.50509e-05,
-7.7983e-05,
-8.08605e-05,
-8.36678e-05,
-8.64141e-05,
-8.9085e-05,
-9.16888e-05,
-9.42119e-05,
-9.66619e-05,
-9.9026e-05,
-0.000101311,
-0.000103505,
-0.000105614,
-0.000107627,
-0.00010955,
-0.000111372,
-0.000113099,
-0.00011472,
-0.000116241,
-0.000117652,
-0.000118959,
-0.000120152,
-0.000121235,
-0.000122201,
-0.000123053,
-0.000123784,
-0.000124397,
-0.000124884,
-0.00012525,
-0.000125487,
-0.000125598,
-0.000125578,
-0.000125428,
-0.000125145,
-0.000124729,
-0.000124185,
-0.000123518,
-0.000122709,
-0.000121766,
-0.000120685,
-0.000119471,
-0.000118119,
-0.000116633,
-0.000115009,
-0.000113251,
-0.000111356,
-0.000109326,
-0.00010716,
-0.00010486,
-0.000102424,
-9.98553e-05,
-9.71528e-05,
-9.43199e-05,
-9.13551e-05,
-8.82623e-05,
-8.50404e-05,
-8.16936e-05,
-7.82211e-05,
-7.46271e-05,
-7.09109e-05,
-6.70773e-05,
-6.31256e-05,
-5.90607e-05,
-5.48823e-05,
-5.05954e-05,
-4.62001e-05,
-4.17016e-05,
-3.71002e-05,
-3.24015e-05,
-2.7606e-05,
-2.27195e-05,
-1.77428e-05,
-1.2682e-05,
-7.53795e-06,
-2.31702e-06,
2.97965e-06,
8.34567e-06,
1.37796e-05,
1.9275e-05,
2.483e-05,
3.04382e-05,
3.60975e-05,
4.18011e-05,
4.75467e-05,
5.33273e-05,
5.91403e-05,
6.49787e-05,
7.08393e-05,
7.67152e-05,
8.26029e-05,
8.84957e-05,
9.43895e-05,
0.000100278,
0.000106157,
0.00011202,
0.000117864,
0.000123681,
0.000129468,
0.000135218,
0.000140929,
0.000146583,
0.000152183,
0.000157725,
0.000163202,
0.000168608,
0.000173938,
0.000179183,
0.00018434,
0.0001894,
0.00019436,
0.000199211,
0.000203949,
0.000208568,
0.000213063,
0.000217426,
0.000221654,
0.00022574,
0.000229678,
0.000233463,
0.000237089,
0.000240551,
0.000243843,
0.000246959,
0.000249895,
0.000252644,
0.000255202,
0.000257562,
0.000259721,
0.000261672,
0.000263411,
0.000264933,
0.000266234,
0.000267308,
0.000268152,
0.00026876,
0.000269128,
0.000269253,
0.000269129,
0.000268754,
0.000268123,
0.000267232,
0.000266079,
0.000264658,
0.000262968,
0.000261006,
0.000258767,
0.000256251,
0.000253453,
0.000250373,
0.000247007,
0.000243354,
0.000239412,
0.00023518,
0.000230655,
0.000225837,
0.000220723,
0.000215314,
0.000209608,
0.000203605,
0.000197304,
0.000190706,
0.000183812,
0.000176621,
0.000169145,
0.000161363,
0.000153275,
0.000144895,
0.000136224,
0.000127266,
0.00011802,
0.000108491,
9.8679e-05,
8.85877e-05,
7.82196e-05,
6.7577e-05,
5.66636e-05,
4.54822e-05,
3.40369e-05,
2.23311e-05,
1.03695e-05,
-1.844e-06,
-1.43041e-05,
-2.70061e-05,
-3.99444e-05,
-5.31139e-05,
-6.65082e-05,
-8.01218e-05,
-9.39481e-05,
-0.000107981,
-0.000122213,
-0.000136638,
-0.000151248,
-0.000166036,
-0.000180995,
-0.000196115,
-0.00021139,
-0.000226811,
-0.000242369,
-0.000258056,
-0.000273861,
-0.000289776,
-0.000305792,
-0.000321898,
-0.000338084,
-0.000354342,
-0.00037066,
-0.000387027,
-0.000403434,
-0.00041987,
-0.000436324,
-0.000452784,
-0.00046924,
-0.00048568,
-0.000502091,
-0.000518464,
-0.000534785,
-0.000551043,
-0.000567225,
-0.000583319,
-0.000599314,
-0.000615196,
-0.000630955,
-0.000646575,
-0.000662049,
-0.000677361,
-0.000692506,
-0.000707464,
-0.00072229,
-0.000736922,
-0.000751266,
-0.000765372,
-0.000779217,
-0.000792798,
-0.000806094,
-0.000819098,
-0.000831793,
-0.000844168,
-0.000856207,
-0.000867898,
-0.000879227,
-0.00089018,
-0.000900744,
-0.000910906,
-0.000920652,
-0.00092997,
-0.000938844,
-0.000947263,
-0.000955214,
-0.000962682,
-0.000969654,
-0.000976119,
-0.000982062,
-0.00098747,
-0.000992332,
-0.000996634,
-0.00100036,
-0.00100351,
-0.00100606,
-0.001008,
-0.00100932,
-0.00101,
-0.00101005,
-0.00100943,
-0.00100816,
-0.0010062,
-0.00100356,
-0.00100021,
-0.000996162,
-0.000991392,
-0.000985892,
-0.000979654,
-0.000972668,
-0.000964925,
-0.000956415,
-0.000947131,
-0.000937065,
-0.000926208,
-0.000914552,
-0.00090209,
-0.000888816,
-0.000874721,
-0.0008598,
-0.000844046,
-0.000827453,
-0.000810015,
-0.000791726,
-0.000772581,
-0.000752576,
-0.000731704,
-0.000709965,
-0.00068735,
-0.000663865,
-0.000639509,
-0.000614269,
-0.000588146,
-0.000561139,
-0.000533246,
-0.000504468,
-0.000474802,
-0.000444251,
-0.000412813,
-0.00038049,
-0.000347281,
-0.000313189,
-0.000278215,
-0.000242361,
-0.000205629,
-0.000168024,
-0.000129546,
-9.02024e-05,
-4.99954e-05,
-8.93026e-06,
3.2988e-05,
7.57537e-05,
0.000119361,
0.000163804,
0.000209075,
0.000255167,
0.000302074,
0.000349786,
0.000398297,
0.000447596,
0.000497676,
0.000548526,
0.000600136,
0.000652497,
0.000705598,
0.000759427,
0.000813972,
0.000869223,
0.000925166,
0.000981789,
0.00103908,
0.00109702,
0.00115561,
0.00121482,
0.00127464,
0.00133505,
0.00139605,
0.00145762,
0.00151973,
0.00158238,
0.00164555,
0.00170922,
0.00177337,
0.00183799,
0.00190305,
0.00196854,
0.00203445,
0.00210075,
0.00216742,
0.00223445,
0.00230181,
0.00236949,
0.00243747,
0.00250572,
0.00257423,
0.00264296,
0.00271192,
0.00278107,
0.00285039,
0.00291986,
0.00298947,
0.00305918,
0.00312898,
0.00319884,
0.00326874,
0.00333866,
0.00340857,
0.00347846,
0.00354831,
0.00361808,
0.00368775,
0.00375731,
0.00382673,
0.00389599,
0.00396506,
0.00403393,
0.00410256,
0.00417094,
0.00423904,
0.00430684,
0.00437431,
0.00444144,
0.0045082,
0.00457457,
0.00464052,
0.00470603,
0.00477108,
0.00483565,
0.00489972,
0.00496325,
0.00502623,
0.00508865,
0.00515046,
0.00521166,
0.00527223,
0.00533213,
0.00539135,
0.00544987,
0.00550766,
0.00556472,
0.005621,
0.00567651,
0.00573121,
0.00578508,
0.00583811,
0.00589028,
0.00594157,
0.00599196,
0.00604143,
0.00608996,
0.00613754,
0.00618415,
0.00622977,
0.00627439,
0.00631798,
0.00636054,
0.00640204,
0.0064425,
0.00648186,
0.00652009,
0.00655722,
0.00659322,
0.00662808,
0.00666179,
0.00669433,
0.00672571,
0.00675589,
0.00678488,
0.00681266,
0.00683921,
0.00686454,
0.00688863,
0.00691147,
0.00693305,
0.00695336,
0.0069724,
0.00699016,
0.00700663,
0.00702181,
0.00703569,
0.00704826,
0.00705952,
0.00706947,
0.00707809,
0.0070854,
0.00709138,
0.00709604,
0.00709937,
0.00710136,
0.00710203,
0.00710136,
0.00709937,
0.00709604,
0.00709138,
0.0070854,
0.00707809,
0.00706947,
0.00705952,
0.00704826,
0.00703569,
0.00702181,
0.00700663,
0.00699016,
0.0069724,
0.00695336,
0.00693305,
0.00691147,
0.00688863,
0.00686454,
0.00683921,
0.00681266,
0.00678488,
0.00675589,
0.00672571,
0.00669433,
0.00666179,
0.00662808,
0.00659322,
0.00655722,
0.00652009,
0.00648186,
0.0064425,
0.00640204,
0.00636054,
0.00631798,
0.00627439,
0.00622977,
0.00618415,
0.00613754,
0.00608996,
0.00604143,
0.00599196,
0.00594157,
0.00589028,
0.00583811,
0.00578508,
0.00573121,
0.00567651,
0.005621,
0.00556472,
0.00550766,
0.00544987,
0.00539135,
0.00533213,
0.00527223,
0.00521166,
0.00515046,
0.00508865,
0.00502623,
0.00496325,
0.00489972,
0.00483565,
0.00477108,
0.00470603,
0.00464052,
0.00457457,
0.0045082,
0.00444144,
0.00437431,
0.00430684,
0.00423904,
0.00417094,
0.00410256,
0.00403393,
0.00396506,
0.00389599,
0.00382673,
0.00375731,
0.00368775,
0.00361808,
0.00354831,
0.00347846,
0.00340857,
0.00333866,
0.00326874,
0.00319884,
0.00312898,
0.00305918,
0.00298947,
0.00291986,
0.00285039,
0.00278107,
0.00271192,
0.00264296,
0.00257423,
0.00250572,
0.00243747,
0.00236949,
0.00230181,
0.00223445,
0.00216742,
0.00210075,
0.00203445,
0.00196854,
0.00190305,
0.00183799,
0.00177337,
0.00170922,
0.00164555,
0.00158238,
0.00151973,
0.00145762,
0.00139605,
0.00133505,
0.00127464,
0.00121482,
0.00115561,
0.00109702,
0.00103908,
0.000981789,
0.000925166,
0.000869223,
0.000813972,
0.000759427,
0.000705598,
0.000652497,
0.000600136,
0.000548526,
0.000497676,
0.000447596,
0.000398297,
0.000349786,
0.000302074,
0.000255167,
0.000209075,
0.000163804,
0.000119361,
7.57537e-05,
3.2988e-05,
-8.93026e-06,
-4.99954e-05,
-9.02024e-05,
-0.000129546,
-0.000168024,
-0.000205629,
-0.000242361,
-0.000278215,
-0.000313189,
-0.000347281,
-0.00038049,
-0.000412813,
-0.000444251,
-0.000474802,
-0.000504468,
-0.000533246,
-0.000561139,
-0.000588146,
-0.000614269,
-0.000639509,
-0.000663865,
-0.00068735,
-0.000709965,
-0.000731704,
-0.000752576,
-0.000772581,
-0.000791726,
-0.000810015,
-0.000827453,
-0.000844046,
-0.0008598,
-0.000874721,
-0.000888816,
-0.00090209,
-0.000914552,
-0.000926208,
-0.000937065,
-0.000947131,
-0.000956415,
-0.000964925,
-0.000972668,
-0.000979654,
-0.000985892,
-0.000991392,
-0.000996162,
-0.00100021,
-0.00100356,
-0.0010062,
-0.00100816,
-0.00100943,
-0.00101005,
-0.00101,
-0.00100932,
-0.001008,
-0.00100606,
-0.00100351,
-0.00100036,
-0.000996634,
-0.000992332,
-0.00098747,
-0.000982062,
-0.000976119,
-0.000969654,
-0.000962682,
-0.000955214,
-0.000947263,
-0.000938844,
-0.00092997,
-0.000920652,
-0.000910906,
-0.000900744,
-0.00089018,
-0.000879227,
-0.000867898,
-0.000856207,
-0.000844168,
-0.000831793,
-0.000819098,
-0.000806094,
-0.000792798,
-0.000779217,
-0.000765372,
-0.000751266,
-0.000736922,
-0.00072229,
-0.000707464,
-0.000692506,
-0.000677361,
-0.000662049,
-0.000646575,
-0.000630955,
-0.000615196,
-0.000599314,
-0.000583319,
-0.000567225,
-0.000551043,
-0.000534785,
-0.000518464,
-0.000502091,
-0.00048568,
-0.00046924,
-0.000452784,
-0.000436324,
-0.00041987,
-0.000403434,
-0.000387027,
-0.00037066,
-0.000354342,
-0.000338084,
-0.000321898,
-0.000305792,
-0.000289776,
-0.000273861,
-0.000258056,
-0.000242369,
-0.000226811,
-0.00021139,
-0.000196115,
-0.000180995,
-0.000166036,
-0.000151248,
-0.000136638,
-0.000122213,
-0.000107981,
-9.39481e-05,
-8.01218e-05,
-6.65082e-05,
-5.31139e-05,
-3.99444e-05,
-2.70061e-05,
-1.43041e-05,
-1.844e-06,
1.03695e-05,
2.23311e-05,
3.40369e-05,
4.54822e-05,
5.66636e-05,
6.7577e-05,
7.82196e-05,
8.85877e-05,
9.8679e-05,
0.000108491,
0.00011802,
0.000127266,
0.000136224,
0.000144895,
0.000153275,
0.000161363,
0.000169145,
0.000176621,
0.000183812,
0.000190706,
0.000197304,
0.000203605,
0.000209608,
0.000215314,
0.000220723,
0.000225837,
0.000230655,
0.00023518,
0.000239412,
0.000243354,
0.000247007,
0.000250373,
0.000253453,
0.000256251,
0.000258767,
0.000261006,
0.000262968,
0.000264658,
0.000266079,
0.000267232,
0.000268123,
0.000268754,
0.000269129,
0.000269253,
0.000269128,
0.00026876,
0.000268152,
0.000267308,
0.000266234,
0.000264933,
0.000263411,
0.000261672,
0.000259721,
0.000257562,
0.000255202,
0.000252644,
0.000249895,
0.000246959,
0.000243843,
0.000240551,
0.000237089,
0.000233463,
0.000229678,
0.00022574,
0.000221654,
0.000217426,
0.000213063,
0.000208568,
0.000203949,
0.000199211,
0.00019436,
0.0001894,
0.00018434,
0.000179183,
0.000173938,
0.000168608,
0.000163202,
0.000157725,
0.000152183,
0.000146583,
0.000140929,
0.000135218,
0.000129468,
0.000123681,
0.000117864,
0.00011202,
0.000106157,
0.000100278,
9.43895e-05,
8.84957e-05,
8.26029e-05,
7.67152e-05,
7.08393e-05,
6.49787e-05,
5.91403e-05,
5.33273e-05,
4.75467e-05,
4.18011e-05,
3.60975e-05,
3.04382e-05,
2.483e-05,
1.9275e-05,
1.37796e-05,
8.34567e-06,
2.97965e-06,
-2.31702e-06,
-7.53795e-06,
-1.2682e-05,
-1.77428e-05,
-2.27195e-05,
-2.7606e-05,
-3.24015e-05,
-3.71002e-05,
-4.17016e-05,
-4.62001e-05,
-5.05954e-05,
-5.48823e-05,
-5.90607e-05,
-6.31256e-05,
-6.70773e-05,
-7.09109e-05,
-7.46271e-05,
-7.82211e-05,
-8.16936e-05,
-8.50404e-05,
-8.82623e-05,
-9.13551e-05,
-9.43199e-05,
-9.71528e-05,
-9.98553e-05,
-0.000102424,
-0.00010486,
-0.00010716,
-0.000109326,
-0.000111356,
-0.000113251,
-0.000115009,
-0.000116633,
-0.000118119,
-0.000119471,
-0.000120685,
-0.000121766,
-0.000122709,
-0.000123518,
-0.000124185,
-0.000124729,
-0.000125145,
-0.000125428,
-0.000125578,
-0.000125598,
-0.000125487,
-0.00012525,
-0.000124884,
-0.000124397,
-0.000123784,
-0.000123053,
-0.000122201,
-0.000121235,
-0.000120152,
-0.000118959,
-0.000117652,
-0.000116241,
-0.00011472,
-0.000113099,
-0.000111372,
-0.00010955,
-0.000107627,
-0.000105614,
-0.000103505,
-0.000101311,
-9.9026e-05,
-9.66619e-05,
-9.42119e-05,
-9.16888e-05,
-8.9085e-05,
-8.64141e-05,
-8.36678e-05,
-8.08605e-05,
-7.7983e-05,
-7.50509e-05,
-7.20538e-05,
-6.90085e-05,
-6.59032e-05,
-6.27565e-05,
-5.95548e-05,
-5.63184e-05,
-5.3032e-05,
-4.97179e-05,
-4.63581e-05,
-4.29778e-05,
-3.95556e-05,
-3.61199e-05,
-3.26453e-05,
-2.91642e-05,
-2.56455e-05,
-2.21275e-05,
-1.85712e-05,
-1.50227e-05,
-1.14317e-05,
-7.85603e-06,
-4.22748e-06,
-6.22187e-07,
3.05918e-06,
6.70859e-06,
1.04905e-05,
1.42303e-05,
1.82863e-05,
2.2286e-05
};
} // FreeDV

View File

@ -1,609 +0,0 @@
/* Generated by rn_file() Octave function */
namespace FreeDV
{
const float gt_alpha5_root_coh[]={
4.05576e-05,
2.58255e-05,
1.58964e-05,
5.78773e-06,
-3.71244e-06,
-1.33229e-05,
-2.2664e-05,
-3.20611e-05,
-4.12734e-05,
-5.04935e-05,
-5.9545e-05,
-6.85565e-05,
-7.73902e-05,
-8.6137e-05,
-9.46835e-05,
-0.000103097,
-0.000111281,
-0.000119289,
-0.000127034,
-0.000134559,
-0.000141789,
-0.000148756,
-0.000155393,
-0.000161723,
-0.000167689,
-0.000173315,
-0.00017854,
-0.000183382,
-0.000187794,
-0.000191793,
-0.000195333,
-0.000198429,
-0.000201038,
-0.000203173,
-0.000204797,
-0.000205922,
-0.000206515,
-0.00020659,
-0.000206117,
-0.000205109,
-0.000203541,
-0.000201427,
-0.000198743,
-0.000195505,
-0.000191693,
-0.000187324,
-0.000182382,
-0.000176885,
-0.000170822,
-0.00016421,
-0.000157041,
-0.000149335,
-0.000141089,
-0.000132323,
-0.000123038,
-0.000113258,
-0.000102985,
-9.22439e-05,
-8.10442e-05,
-6.94109e-05,
-5.73536e-05,
-4.49012e-05,
-3.20661e-05,
-1.88794e-05,
-5.35615e-06,
8.47105e-06,
2.25833e-05,
3.69472e-05,
5.15418e-05,
6.63317e-05,
8.12934e-05,
9.63895e-05,
0.000111594,
0.000126869,
0.000142183,
0.000157497,
0.000172781,
0.000187996,
0.000203111,
0.000218088,
0.000232892,
0.000247474,
0.000261806,
0.000275847,
0.000289559,
0.000302903,
0.000315839,
0.00032833,
0.000340339,
0.000351824,
0.000362751,
0.00037308,
0.000382774,
0.000391795,
0.000400108,
0.000407675,
0.000414464,
0.000420437,
0.000425565,
0.000429812,
0.000433151,
0.000435544,
0.000436975,
0.000437401,
0.000436865,
0.000435237,
0.00043246,
0.000428592,
0.000423608,
0.000417497,
0.00041024,
0.000401823,
0.000392231,
0.000381449,
0.000369471,
0.000356284,
0.000341885,
0.000326267,
0.00030943,
0.000291373,
0.000272099,
0.000251612,
0.000229921,
0.000207034,
0.000182964,
0.000157726,
0.000131338,
0.000103821,
7.51956e-05,
4.54842e-05,
1.4721e-05,
-1.7067e-05,
-4.98479e-05,
-8.35883e-05,
-0.000118248,
-0.00015379,
-0.000190167,
-0.000227336,
-0.000265248,
-0.000303856,
-0.000343104,
-0.000382942,
-0.00042331,
-0.000464152,
-0.000505403,
-0.000547003,
-0.000588883,
-0.000630979,
-0.000673218,
-0.000715533,
-0.000757849,
-0.000800092,
-0.000842187,
-0.000884054,
-0.000925613,
-0.000966788,
-0.00100749,
-0.00104765,
-0.00108717,
-0.00112597,
-0.00116397,
-0.00120108,
-0.0012372,
-0.00127227,
-0.00130617,
-0.00133884,
-0.00137017,
-0.00140008,
-0.00142848,
-0.00145528,
-0.0014804,
-0.00150374,
-0.00152522,
-0.00154475,
-0.00156225,
-0.00157763,
-0.00159081,
-0.00160171,
-0.00161024,
-0.00161633,
-0.0016199,
-0.00162088,
-0.00161917,
-0.00161472,
-0.00160744,
-0.00159729,
-0.00158419,
-0.00156807,
-0.00154888,
-0.00152655,
-0.00150103,
-0.00147227,
-0.00144021,
-0.00140482,
-0.00136604,
-0.00132384,
-0.00127818,
-0.00122903,
-0.00117635,
-0.00112013,
-0.00106033,
-0.000996946,
-0.000929956,
-0.000859348,
-0.000785117,
-0.000707261,
-0.000625779,
-0.00054068,
-0.000451952,
-0.000359651,
-0.000263788,
-0.00016436,
-6.13947e-05,
4.5076e-05,
0.000155016,
0.000268384,
0.000385134,
0.000505217,
0.000628582,
0.000755171,
0.000884923,
0.00101777,
0.00115366,
0.00129249,
0.00143421,
0.00157873,
0.00172596,
0.00187583,
0.00202822,
0.00218306,
0.00234023,
0.00249965,
0.00266119,
0.00282475,
0.00299023,
0.00315749,
0.00332643,
0.00349691,
0.00366882,
0.00384202,
0.00401639,
0.0041918,
0.0043681,
0.00454516,
0.00472285,
0.00490101,
0.00507951,
0.00525821,
0.00543695,
0.0056156,
0.005794,
0.00597201,
0.00614947,
0.00632623,
0.00650216,
0.00667708,
0.00685086,
0.00702335,
0.00719439,
0.00736383,
0.00753153,
0.00769734,
0.00786111,
0.00802269,
0.00818194,
0.00833872,
0.00849289,
0.0086443,
0.00879283,
0.00893832,
0.00908066,
0.00921971,
0.00935534,
0.00948743,
0.00961585,
0.00974049,
0.00986123,
0.00997795,
0.0100905,
0.0101989,
0.0103029,
0.0104025,
0.0104976,
0.0105881,
0.0106738,
0.0107548,
0.010831,
0.0109022,
0.0109684,
0.0110295,
0.0110855,
0.0111364,
0.011182,
0.0112224,
0.0112575,
0.0112872,
0.0113115,
0.0113305,
0.0113441,
0.0113522,
0.0113549,
0.0113522,
0.0113441,
0.0113305,
0.0113115,
0.0112872,
0.0112575,
0.0112224,
0.011182,
0.0111364,
0.0110855,
0.0110295,
0.0109684,
0.0109022,
0.010831,
0.0107548,
0.0106738,
0.0105881,
0.0104976,
0.0104025,
0.0103029,
0.0101989,
0.0100905,
0.00997795,
0.00986123,
0.00974049,
0.00961585,
0.00948743,
0.00935534,
0.00921971,
0.00908066,
0.00893832,
0.00879283,
0.0086443,
0.00849289,
0.00833872,
0.00818194,
0.00802269,
0.00786111,
0.00769734,
0.00753153,
0.00736383,
0.00719439,
0.00702335,
0.00685086,
0.00667708,
0.00650216,
0.00632623,
0.00614947,
0.00597201,
0.005794,
0.0056156,
0.00543695,
0.00525821,
0.00507951,
0.00490101,
0.00472285,
0.00454516,
0.0043681,
0.0041918,
0.00401639,
0.00384202,
0.00366882,
0.00349691,
0.00332643,
0.00315749,
0.00299023,
0.00282475,
0.00266119,
0.00249965,
0.00234023,
0.00218306,
0.00202822,
0.00187583,
0.00172596,
0.00157873,
0.00143421,
0.00129249,
0.00115366,
0.00101777,
0.000884923,
0.000755171,
0.000628582,
0.000505217,
0.000385134,
0.000268384,
0.000155016,
4.5076e-05,
-6.13947e-05,
-0.00016436,
-0.000263788,
-0.000359651,
-0.000451952,
-0.00054068,
-0.000625779,
-0.000707261,
-0.000785117,
-0.000859348,
-0.000929956,
-0.000996946,
-0.00106033,
-0.00112013,
-0.00117635,
-0.00122903,
-0.00127818,
-0.00132384,
-0.00136604,
-0.00140482,
-0.00144021,
-0.00147227,
-0.00150103,
-0.00152655,
-0.00154888,
-0.00156807,
-0.00158419,
-0.00159729,
-0.00160744,
-0.00161472,
-0.00161917,
-0.00162088,
-0.0016199,
-0.00161633,
-0.00161024,
-0.00160171,
-0.00159081,
-0.00157763,
-0.00156225,
-0.00154475,
-0.00152522,
-0.00150374,
-0.0014804,
-0.00145528,
-0.00142848,
-0.00140008,
-0.00137017,
-0.00133884,
-0.00130617,
-0.00127227,
-0.0012372,
-0.00120108,
-0.00116397,
-0.00112597,
-0.00108717,
-0.00104765,
-0.00100749,
-0.000966788,
-0.000925613,
-0.000884054,
-0.000842187,
-0.000800092,
-0.000757849,
-0.000715533,
-0.000673218,
-0.000630979,
-0.000588883,
-0.000547003,
-0.000505403,
-0.000464152,
-0.00042331,
-0.000382942,
-0.000343104,
-0.000303856,
-0.000265248,
-0.000227336,
-0.000190167,
-0.00015379,
-0.000118248,
-8.35883e-05,
-4.98479e-05,
-1.7067e-05,
1.4721e-05,
4.54842e-05,
7.51956e-05,
0.000103821,
0.000131338,
0.000157726,
0.000182964,
0.000207034,
0.000229921,
0.000251612,
0.000272099,
0.000291373,
0.00030943,
0.000326267,
0.000341885,
0.000356284,
0.000369471,
0.000381449,
0.000392231,
0.000401823,
0.00041024,
0.000417497,
0.000423608,
0.000428592,
0.00043246,
0.000435237,
0.000436865,
0.000437401,
0.000436975,
0.000435544,
0.000433151,
0.000429812,
0.000425565,
0.000420437,
0.000414464,
0.000407675,
0.000400108,
0.000391795,
0.000382774,
0.00037308,
0.000362751,
0.000351824,
0.000340339,
0.00032833,
0.000315839,
0.000302903,
0.000289559,
0.000275847,
0.000261806,
0.000247474,
0.000232892,
0.000218088,
0.000203111,
0.000187996,
0.000172781,
0.000157497,
0.000142183,
0.000126869,
0.000111594,
9.63895e-05,
8.12934e-05,
6.63317e-05,
5.15418e-05,
3.69472e-05,
2.25833e-05,
8.47105e-06,
-5.35615e-06,
-1.88794e-05,
-3.20661e-05,
-4.49012e-05,
-5.73536e-05,
-6.94109e-05,
-8.10442e-05,
-9.22439e-05,
-0.000102985,
-0.000113258,
-0.000123038,
-0.000132323,
-0.000141089,
-0.000149335,
-0.000157041,
-0.00016421,
-0.000170822,
-0.000176885,
-0.000182382,
-0.000187324,
-0.000191693,
-0.000195505,
-0.000198743,
-0.000201427,
-0.000203541,
-0.000205109,
-0.000206117,
-0.00020659,
-0.000206515,
-0.000205922,
-0.000204797,
-0.000203173,
-0.000201038,
-0.000198429,
-0.000195333,
-0.000191793,
-0.000187794,
-0.000183382,
-0.00017854,
-0.000173315,
-0.000167689,
-0.000161723,
-0.000155393,
-0.000148756,
-0.000141789,
-0.000134559,
-0.000127034,
-0.000119289,
-0.000111281,
-0.000103097,
-9.46835e-05,
-8.6137e-05,
-7.73902e-05,
-6.85565e-05,
-5.9545e-05,
-5.04935e-05,
-4.12734e-05,
-3.20611e-05,
-2.2664e-05,
-1.33229e-05,
-3.71244e-06,
5.78773e-06,
1.58964e-05,
2.58255e-05
};
} // FreeDV

View File

@ -1,40 +0,0 @@
/* Generated by rxdec_file() Octave function */
namespace FreeDV
{
const float rxdec_coeff[]={
-0.00125472,
-0.00204605,
-0.0019897,
0.000163906,
0.00490937,
0.00986375,
0.0096718,
-0.000480351,
-0.019311,
-0.0361822,
-0.0341251,
0.000827866,
0.0690577,
0.152812,
0.222115,
0.249004,
0.222115,
0.152812,
0.0690577,
0.000827866,
-0.0341251,
-0.0361822,
-0.019311,
-0.000480351,
0.0096718,
0.00986375,
0.00490937,
0.000163906,
-0.0019897,
-0.00204605,
-0.00125472
};
} // FreeDV

View File

@ -1,170 +0,0 @@
/* Generated by test_bits_file() Octave function */
namespace FreeDV
{
const int test_bits[]={
0,
1,
1,
0,
0,
0,
1,
1,
0,
0,
1,
0,
1,
0,
0,
1,
0,
1,
1,
0,
0,
1,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
1,
0,
1,
1,
0,
0,
1,
1,
1,
0,
1,
1,
0,
1,
1,
1,
1,
1,
0,
0,
1,
0,
0,
1,
1,
1,
0,
0,
1,
1,
1,
0,
0,
0,
0,
1,
1,
1,
0,
0,
1,
1,
1,
1,
1,
0,
1,
1,
1,
0,
0,
1,
1,
0,
1,
1,
1,
1,
1,
1,
1,
0,
0,
1,
1,
0,
1,
0,
0,
0,
1,
1,
1,
0,
0,
0,
0,
1,
1,
1,
1,
1,
0,
1,
1,
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
0,
1,
1,
0,
0,
0,
1,
0,
1,
1,
1,
0,
1
};
} // FreeDV

View File

@ -1,569 +0,0 @@
/* Generated by test_bits_coh_file() Octave function */
namespace FreeDV
{
const int test_bits_coh[]={
0,
1,
1,
0,
0,
0,
1,
1,
0,
0,
1,
0,
1,
0,
0,
1,
0,
1,
1,
0,
0,
1,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
1,
0,
1,
1,
0,
0,
1,
1,
1,
0,
1,
1,
0,
1,
1,
1,
1,
1,
0,
0,
1,
0,
0,
1,
1,
1,
0,
0,
1,
1,
1,
0,
0,
0,
0,
1,
1,
1,
0,
0,
1,
1,
1,
1,
1,
0,
1,
1,
1,
0,
0,
1,
1,
0,
1,
1,
1,
1,
1,
1,
1,
0,
0,
1,
1,
0,
1,
0,
0,
0,
1,
1,
1,
0,
0,
0,
0,
1,
1,
1,
1,
1,
0,
1,
1,
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
0,
1,
1,
0,
0,
0,
1,
0,
1,
1,
1,
0,
1,
1,
1,
0,
1,
0,
1,
0,
1,
0,
0,
1,
1,
0,
1,
0,
1,
1,
0,
0,
0,
1,
0,
1,
1,
1,
0,
1,
1,
1,
1,
0,
0,
0,
1,
0,
0,
0,
1,
0,
0,
0,
1,
1,
0,
0,
0,
1,
1,
0,
0,
1,
1,
1,
0,
1,
1,
0,
1,
0,
1,
0,
0,
1,
0,
1,
1,
1,
0,
0,
0,
1,
1,
1,
1,
0,
1,
0,
0,
0,
1,
1,
1,
0,
1,
1,
0,
1,
0,
0,
0,
1,
1,
1,
0,
0,
1,
1,
0,
1,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
1,
0,
1,
0,
1,
1,
0,
0,
0,
0,
1,
0,
0,
1,
0,
1,
0,
0,
0,
1,
1,
1,
0,
0,
1,
1,
1,
1,
1,
0,
1,
0,
0,
0,
0,
1,
0,
1,
1,
1,
0,
0,
0,
0,
1,
1,
0,
0,
1,
1,
1,
0,
0,
0,
0,
1,
0,
0,
1,
0,
1,
0,
1,
0,
1,
1,
0,
1,
0,
1,
1,
1,
0,
0,
1,
1,
0,
1,
0,
1,
0,
0,
1,
1,
1,
1,
1,
1,
0,
0,
0,
1,
1,
0,
0,
1,
1,
1,
1,
1,
0,
0,
0,
0,
0,
1,
0,
1,
0,
0,
0,
0,
0,
1,
0,
0,
1,
0,
0,
1,
1,
1,
0,
1,
1,
0,
0,
0,
0,
0,
1,
1,
1,
0,
1,
0,
0,
1,
1,
0,
1,
1,
0,
1,
1,
0,
1,
1,
1,
1,
1,
1,
1,
0,
0,
0,
1,
1,
0,
1,
1,
0,
1,
0,
1,
0,
1,
1,
1,
0,
1,
1,
0,
1,
1,
1,
1,
0,
1,
1,
0,
1,
0,
0,
0,
0,
1,
1,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
1,
1,
0,
0,
1,
0,
1,
0,
1,
1,
1,
1,
1,
0,
1,
1,
1,
0,
0,
0,
1,
0,
1,
1,
1,
1,
1,
0,
1,
1,
0,
1,
0,
1,
0,
0,
0,
0,
0,
1,
1,
0,
1,
0,
0,
0,
0,
1,
1,
1,
1,
1,
0,
1,
0,
1,
1,
0,
0,
1,
1,
0,
0,
0,
0,
0,
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
1,
1,
1,
0,
0,
1,
1,
1,
0
};
} // FreeDV

View File

@ -13,23 +13,20 @@ set(freedv_HEADERS
)
include_directories(
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
${CMAKE_SOURCE_DIR}/libfreedv
${CODEC2_INCLUDE_DIR}
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
${CODEC2_INCLUDE_DIR}
)
if(NOT SERVER_MODE)
set(freedv_SOURCES
${freedv_SOURCES}
freedvdemodgui.cpp
freedvdemodgui.ui
freedvdemodgui.ui
)
set(freedv_HEADERS
${freedv_HEADERS}
freedvdemodgui.h
)
set(TARGET_NAME demodfreedv)
set(TARGET_LIB "Qt5::Widgets")
set(TARGET_LIB_GUI "sdrgui")
@ -50,13 +47,12 @@ if(ENABLE_EXTERNAL_LIBRARIES)
endif()
target_link_libraries(${TARGET_NAME}
Qt5::Core
${TARGET_LIB}
Qt5::Core
${TARGET_LIB}
sdrbase
${TARGET_LIB_GUI}
swagger
freedv
${CODEC2_LIBRARIES}
swagger
${CODEC2_LIBRARIES}
)
install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER})

View File

@ -23,7 +23,8 @@
#include <QNetworkReply>
#include <QBuffer>
#include "libfreedv.h"
#include "codec2/freedv_api.h"
#include "codec2/modem_stats.h"
#include "SWGChannelSettings.h"
#include "SWGFreeDVDemodSettings.h"
@ -68,12 +69,12 @@ void FreeDVDemod::FreeDVStats::init()
m_fps = 1;
}
void FreeDVDemod::FreeDVStats::collect(struct FreeDV::freedv *freeDV)
void FreeDVDemod::FreeDVStats::collect(struct freedv *freeDV)
{
struct FreeDV::MODEM_STATS stats;
struct MODEM_STATS stats;
FreeDV::freedv_get_modem_extended_stats(freeDV, &stats);
m_totalBitErrors = FreeDV::freedv_get_total_bit_errors(freeDV);
freedv_get_modem_extended_stats(freeDV, &stats);
m_totalBitErrors = freedv_get_total_bit_errors(freeDV);
m_clockOffset = stats.clock_offset;
m_freqOffset = stats.foff;
m_syncMetric = stats.sync_metric;
@ -404,7 +405,7 @@ bool FreeDVDemod::handleMessage(const Message& cmd)
{
qDebug("FreeDVDemod::handleMessage: MsgResyncFreeDVDemod");
m_settingsMutex.lock();
FreeDV::freedv_set_sync(m_freeDV, FreeDV::unsync);
freedv_set_sync(m_freeDV, FREEDV_SYNC_UNSYNC);
m_settingsMutex.unlock();
return true;
}
@ -463,7 +464,7 @@ void FreeDVDemod::pushSampleToDV(int16_t sample)
if (m_iModem == m_nin)
{
int nout = FreeDV::freedv_rx(m_freeDV, m_speechOut, m_modIn);
int nout = freedv_rx(m_freeDV, m_speechOut, m_modIn);
m_freeDVStats.collect(m_freeDV);
m_freeDVSNR.accumulate(m_freeDVStats.m_snrEst);
@ -583,7 +584,7 @@ void FreeDVDemod::applyFreeDVMode(FreeDVDemodSettings::FreeDVMode mode)
// FreeDV object
if (m_freeDV) {
FreeDV::freedv_close(m_freeDV);
freedv_close(m_freeDV);
}
int fdv_mode = -1;
@ -610,32 +611,32 @@ void FreeDVDemod::applyFreeDVMode(FreeDVDemodSettings::FreeDVMode mode)
if (fdv_mode == FREEDV_MODE_700D)
{
struct FreeDV::freedv_advanced adv;
struct freedv_advanced adv;
adv.interleave_frames = 1;
m_freeDV = FreeDV::freedv_open_advanced(fdv_mode, &adv);
m_freeDV = freedv_open_advanced(fdv_mode, &adv);
}
else
{
m_freeDV = FreeDV::freedv_open(fdv_mode);
m_freeDV = freedv_open(fdv_mode);
}
if (m_freeDV)
{
FreeDV::freedv_set_test_frames(m_freeDV, 0);
FreeDV::freedv_set_snr_squelch_thresh(m_freeDV, -100.0);
FreeDV::freedv_set_squelch_en(m_freeDV, 0);
FreeDV::freedv_set_clip(m_freeDV, 0);
FreeDV::freedv_set_ext_vco(m_freeDV, 0);
FreeDV::freedv_set_sync(m_freeDV, FreeDV::manualsync);
freedv_set_test_frames(m_freeDV, 0);
freedv_set_snr_squelch_thresh(m_freeDV, -100.0);
freedv_set_squelch_en(m_freeDV, 0);
freedv_set_clip(m_freeDV, 0);
freedv_set_ext_vco(m_freeDV, 0);
freedv_set_sync(m_freeDV, FREEDV_SYNC_MANUAL);
FreeDV::freedv_set_callback_txt(m_freeDV, nullptr, nullptr, nullptr);
FreeDV::freedv_set_callback_protocol(m_freeDV, nullptr, nullptr, nullptr);
FreeDV::freedv_set_callback_data(m_freeDV, nullptr, nullptr, nullptr);
freedv_set_callback_txt(m_freeDV, nullptr, nullptr, nullptr);
freedv_set_callback_protocol(m_freeDV, nullptr, nullptr, nullptr);
freedv_set_callback_data(m_freeDV, nullptr, nullptr, nullptr);
int nSpeechSamples = FreeDV::freedv_get_n_speech_samples(m_freeDV);
int nMaxModemSamples = FreeDV::freedv_get_n_max_modem_samples(m_freeDV);
int Fs = FreeDV::freedv_get_modem_sample_rate(m_freeDV);
int Rs = FreeDV::freedv_get_modem_symbol_rate(m_freeDV);
int nSpeechSamples = freedv_get_n_speech_samples(m_freeDV);
int nMaxModemSamples = freedv_get_n_max_modem_samples(m_freeDV);
int Fs = freedv_get_modem_sample_rate(m_freeDV);
int Rs = freedv_get_modem_symbol_rate(m_freeDV);
m_freeDVStats.init();
if (nSpeechSamples != m_nSpeechSamples)
@ -660,7 +661,7 @@ void FreeDVDemod::applyFreeDVMode(FreeDVDemodSettings::FreeDVMode mode)
m_iSpeech = 0;
m_iModem = 0;
m_nin = FreeDV::freedv_nin(m_freeDV);
m_nin = freedv_nin(m_freeDV);
if (m_nin > 0) {
m_freeDVStats.m_fps = m_modemSampleRate / m_nin;

View File

@ -45,9 +45,7 @@ class DeviceAPI;
class ThreadedBasebandSampleSink;
class DownChannelizer;
namespace FreeDV {
struct freedv;
}
class FreeDVDemod : public BasebandSampleSink, public ChannelAPI {
Q_OBJECT
@ -222,7 +220,7 @@ private:
{
FreeDVStats();
void init();
void collect(struct FreeDV::freedv *freedv);
void collect(struct freedv *freedv);
bool m_sync;
float m_snrEst;
@ -395,7 +393,7 @@ private:
QNetworkAccessManager *m_networkManager;
QNetworkRequest m_networkRequest;
struct FreeDV::freedv *m_freeDV;
struct freedv *m_freeDV;
int m_nSpeechSamples;
int m_nMaxModemSamples;
int m_nin;

View File

@ -14,7 +14,6 @@ set(modfreedv_HEADERS
include_directories(
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
${CMAKE_SOURCE_DIR}/libfreedv
${CODEC2_INCLUDE_DIR}
)
@ -22,14 +21,12 @@ if(NOT SERVER_MODE)
set(modfreedv_SOURCES
${modfreedv_SOURCES}
freedvmodgui.cpp
freedvmodgui.ui
)
set(modfreedv_HEADERS
${modfreedv_HEADERS}
freedvmodgui.h
)
set(TARGET_NAME modfreedv)
set(TARGET_LIB "Qt5::Widgets")
set(TARGET_LIB_GUI "sdrgui")
@ -50,13 +47,12 @@ if(ENABLE_EXTERNAL_LIBRARIES)
endif()
target_link_libraries(${TARGET_NAME}
Qt5::Core
${TARGET_LIB}
Qt5::Core
${TARGET_LIB}
sdrbase
${TARGET_LIB_GUI}
swagger
freedv
${CODEC2_LIBRARIES}
swagger
${CODEC2_LIBRARIES}
)
install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER})

View File

@ -28,7 +28,7 @@
#include <complex.h>
#include <algorithm>
#include "libfreedv.h"
#include "codec2/freedv_api.h"
#include "SWGChannelSettings.h"
#include "SWGChannelReport.h"
@ -138,7 +138,7 @@ FreeDVMod::~FreeDVMod()
delete[] m_SSBFilterBuffer;
if (m_freeDV) {
FreeDV::freedv_close(m_freeDV);
freedv_close(m_freeDV);
}
}
@ -231,7 +231,7 @@ void FreeDVMod::pullAF(Complex& sample)
calculateLevel(m_speechIn[i]);
}
}
FreeDV::freedv_tx(m_freeDV, m_modOut, m_speechIn);
freedv_tx(m_freeDV, m_modOut, m_speechIn);
break;
case FreeDVModSettings::FreeDVModInputFile:
if (m_iModem >= m_nNomModemSamples)
@ -271,7 +271,7 @@ void FreeDVMod::pullAF(Complex& sample)
}
}
FreeDV::freedv_tx(m_freeDV, m_modOut, m_speechIn);
freedv_tx(m_freeDV, m_modOut, m_speechIn);
}
}
else
@ -296,7 +296,7 @@ void FreeDVMod::pullAF(Complex& sample)
calculateLevel(m_speechIn[i]);
}
}
FreeDV::freedv_tx(m_freeDV, m_modOut, m_speechIn);
freedv_tx(m_freeDV, m_modOut, m_speechIn);
break;
case FreeDVModSettings::FreeDVModInputCWTone:
for (int i = 0; i < m_nSpeechSamples; i++)
@ -325,12 +325,12 @@ void FreeDVMod::pullAF(Complex& sample)
calculateLevel(m_speechIn[i]);
}
}
FreeDV::freedv_tx(m_freeDV, m_modOut, m_speechIn);
freedv_tx(m_freeDV, m_modOut, m_speechIn);
break;
case FreeDVModSettings::FreeDVModInputNone:
default:
std::fill(m_speechIn, m_speechIn + m_nSpeechSamples, 0);
FreeDV::freedv_tx(m_freeDV, m_modOut, m_speechIn);
freedv_tx(m_freeDV, m_modOut, m_speechIn);
break;
}
@ -642,7 +642,7 @@ void FreeDVMod::applyFreeDVMode(FreeDVModSettings::FreeDVMode mode)
// FreeDV object
if (m_freeDV) {
FreeDV::freedv_close(m_freeDV);
freedv_close(m_freeDV);
}
int fdv_mode = -1;
@ -674,32 +674,32 @@ void FreeDVMod::applyFreeDVMode(FreeDVModSettings::FreeDVMode mode)
if (fdv_mode == FREEDV_MODE_700D)
{
struct FreeDV::freedv_advanced adv;
struct freedv_advanced adv;
adv.interleave_frames = 1;
m_freeDV = FreeDV::freedv_open_advanced(fdv_mode, &adv);
m_freeDV = freedv_open_advanced(fdv_mode, &adv);
}
else
{
m_freeDV = FreeDV::freedv_open(fdv_mode);
m_freeDV = freedv_open(fdv_mode);
}
if (m_freeDV)
{
FreeDV::freedv_set_test_frames(m_freeDV, 0);
FreeDV::freedv_set_snr_squelch_thresh(m_freeDV, -100.0);
FreeDV::freedv_set_squelch_en(m_freeDV, 1);
FreeDV::freedv_set_clip(m_freeDV, 0);
FreeDV::freedv_set_tx_bpf(m_freeDV, 1);
FreeDV::freedv_set_ext_vco(m_freeDV, 0);
freedv_set_test_frames(m_freeDV, 0);
freedv_set_snr_squelch_thresh(m_freeDV, -100.0);
freedv_set_squelch_en(m_freeDV, 1);
freedv_set_clip(m_freeDV, 0);
freedv_set_tx_bpf(m_freeDV, 1);
freedv_set_ext_vco(m_freeDV, 0);
FreeDV::freedv_set_callback_txt(m_freeDV, nullptr, nullptr, nullptr);
FreeDV::freedv_set_callback_protocol(m_freeDV, nullptr, nullptr, nullptr);
FreeDV::freedv_set_callback_data(m_freeDV, nullptr, nullptr, nullptr);
freedv_set_callback_txt(m_freeDV, nullptr, nullptr, nullptr);
freedv_set_callback_protocol(m_freeDV, nullptr, nullptr, nullptr);
freedv_set_callback_data(m_freeDV, nullptr, nullptr, nullptr);
int nSpeechSamples = FreeDV::freedv_get_n_speech_samples(m_freeDV);
int nNomModemSamples = FreeDV::freedv_get_n_nom_modem_samples(m_freeDV);
int Fs = FreeDV::freedv_get_modem_sample_rate(m_freeDV);
int Rs = FreeDV::freedv_get_modem_symbol_rate(m_freeDV);
int nSpeechSamples = freedv_get_n_speech_samples(m_freeDV);
int nNomModemSamples = freedv_get_n_nom_modem_samples(m_freeDV);
int Fs = freedv_get_modem_sample_rate(m_freeDV);
int Rs = freedv_get_modem_symbol_rate(m_freeDV);
if (nSpeechSamples != m_nSpeechSamples)
{

View File

@ -46,9 +46,7 @@ class DeviceAPI;
class ThreadedBasebandSampleSource;
class UpChannelizer;
namespace FreeDV {
struct freedv;
}
class FreeDVMod : public BasebandSampleSource, public ChannelAPI {
Q_OBJECT
@ -332,7 +330,7 @@ private:
QNetworkAccessManager *m_networkManager;
QNetworkRequest m_networkRequest;
struct FreeDV::freedv *m_freeDV;
struct freedv *m_freeDV;
int m_nSpeechSamples;
int m_nNomModemSamples;
int m_iSpeech;