refactored varicode impl and api, freedv links with it ok, need to hook up option...
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sun, 1 Jun 2014 05:55:23 +0000 (05:55 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sun, 1 Jun 2014 05:55:23 +0000 (05:55 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@1622 01035d8c-6547-0410-b346-abe4f91aad63

fdmdv2/src/fdmdv2_main.cpp
fdmdv2/src/varicode.c
fdmdv2/src/varicode.h
fdmdv2/src/varicode_table.h

index e85ba27666a4c785f9ea81b076f7ad383e682070..bca6bcadba2c4271055f6d9aec5a1db68beb8027 100644 (file)
@@ -450,7 +450,7 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent)
     // data states
     g_txDataInFifo = fifo_create(MAX_CALLSIGN*VARICODE_MAX_BITS);
     g_rxDataOutFifo = fifo_create(MAX_CALLSIGN*VARICODE_MAX_BITS);
-    varicode_decode_init(&g_varicode_dec_states);
+    varicode_decode_init(&g_varicode_dec_states, 1);
 
     sox_biquad_start();
     golay23_init();
@@ -898,7 +898,7 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
         // varicode encode and write to tx data fifo
 
         short varicode[MAX_CALLSIGN*VARICODE_MAX_BITS];
-        int nout = varicode_encode(varicode, callsigncr, MAX_CALLSIGN*VARICODE_MAX_BITS, strlen(callsign)+1);
+        int nout = varicode_encode(varicode, callsigncr, MAX_CALLSIGN*VARICODE_MAX_BITS, strlen(callsign)+1, 1);
         fifo_write(g_txDataInFifo, varicode, nout);
         //printf("Callsign sending: %s nout: %d\n", callsign, nout);
     }
index c7b6d676f677786e27e4953a52e1f9a878107ce8..9bfb5dca1d817ceb316a896572030b06cb70b9be 100644 (file)
   output is an unpacked array of bits of maximum size max_out.  Note
   unpacked arrays are a more suitable form for modulator input.
 
-  longcode == 1 varicode table that covers entire ASCII char set
-  longcode == 0 is the short, more efficient table, which covers a subset of the ASCII char set. Unknown
-              chars are replaced with spaces.  This mode works with two bits at a time.
+  Code 1 covers the entire ASCII char set.
 */
 
