// tx/rx processing states
int g_nRxIn = FDMDV_NOM_SAMPLES_PER_FRAME;
-int g_CodecBits[MAX_BITS_PER_CODEC_FRAME];
+int g_CodecBits[2*MAX_BITS_PER_FDMDV_FRAME];
int g_State;
paCallBackData *g_rxUserdata;
varicode_decode_init(&g_varicode_dec_states);
sox_biquad_start();
-
+ golay23_init();
}
//-------------------------------------------------------------------------
// second half of frame of codec bits
memcpy(&codec_bits[bits_per_fdmdv_frame], rx_bits, bits_per_fdmdv_frame *sizeof(int));
- // extract data bit
+ // FEC Decoding --------------------------------------------------------------
+
+ if (g_mode == MODE_2000) {
+ /* decode first codeword */
+
+ recd_codeword = 0;
+ for(i=0; i<12; i++) {
+ recd_codeword <<= 1;
+ recd_codeword |= unpacked_input_bits[i];
+ }
+ for(i=bits_per_output_frame; i<bits_per_output_frame+11; i++) {
+ recd_codeword <<= 1;
+ recd_codeword |= unpacked_input_bits[i];
+ }
+ codeword1 = golay23_decode(recd_codeword);
+ //fprintf(stderr, "received codeword1: 0x%x decoded codeword1: 0x%x\n", recd_codeword, codeword1);
+
+ for(i=0; i<12; i++) {
+ unpacked_output_bits[i] = codeword1 >> (22-i);
+ }
+
+ /* decode second codeword */
+
+ recd_codeword = 0;
+ for(i=12; i<24; i++) {
+ recd_codeword <<= 1;
+ recd_codeword |= unpacked_input_bits[i];
+ }
+ for(i=bits_per_output_frame+11; i<bits_per_output_frame+11+11; i++) {
+ recd_codeword <<= 1;
+ recd_codeword |= unpacked_input_bits[i];
+ }
+ codeword2 = golay23_decode(recd_codeword);
+ //fprintf(stderr, "received codeword2: 0x%x decoded codeword2: 0x%x\n", recd_codeword, codeword2);
+
+ for(i=0; i<12; i++) {
+ unpacked_output_bits[12+i] = codeword2 >> (22-i);
+ }
+ }
+
+ // extract data bit ------------------------------------------------------------
data_flag_index = codec2_get_spare_bit_index(c2);
printf("data_flag_index: %d\n", data_flag_index);
)
{
unsigned char packed_bits[MAX_BYTES_PER_CODEC_FRAME];
- int bits[MAX_BITS_PER_CODEC_FRAME];
+ int bits[2*MAX_BITS_PER_FDMDV_FRAME];
COMP tx_fdm[2*FDMDV_NOM_SAMPLES_PER_FRAME];
COMP tx_fdm_offset[2*FDMDV_NOM_SAMPLES_PER_FRAME];
int sync_bit;
- int i, bit, byte, data_flag_index;
+ int i, j, bit, byte, data_flag_index;
short abit;
int bits_per_fdmdv_frame, bits_per_codec_frame, bytes_per_codec_frame;
}
assert(byte == bytes_per_codec_frame);
- // voice/data flag is a spare bit in 1400 bit/s frame that
- // codec defines. Use this 1 bit/frame to send call sign data
+ /* add data bit ----------------------------------*/
+
+ // spare bit in 1400 bit/s frame that codec defines. Use this 1
+ // bit/frame to send call sign data
data_flag_index = codec2_get_spare_bit_index(c2);
assert(data_flag_index != -1); // not supported for all rates
else
bits[data_flag_index] = 0;
+ /* add FEC ---------------------------------------*/
+
+ if (g_mode == MODE_2000) {
+ int data, codeword1, codeword2;
+
+ /* Protect first 24 bits with (23,12) Golay Code. The first
+ 24 bits are the most sensitive, as they contain the
+ pitch/energy VQ and voicing bits. This uses 56 + 11 + 11 =
+ 78 bits, so we have two spare in 80 bit frame sent to
+ modem. */
+
+ /* first codeword */
+
+ data = 0;
+ for(i=0; i<12; i++) {
+ data <<= 1;
+ data |= bits[i];
+ }
+ codeword1 = golay23_encode(data);
+ //fprintf(stderr, "data1: 0x%x codeword1: 0x%x\n", data, codeword1);
+
+ /* second codeword */
+
+ data = 0;
+ for(i=12; i<24; i++) {
+ data <<= 1;
+ data |= bits[i];
+ }
+ codeword2 = golay23_encode(data);
+ //fprintf(stderr, "data: 0x%x codeword2: 0x%x\n", data, codeword2);
+
+ /* now pack output frame with parity bits at end to make them
+ as far apart as possible from the data the protect. Parity
+ bits are LSB of the Golay codeword */
+
+ for(i=bits_per_codec_frame,j=0; i<bits_per_codec_frame+11; i++,j++) {
+ bits[i] = (codeword1 >> (10-j)) & 0x1;
+ }
+ for(j=0; i<bits_per_codec_frame+11+11; i++,j++) {
+ bits[i] = (codeword2 >> (10-j)) & 0x1;
+ }
+ assert(i <= 2*bits_per_fdmdv_frame);
+ }
+
/* modulate even and odd frames */
fdmdv_mod(g_pFDMDV, tx_fdm, bits, &sync_bit);