LDPC encoded test frame, measuring uncoded and coded errors for single interleaver...
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sat, 14 Apr 2018 10:06:54 +0000 (10:06 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sat, 14 Apr 2018 10:06:54 +0000 (10:06 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@3489 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/ofdm_ldpc_rx.m
codec2-dev/octave/ofdm_ldpc_tx.m
codec2-dev/octave/ofdm_lib.m
codec2-dev/octave/ofdm_rx.m
codec2-dev/octave/ofdm_tx.m
codec2-dev/src/ofdm_demod.c
codec2-dev/src/test_bits_ofdm.h

index 9e6bf6dad0616a48cb022042bff01e43805d5515..1fa5fcb13a14af1ca1aaeb5566718ecacebe92ec 100644 (file)
@@ -56,10 +56,10 @@ function ofdm_ldpc_rx(filename, interleave_frames = 1, error_pattern_filename)
   
   % OK generate tx frame for BER calcs
 
-  rand('seed', 100);
+  rand('seed', 1);
+  atx_bits = round(rand(1,code_param.data_bits_per_frame));
   tx_bits = []; tx_codewords = [];
   for f=1:interleave_frames
-    atx_bits = round(rand(1,code_param.data_bits_per_frame));
     tx_bits = [tx_bits atx_bits];
     acodeword = LdpcEncode(atx_bits, code_param.H_rows, code_param.P_matrix);
     tx_codewords = [tx_codewords acodeword];
index bcebb39f3d36c1b51b832d8cdca5a750ff5a4853..55e4154a1cbd4c0f28d1e24ddc2af83e2d405fbb 100644 (file)
@@ -64,10 +64,15 @@ function ofdm_ldpc_tx(filename, Nsec, interleave_frames = 1, EbNodB=100, channel
 
   % OK generate an interleaver frame of codewords from random data bits
 
-  rand('seed', 100);
+  % use single frame of test bits with seed of 1
+  % to keep compatable with ofdm_test_bits.c and friends
+  % as per create_ldpc_test_frame
+  
+  rand('seed', 1);
+  atx_bits = round(rand(1,code_param.data_bits_per_frame));
+  
   tx_bits = tx_symbols = [];
   for f=1:interleave_frames
-    atx_bits = round(rand(1,code_param.data_bits_per_frame));
     tx_bits = [tx_bits atx_bits];
     codeword = LdpcEncode(atx_bits, code_param.H_rows, code_param.P_matrix);
     for b=1:2:code_param.code_bits_per_frame
index 0b2921b90689eacc7fb32aad1c0cf1c0e4f61df2..05644be3bb093842bb6466e3e10e7abc2f5a20df 100644 (file)
@@ -510,6 +510,52 @@ function [rx_bits states aphase_est_pilot_log rx_np rx_amp] = ofdm_demod(states,
 endfunction
 
 
+% generate a test frame of ldpc encoded bits, used for raw and
+% coded BER testing.  Includes UW and txt files
+
+function [tx_bits payload_data_bits] = create_ldpc_test_frame
+  Ts = 0.018; Tcp = 0.002; Rs = 1/Ts; bps = 2; Nc = 17; Ns = 8;
+  states = ofdm_init(bps, Rs, Tcp, Ns, Nc);
+  ofdm_load_const;
+
+  % Set up LDPC code
+
+  mod_order = 4; bps = 2; modulation = 'QPSK'; mapping = 'gray';
+
+  init_cml('/home/david/Desktop/cml/'); % TODO: make this path sensible and portable
+  load HRA_112_112.txt
+  [code_param framesize rate] = ldpc_init_user(HRA_112_112, modulation, mod_order, mapping);
+  assert(Nbitsperframe == (code_param.code_bits_per_frame + Nuwbits + Ntxtbits));
+
+  rand('seed',1);
+  payload_data_bits = round(rand(1,code_param.data_bits_per_frame));
+  codeword = LdpcEncode(payload_data_bits, code_param.H_rows, code_param.P_matrix);
+  Nsymbolsperframe = length(codeword)/bps;
+  
+  % need all these steps to get actual raw codeword bits at demod
+  % note this will only work for single interleaver frame case,
+  % but that's enough for initial quick tests
+  
+  tx_symbols = [];
+  for s=1:Nsymbolsperframe
+    tx_symbols = [tx_symbols qpsk_mod( codeword(2*(s-1)+1:2*s) )];
+  end
+
+  tx_symbols = gp_interleave(tx_symbols);
+
+  codeword_raw = [];
+  for s=1:Nsymbolsperframe
+    codeword_raw = [codeword_raw qpsk_demod(tx_symbols(s))];
+  end
+
+  % insert UW and txt bits
+  
+  tx_bits = [zeros(1,Nuwbits) zeros(1,Ntxtbits) codeword_raw];
+  assert(Nbitsperframe == length(tx_bits));
+
+endfunction
+
+
 % Save test bits frame to a text file in the form of a C array
 % 
 % usage:
@@ -517,15 +563,8 @@ endfunction
 %
 
 function test_bits_ofdm_file
-
-  Ts = 0.018; Tcp = 0.002; Rs = 1/Ts; bps = 2; Nc = 17; Ns = 8;
-  states = ofdm_init(bps, Rs, Tcp, Ns, Nc);
-  ofdm_load_const;
-
-  rand('seed',1);
-  test_bits_ofdm = round(rand(1,Nbitsperframe));
-  test_bits_ofdm(1:states.Ntxtbits) = 0;  % insert Unique Word
-  printf("%d test bits\n", Nbitsperframe);
+  [test_bits_ofdm payload_data_bits] = create_ldpc_test_frame;
+  printf("%d test bits\n", length(test_bits_ofdm));
   
   f=fopen("../src/test_bits_ofdm.h","wt");
   fprintf(f,"/* Generated by test_bits_ofdm_file() Octave function */\n\n");
@@ -533,7 +572,13 @@ function test_bits_ofdm_file
   for m=1:length(test_bits_ofdm)-1
     fprintf(f,"  %d,\n",test_bits_ofdm(m));
   endfor
-  fprintf(f,"  %d\n};\n",test_bits_ofdm(length(test_bits_ofdm)));
+  fprintf(f,"  %d\n};\n",test_bits_ofdm(length(payload_data_bits)));
+
+  fprintf(f,"\nconst int payload_data_bits[]={\n");
+  for m=1:length(payload_data_bits)-1
+    fprintf(f,"  %d,\n",payload_data_bits(m));
+  endfor
+  fprintf(f,"  %d\n};\n",payload_data_bits(length(payload_data_bits)));
   fclose(f);
 
 endfunction
index 8ef93ce0a11ff0ff81991ce444d37ae717cf7ae0..c5eebf72c8bcffdfdff6658e8bc719cf13ecb67d 100644 (file)
@@ -25,10 +25,8 @@ function ofdm_rx(filename, error_pattern_filename)
 
   % OK re-generate tx frame for BER calcs
 
-  rand('seed', 1);
-  tx_bits = round(rand(1,Nbitsperframe));
-  tx_bits(1:states.Nuwbits) = 0;   % insert UW
+  tx_bits = create_ldpc_test_frame;
+
   % init logs and BER stats
 
   rx_bits = []; rx_np_log = []; timing_est_log = []; delta_t_log = []; foff_est_hz_log = [];
index 371922a574621f675b9ebcbeb325732bbde0b886..9571d788edc53bafe618f48177a797ab22fdb46d 100644 (file)
@@ -30,9 +30,7 @@ function ofdm_tx(filename, Nsec, EbNodB=100, channel='awgn', freq_offset_Hz=0, d
 
   Nrows = Nsec*Rs;
   Nframes = floor((Nrows-1)/Ns);
-  rand('seed', 1);
-  tx_bits = round(rand(1,Nbitsperframe));
-  tx_bits(1:states.Nuwbits) = 0; % insert UW
+  tx_bits = create_ldpc_test_frame;
   
   tx = [];
   for f=1:Nframes
index 959e6a31779962165805628acf4530278dea16f3..37b8b4aaa045ea60f45a0fe52ae6d324d7b98505 100644 (file)
@@ -5,8 +5,13 @@
   DATE CREATED: Mar 2018
 
   Given an input file of raw file (8kHz, 16 bit shorts) of OFDM modem
-  samples.  Optionally outputs one char per bit (hard decision), or
-  soft decision rx_np and rx_amp QPSK symbols information for LDPC decoder.
+  samples.  Optionally:
+
+    1/ outputs one char per bit (hard decision)
+    2/ bit LLRS, one double per bir, for external LDPC decoder like ldpc_dec
+    3/ LDPC decoded bits, one char per bit
+
+  Also has test frame modes for uncoded and coded operation.
 
 \*---------------------------------------------------------------------------*/
 
 #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   */
+#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     */
+#define DATA_BITSPERFRAME  112    /* number of LDPC payload data 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   */
@@ -73,6 +79,7 @@ int main(int argc, char *argv[])
 
     int            i, j, f, oct, logframes, arg, llr_en;
     int            Nerrs, Terrs, Tbits, Terrs2, Tbits2, testframes, frame_count;
+    int            ldpc_en, Nerrs_coded, Tbits_coded, Terrs_coded;
     
     struct LDPC   ldpc;
     ldpc.max_iter = HRA_112_112_MAX_ITER;
@@ -92,10 +99,12 @@ int main(int argc, char *argv[])
        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, "  --llr       LLR output, one double per bit, %d doubles/frame\n", CODED_BITSPERFRAME);
         fprintf(stderr, "  -t          Receive test frames and count errors\n");
+        fprintf(stderr, "  --ldpc      Run (224,112) LDPC decoder.  This forces 112, one char/bit output values\n"
+                        "              per frame.  In testframe mode (-t) raw and coded errors will be counted\n");
         fprintf(stderr, "  -v          Verbose info the stderr\n");
         fprintf(stderr, "  -o          Octave log file for testing\n");
-        fprintf(stderr, "  --llr       LLR output, one double per bit, %d doubles/frame\n", CODED_BITSPERFRAME);
         fprintf(stderr, "\n");
        exit(1);
     }
@@ -136,11 +145,17 @@ int main(int argc, char *argv[])
         testframes = 1;
     }
 
+    ldpc_en = 0;
+    if (opt_exists(argv, argc, "--ldpc")) {
+        ldpc_en = 1;
+        llr_en = 1;
+    }
+
     ofdm = ofdm_create(OFDM_CONFIG_700D);
     assert(ofdm != NULL);
 
     if ((arg = opt_exists(argv, argc, "-v")) != 0) {
-        ofdm_set_verbose(ofdm, atoi(argv[arg+1]));
+        ofdm_set_verbose(ofdm, 1);
     }
 
     int Nbitsperframe = ofdm_get_bits_per_frame(ofdm);
@@ -151,10 +166,11 @@ int main(int argc, char *argv[])
     int    rx_bits[Nbitsperframe];
     char   rx_bits_char[Nbitsperframe];
     int    rx_uw[OFDM_NUWBITS];
-    f = 0; Nerrs = Terrs = Tbits = Terrs2 = Tbits2 = frame_count = 0;
+    f = 0; Nerrs = Terrs = Tbits = Terrs2 = Tbits2 = Terrs_coded = Tbits_coded = frame_count = 0;
+    int    parityCheckCount, iter;
 
     float EsNo = 10;
-    fprintf(stderr,"Warning EsNo: %f hard coded", EsNo);
+    fprintf(stderr,"Warning EsNo: %f hard coded\n", EsNo);
 
     nin_frame = ofdm_get_nin(ofdm);
     while(fread(rx_scaled, sizeof(short), nin_frame, fin) == nin_frame) {
@@ -201,40 +217,33 @@ int main(int argc, char *argv[])
                     llr[i] = -bit_likelihood[i];
                 }
                 
-                int    iter;
                 char   out_char[CODED_BITSPERFRAME];
-                int    parityCheckCount;
                 
                 for(i=0; i<CODED_BITSPERFRAME; i++) {
                     llr[i] = -bit_likelihood[i];
                 }
-
-                int ldpc_en = 1;
+                
                 if (ldpc_en) {
+                    
                     /* run LDPC decoder and output decoded bits */
-                    /* TODO
-                       [ ] how to test uncoded modem, maybe use LDPC encoded frame?
-                       [ ] log unsucessfully decoded frames, outout them anyway?
-                     */
                     
                     iter = run_ldpc_decoder(&ldpc, out_char, llr, &parityCheckCount);
-                    #ifdef TODO
-                    if (testframes) {
-                        /* measure raw and coded BER */
-                        Terrs += Nerrs;
-                        Tbits += Nbitsperframe;
-                    }
                     
-                    if (frame_count >= NDISCARD) {
-                        Terrs2 += Nerrs;
-                        Tbits2 += Nbitsperframe;
+                    if (testframes) {
+                        Nerrs_coded = 0;
+                        for(i=0; i<DATA_BITSPERFRAME; i++) {
+                            if (payload_data_bits[i] != out_char[i]) {
+                                Nerrs_coded++;
+                            }
+                        }
+                        Terrs_coded += Nerrs_coded;
+                        Tbits_coded += DATA_BITSPERFRAME;
                     }
-                    #endif
+                    fwrite(out_char, sizeof(char), CODED_BITSPERFRAME, fout);
+                } else {
+                    /* external LDPC decoder, so output LLRs */
+                    fwrite(llr, sizeof(double), CODED_BITSPERFRAME, fout);
                 }
-                
-                fprintf(stderr, "iter: %d parityCheckCount: %d\n", iter, parityCheckCount);
-
-                fwrite(llr, sizeof(double), CODED_BITSPERFRAME, fout);
 
             } else {
                 /* simple hard decision output for uncoded testing, all bits in frame dumped inlcuding UW and txt */
@@ -281,8 +290,12 @@ int main(int argc, char *argv[])
         }
 
         if (ofdm->verbose) {
-            fprintf(stderr, "f: %2d state: %-10s uw_errors: %2d %1d  Nerrs: %3d foff: %3.1f\n",
+            fprintf(stderr, "f: %2d state: %-10s uw_errors: %2d %1d  Nerrs: %3d foff: %3.1f",
                     f, ofdm->last_sync_state, ofdm->uw_errors, ofdm->sync_counter, Nerrs, ofdm->foff_est_hz);
+            if (ldpc_en) {
+                fprintf(stderr, " Nerrs_coded: %3d iter: %3d pCC: %3d", Nerrs_coded, iter, parityCheckCount);
+            }
+            fprintf(stderr, "\n");    
         }
 
         /* optional logging of states */
@@ -323,8 +336,12 @@ int main(int argc, char *argv[])
     fclose(fout);
 
     if (testframes) {
-        fprintf(stderr, "BER..: %5.4f Tbits: %5d Terrs: %5d\n", (float)Terrs/Tbits, Tbits, Terrs);
-        fprintf(stderr, "BER2.: %5.4f Tbits: %5d Terrs: %5d\n", (float)Terrs2/Tbits2, Tbits2, Terrs2);
+        fprintf(stderr, "BER......: %5.4f Tbits: %5d Terrs: %5d\n", (float)Terrs/Tbits, Tbits, Terrs);
+        fprintf(stderr, "BER2.....: %5.4f Tbits: %5d Terrs: %5d\n", (float)Terrs2/Tbits2, Tbits2, Terrs2);
+        if (ldpc_en) {
+            fprintf(stderr, "Coded BER: %5.4f Tbits: %5d Terrs: %5d\n",
+                    (float)Terrs_coded/Tbits_coded, Tbits_coded, Terrs_coded);
+        }        
     }
     
     /* optionally dump Octave files */
index 456a9be14dd6fb76c9548139932b019fbdeac99f..021200979b3828b50d38ce251ffbd47c59b27c9b 100644 (file)
@@ -11,23 +11,40 @@ const int test_bits_ofdm[]={
   0,
   0,
   0,
-  1,
   0,
   0,
   0,
   0,
+  1,
+  1,
   0,
+  1,
+  1,
   0,
+  1,
   0,
   0,
   1,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
   1,
   0,
   1,
+  1,
+  0,
   0,
   1,
   0,
+  1,
   0,
+  1,
   0,
   0,
   0,
@@ -39,52 +56,77 @@ const int test_bits_ofdm[]={
   1,
   0,
   0,
-  0,
+  1,
+  1,
   0,
   0,
   1,
   1,
   1,
   1,
+  0,
+  0,
   1,
   1,
-  0,
   1,
   0,
-  1,
   0,
   1,
   1,
   0,
+  0,
+  1,
+  1,
+  1,
+  1,
   1,
   0,
   0,
+  1,
   0,
   0,
   1,
-  0,
   1,
   0,
   1,
   0,
   1,
   1,
+  0,
   1,
   0,
   1,
   0,
+  0,
+  0,
+  0,
   1,
   0,
+  0,
   1,
   1,
   0,
+  0,
+  0,
+  0,
   1,
   1,
   0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  1,
   1,
   0,
   0,
   1,
+  1,
+  1,
+  1,
+  0,
+  1,
   0,
   1,
   0,
@@ -93,9 +135,11 @@ const int test_bits_ofdm[]={
   1,
   1,
   1,
+  1,
   0,
   0,
   0,
+  1,
   0,
   0,
   0,
@@ -104,8 +148,14 @@ const int test_bits_ofdm[]={
   1,
   0,
   0,
+  0,
+  0,
+  0,
   1,
+  0,
+  0,
   1,
+  0,
   1,
   0,
   0,
@@ -122,17 +172,21 @@ const int test_bits_ofdm[]={
   1,
   1,
   1,
+  0,
+  0,
   1,
-  1,
-  1,
+  0,
+  0,
   1,
   0,
+  0,
   1,
   1,
   1,
   0,
   0,
-  1,
+  0,
+  0,
   1,
   0,
   0,
@@ -144,56 +198,91 @@ const int test_bits_ofdm[]={
   0,
   0,
   0,
+  0,
   1,
   0,
   0,
-  1,
-  1,
-  1,
+  0,
+  0,
+  0,
   1,
   0,
+  0,
+  0,
   1,
   0,
+  0,
+  0,
+  0,
+  0,
+  0,
   1,
   1,
   0,
+  0,
   1,
   1,
   1,
   1,
   0,
   1,
+  0,
   1,
   1,
   1,
-  1,
-  0,
   0,
   1,
   1,
   1,
   0,
-  1,
   0,
-  1,
   0,
+  0,
+  0
+};
+
+const int payload_data_bits[]={
   1,
   1,
+  0,
+  0,
   1,
   1,
   1,
+  0,
   1,
+  0,
   1,
   0,
   0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
   1,
   1,
+  0,
   1,
+  0,
   1,
   0,
   0,
   0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
   1,
+  0,
+  0,
+  0,
+  0,
+  0,
   1,
   1,
   1,
@@ -201,13 +290,23 @@ const int test_bits_ofdm[]={
   1,
   1,
   0,
+  1,
   0,
+  1,
   0,
+  1,
+  1,
   0,
   1,
+  0,
+  0,
+  0,
+  0,
   1,
   0,
+  1,
   0,
+  1,
   0,
   1,
   1,
@@ -215,6 +314,7 @@ const int test_bits_ofdm[]={
   0,
   1,
   0,
+  1,
   0,
   1,
   1,
@@ -222,14 +322,25 @@ const int test_bits_ofdm[]={
   1,
   1,
   0,
+  1,
   0,
   0,
   1,
+  0,
   1,
   0,
   0,
   0,
   1,
+  1,
+  1,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
   0,
   1,
   0,
@@ -238,5 +349,9 @@ const int test_bits_ofdm[]={
   1,
   1,
   0,
+  0,
+  1,
+  1,
+  1,
   0
 };