C interleaver sync working, trying new C state macine to preventfalse syncs when...
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Mon, 16 Apr 2018 21:57:54 +0000 (21:57 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Mon, 16 Apr 2018 21:57:54 +0000 (21:57 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@3492 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/ofdm_ldpc_rx.m
codec2-dev/octave/ofdm_lib.m
codec2-dev/src/gp_interleaver.c
codec2-dev/src/gp_interleaver.h
codec2-dev/src/horus_demod.c
codec2-dev/src/mpdecode_core.c
codec2-dev/src/mpdecode_core.h
codec2-dev/src/ofdm.c
codec2-dev/src/ofdm_demod.c
codec2-dev/src/ofdm_internal.h
codec2-dev/src/test_bits_ofdm.h

index bbe04efe08591049c1d19af04532a5fc715400b2..3c5fa44bced5bbab79b1ce95f1b91be83e7a2044 100644 (file)
@@ -39,8 +39,8 @@ function ofdm_ldpc_rx(filename, interleave_frames = 1, error_pattern_filename)
 
   % load real samples from file
 
-  Ascale= 2E5*1.1491;
-  frx=fopen(filename,"rb"); rx = 2*fread(frx, Inf, "short")/4E5; fclose(frx);
+  Ascale= 2E5*1.1491/2.0;
+  frx=fopen(filename,"rb"); rx = fread(frx, Inf, "short")/Ascale; fclose(frx);
   Nsam = length(rx); Nframes = floor(Nsam/Nsamperframe);
   prx = 1;
 
@@ -144,6 +144,11 @@ function ofdm_ldpc_rx(filename, interleave_frames = 1, error_pattern_filename)
       rx_np(Nsymbolsperinterleavedframe-Nsymbolsperframe+1:Nsymbolsperinterleavedframe) = arx_np(Nuwtxtsymbolsperframe+1:end);
       rx_amp(1:Nsymbolsperinterleavedframe-Nsymbolsperframe) = rx_amp(Nsymbolsperframe+1:Nsymbolsperinterleavedframe);
       rx_amp(Nsymbolsperinterleavedframe-Nsymbolsperframe+1:Nsymbolsperinterleavedframe) = arx_amp(Nuwtxtsymbolsperframe+1:end);
+      
+      % de-interleave QPSK symbols and symbol amplitudes
+
+      rx_np_de = gp_deinterleave(rx_np);
+      rx_amp_de = gp_deinterleave(rx_amp);
 
       % Interleaver Sync:
       %   Needs to work on any data
@@ -151,14 +156,15 @@ function ofdm_ldpc_rx(filename, interleave_frames = 1, error_pattern_filename)
       %   Attempt a decode on every frame, when it converges we have sync
 
       next_sync_state_interleaver = states.sync_state_interleaver;
+      Nerrs_raw = Nerrs_coded = 0;
 
-      if strcmp(states.sync_state_interleaver,'searching')      
-        arx_np = gp_deinterleave(rx_np);
-        arx_amp = gp_deinterleave(rx_amp);
+      if strcmp(states.sync_state_interleaver,'searching')
         st = 1; en = Ncodedbitsperframe/bps;
-        [rx_codeword parity_checks] = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, arx_np(st:en), min(EsNo,30), arx_amp(st:en));
-        if find(parity_checks == code_param.data_bits_per_frame)
-          % sucessful decode!
+        [rx_codeword parity_checks] = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, rx_np_de(st:en), min(EsNo,30), rx_amp_de(st:en));
+        Nerrs = code_param.data_bits_per_frame - max(parity_checks);
+        %printf("Nerrs: %d\n", Nerrs);
+        if Nerrs < 10
+          % sucessful(ish) decode!
           next_sync_state_interleaver = 'synced';
           states.frame_count_interleaver = interleave_frames;
         end
@@ -166,21 +172,15 @@ function ofdm_ldpc_rx(filename, interleave_frames = 1, error_pattern_filename)
 
       states.sync_state_interleaver = next_sync_state_interleaver;
             
