diversity cohpsk ported to C, tcohpsk passes all tests for AWGN channel, but need...
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Fri, 17 Apr 2015 04:50:31 +0000 (04:50 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Fri, 17 Apr 2015 04:50:31 +0000 (04:50 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2120 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/cohpsk.m
codec2-dev/octave/tcohpsk.m
codec2-dev/src/codec2_cohpsk.h
codec2-dev/src/cohpsk.c
codec2-dev/src/cohpsk_internal.h
codec2-dev/unittest/tcohpsk.c

index 7f76e876100db284d0d2b942d6d5fb2491e1205a..c93cca3def66c68f468ee2a4a7d528bc742a3122 100644 (file)
@@ -132,6 +132,8 @@ endfunction
 
 % Symbol rate processing for tx side (modulator) -------------------------------------------------------
 
+% legacy DQPSK mod for comparative testing
+
 function [tx_symb prev_tx_symb] = bits_to_dqpsk_symbols(sim_in, tx_bits, prev_tx_symb)
     Nc         = sim_in.Nc;
     Nsymbrow   = sim_in.Nsymbrow;
@@ -150,6 +152,8 @@ function [tx_symb prev_tx_symb] = bits_to_dqpsk_symbols(sim_in, tx_bits, prev_tx
 endfunction
 
 
+% legacy DQPSK demod for comparative testing
+
 function [rx_symb rx_bits rx_symb_linear prev_rx_symb] = dqpsk_symbols_to_bits(sim_in, rx_symb, prev_rx_symb)
     Nc         = sim_in.Nc;
     Nsymbrow   = sim_in.Nsymbrow;
@@ -205,7 +209,7 @@ function [tx_symb tx_bits] = bits_to_qpsk_symbols(sim_in, tx_bits, code_param)
     
     tx_symb = [pilot(1,:); pilot(2,:); tx_symb;];
 
-    % Optionally copy to other carriers (diversity)
+    % copy to other carriers (diversity)
 
     tmp = tx_symb;
     for d=1:Nd-1
@@ -243,8 +247,8 @@ function [rx_symb rx_bits rx_symb_linear amp_ phi_ EsNo_ cohpsk] = qpsk_symbols_
 
     sampling_points = [1 2 7 8];
     pilot2 = [cohpsk.pilot(1,:); cohpsk.pilot(2,:); cohpsk.pilot(1,:); cohpsk.pilot(2,:);];
-    phi_ = zeros(Nsymbrow, Nc);
-    amp_ = zeros(Nsymbrow, Nc);
+    phi_ = zeros(Nsymbrow, Nc*Nd);
+    amp_ = zeros(Nsymbrow, Nc*Nd);
     
     for c=1:Nc*Nd
       %corr = pilot2(:,c)' * ct_symb_buf(sampling_points,c);      
@@ -254,7 +258,10 @@ function [rx_symb rx_bits rx_symb_linear amp_ phi_ EsNo_ cohpsk] = qpsk_symbols_
       [m b] = linreg(sampling_points, y, length(sampling_points));
       yfit = m*[3 4 5 6] + b;
       phi_(:, c) = angle(yfit);
-      
+      %for r=1:Nsymbrow
+      %  printf("  %f", phi_(r,c));
+      %end
+      %printf("\n");
       mag  = sum(abs(ct_symb_buf(sampling_points,c)));
       amp_(:, c) = mag/length(sampling_points);
     end
@@ -535,7 +542,7 @@ function [next_sync cohpsk] = coarse_freq_offset_est(cohpsk, fdmdv, ch_fdm_frame
   Ndft    = cohpsk.Ndft;
 
   if sync == 0
-    f_start = Fcentre - ((Nc/2)+2)*Fsep; 
+    f_start = Fcentre - ((Nc/2)+2)*Fsep;
     f_stop = Fcentre + ((Nc/2)+2)*Fsep;
     ll = length(ch_fdm_frame);
     h = 0.5 - 0.5*cos(2*pi*(0:ll-1)/(ll-1));
@@ -549,7 +556,7 @@ function [next_sync cohpsk] = coarse_freq_offset_est(cohpsk, fdmdv, ch_fdm_frame
     x = bin_start-1:bin_stop-1;
     bin_est = x*T(bin_start:bin_stop)'/sum(T(bin_start:bin_stop));
     cohpsk.f_est = floor(bin_est/sc+0.5);
-    printf("coarse freq est: %f\n", cohpsk.f_est);
+    printf("  coarse freq est: %f\n", cohpsk.f_est);
     next_sync = 1;
     
   end
@@ -565,6 +572,7 @@ function [next_sync cohpsk] = frame_sync_fine_freq_est(cohpsk, ch_symb, sync, ne
   Rs            = cohpsk.Rs;
   Nsymbrowpilot = cohpsk.Nsymbrowpilot;
   Nc            = cohpsk.Nc;
+  Nd            = cohpsk.Nd;
 
   % update memory in symbol buffer
 
@@ -592,10 +600,10 @@ function [next_sync cohpsk] = frame_sync_fine_freq_est(cohpsk, ch_symb, sync, ne
       f_fine_rect = exp(-j*f_fine*2*pi*sampling_points/Rs)';
       for t=0:cohpsk.Nsymbrowpilot-1
         corr = 0; mag = 0;
-        for c=1:Nc
+        for c=1:Nc*Nd
           f_corr_vec = f_fine_rect .* ct_symb_buf(t+sampling_points,c);
           for p=1:length(sampling_points)
-            corr += pilot2(p,c) * f_corr_vec(p);
+            corr += pilot2(p,c-Nc*floor((c-1)/Nc)) * f_corr_vec(p);
             mag  += abs(f_corr_vec(p));
           end
         end
@@ -612,7 +620,7 @@ function [next_sync cohpsk] = frame_sync_fine_freq_est(cohpsk, ch_symb, sync, ne
 
     printf("  fine freq f: %f max_corr: %f max_mag: %f ct: %d\n", cohpsk.f_fine_est, abs(max_corr), max_mag, cohpsk.ct);
     if max_corr/max_mag > 0.9
-      printf("in sync!\n");
+      printf("  in sync!\n");
       next_sync = 4;
     else
       next_sync = 0;
index 3b381abe98ac1086351697b5f49ec90218185c8b..72aff531d582e3f81c542f3e5c2b3bb8f932ad42 100644 (file)
@@ -44,7 +44,7 @@ afdmdv.Nfilter =  Nfilter;
 afdmdv.gt_alpha5_root = gt_alpha5_root;
 afdmdv.Fsep = 75;
 afdmdv.phase_tx = ones(afdmdv.Nc+1,1);
-freq_hz = Fsep*( -afdmdv.Nc/2 - 0.5 + (1:afdmdv.Nc+1) );
+freq_hz = afdmdv.Fsep*( -Nc*Nd/2 - 0.5 + (1:Nc*Nd) );
 afdmdv.freq_pol = 2*pi*freq_hz/Fs;
 afdmdv.freq = exp(j*afdmdv.freq_pol);
 afdmdv.Fcentre = 1500;
@@ -234,7 +234,6 @@ for i=1:frames
 
 end
 
-if 0
 stem_sig_and_error(1, 111, tx_bits_log_c(1:n), tx_bits_log(1:n) - tx_bits_log_c(1:n), 'tx bits', [1 n -1.5 1.5])
 stem_sig_and_error(2, 211, real(tx_symb_log_c(1:n)), real(tx_symb_log(1:n) - tx_symb_log_c(1:n)), 'tx symb re', [1 n -1.5 1.5])
 stem_sig_and_error(2, 212, imag(tx_symb_log_c(1:n)), imag(tx_symb_log(1:n) - tx_symb_log_c(1:n)), 'tx symb im', [1 n -1.5 1.5])
@@ -251,7 +250,6 @@ stem_sig_and_error(6, 211, real(ch_symb_log_c), real(ch_symb_log - ch_symb_log_c
 stem_sig_and_error(6, 212, imag(ch_symb_log_c), imag(ch_symb_log - ch_symb_log_c), 'ch symb im', [1 n -1.5 1.5])
 stem_sig_and_error(7, 211, real(ct_symb_ff_log_c), real(ct_symb_ff_log - ct_symb_ff_log_c), 'ct symb ff re', [1 n -1.5 1.5])
 stem_sig_and_error(7, 212, imag(ct_symb_ff_log_c), imag(ct_symb_ff_log - ct_symb_ff_log_c), 'ct symb ff im', [1 n -1.5 1.5])
-
 stem_sig_and_error(8, 211, rx_amp_log_c, rx_amp_log - rx_amp_log_c, 'Amp Est', [1 n -1.5 1.5])
 stem_sig_and_error(8, 212, rx_phi_log_c, rx_phi_log - rx_phi_log_c, 'Phase Est', [1 n -4 4])
 stem_sig_and_error(9, 211, real(rx_symb_log_c), real(rx_symb_log - rx_symb_log_c), 'rx symb re', [1 n -1.5 1.5])
@@ -277,7 +275,6 @@ Nerrs_c = sum(xor(tx_bits_prev_log, rx_bits_log_c));
 Tbits_c = length(tx_bits_prev_log);
 ber_c = Nerrs_c/Tbits_c;
 ber = Nerrs/Tbits;
-end
 
 printf("EsNodB: %4.1f ber_c: %3.2f Nerrs_c: %d Tbits_c: %d\n", EsNodB, ber_c, Nerrs_c, Tbits_c);
 
index 77b5c220e6a0ae4b80f51021fb34604d0e3310ab..0c881d3039a9456ef379d7bcfeedcc09e88f253b 100644 (file)
@@ -33,6 +33,7 @@
 #define COHPSK_SAMPLES_PER_FRAME 960
 #define COHPSK_RS                 50
 #define COHPSK_FS               8000
+#define COHPSK_ND                  2              /* diversity factor   */
 
 #include "comp.h"
 #include "codec2_fdmdv.h"
@@ -41,10 +42,10 @@ struct COHPSK;
 
 struct COHPSK *cohpsk_create(void);
 void cohpsk_destroy(struct COHPSK *coh);
-void bits_to_qpsk_symbols(COMP tx_symb[][COHPSK_NC], int tx_bits[], int nbits);
-void qpsk_symbols_to_bits(struct COHPSK *coh, int rx_bits[], COMP ct_symb_buf[][COHPSK_NC]);
+void bits_to_qpsk_symbols(COMP tx_symb[][COHPSK_NC*COHPSK_ND], int tx_bits[], int nbits);
+void qpsk_symbols_to_bits(struct COHPSK *coh, int rx_bits[], COMP ct_symb_buf[][COHPSK_NC*COHPSK_ND]);
 void coarse_freq_offset_est(struct COHPSK *coh, struct FDMDV *fdmdv, COMP ch_fdm_frame[], int sync, int *next_sync);
-void frame_sync_fine_freq_est(struct COHPSK *coh, COMP ch_symb[][COHPSK_NC], int sync, int *next_sync);
+void frame_sync_fine_freq_est(struct COHPSK *coh, COMP ch_symb[][COHPSK_NC*COHPSK_ND], int sync, int *next_sync);
 void fine_freq_correct(struct COHPSK *coh, int sync, int next_sync);
 int sync_state_machine(struct COHPSK *coh, int sync, int next_sync);
 
index 9c8ee662f31058bb393dfdb37990a7b22ffc0f23..deca9c49cc8bc06043ea277fda082542b2ea016f 100644 (file)
@@ -96,9 +96,11 @@ struct COHPSK *cohpsk_create(void)
     int            r,c,p,i;
     float          freq_hz;
 
+    assert(COHPSK_NC == PILOTS_NC);
     assert(COHPSK_SAMPLES_PER_FRAME == M*NSYMROWPILOT);
     assert(COHPSK_RS == RS);
     assert(COHPSK_FS == FS);
+    assert(COHPSK_ND == ND);
 
     coh = (struct COHPSK*)malloc(sizeof(struct COHPSK));
     if (coh == NULL)
@@ -108,7 +110,7 @@ struct COHPSK *cohpsk_create(void)
 
     for(r=0; r<2*NPILOTSFRAME; ) {
         for(p=0; p<NPILOTSFRAME; r++, p++) {
-            for(c=0; c<PILOTS_NC; c++) {
+            for(c=0; c<COHPSK_NC; c++) {
                 coh->pilot2[r][c] = pilots_coh[p][c];
             }
         }
@@ -122,7 +124,7 @@ struct COHPSK *cohpsk_create(void)
     /* Clear symbol buffer memory */
 
     for (r=0; r<NCT_SYMB_BUF; r++) {
-        for(c=0; c<PILOTS_NC; c++) {
+        for(c=0; c<COHPSK_NC*ND; c++) {
             coh->ct_symb_buf[r][c].real = 0.0;
             coh->ct_symb_buf[r][c].imag = 0.0;
         }
@@ -133,12 +135,12 @@ struct COHPSK *cohpsk_create(void)
 
     /* set up fdmdv states so we can use those modem functions */
 
-    fdmdv = fdmdv_create(PILOTS_NC - 1);
-    for(c=0; c<PILOTS_NC; c++) {
+    fdmdv = fdmdv_create(COHPSK_NC*ND - 1);
+    for(c=0; c<COHPSK_NC*ND; c++) {
        fdmdv->phase_tx[c].real = 1.0;
        fdmdv->phase_tx[c].imag = 0.0;
 
-        freq_hz = fdmdv->fsep*( -PILOTS_NC/2 - 0.5 + c + 1.0 );
+        freq_hz = fdmdv->fsep*( -(COHPSK_NC*ND)/2 - 0.5 + c + 1.0 );
        fdmdv->freq[c].real = cosf(2.0*M_PI*freq_hz/FS);
        fdmdv->freq[c].imag = sinf(2.0*M_PI*freq_hz/FS);
        fdmdv->freq_pol[c]  = 2.0*M_PI*freq_hz/FS;
@@ -184,42 +186,57 @@ void cohpsk_destroy(struct COHPSK *coh)
 
 \*---------------------------------------------------------------------------*/
 
-void bits_to_qpsk_symbols(COMP tx_symb[][PILOTS_NC], int tx_bits[], int nbits)
+void bits_to_qpsk_symbols(COMP tx_symb[][COHPSK_NC*ND], int tx_bits[], int nbits)
 {
-    int   i, r, c, p_r, data_r;
+    int   i, r, c, p_r, data_r, d;
     short bits;
 
-    assert(COHPSK_NC == PILOTS_NC);
-    assert((NSYMROW*PILOTS_NC)*2 == nbits);
+    /* check number of bits supplied matchs number of QPSK symbols in the frame */
+
+    assert((NSYMROW*COHPSK_NC)*2 == nbits);
  
     /*
       Insert two rows of Nc pilots at beginning of data frame.
 
-      Organise QPSK symbols into a NSYMBROWS rows by PILOTS_NC cols matrix,
+      Organise QPSK symbols into a NSYMBROWS rows by PILOTS_NC*ND cols matrix,
       each column is a carrier, time flows down the cols......
 
       Note: the "& 0x1" prevents and non binary tx_bits[] screwing up
       our lives.  Call me defensive.
+
+      sqrtf(ND) term ensures the same energy/symbol for different
+      diversity factors.
     */
 
     r = 0;
     for(p_r=0; p_r<2; p_r++) {
-        for(c=0; c<PILOTS_NC; c++) {
-            tx_symb[r][c].real = pilots_coh[p_r][c];
+        for(c=0; c<COHPSK_NC; c++) {
+            tx_symb[r][c].real = pilots_coh[p_r][c]/sqrtf(ND);
             tx_symb[r][c].imag = 0.0;
         }
         r++;
     }
     for(data_r=0; data_r<NSYMROW; data_r++, r++) {
-        for(c=0; c<PILOTS_NC; c++) {
+        for(c=0; c<COHPSK_NC; c++) {
             i = c*NSYMROW + data_r;
             bits = (tx_bits[2*i]&0x1)<<1 | (tx_bits[2*i+1]&0x1);          
-            tx_symb[r][c] = qpsk_mod[bits];
+            tx_symb[r][c] = fcmult(1.0/sqrtf(ND),qpsk_mod[bits]);
         }
     }
     
     assert(p_r == NPILOTSFRAME);
     assert(r == NSYMROWPILOT);
+
+    /* copy to other carriers (diversity) */
+
+    for(d=1; d<ND; d++) {
+        for(r=0; r<NSYMROWPILOT; r++) {
+            for(c=0; c<COHPSK_NC; c++) {
+                tx_symb[r][c+COHPSK_NC*d] = tx_symb[r][c];
+            }
+        }
+    }    
+
 }
 
 
@@ -232,30 +249,28 @@ void bits_to_qpsk_symbols(COMP tx_symb[][PILOTS_NC], int tx_bits[], int nbits)
   Rate Rs demodulator. Extract pilot symbols and estimate amplitude and phase
   of each carrier.  Correct phase of data symbols and convert to bits.
 
-  Further improvement.  In channels with rapidly changing phase by
-  moderate Eb/No, we could perhaps do better by interpolating the
-  phase across symbols rather than using the same phi_ for all symbols.
+  Further improvement.  In channels with slowly changing phase we
+  could optionally use pilots from several past and future symbols.
 
 \*---------------------------------------------------------------------------*/
 
-void qpsk_symbols_to_bits(struct COHPSK *coh, int rx_bits[], COMP ct_symb_buf[][COHPSK_NC])
+void qpsk_symbols_to_bits(struct COHPSK *coh, int rx_bits[], COMP ct_symb_buf[][COHPSK_NC*ND])
 {
-    int   p, r, c, i;
+    int   p, r, c, i, pc, d;
     float x[NPILOTSFRAME+2], x1;
     COMP  y[NPILOTSFRAME+2], yfit;
     COMP  m, b;
-    COMP  corr, rot, pi_on_4, phi_rect;
+    COMP  corr, rot, pi_on_4, phi_rect, div_symb;
     float mag, phi_, amp_;
 
     pi_on_4.real = cosf(M_PI/4); pi_on_4.imag = sinf(M_PI/4);
    
-    /* Average pilots to get phase and amplitude estimates we assume
-       there are two pilots at the start of each frame and two at the
-       end */
-
-    for(c=0; c<PILOTS_NC; c++) {
+    for(c=0; c<COHPSK_NC*ND; c++) {
 //#define AVERAGE
 #ifdef AVERAGE
+        /* Average pilots to get phase and amplitude estimates using
+           two pilots at the start of each frame and two at the end */
+
         corr.real = 0.0; corr.imag = 0.0; mag = 0.0;
         for(p=0; p<NPILOTSFRAME+2; p++) {
             corr = cadd(corr, fcmult(coh->pilot2[p][c], ct_symb_buf[sampling_points[p]][c]));
@@ -270,19 +285,24 @@ void qpsk_symbols_to_bits(struct COHPSK *coh, int rx_bits[], COMP ct_symb_buf[][
         }
 #else
 
-        /* set up lin reg model and interpolate phase */
+        /* Set up lin reg model and interpolate phase.  Works better than average for channels with
+           quickly changing phase, like HF. */
 
         for(p=0; p<NPILOTSFRAME+2; p++) {
             x[p] = sampling_points[p];
-            y[p] = fcmult(coh->pilot2[p][c], ct_symb_buf[sampling_points[p]][c]);
+            pc = c % COHPSK_NC;
+            y[p] = fcmult(coh->pilot2[p][pc], ct_symb_buf[sampling_points[p]][c]);
+            //printf("%f %f\n", y[p].real, y[p].imag);
         }
+        //printf("\n");
         linreg(&m, &b, x, y, NPILOTSFRAME+2);
         for(r=0; r<NSYMROW; r++) {
             x1 = (float)(r+NPILOTSFRAME);
             yfit = cadd(fcmult(x1,m),b);
             coh->phi_[r][c] = atan2(yfit.imag, yfit.real);
+            //printf("  %f", coh->phi_[r][c]);
         }
-
+        //printf("\n");
         /* amplitude estimation */
 
         mag = 0.0;
@@ -295,23 +315,33 @@ void qpsk_symbols_to_bits(struct COHPSK *coh, int rx_bits[], COMP ct_symb_buf[][
         }
 #endif
     }
+    //exit(0);
+    /* now correct phase of data symbols */
 
-    /* now correct phase of data symbols and make decn on bits */
-
-    for(c=0; c<PILOTS_NC; c++) {
+    for(c=0; c<COHPSK_NC*ND; c++) {
         //rot.real = 1.0; rot.imag = 0.0;
         for (r=0; r<NSYMROW; r++) {
             phi_rect.real = cosf(coh->phi_[r][c]); phi_rect.imag = -sinf(coh->phi_[r][c]);
-            i = c*NSYMROW + r;
             coh->rx_symb[r][c] = cmult(ct_symb_buf[NPILOTSFRAME + r][c], phi_rect);
             //printf("%d %d %f %f\n", r,c, coh->rx_symb[r][c].real, coh->rx_symb[r][c].imag);
             //printf("phi_ %d %d %f %f\n", r,c, ct_symb_buf[NPILOTSFRAME + r][c].real, ct_symb_buf[NPILOTSFRAME + r][c].imag);
-            rot = cmult(coh->rx_symb[r][c], pi_on_4);
+        }
+    }
+    
+    /* and finally optional diversity combination and make decn on bits */
+
+    for(c=0; c<COHPSK_NC; c++) {
+        for(r=0; r<NSYMROW; r++) {
+            div_symb = coh->rx_symb[r][c];
+            for (d=1; d<ND; d++) {
+                div_symb = cadd(div_symb, coh->rx_symb[r][c + COHPSK_NC*d]);
+            }
+            rot = cmult(div_symb, pi_on_4);
+            i = c*NSYMROW + r;
             rx_bits[2*i+1] = rot.real < 0;
             rx_bits[2*i]   = rot.imag < 0;
         }
     }
-    
 }
 
 
@@ -335,8 +365,8 @@ void coarse_freq_offset_est(struct COHPSK *coh, struct FDMDV *fdmdv, COMP ch_fdm
     int   bin_start, bin_stop, i;
 
     if (sync == 0) {
-        f_start = FDMDV_FCENTRE - (((float)(PILOTS_NC-1)/2)+2)*FSEP; 
-        f_stop = FDMDV_FCENTRE + (((float)(PILOTS_NC-1)/2)+2)*FSEP;
+        f_start = FDMDV_FCENTRE - (((float)(COHPSK_NC*ND-1)/2)+2)*FSEP; 
+        f_stop = FDMDV_FCENTRE + (((float)(COHPSK_NC*ND-1)/2)+2)*FSEP;
         sc = (float)COARSE_FEST_NDFT/FS;
         bin_start = floorf(f_start*sc+0.5);
         bin_stop = floorf(f_stop*sc+0.5);
@@ -377,15 +407,16 @@ void corr_with_pilots(COMP *corr_out, float *mag_out, struct COHPSK *coh, int t,
 {
     COMP  corr, f_fine_rect, f_corr;
     float mag;
-    int   c, p;
+    int   c, p, pc;
     
     corr.real = 0.0; corr.imag = 0.0; mag = 0.0;
-    for (c=0; c<PILOTS_NC; c++) {
+    for (c=0; c<COHPSK_NC*ND; c++) {
         for (p=0; p<NPILOTSFRAME+2; p++) {
             f_fine_rect.real = cosf(f_fine*2.0*M_PI*(sampling_points[p]+1.0)/RS);
             f_fine_rect.imag = sinf(f_fine*2.0*M_PI*(sampling_points[p]+1.0)/RS);
             f_corr = cmult(f_fine_rect, coh->ct_symb_buf[t+sampling_points[p]][c]);
-            corr = cadd(corr, fcmult(coh->pilot2[p][c], f_corr));
+            pc = c % COHPSK_NC;
+            corr = cadd(corr, fcmult(coh->pilot2[p][pc], f_corr));
             mag  += cabsolute(f_corr);
         }
     }
@@ -397,7 +428,7 @@ void corr_with_pilots(COMP *corr_out, float *mag_out, struct COHPSK *coh, int t,
 
 /*---------------------------------------------------------------------------*\
                                                        
-  FUNCTION....: frame_sync_fine_timing_est()        
+  FUNCTION....: frame_sync_fine_freq_est()          
   AUTHOR......: David Rowe                           
   DATE CREATED: April 2015
 
@@ -410,7 +441,7 @@ void corr_with_pilots(COMP *corr_out, float *mag_out, struct COHPSK *coh, int t,
 
 \*---------------------------------------------------------------------------*/
 
-void frame_sync_fine_freq_est(struct COHPSK *coh, COMP ch_symb[][PILOTS_NC], int sync, int *next_sync)
+void frame_sync_fine_freq_est(struct COHPSK *coh, COMP ch_symb[][COHPSK_NC*ND], int sync, int *next_sync)
 {
     int   r,c,i,t;
     float f_fine, mag, max_corr, max_mag;
@@ -419,13 +450,13 @@ void frame_sync_fine_freq_est(struct COHPSK *coh, COMP ch_symb[][PILOTS_NC], int
     /* update memory in symbol buffer */
 
     for (r=0; r<NCT_SYMB_BUF-NSYMROWPILOT; r++) {
-        for(c=0; c<PILOTS_NC; c++) {
+        for(c=0; c<COHPSK_NC*ND; c++) {
             coh->ct_symb_buf[r][c] = coh->ct_symb_buf[r+NSYMROWPILOT][c];
         }
     }
 
     for (r=NCT_SYMB_BUF-NSYMROWPILOT,i=0; r<NCT_SYMB_BUF; r++,i++) {
-       for(c=0; c<PILOTS_NC; c++) {
+       for(c=0; c<COHPSK_NC*ND; c++) {
            coh->ct_symb_buf[r][c] = ch_symb[i][c];
            //printf("%d %d %f %f\n", i,c,ch_symb[i][c].real, ch_symb[i][c].imag);
        }
@@ -500,7 +531,7 @@ void fine_freq_correct(struct COHPSK *coh, int sync, int next_sync) {
 
           for(r=0; r<NSYMROWPILOT+2; r++) {
               coh->ff_phase = cmult(coh->ff_phase, cconj(coh->ff_rect));
-              for(c=0; c<PILOTS_NC; c++) {
+              for(c=0; c<COHPSK_NC*ND; c++) {
                   coh->ct_symb_ff_buf[r][c] = coh->ct_symb_buf[coh->ct+r][c];
                   coh->ct_symb_ff_buf[r][c] = cmult(coh->ct_symb_ff_buf[r][c], coh->ff_phase);
               }
@@ -511,14 +542,14 @@ void fine_freq_correct(struct COHPSK *coh, int sync, int next_sync) {
           /* second and subsequent frames, just fine freq correct the latest Nsymbrowpilot */
 
           for(r=0; r<2; r++) {
-              for(c=0; c<PILOTS_NC; c++) {
+              for(c=0; c<COHPSK_NC*ND; c++) {
                   coh->ct_symb_ff_buf[r][c] = coh->ct_symb_ff_buf[r+NSYMROWPILOT][c];
               }
           }
           
           for(; r<NSYMROWPILOT+2; r++) {
               coh->ff_phase = cmult(coh->ff_phase, cconj(coh->ff_rect));
-              for(c=0; c<PILOTS_NC; c++) {
+              for(c=0; c<COHPSK_NC*ND; c++) {
                   coh->ct_symb_ff_buf[r][c] = coh->ct_symb_buf[coh->ct+r][c];
                   //printf("%d %d %f %f\n", r,c,coh->ct_symb_ff_buf[r][c].real, coh->ct_symb_ff_buf[r][c].imag);
                   coh->ct_symb_ff_buf[r][c] = cmult(coh->ct_symb_ff_buf[r][c], coh->ff_phase);
@@ -547,8 +578,9 @@ int sync_state_machine(struct COHPSK *coh, int sync, int next_sync)
         /* check that sync is still good, fall out of sync on 3 consecutive bad frames */
 
         corr_with_pilots(&corr, &mag, coh, coh->ct, coh->f_fine_est);
+        // printf("%f\n", cabsolute(corr)/mag);
 
-        if (cabsolute(corr)/mag < 0.9
+        if (cabsolute(corr)/mag < 0.5
             coh->sync_timer++;
         else
             coh->sync_timer = 0;            
@@ -583,14 +615,14 @@ int sync_state_machine(struct COHPSK *coh, int sync, int next_sync)
 void cohpsk_mod(struct COHPSK *coh, COMP tx_fdm[], int tx_bits[])
 {
     struct FDMDV *fdmdv = coh->fdmdv;
-    COMP tx_symb[NSYMROWPILOT][PILOTS_NC];
-    COMP tx_onesym[PILOTS_NC];
+    COMP tx_symb[NSYMROWPILOT][COHPSK_NC*ND];
+    COMP tx_onesym[COHPSK_NC*ND];
     int  r,c;
 
     bits_to_qpsk_symbols(tx_symb, tx_bits, COHPSK_BITS_PER_FRAME);
 
     for(r=0; r<NSYMROWPILOT; r++) {
-        for(c=0; c<PILOTS_NC; c++) 
+        for(c=0; c<COHPSK_NC*ND; c++) 
             tx_onesym[c] = tx_symb[r][c];         
         tx_filter_and_upconvert(&tx_fdm[r*M], fdmdv->Nc , tx_onesym, fdmdv->tx_filter_memory, 
                                 fdmdv->phase_tx, fdmdv->freq, &fdmdv->fbb_phase_tx, fdmdv->fbb_rect);
@@ -623,11 +655,11 @@ void cohpsk_demod(struct COHPSK *coh, int rx_bits[], int *reliable_sync_bit, COM
 {
     struct FDMDV *fdmdv = coh->fdmdv;
     COMP  rx_fdm_frame_bb[M*NSYMROWPILOT];
-    COMP  rx_baseband[PILOTS_NC][M+M/P];
-    COMP  rx_filt[PILOTS_NC][P+1];
+    COMP  rx_baseband[COHPSK_NC*ND][M+M/P];
+    COMP  rx_filt[COHPSK_NC*ND][P+1];
     float env[NT*P], __attribute__((unused)) rx_timing;
-    COMP  ch_symb[NSYMROWPILOT][PILOTS_NC];
-    COMP  rx_onesym[PILOTS_NC];
+    COMP  ch_symb[NSYMROWPILOT][COHPSK_NC*ND];
+    COMP  rx_onesym[COHPSK_NC*ND];
     int   sync, next_sync, nin, r, c;
 
     next_sync = sync = coh->sync;
@@ -643,7 +675,7 @@ void cohpsk_demod(struct COHPSK *coh, int rx_bits[], int *reliable_sync_bit, COM
         rx_filter(rx_filt, fdmdv->Nc, rx_baseband, coh->rx_filter_memory, nin);
         rx_timing = rx_est_timing(rx_onesym, fdmdv->Nc, rx_filt, fdmdv->rx_filter_mem_timing, env, nin);
           
-        for(c=0; c<PILOTS_NC; c++) {
+        for(c=0; c<COHPSK_NC*ND; c++) {
             ch_symb[r][c] = rx_onesym[c];
         }
     }
index fc72326b3fbb66a6798c393aeab72a0456d9e6f7..1fee91249458ff089ec380565138b47f32db8a1a 100644 (file)
 
 #define COARSE_FEST_NDFT 1024
 #define NCT_SYMB_BUF     (2*NSYMROWPILOT+2)
+#define ND               2                           /* diversity factor ND 1 is no diveristy, ND we have orginal plus 
+                                                        one copy */
 
 #include "fdmdv_internal.h"
 #include "kiss_fft.h"
 
 struct COHPSK {
-    float        pilot2[2*NPILOTSFRAME][PILOTS_NC];    
-    float        phi_[NSYMROW][PILOTS_NC];           /* phase estimates for this frame of rx data symbols     */
-    float        amp_[NSYMROW][PILOTS_NC];           /* amplitude estimates for this frame of rx data symbols */
-    COMP         rx_symb[NSYMROW][PILOTS_NC];        /* demodulated symbols                                   */
+    float        pilot2[2*NPILOTSFRAME][COHPSK_NC];    
+    float        phi_[NSYMROW][COHPSK_NC*ND];           /* phase estimates for this frame of rx data symbols     */
+    float        amp_[NSYMROW][COHPSK_NC*ND];           /* amplitude estimates for this frame of rx data symbols */
+    COMP         rx_symb[NSYMROW][COHPSK_NC*ND];        /* demodulated symbols                                   */
     kiss_fft_cfg fft_coarse_fest;
     float        f_est;
-    COMP         rx_filter_memory[PILOTS_NC][NFILTER];
-    COMP         ct_symb_buf[NCT_SYMB_BUF][PILOTS_NC];
+    COMP         rx_filter_memory[COHPSK_NC*ND][NFILTER];
+    COMP         ct_symb_buf[NCT_SYMB_BUF][COHPSK_NC*ND];
     int          ct;                                 /* coarse timing offset in symbols                       */
     float        f_fine_est;
     COMP         ff_rect;
     COMP         ff_phase;
-    COMP         ct_symb_ff_buf[NSYMROWPILOT+2][PILOTS_NC];
+    COMP         ct_symb_ff_buf[NSYMROWPILOT+2][COHPSK_NC*ND];
     int          sync;
     int          sync_timer;
 
index e1e4ceef8e8abc03ba1d0ef727cfb3067aff8fc6..d48730b7a3f90a5d44a3fe421a284b9351002e56 100644 (file)
@@ -55,23 +55,23 @@ int main(int argc, char *argv[])
 {
     struct COHPSK *coh;
     int            tx_bits[COHPSK_BITS_PER_FRAME];
-    COMP           tx_symb[NSYMROWPILOT][PILOTS_NC];
+    COMP           tx_symb[NSYMROWPILOT][COHPSK_NC*ND];
     COMP           tx_fdm_frame[M*NSYMROWPILOT];
     COMP           ch_fdm_frame[M*NSYMROWPILOT];
     COMP           rx_fdm_frame_bb[M*NSYMROWPILOT];
-    COMP           ch_symb[NSYMROWPILOT][PILOTS_NC];
+    COMP           ch_symb[NSYMROWPILOT][COHPSK_NC*ND];
     int            rx_bits[COHPSK_BITS_PER_FRAME];
     
     int            tx_bits_log[COHPSK_BITS_PER_FRAME*FRAMES];
-    COMP           tx_symb_log[NSYMROWPILOT*FRAMES][PILOTS_NC];
+    COMP           tx_symb_log[NSYMROWPILOT*FRAMES][COHPSK_NC*ND];
     COMP           tx_fdm_frame_log[M*NSYMROWPILOT*FRAMES];
     COMP           ch_fdm_frame_log[M*NSYMROWPILOT*FRAMES];
     COMP           rx_fdm_frame_bb_log[M*NSYMROWPILOT*FRAMES];
-    COMP           ch_symb_log[NSYMROWPILOT*FRAMES][PILOTS_NC];
-    COMP           ct_symb_ff_log[NSYMROWPILOT*FRAMES][PILOTS_NC];
-    float          rx_amp_log[NSYMROW*FRAMES][PILOTS_NC];
-    float          rx_phi_log[NSYMROW*FRAMES][PILOTS_NC];
-    COMP           rx_symb_log[NSYMROW*FRAMES][PILOTS_NC];
+    COMP           ch_symb_log[NSYMROWPILOT*FRAMES][COHPSK_NC*ND];
+    COMP           ct_symb_ff_log[NSYMROWPILOT*FRAMES][COHPSK_NC*ND];
+    float          rx_amp_log[NSYMROW*FRAMES][COHPSK_NC*ND];
+    float          rx_phi_log[NSYMROW*FRAMES][COHPSK_NC*ND];
+    COMP           rx_symb_log[NSYMROW*FRAMES][COHPSK_NC*ND];
     int            rx_bits_log[COHPSK_BITS_PER_FRAME*FRAMES];
                                           
     FILE          *fout;
@@ -80,17 +80,17 @@ int main(int argc, char *argv[])
     COMP           phase_ch;
 
     struct FDMDV  *fdmdv;
-    COMP           rx_baseband[PILOTS_NC][M+M/P];
+    COMP           rx_baseband[COHPSK_NC*ND][M+M/P];
     int            nin;
-    COMP           rx_filt[PILOTS_NC][P+1];
-    COMP           rx_filt_log[PILOTS_NC][(P+1)*NSYMROWPILOT*FRAMES];
+    COMP           rx_filt[COHPSK_NC*ND][P+1];
+    COMP           rx_filt_log[COHPSK_NC*ND][(P+1)*NSYMROWPILOT*FRAMES];
     int            rx_filt_log_col_index = 0;
     float          env[NT*P];
     float           __attribute__((unused)) rx_timing;
-    COMP           tx_onesym[PILOTS_NC];
-    COMP           rx_onesym[PILOTS_NC];
+    COMP           tx_onesym[COHPSK_NC*ND];
+    COMP           rx_onesym[COHPSK_NC*ND];
     int            rx_baseband_log_col_index = 0;
-    COMP           rx_baseband_log[PILOTS_NC][(M+M/P)*NSYMROWPILOT*FRAMES];
+    COMP           rx_baseband_log[COHPSK_NC*ND][(M+M/P)*NSYMROWPILOT*FRAMES];
 
     int            sync, next_sync, log_bits;
     float          EsNo, variance;
@@ -133,7 +133,7 @@ int main(int argc, char *argv[])
        bits_to_qpsk_symbols(tx_symb, (int*)tx_bits, COHPSK_BITS_PER_FRAME);
 
         for(r=0; r<NSYMROWPILOT; r++) {
-           for(c=0; c<PILOTS_NC; c++) 
+           for(c=0; c<COHPSK_NC*ND; c++) 
               tx_onesym[c] = tx_symb[r][c];         
            tx_filter_and_upconvert(&tx_fdm_frame[r*M], fdmdv->Nc , tx_onesym, fdmdv->tx_filter_memory, 
                                    fdmdv->phase_tx, fdmdv->freq, &fdmdv->fbb_phase_tx, fdmdv->fbb_rect);
@@ -167,18 +167,18 @@ int main(int argc, char *argv[])
           rx_filter(rx_filt, fdmdv->Nc, rx_baseband, coh->rx_filter_memory, nin);
          rx_timing = rx_est_timing(rx_onesym, fdmdv->Nc, rx_filt, fdmdv->rx_filter_mem_timing, env, nin);
           
-          for(c=0; c<PILOTS_NC; c++) {
+          for(c=0; c<COHPSK_NC*ND; c++) {
              ch_symb[r][c] = rx_onesym[c];
           }
           
-         for(c=0; c<PILOTS_NC; c++) {       
+         for(c=0; c<COHPSK_NC*ND; c++) {       
             for(i=0; i<nin; i++) {
               rx_baseband_log[c][rx_baseband_log_col_index + i] = rx_baseband[c][i]; 
             }
          }
          rx_baseband_log_col_index += nin;        
 
-         for(c=0; c<PILOTS_NC; c++) {       
+         for(c=0; c<COHPSK_NC*ND; c++) {       
             for(i=0; i<P; i++) {
               rx_filt_log[c][rx_filt_log_col_index + i] = rx_filt[c][i]; 
             }
@@ -209,7 +209,7 @@ int main(int argc, char *argv[])
                memcpy(&rx_fdm_frame_bb_log[M*NSYMROWPILOT*f], rx_fdm_frame_bb, sizeof(COMP)*M*NSYMROWPILOT);
 
        for(r=0; r<NSYMROWPILOT; r++, log_r++) {
-            for(c=0; c<PILOTS_NC; c++) {
+            for(c=0; c<COHPSK_NC*ND; c++) {
                tx_symb_log[log_r][c] = tx_symb[r][c]; 
                ch_symb_log[log_r][c] = ch_symb[r][c]; 
                ct_symb_ff_log[log_r][c] = coh->ct_symb_ff_buf[r][c]; 
@@ -219,7 +219,7 @@ int main(int argc, char *argv[])
         if ((sync == 4) || (next_sync == 4)) {
 
            for(r=0; r<NSYMROW; r++, log_data_r++) {
-                for(c=0; c<PILOTS_NC; c++) {
+                for(c=0; c<COHPSK_NC*ND; c++) {
                     rx_amp_log[log_data_r][c] = coh->amp_[r][c]; 
                     rx_phi_log[log_data_r][c] = coh->phi_[r][c]; 
                     rx_symb_log[log_data_r][c] = coh->rx_symb[r][c]; 
@@ -243,17 +243,17 @@ int main(int argc, char *argv[])
     assert(fout != NULL);
     fprintf(fout, "# Created by tcohpsk.c\n");
     octave_save_int(fout, "tx_bits_log_c", tx_bits_log, 1, COHPSK_BITS_PER_FRAME*FRAMES);
-    octave_save_complex(fout, "tx_symb_log_c", (COMP*)tx_symb_log, NSYMROWPILOT*FRAMES, PILOTS_NC, PILOTS_NC);  
+    octave_save_complex(fout, "tx_symb_log_c", (COMP*)tx_symb_log, NSYMROWPILOT*FRAMES, COHPSK_NC*ND, COHPSK_NC*ND);  
     octave_save_complex(fout, "tx_fdm_frame_log_c", (COMP*)tx_fdm_frame_log, 1, M*NSYMROWPILOT*FRAMES, M*NSYMROWPILOT*FRAMES);  
     octave_save_complex(fout, "ch_fdm_frame_log_c", (COMP*)ch_fdm_frame_log, 1, M*NSYMROWPILOT*FRAMES, M*NSYMROWPILOT*FRAMES);  
     octave_save_complex(fout, "rx_fdm_frame_bb_log_c", (COMP*)rx_fdm_frame_bb_log, 1, M*NSYMROWPILOT*FRAMES, M*NSYMROWPILOT*FRAMES);  
-    octave_save_complex(fout, "rx_baseband_log_c", (COMP*)rx_baseband_log, PILOTS_NC, rx_baseband_log_col_index, (M+M/P)*FRAMES*NSYMROWPILOT);  
-    octave_save_complex(fout, "rx_filt_log_c", (COMP*)rx_filt_log, PILOTS_NC, rx_filt_log_col_index, (P+1)*FRAMES*NSYMROWPILOT);  
-    octave_save_complex(fout, "ch_symb_log_c", (COMP*)ch_symb_log, NSYMROWPILOT*FRAMES, PILOTS_NC, PILOTS_NC);  
-    octave_save_complex(fout, "ct_symb_ff_log_c", (COMP*)ct_symb_ff_log, NSYMROWPILOT*FRAMES, PILOTS_NC, PILOTS_NC);  
-    octave_save_float(fout, "rx_amp_log_c", (float*)rx_amp_log, log_data_r, PILOTS_NC, PILOTS_NC);  
-    octave_save_float(fout, "rx_phi_log_c", (float*)rx_phi_log, log_data_r, PILOTS_NC, PILOTS_NC);  
-    octave_save_complex(fout, "rx_symb_log_c", (COMP*)rx_symb_log, log_data_r, PILOTS_NC, PILOTS_NC);  
+    octave_save_complex(fout, "rx_baseband_log_c", (COMP*)rx_baseband_log, COHPSK_NC*ND, rx_baseband_log_col_index, (M+M/P)*FRAMES*NSYMROWPILOT);  
+    octave_save_complex(fout, "rx_filt_log_c", (COMP*)rx_filt_log, COHPSK_NC*ND, rx_filt_log_col_index, (P+1)*FRAMES*NSYMROWPILOT);  
+    octave_save_complex(fout, "ch_symb_log_c", (COMP*)ch_symb_log, NSYMROWPILOT*FRAMES, COHPSK_NC*ND, COHPSK_NC*ND);  
+    octave_save_complex(fout, "ct_symb_ff_log_c", (COMP*)ct_symb_ff_log, NSYMROWPILOT*FRAMES, COHPSK_NC*ND, COHPSK_NC*ND);  
+    octave_save_float(fout, "rx_amp_log_c", (float*)rx_amp_log, log_data_r, COHPSK_NC*ND, COHPSK_NC*ND);  
+    octave_save_float(fout, "rx_phi_log_c", (float*)rx_phi_log, log_data_r, COHPSK_NC*ND, COHPSK_NC*ND);  
+    octave_save_complex(fout, "rx_symb_log_c", (COMP*)rx_symb_log, log_data_r, COHPSK_NC*ND, COHPSK_NC*ND);  
     octave_save_int(fout, "rx_bits_log_c", rx_bits_log, 1, COHPSK_BITS_PER_FRAME*log_bits);
     fclose(fout);