Jeroen's data channel patch applied
authorbaobrien <baobrien@01035d8c-6547-0410-b346-abe4f91aad63>
Sat, 12 Mar 2016 05:29:44 +0000 (05:29 +0000)
committerbaobrien <baobrien@01035d8c-6547-0410-b346-abe4f91aad63>
Sat, 12 Mar 2016 05:29:44 +0000 (05:29 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2729 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/src/CMakeLists.txt
codec2-dev/src/codec2.c
codec2-dev/src/codec2.h
codec2-dev/src/fmfsk.h
codec2-dev/src/freedv_api.c
codec2-dev/src/freedv_api.h
codec2-dev/src/freedv_data_channel.c [new file with mode: 0644]
codec2-dev/src/freedv_data_channel.h [new file with mode: 0644]
codec2-dev/src/freedv_vhf_framing.c
codec2-dev/src/freedv_vhf_framing.h
codec2-dev/src/fsk.h

index 1f605c4528c2dab600c055375830c2da4bd35265..acac63a822f26ec5fb4be071ef1cbbde3a75ba53 100644 (file)
@@ -157,12 +157,13 @@ set(CODEC2_SRCS
     codebookmel.c
     codebooklspmelvq.c
     codebookge.c
-    golay23.c
-    freedv_api.c
-    freedv_vhf_framing.c
-    varicode.c
-    modem_stats.c
-)
+    golay23.c\r
+    freedv_api.c\r
+    freedv_vhf_framing.c\r
+    freedv_data_channel.c\r
+    varicode.c\r
+    modem_stats.c\r
+)\r
 
 set(CODEC2_PUBLIC_HEADERS
     golay23.h
index eed45a95f0a021d91fbda42141e5ec8da9618918..485d31b1dca8b2a765c785090612f5969fc69292 100644 (file)
@@ -1750,6 +1750,80 @@ void codec2_decode_700b(struct CODEC2 *c2, short speech[], const unsigned char *
 }
 #endif
 
+/*---------------------------------------------------------------------------*\
+
+  FUNCTION....: codec2_get_energy()
+  AUTHOR......: Jeroen Vreeken
+  DATE CREATED: 08/03/2016
+
+  Extract energy value from an encoded frame.
+
+\*---------------------------------------------------------------------------*/
+
+float codec2_get_energy(struct CODEC2 *c2, const unsigned char *bits)
+{
+    assert(c2 != NULL);
+    assert(
+          (c2->mode == CODEC2_MODE_3200) ||
+          (c2->mode == CODEC2_MODE_2400) ||
+          (c2->mode == CODEC2_MODE_1600) ||
+          (c2->mode == CODEC2_MODE_1400) ||
+          (c2->mode == CODEC2_MODE_1300) ||
+          (c2->mode == CODEC2_MODE_1200) ||
+          (c2->mode == CODEC2_MODE_700) ||
+          (c2->mode == CODEC2_MODE_700B)
+          );
+    MODEL model;
+    float xq_dec[2] = {};
+    int e_index, WoE_index;
+    float e;
+    unsigned int nbit;
+
+    if (c2->mode == CODEC2_MODE_3200) {
+        nbit = 1 + 1 + WO_BITS;
+       e_index = unpack(bits, &nbit, E_BITS);
+        e = decode_energy(e_index, E_BITS);
+    }
+    if (c2->mode == CODEC2_MODE_2400) {
+        nbit = 1 + 1;
+        WoE_index = unpack(bits, &nbit, WO_E_BITS);
+        decode_WoE(&model, &e, xq_dec, WoE_index);
+    }
+    if (c2->mode == CODEC2_MODE_1600) {
+        nbit = 1 + 1 + WO_BITS;
+        e_index = unpack(bits, &nbit, E_BITS);
+        e = decode_energy(e_index, E_BITS);
+    }
+    if (c2->mode == CODEC2_MODE_1400) {
+        nbit = 1 + 1;
+        WoE_index = unpack(bits, &nbit, WO_E_BITS);
+        decode_WoE(&model, &e, xq_dec, WoE_index);
+    }
+    if (c2->mode == CODEC2_MODE_1300) {
+        nbit = 1 + 1 + 1 + 1 + WO_BITS;
+        e_index = unpack_natural_or_gray(bits, &nbit, E_BITS, c2->gray);
+        e = decode_energy(e_index, E_BITS);
+    }
+    if (c2->mode == CODEC2_MODE_1200) {
+        nbit = 1 + 1;
+        WoE_index = unpack(bits, &nbit, WO_E_BITS);
+        decode_WoE(&model, &e, xq_dec, WoE_index);
+    }
+    if (c2->mode == CODEC2_MODE_700) {
+        nbit = 1 + 5;
+        e_index = unpack_natural_or_gray(bits, &nbit, 3, c2->gray);
+        e = decode_energy(e_index, 3);
+    }
+    if (c2->mode == CODEC2_MODE_700B) {
+        nbit = 1 + 5;
+        e_index = unpack_natural_or_gray(bits, &nbit, 3, c2->gray);
+        e = decode_energy(e_index, 3);
+    }
+
+    return e;
+}
+
+
 /*---------------------------------------------------------------------------*\
 
   FUNCTION....: synthesise_one_frame()
index 8b1cb5b310b5b2936996d2edaf6579da1bcada0d..a6c608fc99a44eb994f91562a0ac6dd8d8ffcb8c 100644 (file)
@@ -54,12 +54,13 @@ int  codec2_bits_per_frame(struct CODEC2 *codec2_state);
 
 void codec2_set_lpc_post_filter(struct CODEC2 *codec2_state, int enable, int bass_boost, float beta, float gamma);
 int  codec2_get_spare_bit_index(struct CODEC2 *codec2_state);
-int  codec2_rebuild_spare_bit(struct CODEC2 *codec2_state, int unpacked_bits[]);
-void codec2_set_natural_or_gray(struct CODEC2 *codec2_state, int gray);
-void codec2_set_softdec(struct CODEC2 *c2, float *softdec);
-
-#endif
-
+int  codec2_rebuild_spare_bit(struct CODEC2 *codec2_state, int unpacked_bits[]);\r
+void codec2_set_natural_or_gray(struct CODEC2 *codec2_state, int gray);\r
+void codec2_set_softdec(struct CODEC2 *c2, float *softdec);\r
+float codec2_get_energy(struct CODEC2 *codec2_state, const unsigned char *bits);\r
+\r
+#endif\r
+\r
 #ifdef __cplusplus
 }
 #endif
index abf0c92c4dd67b81587eee33c86b917480dd2003..cd17505f5f0df605bfd9f9afb75bbf1b3ddac68b 100644 (file)
 #ifndef __C2FMFSK_H
 #define __C2FMFSK_H
 #include <stdint.h>
-#include "comp.h"
-#include "modem_stats.h"
-
-/* 
- * fm-me-2fsk state
- */
+#include "comp.h"\r
+#include "modem_stats.h"\r
+\r
+#define FMFSK_SCALE 32767\r
+\r
+/* \r
+ * fm-me-2fsk state\r
+ */\r
 struct FMFSK{
     /* Static fmfsk parameters */
     int Rb;             /* Manchester-encoded bitrate */
index 70c5be2f9a25a4cfb791816874217edbecbd33d6..ce6817dcc63fcc75ba5e11c544260243acce5d94 100644 (file)
@@ -344,7 +344,7 @@ void freedv_close(struct freedv *freedv) {
 /* real-valued short sample output, useful for going straight to DAC */
 
 /* TX routines for 2400 FSK modes, after codec2 encoding */
-static void freedv_tx_fsk(struct freedv *f, short mod_out[]) {
+static 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 */
@@ -382,15 +382,44 @@ static void freedv_tx_fsk(struct freedv *f, short mod_out[]) {
     /* do 4fsk mod */
     if(f->mode == FREEDV_MODE_2400A){
         fsk_mod(f->fsk,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]*FSK_SCALE);
+        }
     /* do me-fsk mod */
     }else if(f->mode == FREEDV_MODE_2400B){
         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);
+        }
     }
+}
+
+/* TX routines for 2400 FSK modes, data channel */
+static 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 */
         