-      Nerrs_raw = Nerrs_coded = 0;
       if strcmp(states.sync_state_interleaver,'synced') && (states.frame_count_interleaver == interleave_frames)
         states.frame_count_interleaver = 0;
-        printf("decode!\n");
+        %printf("decode!\n");
         
-        % de-interleave QPSK symbols and symbol amplitudes
-
-        arx_np = gp_deinterleave(rx_np);
-        arx_amp = gp_deinterleave(rx_amp);
-
         % measure uncoded bit errors over interleaver frame
 
         rx_bits_raw = [];
         for s=1:Nsymbolsperinterleavedframe
-          rx_bits_raw = [rx_bits_raw qpsk_demod(rx_np(s))];
+          rx_bits_raw = [rx_bits_raw qpsk_demod(rx_np_de(s))];
         end
         for ff=1:interleave_frames
           st = (ff-1)*Ncodedbitsperframe+1; en = st+Ncodedbitsperframe-1;
@@ -199,7 +199,7 @@ function ofdm_ldpc_rx(filename, interleave_frames = 1, error_pattern_filename)
         rx_bits = [];
         for ff=1:interleave_frames
           st = (ff-1)*Ncodedbitsperframe/bps+1; en = st + Ncodedbitsperframe/bps - 1;
-          [rx_codeword ldpc_errors] = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, arx_np(st:en), min(EsNo,30), arx_amp(st:en));
+          [rx_codeword ldpc_errors] = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, rx_np_de(st:en), min(EsNo,30), rx_amp_de(st:en));
           rx_bits = [rx_bits rx_codeword(1:code_param.data_bits_per_frame)];
         end
 
index 63ab4b6dfcf9a6f2f1333e8435820cb63f7ba35a..4a7699d6d733ddef15e974ef79b085e2e367984c 100644 (file)
@@ -519,7 +519,9 @@ 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;
-
+  ldpc;
+  gp_interleaver;
+  
   % Set up LDPC code
 
   mod_order = 4; bps = 2; modulation = 'QPSK'; mapping = 'gray';
@@ -574,13 +576,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(payload_data_bits)));
+  fprintf(f,"  %d\n};\n",test_bits_ofdm(end));
 
   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)));
+  fprintf(f,"  %d\n};\n",payload_data_bits(end));
   fclose(f);
 
 endfunction
@@ -651,3 +653,17 @@ function states = sync_state_machine(states, rx_uw)
   states.last_sync_state_interleaver = states.sync_state_interleaver;
   states.sync_state = next_state;
 endfunction
+
+
+% test function, kind of like a CRC for QPSK symbols, to compare two vectors
+
+function acc = test_acc(v)
+  sre = 0; sim = 0;
+  for i=1:length(v)
+    x = v(i);
+    re = round(real(x)); im = round(imag(x));
+    sre += re; sim += im;
+    %printf("%d %10f %10f %10f %10f\n", i, re, im, sre, sim);
+  end
+  acc = sre + j*sim;
+end
index c138e1673377096407f8f1cb9c8f60b5da4754fa..1b92cb18089939b56530395764cfcf3f1f4bde2b 100644 (file)
@@ -4,7 +4,7 @@
   AUTHOR......: David Rowe
   DATE CREATED: April 2018
 
-  Golden Prime Interleaver. My interprestation of "On the Analysis and
+  Golden Prime Interleaver. My interpretation of "On the Analysis and
   Design of Good Algebraic Interleavers", Xie et al,eq (5).
 
   See also octvae/gp_interleaver.m
@@ -29,6 +29,7 @@
 */
 
 #include <assert.h>
+#include <stdio.h>
 #include "gp_interleaver.h"
 
 /*
@@ -41,7 +42,7 @@
 */
 
 int b_table[] = {
-    112,71,
+  112,71,
   224,139,
   448,277,
   672,419,
@@ -79,20 +80,38 @@ int choose_interleaver_b(int Nbits)
 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;
+    j = (b*i) % Nbits;
     interleaved_frame[j] = frame[i];
   }
 }
 
