modem_stats.c
c2wideband.c
dct2.c
+ ofdm.c
+ mpdecode_core.c
+ gp_interleaver.c
+ interldpc.c
)
set(CODEC2_PUBLIC_HEADERS
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)
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)
#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
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));
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;
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 */
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);
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));
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));
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;
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);
#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);