codec2-dev building again but may have broken some ofdm or dr_rs232 code, still testing
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 12 Apr 2018 02:42:24 +0000 (02:42 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 12 Apr 2018 02:42:24 +0000 (02:42 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@3466 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/src/drs232_ldpc.c
codec2-dev/src/fsk_mod_ext_vco.c
codec2-dev/src/ldpc_dec.c
codec2-dev/src/mpdecode_core.c
codec2-dev/src/mpdecode_core.h

index 40bb7061fe1045284ed7bee7e9a390846d74e3d5..31a4decabc38b082a338856076fa7d971da4d070 100755 (executable)
@@ -114,7 +114,7 @@ int main(int argc, char *argv[]) {
     uint8_t     packet[BYTES_PER_PACKET+CRC_BYTES];
     uint8_t     abyte;
     uint16_t    tx_checksum, rx_checksum, packet_errors, packets;
-    int         CodeLength, iter;
+    int         CodeLength, iter, parityCheckCount;
     struct LDPC ldpc;
 
     assert(sizeof(uw) == UW_BITS);
@@ -227,7 +227,7 @@ int main(int argc, char *argv[]) {
                /* now LDPC decode */
 
                sd_to_llr(llr, symbol_buf_no_rs232, CodeLength);
-               iter = run_ldpc_decoder(&ldpc, unpacked_packet, llr);
+               iter = run_ldpc_decoder(&ldpc, unpacked_packet, llr, &parityCheckCount);
 
                /* pack into bytes */
 
index 137bdab71007c392e191a4ac8808e18a4bf197af..91151f25ef2930cfacb1016741c94f43d8ecba3c 100644 (file)
@@ -86,8 +86,10 @@ int main(int argc,char *argv[]){
         /* 2 FSK -d/2, +d/2                */
         /* 4 FSK -3*d/2, -d/2, +d/2, 3*d/2 */
 
+        /* note: drive is inverted, a higher tone drives VCO voltage lower */
+
         float symf = sym;
-        float level = d*(symf - ((float)m-1)*0.5);
+        float level = d*(((float)m-1)*0.5 - symf);
         assert(level <= 32767.0);
         assert(level >= -32768.0);
         short level_short = (short)level;
index edf14bb33581526c3f7ef97df6226734c69244a7..479771a85ac80a365b6cf7ad70feb2268ffb0543 100644 (file)
@@ -68,7 +68,7 @@ void extract_output(char out_char[], int DecodedBits[], int ParityCheckCount[],
 int main(int argc, char *argv[])\r
 {    \r
     int         CodeLength, NumberParityBits;\r
-    int         i, r, num_ok, num_runs, codename;\r
+    int         i, r, num_ok, num_runs, codename, parityCheckCount, mute, state, next_state, frame;\r
     char        out_char[CODELENGTH], *adetected_data;\r
     struct LDPC ldpc;\r
     double     *ainput;\r
@@ -84,13 +84,13 @@ int main(int argc, char *argv[])
         fprintf(stderr, "usage: %s InOneSymbolPerDouble OutOneBitPerByte [--sd] [--half] [--code CodeName]\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, "   --code                  Treat input file samples as Soft Decision\n");\r
-        fprintf(stderr, "                           demod outputs rather than LLRs\n");\r
+        fprintf(stderr, "   --code                  Use LDPC code CodeName\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, "   --mute                  Only output frames with < 10%% parity check fails\n");\r
         fprintf(stderr, "\n");\r
         exit(0);\r
     }\r
@@ -157,7 +157,7 @@ int main(int argc, char *argv[])
 \r
         for(r=0; r<num_runs; r++) {\r
 \r
-            run_ldpc_decoder(&ldpc, out_char, ainput);\r
+            run_ldpc_decoder(&ldpc, out_char, ainput, &parityCheckCount);\r
 \r
             int ok = 0;\r
             for (i=0; i<CodeLength; i++) {\r
@@ -198,12 +198,16 @@ int main(int argc, char *argv[])
 \r
         sdinput = 0;\r
         readhalfframe = 0;\r
+        mute = 0; state = 0; frame = 0;\r
         if (opt_exists(argv, argc, "--sd")) {\r
             sdinput = 1;\r
         }\r
         if (opt_exists(argv, argc, "--half")) {\r
             readhalfframe = 1;\r
         }\r
+        if (opt_exists(argv, argc, "--mute")) {\r
+            mute = 1;\r
+        }\r
 \r
         double *input_double = calloc(CodeLength, sizeof(double));\r
 \r
@@ -222,13 +226,46 @@ int main(int argc, char *argv[])
                 sd_to_llr(input_double, input_double, CodeLength);\r
             }\r
 \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
-            if (iter != MAX_ITER) {\r
-              fwrite(out_char, sizeof(char), ldpc.NumberRowsHcols, fout);\r
+            iter = run_ldpc_decoder(&ldpc, out_char, input_double, &parityCheckCount);\r
+\r
+            if (mute) {\r
+\r
+                // Output data bits if decoder converged, or was\r
+                // within 10% of all parity checks converging (10% est\r
+                // BER).  usefule for real world operation as it can\r
+                // resync and won't send crappy packets to the decoder\r
+                \r
+                float ber_est = (float)(ldpc.NumberParityBits - parityCheckCount)/ldpc.NumberParityBits;\r
+                //fprintf(stderr, "iter: %4d parityCheckErrors: %4d ber: %3.2f\n", iter, ldpc.NumberParityBits - parityCheckCount, ber_est);\r
+                if (ber_est < 0.1) {\r
+                    fwrite(out_char, sizeof(char), ldpc.NumberRowsHcols, fout);\r
+                }\r
+\r
+            } else {\r
+                \r
+                // Output all data packets, based on initial FEC sync\r
+                // estimate.  Useful for testing with cohpsk_put_bits,\r
+                // as it maintains sync with test bits state machine.\r
+                \r
+                next_state = state;\r
+                switch(state) {\r
+                case 0:\r
+                    if (iter < MAX_ITER) {\r
+                        /* OK we've found which frame to sync on */\r
+                        next_state = 1;\r
+                        frame = 0;\r
+                    }\r
+                    break;\r
+                case 1:\r
+                    frame++;\r
+                    if ((frame % 2) == 0) {\r
+                        /* write decoded packets every second input frame */\r
+                        fwrite(out_char, sizeof(char), ldpc.NumberRowsHcols, fout);\r
+                    }\r
+                    break;\r
+                }\r
+                state = next_state;\r
+                //fprintf(stderr, "state: %d iter: %d\n", state, iter);\r
             }\r
 \r
             for(i=0; i<offset; i++) {\r
index e3d6d12bfbdc1d4f3875bc888a98de23bfd023f8..9faf31b30b067d4f5f531a293e392aa308ba5ddc 100644 (file)
@@ -46,8 +46,7 @@ static float phi0(
   }
 }
 
-static float correction(
-                       float xinput )
+static float correction(float xinput )
 {
   if (xinput > 2.625 )
     return( 0 );
@@ -67,6 +66,31 @@ static float LambdaAPPstar(  float mag1,
     return( fabs( mag1 + correction( mag1 + mag2 ) - correction( mag2 - mag1 ) ) );
 }
 
+/* Values for linear approximation (DecoderType=5) */
+
+#define AJIAN -0.24904163195436
+#define TJIAN 2.50681740420944
+
+/* The linear-log-MAP algorithm */
+
+static float max_star0(
+                       float delta1, 
+                       float delta2 )
+{
+    register float diff;
+       
+    diff = delta2 - delta1;
+
+    if ( diff > TJIAN )
+        return( delta2 );
+    else if ( diff < -TJIAN )
+        return( delta1 );
+    else if ( diff > 0 )
+        return( delta2 + AJIAN*(diff-TJIAN) );
+    else
+        return( delta1 - AJIAN*(diff+TJIAN) );
+}
+
 void init_c_v_nodes(struct c_node *c_nodes, 
                     int     shift, 
                     int     NumberParityBits, 
@@ -562,7 +586,7 @@ void SumProduct(     int      BitErrors[],
 
 /* Convenience function to call LDPC decoder from C programs */
 
-int run_ldpc_decoder(struct LDPC *ldpc, char out_char[], double input[]) {
+int run_ldpc_decoder(struct LDPC *ldpc, char out_char[], double input[], int *parityCheckCount) {
     int                max_iter, dec_type;
     float       q_scale_factor, r_scale_factor;
     int                max_row_weight, max_col_weight;
@@ -635,6 +659,8 @@ int run_ldpc_decoder(struct LDPC *ldpc, char out_char[], double input[]) {
 
     int iter = extract_output(out_char, DecodedBits, ParityCheckCount, max_iter, CodeLength, NumberParityBits);
 
+    *parityCheckCount = ParityCheckCount[iter-1];
+
     /* Clean up memory */
 
     free(ParityCheckCount);
@@ -702,6 +728,81 @@ void sd_to_llr(double llr[], double sd[], int n) {
 }
 
 
+/*
+   output[] is symbol likelihood
+
+   Note we assume fading[] is real, it is also possible to compute
+   with complex fading.
+*/
+
+void Demod2D(float  symbol_likelihood[],       /* output, M*number_symbols              */
+             COMP   r[],                       /* received QPSK symbols, number_symbols */
+             COMP   S_matrix[],                /* constellation of size M               */
+             float  EsNo,
+             float  fading[],                  /* real fading values, number_symbols    */
+             int    number_symbols)
+{
+    int     M=4;
+    int     i,j;
+    float   tempsr, tempsi, Er, Ei;
+
+    /* determine output */
+  
+    for (i=0;i<number_symbols;i++) {                /* go through each received symbol */
+        for (j=0;j<M;j++) {                         /* each postulated symbol          */
+            tempsr = fading[i]*S_matrix[j].real;
+            tempsi = fading[i]*S_matrix[j].imag;
+            Er = r[i].real - tempsr;
+            Ei = r[i].imag - tempsi;
+            symbol_likelihood[i*M+j] = -EsNo*(Er*Er+Ei*Ei);
+        }
+    }
+
+}
+
+
+void Somap(float  bit_likelihood[],      /* number_bits, bps*number_symbols */
+           float  symbol_likelihood[],   /* M*number_symbols                */
+           int    number_symbols)
+{
+    int   M=2, bps = 2;
+    int   n,i,j,k,mask;
+    float num[bps], den[bps];
+    float metric;
+
+    for (n=0; n<number_symbols; n++) { /* loop over symbols */
+        for (k=0;k<bps;k++) {
+            /* initialize */
+            num[k] = -1000000;                 
+            den[k] = -1000000;                 
+        }
+        for (i=0;i<M;i++) {
+            metric =  symbol_likelihood[n*M+i]; /* channel metric for this symbol */
+
+            mask = 1 << bps - 1;
+            for (j=0;j<bps;j++) {      
+                mask = mask >> 1;
+            }
+            mask = 1 << bps - 1;
+            
+            for (k=0;k<bps;k++) {      /* loop over bits */
+                if (mask&i) {
+                    /* this bit is a one */
+                    num[k] = max_star0( num[k], metric );
+                } else {
+                    /* this bit is a zero */
+                    den[k] = max_star0( den[k], metric );
+                }
+                mask = mask >> 1;
+            }
+        }
+        for (k=0;k<bps;k++) {
+            bit_likelihood[bps*n+k] = num[k] - den[k];
+        }
+    }
+}
+
 int extract_output(char out_char[], int DecodedBits[], int ParityCheckCount[], int max_iter, int CodeLength, int NumberParityBits) {
     int i, j;
 
index bbb6250fadf1cba682ffdf8711dc1cbb396090e9..308a930d54b98a51669cbf4d10717ce3984715bf 100644 (file)
@@ -11,6 +11,8 @@
 #ifndef __MPDECODE_CORE__
 #define __MPDECODE_CORE__
 
+#include "comp.h"
+
 struct LDPC {
     int max_iter;
     int dec_type;
@@ -25,10 +27,13 @@ struct LDPC {
     double *H_cols;
 };
 
-int run_ldpc_decoder(struct LDPC *ldpc, char out_char[], double input[]);
+int run_ldpc_decoder(struct LDPC *ldpc, char out_char[], double input[], int *parityCheckCount);
 
 void sd_to_llr(double llr[], double sd[], int n);
 
+void Demod2D(float symbol_likelihood[], COMP r[], COMP S_matrix[], float EsNo, float fading[], int number_symbols);
+void SomapDemod2D(float bit_likelihood[], float symbol_likelihood[]);
+
 struct v_node {
   int degree;
   float initial_value;