+void gp_deinterleave_comp(COMP frame[], COMP interleaved_frame[], int Nbits) {
+  int b = choose_interleaver_b(Nbits);
+  int i,j;
+  for (i=0; i<Nbits; i++) {
+    j = (b*i) % Nbits;
+    frame[i] =  interleaved_frame[j];
+  }
+}
+
 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;
+    j = (b*i) % Nbits;
     interleaved_frame[j] = frame[i];
   }
 }
 
+void gp_deinterleave_float(float frame[], float interleaved_frame[], int Nbits) {
+  int b = choose_interleaver_b(Nbits);
+  int i,j;
+   
+  for (i=0; i<Nbits; i++) {
+    j = (b*i) % Nbits;
+    frame[i] = interleaved_frame[j];
+  }
+}
+
index fd8a602b40358e72e2b9c0cc0736c5f0ca8e5ef6..b95820aded9734394f043ae3f7e6fcae957dbaf5 100644 (file)
@@ -34,6 +34,8 @@
 #include "comp.h"
 
 void gp_interleave_comp(COMP interleaved_frame[], COMP frame[], int Nbits);
+void gp_deinterleave_comp(COMP frame[], COMP interleaved_frame[], int Nbits);
 void gp_interleave_float(float frame[], float interleaved_frame[], int Nbits);
+void gp_deinterleave_float(float interleaved_frame[], float frame[], int Nbits);
 
 #endif
