diff --git a/src/freedv_700.c b/src/freedv_700.c index 7c8536c3..a7d7aac1 100644 --- a/src/freedv_700.c +++ b/src/freedv_700.c @@ -189,7 +189,7 @@ void freedv_ofdm_voice_open(struct freedv *f, char *mode) { // open function for OFDM data modes, TODO consider moving to a new // (freedv_ofdm_data.c) file -void freedv_ofdm_data_open(struct freedv *f) { +void freedv_ofdm_data_open(struct freedv *f, struct freedv_advanced *adv) { struct OFDM_CONFIG ofdm_config; char mode[32]; if (f->mode == FREEDV_MODE_DATAC0) strcpy(mode, "datac0"); @@ -198,8 +198,14 @@ void freedv_ofdm_data_open(struct freedv *f) { if (f->mode == FREEDV_MODE_DATAC4) strcpy(mode, "datac4"); if (f->mode == FREEDV_MODE_DATAC13) strcpy(mode, "datac13"); if (f->mode == FREEDV_MODE_DATAC14) strcpy(mode, "datac14"); - - ofdm_init_mode(mode, &ofdm_config); + if (f->mode == FREEDV_MODE_DATA_CUSTOM) { + assert(adv != NULL); + assert(adv->config != NULL); + memcpy(&ofdm_config, (struct OFDM_CONFIG *)adv->config, + sizeof(struct OFDM_CONFIG)); + } else { + ofdm_init_mode(mode, &ofdm_config); + } f->ofdm = ofdm_create(&ofdm_config); assert(f->ofdm != NULL); @@ -219,8 +225,8 @@ void freedv_ofdm_data_open(struct freedv *f) { f->ofdm_ntxtbits = ofdm_config.txtbits; /* payload bits per FreeDV API "frame". In OFDM modem nomenclature this is - the number of payload data bits per packet, or the number of data bits in a - LDPC codeword */ + the number of payload data bits per packet, or the number of data bits in + a LDPC codeword */ f->bits_per_modem_frame = f->ldpc->data_bits_per_frame; // buffers for received symbols for one packet/LDPC codeword - may span many @@ -299,8 +305,8 @@ int freedv_comprx_700c(struct freedv *f, COMP demod_in_8kHz[]) { int rx_status = 0; - // quisk_cfInterpDecim() modifies input data so lets make a copy just in case - // there is no sync and we need to echo input to output + // quisk_cfInterpDecim() modifies input data so lets make a copy just in + // case there is no sync and we need to echo input to output // freedv_nin(f): input samples at Fs=8000 Hz // f->nin: input samples at Fs=7500 Hz @@ -332,7 +338,8 @@ int freedv_comprx_700c(struct freedv *f, COMP demod_in_8kHz[]) { rx_status |= FREEDV_RX_BITS; } else { if (f->test_frames_diversity) { - /* normal operation - error pattern on frame after diveristy combination + /* normal operation - error pattern on frame after diveristy + * combination */ short error_pattern[COHPSK_BITS_PER_FRAME]; int bit_errors; @@ -471,8 +478,8 @@ int freedv_comp_short_rx_ofdm(struct freedv *f, void *demod_in_8kHz, memcpy(&rx_amps[Nsymsperpacket - Nsymsperframe], ofdm->rx_amp, sizeof(float) * Nsymsperframe); - /* look for UW as frames enter packet buffer, note UW may span several modem - * frames */ + /* look for UW as frames enter packet buffer, note UW may span several + * modem frames */ int st_uw = Nsymsperpacket - ofdm->nuwframes * Nsymsperframe; ofdm_extract_uw(ofdm, &rx_syms[st_uw], &rx_amps[st_uw], rx_uw); @@ -510,8 +517,8 @@ int freedv_comp_short_rx_ofdm(struct freedv *f, void *demod_in_8kHz, else rx_status |= FREEDV_RX_BIT_ERRORS; } else { - // voice modes aren't as strict - pass everything through to the speech - // decoder, but flag frame with possible errors + // voice modes aren't as strict - pass everything through to the + // speech decoder, but flag frame with possible errors rx_status |= FREEDV_RX_BITS; if (parityCheckCount != ldpc->NumberParityBits) rx_status |= FREEDV_RX_BIT_ERRORS; diff --git a/src/freedv_api.c b/src/freedv_api.c index 3ccf63da..a158d2aa 100644 --- a/src/freedv_api.c +++ b/src/freedv_api.c @@ -60,7 +60,7 @@ /* The API version number. The first version is 10. Increment if the API changes in a way that would require changes by the API user. */ -#define VERSION 15 +#define VERSION 16 /* Version 10 Initial version August 2, 2015. @@ -79,6 +79,9 @@ Version 15 December 2022 Removing rarely used DPSK support which is not needed given fast fading modes + + Version 16 April 2024, added field to struct freedv_advanced to support + FREEDV_MODE_DATA_CUSTOM */ char *ofdm_statemode[] = {"search", "trial", "synced"}; @@ -101,7 +104,8 @@ char *rx_sync_flags_to_text[] = {"----", "---T", "--S-", "--ST", "-B--", "-B-T", struct freedv *freedv_open(int mode) { // defaults for those modes that support the use of adv - struct freedv_advanced adv = {0, 2, 100, 8000, 1000, 200, "H_256_512_4"}; + struct freedv_advanced adv = {0, 2, 100, 8000, + 1000, 200, "H_256_512_4", NULL}; return freedv_open_advanced(mode, &adv); } @@ -126,7 +130,8 @@ struct freedv *freedv_open_advanced(int mode, struct freedv_advanced *adv) { FDV_MODE_ACTIVE(FREEDV_MODE_DATAC3, mode) || FDV_MODE_ACTIVE(FREEDV_MODE_DATAC4, mode) || FDV_MODE_ACTIVE(FREEDV_MODE_DATAC13, mode) || - FDV_MODE_ACTIVE(FREEDV_MODE_DATAC14, mode)) == false) + FDV_MODE_ACTIVE(FREEDV_MODE_DATAC14, mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_DATA_CUSTOM, mode)) == false) return NULL; /* set everything to zero just in case */ @@ -150,12 +155,16 @@ struct freedv *freedv_open_advanced(int mode, struct freedv_advanced *adv) { if (FDV_MODE_ACTIVE(FREEDV_MODE_2400B, mode)) freedv_2400b_open(f); if (FDV_MODE_ACTIVE(FREEDV_MODE_800XA, mode)) freedv_800xa_open(f); if (FDV_MODE_ACTIVE(FREEDV_MODE_FSK_LDPC, mode)) freedv_fsk_ldpc_open(f, adv); - if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC0, mode)) freedv_ofdm_data_open(f); - if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC1, mode)) freedv_ofdm_data_open(f); - if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC3, mode)) freedv_ofdm_data_open(f); - if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC4, mode)) freedv_ofdm_data_open(f); - if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC13, mode)) freedv_ofdm_data_open(f); - if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC14, mode)) freedv_ofdm_data_open(f); + if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC0, mode)) freedv_ofdm_data_open(f, NULL); + if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC1, mode)) freedv_ofdm_data_open(f, NULL); + if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC3, mode)) freedv_ofdm_data_open(f, NULL); + if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC4, mode)) freedv_ofdm_data_open(f, NULL); + if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC13, mode)) + freedv_ofdm_data_open(f, NULL); + if (FDV_MODE_ACTIVE(FREEDV_MODE_DATAC14, mode)) + freedv_ofdm_data_open(f, NULL); + if (FDV_MODE_ACTIVE(FREEDV_MODE_DATA_CUSTOM, mode)) + freedv_ofdm_data_open(f, adv); varicode_decode_init(&f->varicode_dec_states, 1); diff --git a/src/freedv_api.h b/src/freedv_api.h index e4ca468b..9f72c8f9 100644 --- a/src/freedv_api.h +++ b/src/freedv_api.h @@ -62,6 +62,7 @@ extern "C" { #define FREEDV_MODE_DATAC4 18 #define FREEDV_MODE_DATAC13 19 #define FREEDV_MODE_DATAC14 20 +#define FREEDV_MODE_DATA_CUSTOM 21 // Sample rates used #define FREEDV_FS_8000 8000 @@ -144,6 +145,9 @@ extern "C" { #if !defined(FREEDV_MODE_DATAC14_EN) #define FREEDV_MODE_DATAC14_EN FREEDV_MODE_EN_DEFAULT #endif +#if !defined(FREEDV_MODE_DATA_CUSTOM_EN) +#define FREEDV_MODE_DATA_CUSTOM_EN FREEDV_MODE_EN_DEFAULT +#endif #define FDV_MODE_ACTIVE(mode_name, var) \ ((mode_name##_EN) == 0 ? 0 : (var) == mode_name) @@ -163,6 +167,9 @@ struct freedv_advanced { int first_tone; // Freq of first tone Hz int tone_spacing; // Spacing between tones Hz char *codename; // LDPC codename, from codes listed in ldpc_codes.c + + // parameters for FREEDV_MODE_DATA_CUSTOM + void *config; // ptr to struct OFDM_CONFIG }; // Called when text message char is decoded diff --git a/src/freedv_api_internal.h b/src/freedv_api_internal.h index ef6426f6..9559a2d9 100644 --- a/src/freedv_api_internal.h +++ b/src/freedv_api_internal.h @@ -221,7 +221,7 @@ void freedv_2400a_open(struct freedv *f); void freedv_2400b_open(struct freedv *f); void freedv_800xa_open(struct freedv *f); void freedv_fsk_ldpc_open(struct freedv *f, struct freedv_advanced *adv); -void freedv_ofdm_data_open(struct freedv *f); +void freedv_ofdm_data_open(struct freedv *f, struct freedv_advanced *adv); // each mode has tx and rx functions in various flavours for real and complex // valued samples