-    /* Convert float samps to short */
-    for(i=0; i<f->n_nom_modem_samples; i++){
-        mod_out[i] = (short)(tx_float[i]*FDMDV_SCALE);
+    fvhff_frame_data_bits(f->deframer, FREEDV_VHF_FRAME_A,(uint8_t*)(f->tx_bits));
+        
+    /* Allocate floating point buffer for FSK mod */
+    tx_float = alloca(sizeof(float)*f->n_nom_modem_samples);
+        
+    /* do 4fsk mod */
+    if(f->mode == FREEDV_MODE_2400A){
+        fsk_mod(f->fsk,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]*FSK_SCALE);
+        }
+    /* do me-fsk mod */
+    }else if(f->mode == FREEDV_MODE_2400B){
+        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);
+        }
     }
 }
 
@@ -409,7 +438,7 @@ void freedv_tx(struct freedv *f, short mod_out[], short speech_in[]) {
     if((f->mode == FREEDV_MODE_2400A) || (f->mode == FREEDV_MODE_2400B)){
         codec2_encode(f->codec2, f->packed_codec_bits, speech_in);
         
-       freedv_tx_fsk(f, mod_out);
+       freedv_tx_fsk_voice(f, mod_out);
     }else{
         freedv_comptx(f, tx_fdm, speech_in);
         for(i=0; i<f->n_nom_modem_samples; i++)
@@ -653,7 +682,7 @@ void freedv_codectx(struct freedv *f, short mod_out[], unsigned char *packed_cod
            break;
         case FREEDV_MODE_2400A:
        case FREEDV_MODE_2400B:       
-            freedv_tx_fsk(f, mod_out);
+            freedv_tx_fsk_voice(f, mod_out);
            return; /* output is already real */
     }
     /* convert complex to real */
@@ -661,6 +690,24 @@ void freedv_codectx(struct freedv *f, short mod_out[], unsigned char *packed_cod
         mod_out[i] = tx_fdm[i].real;
 }
 
+void freedv_datatx  (struct freedv *f, short mod_out[]){
+    assert(f != NULL);
+
+    if (f->mode == FREEDV_MODE_2400A || f->mode == FREEDV_MODE_2400B) {
+            freedv_tx_fsk_data(f, mod_out);
+    }
+}
+
+int  freedv_data_ntxframes (struct freedv *f){
+    assert(f != NULL);
+
+    if (f->mode == FREEDV_MODE_2400A || f->mode == FREEDV_MODE_2400B) {
+        if (f->deframer->fdc)
+            return freedv_data_get_n_tx_frames(f->deframer->fdc);
+    }
+    return 0;
+}
+
 int freedv_nin(struct freedv *f) {
     if ((f->mode == FREEDV_MODE_700) || (f->mode == FREEDV_MODE_700B))
         // For mode 700, the input rate is 8000 sps, but the modem rate is 7500 sps
@@ -1262,6 +1309,55 @@ void freedv_set_callback_protocol(struct freedv *f, freedv_callback_protorx rx,
     f->proto_callback_state = callback_state;
 }
 
+/*---------------------------------------------------------------------------*\
+
+  FUNCTION....: freedv_set_callback_datarx / freedv_set_callback_datatx
+  AUTHOR......: Jeroen Vreeken
+  DATE CREATED: 04 March 2016
+
+  Set the callback functions and callback pointer that will be used for the
+  data channel. freedv_callback_datarx will be called when a packet has been
+  successfully received. freedv_callback_data_tx will be called when 
+  transmission of a new packet can begin.
+  If the returned size of the datatx callback is zero the data frame is still
+  generated, but will contain only a header update.
+\*---------------------------------------------------------------------------*/
+void freedv_set_callback_data(struct freedv *f, freedv_callback_datarx datarx, freedv_callback_datatx datatx, void *callback_state) {
+    if ((f->mode == FREEDV_MODE_2400A) || (f->mode == FREEDV_MODE_2400B)){
+        if (!f->deframer->fdc)
+            f->deframer->fdc = freedv_data_channel_create();
+        if (!f->deframer->fdc)
+            return;
+        
+        freedv_data_set_cb_rx(f->deframer->fdc, datarx, callback_state);
+        freedv_data_set_cb_tx(f->deframer->fdc, datatx, callback_state);
+    }
+}
+
+/*---------------------------------------------------------------------------*\
+
+  FUNCTION....: freedv_set_data_header
+  AUTHOR......: Jeroen Vreeken
+  DATE CREATED: 04 March 2016
+
+  Set the data header for the data channel.
+  Header compression will be used whenever packets from this header are sent.
+  The header will also be used for fill packets when a data frame is requested
+  without a packet available.
+\*---------------------------------------------------------------------------*/
+void freedv_set_data_header(struct freedv *f, unsigned char *header)
+{
+    if ((f->mode == FREEDV_MODE_2400A) || (f->mode == FREEDV_MODE_2400B)){
+        if (!f->deframer->fdc)
+            f->deframer->fdc = freedv_data_channel_create();
+        if (!f->deframer->fdc)
+            return;
+        
+        freedv_data_set_header(f->deframer->fdc, header);
+    }
+}
+
+
 /*---------------------------------------------------------------------------*\
 
   FUNCTION....: freedv_get_modem_stats
index a9805781f0e1c932d50aa56bf0484eb2a3a4c203..c95de56c9516a784c82436177ae46db5b09ab868 100644 (file)
@@ -55,38 +55,49 @@ typedef void (*freedv_calback_error_pattern)
 /* Protocol bits are packed MSB-first */
 /* Called when a frame containing protocol data is decoded */
 typedef void (*freedv_callback_protorx)(void *, char *);
-/* Called when a frame containing protocol data is to be sent */
-typedef char * (*freedv_callback_prototx)(void *);
-
-// FreeDV API functions:
-// open, close
-struct freedv *freedv_open(int mode);
+/* Called when a frame containing protocol data is to be sent */\r
+typedef char * (*freedv_callback_prototx)(void *);\r
+\r
+/* Data packet callbacks */\r
+/* Called when a packet has been received */\r
+typedef void (*freedv_callback_datarx)(void *, unsigned char *packet, size_t size);\r
+/* Called when a new packet can be send */\r
+typedef void (*freedv_callback_datatx)(void *, unsigned char *packet, size_t *size);\r
+\r
+\r
+// FreeDV API functions:\r
+// open, close\r
+struct freedv *freedv_open(int mode);\r
 void freedv_close   (struct freedv *freedv);
 // Transmit
-void freedv_tx      (struct freedv *freedv, short mod_out[], short speech_in[]);
-void freedv_comptx  (struct freedv *freedv, COMP  mod_out[], short speech_in[]);
-void freedv_codectx (struct freedv *f, short mod_out[], unsigned char *packed_codec_bits);
-// Receive
-int freedv_nin      (struct freedv *freedv);
-int freedv_rx       (struct freedv *freedv, short speech_out[], short demod_in[]);
+void freedv_tx      (struct freedv *freedv, short mod_out[], short speech_in[]);\r
+void freedv_comptx  (struct freedv *freedv, COMP  mod_out[], short speech_in[]);\r
+void freedv_codectx (struct freedv *f, short mod_out[], unsigned char *packed_codec_bits);\r
+void freedv_datatx  (struct freedv *f, short mod_out[]);\r
+int  freedv_data_ntxframes (struct freedv *freedv);\r
+// Receive\r
+int freedv_nin      (struct freedv *freedv);\r
+int freedv_rx       (struct freedv *freedv, short speech_out[], short demod_in[]);\r
 int freedv_floatrx  (struct freedv *freedv, short speech_out[], float demod_in[]);
 int freedv_comprx   (struct freedv *freedv, short speech_out[], COMP  demod_in[]);
 int freedv_codecrx  (struct freedv *freedv, unsigned char *packed_codec_bits, short demod_in[]);
-// Set parameters
-void freedv_set_callback_txt            (struct freedv *freedv, freedv_callback_rx rx, freedv_callback_tx tx, void *callback_state);
-void freedv_set_callback_protocol       (struct freedv *freedv, freedv_callback_protorx rx, freedv_callback_prototx tx, void *callback_state);
-void freedv_set_test_frames                        (struct freedv *freedv, int test_frames);
-void freedv_set_smooth_symbols             (struct freedv *freedv, int smooth_symbols);
-void freedv_set_squelch_en                         (struct freedv *freedv, int squelch_en);
+// Set parameters\r
+void freedv_set_callback_txt            (struct freedv *freedv, freedv_callback_rx rx, freedv_callback_tx tx, void *callback_state);\r
+void freedv_set_callback_protocol       (struct freedv *freedv, freedv_callback_protorx rx, freedv_callback_prototx tx, void *callback_state);\r
+void freedv_set_callback_data         (struct freedv *freedv, freedv_callback_datarx datarx, freedv_callback_datatx datatx, void *callback_state);\r
+void freedv_set_test_frames                        (struct freedv *freedv, int test_frames);\r
+void freedv_set_smooth_symbols             (struct freedv *freedv, int smooth_symbols);\r
+void freedv_set_squelch_en                         (struct freedv *freedv, int squelch_en);\r
 void freedv_set_snr_squelch_thresh         (struct freedv *freedv, float snr_squelch_thresh);
 void freedv_set_clip                   (struct freedv *freedv, int val);
 void freedv_set_total_bit_errors       (struct freedv *freedv, int val);
-void freedv_set_total_bits              (struct freedv *freedv, int val);
-void freedv_set_callback_error_pattern  (struct freedv *freedv, freedv_calback_error_pattern cb, void *state);
-void freedv_set_varicode_code_num       (struct freedv *freedv, int val);
-
-// Get parameters
-int freedv_get_version(void);
+void freedv_set_total_bits              (struct freedv *freedv, int val);\r
+void freedv_set_callback_error_pattern  (struct freedv *freedv, freedv_calback_error_pattern cb, void *state);\r
+void freedv_set_varicode_code_num       (struct freedv *freedv, int val);\r
+void freedv_set_data_header             (struct freedv *freedv, unsigned char *header);\r
+\r
+// Get parameters\r
+int freedv_get_version(void);\r
 int freedv_get_mode                 (struct freedv *freedv);
 void freedv_get_modem_stats         (struct freedv *freedv, int *sync, float *snr_est);
 void freedv_get_modem_extended_stats(struct freedv *freedv, struct MODEM_STATS *stats);
diff --git a/codec2-dev/src/freedv_data_channel.c b/codec2-dev/src/freedv_data_channel.c
new file mode 100644 (file)
index 0000000..723412e
--- /dev/null
@@ -0,0 +1,253 @@
+/*---------------------------------------------------------------------------*\\r
+\r
+  FILE........: freedv_data_channel.c\r
+  AUTHOR......: Jeroen Vreeken\r
+  DATE CREATED: 03 March 2016\r
+\r
+  Data channel for ethernet like packets in freedv VHF frames.\r
+  Currently designed for-\r
+  * 2 control bits per frame\r
+  * 4 byte counter bits per frame\r
+  * 64 bits of data per frame\r
+\*---------------------------------------------------------------------------*/\r
+\r
+/*\r
+  Copyright (C) 2016 Jeroen Vreeken\r
+\r
+  All rights reserved.\r
+\r
+  This program is free software; you can redistribute it and/or modify\r
+  it under the terms of the GNU Lesser General Public License version 2.1, as\r
+  published by the Free Software Foundation.  This program is\r
+  distributed in the hope that it will be useful, but WITHOUT ANY\r
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\r
+  License for more details.\r
+\r
+  You should have received a copy of the GNU Lesser General Public License\r
+  along with this program; if not, see <http://www.gnu.org/licenses/>.\r
+*/\r
+\r
+#include "freedv_data_channel.h"\r
+\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+static unsigned char fdc_header_bcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };\r
+\r
+/* CCIT CRC table (0x1201 polynomal) */\r
+static unsigned short fdc_crc_table[256] = {\r
+    0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,\r
+    0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,\r
+    0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,\r
+    0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,\r
+    0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,\r
+    0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,\r
+    0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,\r
+    0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,\r
+    0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,\r
+    0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,\r
+    0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,\r
+    0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,\r
+    0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,\r
+    0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,\r
+    0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,\r
+    0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,\r
+    0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,\r
+    0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,\r
+    0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,\r
+    0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,\r
+    0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,\r
+    0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,\r
+    0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,\r
+    0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,\r
+    0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,\r
+    0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,\r
+    0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,\r
+    0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,\r
+    0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,\r
+    0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,\r
+    0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,\r
+    0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78\r
+};\r
+\r
+static unsigned short fdc_crc(unsigned char *buffer, size_t len)\r
+{\r
+    unsigned short crc = 0xffff;\r
+    size_t i;\r
+\r
+    for (i = 0; i < len; i++, buffer++) {\r
+        crc = (crc >> 8) ^ fdc_crc_table[(crc ^ *buffer) & 0xff];\r
+    }\r
+\r
+    return crc ^ 0xffff;\r
+}\r
\r
+struct freedv_data_channel *freedv_data_channel_create(void)\r
+{\r
+    struct freedv_data_channel *fdc;\r
+  \r
+    fdc = malloc(sizeof(struct freedv_data_channel));\r
+    if (!fdc)\r
+        return NULL;\r
+\r
+    fdc->cb_rx = NULL;\r
+\r
+    freedv_data_set_header(fdc, fdc_header_bcast);\r
+\r
+    memcpy(fdc->rx_header, fdc->tx_header, 8);\r
+    \r
+    return fdc;\r
+}\r
+\r
+void freedv_data_channel_destroy(struct freedv_data_channel *fdc)\r
+{\r
+    free(fdc);\r
+}\r
+\r
+\r
+void freedv_data_set_cb_rx(struct freedv_data_channel *fdc, freedv_data_callback_rx cb, void *state)\r
+{\r
+    fdc->cb_rx = cb;\r
+    fdc->cb_rx_state = state;\r
+}\r
+\r
+void freedv_data_set_cb_tx(struct freedv_data_channel *fdc, freedv_data_callback_tx cb, void *state)\r
+{\r
+    fdc->cb_tx = cb;\r
+    fdc->cb_tx_state = state;\r
+}\r
+\r
+void freedv_data_channel_rx_frame(struct freedv_data_channel *fdc, unsigned char data[8], int from_bit, int bcast_bit, int end_bits)\r
+{\r
+    /* New packet? */\r
+    if (fdc->packet_rx_cnt == 0) {\r
+        /* Does the packet have a compressed from field? */\r
+        if (from_bit) {\r
+           /* Compressed from: take the previously received header */\r
+           memcpy(fdc->packet_rx + fdc->packet_rx_cnt, fdc->rx_header, 6);\r
+           fdc->packet_rx_cnt += 6;        \r
+               }\r
+       if (bcast_bit) {\r
+           /* Compressed to: fill in broadcast address */\r
+           memcpy(fdc->packet_rx + fdc->packet_rx_cnt, fdc_header_bcast, sizeof(fdc_header_bcast));\r
+           fdc->packet_rx_cnt += 6;\r
+       }\r
+    }\r
+    \r
+    int copy_bits;\r
+    if (end_bits) {\r
+        copy_bits = end_bits;\r
+    } else {\r
+        copy_bits = 8;\r
+    }\r
+    if (fdc->packet_rx_cnt + copy_bits >= FREEDV_DATA_CHANNEL_PACKET_MAX) {\r
+        /* Something went wrong... this can not be a real packet */\r
+       fdc->packet_rx_cnt = 0;\r
+       return;\r
+    }\r
+\r
+    memcpy(fdc->packet_rx + fdc->packet_rx_cnt, data, copy_bits);\r
+    fdc->packet_rx_cnt += copy_bits;\r
+    \r
+    if (end_bits != 0 && fdc->packet_rx_cnt >= 2) {\r
+        unsigned short calc_crc = fdc_crc(fdc->packet_rx, fdc->packet_rx_cnt - 2);\r
+        unsigned short rx_crc;\r
+       rx_crc = fdc->packet_rx[fdc->packet_rx_cnt - 1] << 8;\r
+        rx_crc |= fdc->packet_rx[fdc->packet_rx_cnt - 2];\r
+\r
+        if (rx_crc == calc_crc) {\r
+            if (fdc->packet_rx_cnt == 8) {\r
+               /* It is a single header field, remember it for later */\r
+                memcpy(fdc->rx_header, fdc->packet_rx, 6);\r
+            }\r
+\r
+            /* callback */\r
+            if (fdc->cb_rx) {\r
+                unsigned char tmp[6];\r
+               memcpy(tmp, fdc->packet_rx, 6);\r
+               memcpy(fdc->packet_rx, fdc->packet_rx + 6, 6);\r
+               memcpy(fdc->packet_rx + 6, tmp, 6);\r
+               \r
+               size_t size = fdc->packet_rx_cnt - 2;\r
+                if (size < 12)\r
+                    size = 12;\r
+                fdc->cb_rx(fdc->cb_rx_state, fdc->packet_rx, size);\r
+            }\r
+        }    \r
+        fdc->packet_rx_cnt = 0;\r
+    }\r
+}\r
+\r
+void freedv_data_channel_tx_frame(struct freedv_data_channel *fdc, unsigned char data[8], int *from_bit, int *bcast_bit, int *end_bits)\r
+{\r
+    *from_bit = 0;\r
+    *bcast_bit = 0;\r
+    \r
+    if (!fdc->packet_tx_size) {\r
+        fdc->packet_tx_cnt = 0;\r
+       \r
+        if (fdc->cb_tx) {\r
+            fdc->packet_tx_size = FREEDV_DATA_CHANNEL_PACKET_MAX;\r
+            fdc->cb_tx(fdc->cb_tx_state, fdc->packet_tx, &fdc->packet_tx_size);\r
+        }\r
+       if (!fdc->packet_tx_size) {\r
+           /* Nothing to send, insert a header frame */\r
+           memcpy(fdc->packet_tx, fdc->tx_header, 8);\r
+           fdc->packet_tx_size = 8;\r
+       } else {\r
+           /* new packet */\r
+           unsigned short crc;\r
+            unsigned char tmp[6];\r
+\r
+            memcpy(tmp, fdc->packet_tx, 6);\r
+           memcpy(fdc->packet_tx, fdc->packet_tx + 6, 6);\r
+           memcpy(fdc->packet_tx + 6, tmp, 6);\r
+\r
+            crc = fdc_crc(fdc->packet_tx, fdc->packet_tx_size);\r
+\r
+           fdc->packet_tx[fdc->packet_tx_size] = crc & 0xff;\r
+           fdc->packet_tx_size++;\r
+           fdc->packet_tx[fdc->packet_tx_size] = (crc >> 8) & 0xff;\r
+           fdc->packet_tx_size++;\r
+           \r
+           if (!memcmp(fdc->packet_tx, fdc->tx_header, 6)) {\r
+               *from_bit = 1;\r
+               fdc->packet_tx_cnt = 6;\r
+               \r
+               if (!memcmp(fdc->packet_tx + 6, fdc_header_bcast, 6)) {\r
+                   *bcast_bit = 1;\r
+                   fdc->packet_tx_cnt += 6;\r
+               }\r
+           }\r
+       }\r
+    }\r
+    if (fdc->packet_tx_size) {\r
+        int copy = fdc->packet_tx_size - fdc->packet_tx_cnt;\r
+       \r
+        if (copy > 8) {\r
+            copy = 8;\r
+           *end_bits = 0;\r
+        } else {\r
+            *end_bits = copy;\r
+            fdc->packet_tx_size = 0;\r
+        }\r
+        memcpy(data, fdc->packet_tx + fdc->packet_tx_cnt, copy);\r
+        fdc->packet_tx_cnt += copy;\r
+    }\r
+}\r
+\r
+void freedv_data_set_header(struct freedv_data_channel *fdc, unsigned char *header)\r
+{\r
+    unsigned short crc = fdc_crc(header, 6);\r
+\r
+    memcpy(fdc->tx_header, header, 6);\r
+    fdc->tx_header[6] = crc & 0xff;\r
+    fdc->tx_header[7] = (crc >> 8) & 0xff;\r
+}\r
+\r
+int freedv_data_get_n_tx_frames(struct freedv_data_channel *fdc)\r
+{\r
+    /* packet will be send in 8 byte frames */\r
+    return (fdc->packet_tx_size + 7) / 8;\r
+}\r
diff --git a/codec2-dev/src/freedv_data_channel.h b/codec2-dev/src/freedv_data_channel.h
new file mode 100644 (file)
index 0000000..cae2514
--- /dev/null
@@ -0,0 +1,70 @@
+/*---------------------------------------------------------------------------*\\r
+\r
+  FILE........: freedv_data_channel.h\r
+  AUTHOR......: Jeroen Vreeken\r
+  DATE CREATED: 03 March 2016\r
+\r
+  Data channel for ethernet like packets in freedv VHF frames.\r
+  Currently designed for-\r
+  * 2 control bits per frame\r
+  * 4 byte counter bits per frame\r
+  * 64 bits of data per frame\r
+\*---------------------------------------------------------------------------*/\r
+\r
+/*\r
+  Copyright (C) 2016 Jeroen Vreeken\r
+\r
+  All rights reserved.\r
+\r
+  This program is free software; you can redistribute it and/or modify\r
+  it under the terms of the GNU Lesser General Public License version 2.1, as\r
+  published by the Free Software Foundation.  This program is\r
+  distributed in the hope that it will be useful, but WITHOUT ANY\r
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\r
+  License for more details.\r
+\r
+  You should have received a copy of the GNU Lesser General Public License\r
+  along with this program; if not, see <http://www.gnu.org/licenses/>.\r
+*/\r
+\r
+#ifndef _FREEDV_DATA_CHANNEL_H\r
+#define _FREEDV_DATA_CHANNEL_H\r
+\r
+#include <stdlib.h>\r
+\r
+#define FREEDV_DATA_CHANNEL_PACKET_MAX 2048\r
+\r
+typedef void (*freedv_data_callback_rx)(void *, unsigned char *packet, size_t size);\r
+typedef void (*freedv_data_callback_tx)(void *, unsigned char *packet, size_t *size);\r
+\r
+struct freedv_data_channel {\r
+    freedv_data_callback_rx cb_rx;\r
+    void *cb_rx_state;\r
+     freedv_data_callback_tx cb_tx;\r
+    void *cb_tx_state;\r
+   \r
+    unsigned char rx_header[8];\r
+    unsigned char packet_rx[FREEDV_DATA_CHANNEL_PACKET_MAX + 2];\r
+    int packet_rx_cnt;\r
+    \r
+    unsigned char tx_header[8];\r
+    unsigned char packet_tx[FREEDV_DATA_CHANNEL_PACKET_MAX + 2];\r
+    int packet_tx_cnt;\r
+    size_t packet_tx_size;\r
+};\r
+\r
+\r
+struct freedv_data_channel *freedv_data_channel_create(void);\r
+void freedv_data_channel_destroy(struct freedv_data_channel *fdc);\r
+\r
+void freedv_data_set_cb_rx(struct freedv_data_channel *fdc, freedv_data_callback_rx cb, void *state);\r
+void freedv_data_set_cb_tx(struct freedv_data_channel *fdc, freedv_data_callback_tx cb, void *state);\r
+\r
+void freedv_data_channel_rx_frame(struct freedv_data_channel *fdc, unsigned char data[8], int from_bit, int bcast_bit, int end_bits);\r
+void freedv_data_channel_tx_frame(struct freedv_data_channel *fdc, unsigned char data[8], int *from_bit, int *bcast_bit, int *end_bits);\r
+\r
+void freedv_data_set_header(struct freedv_data_channel *fdc, unsigned char *header);\r
+int freedv_data_get_n_tx_frames(struct freedv_data_channel *fdc);\r
+\r
+#endif /* _FREEDV_DATA_CHANNEL_H */\r
index 66604fdd6d84f71d24ef1e3b2a31c5d63474296e..4d74252134fdb0bbb83ef4b984a805ed08c22312 100644 (file)
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-
-#include "freedv_vhf_framing.h"
-
-/* The UW of the VHF type A frame */
-static const uint8_t A_uw[] =      {0,1,1,0,0,1,1,1,
-                                    1,0,1,0,1,1,0,1};
-/* Blank VHF type A frame */
-static const uint8_t A_blank[] =   {1,0,1,0,0,1,1,1, /* Padding[0:3] Proto[0:3]   */
-                                    1,0,1,0,0,1,1,1, /* Proto[4:11]               */
+\r
+#include "freedv_vhf_framing.h"\r
+\r
+/* The voice UW of the VHF type A frame */\r
+static const uint8_t A_uw_v[] =    {0,1,1,0,0,1,1,1,\r
+                                    1,0,1,0,1,1,0,1};\r
+\r
+/* The data UW of the VHF type A frame */\r
+static const uint8_t A_uw_d[] =    {1,1,1,1,0,0,0,1,\r
+                                    1,1,1,1,1,1,0,0};\r
+\r
+/* Blank VHF type A frame */\r
+static const uint8_t A_blank[] =   {1,0,1,0,0,1,1,1, /* Padding[0:3] Proto[0:3]   */\r
+                                    1,0,1,0,0,1,1,1, /* Proto[4:11]               */\r
                                     0,0,0,0,0,0,0,0, /* Voice[0:7]                */
                                     0,0,0,0,0,0,0,0, /* Voice[8:15]               */
                                     0,0,0,0,0,0,0,0, /* Voice[16:23]              */
@@ -63,12 +68,16 @@ static const uint8_t A_blank[] =   {1,0,1,0,0,1,1,1, /* Padding[0:3] Proto[0:3]
 #define ST_NOSYNC 0 /* Not synchronized */
 #define ST_SYNC 1   /* Synchronized */
 
-/* Get a single bit out of an MSB-first packed byte array */
-#define UNPACK_BIT_MSBFIRST(bytes,bitidx) ((bytes)[(bitidx)>>3]>>(7-((bitidx)&0x7)))&0x1
-
-
-/* Place codec and other bits into a frame */
-void fvhff_frame_bits(  int frame_type,
+/* Get a single bit out of an MSB-first packed byte array */\r
+#define UNPACK_BIT_MSBFIRST(bytes,bitidx) ((bytes)[(bitidx)>>3]>>(7-((bitidx)&0x7)))&0x1\r
+\r
+enum frame_payload_type {\r
+       FRAME_PAYLOAD_TYPE_VOICE,\r
+       FRAME_PAYLOAD_TYPE_DATA,\r
+};\r
+\r
+/* Place codec and other bits into a frame */\r
+void fvhff_frame_bits(  int frame_type,\r
                         uint8_t bits_out[],
                         uint8_t codec2_in[],
                         uint8_t proto_in[],
@@ -111,12 +120,58 @@ void fvhff_frame_bits(  int frame_type,
             bits_out[i] = UNPACK_BIT_MSBFIRST(codec2_in,ibit);
             ibit++;
         }
-    }
-}
-
-/* Init and allocate memory for a freedv-vhf framer/deframer */
-struct freedv_vhf_deframer * fvhff_create_deframer(uint8_t frame_type, int enable_bit_flip){
-    struct freedv_vhf_deframer * deframer;
+    }\r
+}\r
+\r
+/* Place data and other bits into a frame */\r
+void fvhff_frame_data_bits(struct freedv_vhf_deframer * def, int frame_type,\r
+                        uint8_t bits_out[]){\r
+    int i,ibit;\r
+    if(frame_type == FREEDV_VHF_FRAME_A){\r
+        uint8_t data[8];\r
+       int end_bits;\r
+       int from_bit;\r
+       int bcast_bit;\r
+\r
+        /* Fill out frame with blank frame prototype */\r
+        for(i=0; i<4; i++)\r
+            bits_out[i] = A_blank[i];\r
+        for(i=92; i<96; i++)\r
+            bits_out[i] = A_blank[i];\r
+        \r
+       /* UW data */\r
+       for (i=0; i < 16; i++)\r
+           bits_out[40 + i] = A_uw_d[i];\r
+       \r
+       if (def->fdc)\r
+            freedv_data_channel_tx_frame(def->fdc, data, &from_bit, &bcast_bit, &end_bits);\r
+       else\r
+           return;\r
+\r
+       bits_out[4] = from_bit;\r
+       bits_out[5] = bcast_bit;\r
+       bits_out[6] = 0; /* unused */\r
+       bits_out[7] = 0; /* unused */\r
+\r
+        /* Fill in data bits */\r
+        ibit = 0;\r
+        for(i=8; i<40; i++){   /* First half */\r
+            bits_out[i] = UNPACK_BIT_MSBFIRST(data,ibit);\r
+            ibit++;\r
+        }\r
+        for(i=56; i<88; i++){   /* Second half */\r
+            bits_out[i] = UNPACK_BIT_MSBFIRST(data,ibit);\r
+            ibit++;\r
+        }\r
+\r
+        for (i = 0; i < 4; i++)\r
+           bits_out[88 + i] = (end_bits >> (3-i)) & 0x1;\r
+    }\r
+}\r
+\r
+/* Init and allocate memory for a freedv-vhf framer/deframer */\r
+struct freedv_vhf_deframer * fvhff_create_deframer(uint8_t frame_type, int enable_bit_flip){\r
+    struct freedv_vhf_deframer * deframer;\r
     uint8_t *bits,*invbits;
     /* It's a Type A frame */
     if(frame_type == FREEDV_VHF_FRAME_A){
@@ -145,59 +200,80 @@ struct freedv_vhf_deframer * fvhff_create_deframer(uint8_t frame_type, int enabl
         deframer->state = ST_NOSYNC;
         deframer->bitptr = 0;
         deframer->last_uw = 0;
-        deframer->miss_cnt = 0;
-        deframer->frame_size = 96;
-        deframer->on_inv_bits = 0;
-        return deframer;
-    }
-    return NULL;
-}
-
-void fvhff_destroy_deframer(struct freedv_vhf_deframer * def){
-    free(def->bits);
-    free(def);
-}
+        deframer->miss_cnt = 0;\r
+        deframer->frame_size = 96;\r
+        deframer->on_inv_bits = 0;\r
+\r
+        deframer->fdc = NULL;\r
+\r
+        return deframer;\r
+    }\r
+    return NULL;\r
+}\r
+\r
+void fvhff_destroy_deframer(struct freedv_vhf_deframer * def){\r
+    freedv_data_channel_destroy(def->fdc);\r
+    free(def->bits);\r
+    free(def);\r
+}\r
 
 int fvhff_synchronized(struct freedv_vhf_deframer * def){
     return (def->state) == ST_SYNC;
-}
-
-/* See if the UW is where it should be, to within a tolerance, in a bit buffer */
-static int fvhff_match_uw(struct freedv_vhf_deframer * def,uint8_t bits[],int tol){
-    int frame_type  = def->ftype;
-    int bitptr      = def->bitptr;
-    int frame_size  = def->frame_size;
-    int iuw,ibit;
-    const uint8_t * uw;
-    int uw_len;
-    int uw_offset;
-    int diff = 0;
-    
-    /* Set up parameters for the standard type of frame */
-    if(frame_type == FREEDV_VHF_FRAME_A){
-        uw = A_uw;
-        uw_len = 16;
-        uw_offset = 40;
-    } else {
-        return 0;
-    }
-    
-    /* Start bit pointer where UW should be */
-    ibit = bitptr + uw_offset;
-    if(ibit >= frame_size) ibit -= frame_size;
-    /* Walk through and match bits in frame with bits of UW */
-    for(iuw=0; iuw<uw_len; iuw++){
-        if(bits[ibit] != uw[iuw]) diff++;
-        ibit++;
-        if(ibit >= frame_size) ibit = 0;
-    }
-    return diff <= tol;
-}
-
-static void fvhff_extract_frame(struct freedv_vhf_deframer * def,uint8_t bits[],uint8_t codec2_out[],uint8_t proto_out[],uint8_t vc_out[]){
-    int frame_type  = def->ftype;
-    int bitptr      = def->bitptr;
-    int frame_size  = def->frame_size;
+}\r
+\r
+/* See if the UW is where it should be, to within a tolerance, in a bit buffer */\r
+static int fvhff_match_uw(struct freedv_vhf_deframer * def,uint8_t bits[],int tol, enum frame_payload_type *pt){\r
+    int frame_type  = def->ftype;\r
+    int bitptr      = def->bitptr;\r
+    int frame_size  = def->frame_size;\r
+    int iuw,ibit;\r
+    const uint8_t * uw[2];\r
+    int uw_len;\r
+    int uw_offset;\r
+    int diff[2] = { 0, 0 };\r
+    int i;\r
+    int match[2];\r
+    int r;\r
+    \r
+    /* Set up parameters for the standard type of frame */\r
+    if(frame_type == FREEDV_VHF_FRAME_A){\r
+        uw[0] = A_uw_v;\r
+       uw[1] = A_uw_d;\r
+        uw_len = 16;\r
+        uw_offset = 40;\r
+    } else {\r
+        return 0;\r
+    }\r
+    \r
+    /* Check both the voice and data UWs */\r
+    for (i = 0; i < 2; i++) {\r
+        /* Start bit pointer where UW should be */\r
+        ibit = bitptr + uw_offset;\r
+        if(ibit >= frame_size) ibit -= frame_size;\r
+        /* Walk through and match bits in frame with bits of UW */\r
+        for(iuw=0; iuw<uw_len; iuw++){\r
+            if(bits[ibit] != uw[i][iuw]) diff[i]++;\r
+            ibit++;\r
+            if(ibit >= frame_size) ibit = 0;\r
+        }\r
+       match[i] = diff[i] <= tol;\r
+    }\r
+    /* Pick the best matching UW */\r
+    if (diff[0] < diff[1]) {\r
+       r = match[0];\r
+        *pt = FRAME_PAYLOAD_TYPE_VOICE;\r
+    } else {\r
+        r = match[1];\r
+        *pt = FRAME_PAYLOAD_TYPE_DATA;\r
+    }\r
+    \r
+    return r;\r
+}\r
+\r
+static void fvhff_extract_frame_voice(struct freedv_vhf_deframer * def,uint8_t bits[],uint8_t codec2_out[],uint8_t proto_out[],uint8_t vc_out[]){\r
+    int frame_type  = def->ftype;\r
+    int bitptr      = def->bitptr;\r
+    int frame_size  = def->frame_size;\r
     int iframe,ibit;
     
     if(frame_type == FREEDV_VHF_FRAME_A){
@@ -253,12 +329,79 @@ static void fvhff_extract_frame(struct freedv_vhf_deframer * def,uint8_t bits[],
             }
         }
 
-    }
-}
-
-/*
- * Try to find the UW and extract codec/proto/vc bits in def->frame_size bits 
- */
+    }\r
+}\r
+\r
+static void fvhff_extract_frame_data(struct freedv_vhf_deframer * def,uint8_t bits[]){\r
+    int frame_type  = def->ftype;\r
+    int bitptr      = def->bitptr;\r
+    int frame_size  = def->frame_size;\r
+    int iframe,ibit;\r
+    \r
+    if(frame_type == FREEDV_VHF_FRAME_A){\r
+        uint8_t data[8];\r
+       int end_bits = 0;\r
+       int from_bit;\r
+       int bcast_bit;\r
+       \r
+        iframe = bitptr+4;\r
+        if(iframe >= frame_size) iframe-=frame_size;\r
+       from_bit = bits[iframe];\r
+       iframe++;\r
+        if(iframe >= frame_size) iframe-=frame_size;\r
+       bcast_bit = bits[iframe];\r
+\r
+        /* Extract data bits */\r
+        memset(data,0,8);\r
+        ibit = 0;\r
+        /* Extract and pack first half, MSB first */\r
+        iframe = bitptr+8;\r
+        if(iframe >= frame_size) iframe-=frame_size;\r
+        for(;ibit<32;ibit++){\r
+            data[ibit>>3] |= (bits[iframe]&0x1)<<(7-(ibit&0x7));\r
+            iframe++;\r
+            if(iframe >= frame_size) iframe=0;\r
+        }\r
+        \r
+        /* Extract and pack last half, MSB first */\r
+        iframe = bitptr+56;\r
+        if(iframe >= frame_size) iframe-=frame_size;\r
+        for(;ibit<64;ibit++){\r
+            data[ibit>>3] |= (bits[iframe]&0x1)<<(7-(ibit&0x7));\r
+            iframe++;\r
+            if(iframe >= frame_size) iframe=0;\r
+        }\r
+\r
+        /* Extract endbits value, MSB first*/\r
+        iframe = bitptr+88;\r
+       ibit = 0;\r
+        if(iframe >= frame_size) iframe-=frame_size;\r
+        for(;ibit<4;ibit++){\r
+            end_bits |= (bits[iframe]&0x1)<<(3-(ibit));\r
+            iframe++;\r
+            if(iframe >= frame_size) iframe=0;\r
+        }\r
+       \r
+       if (def->fdc) {\r
+           freedv_data_channel_rx_frame(def->fdc, data, from_bit, bcast_bit, end_bits);\r
+       }\r
+    }\r
+}\r
+\r
+static void fvhff_extract_frame(struct freedv_vhf_deframer * def,uint8_t bits[],uint8_t codec2_out[],uint8_t proto_out[],uint8_t vc_out[],enum frame_payload_type pt){\r
+    switch (pt) {\r
+        case FRAME_PAYLOAD_TYPE_VOICE:\r
+           fvhff_extract_frame_voice(def, bits, codec2_out, proto_out, vc_out);\r
+           break;\r
+       case FRAME_PAYLOAD_TYPE_DATA:\r
+           fvhff_extract_frame_data(def, bits);\r
+           break;\r
+    }\r
+}\r
+\r
+/*\r
+ * Try to find the UW and extract codec/proto/vc bits in def->frame_size bits \r
+ */\r
 int fvhff_deframe_bits(struct freedv_vhf_deframer * def,uint8_t codec2_out[],uint8_t proto_out[],uint8_t vc_out[],uint8_t bits_in[]){
     uint8_t * strbits  = def->bits;
     uint8_t * invbits  = def->invbits;
@@ -272,12 +415,13 @@ int fvhff_deframe_bits(struct freedv_vhf_deframer * def,uint8_t codec2_out[],uin
     int frame_size  = def->frame_size;
     int i;
     int uw_first_tol;   
-    int uw_sync_tol;
-    int miss_tol;
-    int extracted_frame = 0;
-    
-    /* Possibly set up frame-specific params here */
-    if(frame_type == FREEDV_VHF_FRAME_A){
+    int uw_sync_tol;\r
+    int miss_tol;\r
+    int extracted_frame = 0;\r
+    enum frame_payload_type pt;\r
+    \r
+    /* Possibly set up frame-specific params here */\r
+    if(frame_type == FREEDV_VHF_FRAME_A){\r
         uw_first_tol = 1;   /* The UW bit-error tolerance for the first frame */
         uw_sync_tol = 3;    /* The UW bit error tolerance for frames after sync */
         miss_tol = 5;       /* How many UWs may be missed before going into the de-synced state */
@@ -306,48 +450,49 @@ int fvhff_deframe_bits(struct freedv_vhf_deframer * def,uint8_t codec2_out[],uin
             }
             /* UW should be here. We're sunk, so deframe anyway */
             if(last_uw == frame_size){
-                last_uw = 0;
-                extracted_frame = 1;
-                
-                if(!fvhff_match_uw(def,bits,uw_sync_tol))
-                    miss_cnt++;
-                else
-                    miss_cnt=0;
+                last_uw = 0;\r
+                extracted_frame = 1;\r
+                \r
+                if(!fvhff_match_uw(def,bits,uw_sync_tol, &pt))\r
+                    miss_cnt++;\r
+                else\r
+                    miss_cnt=0;\r
                 
                 /* If we go over the miss tolerance, go into no-sync */
                 if(miss_cnt>miss_tol){
                     state = ST_NOSYNC;
-                }
-                /* Extract the bits */
-                extracted_frame = 1;
-                fvhff_extract_frame(def,bits,codec2_out,proto_out,vc_out);
-            }
-        /* Not yet sunk */
-        }else{
-            /* It's a sync!*/
-            if(invbits!=NULL){
-                if(fvhff_match_uw(def,invbits,uw_first_tol)){
-                    state = ST_SYNC;
-                    last_uw = 0;
-                    miss_cnt = 0;
-                    extracted_frame = 1;
-                    on_inv_bits = 1;
-                    fvhff_extract_frame(def,invbits,codec2_out,proto_out,vc_out);
-                }
-            }
-            if(fvhff_match_uw(def,strbits,uw_first_tol)){
-                state = ST_SYNC;
-                last_uw = 0;
-                miss_cnt = 0;
-                extracted_frame = 1;
-                on_inv_bits = 0;
-                fvhff_extract_frame(def,strbits,codec2_out,proto_out,vc_out);
-            }
-        }
-    }
+                }\r
+                /* Extract the bits */\r
+                extracted_frame = 1;\r
+                fvhff_extract_frame(def,bits,codec2_out,proto_out,vc_out,pt);\r
+            }\r
+        /* Not yet sunk */\r
+        }else{\r
+            /* It's a sync!*/\r
+            if(invbits!=NULL){\r
+                if(fvhff_match_uw(def,invbits,uw_first_tol, &pt)){\r
+                    state = ST_SYNC;\r
+                    last_uw = 0;\r
+                    miss_cnt = 0;\r
+                    extracted_frame = 1;\r
+                    on_inv_bits = 1;\r
+                    fvhff_extract_frame(def,invbits,codec2_out,proto_out,vc_out,pt);\r
+                }\r
+            }\r
+            if(fvhff_match_uw(def,strbits,uw_first_tol, &pt)){\r
+                state = ST_SYNC;\r
+                last_uw = 0;\r
+                miss_cnt = 0;\r
+                extracted_frame = 1;\r
+                on_inv_bits = 0;\r
+                fvhff_extract_frame(def,strbits,codec2_out,proto_out,vc_out,pt);\r
+            }\r
+        }\r
+    }\r
     def->state = state;
