diff options
Diffstat (limited to 'src/freedv_fsk.c')
| -rw-r--r-- | src/freedv_fsk.c | 1145 |
1 files changed, 609 insertions, 536 deletions
diff --git a/src/freedv_fsk.c b/src/freedv_fsk.c index 31d30d3..edd0bfd 100644 --- a/src/freedv_fsk.c +++ b/src/freedv_fsk.c @@ -9,628 +9,701 @@ \*---------------------------------------------------------------------------*/ #include <assert.h> -#include <stdlib.h> +#include <math.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> -#include <math.h> -#include "fsk.h" -#include "fmfsk.h" #include "codec2.h" -#include "freedv_vhf_framing.h" -#include "varicode.h" -#include "freedv_api.h" -#include "freedv_api_internal.h" #include "comp_prim.h" #include "debug_alloc.h" -#include "ldpc_codes.h" +#include "fmfsk.h" +#include "freedv_api.h" +#include "freedv_api_internal.h" +#include "freedv_vhf_framing.h" +#include "fsk.h" #include "interldpc.h" +#include "ldpc_codes.h" +#include "varicode.h" /* 32 bit 0x5186fe15 Unique word for fsk_ldpc modes */ -static uint8_t fsk_ldpc_uw[] = {0,1,0,1, 0,0,0,1, 1,0,0,0, 0,1,1,0, 1,1,1,1, 1,1,1,0, 0,0,0,1, 0,1,0,1}; +static uint8_t fsk_ldpc_uw[] = {0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1}; void freedv_2400a_open(struct freedv *f) { - f->n_protocol_bits = 20; - f->deframer = fvhff_create_deframer(FREEDV_VHF_FRAME_A,0); - assert(f->deframer != NULL); - f->fsk = fsk_create_hbr(48000,1200,4,10,FSK_DEFAULT_NSYM,1200,1200); - assert(f->fsk != NULL); - - /* Note: fsk expects tx/rx bits as an array of uint8_ts, not ints */ - f->tx_bits = (int*)MALLOC(f->fsk->Nbits*sizeof(uint8_t)); - assert(f->tx_bits != NULL); - - f->n_nom_modem_samples = f->fsk->N; - f->n_max_modem_samples = f->fsk->N + (f->fsk->Ts); - f->n_nat_modem_samples = f->fsk->N; - f->nin = f->nin_prev = fsk_nin(f->fsk); - f->modem_sample_rate = 48000; - f->modem_symbol_rate = 1200; - - f->speech_sample_rate = FREEDV_FS_8000; - f->codec2 = codec2_create(CODEC2_MODE_1300); assert(f->codec2 != NULL); - f->n_speech_samples = codec2_samples_per_frame(f->codec2); - - f->n_codec_frames = 1; - f->bits_per_codec_frame = codec2_bits_per_frame(f->codec2); - f->bits_per_modem_frame = f->bits_per_codec_frame; - int n_packed_bytes = (f->bits_per_modem_frame + 7)/8; - f->tx_payload_bits = MALLOC(n_packed_bytes); assert(f->tx_payload_bits != NULL); - f->rx_payload_bits = MALLOC(n_packed_bytes); assert(f->rx_payload_bits != NULL); + f->n_protocol_bits = 20; + f->deframer = fvhff_create_deframer(FREEDV_VHF_FRAME_A, 0); + assert(f->deframer != NULL); + f->fsk = fsk_create_hbr(48000, 1200, 4, 10, FSK_DEFAULT_NSYM, 1200, 1200); + assert(f->fsk != NULL); + + /* Note: fsk expects tx/rx bits as an array of uint8_ts, not ints */ + f->tx_bits = (int *)MALLOC(f->fsk->Nbits * sizeof(uint8_t)); + assert(f->tx_bits != NULL); + + f->n_nom_modem_samples = f->fsk->N; + f->n_max_modem_samples = f->fsk->N + (f->fsk->Ts); + f->n_nat_modem_samples = f->fsk->N; + f->nin = f->nin_prev = fsk_nin(f->fsk); + f->modem_sample_rate = 48000; + f->modem_symbol_rate = 1200; + + f->speech_sample_rate = FREEDV_FS_8000; + f->codec2 = codec2_create(CODEC2_MODE_1300); + assert(f->codec2 != NULL); + f->n_speech_samples = codec2_samples_per_frame(f->codec2); + + f->n_codec_frames = 1; + f->bits_per_codec_frame = codec2_bits_per_frame(f->codec2); + f->bits_per_modem_frame = f->bits_per_codec_frame; + int n_packed_bytes = (f->bits_per_modem_frame + 7) / 8; + f->tx_payload_bits = MALLOC(n_packed_bytes); + assert(f->tx_payload_bits != NULL); + f->rx_payload_bits = MALLOC(n_packed_bytes); + assert(f->rx_payload_bits != NULL); } void freedv_2400b_open(struct freedv *f) { - f->n_protocol_bits = 20; - f->deframer = fvhff_create_deframer(FREEDV_VHF_FRAME_A,1); - assert(f->deframer != NULL); - - f->fmfsk = fmfsk_create(48000,2400); - assert (f->fmfsk != NULL); - - /* Note: fsk expects tx/rx bits as an array of uint8_ts, not ints */ - f->tx_bits = (int*)MALLOC(f->fmfsk->nbit*sizeof(uint8_t)); - assert(f->tx_bits != NULL); - f->n_nom_modem_samples = f->fmfsk->N; - f->n_max_modem_samples = f->fmfsk->N + (f->fmfsk->Ts); - f->n_nat_modem_samples = f->fmfsk->N; - f->nin = f->nin_prev = fmfsk_nin(f->fmfsk); - f->modem_sample_rate = 48000; - - f->speech_sample_rate = FREEDV_FS_8000; - f->codec2 = codec2_create(CODEC2_MODE_1300); assert(f->codec2 != NULL); - f->n_speech_samples = codec2_samples_per_frame(f->codec2); - - f->n_codec_frames = 1; - f->bits_per_codec_frame = codec2_bits_per_frame(f->codec2); - f->bits_per_modem_frame = f->bits_per_codec_frame; - int n_packed_bytes = (f->bits_per_modem_frame + 7)/8; - f->tx_payload_bits = MALLOC(n_packed_bytes); assert(f->tx_payload_bits != NULL); - f->rx_payload_bits = MALLOC(n_packed_bytes); assert(f->rx_payload_bits != NULL); + f->n_protocol_bits = 20; + f->deframer = fvhff_create_deframer(FREEDV_VHF_FRAME_A, 1); + assert(f->deframer != NULL); + + f->fmfsk = fmfsk_create(48000, 2400); + assert(f->fmfsk != NULL); + + /* Note: fsk expects tx/rx bits as an array of uint8_ts, not ints */ + f->tx_bits = (int *)MALLOC(f->fmfsk->nbit * sizeof(uint8_t)); + assert(f->tx_bits != NULL); + f->n_nom_modem_samples = f->fmfsk->N; + f->n_max_modem_samples = f->fmfsk->N + (f->fmfsk->Ts); + f->n_nat_modem_samples = f->fmfsk->N; + f->nin = f->nin_prev = fmfsk_nin(f->fmfsk); + f->modem_sample_rate = 48000; + + f->speech_sample_rate = FREEDV_FS_8000; + f->codec2 = codec2_create(CODEC2_MODE_1300); + assert(f->codec2 != NULL); + f->n_speech_samples = codec2_samples_per_frame(f->codec2); + + f->n_codec_frames = 1; + f->bits_per_codec_frame = codec2_bits_per_frame(f->codec2); + f->bits_per_modem_frame = f->bits_per_codec_frame; + int n_packed_bytes = (f->bits_per_modem_frame + 7) / 8; + f->tx_payload_bits = MALLOC(n_packed_bytes); + assert(f->tx_payload_bits != NULL); + f->rx_payload_bits = MALLOC(n_packed_bytes); + assert(f->rx_payload_bits != NULL); } void freedv_800xa_open(struct freedv *f) { - f->deframer = fvhff_create_deframer(FREEDV_HF_FRAME_B,0); - assert(f->deframer != NULL); - f->fsk = fsk_create_hbr(8000,400,4,10,32,800,400); - assert(f->fsk != NULL); - - f->tx_bits = (int*)MALLOC(f->fsk->Nbits*sizeof(uint8_t)); - assert(f->fsk != NULL); - - f->n_nom_modem_samples = f->fsk->N; - f->n_max_modem_samples = f->fsk->N + (f->fsk->Ts); - f->n_nat_modem_samples = f->fsk->N; - f->nin = f->nin_prev = fsk_nin(f->fsk); - f->modem_sample_rate = 8000; - f->modem_symbol_rate = 400; - fsk_stats_normalise_eye(f->fsk, 0); - - f->codec2 = codec2_create(CODEC2_MODE_700C); assert(f->codec2 != NULL); - f->speech_sample_rate = FREEDV_FS_8000; - f->n_codec_frames = 2; - f->n_speech_samples = f->n_codec_frames*codec2_samples_per_frame(f->codec2); - - f->bits_per_codec_frame = codec2_bits_per_frame(f->codec2); - f->bits_per_modem_frame = f->n_codec_frames*f->bits_per_codec_frame; - int n_packed_bytes = (f->bits_per_modem_frame + 7)/8; - f->tx_payload_bits = MALLOC(n_packed_bytes); assert(f->tx_payload_bits != NULL); - f->rx_payload_bits = MALLOC(n_packed_bytes); assert(f->rx_payload_bits != NULL); + f->deframer = fvhff_create_deframer(FREEDV_HF_FRAME_B, 0); + assert(f->deframer != NULL); + f->fsk = fsk_create_hbr(8000, 400, 4, 10, 32, 800, 400); + assert(f->fsk != NULL); + + f->tx_bits = (int *)MALLOC(f->fsk->Nbits * sizeof(uint8_t)); + assert(f->fsk != NULL); + + f->n_nom_modem_samples = f->fsk->N; + f->n_max_modem_samples = f->fsk->N + (f->fsk->Ts); + f->n_nat_modem_samples = f->fsk->N; + f->nin = f->nin_prev = fsk_nin(f->fsk); + f->modem_sample_rate = 8000; + f->modem_symbol_rate = 400; + fsk_stats_normalise_eye(f->fsk, 0); + + f->codec2 = codec2_create(CODEC2_MODE_700C); + assert(f->codec2 != NULL); + f->speech_sample_rate = FREEDV_FS_8000; + f->n_codec_frames = 2; + f->n_speech_samples = f->n_codec_frames * codec2_samples_per_frame(f->codec2); + + f->bits_per_codec_frame = codec2_bits_per_frame(f->codec2); + f->bits_per_modem_frame = f->n_codec_frames * f->bits_per_codec_frame; + int n_packed_bytes = (f->bits_per_modem_frame + 7) / 8; + f->tx_payload_bits = MALLOC(n_packed_bytes); + assert(f->tx_payload_bits != NULL); + f->rx_payload_bits = MALLOC(n_packed_bytes); + assert(f->rx_payload_bits != NULL); } - void freedv_fsk_ldpc_open(struct freedv *f, struct freedv_advanced *adv) { - assert(adv != NULL); - - /* set up modem */ - assert((adv->Fs % adv->Rs) == 0); // Fs/Rs must be an integer - int P = adv->Fs/adv->Rs; - assert(P >= 8); // Good idea for P >= 8 - while ((P > 10) && ((P % 2) == 0)) // reduce internal oversampling rate P as far as we can, keep it an integer - P /= 2; - //fprintf(stderr, "Fs: %d Rs: %d M: %d P: %d\n", adv->Fs, adv->Rs, adv->M, P); - f->fsk = fsk_create_hbr(adv->Fs, adv->Rs, adv->M, P, FSK_DEFAULT_NSYM, adv->first_tone, adv->tone_spacing); - assert(f->fsk != NULL); - fsk_set_freq_est_limits(f->fsk, 0, adv->Fs/2); - fsk_stats_normalise_eye(f->fsk, 0); - - /* set up LDPC code */ - int code_index = ldpc_codes_find(adv->codename); - assert(code_index != -1); - f->ldpc = (struct LDPC*)MALLOC(sizeof(struct LDPC)); assert(f->ldpc != NULL); - ldpc_codes_setup(f->ldpc, adv->codename); - f->ldpc->max_iter = 15; - //fprintf(stderr, "Using: %s\n", f->ldpc->name); - - f->bits_per_modem_frame = f->ldpc->data_bits_per_frame; - int bits_per_frame = f->ldpc->coded_bits_per_frame + sizeof(fsk_ldpc_uw); - f->tx_payload_bits = MALLOC(f->bits_per_modem_frame); assert(f->tx_payload_bits != NULL); - f->rx_payload_bits = MALLOC(f->bits_per_modem_frame); assert(f->rx_payload_bits != NULL); - - /* sample buffer size for tx modem samples, we modulate a full frame */ - f->n_nom_modem_samples = f->fsk->Ts*(bits_per_frame/(f->fsk->mode>>1)); - f->n_nat_modem_samples = f->n_nom_modem_samples; - - /* maximum sample buffer size for rx modem samples, note we only - demodulate partial frames on each call to fsk_demod() */ - f->n_max_modem_samples = f->fsk->N + (f->fsk->Ts); - - f->nin = f->nin_prev = fsk_nin(f->fsk); - f->modem_sample_rate = adv->Fs; - f->modem_symbol_rate = adv->Rs; - f->tx_amp = FSK_SCALE; - - /* deframer set up */ - f->frame_llr_size = 2*bits_per_frame; - f->frame_llr = (float*)MALLOC(f->frame_llr_size*sizeof(float)); assert(f->frame_llr != NULL); - f->frame_llr_nbits = 0; - - f->twoframes_hard = MALLOC(2*bits_per_frame); assert(f->twoframes_hard != NULL); - memset(f->twoframes_hard, 0, 2*bits_per_frame); - f->twoframes_llr = (float*)MALLOC(2*bits_per_frame*sizeof(float)); assert(f->twoframes_llr != NULL); - for(int i=0; i<2*bits_per_frame; i++) f->twoframes_llr[i] = 0.0; - - /* currently configured a simple frame-frame approach */ - f->fsk_ldpc_thresh1 = 5; - f->fsk_ldpc_thresh2 = 6; - f->fsk_ldpc_baduw_thresh=1; - - //fprintf(stderr, "thresh1: %d thresh2: %d\n", f->fsk_ldpc_thresh1, f->fsk_ldpc_thresh2); - f->fsk_ldpc_baduw = 0; - f->fsk_ldpc_best_location = 0; f->fsk_ldpc_state = 0; - f->fsk_ldpc_snr = 1.0; - f->fsk_S[0] = f->fsk_S[1] = f->fsk_N[0] = f->fsk_N[1] = 0.0; + assert(adv != NULL); + + /* set up modem */ + assert((adv->Fs % adv->Rs) == 0); // Fs/Rs must be an integer + int P = adv->Fs / adv->Rs; + assert(P >= 8); // Good idea for P >= 8 + while ((P > 10) && ((P % 2) == 0)) // reduce internal oversampling rate P as + // far as we can, keep it an integer + P /= 2; + // fprintf(stderr, "Fs: %d Rs: %d M: %d P: %d\n", adv->Fs, adv->Rs, adv->M, + // P); + f->fsk = fsk_create_hbr(adv->Fs, adv->Rs, adv->M, P, FSK_DEFAULT_NSYM, + adv->first_tone, adv->tone_spacing); + assert(f->fsk != NULL); + fsk_set_freq_est_limits(f->fsk, 0, adv->Fs / 2); + fsk_stats_normalise_eye(f->fsk, 0); + + /* set up LDPC code */ + int code_index = ldpc_codes_find(adv->codename); + assert(code_index != -1); + f->ldpc = (struct LDPC *)MALLOC(sizeof(struct LDPC)); + assert(f->ldpc != NULL); + ldpc_codes_setup(f->ldpc, adv->codename); + f->ldpc->max_iter = 15; + // fprintf(stderr, "Using: %s\n", f->ldpc->name); + + f->bits_per_modem_frame = f->ldpc->data_bits_per_frame; + int bits_per_frame = f->ldpc->coded_bits_per_frame + sizeof(fsk_ldpc_uw); + f->tx_payload_bits = MALLOC(f->bits_per_modem_frame); + assert(f->tx_payload_bits != NULL); + f->rx_payload_bits = MALLOC(f->bits_per_modem_frame); + assert(f->rx_payload_bits != NULL); + + /* sample buffer size for tx modem samples, we modulate a full frame */ + f->n_nom_modem_samples = f->fsk->Ts * (bits_per_frame / (f->fsk->mode >> 1)); + f->n_nat_modem_samples = f->n_nom_modem_samples; + + /* maximum sample buffer size for rx modem samples, note we only + demodulate partial frames on each call to fsk_demod() */ + f->n_max_modem_samples = f->fsk->N + (f->fsk->Ts); + + f->nin = f->nin_prev = fsk_nin(f->fsk); + f->modem_sample_rate = adv->Fs; + f->modem_symbol_rate = adv->Rs; + f->tx_amp = FSK_SCALE; + + /* deframer set up */ + f->frame_llr_size = 2 * bits_per_frame; + f->frame_llr = (float *)MALLOC(f->frame_llr_size * sizeof(float)); + assert(f->frame_llr != NULL); + f->frame_llr_nbits = 0; + + f->twoframes_hard = MALLOC(2 * bits_per_frame); + assert(f->twoframes_hard != NULL); + memset(f->twoframes_hard, 0, 2 * bits_per_frame); + f->twoframes_llr = (float *)MALLOC(2 * bits_per_frame * sizeof(float)); + assert(f->twoframes_llr != NULL); + for (int i = 0; i < 2 * bits_per_frame; i++) f->twoframes_llr[i] = 0.0; + + /* currently configured a simple frame-frame approach */ + f->fsk_ldpc_thresh1 = 5; + f->fsk_ldpc_thresh2 = 6; + f->fsk_ldpc_baduw_thresh = 1; + + // fprintf(stderr, "thresh1: %d thresh2: %d\n", f->fsk_ldpc_thresh1, + // f->fsk_ldpc_thresh2); + f->fsk_ldpc_baduw = 0; + f->fsk_ldpc_best_location = 0; + f->fsk_ldpc_state = 0; + f->fsk_ldpc_snr = 1.0; + f->fsk_S[0] = f->fsk_S[1] = f->fsk_N[0] = f->fsk_N[1] = 0.0; } - /* TX routines for 2400 FSK modes, after codec2 encoding */ void freedv_tx_fsk_voice(struct freedv *f, short mod_out[]) { - int i; - float *tx_float; /* To hold on to modulated samps from fsk/fmfsk */ - uint8_t vc_bits[2]; /* Varicode bits for 2400 framing */ - uint8_t proto_bits[3]; /* Prococol bits for 2400 framing */ - - /* Frame for 2400A/B */ - if(FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)){ - /* Get varicode bits for TX and possibly ask for a new char */ - /* 2 bits per 2400A/B frame, so this has to be done twice */ - for(i=0;i<2;i++){ - if (f->nvaricode_bits) { - vc_bits[i] = f->tx_varicode_bits[f->varicode_bit_index++]; - f->nvaricode_bits--; - } - - if (f->nvaricode_bits == 0) { - /* get new char and encode */ - char s[2]; - if (f->freedv_get_next_tx_char != NULL) { - s[0] = (*f->freedv_get_next_tx_char)(f->callback_state); - f->nvaricode_bits = varicode_encode(f->tx_varicode_bits, s, VARICODE_MAX_BITS, 1, 1); - f->varicode_bit_index = 0; - } - } + int i; + float *tx_float; /* To hold on to modulated samps from fsk/fmfsk */ + uint8_t vc_bits[2]; /* Varicode bits for 2400 framing */ + uint8_t proto_bits[3]; /* Prococol bits for 2400 framing */ + + /* Frame for 2400A/B */ + if (FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode)) { + /* Get varicode bits for TX and possibly ask for a new char */ + /* 2 bits per 2400A/B frame, so this has to be done twice */ + for (i = 0; i < 2; i++) { + if (f->nvaricode_bits) { + vc_bits[i] = f->tx_varicode_bits[f->varicode_bit_index++]; + f->nvaricode_bits--; + } + + if (f->nvaricode_bits == 0) { + /* get new char and encode */ + char s[2]; + if (f->freedv_get_next_tx_char != NULL) { + s[0] = (*f->freedv_get_next_tx_char)(f->callback_state); + f->nvaricode_bits = + varicode_encode(f->tx_varicode_bits, s, VARICODE_MAX_BITS, 1, 1); + f->varicode_bit_index = 0; } + } + } - /* If the API user hasn't set up message callbacks, don't bother with varicode bits */ - if(f->freedv_get_next_proto != NULL){ - (*f->freedv_get_next_proto)(f->proto_callback_state,(char*)proto_bits); - fvhff_frame_bits(FREEDV_VHF_FRAME_A,(uint8_t*)(f->tx_bits),f->tx_payload_bits,proto_bits,vc_bits); - }else if(f->freedv_get_next_tx_char != NULL){ - fvhff_frame_bits(FREEDV_VHF_FRAME_A,(uint8_t*)(f->tx_bits),f->tx_payload_bits,NULL,vc_bits); - }else { - fvhff_frame_bits(FREEDV_VHF_FRAME_A,(uint8_t*)(f->tx_bits),f->tx_payload_bits,NULL,NULL); - } + /* If the API user hasn't set up message callbacks, don't bother with + * varicode bits */ + if (f->freedv_get_next_proto != NULL) { + (*f->freedv_get_next_proto)(f->proto_callback_state, (char *)proto_bits); + fvhff_frame_bits(FREEDV_VHF_FRAME_A, (uint8_t *)(f->tx_bits), + f->tx_payload_bits, proto_bits, vc_bits); + } else if (f->freedv_get_next_tx_char != NULL) { + fvhff_frame_bits(FREEDV_VHF_FRAME_A, (uint8_t *)(f->tx_bits), + f->tx_payload_bits, NULL, vc_bits); + } else { + fvhff_frame_bits(FREEDV_VHF_FRAME_A, (uint8_t *)(f->tx_bits), + f->tx_payload_bits, NULL, NULL); + } /* Frame for 800XA */ - }else if(FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)){ - fvhff_frame_bits(FREEDV_HF_FRAME_B,(uint8_t*)(f->tx_bits),f->tx_payload_bits,NULL,NULL); + } else if (FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode)) { + fvhff_frame_bits(FREEDV_HF_FRAME_B, (uint8_t *)(f->tx_bits), + f->tx_payload_bits, NULL, NULL); + } + + /* Allocate floating point buffer for FSK mod */ + tx_float = MALLOC(sizeof(float) * f->n_nom_modem_samples); + + /* do 4fsk mod */ + if (FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode)) { + if (f->ext_vco) { + fsk_mod_ext_vco(f->fsk, tx_float, (uint8_t *)(f->tx_bits), f->fsk->Nbits); + for (i = 0; i < f->n_nom_modem_samples; i++) { + mod_out[i] = (short)tx_float[i]; + } + } else { + fsk_mod(f->fsk, tx_float, (uint8_t *)(f->tx_bits), f->fsk->Nbits); + /* Convert float samps to short */ + for (i = 0; i < f->n_nom_modem_samples; i++) { + mod_out[i] = (short)(tx_float[i] * FSK_SCALE * NORM_PWR_FSK); + } } - - /* Allocate floating point buffer for FSK mod */ - tx_float = MALLOC(sizeof(float)*f->n_nom_modem_samples); - - /* do 4fsk mod */ - if(FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)){ - if (f->ext_vco) { - fsk_mod_ext_vco(f->fsk,tx_float,(uint8_t*)(f->tx_bits), f->fsk->Nbits); - for(i=0; i<f->n_nom_modem_samples; i++){ - mod_out[i] = (short)tx_float[i]; - } - } - else { - fsk_mod(f->fsk,tx_float,(uint8_t*)(f->tx_bits),f->fsk->Nbits); - /* Convert float samps to short */ - for(i=0; i<f->n_nom_modem_samples; i++){ - mod_out[i] = (short)(tx_float[i]*FSK_SCALE*NORM_PWR_FSK); - } - } /* do me-fsk mod */ - }else if(FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)){ - fmfsk_mod(f->fmfsk,tx_float,(uint8_t*)(f->tx_bits)); - /* Convert float samps to short */ - for(i=0; i<f->n_nom_modem_samples; i++){ - mod_out[i] = (short)(tx_float[i]*FMFSK_SCALE); - } + } else if (FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode)) { + fmfsk_mod(f->fmfsk, tx_float, (uint8_t *)(f->tx_bits)); + /* Convert float samps to short */ + for (i = 0; i < f->n_nom_modem_samples; i++) { + mod_out[i] = (short)(tx_float[i] * FMFSK_SCALE); } + } - FREE(tx_float); + FREE(tx_float); } /* TX routines for 2400 FSK modes, after codec2 encoding */ void freedv_comptx_fsk_voice(struct freedv *f, COMP mod_out[]) { - int i; - float *tx_float; /* To hold on to modulated samps from fsk/fmfsk */ - uint8_t vc_bits[2]; /* Varicode bits for 2400 framing */ - uint8_t proto_bits[3]; /* Prococol bits for 2400 framing */ - - /* Frame for 2400A/B */ - if(FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)){ - /* Get varicode bits for TX and possibly ask for a new char */ - /* 2 bits per 2400A/B frame, so this has to be done twice */ - for(i=0;i<2;i++){ - if (f->nvaricode_bits) { - vc_bits[i] = f->tx_varicode_bits[f->varicode_bit_index++]; - f->nvaricode_bits--; - } - - if (f->nvaricode_bits == 0) { - /* get new char and encode */ - char s[2]; - if (f->freedv_get_next_tx_char != NULL) { - s[0] = (*f->freedv_get_next_tx_char)(f->callback_state); - f->nvaricode_bits = varicode_encode(f->tx_varicode_bits, s, VARICODE_MAX_BITS, 1, 1); - f->varicode_bit_index = 0; - } - } + int i; + float *tx_float; /* To hold on to modulated samps from fsk/fmfsk */ + uint8_t vc_bits[2]; /* Varicode bits for 2400 framing */ + uint8_t proto_bits[3]; /* Prococol bits for 2400 framing */ + + /* Frame for 2400A/B */ + if (FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode)) { + /* Get varicode bits for TX and possibly ask for a new char */ + /* 2 bits per 2400A/B frame, so this has to be done twice */ + for (i = 0; i < 2; i++) { + if (f->nvaricode_bits) { + vc_bits[i] = f->tx_varicode_bits[f->varicode_bit_index++]; + f->nvaricode_bits--; + } + + if (f->nvaricode_bits == 0) { + /* get new char and encode */ + char s[2]; + if (f->freedv_get_next_tx_char != NULL) { + s[0] = (*f->freedv_get_next_tx_char)(f->callback_state); + f->nvaricode_bits = + varicode_encode(f->tx_varicode_bits, s, VARICODE_MAX_BITS, 1, 1); + f->varicode_bit_index = 0; } + } + } - /* If the API user hasn't set up message callbacks, don't bother with varicode bits */ - if(f->freedv_get_next_proto != NULL){ - (*f->freedv_get_next_proto)(f->proto_callback_state,(char*)proto_bits); - fvhff_frame_bits(FREEDV_VHF_FRAME_A,(uint8_t*)(f->tx_bits),f->tx_payload_bits,proto_bits,vc_bits); - }else if(f->freedv_get_next_tx_char != NULL){ - fvhff_frame_bits(FREEDV_VHF_FRAME_A,(uint8_t*)(f->tx_bits),f->tx_payload_bits,NULL,vc_bits); - }else { - fvhff_frame_bits(FREEDV_VHF_FRAME_A,(uint8_t*)(f->tx_bits),f->tx_payload_bits,NULL,NULL); - } + /* If the API user hasn't set up message callbacks, don't bother with + * varicode bits */ + if (f->freedv_get_next_proto != NULL) { + (*f->freedv_get_next_proto)(f->proto_callback_state, (char *)proto_bits); + fvhff_frame_bits(FREEDV_VHF_FRAME_A, (uint8_t *)(f->tx_bits), + f->tx_payload_bits, proto_bits, vc_bits); + } else if (f->freedv_get_next_tx_char != NULL) { + fvhff_frame_bits(FREEDV_VHF_FRAME_A, (uint8_t *)(f->tx_bits), + f->tx_payload_bits, NULL, vc_bits); + } else { + fvhff_frame_bits(FREEDV_VHF_FRAME_A, (uint8_t *)(f->tx_bits), + f->tx_payload_bits, NULL, NULL); + } /* Frame for 800XA */ - }else if(FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)){ - fvhff_frame_bits(FREEDV_HF_FRAME_B,(uint8_t*)(f->tx_bits),f->tx_payload_bits,NULL,NULL); + } else if (FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode)) { + fvhff_frame_bits(FREEDV_HF_FRAME_B, (uint8_t *)(f->tx_bits), + f->tx_payload_bits, NULL, NULL); + } + + /* Allocate floating point buffer for FSK mod */ + tx_float = MALLOC(sizeof(float) * f->n_nom_modem_samples); + + /* do 4fsk mod */ + if (FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode)) { + fsk_mod_c(f->fsk, mod_out, (uint8_t *)(f->tx_bits), f->fsk->Nbits); + /* Convert float samps to short */ + for (i = 0; i < f->n_nom_modem_samples; i++) { + mod_out[i] = fcmult(NORM_PWR_FSK, mod_out[i]); } - - /* Allocate floating point buffer for FSK mod */ - tx_float = MALLOC(sizeof(float)*f->n_nom_modem_samples); - - /* do 4fsk mod */ - if(FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)){ - fsk_mod_c(f->fsk,mod_out,(uint8_t*)(f->tx_bits), f->fsk->Nbits); - /* Convert float samps to short */ - for(i=0; i<f->n_nom_modem_samples; i++){ - mod_out[i] = fcmult(NORM_PWR_FSK,mod_out[i]); - } /* do me-fsk mod */ - }else if(FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)){ - fmfsk_mod(f->fmfsk,tx_float,(uint8_t*)(f->tx_bits)); - /* Convert float samps to short */ - for(i=0; i<f->n_nom_modem_samples; i++){ - mod_out[i].real = (tx_float[i]); - } + } else if (FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode)) { + fmfsk_mod(f->fmfsk, tx_float, (uint8_t *)(f->tx_bits)); + /* Convert float samps to short */ + for (i = 0; i < f->n_nom_modem_samples; i++) { + mod_out[i].real = (tx_float[i]); } + } - FREE(tx_float); + FREE(tx_float); } /* TX routines for 2400 FSK modes, data channel */ void freedv_tx_fsk_data(struct freedv *f, short mod_out[]) { - int i; - float *tx_float; /* To hold on to modulated samps from fsk/fmfsk */ - - if (FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)) - fvhff_frame_data_bits(f->deframer, FREEDV_HF_FRAME_B,(uint8_t*)(f->tx_bits)); - else - fvhff_frame_data_bits(f->deframer, FREEDV_VHF_FRAME_A,(uint8_t*)(f->tx_bits)); - - /* Allocate floating point buffer for FSK mod */ - tx_float = MALLOC(sizeof(float)*f->n_nom_modem_samples); - - /* do 4fsk mod */ - if (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)){ - fsk_mod(f->fsk,tx_float,(uint8_t*)(f->tx_bits), f->fsk->Nbits); - /* Convert float samps to short */ - for(i=0; i<f->n_nom_modem_samples; i++){ - mod_out[i] = (short)(tx_float[i]*FSK_SCALE); - } + int i; + float *tx_float; /* To hold on to modulated samps from fsk/fmfsk */ + + if (FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode)) + fvhff_frame_data_bits(f->deframer, FREEDV_HF_FRAME_B, + (uint8_t *)(f->tx_bits)); + else + fvhff_frame_data_bits(f->deframer, FREEDV_VHF_FRAME_A, + (uint8_t *)(f->tx_bits)); + + /* Allocate floating point buffer for FSK mod */ + tx_float = MALLOC(sizeof(float) * f->n_nom_modem_samples); + + /* do 4fsk mod */ + if (FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode)) { + fsk_mod(f->fsk, tx_float, (uint8_t *)(f->tx_bits), f->fsk->Nbits); + /* Convert float samps to short */ + for (i = 0; i < f->n_nom_modem_samples; i++) { + mod_out[i] = (short)(tx_float[i] * FSK_SCALE); + } /* do me-fsk mod */ - } else if(FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode)){ - fmfsk_mod(f->fmfsk,tx_float,(uint8_t*)(f->tx_bits)); - /* Convert float samps to short */ - for(i=0; i<f->n_nom_modem_samples; i++){ - mod_out[i] = (short)(tx_float[i]*FMFSK_SCALE); - } + } else if (FDV_MODE_ACTIVE(FREEDV_MODE_2400B, f->mode)) { + fmfsk_mod(f->fmfsk, tx_float, (uint8_t *)(f->tx_bits)); + /* Convert float samps to short */ + for (i = 0; i < f->n_nom_modem_samples; i++) { + mod_out[i] = (short)(tx_float[i] * FMFSK_SCALE); } + } - FREE(tx_float); + FREE(tx_float); } int freedv_tx_fsk_ldpc_bits_per_frame(struct freedv *f) { - return f->ldpc->coded_bits_per_frame + sizeof(fsk_ldpc_uw); + return f->ldpc->coded_bits_per_frame + sizeof(fsk_ldpc_uw); } /* in a separate function so callable by other FSK Txs */ -void freedv_tx_fsk_ldpc_framer(struct freedv *f, uint8_t frame[], uint8_t payload_data[]) { - - /* lets build up the frame to Tx ............. */ - - /* insert UW */ - memcpy(frame, fsk_ldpc_uw, sizeof(fsk_ldpc_uw)); - /* insert data bits */ - memcpy(frame + sizeof(fsk_ldpc_uw), payload_data, f->bits_per_modem_frame); - /* insert parity bits */ - encode(f->ldpc, frame + sizeof(fsk_ldpc_uw), frame + sizeof(fsk_ldpc_uw) + f->bits_per_modem_frame); +void freedv_tx_fsk_ldpc_framer(struct freedv *f, uint8_t frame[], + uint8_t payload_data[]) { + /* lets build up the frame to Tx ............. */ + + /* insert UW */ + memcpy(frame, fsk_ldpc_uw, sizeof(fsk_ldpc_uw)); + /* insert data bits */ + memcpy(frame + sizeof(fsk_ldpc_uw), payload_data, f->bits_per_modem_frame); + /* insert parity bits */ + encode(f->ldpc, frame + sizeof(fsk_ldpc_uw), + frame + sizeof(fsk_ldpc_uw) + f->bits_per_modem_frame); } /* FreeDV FSK_LDPC mode tx */ void freedv_tx_fsk_ldpc_data(struct freedv *f, COMP mod_out[]) { - int bits_per_frame = freedv_tx_fsk_ldpc_bits_per_frame(f); - uint8_t frame[bits_per_frame]; + int bits_per_frame = freedv_tx_fsk_ldpc_bits_per_frame(f); + uint8_t frame[bits_per_frame]; - assert(f->mode == FREEDV_MODE_FSK_LDPC); + assert(f->mode == FREEDV_MODE_FSK_LDPC); - freedv_tx_fsk_ldpc_framer(f, frame, f->tx_payload_bits); - fsk_mod_c(f->fsk, mod_out, frame, bits_per_frame); + freedv_tx_fsk_ldpc_framer(f, frame, f->tx_payload_bits); + fsk_mod_c(f->fsk, mod_out, frame, bits_per_frame); - /* scale samples */ - for(int i=0; i<f->n_nom_modem_samples; i++) { - mod_out[i].real *= f->tx_amp; - mod_out[i].imag *= f->tx_amp; - } + /* scale samples */ + for (int i = 0; i < f->n_nom_modem_samples; i++) { + mod_out[i].real *= f->tx_amp; + mod_out[i].imag *= f->tx_amp; + } } -void freedv_tx_fsk_ldpc_data_preamble(struct freedv *f, COMP mod_out[], int npreamble_bits, int npreamble_samples) { - struct FSK *fsk = f->fsk; - uint8_t preamble[npreamble_bits]; - // cycle through all 2 and 4FSK symbols, not sure if this is better than random - int sym = 0; - for(int i=0; i<npreamble_bits; i+=2) { - preamble[i] = (sym>>1) & 0x1; - preamble[i+1] = sym & 0x1; - sym += 1; - } - - fsk_mod_c(fsk, mod_out, preamble, npreamble_bits); - /* scale samples */ - for(int i=0; i<npreamble_samples; i++) { - mod_out[i].real *= f->tx_amp; - mod_out[i].imag *= f->tx_amp; - } +void freedv_tx_fsk_ldpc_data_preamble(struct freedv *f, COMP mod_out[], + int npreamble_bits, + int npreamble_samples) { + struct FSK *fsk = f->fsk; + uint8_t preamble[npreamble_bits]; + // cycle through all 2 and 4FSK symbols, not sure if this is better than + // random + int sym = 0; + for (int i = 0; i < npreamble_bits; i += 2) { + preamble[i] = (sym >> 1) & 0x1; + preamble[i + 1] = sym & 0x1; + sym += 1; + } + + fsk_mod_c(fsk, mod_out, preamble, npreamble_bits); + /* scale samples */ + for (int i = 0; i < npreamble_samples; i++) { + mod_out[i].real *= f->tx_amp; + mod_out[i].imag *= f->tx_amp; + } } - /* FreeDV FSK_LDPC mode rx */ int freedv_rx_fsk_ldpc_data(struct freedv *f, COMP demod_in[]) { - int bits_per_frame = freedv_tx_fsk_ldpc_bits_per_frame(f); - struct FSK *fsk = f->fsk; - float rx_filt[fsk->mode*fsk->Nsym]; - int rx_status = 0, seq = 0; - - /* Couple of layers of buffers to move chunks of fsk->Nbits into a - double buffer we can use for frame sync. There are other ways - of doing this, e.g. FIFOs */ - - /* demodulate to bit LLRs which are placed at end of buffer */ - fsk_demod_sd(fsk, rx_filt, demod_in); - fsk_rx_filt_to_llrs(&f->frame_llr[f->frame_llr_nbits], - rx_filt, fsk->v_est, fsk->SNRest, fsk->mode, fsk->Nsym); - f->nin = fsk_nin(fsk); - f->frame_llr_nbits += fsk->Nbits; - assert(f->frame_llr_nbits < f->frame_llr_size); - - if (f->frame_llr_nbits >= bits_per_frame) { - /* We have an entire frame of llrs, place them at the end of the double buffer */ - memmove(f->twoframes_llr, &f->twoframes_llr[bits_per_frame], bits_per_frame*sizeof(float)); - memcpy(&f->twoframes_llr[bits_per_frame], f->frame_llr, bits_per_frame*sizeof(float)); - - /* update new hard decisions buffer (used for UW search) */ - memmove(f->twoframes_hard, &f->twoframes_hard[bits_per_frame], bits_per_frame); - for(int i=0; i<bits_per_frame; i++) { - if (f->frame_llr[i] < 0) - f->twoframes_hard[bits_per_frame + i] = 1; - else - f->twoframes_hard[bits_per_frame + i] = 0; - } - - /* update single frame buffer */ - memmove(f->frame_llr, &f->frame_llr[bits_per_frame], (f->frame_llr_nbits-bits_per_frame)*sizeof(float)); - f->frame_llr_nbits -= bits_per_frame; - assert(f->frame_llr_nbits >= 0); - - /* Sample SNR which we report back to used in fsk->snr_est. - Note that fsk->SNRest is the SNR of the last fsk->Nbits - that were placed at the end of the buffer. We delay this - by one frame to report the SNR of the frame we are - currently decoding */ - f->snr_est = (double)10.0*log10(f->fsk_ldpc_snr); - f->fsk_ldpc_snr = fsk->SNRest; - f->fsk_S[0] = f->fsk_S[1]; f->fsk_N[0] = f->fsk_N[1]; - /* also store delayed versions of signal and noise power, useful for channel estimation */ - f->fsk_S[1] = fsk->rx_sig_pow; - f->fsk_N[1] = fsk->rx_nse_pow; - - /* OK lets run frame based processing, starting with state machine */ - - int errors = 0; - int next_state = f->fsk_ldpc_state; - switch(f->fsk_ldpc_state) { - case 0: /* out of sync - look for UW */ - f->fsk_ldpc_best_location = 0; - int best_errors = sizeof(fsk_ldpc_uw); - for(int i=0; i<bits_per_frame; i++) { - errors = 0; - for(int u=0; u<sizeof(fsk_ldpc_uw); u++) - errors += f->twoframes_hard[i+u] ^ fsk_ldpc_uw[u]; - //fprintf(stderr, " errors: %d %d %d\n", i, errors, best_errors); - if (errors < best_errors) { best_errors = errors; f->fsk_ldpc_best_location = i; } - } - if (best_errors <= f->fsk_ldpc_thresh1) { - errors = best_errors; - next_state = 1; - f->fsk_ldpc_baduw = 0; - } - break; - case 1: /* in sync */ - assert(f->fsk_ldpc_best_location >= 0); - assert(f->fsk_ldpc_best_location < bits_per_frame); - - /* check UW still OK */ - for(int u=0; u<sizeof(fsk_ldpc_uw); u++) - errors += f->twoframes_hard[f->fsk_ldpc_best_location+u] ^ fsk_ldpc_uw[u]; - if (errors > f->fsk_ldpc_thresh2) { - f->fsk_ldpc_baduw++; - if (f->fsk_ldpc_baduw >= f->fsk_ldpc_baduw_thresh) { - next_state = 0; - } - } - else f->fsk_ldpc_baduw = 0; - break; - } + int bits_per_frame = freedv_tx_fsk_ldpc_bits_per_frame(f); + struct FSK *fsk = f->fsk; + float rx_filt[fsk->mode * fsk->Nsym]; + int rx_status = 0, seq = 0; + + /* Couple of layers of buffers to move chunks of fsk->Nbits into a + double buffer we can use for frame sync. There are other ways + of doing this, e.g. FIFOs */ + + /* demodulate to bit LLRs which are placed at end of buffer */ + fsk_demod_sd(fsk, rx_filt, demod_in); + fsk_rx_filt_to_llrs(&f->frame_llr[f->frame_llr_nbits], rx_filt, fsk->v_est, + fsk->SNRest, fsk->mode, fsk->Nsym); + f->nin = fsk_nin(fsk); + f->frame_llr_nbits += fsk->Nbits; + assert(f->frame_llr_nbits < f->frame_llr_size); + + if (f->frame_llr_nbits >= bits_per_frame) { + /* We have an entire frame of llrs, place them at the end of the double + * buffer */ + memmove(f->twoframes_llr, &f->twoframes_llr[bits_per_frame], + bits_per_frame * sizeof(float)); + memcpy(&f->twoframes_llr[bits_per_frame], f->frame_llr, + bits_per_frame * sizeof(float)); + + /* update new hard decisions buffer (used for UW search) */ + memmove(f->twoframes_hard, &f->twoframes_hard[bits_per_frame], + bits_per_frame); + for (int i = 0; i < bits_per_frame; i++) { + if (f->frame_llr[i] < 0) + f->twoframes_hard[bits_per_frame + i] = 1; + else + f->twoframes_hard[bits_per_frame + i] = 0; + } - int Nerrs_raw=0, Nerrs_coded=0, iter=0, parityCheckCount=0; - if (next_state == 1) { - /* We may have a valid frame, based on the number on UW errors. Lets do a LDPC decode and check the CRC */ - - uint8_t decoded_codeword[f->ldpc->ldpc_coded_bits_per_frame]; - iter = run_ldpc_decoder(f->ldpc, decoded_codeword, - &f->twoframes_llr[f->fsk_ldpc_best_location+sizeof(fsk_ldpc_uw)], - &parityCheckCount); - memcpy(f->rx_payload_bits, decoded_codeword, f->bits_per_modem_frame); - - /* check CRC */ - if (freedv_check_crc16_unpacked(f->rx_payload_bits, f->bits_per_modem_frame)) - rx_status |= FREEDV_RX_BITS; - else { - /* if CRC failed on first frame in packet, this was probably a dud UW match, so go straight back to searching */ - if (f->fsk_ldpc_state == 0) next_state = 0; - rx_status |= FREEDV_RX_BIT_ERRORS; - } + /* update single frame buffer */ + memmove(f->frame_llr, &f->frame_llr[bits_per_frame], + (f->frame_llr_nbits - bits_per_frame) * sizeof(float)); + f->frame_llr_nbits -= bits_per_frame; + assert(f->frame_llr_nbits >= 0); + + /* Sample SNR which we report back to used in fsk->snr_est. + Note that fsk->SNRest is the SNR of the last fsk->Nbits + that were placed at the end of the buffer. We delay this + by one frame to report the SNR of the frame we are + currently decoding */ + f->snr_est = (double)10.0 * log10(f->fsk_ldpc_snr); + f->fsk_ldpc_snr = fsk->SNRest; + f->fsk_S[0] = f->fsk_S[1]; + f->fsk_N[0] = f->fsk_N[1]; + /* also store delayed versions of signal and noise power, useful for channel + * estimation */ + f->fsk_S[1] = fsk->rx_sig_pow; + f->fsk_N[1] = fsk->rx_nse_pow; + + /* OK lets run frame based processing, starting with state machine */ + + int errors = 0; + int next_state = f->fsk_ldpc_state; + switch (f->fsk_ldpc_state) { + case 0: /* out of sync - look for UW */ + f->fsk_ldpc_best_location = 0; + int best_errors = sizeof(fsk_ldpc_uw); + for (int i = 0; i < bits_per_frame; i++) { + errors = 0; + for (int u = 0; u < sizeof(fsk_ldpc_uw); u++) + errors += f->twoframes_hard[i + u] ^ fsk_ldpc_uw[u]; + // fprintf(stderr, " errors: %d %d %d\n", i, errors, best_errors); + if (errors < best_errors) { + best_errors = errors; + f->fsk_ldpc_best_location = i; + } } - f->fsk_ldpc_state = next_state; - - if (f->fsk_ldpc_state == 1) { - if (f->test_frames) { - /* regenerate tx test frame */ - uint8_t tx_frame[bits_per_frame]; - memcpy(tx_frame, fsk_ldpc_uw, sizeof(fsk_ldpc_uw)); - ofdm_generate_payload_data_bits(tx_frame + sizeof(fsk_ldpc_uw), f->bits_per_modem_frame); - int bytes_per_modem_frame = f->bits_per_modem_frame/8; - uint8_t tx_bytes[bytes_per_modem_frame]; - freedv_pack(tx_bytes, tx_frame + sizeof(fsk_ldpc_uw), f->bits_per_modem_frame); - uint16_t tx_crc16 = freedv_gen_crc16(tx_bytes, bytes_per_modem_frame - 2); - uint8_t tx_crc16_bytes[] = { tx_crc16 >> 8, tx_crc16 & 0xff }; - freedv_unpack(tx_frame + sizeof(fsk_ldpc_uw) + f->bits_per_modem_frame - 16, tx_crc16_bytes, 16); - encode(f->ldpc, tx_frame + sizeof(fsk_ldpc_uw), tx_frame + sizeof(fsk_ldpc_uw) + f->bits_per_modem_frame); - - /* count uncoded (raw) errors across UW, payload bits, parity bits */ - Nerrs_raw = count_errors(tx_frame, f->twoframes_hard + f->fsk_ldpc_best_location, bits_per_frame); - f->total_bit_errors += Nerrs_raw; - f->total_bits += bits_per_frame; - - /* count coded errors across just payload bits */ - Nerrs_coded = count_errors(tx_frame + sizeof(fsk_ldpc_uw), f->rx_payload_bits, f->bits_per_modem_frame); - f->total_bit_errors_coded += Nerrs_coded; - f->total_bits_coded += f->bits_per_modem_frame; - if (Nerrs_coded) f->total_packet_errors++; - f->total_packets++; - - } - - /* extract packet sequence numbers optionally placed in byte[0] */ - seq = 0; - for(int i=0; i<8; i++) - seq |= f->rx_payload_bits[8+i] << (7-i); + if (best_errors <= f->fsk_ldpc_thresh1) { + errors = best_errors; + next_state = 1; + f->fsk_ldpc_baduw = 0; } + break; + case 1: /* in sync */ + assert(f->fsk_ldpc_best_location >= 0); + assert(f->fsk_ldpc_best_location < bits_per_frame); + + /* check UW still OK */ + for (int u = 0; u < sizeof(fsk_ldpc_uw); u++) + errors += + f->twoframes_hard[f->fsk_ldpc_best_location + u] ^ fsk_ldpc_uw[u]; + if (errors > f->fsk_ldpc_thresh2) { + f->fsk_ldpc_baduw++; + if (f->fsk_ldpc_baduw >= f->fsk_ldpc_baduw_thresh) { + next_state = 0; + } + } else + f->fsk_ldpc_baduw = 0; + break; + } - if (f->fsk_ldpc_state == 1) rx_status |= FREEDV_RX_SYNC; /* need this set before verbose logging fprintf() */ - if (((f->verbose == 1) && (rx_status & FREEDV_RX_BITS)) || (f->verbose == 2)) { - fprintf(stderr, "%3d nbits: %3d st: %d uwloc: %3d uwerr: %2d bad_uw: %d snrdB: %4.1f eraw: %3d ecdd: %3d " - "iter: %3d pcc: %3d seq: %3d rxst: %s\n", - ++(f->frames), f->frame_llr_nbits, f->fsk_ldpc_state, f->fsk_ldpc_best_location, errors, - f->fsk_ldpc_baduw, (double)f->snr_est, Nerrs_raw, Nerrs_coded, iter, parityCheckCount, - seq, rx_sync_flags_to_text[rx_status]); - } + int Nerrs_raw = 0, Nerrs_coded = 0, iter = 0, parityCheckCount = 0; + if (next_state == 1) { + /* We may have a valid frame, based on the number on UW errors. Lets do a + * LDPC decode and check the CRC */ + + uint8_t decoded_codeword[f->ldpc->ldpc_coded_bits_per_frame]; + iter = run_ldpc_decoder( + f->ldpc, decoded_codeword, + &f->twoframes_llr[f->fsk_ldpc_best_location + sizeof(fsk_ldpc_uw)], + &parityCheckCount); + memcpy(f->rx_payload_bits, decoded_codeword, f->bits_per_modem_frame); + + /* check CRC */ + if (freedv_check_crc16_unpacked(f->rx_payload_bits, + f->bits_per_modem_frame)) + rx_status |= FREEDV_RX_BITS; + else { + /* if CRC failed on first frame in packet, this was probably a dud UW + * match, so go straight back to searching */ + if (f->fsk_ldpc_state == 0) next_state = 0; + rx_status |= FREEDV_RX_BIT_ERRORS; + } } - else { - /* set RX_SYNC flag even if we don't perform frame processing */ - if (f->fsk_ldpc_state == 1) rx_status |= FREEDV_RX_SYNC; + f->fsk_ldpc_state = next_state; + + if (f->fsk_ldpc_state == 1) { + if (f->test_frames) { + /* regenerate tx test frame */ + uint8_t tx_frame[bits_per_frame]; + memcpy(tx_frame, fsk_ldpc_uw, sizeof(fsk_ldpc_uw)); + ofdm_generate_payload_data_bits(tx_frame + sizeof(fsk_ldpc_uw), + f->bits_per_modem_frame); + int bytes_per_modem_frame = f->bits_per_modem_frame / 8; + uint8_t tx_bytes[bytes_per_modem_frame]; + freedv_pack(tx_bytes, tx_frame + sizeof(fsk_ldpc_uw), + f->bits_per_modem_frame); + uint16_t tx_crc16 = + freedv_gen_crc16(tx_bytes, bytes_per_modem_frame - 2); + uint8_t tx_crc16_bytes[] = {tx_crc16 >> 8, tx_crc16 & 0xff}; + freedv_unpack( + tx_frame + sizeof(fsk_ldpc_uw) + f->bits_per_modem_frame - 16, + tx_crc16_bytes, 16); + encode(f->ldpc, tx_frame + sizeof(fsk_ldpc_uw), + tx_frame + sizeof(fsk_ldpc_uw) + f->bits_per_modem_frame); + + /* count uncoded (raw) errors across UW, payload bits, parity bits */ + Nerrs_raw = count_errors(tx_frame, + f->twoframes_hard + f->fsk_ldpc_best_location, + bits_per_frame); + f->total_bit_errors += Nerrs_raw; + f->total_bits += bits_per_frame; + + /* count coded errors across just payload bits */ + Nerrs_coded = count_errors(tx_frame + sizeof(fsk_ldpc_uw), + f->rx_payload_bits, f->bits_per_modem_frame); + f->total_bit_errors_coded += Nerrs_coded; + f->total_bits_coded += f->bits_per_modem_frame; + if (Nerrs_coded) f->total_packet_errors++; + f->total_packets++; + } + + /* extract packet sequence numbers optionally placed in byte[0] */ + seq = 0; + for (int i = 0; i < 8; i++) seq |= f->rx_payload_bits[8 + i] << (7 - i); } - return rx_status; -} + if (f->fsk_ldpc_state == 1) + rx_status |= + FREEDV_RX_SYNC; /* need this set before verbose logging fprintf() */ + if (((f->verbose == 1) && (rx_status & FREEDV_RX_BITS)) || + (f->verbose == 2)) { + fprintf(stderr, + "%3d nbits: %3d st: %d uwloc: %3d uwerr: %2d bad_uw: %d snrdB: " + "%4.1f eraw: %3d ecdd: %3d " + "iter: %3d pcc: %3d seq: %3d rxst: %s\n", + ++(f->frames), f->frame_llr_nbits, f->fsk_ldpc_state, + f->fsk_ldpc_best_location, errors, f->fsk_ldpc_baduw, + (double)f->snr_est, Nerrs_raw, Nerrs_coded, iter, + parityCheckCount, seq, rx_sync_flags_to_text[rx_status]); + } + } else { + /* set RX_SYNC flag even if we don't perform frame processing */ + if (f->fsk_ldpc_state == 1) rx_status |= FREEDV_RX_SYNC; + } + return rx_status; +} int freedv_comprx_fsk(struct freedv *f, COMP demod_in[]) { - /* Varicode and protocol bits */ - uint8_t vc_bits[2]; - uint8_t proto_bits[3]; - short vc_bit; - int i; - int n_ascii; - char ascii_out; - int rx_status = 0; - - if(FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode)){ - fsk_demod(f->fsk,(uint8_t*)f->tx_bits,demod_in); - f->nin = fsk_nin(f->fsk); - float EbNodB = f->fsk->stats->snr_est; /* fsk demod actually estimates Eb/No */ - f->snr_est = EbNodB + 10.0*log10f(800.0/3000.0); /* so convert to SNR Rb=800, noise B=3000 */ - } else{ - /* 2400B needs real input samples */ - int n = fmfsk_nin(f->fmfsk); - float demod_in_float[n]; - for(i=0; i<n; i++) { - demod_in_float[i] = demod_in[i].real; - } - fmfsk_demod(f->fmfsk,(uint8_t*)f->tx_bits,demod_in_float); - /* The fmfsk modem operates on the baseband output of an analog FM demod so the - mapping to SNR in 8k is hard to determine */ - f->snr_est = f->fmfsk->snr_mean; - f->nin = fmfsk_nin(f->fmfsk); + /* Varicode and protocol bits */ + uint8_t vc_bits[2]; + uint8_t proto_bits[3]; + short vc_bit; + int i; + int n_ascii; + char ascii_out; + int rx_status = 0; + + if (FDV_MODE_ACTIVE(FREEDV_MODE_2400A, f->mode) || + FDV_MODE_ACTIVE(FREEDV_MODE_800XA, f->mode)) { + fsk_demod(f->fsk, (uint8_t *)f->tx_bits, demod_in); + f->nin = fsk_nin(f->fsk); + float EbNodB = + f->fsk->stats->snr_est; /* fsk demod actually estimates Eb/No */ + f->snr_est = + EbNodB + + 10.0 * + log10f(800.0 / 3000.0); /* so convert to SNR Rb=800, noise B=3000 */ + } else { + /* 2400B needs real input samples */ + int n = fmfsk_nin(f->fmfsk); + float demod_in_float[n]; + for (i = 0; i < n; i++) { + demod_in_float[i] = demod_in[i].real; } + fmfsk_demod(f->fmfsk, (uint8_t *)f->tx_bits, demod_in_float); + /* The fmfsk modem operates on the baseband output of an analog FM demod so + the mapping to SNR in 8k is hard to determine */ + f->snr_est = f->fmfsk->snr_mean; + f->nin = fmfsk_nin(f->fmfsk); + } + + rx_status = fvhff_deframe_bits(f->deframer, f->rx_payload_bits, proto_bits, + vc_bits, (uint8_t *)f->tx_bits); + if ((rx_status & FREEDV_RX_SYNC) && (rx_status & FREEDV_RX_BITS)) { + /* Decode varicode text */ + for (i = 0; i < 2; i++) { + /* Note: deframe_bits spits out bits in uint8_ts while varicode_decode + * expects shorts */ + vc_bit = vc_bits[i]; + n_ascii = + varicode_decode(&f->varicode_dec_states, &ascii_out, &vc_bit, 1, 1); + if (n_ascii && (f->freedv_put_next_rx_char != NULL)) { + (*f->freedv_put_next_rx_char)(f->callback_state, ascii_out); + } + } + /* Pass proto bits on down if callback is present */ + if (f->freedv_put_next_proto != NULL) { + (*f->freedv_put_next_proto)(f->proto_callback_state, (char *)proto_bits); + } + f->sync = 1; + } else + f->sync = 0; - rx_status = fvhff_deframe_bits(f->deframer,f->rx_payload_bits,proto_bits,vc_bits,(uint8_t*)f->tx_bits); - if((rx_status & FREEDV_RX_SYNC) && (rx_status & FREEDV_RX_BITS)){ - /* Decode varicode text */ - for(i=0; i<2; i++){ - /* Note: deframe_bits spits out bits in uint8_ts while varicode_decode expects shorts */ - vc_bit = vc_bits[i]; - n_ascii = varicode_decode(&f->varicode_dec_states, &ascii_out, &vc_bit, 1, 1); - if (n_ascii && (f->freedv_put_next_rx_char != NULL)) { - (*f->freedv_put_next_rx_char)(f->callback_state, ascii_out); - } - } - /* Pass proto bits on down if callback is present */ - if( f->freedv_put_next_proto != NULL){ - (*f->freedv_put_next_proto)(f->proto_callback_state,(char*)proto_bits); - } - f->sync = 1; - } else - f->sync = 0; - - return rx_status; + return rx_status; } - int freedv_floatrx(struct freedv *f, short speech_out[], float demod_in[]) { - assert(f != NULL); - int i; - int nin = freedv_nin(f); + assert(f != NULL); + int i; + int nin = freedv_nin(f); - assert(nin <= f->n_max_modem_samples); + assert(nin <= f->n_max_modem_samples); - COMP rx_fdm[f->n_max_modem_samples]; - for(i=0; i<nin; i++) { - rx_fdm[i].real = demod_in[i]; - rx_fdm[i].imag = 0; - } + COMP rx_fdm[f->n_max_modem_samples]; + for (i = 0; i < nin; i++) { + rx_fdm[i].real = demod_in[i]; + rx_fdm[i].imag = 0; + } - return freedv_comprx(f, speech_out, rx_fdm); + return freedv_comprx(f, speech_out, rx_fdm); } |
