ldpc_dec modified to read in half frames and perform FEC frame sync, cohpsk and unit...
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sun, 19 Mar 2017 09:45:36 +0000 (09:45 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sun, 19 Mar 2017 09:45:36 +0000 (09:45 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@3072 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/src/codec2_cohpsk.h
codec2-dev/src/cohpsk.c
codec2-dev/src/cohpsk_defs.h
codec2-dev/src/cohpsk_demod.c
codec2-dev/src/cohpsk_mod.c
codec2-dev/src/freedv_api.c
codec2-dev/src/ldpc_dec.c

index 27d35cd234159e0697ed9960b71f826ca7ef9310..a0ad488cd15972a4baf24e8564b31d5124b78d7d 100644 (file)
@@ -46,7 +46,7 @@ extern const int test_bits_coh[];
 
 struct COHPSK *cohpsk_create(void);
 void cohpsk_destroy(struct COHPSK *coh);
-void cohpsk_mod(struct COHPSK *cohpsk, COMP tx_fdm[], int tx_bits[]);
+void cohpsk_mod(struct COHPSK *cohpsk, COMP tx_fdm[], int tx_bits[], int nbits);
 void cohpsk_clip(COMP tx_fdm[]);
 void cohpsk_demod(struct COHPSK *cohpsk, float rx_bits[], int *sync, COMP rx_fdm[], int *nin_frame);
 void cohpsk_get_demod_stats(struct COHPSK *cohpsk, struct MODEM_STATS *stats);
index 2cdf0123a1488f4d3cc7b51297b3f76513aa3e4f..303db04545db371eb08966edb430f6b3ba01064d 100644 (file)
@@ -222,12 +222,22 @@ void cohpsk_destroy(struct COHPSK *coh)
 
 void bits_to_qpsk_symbols(COMP tx_symb[][COHPSK_NC*ND], int tx_bits[], int nbits)
 {
-    int   i, r, c, p_r, data_r, d;
+    int   i, r, c, p_r, data_r, d, diversity;
     short bits;
 
-    /* check number of bits supplied matchs number of QPSK symbols in the frame */
+    /* check allowed number of bits supplied matches number of QPSK
+       symbols in the frame */
 
-    assert((NSYMROW*COHPSK_NC)*2 == nbits);
+    assert( (NSYMROW*COHPSK_NC*2 == nbits) || (NSYMROW*COHPSK_NC*2*ND == nbits));
+    
+    /* if we input twice as many bits we don't do diversity */
+
+    if (NSYMROW*COHPSK_NC*2 == nbits) {    
+        diversity = 1; /* diversity mode                         */
+    }
+    else {
+        diversity = 2; /* twice as many bits, non diversity mode */
+    }
 
     /*
       Insert two rows of Nc pilots at beginning of data frame.
@@ -244,15 +254,14 @@ void bits_to_qpsk_symbols(COMP tx_symb[][COHPSK_NC*ND], int tx_bits[], int nbits
 
     r = 0;
     for(p_r=0; p_r<2; p_r++) {
-        for(c=0; c<COHPSK_NC; c++) {
-            tx_symb[r][c].real = pilots_coh[p_r][c]/sqrtf(ND);
+        for(c=0; c<COHPSK_NC*ND; c++) {
+            tx_symb[r][c].real = pilots_coh[p_r][c % COHPSK_NC]/sqrtf(ND);
             tx_symb[r][c].imag = 0.0;
         }
         r++;
     }
     for(data_r=0; data_r<NSYMROW; data_r++, r++) {
-
-        for(c=0; c<COHPSK_NC; c++) {
+        for(c=0; c<COHPSK_NC*diversity; c++) {
             i = c*NSYMROW + data_r;
             bits = (tx_bits[2*i]&0x1)<<1 | (tx_bits[2*i+1]&0x1);
             tx_symb[r][c] = fcmult(1.0/sqrtf(ND),qpsk_mod[bits]);
@@ -262,16 +271,15 @@ void bits_to_qpsk_symbols(COMP tx_symb[][COHPSK_NC*ND], int tx_bits[], int nbits
     assert(p_r == NPILOTSFRAME);
     assert(r == NSYMROWPILOT);
 
-    /* copy to other carriers (diversity) */
+    /* if in diversity mode, copy symbols to upper carriers */
 
-    for(d=1; d<ND; d++) {
+    for(d=1; d<1+ND-diversity; d++) {
         for(r=0; r<NSYMROWPILOT; r++) {
             for(c=0; c<COHPSK_NC; c++) {
                 tx_symb[r][c+COHPSK_NC*d] = tx_symb[r][c];
             }
         }
     }
-
 }
 
 
@@ -654,8 +662,12 @@ int sync_state_machine(struct COHPSK *coh, int sync, int next_sync)
   AUTHOR......: David Rowe
   DATE CREATED: 5/4/2015
 
-  COHPSK modulator, take a frame of COHPSK_BITS_PER_FRAME bits and
-  generates a frame of COHPSK_NOM_SAMPLES_PER_FRAME modulated symbols.
+  COHPSK modulator, take a frame of COHPSK_BITS_PER_FRAME or
+  2*COHPSK_BITS_PER_FRAME bits and generates a frame of
+  COHPSK_NOM_SAMPLES_PER_FRAME modulated symbols.
+
+  if nbits == COHPSK_BITS_PER_FRAME, diveristy mode is used, if nbits
+  == 2*COHPSK_BITS_PER_FRAME diversity mode is not used.
 
   The output signal is complex to support single sided frequency
   shifting, for example when testing frequency offsets in channel
@@ -663,14 +675,14 @@ int sync_state_machine(struct COHPSK *coh, int sync, int next_sync)
 
 \*---------------------------------------------------------------------------*/
 
-void cohpsk_mod(struct COHPSK *coh, COMP tx_fdm[], int tx_bits[])
+void cohpsk_mod(struct COHPSK *coh, COMP tx_fdm[], int tx_bits[], int nbits)
 {
     struct FDMDV *fdmdv = coh->fdmdv;
     COMP  tx_symb[NSYMROWPILOT][COHPSK_NC*ND];
     COMP  tx_onesym[COHPSK_NC*ND];
     int  r,c;
 
-    bits_to_qpsk_symbols(tx_symb, tx_bits, COHPSK_BITS_PER_FRAME);
+    bits_to_qpsk_symbols(tx_symb, tx_bits, nbits);
 
     for(r=0; r<NSYMROWPILOT; r++) {
         for(c=0; c<COHPSK_NC*ND; c++)
index a03bfe7903516aebf2fbac7a7bc5e58ca5a2ee8e..28b756e41fa5e6fcee3ade183b1540e77eff8e67 100644 (file)
@@ -1,9 +1,9 @@
 /* Generated by write_pilot_file() Octave function */
 
-#define NSYMROW      4   /* number of data symbols on each row (i.e. each carrier) */
+#define NSYMROW      4   /* number of data symbols per carrier (number of rows)     */
 #define NS           4   /* number of data symbols between pilots                   */
-#define NPILOTSFRAME 2   /* number of pilot symbols on each row                     */
+#define NPILOTSFRAME 2   /* number of pilot symbols per carrier                     */
 #define PILOTS_NC    7   /* number of carriers                                      */
 
-#define NSYMROWPILOT 6   /* length of row after pilots inserted                     */
+#define NSYMROWPILOT 6   /* number of rows after pilots inserted                    */
 
index e05e7c84e2e901c80ad5fd27d1d6ca5c8504bcc7..a2e92c72bba273660b7367518865362e164e2dbd 100644 (file)
 #define LOG_FRAMES 100
 #define SYNC_FRAMES 12                    /* sync state uses up extra log storage as we reprocess several times */
 
+int opt_exists(char *argv[], int argc, char opt[]) {
+    int i;
+    for (i=0; i<argc; i++) {
+        if (strcmp(argv[i], opt) == 0) {
+            return i;
+        }
+    }
+    return 0;
+}
+
 int main(int argc, char *argv[])
 {
     FILE          *fin, *fout, *foct;
@@ -55,10 +65,15 @@ int main(int argc, char *argv[])
     float        *rx_phi_log = NULL;
     COMP         *rx_symb_log = NULL;
     float         f_est_log[LOG_FRAMES], ratio_log[LOG_FRAMES];
-    int           i, r, c, log_data_r, oct, logframes;
+    int           i, r, c, log_data_r, oct, logframes, arg, diversity;
 
     if (argc < 3) {
-       printf("usage: %s InputModemRawFile OutputOneBitPerIntFile [OctaveLogFile]\n", argv[0]);
+        fprintf(stderr, "\n");
+       printf("usage: %s InputModemRawFile OutputOneCharPerBitFile [-o OctaveLogFile] [--nd]\n", argv[0]);
+        fprintf(stderr, "\n");
+        fprintf(stderr, "  -o          Octave log file for testing\n");
+        fprintf(stderr, "  --nd        non-diversity mode, output frames of %d bits\n", ND*COHPSK_BITS_PER_FRAME);
+        fprintf(stderr, "\n");
        exit(1);
     }
 
@@ -78,15 +93,22 @@ int main(int argc, char *argv[])
 
     foct = NULL;
     oct = 0;
-    if (argc == 4) {
-        if ( (foct = fopen(argv[3],"wt")) == NULL ) {
+    if ((arg = opt_exists(argv, argc, "-o")) != 0) {
+        if ( (foct = fopen(argv[arg+1],"wt")) == NULL ) {
             fprintf(stderr, "Error opening output Octave file: %s: %s.\n",
-                    argv[3], strerror(errno));
+                    argv[4], strerror(errno));
        exit(1);
         }
         oct = 1;
     }
 
+    if (opt_exists(argv, argc, "--nd")) {
+        diversity = 2;
+    } else {
+        diversity = 1;
+    }
+    fprintf(stderr, "cohpsk_demod: diversity: %d\n", diversity);
+
     cohpsk = cohpsk_create();
     cohpsk_set_verbose(cohpsk, 0);
 
@@ -120,9 +142,19 @@ int main(int argc, char *argv[])
        cohpsk_demod(cohpsk, rx_bits, &sync, rx_fdm, &nin_frame);
 
        if (sync) {
-            for(i=0; i<COHPSK_BITS_PER_FRAME; i++)
-                rx_bits_char[i] = rx_bits[i] < 0.0;
-            fwrite(rx_bits_char, sizeof(char), COHPSK_BITS_PER_FRAME, fout);
+            if (diversity == 1) {
+                for(i=0; i<COHPSK_BITS_PER_FRAME; i++)
+                    rx_bits_char[i] = rx_bits[i] < 0.0;
+                fwrite(rx_bits_char, sizeof(char), COHPSK_BITS_PER_FRAME, fout);
+            }
+            else {
+                for(i=0; i<COHPSK_BITS_PER_FRAME; i++)
+                    rx_bits_char[i] = cohpsk->rx_bits_lower[i] < 0.0;
+                fwrite(rx_bits_char, sizeof(char), COHPSK_BITS_PER_FRAME, fout);
+                for(i=0; i<COHPSK_BITS_PER_FRAME; i++)
+                    rx_bits_char[i] = cohpsk->rx_bits_upper[i] < 0.0;
+                fwrite(rx_bits_char, sizeof(char), COHPSK_BITS_PER_FRAME, fout);
+            }
 
             if (oct) {
                 for(r=0; r<NSYMROW; r++, log_data_r++) {
index 25c1a57a5f53627eafe25e7ef3e3daa436f2b6a9..51953e3870c9f5abd9708540fd27373b2e66eda3 100644 (file)
 #include "codec2_cohpsk.h"
 #include "codec2_fdmdv.h"
 
+int opt_exists(char *argv[], int argc, char opt[]) {
+    int i;
+    for (i=0; i<argc; i++) {
+        if (strcmp(argv[i], opt) == 0) {
+            return i;
+        }
+    }
+    return 0;
+}
+
 int main(int argc, char *argv[])
 {
     FILE          *fin, *fout;
     struct COHPSK *cohpsk;
-    char          tx_bits_char[COHPSK_BITS_PER_FRAME];
-    int           tx_bits[COHPSK_BITS_PER_FRAME];
+    char          tx_bits_char[2*COHPSK_BITS_PER_FRAME];
+    int           tx_bits[2*COHPSK_BITS_PER_FRAME];
     COMP          tx_fdm[COHPSK_NOM_SAMPLES_PER_FRAME];
     short         tx_fdm_scaled[COHPSK_NOM_SAMPLES_PER_FRAME];
-    int           frames;
+    int           frames, diversity;
     int           i;
 
     if (argc < 3) {
-       printf("usage: %s InputOneCharPerBitFile OutputModemRawFile\n", argv[0]);
+        fprintf(stderr, "\n");
+       fprintf(stderr, "usage: %s InputOneCharPerBitFile OutputModemRawFile [-nd]\n", argv[0]);
+        fprintf(stderr, "\n");
+        fprintf(stderr, "  --nd        non-diversity mode, input frames of %d bits\n", 2*COHPSK_BITS_PER_FRAME);
+        fprintf(stderr, "\n");
        exit(1);
     }
 
@@ -69,14 +83,22 @@ int main(int argc, char *argv[])
 
     cohpsk = cohpsk_create();
 
+    if (opt_exists(argv, argc, "--nd")) {
+        diversity = 2;
+    }
+    else {
+        diversity = 1;
+    }
+    fprintf(stderr, "diversity: %d\n", diversity);
+
     frames = 0;
 
-    while(fread(tx_bits_char, sizeof(char), COHPSK_BITS_PER_FRAME, fin) == COHPSK_BITS_PER_FRAME) {
+    while(fread(tx_bits_char, sizeof(char), COHPSK_BITS_PER_FRAME*diversity, fin) == COHPSK_BITS_PER_FRAME*diversity) {
        frames++;
-
-        for(i=0; i<COHPSK_BITS_PER_FRAME; i++)
+        
+        for(i=0; i<COHPSK_BITS_PER_FRAME*diversity; i++)
             tx_bits[i] = tx_bits_char[i];
-       cohpsk_mod(cohpsk, tx_fdm, tx_bits);
+       cohpsk_mod(cohpsk, tx_fdm, tx_bits, COHPSK_BITS_PER_FRAME*diversity);
         cohpsk_clip(tx_fdm);
 
        /* scale and save to disk as shorts */
index 302d69ab57f6492befcd8339ef155be5d39a9f4e..8afb8461c140ec51f71874fdb00b7599d44be1af 100644 (file)
@@ -685,7 +685,7 @@ static void freedv_comptx_fdmdv_700(struct freedv *f, COMP mod_out[]) {
 
     /* cohpsk modulator */
 
-    cohpsk_mod(f->cohpsk, tx_fdm, f->codec_bits);
+    cohpsk_mod(f->cohpsk, tx_fdm, f->codec_bits, COHPSK_BITS_PER_FRAME);
     if (f->clip)
         cohpsk_clip(tx_fdm);
     for(i=0; i<f->n_nat_modem_samples; i++)
index 5931a2290d115b6c1d0c2623aa5200109f28cd2c..529f80416d647ee4ccbd192b6d7aa13064daefed 100644 (file)
 #include "H2064_516_sparse.h"  \r
 #endif\r
 \r
+int opt_exists(char *argv[], int argc, char opt[]) {\r
+    int i;\r
+    for (i=0; i<argc; i++) {\r
+        if (strcmp(argv[i], opt) == 0) {\r
+            return 1;\r
+        }\r
+    }\r
+    return 0;\r
+}\r
+\r
 void extract_output(char out_char[], int DecodedBits[], int ParityCheckCount[], int max_iter, int CodeLength, int NumberParityBits);\r
 \r
 int main(int argc, char *argv[])\r
@@ -69,13 +79,18 @@ int main(int argc, char *argv[])
     NumberParityBits = NUMBERPARITYBITS;\r
        \r
     if (argc < 2) {\r
-        fprintf(stderr, "usage: %s --test\n", argv[0]);\r
+        fprintf(stderr, "\n");\r
+        fprintf(stderr, "usage: %s --test\n\n", argv[0]);\r
         fprintf(stderr, "  Run internal self test and print code parameters.\n\n");\r
-        fprintf(stderr, "usage: %s InOneSymbolPerDouble OutOneBitPerByte [--sd]\n", argv[0]);\r
-        fprintf(stderr, "  InOneSymbolPerDouble is a file of double LLRs.  If the\n");\r
-        fprintf(stderr, "  --sd flag is used the input file can be Soft Decision\n");\r
-        fprintf(stderr, "  symbols, and LLRs will be calculated internally. Use -\n");\r
-        fprintf(stderr, "  for the file names to use stdin/stdout.\n");\r
+        fprintf(stderr, "usage: %s InOneSymbolPerDouble OutOneBitPerByte [--sd] [--half]\n\n", argv[0]);\r
+        fprintf(stderr, "   InOneSymbolPerDouble    Input file of double LLRs, use - for the \n");        \r
+        fprintf(stderr, "                           file names to use stdin/stdout\n");\r
+        fprintf(stderr, "   --sd                    Treat input file samples as Soft Decision\n");\r
+        fprintf(stderr, "                           demod outputs rather than LLRs\n");\r
+        fprintf(stderr, "   --half                  Load framesize/2 input samples for each decode\n");\r
+        fprintf(stderr, "                           attempt, only output decoded bits if decoder\n");\r
+        fprintf(stderr, "                           converges.  Form of frame sync.\n");\r
+        fprintf(stderr, "\n");\r
         exit(0);\r
     }\r
 \r
@@ -126,7 +141,7 @@ int main(int argc, char *argv[])
     }\r
     else {\r
         FILE *fin, *fout;\r
-        int   sdinput;\r
+        int   sdinput, readhalfframe, nread, offset, iter;\r
 \r
         /* File I/O mode ------------------------------------------------*/\r
 \r
@@ -145,23 +160,43 @@ int main(int argc, char *argv[])
         }\r
 \r
         sdinput = 0;\r
-        //printf("argc: %d\n", argc);\r
-        if (argc == 4)\r
-            if (strcmp(argv[3], "--sd") == 0)\r
-                sdinput = 1;\r
+        readhalfframe = 0;\r
+        if (opt_exists(argv, argc, "--sd")) {\r
+            sdinput = 1;\r
+        }\r
+        if (opt_exists(argv, argc, "--half")) {\r
+            readhalfframe = 1;\r
+        }\r
 \r
         double *input_double = calloc(CodeLength, sizeof(double));\r
 \r
-        while(fread(input_double, sizeof(double), CodeLength, fin) == CodeLength) {\r
+        nread = CodeLength;\r
+        offset = 0;\r
+        if (readhalfframe) {\r
+            nread = CodeLength/2;\r
+            offset = CodeLength/2;\r
+            for(i=0; i<offset; i++) {\r
+                input_double[i] = 0.0;\r
+            }\r
+        }\r
+\r
+        while(fread(&input_double[offset], sizeof(double), nread, fin) == nread) {\r
             if (sdinput) {\r
                 sd_to_llr(input_double, input_double, CodeLength);\r
             }\r
 \r
-            run_ldpc_decoder(&ldpc, out_char, input_double);\r
+            iter = run_ldpc_decoder(&ldpc, out_char, input_double);\r
+            fprintf(stderr, "%4d ", iter);\r
+\r
+            // output data bits if decoder converged\r
 \r
-            //printf("%4d ", iter);\r
-            // just output data bits\r
-            fwrite(out_char, sizeof(char), NUMBERROWSHCOLS, fout);\r
+            if (iter != MAX_ITER) {\r
+              fwrite(out_char, sizeof(char), NUMBERROWSHCOLS, fout);\r
+            }\r
+\r
+            for(i=0; i<offset; i++) {\r
+                input_double[i] = input_double[i+offset];\r
+            }\r
         }\r
 \r
         free(input_double);\r