-    def->last_uw = last_uw;
-    def->miss_cnt = miss_cnt;
-    def->on_inv_bits = on_inv_bits;
-    return extracted_frame;
-}
+    def->last_uw = last_uw;\r
+    def->miss_cnt = miss_cnt;\r
+    def->on_inv_bits = on_inv_bits;\r
+    /* return zero for data frames, they are already handled by callback */\r
+    return extracted_frame && pt == FRAME_PAYLOAD_TYPE_VOICE;\r
+}\r
index 7ced7f3589e8916cbc297b4cbc3749c54e6b92ad..a3843ef32e4835d238a8eefaff4865cabf421bee 100644 (file)
   along with this program; if not, see <http://www.gnu.org/licenses/>.
 */
 
-#ifndef _FREEDV_VHF_FRAMING_H
-#define _FREEDV_VHF_FRAMING_H
-
-/* Standard frame type */
-#define FREEDV_VHF_FRAME_A 1
-
+#ifndef _FREEDV_VHF_FRAMING_H\r
+#define _FREEDV_VHF_FRAMING_H\r
+\r
+#include "freedv_data_channel.h"\r
+\r
+/* Standard frame type */\r
+#define FREEDV_VHF_FRAME_A 1\r
+\r
 struct freedv_vhf_deframer {
     int ftype;          /* Type of frame to be looking for */
     int state;          /* State of deframer */
@@ -47,22 +49,25 @@ struct freedv_vhf_deframer {
     
     int bitptr;         /* Pointer into circular bit buffer */
     int miss_cnt;       /* How many UWs have been missed */
-    int last_uw;        /* How many bits since the last UW? */
-    int frame_size;     /* How big is a frame? */
-    int on_inv_bits;    /* Are we using the inverted bits? */
-};
-
-/* Init and allocate memory for a freedv-vhf framer/deframer */
+    int last_uw;        /* How many bits since the last UW? */\r
+    int frame_size;     /* How big is a frame? */\r
+    int on_inv_bits;    /* Are we using the inverted bits? */\r
+\r
+    struct freedv_data_channel *fdc;\r
+};\r
+\r
+/* Init and allocate memory for a freedv-vhf framer/deframer */\r
 struct freedv_vhf_deframer * fvhff_create_deframer(uint8_t frame_type,int enable_bit_flip);
 
 /* Free the memory used by a freedv-vhf framer/deframer */
 void fvhff_destroy_deframer(struct freedv_vhf_deframer * def);
