aboutsummaryrefslogtreecommitdiff
path: root/src/freedv_1600.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/freedv_1600.c')
-rw-r--r--src/freedv_1600.c425
1 files changed, 219 insertions, 206 deletions
diff --git a/src/freedv_1600.c b/src/freedv_1600.c
index fa44c6a..32f7236 100644
--- a/src/freedv_1600.c
+++ b/src/freedv_1600.c
@@ -9,250 +9,263 @@
\*---------------------------------------------------------------------------*/
#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 "codec2_fdmdv.h"
-#include "golay23.h"
#include "codec2.h"
-#include "varicode.h"
-#include "freedv_api.h"
-#include "freedv_api_internal.h"
+#include "codec2_fdmdv.h"
#include "comp_prim.h"
#include "debug_alloc.h"
#include "fdmdv_internal.h"
+#include "freedv_api.h"
+#include "freedv_api_internal.h"
+#include "golay23.h"
+#include "varicode.h"
void freedv_1600_open(struct freedv *f) {
- f->snr_squelch_thresh = 2.0;
- f->squelch_en = true;
- f->tx_sync_bit = 0;
- int Nc = 16;
- f->fdmdv = fdmdv_create(Nc);
- assert(f->fdmdv != NULL);
- golay23_init();
- f->nin = f->nin_prev = FDMDV_NOM_SAMPLES_PER_FRAME;
- f->n_nom_modem_samples = 2*FDMDV_NOM_SAMPLES_PER_FRAME;
- f->n_nat_modem_samples = f->n_nom_modem_samples;
- f->n_max_modem_samples = FDMDV_NOM_SAMPLES_PER_FRAME+FDMDV_MAX_SAMPLES_PER_FRAME;
- f->modem_sample_rate = FREEDV_FS_8000;
- int nbit = fdmdv_bits_per_frame(f->fdmdv);
- f->fdmdv_bits = (int*)MALLOC(nbit*sizeof(int));
- assert(f->fdmdv_bits != NULL);
- nbit = 2*fdmdv_bits_per_frame(f->fdmdv);
- f->fdmdv_tx_bits = (int*)CALLOC(1, nbit*sizeof(int));
- f->fdmdv_rx_bits = (int*)CALLOC(1, nbit*sizeof(int));
- assert(f->fdmdv_tx_bits != NULL); assert(f->fdmdv_rx_bits != NULL);
- f->evenframe = 0;
- f->sz_error_pattern = fdmdv_error_pattern_size(f->fdmdv);
-
- 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->bits_per_modem_frame = fdmdv_bits_per_frame(f->fdmdv);
- f->bits_per_codec_frame = codec2_bits_per_frame(f->codec2);
- f->n_codec_frames = 1;
- f->tx_payload_bits = MALLOC(f->bits_per_codec_frame); assert(f->tx_payload_bits != NULL);
- f->rx_payload_bits = MALLOC(f->bits_per_codec_frame); assert(f->rx_payload_bits != NULL);
+ f->snr_squelch_thresh = 2.0;
+ f->squelch_en = true;
+ f->tx_sync_bit = 0;
+ int Nc = 16;
+ f->fdmdv = fdmdv_create(Nc);
+ assert(f->fdmdv != NULL);
+ golay23_init();
+ f->nin = f->nin_prev = FDMDV_NOM_SAMPLES_PER_FRAME;
+ f->n_nom_modem_samples = 2 * FDMDV_NOM_SAMPLES_PER_FRAME;
+ f->n_nat_modem_samples = f->n_nom_modem_samples;
+ f->n_max_modem_samples =
+ FDMDV_NOM_SAMPLES_PER_FRAME + FDMDV_MAX_SAMPLES_PER_FRAME;
+ f->modem_sample_rate = FREEDV_FS_8000;
+ int nbit = fdmdv_bits_per_frame(f->fdmdv);
+ f->fdmdv_bits = (int *)MALLOC(nbit * sizeof(int));
+ assert(f->fdmdv_bits != NULL);
+ nbit = 2 * fdmdv_bits_per_frame(f->fdmdv);
+ f->fdmdv_tx_bits = (int *)CALLOC(1, nbit * sizeof(int));
+ f->fdmdv_rx_bits = (int *)CALLOC(1, nbit * sizeof(int));
+ assert(f->fdmdv_tx_bits != NULL);
+ assert(f->fdmdv_rx_bits != NULL);
+ f->evenframe = 0;
+ f->sz_error_pattern = fdmdv_error_pattern_size(f->fdmdv);
+
+ 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->bits_per_modem_frame = fdmdv_bits_per_frame(f->fdmdv);
+ f->bits_per_codec_frame = codec2_bits_per_frame(f->codec2);
+ f->n_codec_frames = 1;
+ f->tx_payload_bits = MALLOC(f->bits_per_codec_frame);
+ assert(f->tx_payload_bits != NULL);
+ f->rx_payload_bits = MALLOC(f->bits_per_codec_frame);
+ assert(f->rx_payload_bits != NULL);
}
-
void freedv_comptx_fdmdv_1600(struct freedv *f, COMP mod_out[]) {
- int i, j;
- int data, codeword1, data_flag_index;
- COMP tx_fdm[f->n_nat_modem_samples];
-
- // spare bit in frame that codec defines. Use this 1
- // bit/frame to send txt messages
-
- data_flag_index = codec2_get_spare_bit_index(f->codec2);
-
- if (f->nvaricode_bits) {
- f->tx_payload_bits[data_flag_index] = f->tx_varicode_bits[f->varicode_bit_index++];
- f->nvaricode_bits--;
+ int i, j;
+ int data, codeword1, data_flag_index;
+ COMP tx_fdm[f->n_nat_modem_samples];
+
+ // spare bit in frame that codec defines. Use this 1
+ // bit/frame to send txt messages
+
+ data_flag_index = codec2_get_spare_bit_index(f->codec2);
+
+ if (f->nvaricode_bits) {
+ f->tx_payload_bits[data_flag_index] =
+ 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,
+ f->varicode_dec_states.code_num);
+ f->varicode_bit_index = 0;
}
+ }
- 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, f->varicode_dec_states.code_num);
- f->varicode_bit_index = 0;
- }
- }
+ /* Protect first 12 out of first 16 excitation bits with (23,12) Golay Code:
- /* Protect first 12 out of first 16 excitation bits with (23,12) Golay Code:
+ 0,1,2,3: v[0]..v[3]
+ 4,5,6,7: MSB of pitch
+ 11,12,13,14: MSB of energy
- 0,1,2,3: v[0]..v[3]
- 4,5,6,7: MSB of pitch
- 11,12,13,14: MSB of energy
+ */
- */
+ data = 0;
+ for (i = 0; i < 8; i++) {
+ data <<= 1;
+ data |= f->tx_payload_bits[i];
+ }
+ for (i = 11; i < 15; i++) {
+ data <<= 1;
+ data |= f->tx_payload_bits[i];
+ }
+ codeword1 = golay23_encode(data);
- data = 0;
- for(i=0; i<8; i++) {
- data <<= 1;
- data |= f->tx_payload_bits[i];
- }
- for(i=11; i<15; i++) {
- data <<= 1;
- data |= f->tx_payload_bits[i];
- }
- codeword1 = golay23_encode(data);
+ /* now pack output frame with parity bits at end to make them
+ as far apart as possible from the data they protect. Parity
+ bits are LSB of the Golay codeword */
- /* now pack output frame with parity bits at end to make them
- as far apart as possible from the data they protect. Parity
- bits are LSB of the Golay codeword */
+ for (i = 0; i < f->bits_per_codec_frame; i++)
+ f->fdmdv_tx_bits[i] = f->tx_payload_bits[i];
+ for (j = 0; i < f->bits_per_codec_frame + 11; i++, j++) {
+ f->fdmdv_tx_bits[i] = (codeword1 >> (10 - j)) & 0x1;
+ }
+ f->fdmdv_tx_bits[i] = 0; /* spare bit */
- for(i=0; i<f->bits_per_codec_frame; i++)
- f->fdmdv_tx_bits[i] = f->tx_payload_bits[i];
- for(j=0; i<f->bits_per_codec_frame+11; i++,j++) {
- f->fdmdv_tx_bits[i] = (codeword1 >> (10-j)) & 0x1;
- }
- f->fdmdv_tx_bits[i] = 0; /* spare bit */
+ /* optionally overwrite with test frames */
- /* optionally overwrite with test frames */
+ if (f->test_frames) {
+ fdmdv_get_test_bits(f->fdmdv, f->fdmdv_tx_bits);
+ fdmdv_get_test_bits(f->fdmdv, &f->fdmdv_tx_bits[f->bits_per_modem_frame]);
+ }
- if (f->test_frames) {
- fdmdv_get_test_bits(f->fdmdv, f->fdmdv_tx_bits);
- fdmdv_get_test_bits(f->fdmdv, &f->fdmdv_tx_bits[f->bits_per_modem_frame]);
- }
+ /* modulate even and odd frames */
- /* modulate even and odd frames */
+ fdmdv_mod(f->fdmdv, tx_fdm, f->fdmdv_tx_bits, &f->tx_sync_bit);
+ assert(f->tx_sync_bit == 1);
- fdmdv_mod(f->fdmdv, tx_fdm, f->fdmdv_tx_bits, &f->tx_sync_bit);
- assert(f->tx_sync_bit == 1);
+ fdmdv_mod(f->fdmdv, &tx_fdm[FDMDV_NOM_SAMPLES_PER_FRAME],
+ &f->fdmdv_tx_bits[f->bits_per_modem_frame], &f->tx_sync_bit);
+ assert(f->tx_sync_bit == 0);
- fdmdv_mod(f->fdmdv, &tx_fdm[FDMDV_NOM_SAMPLES_PER_FRAME], &f->fdmdv_tx_bits[f->bits_per_modem_frame], &f->tx_sync_bit);
- assert(f->tx_sync_bit == 0);
+ assert(2 * FDMDV_NOM_SAMPLES_PER_FRAME == f->n_nom_modem_samples);
- assert(2*FDMDV_NOM_SAMPLES_PER_FRAME == f->n_nom_modem_samples);
-
- for(i=0; i<f->n_nom_modem_samples; i++)
- mod_out[i] = fcmult(FDMDV_SCALE, tx_fdm[i]);
+ for (i = 0; i < f->n_nom_modem_samples; i++)
+ mod_out[i] = fcmult(FDMDV_SCALE, tx_fdm[i]);
}
-
int freedv_comprx_fdmdv_1600(struct freedv *f, COMP demod_in[]) {
- int bits_per_fdmdv_frame;
- int i, j;
- int recd_codeword, codeword1, data_flag_index, n_ascii;
- short abit[1];
- char ascii_out;
- int reliable_sync_bit;
- int rx_status = 0;
-
- COMP ademod_in[f->nin];
- for(i=0; i<f->nin; i++)
- ademod_in[i] = fcmult(1.0/FDMDV_SCALE, demod_in[i]);
-
- bits_per_fdmdv_frame = fdmdv_bits_per_frame(f->fdmdv);
-
- fdmdv_demod(f->fdmdv, f->fdmdv_bits, &reliable_sync_bit, ademod_in, &f->nin);
- fdmdv_get_demod_stats(f->fdmdv, &f->stats);
- f->sync = f->fdmdv->sync;
- f->snr_est = f->stats.snr_est;
-
- if (reliable_sync_bit == 1) {
- f->evenframe = 1;
- }
+ int bits_per_fdmdv_frame;
+ int i, j;
+ int recd_codeword, codeword1, data_flag_index, n_ascii;
+ short abit[1];
+ char ascii_out;
+ int reliable_sync_bit;
+ int rx_status = 0;
+
+ COMP ademod_in[f->nin];
+ for (i = 0; i < f->nin; i++)
+ ademod_in[i] = fcmult(1.0 / FDMDV_SCALE, demod_in[i]);
+
+ bits_per_fdmdv_frame = fdmdv_bits_per_frame(f->fdmdv);
+
+ fdmdv_demod(f->fdmdv, f->fdmdv_bits, &reliable_sync_bit, ademod_in, &f->nin);
+ fdmdv_get_demod_stats(f->fdmdv, &f->stats);
+ f->sync = f->fdmdv->sync;
+ f->snr_est = f->stats.snr_est;
+
+ if (reliable_sync_bit == 1) {
+ f->evenframe = 1;
+ }
+
+ if (f->sync) {
+ rx_status = FREEDV_RX_SYNC;
+
+ if (f->evenframe == 0) {
+ memcpy(f->fdmdv_rx_bits, f->fdmdv_bits,
+ bits_per_fdmdv_frame * sizeof(int));
+ } else {
+ memcpy(&f->fdmdv_rx_bits[bits_per_fdmdv_frame], f->fdmdv_bits,
+ bits_per_fdmdv_frame * sizeof(int));
+
+ if (f->test_frames == 0) {
+ recd_codeword = 0;
+ for (i = 0; i < 8; i++) {
+ recd_codeword <<= 1;
+ recd_codeword |= (f->fdmdv_rx_bits[i] & 0x1);
+ }
+ for (i = 11; i < 15; i++) {
+ recd_codeword <<= 1;
+ recd_codeword |= (f->fdmdv_rx_bits[i] & 0x1);
+ }
+ for (i = f->bits_per_codec_frame; i < f->bits_per_codec_frame + 11;
+ i++) {
+ recd_codeword <<= 1;
+ recd_codeword |= (f->fdmdv_rx_bits[i] & 0x1);
+ }
+ codeword1 = golay23_decode(recd_codeword);
+ f->total_bit_errors += golay23_count_errors(recd_codeword, codeword1);
+ f->total_bits += 23;
- if (f->sync) {
- rx_status = FREEDV_RX_SYNC;
+ for (i = 0; i < f->bits_per_codec_frame; i++)
+ f->rx_payload_bits[i] = f->fdmdv_rx_bits[i];
- if (f->evenframe == 0) {
- memcpy(f->fdmdv_rx_bits, f->fdmdv_bits, bits_per_fdmdv_frame*sizeof(int));
+ for (i = 0; i < 8; i++) {
+ f->rx_payload_bits[i] = (codeword1 >> (22 - i)) & 0x1;
+ }
+ for (i = 8, j = 11; i < 12; i++, j++) {
+ f->rx_payload_bits[j] = (codeword1 >> (22 - i)) & 0x1;
}
- else {
- memcpy(&f->fdmdv_rx_bits[bits_per_fdmdv_frame], f->fdmdv_bits, bits_per_fdmdv_frame*sizeof(int));
-
- if (f->test_frames == 0) {
- recd_codeword = 0;
- for(i=0; i<8; i++) {
- recd_codeword <<= 1;
- recd_codeword |= (f->fdmdv_rx_bits[i] & 0x1);
- }
- for(i=11; i<15; i++) {
- recd_codeword <<= 1;
- recd_codeword |= (f->fdmdv_rx_bits[i] & 0x1);
- }
- for(i=f->bits_per_codec_frame; i<f->bits_per_codec_frame+11; i++) {
- recd_codeword <<= 1;
- recd_codeword |= (f->fdmdv_rx_bits[i] & 0x1);
- }
- codeword1 = golay23_decode(recd_codeword);
- f->total_bit_errors += golay23_count_errors(recd_codeword, codeword1);
- f->total_bits += 23;
-
- for(i=0; i<f->bits_per_codec_frame; i++)
- f->rx_payload_bits[i] = f->fdmdv_rx_bits[i];
-
- for(i=0; i<8; i++) {
- f->rx_payload_bits[i] = (codeword1 >> (22-i)) & 0x1;
- }
- for(i=8,j=11; i<12; i++,j++) {
- f->rx_payload_bits[j] = (codeword1 >> (22-i)) & 0x1;
- }
-
- // extract txt msg data bit ------------------------------------------------------------
-
- data_flag_index = codec2_get_spare_bit_index(f->codec2);
- abit[0] = f->rx_payload_bits[data_flag_index];
-
- n_ascii = varicode_decode(&f->varicode_dec_states, &ascii_out, abit, 1, 1);
- if (n_ascii && (f->freedv_put_next_rx_char != NULL)) {
- (*f->freedv_put_next_rx_char)(f->callback_state, ascii_out);
- }
-
- // reconstruct missing bit we steal for data bit and decode
- codec2_rebuild_spare_bit(f->codec2, (char*)f->rx_payload_bits);
-
- rx_status |= FREEDV_RX_BITS;
+
+ // extract txt msg data bit
+ // ------------------------------------------------------------
+
+ data_flag_index = codec2_get_spare_bit_index(f->codec2);
+ abit[0] = f->rx_payload_bits[data_flag_index];
+
+ n_ascii =
+ varicode_decode(&f->varicode_dec_states, &ascii_out, abit, 1, 1);
+ if (n_ascii && (f->freedv_put_next_rx_char != NULL)) {
+ (*f->freedv_put_next_rx_char)(f->callback_state, ascii_out);
+ }
+
+ // reconstruct missing bit we steal for data bit and decode
+ codec2_rebuild_spare_bit(f->codec2, (char *)f->rx_payload_bits);
+
+ rx_status |= FREEDV_RX_BITS;
+ } else {
+ int test_frame_sync, bit_errors, ntest_bits, k;
+ short error_pattern[fdmdv_error_pattern_size(f->fdmdv)];
+
+ for (k = 0; k < 2; k++) {
+ /* test frames, so lets sync up to the test frames and count any
+ * errors */
+
+ fdmdv_put_test_bits(f->fdmdv, &test_frame_sync, error_pattern,
+ &bit_errors, &ntest_bits,
+ &f->fdmdv_rx_bits[k * bits_per_fdmdv_frame]);
+
+ if (test_frame_sync == 1) {
+ f->test_frame_sync_state = 1;
+ f->test_frame_count = 0;
+ }
+
+ if (f->test_frame_sync_state) {
+ if (f->test_frame_count == 0) {
+ f->total_bit_errors += bit_errors;
+ f->total_bits += ntest_bits;
+ if (f->freedv_put_error_pattern != NULL) {
+ (*f->freedv_put_error_pattern)(
+ f->error_pattern_callback_state, error_pattern,
+ fdmdv_error_pattern_size(f->fdmdv));
+ }
}
- else {
- int test_frame_sync, bit_errors, ntest_bits, k;
- short error_pattern[fdmdv_error_pattern_size(f->fdmdv)];
-
- for(k=0; k<2; k++) {
- /* test frames, so lets sync up to the test frames and count any errors */
-
- fdmdv_put_test_bits(f->fdmdv, &test_frame_sync, error_pattern, &bit_errors, &ntest_bits, &f->fdmdv_rx_bits[k*bits_per_fdmdv_frame]);
-
- if (test_frame_sync == 1) {
- f->test_frame_sync_state = 1;
- f->test_frame_count = 0;
- }
-
- if (f->test_frame_sync_state) {
- if (f->test_frame_count == 0) {
- f->total_bit_errors += bit_errors;
- f->total_bits += ntest_bits;
- if (f->freedv_put_error_pattern != NULL) {
- (*f->freedv_put_error_pattern)(f->error_pattern_callback_state, error_pattern, fdmdv_error_pattern_size(f->fdmdv));
- }
- }
- f->test_frame_count++;
- if (f->test_frame_count == 4)
- f->test_frame_count = 0;
- }
-
- }
- } /* if (test_frames == 0) .... */
+ f->test_frame_count++;
+ if (f->test_frame_count == 4) f->test_frame_count = 0;
+ }
}
+ } /* if (test_frames == 0) .... */
+ }
- /* note this freewheels if reliable sync disappears on bad channels */
+ /* note this freewheels if reliable sync disappears on bad channels */
- if (f->evenframe)
- f->evenframe = 0;
- else
- f->evenframe = 1;
+ if (f->evenframe)
+ f->evenframe = 0;
+ else
+ f->evenframe = 1;
- } /* if (sync) .... */
+ } /* if (sync) .... */
- return rx_status;
+ return rx_status;
}