some LDPC frames decoding from ofdm_demod, need to do some cleanup
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Fri, 13 Apr 2018 06:28:07 +0000 (06:28 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Fri, 13 Apr 2018 06:28:07 +0000 (06:28 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@3474 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/src/CMakeLists.txt
codec2-dev/src/gp_interleaver.c [new file with mode: 0644]
codec2-dev/src/gp_interleaver.h [new file with mode: 0644]
codec2-dev/src/ldpc_dec.c
codec2-dev/src/ldpc_enc.c
codec2-dev/src/mpdecode_core.c
codec2-dev/src/mpdecode_core.h
codec2-dev/src/ofdm_demod.c

index b071a9a5260546bc038e4d6b09b976695c45f4f9..2cb6fc798e55676936b119d6c9725e0257cb7c6a 100644 (file)
@@ -340,7 +340,7 @@ target_link_libraries(ofdm_put_test_bits ${CMAKE_REQUIRED_LIBRARIES} codec2)
 add_executable(ofdm_mod ofdm_mod.c)
 target_link_libraries(ofdm_mod ${CMAKE_REQUIRED_LIBRARIES} codec2)
 
-add_executable(ofdm_demod ofdm_demod.c octave.c mpdecode_core.c)
+add_executable(ofdm_demod ofdm_demod.c octave.c mpdecode_core.c gp_interleaver.c)
 target_link_libraries(ofdm_demod ${CMAKE_REQUIRED_LIBRARIES} codec2)
 
 add_executable(fmfsk_mod fmfsk_mod.c)
diff --git a/codec2-dev/src/gp_interleaver.c b/codec2-dev/src/gp_interleaver.c
new file mode 100644 (file)
index 0000000..c138e16
--- /dev/null
@@ -0,0 +1,98 @@
+/*---------------------------------------------------------------------------*\
+
+  FILE........: gp_interleaver.c
+  AUTHOR......: David Rowe
+  DATE CREATED: April 2018
+
+  Golden Prime Interleaver. My interprestation of "On the Analysis and
+  Design of Good Algebraic Interleavers", Xie et al,eq (5).
+
+  See also octvae/gp_interleaver.m
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2018 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <assert.h>
+#include "gp_interleaver.h"
+
+/*
+  Choose b for Golden Prime Interleaver.  b is chosen to be the
+  closest integer, which is relatively prime to N, to the Golden
+  section of N.
+
+  Implemented with a LUT in C for convenience, Octave version
+  has a more complete implementation.
+*/
+
+int b_table[] = {
+    112,71,
+  224,139,
+  448,277,
+  672,419,
+  896,557,
+  1120,701,
+  1344,839,
+  1568,971,
+  1792,1109,
+  2016,1249,
+  2240,1399,
+  2464,1523,
+  2688,1663,
+  2912,1801,
+  3136,1949,
+  3360,2081,
+  3584,2213
+};
+
+int choose_interleaver_b(int Nbits)
+{
+    int i;
+
+    for(i=0; i<sizeof(b_table)/(2*sizeof(int)); i+=2) {
+        if (b_table[i] == Nbits) {
+            return b_table[i+1];
+        }
+    }
+
+    /* if we get it means a Nbits we dont have in our table so choke */
+    
+    assert(0);
+}
+
+
+void gp_interleave_comp(COMP interleaved_frame[], COMP frame[], int Nbits) {
+  int b = choose_interleaver_b(Nbits);
+  int i,j;
+   
+  for (i=0; i<Nbits; i++) {
+    j = b*i % Nbits;
+    interleaved_frame[j] = frame[i];
+  }
+}
+
+void gp_interleave_float(float interleaved_frame[], float frame[], int Nbits) {
+  int b = choose_interleaver_b(Nbits);
+  int i,j;
+   
+  for (i=0; i<Nbits; i++) {
+    j = b*i % Nbits;
+    interleaved_frame[j] = frame[i];
+  }
+}
+
diff --git a/codec2-dev/src/gp_interleaver.h b/codec2-dev/src/gp_interleaver.h
new file mode 100644 (file)
index 0000000..fd8a602
--- /dev/null
@@ -0,0 +1,39 @@
+/*---------------------------------------------------------------------------*\
+
+  FILE........: gp_interleaver.h
+  AUTHOR......: David Rowe
+  DATE CREATED: April 2018
+
+  Golden Prime Interleaver. My interprestation of "On the Analysis and
+  Design of Good Algebraic Interleavers", Xie et al,eq (5).
+
+  See also octvae/gp_interleaver.m
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2018 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __GP_INTERLEAVER__
+#define __GP_INTERLEAVER__
+
+#include "comp.h"
+
+void gp_interleave_comp(COMP interleaved_frame[], COMP frame[], int Nbits);
+void gp_interleave_float(float frame[], float interleaved_frame[], int Nbits);
+
+#endif
index 479771a85ac80a365b6cf7ad70feb2268ffb0543..e14b58a215204cf2f6a66c12a72b12371d7bc2a5 100644 (file)
@@ -85,6 +85,7 @@ int main(int argc, char *argv[])
         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                  Use LDPC code CodeName\n");\r
+        fprintf(stderr, "   --listcodes             List available LDPC codes\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
@@ -220,6 +221,7 @@ int main(int argc, char *argv[])
                 input_double[i] = 0.0;\r
             }\r
         }\r
+        fprintf(stderr, "CodeLength: %d offset: %d\n", CodeLength, offset);\r
 \r
         while(fread(&input_double[offset], sizeof(double), nread, fin) == nread) {\r
             if (sdinput) {\r
@@ -232,7 +234,7 @@ int main(int argc, char *argv[])
 \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
+                // BER).  useful 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
@@ -265,7 +267,7 @@ int main(int argc, char *argv[])
                     break;\r
                 }\r
                 state = next_state;\r
-                //fprintf(stderr, "state: %d iter: %d\n", state, iter);\r
+                fprintf(stderr, "state: %d iter: %d\n", state, iter);\r
             }\r
 \r
             for(i=0; i<offset; i++) {\r
index 6a6011ec0f0500812927de8624667addf91fdd70..bbc5375010d110dc1c52c38cbd78c5f6a4c53cb0 100644 (file)
@@ -31,27 +31,6 @@ int opt_exists(char *argv[], int argc, char opt[]) {
     return 0;
 }
 
-void encode(struct LDPC *ldpc, unsigned char ibits[], unsigned char pbits[]) {
-    unsigned int p, i, tmp, par, prev=0;
-    int          ind;
-    double      *H_rows = ldpc->H_rows;
-
-    for (p=0; p<ldpc->NumberParityBits; p++) {
-        par = 0; 
-
-        for (i=0; i<ldpc->max_row_weight; i++) {
-            ind = (int)H_rows[p + i*ldpc->NumberParityBits];
-            par = par + ibits[ind-1];
-        }
-
-        tmp = par + prev;
-
-        tmp &= 1;    // only retain the lsb 
-        prev = tmp; 
-        pbits[p] = tmp; 
-    }
-}
-
 int main(int argc, char *argv[])
 {
     unsigned char ibits[NUMBERROWSHCOLS];
index 28d1609bbbdfb0a698fc9e595625439694812fb6..5cda6795777be36e054fd6ce4a09dfacb0fbeed7 100644 (file)
 int extract_output(char out_char[], int DecodedBits[], int ParityCheckCount[], 
                     int max_iter, int CodeLength, int NumberParityBits);
 
+void encode(struct LDPC *ldpc, unsigned char ibits[], unsigned char pbits[]) {
+    unsigned int p, i, tmp, par, prev=0;
+    int          ind;
+    double      *H_rows = ldpc->H_rows;
+
+    for (p=0; p<ldpc->NumberParityBits; p++) {
+        par = 0; 
+
+        for (i=0; i<ldpc->max_row_weight; i++) {
+            ind = (int)H_rows[p + i*ldpc->NumberParityBits];
+            par = par + ibits[ind-1];
+        }
+
+        tmp = par + prev;
+
+        tmp &= 1;    // only retain the lsb 
+        prev = tmp; 
+        pbits[p] = tmp; 
+    }
+}
+
 /* Phi function */
 static float phi0(
                  float x )
index 82d27a443b33910cea5a7a00c815f6f8cdd0af72..6fd202db014545186b9a83768fd39447d5c5d626 100644 (file)
@@ -27,6 +27,8 @@ struct LDPC {
     double *H_cols;
 };
 
+void encode(struct LDPC *ldpc, unsigned char ibits[], unsigned char pbits[]);
+
 int run_ldpc_decoder(struct LDPC *ldpc, char out_char[], double input[], int *parityCheckCount);
 
 void sd_to_llr(double llr[], double sd[], int n);
index 8905e23645492f94c8114ab6a20e20007ad0868e..40d4b1c6943cdfd53b82c93b37a09d070ca324fc 100644 (file)
@@ -11,7 +11,7 @@
 \*---------------------------------------------------------------------------*/
 
 /*
-  Copyright (C) 2015 David Rowe
+  Copyright (C) 2018 David Rowe
 
   All rights reserved.
 
 #include "octave.h"
 #include "test_bits_ofdm.h"
 #include "mpdecode_core.h"
+#include "gp_interleaver.h"
 
 #define ASCALE   (2E5*1.1491/2.0) /* scale from shorts back to floats     */
 #define NFRAMES  100              /* just log the first 100 frames        */
 #define NDISCARD 20               /* BER2measure disctrds first 20 frames */
 #define CODED_BITSPERFRAME 224    /* number of LDPC codeword bits/frame   */
 
+#include "HRA_112_112.h"          /* generated by ldpc_fsk_lib.m:ldpc_decode() */
+#define CODED_BITSPERFRAME 224    /* number of LDPC codeword bits/frame   */
+
 int opt_exists(char *argv[], int argc, char opt[]) {
     int i;
     for (i=0; i<argc; i++) {
@@ -70,9 +74,22 @@ int main(int argc, char *argv[])
     int            i, j, f, oct, logframes, arg, llr_en;
     int            Nerrs, Terrs, Tbits, Terrs2, Tbits2, testframes, frame_count;
     
+    struct LDPC   ldpc;
+    ldpc.max_iter = HRA_112_112_MAX_ITER;
+    ldpc.dec_type = 0;
+    ldpc.q_scale_factor = 1;
+    ldpc.r_scale_factor = 1;
+    ldpc.CodeLength = HRA_112_112_CODELENGTH;
+    ldpc.NumberParityBits = HRA_112_112_NUMBERPARITYBITS;
+    ldpc.NumberRowsHcols = HRA_112_112_NUMBERROWSHCOLS;
+    ldpc.max_row_weight = HRA_112_112_MAX_ROW_WEIGHT;
+    ldpc.max_col_weight = HRA_112_112_MAX_COL_WEIGHT;
+    ldpc.H_rows = HRA_112_112_H_rows;
+    ldpc.H_cols = HRA_112_112_H_cols;
+
     if (argc < 3) {
         fprintf(stderr, "\n");
-       printf("usage: %s InputModemRawFile OutputFile [-o OctaveLogFile] [--sd] [-v VerboseLevel]\n", argv[0]);
+       printf("usage: %s InputModemRawFile OutputFile [-o OctaveLogFile] [--llr] [-v VerboseLevel]\n", argv[0]);
         fprintf(stderr, "\n");
         fprintf(stderr, "              Default output file format is one byte per bit hard decision\n");
         fprintf(stderr, "  -t          Receive test frames and count errors\n");
@@ -159,22 +176,58 @@ int main(int argc, char *argv[])
             if (llr_en) {
                 double symbol_likelihood[ (CODED_BITSPERFRAME/OFDM_BPS) * (1<<OFDM_BPS) ];
                 double bit_likelihood[CODED_BITSPERFRAME];
+                double llr[CODED_BITSPERFRAME];
 
                 /* first few symbols are used for UW and txt bits, find start of (224,112) LDPC codeword */
 
                 assert((OFDM_NUWBITS+OFDM_NTXTBITS+CODED_BITSPERFRAME) == OFDM_BITSPERFRAME);
 
-                COMP ldpc_codeword_symbols[(CODED_BITSPERFRAME/OFDM_BPS)];
+                COMP ldpc_codeword_symbols[CODED_BITSPERFRAME/OFDM_BPS];
                 for(i=0, j=(OFDM_NUWBITS+OFDM_NTXTBITS)/OFDM_BPS; i<(CODED_BITSPERFRAME/OFDM_BPS); i++,j++) {
                     ldpc_codeword_symbols[i].real = crealf(ofdm->rx_np[j]);
                     ldpc_codeword_symbols[i].imag = cimagf(ofdm->rx_np[j]);
                 }
                 float *ldpc_codeword_symbol_amps = &ofdm->rx_amp[(OFDM_NUWBITS+OFDM_NTXTBITS)/OFDM_BPS];
+
+                COMP codeword_symbols_de[CODED_BITSPERFRAME/OFDM_BPS];
+                float codeword_amps_de[CODED_BITSPERFRAME/OFDM_BPS];
+
+                gp_interleave_comp(codeword_symbols_de, ldpc_codeword_symbols, CODED_BITSPERFRAME/OFDM_BPS);
+                gp_interleave_float(codeword_amps_de, ldpc_codeword_symbol_amps, CODED_BITSPERFRAME/OFDM_BPS);
                 
-                Demod2D(symbol_likelihood, ldpc_codeword_symbols, S_matrix, EsNo, ldpc_codeword_symbol_amps,  CODED_BITSPERFRAME/OFDM_BPS);
+                Demod2D(symbol_likelihood, codeword_symbols_de, S_matrix, EsNo, codeword_amps_de,  CODED_BITSPERFRAME/OFDM_BPS);
                 Somap(bit_likelihood, symbol_likelihood, CODED_BITSPERFRAME/OFDM_BPS);
+                for(i=0; i<CODED_BITSPERFRAME; i++) {
+                    llr[i] = -bit_likelihood[i];
+                }
+                
+                int    iter;
+                char   out_char[CODED_BITSPERFRAME];
+                int    parityCheckCount;
+        
+        
+                fprintf(stderr, "\n");
+                for(i=0; i<CODED_BITSPERFRAME; i++) {
+                    llr[i] = -bit_likelihood[i];
+                    if (i <5) {
+                        fprintf(stderr, "%d symb: %f %f a: %f llr %f\n", i,
+                                ldpc_codeword_symbols[i].real, ldpc_codeword_symbols[i].imag,
+                                ldpc_codeword_symbol_amps[i], llr[i]);
+                    }
+                }
+                
+                fprintf(stderr, "\n");
+        
+                iter = run_ldpc_decoder(&ldpc, out_char, llr, &parityCheckCount);
                 
-                fwrite(bit_likelihood, sizeof(double), CODED_BITSPERFRAME, fout);
+                fprintf(stderr, "iter: %d parityCheckCount: %d\n", iter, parityCheckCount);
+                  /*
+                  for(i=0; i<CODED_BITSPERFRAME; i++) {
+                  fprintf(stderr, "%d ", out_char[i]);
+                  }
+                  */
+
+                fwrite(llr, sizeof(double), CODED_BITSPERFRAME, fout);
 
             } else {
                 /* simple hard decision output for uncoded testing, all bits in frame dumped inlcuding UW and txt */