-int varicode_encode(short varicode_out[], char ascii_in[], int max_out, int n_in, int long_code) {
-    int            n_out, index, n_zeros, v_len, i;
+int varicode_encode1(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;
 
     n_out = 0;
 
     while(n_in && (n_out < max_out)) {
 
-        if (long_code) {
-            assert((unsigned int)(*ascii_in) < 128);
+        assert((unsigned int)(*ascii_in) < 128);
 
-            index = 2*(unsigned int)(*ascii_in);
-            byte1 = long_varicode_table[index];
-            byte2 = long_varicode_table[index+1];
-            packed = (byte1 << 8) + byte2;
+        index = 2*(unsigned int)(*ascii_in);
+        byte1 = varicode_table1[index];
+        byte2 = varicode_table1[index+1];
+        packed = (byte1 << 8) + byte2;
+
+        //printf("n_in: %d ascii_in: %c index: %d packed 0x%x\n", n_in, *ascii_in, index, packed);
+        ascii_in++;
+
+        n_zeros = 0;
+        v_len = 0;
+        while ((n_zeros < 2) && (n_out < max_out) && (v_len <= VARICODE_MAX_BITS)) {
+            if (packed & 0x8000) {
+                *varicode_out = 1;
+                n_zeros = 0;
+            }
+            else {
+                *varicode_out = 0;
+                n_zeros++;
+            }
+            //printf("packed: 0x%x *varicode_out: %d n_zeros: %d v_len: %d\n", packed, *varicode_out, n_zeros,v_len );
+            packed <<= 1;
+            varicode_out++;
+            n_out++;
+            v_len++;                
         }
-        else {
+        assert(v_len <= VARICODE_MAX_BITS);
+
+        n_in--;            
+    }
+
+    return n_out;
+}
+
+
+/*
+  Code 2 covers a subset, but is more efficient that Code 1 (282
+  compared to 1315 bits on unittest) Unsupported characters are
+  replaced by spaces.  We encode/decode two bits at a time.  
+*/
 
-            packed = short_varicode_table[0]; // default to space if char not found
+int varicode_encode2(short varicode_out[], char ascii_in[], int max_out, int n_in) {
+    int            n_out, n_zeros, v_len, i;
+    unsigned short packed;
+
+    n_out = 0;
+
+    while(n_in && (n_out < max_out)) {
+
+        packed = varicode_table2[0]; // default to space if char not found
           
-            // see if our character exists
-            for(i=0; i<sizeof(short_varicode_table); i+=2) {
-                if (short_varicode_table[i] == *ascii_in)
-                    packed = (unsigned short)short_varicode_table[i+1] << 8;
-            }
+        // see if our character exists
+        for(i=0; i<sizeof(varicode_table2); i+=2) {
+            if (varicode_table2[i] == *ascii_in)
+                packed = (unsigned short)varicode_table2[i+1] << 8;
         }
 
         //printf("n_in: %d ascii_in: %c index: %d packed 0x%x\n", n_in, *ascii_in, index, packed);
@@ -74,62 +111,64 @@ int varicode_encode(short varicode_out[], char ascii_in[], int max_out, int n_in
         n_zeros = 0;
         v_len = 0;
         while ((n_zeros < 2) && (n_out < max_out) && (v_len <= VARICODE_MAX_BITS)) {
-            if (long_code) {
-                if (packed & 0x8000) {
-                    *varicode_out = 1;
-                    n_zeros = 0;
-                }
-                else {
-                    *varicode_out = 0;
-                    n_zeros++;
-                }
-                //printf("packed: 0x%x *varicode_out: %d n_zeros: %d v_len: %d\n", packed, *varicode_out, n_zeros,v_len );
-                packed <<= 1;
-                varicode_out++;
-                n_out++;
-                v_len++;
-            }
-            else {
-                if (packed & 0x8000)
-                    varicode_out[0] = 1;
-                else
-                    varicode_out[0] = 0;
+            if (packed & 0x8000)
+                varicode_out[0] = 1;
+            else
+                varicode_out[0] = 0;
                     
-                if (packed & 0x4000)
-                    varicode_out[1] = 1;
-                else
-                    varicode_out[1] = 0;
-                
-                if (packed & 0xc000)
-                    n_zeros = 0;
-                else
-                    n_zeros += 2;
-
-                //printf("packed: 0x%x *varicode_out: %d n_zeros: %d v_len: %d\n", packed, *varicode_out, n_zeros,v_len );
-                packed <<= 2;
-                varicode_out +=2;
-                n_out += 2;
-                v_len += 2;
-           }
+            if (packed & 0x4000)
+                varicode_out[1] = 1;
+            else
+                varicode_out[1] = 0;
                 
+            if (packed & 0xc000)
+                n_zeros = 0;
+            else
+                n_zeros += 2;
+
+            //printf("packed: 0x%x *varicode_out: %d n_zeros: %d v_len: %d\n", packed, *varicode_out, n_zeros,v_len );
+            packed <<= 2;
+            varicode_out +=2;
+            n_out += 2;
+            v_len += 2;
         }
         assert(v_len <= VARICODE_MAX_BITS);
 
         n_in--;            
     }
 
+    assert((n_out % 2) == 0);  /* outputs two bits at a time */
+
     return n_out;
 }
 
-void varicode_decode_init(struct VARICODE_DEC *dec_states)
+
+int varicode_encode(short varicode_out[], char ascii_in[], int max_out, int n_in, int code_num) {
+    
+    assert((code_num ==1) || (code_num ==2));
+
+    if (code_num == 1)
+        return varicode_encode1(varicode_out, ascii_in, max_out, n_in);
+    else
+       return  varicode_encode2(varicode_out, ascii_in, max_out, n_in);
+}
+
+
+void varicode_decode_init(struct VARICODE_DEC *dec_states, int code_num)
 {
+    assert((code_num ==1) || (code_num ==2));
+
     dec_states->state = 0;
     dec_states->n_zeros = 0;
     dec_states->v_len = 0;
     dec_states->packed = 0;
+    dec_states->code_num = code_num;
 }
 
-static int decode_one_bit(struct VARICODE_DEC *s, char *single_ascii, short varicode_in1, short varicode_in2, int long_code)
+
+/* Code 1 decode function, accepts one bit at a time */
+
+static int decode_one_bit(struct VARICODE_DEC *s, char *single_ascii, short varicode_in, int long_code)
 {
     int            found, i;
     unsigned short byte1, byte2;
@@ -138,45 +177,21 @@ static int decode_one_bit(struct VARICODE_DEC *s, char *single_ascii, short vari
     //       s->state, varicode_in, s->packed, s->n_zeros);
 
     if (s->state == 0) {
-        if (long_code) {
-            if (!varicode_in1)
-                return 0;
-            else 
-                s->state = 1;
-        }
-        else {
-            if (!(varicode_in1 || varicode_in2))
-                return 0;
-            else 
-                s->state = 1;
-       }
-
+        if (!varicode_in)
+            return 0;
+        else 
+            s->state = 1;
     }
 
     if (s->state == 1) {
-        if (long_code) {
-            if (varicode_in1) {
-                s->packed |= (0x8000 >> s->v_len);
-                s->n_zeros = 0;
-            }
-            else {
-                s->n_zeros++;
-            }
-            s->v_len++;
+        if (varicode_in) {
+            s->packed |= (0x8000 >> s->v_len);
+            s->n_zeros = 0;
         }
         else {
-            if (varicode_in1)
-                s->packed |= (0x8000 >> s->v_len);
-            if (varicode_in2)
-                s->packed |= (0x4000 >> s->v_len);
-            if (varicode_in1 || varicode_in2)
-                s->n_zeros = 0;
-            else
-                s->n_zeros+=2;
-
-            s->v_len+=2;            
+            s->n_zeros++;
         }
-
+        s->v_len++;
         found = 0;
 
         /* end of character code */
@@ -187,41 +202,90 @@ static int decode_one_bit(struct VARICODE_DEC *s, char *single_ascii, short vari
 
                 byte1 = s->packed >> 8;
                 //printf("looking for byte1 : 0x%x ... ", byte1);
-                if (long_code) {
-                    byte2 = s->packed & 0xff;
-
-                    for(i=0; i<128; i++) {
-                        if ((byte1 == long_varicode_table[2*i]) && (byte2 == long_varicode_table[2*i+1])) {
-                            found = 1;
-                            *single_ascii = i;
-                        }
+                byte2 = s->packed & 0xff;
+
+                for(i=0; i<128; i++) {
+                    if ((byte1 == varicode_table1[2*i]) && (byte2 == varicode_table1[2*i+1])) {
+                        found = 1;
+                        *single_ascii = i;
                     }
                 }
-                else {
-                    for(i=0; i<sizeof(short_varicode_table); i+=2) {
-                        //printf("byte1: 0x%x 0x%x\n", byte1, (unsigned char)short_varicode_table[i+1]);
-                        if (byte1 == (unsigned char)short_varicode_table[i+1]) {
-                            found = 1;
-                            *single_ascii = short_varicode_table[i];
-                            //printf("found: %d i=%d char=%c ", found, i, *single_ascii);
-                        }
+            }
+            varicode_decode_init(s, s->code_num);
+        }
+
+        /* code can run too long if we have a bit error */
+
+        if (s->v_len > VARICODE_MAX_BITS)
+            varicode_decode_init(s, s->code_num);
+    }
+
+    return found;
+}
+
+
+/* Code 2 decode function, accepts two bits at a time */
+
+static int decode_two_bits(struct VARICODE_DEC *s, char *single_ascii, short varicode_in1, short varicode_in2)
+{
+    int            found, i;
+    unsigned short byte1;
+
+    //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_in1 || varicode_in2))
+            return 0;
+        else 
+            s->state = 1;
+    }
+
+    if (s->state == 1) {
+        if (varicode_in1)
+            s->packed |= (0x8000 >> s->v_len);
+        if (varicode_in2)
+            s->packed |= (0x4000 >> s->v_len);
+        if (varicode_in1 || varicode_in2)
+            s->n_zeros = 0;
+        else
+            s->n_zeros+=2;
+
+        s->v_len+=2;            
+        found = 0;
+
+        /* end of character code */
+
+        if (s->n_zeros == 2) {
+            if (s->v_len) {
+                /* run thru table but note with bit errors we might not actually find a match */
+
+                byte1 = s->packed >> 8;
+                //printf("looking for byte1 : 0x%x ... ", byte1);
+                for(i=0; i<sizeof(varicode_table2); i+=2) {
+                    //printf("byte1: 0x%x 0x%x\n", byte1, (unsigned char)varicode_table2[i+1]);
+                    if (byte1 == (unsigned char)varicode_table2[i+1]) {
+                        found = 1;
+                        *single_ascii = varicode_table2[i];
+                        //printf("found: %d i=%d char=%c ", found, i, *single_ascii);
                     }
                 }
-                //printf("\n");
             }
-            varicode_decode_init(s);
+            varicode_decode_init(s, s->code_num);
         }
 
         /* code can run too long if we have a bit error */
 
         if (s->v_len > VARICODE_MAX_BITS)
-            varicode_decode_init(s);
+            varicode_decode_init(s, s->code_num);
     }
 
     return found;
 }
 
-int varicode_decode(struct VARICODE_DEC *dec_states, char ascii_out[], short varicode_in[], int max_out, int n_in, int long_code) {
+
+int varicode_decode1(struct VARICODE_DEC *dec_states, char ascii_out[], short varicode_in[], int max_out, int n_in) {
     int            output, n_out;
     char           single_ascii;
 
@@ -230,16 +294,9 @@ int varicode_decode(struct VARICODE_DEC *dec_states, char ascii_out[], short var
     //printf("varicode_decode: n_in: %d\n", n_in);
 
     while(n_in && (n_out < max_out)) {
-        if (long_code) {
-            output = decode_one_bit(dec_states, &single_ascii, varicode_in[0], 0, long_code);
-            varicode_in++;
-            n_in--;
-        }
-        else {
-            output = decode_one_bit(dec_states, &single_ascii, varicode_in[0], varicode_in[1], long_code);
-            varicode_in +=2;
-            n_in -= 2;
-        }
+        output = decode_one_bit(dec_states, &single_ascii, varicode_in[0], 0);
+        varicode_in++;
+        n_in--;
 
         if (output) {
             *ascii_out++ = single_ascii;
@@ -251,21 +308,53 @@ int varicode_decode(struct VARICODE_DEC *dec_states, char ascii_out[], short var
 }
 
 
+int varicode_decode2(struct VARICODE_DEC *dec_states, char ascii_out[], short varicode_in[], int max_out, int n_in) {
+    int            output, n_out;
+    char           single_ascii;
+
+    //assert((n_in % 2) == 0);  /* code always processes two bits at a time */
+    n_out = 0;
+
+    //printf("varicode_decode: n_in: %d\n", n_in);
+
+    while(n_in && (n_out < max_out)) {
+        output = decode_two_bits(dec_states, &single_ascii, varicode_in[0], varicode_in[1]);
+        varicode_in +=2;
+        n_in -= 2;
+        if (output) {
+            *ascii_out++ = single_ascii;
+            n_out++;
+        }            
+    }
+
+    return n_out;
+}
+
+
+int varicode_decode(struct VARICODE_DEC *dec_states, char ascii_out[], short varicode_in[], int max_out, int n_in) {
+    if (dec_states->code_num == 1)
+        return varicode_decode1(dec_states, ascii_out, varicode_in, max_out, n_in);
+    else
+        return varicode_decode2(dec_states, ascii_out, varicode_in, max_out, n_in);
+}
+
+
 #ifdef VARICODE_UNITTEST
-void test_varicode(int long_code) {
+void test_varicode(int code_num) {
     char *ascii_in;
     short *varicode;
     int  i, n_varicode_bits_out, n_ascii_chars_out, length, half;
     char *ascii_out;
     struct VARICODE_DEC dec_states;
 
-    if (long_code) {
+    if (code_num == 1) {
         printf("long code:\n");
-        length = sizeof(long_varicode_table)/2;
+        length = sizeof(varicode_table1)/2;
     }
     else {
         printf("short code:\n");
-        length = sizeof(short_varicode_table)/2;
+        length = sizeof(varicode_table2)/2;
     }
     //length = 10;
     ascii_in = (char*)malloc(length);
@@ -274,31 +363,31 @@ void test_varicode(int long_code) {
 
     // 1. test all Varicode codes -------------------------------------------------------------
 
-    if (long_code) {
+    if (code_num == 1) {
         for(i=0; i<length; i++)
             ascii_in[i] = (char)i;
     }
     else {
         for(i=0; i<length; i++)
-            ascii_in[i] = short_varicode_table[2*i];
+            ascii_in[i] = varicode_table2[2*i];
     }
     //printf("  ascii_in: %s\n", ascii_in);
-    n_varicode_bits_out = varicode_encode(varicode, ascii_in, VARICODE_MAX_BITS*length, length, long_code);
+    n_varicode_bits_out = varicode_encode(varicode, ascii_in, VARICODE_MAX_BITS*length, length, code_num);
 
     printf("  n_varicode_bits_out: %d\n", n_varicode_bits_out);
     //for(i=0; i<n_varicode_bits_out; i++) {
     //    printf("%d \n", varicode[i]);
     //}
 
-    // split decode in half to test how it preseves state between calls 
+    // split decode in half to test how it preserves state between calls 
 
-    varicode_decode_init(&dec_states);
+    varicode_decode_init(&dec_states, code_num);
     half = n_varicode_bits_out/2;
-    n_ascii_chars_out  = varicode_decode(&dec_states, ascii_out, varicode, length, half, long_code);
+    n_ascii_chars_out  = varicode_decode(&dec_states, ascii_out, varicode, length, half);
     // 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, long_code);
+                                         &varicode[half], length-n_ascii_chars_out, n_varicode_bits_out - half);
     //printf("n_ascii_chars_out: %d\n", n_ascii_chars_out);
 
     assert(n_ascii_chars_out == length);
@@ -315,13 +404,13 @@ void test_varicode(int long_code) {
     sprintf(ascii_in, "CQ CQ CQ, this is VK5DGR");
         
     assert(strlen(ascii_in) < length);
-    if (long_code == 0)
+    if (code_num == 2)
         for(i=0; i<strlen(ascii_in); i++)
             ascii_in[i] = tolower(ascii_in[i]);
 
     for(i=0; i<3; i++) {
-        n_varicode_bits_out = varicode_encode(varicode, ascii_in, VARICODE_MAX_BITS*length, strlen(ascii_in), long_code);
-        n_ascii_chars_out   = varicode_decode(&dec_states, ascii_out, varicode, length, n_varicode_bits_out, long_code);
+        n_varicode_bits_out = varicode_encode(varicode, ascii_in, VARICODE_MAX_BITS*length, strlen(ascii_in), code_num);
+        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);
@@ -331,7 +420,7 @@ void test_varicode(int long_code) {
             printf("  Test 2 Fail\n");
 
         memset(varicode, 0, sizeof(short)*20);
-        n_ascii_chars_out = varicode_decode(&dec_states, ascii_out, varicode, length, 20, long_code);
+        n_ascii_chars_out = varicode_decode(&dec_states, ascii_out, varicode, length, 20);
         assert(n_ascii_chars_out == 0);
     }
 
@@ -341,8 +430,8 @@ void test_varicode(int long_code) {
 }
 
 int main(void) {
-    test_varicode(0);
     test_varicode(1);
+    test_varicode(2);
     return 0;
 }
 #endif
index ac189af2d33abf44f1ce24ea72c0866aa02d0d58..dd2329a9435520892a0320b6a413c409d9de1f9d 100644 (file)
@@ -35,11 +35,12 @@ struct VARICODE_DEC {
     int            n_zeros;
     int            v_len;
     unsigned short packed;
+    int            code_num;
 };
     
-int varicode_encode(short varicode_out[], char ascii_in[], int max_out, int n_in, int longcode);
-void varicode_decode_init(struct VARICODE_DEC *dec_states);
-int varicode_decode(struct VARICODE_DEC *dec_states, char ascii_out[], short varicode_in[], int max_out, int n_in, int longcode);
+int varicode_encode(short varicode_out[], char ascii_in[], int max_out, int n_in, int code_num);
+void varicode_decode_init(struct VARICODE_DEC *dec_states, int code_num);
+int varicode_decode(struct VARICODE_DEC *dec_states, char ascii_out[], short varicode_in[], int max_out, int n_in);
 
 #ifdef __cplusplus
 }
index f27efbf77838c719da2aceab667c2fb3cc2d282c..3bf2ac5c982ce5428675e4795e573ca57a47af89 100644 (file)
@@ -31,7 +31,7 @@ sent before the next character is sent.
 This file is constructed with information from the article "PSK31 Fundamentals"
 by Peter Martinez, G3PLX by Clint Turner, KA7OEI
 */
-unsigned char const long_varicode_table[256] = {
+unsigned char const varicode_table1[256] =     {
     0b10101010,
     0b11000000, // 0 NUL
     0b10110110,
@@ -290,7 +290,10 @@ unsigned char const long_varicode_table[256] =     {
     0b01000000, // 127 (del)
 };
 
-char const short_varicode_table[] = {
+// This code was used on FDMDV version 1, and is more compact that Code 1, but only covers a subset
+// of the ASCII cahacter set
+
+char const varicode_table2[] = {
 
     ' ' ,0b11000000,
     ',' ,0b01000000,