first pass with data, can send messages and printf to screen. Need to think about...
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Mon, 26 Nov 2012 00:23:24 +0000 (00:23 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Mon, 26 Nov 2012 00:23:24 +0000 (00:23 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@1069 01035d8c-6547-0410-b346-abe4f91aad63

fdmdv2/src/Makefile.linux
fdmdv2/src/Makefile.win32
fdmdv2/src/fdmdv2_defines.h
fdmdv2/src/fdmdv2_main.cpp
fdmdv2/src/varicode.c
fdmdv2/src/varicode.h

index 89f1c845edc44046c38f4fe4793f318d81d5079a..54da7727f5e52de3fbf29598b98349b3919fdf7f 100644 (file)
@@ -28,9 +28,10 @@ fdmdv2_plot_waterfall_linux.o \
 fdmdv2_pa_wrapper.o \
 dlg_audiooptions.o \
 dlg_comports.o \
-dlg_filter.o
+dlg_filter.o \
+varicode.o
 
-HDRS = dlg_audiooptions.h dlg_comports.h dlg_filter.h fdmdv2_main.h fdmdv2_defines.h fdmdv2_plot.h fdmdv2_plot_scalar.h fdmdv2_plot_waterfall_linux.h fdmdv2_plot_scatter.h fdmdv2_plot_spectrum.h fdmdv2_pa_wrapper.h topFrame.h
+HDRS = dlg_audiooptions.h dlg_comports.h dlg_filter.h fdmdv2_main.h fdmdv2_defines.h fdmdv2_plot.h fdmdv2_plot_scalar.h fdmdv2_plot_waterfall_linux.h fdmdv2_plot_scatter.h fdmdv2_plot_spectrum.h fdmdv2_pa_wrapper.h topFrame.h varicode.h
 
 all: freedv
 
@@ -40,7 +41,6 @@ freedv: $(OBJS)
 %.o: %.cpp $(HDRS) Makefile.linux
        g++ $(CPP_FLAGS) -c $< -o $@
 
-
 clean:
        rm -f *.o fdmdv2
 
index dbb999742257cb231a5db6deb77fcb5d5ef1db98..7735a056b45fa59fea77c8a92a252b2e5440aedf 100644 (file)
@@ -28,9 +28,10 @@ fdmdv2_plot_waterfall_linux.o \
 fdmdv2_pa_wrapper.o \
 dlg_audiooptions.o \
 dlg_comports.o \
-dlg_filter.o
+dlg_filter.o \
+varicode.o
 
-HDRS = dlg_audiooptions.h dlg_comports.h dlg_filter.h fdmdv2_main.h fdmdv2_defines.h fdmdv2_plot.h fdmdv2_plot_scalar.h fdmdv2_plot_waterfall_linux.h fdmdv2_plot_scatter.h fdmdv2_plot_spectrum.h fdmdv2_pa_wrapper.h topFrame.h dlg_audiooptions.h topFrame.h
+HDRS = dlg_audiooptions.h dlg_comports.h dlg_filter.h fdmdv2_main.h fdmdv2_defines.h fdmdv2_plot.h fdmdv2_plot_scalar.h fdmdv2_plot_waterfall_linux.h fdmdv2_plot_scatter.h fdmdv2_plot_spectrum.h fdmdv2_pa_wrapper.h topFrame.h dlg_audiooptions.h topFrame.h varicode.h
 
 all: freedv
 
index 00dc1253ab6de85e0dc3fd78be9147c0b2e7c76b..7492d19d1f781dae01d0169f28850fe4150b84bf 100644 (file)
@@ -69,7 +69,9 @@
 
 #define SNRSLOW_BETA        0.5                           // time constant for slow SNR for display
 
+// Data
 #define MAX_TXID            1024
+#define SILENCE_THRESHOLD    100
 
 enum
 {
index c8201eb7d82d0e6311f666f6b0533789ce348a2c..74dd90e4fa99a5978dc9a0b52179b1dbaeae88a4 100644 (file)
@@ -48,7 +48,10 @@ int   g_analog;
 int   g_split;
 int   g_tx;
 float g_snr;
-char  g_txid[MAX_TXID];
+
+// sending and receiving data
+struct FIFO         *g_txDataInFifo;
+struct VARICODE_DEC  g_varicode_dec_states;
 
 // tx/rx processing states
 int                 g_nRxIn = FDMDV_NOM_SAMPLES_PER_FRAME;
@@ -89,12 +92,6 @@ float               g_TxFreqOffsetHz;
 COMP                g_TxFreqOffsetPhaseRect;
 COMP                g_TxFreqOffsetFreqRect;
 
-// DRs debug variables, will be cleaned up eventually
-int cb_cnt, cb1, cb2;
-int mute_mic = 0;
-int sc1, sc2;
-int g_outfifo2_empty;
-
 // experimental mutex to make sound card callbacks mutually exclusive
 // TODO: review code and see if we need this any more, as fifos should
 // now be thread safe
@@ -382,6 +379,11 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent)
     g_tx = 0;
     g_split = 0;
 
+    // data states
+    
+    g_txDataInFifo = fifo_create(MAX_TXID*VARICODE_MAX_BITS);   
+    varicode_decode_init(&g_varicode_dec_states);
+
 }
 
 //-------------------------------------------------------------------------
@@ -733,8 +735,20 @@ void MainFrame::OnTogBtnRxID(wxCommandEvent& event)
 void MainFrame::OnTogBtnTxID(wxCommandEvent& event)
 {
     wxString txid = m_txtCtrlTx->GetValue();
-    strncpy(g_txid, (const char*) txid.mb_str(wxConvUTF8), MAX_TXID-1);
-    printf("MainFrame::OnTogBtnTxID, sending: %s\n", g_txid);
+    char txid2[MAX_TXID];
+    strncpy(txid2, (const char*) txid.mb_str(wxConvUTF8), MAX_TXID-1);
+    
+    // varicode encode and write to tx data fifo
+
+    short varicode[MAX_TXID*VARICODE_MAX_BITS];
+    int nout = varicode_encode(varicode, txid2, MAX_TXID*VARICODE_MAX_BITS, strlen(txid2));
+    printf("tx varicode: ");
+    for(int i=0; i<nout; i++)
+        printf("%d", varicode[i]);
+    printf("\n");
+    int ret = fifo_write(g_txDataInFifo, varicode, nout);
+    printf("MainFrame::OnTogBtnTxID, sending: %s nout: %d ret: %d\n", txid2, nout, ret);
+
     event.Skip();
 }
 
@@ -1346,10 +1360,6 @@ void MainFrame::startRxStream()
     int   inputChannels1, inputChannels2;
 
     if(!m_RxRunning) {
-        cb_cnt = 0;
-        sc1 = sc2 = 0;
-        g_outfifo2_empty = 0;
-
         m_RxRunning = true;
 
         if(Pa_Initialize())
@@ -1804,9 +1814,6 @@ int MainFrame::rxCallback(
 
     wxMutexLocker lock(g_mutexProtectingCallbackData);
 
-    if (cb_cnt)
-        printf("cb1: already in a callback\n");
-    cb_cnt++;
     if (statusFlags)
         printf("cb1 statusFlags: 0x%x\n", (int)statusFlags);
 
@@ -1847,7 +1854,6 @@ int MainFrame::rxCallback(
             wptr[1] = 0;
         }
     }
-    cb_cnt--;
 
     return paContinue;
 }
@@ -1872,7 +1878,7 @@ void per_frame_rx_processing(
     int                 rx_bits[FDMDV_BITS_PER_FRAME];
     unsigned char       packed_bits[BYTES_PER_CODEC_FRAME];
     float               rx_spec[FDMDV_NSPEC];
-    int                 i;
+    int                 i,j;
     int                 nin_prev;
     int                 bit;
     int                 byte;
@@ -1972,31 +1978,70 @@ void per_frame_rx_processing(
                 }
                 if(sync_bit == 1)
                 {
+                    int data_flag_index;
+
                     // second half of frame of codec bits
                     memcpy(&codec_bits[FDMDV_BITS_PER_FRAME], rx_bits, FDMDV_BITS_PER_FRAME*sizeof(int));
-                    // pack bits, MSB received first
-                    bit  = 7;
-                    byte = 0;
-                    memset(packed_bits, 0, BYTES_PER_CODEC_FRAME);
-                    for(i = 0; i < BITS_PER_CODEC_FRAME; i++)
-                    {
-                        packed_bits[byte] |= (codec_bits[i] << bit);
-                        bit--;
-                        if(bit < 0)
-                        {
-                            bit = 7;
-                            byte++;
+
+                    // lets see if this is a data frame
+
+                    data_flag_index = codec2_get_spare_bit_index(c2);
+                    assert(data_flag_index != -1); // not supported for all rates
+                    
+                    if (codec_bits[data_flag_index]) {
+                        //printf("data_flag_index: %d\n", data_flag_index);
+                        //printf("rx data bits: ");
+                        //for(i=0; i<BITS_PER_CODEC_FRAME; i++)
+                        //    printf("%d",codec_bits[i]);
+                        //printf("\n");
+
+                        // if data construct data frame, varicode decode, write to fifo, send event
+
+                        short varicode[BITS_PER_CODEC_FRAME - 1];
+                        char  ascii_out[MAX_TXID];
+                        int   n_ascii;
+
+                        for(i=0,j=0; i<data_flag_index; i++,j++)
+                            varicode[j] = codec_bits[i];
+                        for(i=data_flag_index+1; i<BITS_PER_CODEC_FRAME; i++,j++)
+                            varicode[j] = codec_bits[i];
+                        n_ascii = varicode_decode(&g_varicode_dec_states, ascii_out, varicode, MAX_TXID, BITS_PER_CODEC_FRAME-1);
+                        
+                        if (n_ascii) {
+                            ascii_out[n_ascii] = 0;
+                            printf("%d ascii received: %s\n", n_ascii, ascii_out);
                         }
                     }
-                    assert(byte == BYTES_PER_CODEC_FRAME);
+                    else {
+
+                        // if voice reconstruct missing bit we steal for data flag and decode
+                        
+                        codec2_rebuild_spare_bit(c2, codec_bits);
 
-                    // add decoded speech to end of output buffer
+                        // pack bits, MSB received first
 
-            assert(codec2_samples_per_frame(c2) == (2*N8));
+                        bit  = 7;
+                        byte = 0;
+                        memset(packed_bits, 0, BYTES_PER_CODEC_FRAME);
+                        for(i = 0; i < BITS_PER_CODEC_FRAME; i++)
+                        {
+                            packed_bits[byte] |= (codec_bits[i] << bit);
+                            bit--;
+                            if(bit < 0)
+                                {
+                                    bit = 7;
+                                    byte++;
+                                }
+                        }
+                        assert(byte == BYTES_PER_CODEC_FRAME);
 
-            codec2_decode(c2, output_buf, packed_bits);
-            fifo_write(output_fifo, output_buf, codec2_samples_per_frame(c2));
+                        // add decoded speech to end of output buffer
 
+                        assert(codec2_samples_per_frame(c2) == (2*N8));
+
+                        codec2_decode(c2, output_buf, packed_bits);
+                        fifo_write(output_fifo, output_buf, codec2_samples_per_frame(c2));
+                    }
                 }
                 break;
         }
@@ -2015,22 +2060,72 @@ void per_frame_tx_processing(
     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;
+    int            i, bit, byte, data_flag_index;
+    unsigned int   nread;
+    short          peak, abit;
 
-    codec2_encode(c2, packed_bits, input_buf);
+    // detect silence (todo: or maybe once every 5-10 secs?)
 
-    /* unpack bits, MSB first */
+    peak = 0.0;
+    for(i=0; i<2*N8; i++) {
+        if (input_buf[i] > peak)
+           peak = input_buf[i];            
+    }
+
+    // voice/data flag is a spare bit in 1400 bit/s frame that
+    // codec defines
+
+    data_flag_index = codec2_get_spare_bit_index(c2);
+    assert(data_flag_index != -1); // not supported for all rates
+
+    // if there is low speech energy and data to send, then send data frame
+
+    if ((peak < SILENCE_THRESHOLD) && fifo_used(g_txDataInFifo)) {
+        printf("sending data ...\n");
+
+        // we have to handle the case where we might not have a whole
+        // frame of data to send, in that case pad with zeros
+
+        for(i=0; i<data_flag_index; i++) {
+            nread = fifo_read(g_txDataInFifo, &abit, 1);
+            //printf("nread: %d abit: %d\n", nread, abit);
+            if (nread)
+                bits[i] = 0;
+            else
+                bits[i] = abit;
+        }
+        bits[data_flag_index] = 1; // signals a data frame
+        for(i=data_flag_index+1; i<BITS_PER_CODEC_FRAME; i++) {
+            nread = fifo_read(g_txDataInFifo, &abit, 1);
+            if (nread)
+                bits[i] = 0;
+            else
+                bits[i] = abit;
+        }
 
-    bit = 7; byte = 0;
-    for(i=0; i<BITS_PER_CODEC_FRAME; i++) {
-    bits[i] = (packed_bits[byte] >> bit) & 0x1;
-    bit--;
-    if (bit < 0) {
-        bit = 7;
-        byte++;
+        //printf("tx data bits: ");
+        //for(i=0; i<BITS_PER_CODEC_FRAME; i++)
+        //    printf("%d",bits[i]);
+        //printf("\n");
     }
+    else {
+        codec2_encode(c2, packed_bits, input_buf);
+        
+        /* unpack bits, MSB first */
+
+        bit = 7; byte = 0;
+        for(i=0; i<BITS_PER_CODEC_FRAME; i++) {
+            bits[i] = (packed_bits[byte] >> bit) & 0x1;
+            bit--;
+            if (bit < 0) {
+                bit = 7;
+                byte++;
+            }
+        }
+        assert(byte == BYTES_PER_CODEC_FRAME);
+
+        bits[data_flag_index] = 0;
     }
-    assert(byte == BYTES_PER_CODEC_FRAME);
 
     /* modulate even and odd frames */
 
@@ -2070,9 +2165,6 @@ int MainFrame::txCallback(
 
     wxMutexLocker lock(g_mutexProtectingCallbackData);
 
-    if (cb_cnt)
-        printf("cb2: already in a callback\n");
-    cb_cnt++;
     if (statusFlags)
         printf("cb2 statusFlags: 0x%x\n", (int)statusFlags);
 
@@ -2118,8 +2210,6 @@ int MainFrame::txCallback(
         }
     }
 #endif
-    //printf("end cb2\n");
-    cb_cnt--;
     return paContinue;
 }
 
index 165f9b33e253a0ce3a8241010782a95406c75355..95ffc8a515ce33f3d79237751383c97653be0e05 100644 (file)
 #include "varicode.h"
 #include "varicode_table.h"
 
-#define VARICODE_MAX_BITS (10+2) /* 10 bits for code plus 2 0 bits for inter-character space */
 
 /*
   output is an unpacked array of bits of maximum size max_out.  Note
   unpacked arrays are a more suitable form for modulator input.
 */
 
-int varicode_encode(int varicode_out[], char ascii_in[], int max_out, int n_in) {
+int varicode_encode(short varicode_out[], char ascii_in[], int max_out, int n_in) {
     int            n_out, index, n_zeros, v_len;
     unsigned short byte1, byte2, packed;
 
@@ -83,62 +82,75 @@ int varicode_encode(int varicode_out[], char ascii_in[], int max_out, int n_in)
 
 void varicode_decode_init(struct VARICODE_DEC *dec_states)
 {
+    dec_states->state = 0;
     dec_states->n_zeros = 0;
     dec_states->v_len = 0;
     dec_states->packed = 0;
 }
 
-static int decode_one_bit(struct VARICODE_DEC *s, char *single_ascii, int varicode_in)
+static int decode_one_bit(struct VARICODE_DEC *s, char *single_ascii, short varicode_in)
 {
     int            found, i;
     unsigned short byte1, byte2;
 
-    if (varicode_in) {
-        s->packed |= (0x8000 >> s->v_len);
-        s->n_zeros = 0;
-    }
-    else {
-        s->n_zeros++;
+    //printf("decode_one_bit : state: %d varicode_in: %d packed: 0x%x n_zeros: %d\n",
+    //       s->state, varicode_in, s->packed, s->n_zeros);
+
+    if (s->state == 0) {
+        if (!varicode_in)
+            return 0;
+        else 
+            s->state = 1;
     }
-    s->v_len++;
 
-    found = 0;
+    if (s->state == 1) {
+        if (varicode_in) {
+            s->packed |= (0x8000 >> s->v_len);
+            s->n_zeros = 0;
+        }
+        else {
+            s->n_zeros++;
+        }
+        s->v_len++;
+
+        found = 0;
 
-    /* end of character code */
+        /* end of character code */
 
-    if (s->n_zeros == 2) {
-        if (s->v_len) {
-            byte1 = s->packed >> 8;
-            byte2 = s->packed & 0xff;
+        if (s->n_zeros == 2) {
+            if (s->v_len) {
+                byte1 = s->packed >> 8;
+                byte2 = s->packed & 0xff;
 
-            /* run thru table but note with bit errors means we might
-               not actually find a match */
+                /* run thru table but note with bit errors means we might
+                   not actually find a match */
 
-            for(i=0; i<128; i++) {
-                if ((byte1 == varicode_table[2*i]) && (byte2 == varicode_table[2*i+1])) {
-                    found = 1;
-                    *single_ascii = i;
+                for(i=0; i<128; i++) {
+                    if ((byte1 == varicode_table[2*i]) && (byte2 == varicode_table[2*i+1])) {
+                        found = 1;
+                        *single_ascii = i;
+                    }
                 }
             }
+            varicode_decode_init(s);
         }
-        varicode_decode_init(s);
-    }
 
-    /* code can run too long if we have a bit error */
+        /* code can run too long if we have a bit error */
+
+        if (s->v_len > VARICODE_MAX_BITS)
+            varicode_decode_init(s);
+    }
 
-    if (s->v_len > VARICODE_MAX_BITS)
-        varicode_decode_init(s);
-  
     return found;
 }
 
-int varicode_decode(struct VARICODE_DEC *dec_states, char ascii_out[], int varicode_in[], int max_out, int n_in) {
+int varicode_decode(struct VARICODE_DEC *dec_states, char ascii_out[], short varicode_in[], int max_out, int n_in) {
     int            output, n_out;
     char           single_ascii;
 
     n_out = 0;
 
-    printf("varicode_decode: n_in: %d\n", n_in);
+    //printf("varicode_decode: n_in: %d\n", n_in);
 
     while(n_in && (n_out < max_out)) {
         output = decode_one_bit(dec_states, &single_ascii, *varicode_in);
@@ -157,7 +169,7 @@ int varicode_decode(struct VARICODE_DEC *dec_states, char ascii_out[], int varic
 #ifdef VARICODE_UNITTEST
 int main(void) {
     char *ascii_in;
-    int *varicode;
+    short *varicode;
     int  i, n_varicode_bits_out, n_ascii_chars_out, length, half;
     char *ascii_out;
     struct VARICODE_DEC dec_states;
@@ -165,23 +177,27 @@ int main(void) {
     length = sizeof(varicode_table)/2;
 
     ascii_in = (char*)malloc(length);
-    varicode = (int*)malloc(VARICODE_MAX_BITS*sizeof(int)*length);
+    varicode = (short*)malloc(VARICODE_MAX_BITS*sizeof(short)*length);
     ascii_out = (char*)malloc(length);
     
+    // 1. test all Varicode codes -------------------------------------------------------------
+
     for(i=0; i<length; i++)
         ascii_in[i] = (char)i;
     n_varicode_bits_out = varicode_encode(varicode, ascii_in, VARICODE_MAX_BITS*length, length);
 
-    printf("n_varicode_bits_out: %d\n", n_varicode_bits_out);
+    //printf("n_varicode_bits_out: %d\n", n_varicode_bits_out);
+
+    // split decode in half to test how it preseves state between calls 
 
     varicode_decode_init(&dec_states);
     half = n_varicode_bits_out/2;
     n_ascii_chars_out  = varicode_decode(&dec_states, ascii_out, varicode, length, half);
-    printf("n_ascii_chars_out: %d\n", n_ascii_chars_out);
+    //printf("n_ascii_chars_out: %d\n", n_ascii_chars_out);
 
     n_ascii_chars_out += varicode_decode(&dec_states, &ascii_out[n_ascii_chars_out], 
                                          &varicode[half], length-n_ascii_chars_out, n_varicode_bits_out - half);
-    printf("n_ascii_chars_out: %d\n", n_ascii_chars_out);
+    //printf("n_ascii_chars_out: %d\n", n_ascii_chars_out);
 
     assert(n_ascii_chars_out == length);
 
@@ -190,10 +206,32 @@ int main(void) {
     //}
 
     //printf("ascii_out: %s\n", ascii_out);
+
     if (memcmp(ascii_in, ascii_out, length) == 0)
-        printf("Pass\n");
+        printf("Test 1 Pass\n");
     else
-        printf("Fail\n");
+        printf("Test 1 Fail\n");
+
+    // 2. Test some ascii with a run of zeros -----------------------------------------------------
+
+    sprintf(ascii_in, "CQ CQ CQ, this is VK5DGR");
+    assert(strlen(ascii_in) < length);
+
+    for(i=0; i<3; i++) {
+        n_varicode_bits_out = varicode_encode(varicode, ascii_in, VARICODE_MAX_BITS*length, strlen(ascii_in));
+        n_ascii_chars_out   = varicode_decode(&dec_states, ascii_out, varicode, length, n_varicode_bits_out);
+        ascii_out[n_ascii_chars_out] = 0;
+
+        printf("ascii_out: %s\n", ascii_out);
+        if (strcmp(ascii_in, ascii_out) == 0)
+            printf("Test 2 Pass\n");
+        else
+            printf("Test 2 Fail\n");
+
+        memset(varicode, 0, sizeof(short)*20);
+        n_ascii_chars_out = varicode_decode(&dec_states, ascii_out, varicode, length, 20);
+        assert(n_ascii_chars_out == 0);
+    }
 
     free(ascii_in);
     free(ascii_out);
index 591339f328024f03ccf1e4c5798eb393b76900e6..e49d476e46c96db36fc6430b6d8f8ea56224a8e1 100644 (file)
@@ -27,15 +27,19 @@ extern "C" {
 
 #endif
 
+#define VARICODE_MAX_BITS (10+2) /* max varicode bits for each ascii character */
+                                 /* 10 bits for code plus 2 0 bits for inter-character space */
+
 struct VARICODE_DEC {
+    int            state;
     int            n_zeros;
     int            v_len;
     unsigned short packed;
 };
     
-int varicode_encode(int varicode_out[], char ascii_in[], int max_out, int n_in);
+int varicode_encode(short varicode_out[], char ascii_in[], int max_out, int n_in);
 void varicode_decode_init(struct VARICODE_DEC *dec_states);
-int varicode_decode(struct VARICODE_DEC *dec_states, char ascii_out[], int varicode_in[], int max_out, int n_in);
+int varicode_decode(struct VARICODE_DEC *dec_states, char ascii_out[], short varicode_in[], int max_out, int n_in);
 
 #ifdef __cplusplus
 }