From 62e21d1f9c67b29352f407a2e2b4cdb341bc92b2 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sat, 21 Apr 2018 21:11:31 +0000 Subject: [PATCH] first pass at init and shutdown code for freedv 700D git-svn-id: https://svn.code.sf.net/p/freetel/code@3517 01035d8c-6547-0410-b346-abe4f91aad63 --- codec2-dev/src/CMakeLists.txt | 20 ++++--- codec2-dev/src/freedv_api.c | 80 ++++++++++++++++++++++++---- codec2-dev/src/freedv_api.h | 1 + codec2-dev/src/freedv_api_internal.h | 11 ++-- codec2-dev/src/interldpc.c | 2 +- 5 files changed, 92 insertions(+), 22 deletions(-) diff --git a/codec2-dev/src/CMakeLists.txt b/codec2-dev/src/CMakeLists.txt index 44727032..5d629013 100644 --- a/codec2-dev/src/CMakeLists.txt +++ b/codec2-dev/src/CMakeLists.txt @@ -233,6 +233,10 @@ set(CODEC2_SRCS modem_stats.c c2wideband.c dct2.c + ofdm.c + mpdecode_core.c + gp_interleaver.c + interldpc.c ) set(CODEC2_PUBLIC_HEADERS @@ -337,10 +341,10 @@ target_link_libraries(ofdm_get_test_bits ${CMAKE_REQUIRED_LIBRARIES} codec2) add_executable(ofdm_put_test_bits ofdm_put_test_bits.c) target_link_libraries(ofdm_put_test_bits ${CMAKE_REQUIRED_LIBRARIES} codec2) -add_executable(ofdm_mod ofdm_mod.c interldpc.c mpdecode_core.c gp_interleaver.c) +add_executable(ofdm_mod ofdm_mod.c) target_link_libraries(ofdm_mod ${CMAKE_REQUIRED_LIBRARIES} codec2) -add_executable(ofdm_demod ofdm_demod.c octave.c mpdecode_core.c gp_interleaver.c interldpc.c) +add_executable(ofdm_demod ofdm_demod.c octave.c) target_link_libraries(ofdm_demod ${CMAKE_REQUIRED_LIBRARIES} codec2) add_executable(fmfsk_mod fmfsk_mod.c) @@ -367,17 +371,17 @@ target_link_libraries(cohpsk_put_test_bits ${CMAKE_REQUIRED_LIBRARIES} codec2) add_executable(cohpsk_ch cohpsk_ch.c) target_link_libraries(cohpsk_ch ${CMAKE_REQUIRED_LIBRARIES} codec2) -add_executable(ldpc_enc ldpc_enc.c mpdecode_core.c) -target_link_libraries(ldpc_enc ${CMAKE_REQUIRED_LIBRARIES}) +add_executable(ldpc_enc ldpc_enc.c) +target_link_libraries(ldpc_enc ${CMAKE_REQUIRED_LIBRARIES} codec2) -add_executable(ldpc_dec ldpc_dec.c mpdecode_core.c) -target_link_libraries(ldpc_dec ${CMAKE_REQUIRED_LIBRARIES}) +add_executable(ldpc_dec ldpc_dec.c) +target_link_libraries(ldpc_dec ${CMAKE_REQUIRED_LIBRARIES} codec2) add_executable(drs232 drs232.c) target_link_libraries(drs232 ${CMAKE_REQUIRED_LIBRARIES}) -add_executable(drs232_ldpc drs232_ldpc.c mpdecode_core.c) -target_link_libraries(drs232_ldpc ${CMAKE_REQUIRED_LIBRARIES}) +add_executable(drs232_ldpc drs232_ldpc.c) +target_link_libraries(drs232_ldpc ${CMAKE_REQUIRED_LIBRARIES} codec2) add_definitions(-DHORUS_L2_RX -DINTERLEAVER -DSCRAMBLER) add_executable(horus_demod horus_demod.c horus_api.c horus_l2.c fsk.c kiss_fft.c) diff --git a/codec2-dev/src/freedv_api.c b/codec2-dev/src/freedv_api.c index a9aa3ca2..85570425 100644 --- a/codec2-dev/src/freedv_api.c +++ b/codec2-dev/src/freedv_api.c @@ -51,6 +51,12 @@ #include "freedv_vhf_framing.h" #include "comp_prim.h" +#include "codec2_ofdm.h" +#include "ofdm_internal.h" +#include "mpdecode_core.h" +#include "gp_interleaver.h" +#include "interldpc.h" + #define VERSION 11 /* The API version number. The first version is 10. Increment if the API changes in a way that would require changes by the API @@ -83,7 +89,7 @@ struct freedv *freedv_open(int mode) { if ((mode != FREEDV_MODE_1600) && (mode != FREEDV_MODE_700) && (mode != FREEDV_MODE_700B) && (mode != FREEDV_MODE_2400A) && (mode != FREEDV_MODE_2400B) && (mode != FREEDV_MODE_800XA) && - (mode != FREEDV_MODE_700C)) + (mode != FREEDV_MODE_700C) && (mode != FREEDV_MODE_700D) ) return NULL; f = (struct freedv*)malloc(sizeof(struct freedv)); @@ -96,6 +102,8 @@ struct freedv *freedv_open(int mode) { f->error_pattern_callback_state = NULL; f->n_protocol_bits = 0; + /* Init states for this mode, and set up samples in/out -----------------------------------------*/ + if (mode == FREEDV_MODE_1600) { f->snr_squelch_thresh = 2.0; f->squelch_en = 1; @@ -155,7 +163,38 @@ struct freedv *freedv_open(int mode) { return NULL; f->sz_error_pattern = cohpsk_error_pattern_size(); } + + if (mode == FREEDV_MODE_700D) { + /* + TODO: + [ ] how to set up interleaver, prob init time option best, as many arrays depend on it + [ ] clip option? Haven't tried clipping OFDM waveform yet + [ ] support for uncoded and coded error patterns + */ + + f->snr_squelch_thresh = 0.0; + f->squelch_en = 0; + codec2_mode = CODEC2_MODE_700C; + f->ofdm = ofdm_create(OFDM_CONFIG_700D); + + f->nin = ofdm_get_samples_per_frame(); + f->n_nat_modem_samples = ofdm_get_samples_per_frame(); + f->n_nom_modem_samples = ofdm_get_samples_per_frame(); + f->n_max_modem_samples = ofdm_get_max_samples_per_frame(); + f->modem_sample_rate = OFDM_FS; + f->clip = 0; + nbit = OFDM_BITSPERFRAME; + f->tx_bits = (int*)malloc(nbit*sizeof(int)); + if (f->tx_bits == NULL) + return NULL; + f->sz_error_pattern = OFDM_BITSPERFRAME; /* uncoded errors */ + + f->ldpc = (struct LDPC*)malloc(sizeof(struct LDPC)); + if (f->ldpc == NULL) { return NULL; } + set_up_hra_112_112(f->ldpc); + } #endif + if ((mode == FREEDV_MODE_2400A) || (mode == FREEDV_MODE_2400B)) { /* Set up the C2 mode */ @@ -245,16 +284,23 @@ struct freedv *freedv_open(int mode) { f->sz_error_pattern = 0; } - f->test_frames_diversity = 1; f->test_frame_sync_state = 0; f->test_frame_sync_state_upper = 0; f->total_bits = 0; f->total_bit_errors = 0; + /* Init Codec 2 for this FreeDV mode ----------------------------------------------------*/ + f->codec2 = codec2_create(codec2_mode); if (f->codec2 == NULL) return NULL; + + /* work out how many codec 2 frames per mode frame, and number of + bytes of storage for packed and unpacket bits. TODO: do we really + need to work in packed bits at all? It's messy, chars would probably + be OK.... */ + if ((mode == FREEDV_MODE_1600) || (mode == FREEDV_MODE_2400A) || (mode == FREEDV_MODE_2400B)) { f->n_speech_samples = codec2_samples_per_frame(f->codec2); f->n_codec_bits = codec2_bits_per_frame(f->codec2); @@ -268,17 +314,25 @@ struct freedv *freedv_open(int mode) { nbyte = nbyte*2; nbit = 8*nbyte; f->n_codec_bits = nbit; - } else { /* ((mode == FREEDV_MODE_700) || (mode == FREEDV_MODE_700B) || (mode == FREEDV_MODE_700C)) */ + } else if ((mode == FREEDV_MODE_700) || (mode == FREEDV_MODE_700B) || (mode == FREEDV_MODE_700C)) { f->n_speech_samples = 2*codec2_samples_per_frame(f->codec2); f->n_codec_bits = 2*codec2_bits_per_frame(f->codec2); nbit = f->n_codec_bits; nbyte = 2*((codec2_bits_per_frame(f->codec2) + 7) / 8); + } else /* mode == FREEDV_MODE_700D */ { + + /* should be exactly an integer number ofCodec 2 frames in a OFDM modem frame */ + + assert((f->ldpc->data_bits_per_frame % codec2_bits_per_frame(f->codec2)) == 0); + + int Ncodec2frames = f->ldpc->data_bits_per_frame/codec2_bits_per_frame(f->codec2); + + f->n_speech_samples = Ncodec2frames*codec2_samples_per_frame(f->codec2); + f->n_codec_bits = Ncodec2frames*codec2_bits_per_frame(f->codec2); + nbit = f->n_codec_bits; + nbyte = (nbit + 7) / 8; } - f->prev_rx_bits = (float*)malloc(sizeof(float)*2*codec2_bits_per_frame(f->codec2)); - if (f->prev_rx_bits == NULL) - return NULL; - f->packed_codec_bits = (unsigned char*)malloc(nbyte*sizeof(char)); if (mode == FREEDV_MODE_1600) f->codec_bits = (int*)malloc(nbit*sizeof(int)); @@ -286,10 +340,13 @@ struct freedv *freedv_open(int mode) { f->codec_bits = (int*)malloc(COHPSK_BITS_PER_FRAME*sizeof(int)); /* Note: VHF Framer/deframer goes directly from packed codec/vc/proto bits to filled frame */ + if ((f->packed_codec_bits == NULL) || (f->codec_bits == NULL)) return NULL; - if ((mode == FREEDV_MODE_700) || (mode == FREEDV_MODE_700B) || (mode == FREEDV_MODE_700C) ) { // change modem rates to 8000 sps + /* Sample rate conversion for modes using COHPSK */ + + if ((mode == FREEDV_MODE_700) || (mode == FREEDV_MODE_700B) || (mode == FREEDV_MODE_700C) ) { f->ptFilter7500to8000 = (struct quisk_cfFilter *)malloc(sizeof(struct quisk_cfFilter)); f->ptFilter8000to7500 = (struct quisk_cfFilter *)malloc(sizeof(struct quisk_cfFilter)); quisk_filt_cfInit(f->ptFilter8000to7500, quiskFilt120t480, sizeof(quiskFilt120t480)/sizeof(float)); @@ -300,6 +357,8 @@ struct freedv *freedv_open(int mode) { f->ptFilter8000to7500 = NULL; } + /* Varicode low bit rate text states */ + varicode_decode_init(&f->varicode_dec_states, 1); f->nvaricode_bits = 0; f->varicode_bit_index = 0; @@ -325,7 +384,6 @@ struct freedv *freedv_open(int mode) { void freedv_close(struct freedv *freedv) { assert(freedv != NULL); - free(freedv->prev_rx_bits); free(freedv->packed_codec_bits); free(freedv->codec_bits); free(freedv->tx_bits); @@ -334,6 +392,10 @@ void freedv_close(struct freedv *freedv) { #ifndef CORTEX_M4 if ((freedv->mode == FREEDV_MODE_700) || (freedv->mode == FREEDV_MODE_700B) || (freedv->mode == FREEDV_MODE_700C)) cohpsk_destroy(freedv->cohpsk); + if (freedv->mode == FREEDV_MODE_700D) { + free(freedv->ldpc); + ofdm_destroy(freedv->ofdm); + } #endif if ((freedv->mode == FREEDV_MODE_2400A) || (freedv->mode == FREEDV_MODE_800XA)){ fsk_destroy(freedv->fsk); diff --git a/codec2-dev/src/freedv_api.h b/codec2-dev/src/freedv_api.h index 34ec730f..28e0cc66 100644 --- a/codec2-dev/src/freedv_api.h +++ b/codec2-dev/src/freedv_api.h @@ -45,6 +45,7 @@ #define FREEDV_MODE_2400B 4 #define FREEDV_MODE_800XA 5 #define FREEDV_MODE_700C 6 +#define FREEDV_MODE_700D 7 struct freedv; diff --git a/codec2-dev/src/freedv_api_internal.h b/codec2-dev/src/freedv_api_internal.h index 7ef000cf..7657879c 100644 --- a/codec2-dev/src/freedv_api_internal.h +++ b/codec2-dev/src/freedv_api_internal.h @@ -61,16 +61,20 @@ static float quiskFilt120t480[480]; struct freedv { int mode; + /* states for various modems we support */ + struct CODEC2 *codec2; struct FDMDV *fdmdv; - struct MODEM_STATS stats; 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 freedv_vhf_deframer * deframer; // Extracts frames from VHF stream - struct quisk_cfFilter * ptFilter7500to8000; // Filters to change to/from 7500 and 8000 sps + struct quisk_cfFilter * ptFilter7500to8000; // Filters to change to/from 7500 and 8000 sps struct quisk_cfFilter * ptFilter8000to7500; int n_speech_samples; @@ -88,7 +92,6 @@ struct freedv { int *rx_bits; int tx_sync_bit; int smooth_symbols; - float *prev_rx_bits; int n_codec_bits; // amount of codec bits in a frame int *ptest_bits_coh; diff --git a/codec2-dev/src/interldpc.c b/codec2-dev/src/interldpc.c index 716c4c7f..4c1a9365 100644 --- a/codec2-dev/src/interldpc.c +++ b/codec2-dev/src/interldpc.c @@ -4,7 +4,7 @@ AUTHOR......: David Rowe DATE CREATED: April 2018 - Helper functions for interleaved LDPC modems. + Helper functions for interleaved LDPC waveforms. \*---------------------------------------------------------------------------*/ -- 2.25.1