refactored LDPC decoder tomake it easier to call from other C programs
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Fri, 16 Sep 2016 03:09:06 +0000 (03:09 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Fri, 16 Sep 2016 03:09:06 +0000 (03:09 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2865 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/src/drs232.c
codec2-dev/src/ldpc_dec.c
codec2-dev/src/mpdecode_core.c
codec2-dev/src/mpdecode_core.h

index f0a08ef1fb259e9e858da92ed66d896babc01f03..0bf89701f0c0bcdb9e40edd224a6e46124a4461d 100644 (file)
@@ -60,7 +60,7 @@
 #define BITS_PER_BYTE          10
 #define UNPACKED_PACKET_BYTES  ((UW_BYTES+BYTES_PER_PACKET+CRC_BYTES)*BITS_PER_BYTE)
 
-/* UW pattern we look for, inclduing start/stop bits */
+/* UW pattern we look for, including start/stop bits */
 
 uint8_t uw[] = {
     /* 0xb                0xa */
@@ -95,20 +95,20 @@ int main(int argc, char *argv[]) {
     uint16_t    tx_checksum, rx_checksum;
 
     if (argc < 3) {
-       printf("usage: drs232 InputOneBitPerChar OutputPackets\n");
-       exit(1);
+       fprintf(stderr, "usage: drs232 InputOneBitPerChar OutputPackets [--sd]\n");
+       exit(1);
     }
 
     if (strcmp(argv[1], "-")  == 0) fin = stdin;
     else if ( (fin = fopen(argv[1],"rb")) == NULL ) {
-       fprintf(stderr, "Error opening input speech file: %s: %s.\n",
+       fprintf(stderr, "Error opening input file: %s: %s.\n",
          argv[2], strerror(errno));
        exit(1);
     }
 
     if (strcmp(argv[2], "-") == 0) fout = stdout;
     else if ( (fout = fopen(argv[2],"wb")) == NULL ) {
-       fprintf(stderr, "Error opening output speech file: %s: %s.\n",
+       fprintf(stderr, "Error opening output file: %s: %s.\n",
          argv[3], strerror(errno));
        exit(1);
     }
index ec1c528655218458ba11d1d22bfb8fca1f195a41..a60323aa7539be8bd9356ed23296713de65f7dde 100644 (file)
 \r
 #include "ldpc_code.h"  \r
 \r
-void run_ldpc_decoder(int DecodedBits[], int ParityCheckCount[], double input[]);\r
-\r
 int main(int argc, char *argv[])\r
 {    \r
     int         CodeLength, NumberParityBits, max_iter;\r
     int         i, j, r, num_ok, num_runs;\r
     char        out_char[CODELENGTH];\r
+    struct LDPC ldpc;\r
 \r
     /* derive some parameters */\r
 \r
@@ -75,6 +74,20 @@ int main(int argc, char *argv[])
         exit(0);\r
     }\r
 \r
+    /* set up LDPC code from include file constants */\r
+\r
+    ldpc.max_iter = MAX_ITER;\r
+    ldpc.dec_type = 0;\r
+    ldpc.q_scale_factor = 1;\r
+    ldpc.r_scale_factor = 1;\r
+    ldpc.CodeLength = CODELENGTH;\r
+    ldpc.NumberParityBits = NUMBERPARITYBITS;\r
+    ldpc.NumberRowsHcols = NUMBERROWSHCOLS;\r
+    ldpc.max_row_weight = MAX_ROW_WEIGHT;\r
+    ldpc.max_col_weight = MAX_COL_WEIGHT;\r
+    ldpc.H_rows = H_rows;\r
+    ldpc.H_cols = H_cols;\r
+\r
     int *DecodedBits = calloc( max_iter*CodeLength, sizeof( int ) );\r
     int *ParityCheckCount = calloc( max_iter, sizeof(int) );\r
 \r
@@ -90,7 +103,7 @@ int main(int argc, char *argv[])
 \r
         for(r=0; r<num_runs; r++) {\r
 \r
-            run_ldpc_decoder(DecodedBits, ParityCheckCount, input);\r
+            run_ldpc_decoder(&ldpc, DecodedBits, ParityCheckCount, input);\r
 \r
             /* Check output by comparing every output iteration */\r
 \r
@@ -137,41 +150,13 @@ int main(int argc, char *argv[])
                 sdinput = 1;\r
 \r
         double *input_double = calloc(CodeLength, sizeof(double));\r
-        double sum, mean, sign, sumsq, estvar, estEsN0, x;\r
 \r
         while(fread(input_double, sizeof(double), CodeLength, fin) == CodeLength) {\r
             if (sdinput) {\r
-                /* convert SD samples to LLRs -------------------------------*/\r
-\r
-                sum = 0.0;\r
-                for(i=0; i<CodeLength; i++)\r
-                    sum += fabs(input_double[i]);\r
-                mean = sum/CodeLength;\r
-                \r
-                /* scale by mean to map onto +/- 1 symbol position */\r
-\r
-                for(i=0; i<CodeLength; i++) {\r
-                    input_double[i] /= mean;\r
-                }\r
-\r
-                /* find variance from +/-1 symbol position */\r
-\r
-                sum = sumsq = 0.0; \r
-                for(i=0; i<CodeLength; i++) {\r
-                    sign = (input_double[i] > 0.0) - (input_double[i] < 0.0);\r
-                    x = (input_double[i] - sign);\r
-                    sum += x;\r
-                    sumsq += x*x;\r
-                }\r
-                mean = sum/CodeLength;\r
-                estvar = sumsq/CodeLength - mean*mean;\r
-\r
-                estEsN0 = 1.0/(2.0 * estvar + 1E-3); \r
-                for(i=0; i<CodeLength; i++)\r
-                    input_double[i] = 4.0 * estEsN0 * input_double[i];              \r
+                sd_to_llr(input_double, input_double, CodeLength);\r
             }\r
 \r
-            run_ldpc_decoder(DecodedBits, ParityCheckCount, input_double);\r
+            run_ldpc_decoder(&ldpc, DecodedBits, ParityCheckCount, input_double);\r
             \r
             /* extract output bits from ouput iteration that solved all parity equations, or failing that\r
                the last iteration. */\r
@@ -209,97 +194,5 @@ int main(int argc, char *argv[])
 }\r
 \r
 \r
-void run_ldpc_decoder(int DecodedBits[], int ParityCheckCount[], double input[]) {\r
-    int                max_iter, dec_type;\r
-    float       q_scale_factor, r_scale_factor;\r
-    int                max_row_weight, max_col_weight;\r
-    int         CodeLength, NumberParityBits, NumberRowsHcols, shift, H1;\r
-    int         i;\r
-    struct c_node *c_nodes;\r
-    struct v_node *v_nodes;\r
-    \r
-    /* default values */\r
-\r
-    max_iter  = MAX_ITER;\r
-    dec_type  = 0;\r
-    q_scale_factor = 1;\r
-    r_scale_factor = 1;\r
-\r
-    /* derive some parameters */\r
-\r
-    CodeLength = CODELENGTH;                    /* length of entire codeword */\r
-    NumberParityBits = NUMBERPARITYBITS;\r
-    NumberRowsHcols = NUMBERROWSHCOLS;\r
-\r
-    shift = (NumberParityBits + NumberRowsHcols) - CodeLength;\r
-    if (NumberRowsHcols == CodeLength) {\r
-        H1=0;\r
-        shift=0;\r
-    } else {\r
-        H1=1;\r
-    }\r
-       \r
-    max_row_weight = MAX_ROW_WEIGHT;\r
-    max_col_weight = MAX_COL_WEIGHT;\r
-       \r
-    c_nodes = calloc( NumberParityBits, sizeof( struct c_node ) );\r
-    v_nodes = calloc( CodeLength, sizeof( struct v_node));\r
-       \r
-    /* initialize c-node and v-node structures */\r
-\r
-    c_nodes = calloc( NumberParityBits, sizeof( struct c_node ) );\r
-    v_nodes = calloc( CodeLength, sizeof( struct v_node));\r
-       \r
-    init_c_v_nodes(c_nodes, shift, NumberParityBits, max_row_weight, H_rows, H1, CodeLength, \r
-                   v_nodes, NumberRowsHcols, H_cols, max_col_weight, dec_type, input);\r
-\r
-    int DataLength = CodeLength - NumberParityBits;\r
-    int *data_int = calloc( DataLength, sizeof(int) );\r
-       \r
-    /* need to clear these on each call */\r
-\r
-    for(i=0; i<max_iter; i++)\r
-        ParityCheckCount[i] = 0;\r
-     for(i=0; i<max_iter*CodeLength; i++)\r
-         DecodedBits[i] = 0;\r
-\r
-    /* Call function to do the actual decoding */\r
-\r
-    if ( dec_type == 1) {\r
-        MinSum( ParityCheckCount, DecodedBits, c_nodes, v_nodes, CodeLength, \r
-                NumberParityBits, max_iter, r_scale_factor, q_scale_factor, data_int );\r
-    } else if ( dec_type == 2) {\r
-        fprintf(stderr, "dec_type = 2 not currently supported");\r
-        /* ApproximateMinStar( BitErrors, DecodedBits, c_nodes, v_nodes, \r
-           CodeLength, NumberParityBits, max_iter, r_scale_factor, q_scale_factor );*/\r
-    } else {\r
-        SumProduct( ParityCheckCount, DecodedBits, c_nodes, v_nodes, CodeLength, \r
-                    NumberParityBits, max_iter, r_scale_factor, q_scale_factor, data_int ); \r
-    }\r
 \r
-    /* Clean up memory */\r
 \r
-    free( data_int );\r
-\r
-    /*  Cleaning c-node elements */\r
-\r
-    for (i=0;i<NumberParityBits;i++) {\r
-        free( c_nodes[i].index );\r
-        free( c_nodes[i].message );\r
-        free( c_nodes[i].socket );\r
-    }\r
-       \r
-    /* printf( "Cleaning c-nodes \n" ); */\r
-    free( c_nodes );\r
-       \r
-    /* printf( "Cleaning v-node elements\n" ); */\r
-    for (i=0;i<CodeLength;i++) {\r
-        free( v_nodes[i].index);\r
-        free( v_nodes[i].sign );\r
-        free( v_nodes[i].message );\r
-        free( v_nodes[i].socket );\r
-    }\r
-       \r
-    /* printf( "Cleaning v-nodes \n" ); */\r
-    free( v_nodes );\r
-}\r
index b308fd91073eedd7fc2ad276040bd0276f0f4c80..746bc5ffd123fc9b1fefc7458d35b0c6425f5a5e 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <math.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include "mpdecode_core.h"
 
 /* Phi function */
@@ -553,9 +554,137 @@ void SumProduct(   int      BitErrors[],
   }
    
   // printf(" ssum is %d \n",   ssum); 
-   
+}
+
+
+/* Convenience function to call LDPC decoder from C programs */
+
+void run_ldpc_decoder(struct LDPC *ldpc, int DecodedBits[], int ParityCheckCount[], double input[]) {
+    int                max_iter, dec_type;
+    float       q_scale_factor, r_scale_factor;
+    int                max_row_weight, max_col_weight;
+    int         CodeLength, NumberParityBits, NumberRowsHcols, shift, H1;
+    int         i;
+    struct c_node *c_nodes;
+    struct v_node *v_nodes;
     
+    /* default values */
+
+    max_iter  = ldpc->max_iter;
+    dec_type  = ldpc->dec_type;
+    q_scale_factor = ldpc->q_scale_factor;
+    r_scale_factor = ldpc->r_scale_factor;
+
+    CodeLength = ldpc->CodeLength;                    /* length of entire codeword */
+    NumberParityBits = ldpc->NumberParityBits;
+    NumberRowsHcols = ldpc->NumberRowsHcols;
+
+    /* derive some parameters */
+
+    shift = (NumberParityBits + NumberRowsHcols) - CodeLength;
+    if (NumberRowsHcols == CodeLength) {
+        H1=0;
+        shift=0;
+    } else {
+        H1=1;
+    }
+       
+    max_row_weight = ldpc->max_row_weight;
+    max_col_weight = ldpc->max_col_weight;
+       
+    c_nodes = calloc( NumberParityBits, sizeof( struct c_node ) );
+    v_nodes = calloc( CodeLength, sizeof( struct v_node));
+       
+    /* initialize c-node and v-node structures */
+
+    c_nodes = calloc( NumberParityBits, sizeof( struct c_node ) );
+    v_nodes = calloc( CodeLength, sizeof( struct v_node));
+       
+    init_c_v_nodes(c_nodes, shift, NumberParityBits, max_row_weight, ldpc->H_rows, H1, CodeLength, 
+                   v_nodes, NumberRowsHcols, ldpc->H_cols, max_col_weight, dec_type, input);
+
+    int DataLength = CodeLength - NumberParityBits;
+    int *data_int = calloc( DataLength, sizeof(int) );
+       
+    /* need to clear these on each call */
+
+    for(i=0; i<max_iter; i++)
+        ParityCheckCount[i] = 0;
+     for(i=0; i<max_iter*CodeLength; i++)
+         DecodedBits[i] = 0;
+
+    /* Call function to do the actual decoding */
+
+    if ( dec_type == 1) {
+        MinSum( ParityCheckCount, DecodedBits, c_nodes, v_nodes, CodeLength, 
+                NumberParityBits, max_iter, r_scale_factor, q_scale_factor, data_int );
+    } else if ( dec_type == 2) {
+        fprintf(stderr, "dec_type = 2 not currently supported");
+        /* ApproximateMinStar( BitErrors, DecodedBits, c_nodes, v_nodes, 
+           CodeLength, NumberParityBits, max_iter, r_scale_factor, q_scale_factor );*/
+    } else {
+        SumProduct( ParityCheckCount, DecodedBits, c_nodes, v_nodes, CodeLength, 
+                    NumberParityBits, max_iter, r_scale_factor, q_scale_factor, data_int ); 
+    }
+
+    /* Clean up memory */
+
+    free( data_int );
+
+    /*  Cleaning c-node elements */
+
+    for (i=0;i<NumberParityBits;i++) {
+        free( c_nodes[i].index );
+        free( c_nodes[i].message );
+        free( c_nodes[i].socket );
+    }
+       
+    /* printf( "Cleaning c-nodes \n" ); */
+    free( c_nodes );
+       
+    /* printf( "Cleaning v-node elements\n" ); */
+    for (i=0;i<CodeLength;i++) {
+        free( v_nodes[i].index);
+        free( v_nodes[i].sign );
+        free( v_nodes[i].message );
+        free( v_nodes[i].socket );
+    }
+       
+    /* printf( "Cleaning v-nodes \n" ); */
+    free( v_nodes );
 }
 
 
+void sd_to_llr(double llr[], double sd[], int n) {
+    double sum, mean, sign, sumsq, estvar, estEsN0, x;
+    int i;
+
+    /* convert SD samples to LLRs -------------------------------*/
+
+    sum = 0.0;
+    for(i=0; i<n; i++)
+        sum += fabs(sd[i]);
+    mean = sum/n;
+                
+    /* scale by mean to map onto +/- 1 symbol position */
+
+    for(i=0; i<n; i++) {
+        sd[i] /= mean;
+    }
+
+    /* find variance from +/-1 symbol position */
+
+    sum = sumsq = 0.0; 
+    for(i=0; i<n; i++) {
+        sign = (sd[i] > 0.0) - (sd[i] < 0.0);
+        x = (sd[i] - sign);
+        sum += x;
+        sumsq += x*x;
+    }
+    mean = sum/n;
+    estvar = sumsq/n - mean*mean;
+
+    estEsN0 = 1.0/(2.0 * estvar + 1E-3); 
+    for(i=0; i<n; i++)
+        llr[i] = 4.0 * estEsN0 * sd[i];              
+}
index be4302306c844589c9b9b2cbf9ed80d05c12f6fa..44a6b8869cf763646d1da1dea5b1f0b93d3245b5 100644 (file)
@@ -4,12 +4,31 @@
   CREATED: Sep 2016
 
   C-callable core functions for MpDecode, so they can be used for
-  Octave and C programs.
+  Octave and C programs.  Also some convenience functions to help use
+  the C-callable LDPC decoder in C programs.
 */
 
 #ifndef __MPDECODE_CORE__
 #define __MPDECODE_CORE__
 
+struct LDPC {
+    int max_iter;
+    int dec_type;
+    int q_scale_factor;
+    int r_scale_factor;
+    int CodeLength;
+    int NumberParityBits;
+    int NumberRowsHcols;
+    int max_row_weight;
+    int max_col_weight;
+    double *H_rows;
+    double *H_cols;
+};
+
+void run_ldpc_decoder(struct LDPC *ldpc, int DecodedBits[], int ParityCheckCount[], double input[]);
+
+void sd_to_llr(double llr[], double sd[], int n);
+
 struct v_node {
   int degree;
   float initial_value;