-
-/* Place codec and other bits into a frame */
-void fvhff_frame_bits(int frame_type,uint8_t bits_out[],uint8_t codec2_in[],uint8_t proto_in[],uint8_t vc_in[]);
-
-/* Find and extract frames from a stream of bits */
-int fvhff_deframe_bits(struct freedv_vhf_deframer * def,uint8_t codec2_out[],uint8_t proto_out[],uint8_t vc_out[],uint8_t bits_in[]);
+\r
+/* Place codec and other bits into a frame */\r
+void fvhff_frame_bits(int frame_type,uint8_t bits_out[],uint8_t codec2_in[],uint8_t proto_in[],uint8_t vc_in[]);\r
+void fvhff_frame_data_bits(struct freedv_vhf_deframer * def, int frame_type,uint8_t bits_out[]);\r
+\r
+/* Find and extract frames from a stream of bits */\r
+int fvhff_deframe_bits(struct freedv_vhf_deframer * def,uint8_t codec2_out[],uint8_t proto_out[],uint8_t vc_out[],uint8_t bits_in[]);\r
 
 /* Is the de-framer synchronized? */
 int fvhff_synchronized(struct freedv_vhf_deframer * def);
index 6e7a7dd5e7978f788dd41f500b7d6ecfb429e44b..29563dca596171a2cce52e6a041f253eb0471f4f 100644 (file)
 #include "kiss_fftr.h"
 #include "modem_stats.h"
 
-#define MODE_2FSK 2
-#define MODE_4FSK 4
-
-struct FSK {
-    /*  Static parameters set up by fsk_init */
-    int Ndft;               /* buffer size for freq offset est fft */
+#define MODE_2FSK 2\r
+#define MODE_4FSK 4\r
+\r
+#define FSK_SCALE 16383\r
+\r
+struct FSK {\r
+    /*  Static parameters set up by fsk_init */\r
+    int Ndft;               /* buffer size for freq offset est fft */\r
     int Fs;                 /* sample freq */
     int N;                  /* processing buffer size */
     int Rs;                 /* symbol rate */