index 9d50fd39ece76be329193928ae64402615ebbcdc..cf95d3bed23c095ae33616060e90627120704f28 100644 (file)
@@ -119,7 +119,7 @@ int main(int argc, char *argv[]) {
         fprintf(stderr,"\n");
         fprintf(stderr,"InputModemRawFile      48 kHz 16 bit shorts real modem signal from radio\n");
         fprintf(stderr," -m RTTY|binary\n"); 
-        fprintf(stderr,"--mode=RTTY|binary[r]  RTTY or binary Horus protcols\n");
+        fprintf(stderr,"--mode=RTTY|binary     RTTY or binary Horus protcols\n");
         fprintf(stderr," -t[r] --stats=[r]     Print out modem statistics to stderr in JSON.\n");
         fprintf(stderr,"                       r, if provided, sets the number of modem frames\n"
                        "                       between statistic printouts\n");
index 5cda6795777be36e054fd6ce4a09dfacb0fbeed7..62172e0502fa996c3e81c37df1903eb6290c549f 100644 (file)
 #include <stdio.h>
 #include "mpdecode_core.h"
 
+#define QPSK_CONSTELLATION_SIZE 4
+#define QPSK_BITS_PER_SYMBOL    2
+
+/* QPSK constellation for symbol likelihood calculations */
+
+static COMP S_matrix[] = {
+    { 1.0f,  0.0f},
+    { 0.0f,  1.0f},
+    { 0.0f, -1.0f},
+    {-1.0f,  0.0f}
+};
+         
+
 int extract_output(char out_char[], int DecodedBits[], int ParityCheckCount[], 
                     int max_iter, int CodeLength, int NumberParityBits);
 
@@ -767,7 +780,7 @@ void Demod2D(double  symbol_likelihood[],       /* output, M*number_symbols
              float   fading[],                  /* real fading values, number_symbols    */
              int     number_symbols)
 {
-    int     M=4;
+    int     M=QPSK_CONSTELLATION_SIZE;
     int     i,j;
     double  tempsr, tempsi, Er, Ei;
 
@@ -792,7 +805,7 @@ void Somap(double  bit_likelihood[],      /* number_bits, bps*number_symbols */
            double  symbol_likelihood[],   /* M*number_symbols                */
            int     number_symbols)
 {
-    int    M=4, bps = 2;
+    int    M=QPSK_CONSTELLATION_SIZE, bps = QPSK_BITS_PER_SYMBOL;
     int    n,i,j,k,mask;
     double num[bps], den[bps];
     double metric;
@@ -858,3 +871,15 @@ int extract_output(char out_char[], int DecodedBits[], int ParityCheckCount[], i
     return iter;
 }
 
+int symbols_to_llrs(double llr[], COMP rx_qpsk_symbols[], float rx_amps[], float EsNo, int nsyms) {
+    int i;
+    
+    double symbol_likelihood[nsyms*QPSK_CONSTELLATION_SIZE];
+    double bit_likelihood[nsyms*QPSK_BITS_PER_SYMBOL];
+
+    Demod2D(symbol_likelihood, rx_qpsk_symbols, S_matrix, EsNo, rx_amps,  nsyms);
+    Somap(bit_likelihood, symbol_likelihood, nsyms);
+    for(i=0; i<nsyms*QPSK_BITS_PER_SYMBOL; i++) {
+        llr[i] = -bit_likelihood[i];
+    }
+}
index 6fd202db014545186b9a83768fd39447d5c5d626..50517a4085bfdf9122c37649e74cc51a72d0a548 100644 (file)
@@ -35,6 +35,7 @@ void sd_to_llr(double llr[], double sd[], int n);
 
 void Demod2D(double symbol_likelihood[], COMP r[], COMP S_matrix[], float EsNo, float fading[], int number_symbols);
 void Somap(double bit_likelihood[], double symbol_likelihood[], int number_symbols);
+int symbols_to_llrs(double llr[], COMP rx_qpsk_symbols[], float rx_amps[], float EsNo, int nsyms);
 
 struct v_node {
   int degree;
index baf18430276e2e82f01ff500d3a265166b7b87f5..a66351a1bea0789954efa8912981f70196d3694f 100644 (file)
@@ -52,7 +52,7 @@ static void dft(struct OFDM *, complex float *, complex float *);
 static void idft(struct OFDM *, complex float *, complex float *);
 static complex float vector_sum(complex float *, int);
 static complex float qpsk_mod(int *);
-static void qpsk_demod(complex float, int *);
+void qpsk_demod(complex float, int *);
 static void ofdm_txframe(struct OFDM *, complex float [OFDM_SAMPLESPERFRAME], complex float *);
 static int coarse_sync(struct OFDM *, complex float *, int, float *foff_est);
 
@@ -92,7 +92,7 @@ static complex float qpsk_mod(int *bits) {
 
 /* Gray coded QPSK demodulation function */
 
-static void qpsk_demod(complex float symbol, int *bits) {
+void qpsk_demod(complex float symbol, int *bits) {
     complex float rotate = symbol * cexpf(I * (M_PI / 4.0f));
     bits[0] = crealf(rotate) < 0.0f;
     bits[1] = cimagf(rotate) < 0.0f;
@@ -392,6 +392,10 @@ struct OFDM *ofdm_create(const struct OFDM_CONFIG *config) {
     ofdm->sync_start = 0;
     ofdm->sync_end = 0;
     
+    strcpy(ofdm->sync_state_interleaver,"searching");
+    strcpy(ofdm->last_sync_state_interleaver,"searching");
+    ofdm->frame_count_interleaver = 0;
+    
     /* create the OFDM waveform */
 
     complex float temp[OFDM_M];
@@ -954,7 +958,7 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) {
 
 void ofdm_sync_state_machine(struct OFDM *ofdm, int *rx_uw) {
     char next_state[OFDM_STATE_STR];
-    int  i, j, sync_counter_thresh;
+    int  i, j, sync_counter_thresh, uw_thresh;
     
     strcpy(next_state, ofdm->sync_state);    
     ofdm->sync_start = ofdm->sync_end = 0;
@@ -988,23 +992,11 @@ void ofdm_sync_state_machine(struct OFDM *ofdm, int *rx_uw) {
         }
     }
 
-    if ((strcmp(ofdm->sync_state,"synced") == 0) || (strcmp(ofdm->sync_state, "trial_sync") == 0)) {
+    if (!strcmp(ofdm->sync_state,"synced") || !strcmp(ofdm->sync_state, "trial_sync")) {
         
         ofdm->frame_count++;
-      
-        /* during trial sync we don't tolerate errors so much, once we have synced up
-           we are willing to wait out a fade */
-      
-        if (ofdm->frame_count == 3) {
-            strcpy(next_state, "synced");
-        }
-
-        if (strcmp(ofdm->sync_state, "synced") == 0) {
-            sync_counter_thresh = 6;
-        } else {
-            sync_counter_thresh = 3;
-        }
-
+        ofdm->frame_count_interleaver++;
+       
         /* freq offset est may be too far out, and has aliases every 1/Ts, so
            we use a Unique Word to get a really solid indication of sync. */
 
@@ -1012,17 +1004,50 @@ void ofdm_sync_state_machine(struct OFDM *ofdm, int *rx_uw) {
         for (i=0; i<OFDM_NUWBITS; i++) {
             ofdm->uw_errors += rx_uw[i]; 
         }
-        if (ofdm->uw_errors > 2) {
-            ofdm->sync_counter++;
-            if (ofdm->sync_counter == sync_counter_thresh) {
+
+        /* during trial sync we don't tolerate errors so much, we look
+           for 3 consecutive frames with low error rate to confirm
+           sync */
+      
+        if (!strcmp(ofdm->sync_state, "trial_sync")) {
+            if (ofdm->uw_errors > 1) {
+                /* if we exceed thresh stay in trial sync */
+                ofdm->sync_counter++;
+                ofdm->frame_count = 0; 
+            }
+            if (ofdm->sync_counter == 2) {
+                /* if we get two bad frames drop sync and start again */
                 strcpy(next_state, "searching");
+                strcpy(ofdm->sync_state_interleaver, "searching");                
             }
-        } else {
-            ofdm->sync_counter = 0;
+           
+            if (ofdm->frame_count == 3) {
+                /* three good frames, sync is OK! */
+                strcpy(next_state, "synced");
+            }
+        }
+
+        /* once we have synced up we tolerate a higher error rate to wait out fades */
+
+        if (!strcmp(ofdm->sync_state, "synced")) {
+            if (ofdm->uw_errors > 2) {
+                ofdm->sync_counter++;
+            } else {
+                if (ofdm->sync_counter) {
+                    ofdm->sync_counter--;
+                }
+            }
+                
+            if (ofdm->sync_counter == 6) {
+                /* run of consective bad frames ... drop sync */
+                strcpy(next_state, "searching");
+                strcpy(ofdm->sync_state_interleaver, "searching");
+            }           
         }
     }
     
     strcpy(ofdm->last_sync_state, ofdm->sync_state);
+    strcpy(ofdm->last_sync_state_interleaver, ofdm->sync_state_interleaver);
     strcpy(ofdm->sync_state, next_state);
 }
 
index 37b8b4aaa045ea60f45a0fe52ae6d324d7b98505..2afda390340389420596a10720aaa5243dde3eb9 100644 (file)
 #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 DATA_BITSPERFRAME  112    /* number of LDPC payload data 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   */
+/* number of LDPC codeword QPSK symbols/frame */
+
+#define CODED_SYMSPERFRAME (CODED_BITSPERFRAME/OFDM_BPS) 
+
+#include "HRA_112_112.h"           /* generated by ldpc_fsk_lib.m:ldpc_decode()  */
+
+void qpsk_demod(complex float symbol, int *bits);
 
 int opt_exists(char *argv[], int argc, char opt[]) {
     int i;
@@ -65,6 +70,26 @@ int opt_exists(char *argv[], int argc, char opt[]) {
     return 0;
 }
 
+/* CRC type function, used to compare QPSK vectors when debugging */
+
+COMP test_acc(COMP v[], int n) {
+    COMP acc = {0.0,0.0};
+    int i;
+    for(i=0; i<n; i++) {
+        acc.real += round(v[i].real);
+        acc.imag += round(v[i].imag);
+        //fprintf(stderr, "%d %10f %10f %10f %10f\n", i, round(v[i].real), round(v[i].imag), acc.real, acc.imag);
+    }
+    return acc;
+}
+
+void printf_n(COMP v[], int n) {
+    int i;
+    for(i=0; i<n; i++) {
+        fprintf(stderr, "%d %10f %10f\n", i, round(v[i].real), round(v[i].imag));
+    }
+}
+
 int main(int argc, char *argv[])
 {
     FILE          *fin, *fout, *foct;
@@ -77,9 +102,9 @@ int main(int argc, char *argv[])
     float          foff_hz_log[NFRAMES];
     int            timing_est_log[NFRAMES];
 
-    int            i, j, f, oct, logframes, arg, llr_en;
+    int            i, j, f, oct, logframes, arg, llr_en, interleave_frames;
     int            Nerrs, Terrs, Tbits, Terrs2, Tbits2, testframes, frame_count;
-    int            ldpc_en, Nerrs_coded, Tbits_coded, Terrs_coded;
+    int            ldpc_en, Nerrs_coded, Tbits_coded, Terrs_coded, Nerrs_raw;
     
     struct LDPC   ldpc;
     ldpc.max_iter = HRA_112_112_MAX_ITER;
@@ -151,6 +176,15 @@ int main(int argc, char *argv[])
         llr_en = 1;
     }
 
+    interleave_frames = 1;
+    if ((arg = opt_exists(argv, argc, "--interleave"))) {
+        interleave_frames = atoi(argv[arg+1]);
+        fprintf(stderr, "interleave_frames: %d\n",  interleave_frames);
+        /* we can't de-interleave without LDPC for sync, so switch that on */
+        ldpc_en = 1;
+        llr_en = 1;
+    }
+
     ofdm = ofdm_create(OFDM_CONFIG_700D);
     assert(ofdm != NULL);
 
@@ -172,6 +206,11 @@ int main(int argc, char *argv[])
     float EsNo = 10;
     fprintf(stderr,"Warning EsNo: %f hard coded\n", EsNo);
 
+    COMP  codeword_symbols[interleave_frames*CODED_SYMSPERFRAME];
+    float codeword_amps[interleave_frames*CODED_SYMSPERFRAME];
+    COMP  codeword_symbols_de[interleave_frames*CODED_SYMSPERFRAME];
+    float codeword_amps_de[interleave_frames*CODED_SYMSPERFRAME];
+
     nin_frame = ofdm_get_nin(ofdm);
     while(fread(rx_scaled, sizeof(short), nin_frame, fin) == nin_frame) {
 
@@ -190,61 +229,115 @@ int main(int argc, char *argv[])
             ofdm_demod(ofdm, rx_bits, rxbuf_in);
             
             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 */
+                
+                /* first few symbols are used for UW and txt bits, find start of (224,112) LDPC codeword 
+                   and extract QPSK symbols and amplitude estimates */
 
                 assert((OFDM_NUWBITS+OFDM_NTXTBITS+CODED_BITSPERFRAME) == OFDM_BITSPERFRAME);
 
-                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);
+                /* now we need to buffer for de-interleaving -------------------------------------*/
                 
-                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];
-                }
+                /* shift interleaved symbol buffers to make room for new symbols */
                 
-                char   out_char[CODED_BITSPERFRAME];
+                for(i=0, j=CODED_SYMSPERFRAME; j<interleave_frames*CODED_SYMSPERFRAME; i++,j++) {
+                    codeword_symbols[i] = codeword_symbols[j];
+                    codeword_amps[i] = codeword_amps[j];
+                }
+
+                /* newest symbols at end of buffer (uses final i from last loop), note we 
+                   change COMP formats from what modem uses internally */
                 
-                for(i=0; i<CODED_BITSPERFRAME; i++) {
-                    llr[i] = -bit_likelihood[i];
+                for(i=(interleave_frames-1)*CODED_SYMSPERFRAME,j=(OFDM_NUWBITS+OFDM_NTXTBITS)/OFDM_BPS; i<interleave_frames*CODED_SYMSPERFRAME; i++,j++) {
+                    codeword_symbols[i].real = crealf(ofdm->rx_np[j]);
+                    codeword_symbols[i].imag = cimagf(ofdm->rx_np[j]);
+                    codeword_amps[i] = ofdm->rx_amp[j];
                 }
+               
+                /* run de-interleaver */
                 
+                gp_deinterleave_comp (codeword_symbols_de, codeword_symbols, interleave_frames*CODED_SYMSPERFRAME);
+                gp_deinterleave_float(codeword_amps_de   , codeword_amps   , interleave_frames*CODED_SYMSPERFRAME);
+
+                double llr[CODED_BITSPERFRAME];
+
                 if (ldpc_en) {
+                    char out_char[CODED_BITSPERFRAME];
+
+                    /* 
+                       Interleaver Sync:
+                         Needs to work on any data
+                         Use indication of LDPC convergence, may need to patch CML code for that
+                         Attempt a decode on every frame, when it converges we have sync
+                    */
                     
-                    /* run LDPC decoder and output decoded bits */
-                    
-                    iter = run_ldpc_decoder(&ldpc, out_char, llr, &parityCheckCount);
-                    
-                    if (testframes) {
-                        Nerrs_coded = 0;
-                        for(i=0; i<DATA_BITSPERFRAME; i++) {
-                            if (payload_data_bits[i] != out_char[i]) {
-                                Nerrs_coded++;
-                            }
+                    char next_sync_state_interleaver[OFDM_STATE_STR];
+                    strcpy(next_sync_state_interleaver, ofdm->sync_state_interleaver);
+                    if (strcmp(ofdm->sync_state_interleaver,"searching") == 0) {
+                        symbols_to_llrs(llr, codeword_symbols_de, codeword_amps_de, EsNo, CODED_SYMSPERFRAME);               
+                        iter = run_ldpc_decoder(&ldpc, out_char, llr, &parityCheckCount);
+                        Nerrs = DATA_BITSPERFRAME - parityCheckCount;
+                        fprintf(stderr, "iter: %d pcc: %d Nerrs: %d\n", iter, parityCheckCount, Nerrs);
+                        if (Nerrs < 10) {
+                            /* sucessful decode! */
+                            strcpy(next_sync_state_interleaver, "synced");
+                            ofdm->frame_count_interleaver = interleave_frames;
                         }
-                        Terrs_coded += Nerrs_coded;
-                        Tbits_coded += DATA_BITSPERFRAME;
                     }
-                    fwrite(out_char, sizeof(char), CODED_BITSPERFRAME, fout);
+                    strcpy(ofdm->sync_state_interleaver, next_sync_state_interleaver);
+                     
+                    Nerrs_raw = Nerrs_coded = 0;
+                    if (!strcmp(ofdm->sync_state_interleaver,"synced") && (ofdm->frame_count_interleaver == interleave_frames)) {
+                        ofdm->frame_count_interleaver = 0;
+                        // printf("decode!\n");
+        
+                        if (testframes) {
+                            
+                            /* measure uncoded (raw) bit errors over interleaver frame */
+
+                            int rx_bits_raw[CODED_BITSPERFRAME];
+                            for (j=0; j<interleave_frames; j++) {
+                                for(i=0; i<CODED_SYMSPERFRAME; i++) {
+                                    complex float s = codeword_symbols_de[j*CODED_SYMSPERFRAME+i].real + I*codeword_symbols_de[j*CODED_SYMSPERFRAME+i].imag;                                  
+                                    qpsk_demod(s, &rx_bits_raw[OFDM_BPS*i]);
+                                }
+                                Nerrs = 0;
+                                for(i=0; i<CODED_BITSPERFRAME; i++) {
+                                    //fprintf(stderr, "%d %d %d\n", i, test_bits_ofdm[i], rx_bits_raw[i]);
+                                    if (test_bits_ofdm[i] != rx_bits_raw[i]) {
+                                        Nerrs++;
+                                    }
+                                }
+                                Nerrs_raw += Nerrs;
+                            }
+                            Terrs += Nerrs_raw;
+                            Tbits += Nbitsperframe;
+                        }
+
+                        for (j=0; j<interleave_frames; j++) {
+                            symbols_to_llrs(llr, &codeword_symbols_de[j*CODED_SYMSPERFRAME],
+                                                 &codeword_amps_de[j*CODED_SYMSPERFRAME],
+                                                 EsNo, CODED_SYMSPERFRAME);               
+                            iter = run_ldpc_decoder(&ldpc, out_char, llr, &parityCheckCount);
+
+                            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;
+                            }
+                            fwrite(out_char, sizeof(char), CODED_BITSPERFRAME, fout);
+                        }
+                    } /* if interleaver synced ..... */
+                         
                 } else {
-                    /* external LDPC decoder, so output LLRs */
-                    fwrite(llr, sizeof(double), CODED_BITSPERFRAME, fout);
+                    /* lpdc_en == 0,  external LDPC decoder, so output LLRs */
+                    symbols_to_llrs(llr, codeword_symbols_de, codeword_amps_de, EsNo, CODED_SYMSPERFRAME);
+                        fwrite(llr, sizeof(double), CODED_BITSPERFRAME, fout);
                 }
-
             } else {
                 /* simple hard decision output for uncoded testing, all bits in frame dumped inlcuding UW and txt */
                 for(i=0; i<Nbitsperframe; i++) {
@@ -259,9 +352,9 @@ int main(int argc, char *argv[])
                 rx_uw[i] = rx_bits[i];
             }
 
-            /* optional error counting in testframe mode */
+            /* optional error counting on uncoded data in non-LDPC testframe mode */
             
-            if (testframes) {
+            if (testframes && (ldpc_en == 0)) {
                 Nerrs = 0;
                 for(i=0; i<Nbitsperframe; i++) {
                     if (test_bits_ofdm[i] != rx_bits[i]) {
@@ -286,15 +379,14 @@ int main(int argc, char *argv[])
         /* act on any events returned by state machine */
     
         if (ofdm->sync_start) {
-            Terrs = Tbits = Terrs2 = Tbits2 = frame_count = 0;
+            Terrs = Tbits = Terrs2 = Tbits2 = Terrs_coded = Tbits_coded = frame_count = 0;
         }
 
         if (ofdm->verbose) {
-            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, "f: %2d st: %-10s uw_errs: %2d %1d inter_st: %-10s inter_fr: %d Nerrs_raw: %3d Nerrs_coded: %3d foff: %4.1f",
+                    f, ofdm->last_sync_state, ofdm->uw_errors, ofdm->sync_counter,
+                    ofdm->last_sync_state_interleaver, ofdm->frame_count_interleaver,
+                    Nerrs_raw, Nerrs_coded, ofdm->foff_est_hz);
             fprintf(stderr, "\n");    
         }
 
@@ -337,7 +429,9 @@ int main(int argc, char *argv[])
 
     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);
+        if (!ldpc_en) {
+            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);
index aeda31751f66a6c54ef111bce9f61d426c6b6ef4..043d6d115c623c9d9cd26385a22705cad235cc55 100644 (file)
@@ -124,7 +124,7 @@ struct OFDM {
     float rx_amp[OFDM_ROWSPERFRAME * OFDM_NC];
     float aphase_est_pilot_log[OFDM_ROWSPERFRAME * OFDM_NC];
 
-    /* sync state machine */
+    /* modem sync state machine */
 
     char sync_state[OFDM_STATE_STR];
     char last_sync_state[OFDM_STATE_STR];
@@ -133,17 +133,14 @@ struct OFDM {
     int frame_count;
     int sync_start;
     int sync_end;
-};
-
-/* QPSK constellation for symbol likelihood calculations */
 
-static COMP S_matrix[] = {
-    { 1.0f,  0.0f},
-    { 0.0f,  1.0f},
-    { 0.0f, -1.0f},
-    {-1.0f,  0.0f}
+    /* interleaver sync state machine */
+    
+    char sync_state_interleaver[OFDM_STATE_STR];
+    char last_sync_state_interleaver[OFDM_STATE_STR];
+    int  frame_count_interleaver;
 };
-         
+
 #ifdef __cplusplus
 }
 #endif
index 021200979b3828b50d38ce251ffbd47c59b27c9b..32dda83564560b60e70738aca93915309706730d 100644 (file)
@@ -238,7 +238,7 @@ const int test_bits_ofdm[]={
   0,
   0,
   0,
-  0
+  1
 };
 
 const int payload_data_bits[]={