cohpsk sample slip code interated into C and initial tests passing, need some better...
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 26 May 2015 06:54:31 +0000 (06:54 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 26 May 2015 06:54:31 +0000 (06:54 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2148 01035d8c-6547-0410-b346-abe4f91aad63

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
codec2-dev/unittest/test_cohpsk_ch.c

index 71af0c22725fc1acd662c728bcf3b9c08736ee13..caa83b9e63f7f428244aedb9f3f8708d0adbe3cd 100644 (file)
@@ -337,27 +337,14 @@ ch_fdm_frame_log = resample(ch_fdm_frame_log, (1E6 + sample_rate_ppm), 1E6);
 % Now run demod ----------------------------------------------------------------
 
 ch_fdm_frame_log_index = 1;
+nin = M;
 f = 0;
+nin_frame = acohpsk.Nsymbrowpilot*M;
 
 %while (ch_fdm_frame_log_index + acohpsk.Nsymbrowpilot*M+M/P) < length(ch_fdm_frame_log)
 for f=1:frames;
   acohpsk.frame = f;
 
-  if sync == 0  
-    nin = M;
-  else
-    nin = M;
-    if 0
-    if rx_timing(1) > M/P
-      nin = M + M/P;
-    end
-    if rx_timing(1) < -M/P
-      nin = M - M/P;
-    end
-    end
-  end
-
-  nin_frame = (acohpsk.Nsymbrowpilot-1)*M + nin;
   ch_fdm_frame = ch_fdm_frame_log(ch_fdm_frame_log_index:ch_fdm_frame_log_index + nin_frame - 1);
   ch_fdm_frame_log_index += nin_frame;
 
@@ -390,6 +377,7 @@ for f=1:frames;
       
       rx_filt_log = [rx_filt_log rx_filt];
       ch_symb_log = [ch_symb_log; ch_symb];
+      rx_timing_log = [rx_timing_log rx_timing];
 
       for i=1:Nsw-1
         acohpsk.ct_symb_buf = update_ct_symb_buf(acohpsk.ct_symb_buf, ch_symb((i-1)*acohpsk.Nsymbrowpilot+1:i*acohpsk.Nsymbrowpilot,:), acohpsk.Nct_sym_buf, acohpsk.Nsymbrowpilot);
@@ -419,7 +407,8 @@ for f=1:frames;
       rx_baseband_log = [rx_baseband_log rx_baseband];
       rx_filt_log = [rx_filt_log rx_filt];
       ch_symb_log = [ch_symb_log; ch_symb];
+      rx_timing_log = [rx_timing_log rx_timing];
+
       for i=1:Nsw-1
         acohpsk.ct_symb_buf = update_ct_symb_buf(acohpsk.ct_symb_buf, ch_symb((i-1)*acohpsk.Nsymbrowpilot+1:i*acohpsk.Nsymbrowpilot,:), acohpsk.Nct_sym_buf, acohpsk.Nsymbrowpilot);
       end
@@ -492,6 +481,20 @@ for f=1:frames;
 
   [sync acohpsk] = sync_state_machine(acohpsk, sync, next_sync);
 
+  % work out how many samples we need for next time
+
+  nin = M;
+  if sync == 1
+    if rx_timing(length(rx_timing)) > M/P
+      nin = M + M/P;
+    end
+    if rx_timing(length(rx_timing)) < -M/P
+      nin = M - M/P;
+    end
+  end
+  nin_frame = (acohpsk.Nsymbrowpilot-1)*M + nin;
+  %printf("%f %d %d\n", rx_timing(length(rx_timing)), nin, nin_frame);
+
   prev_tx_bits2 = prev_tx_bits;
   prev_tx_bits = tx_bits;
 
@@ -545,6 +548,7 @@ if compare_with_c
 
   stem_sig_and_error(10, 111, rx_bits_log_c, rx_bits_log - rx_bits_log_c, 'rx bits', [1 length(rx_bits_log) -1.5 1.5])
   stem_sig_and_error(11, 111, f_est_log_c - Fcentre, f_est_log - f_est_log_c, 'f est', [1 length(f_est_log) foff-5 foff+5])
+  stem_sig_and_error(12, 111, rx_timing_log_c, rx_timing_log_c - rx_timing_log, 'rx timing', [1 length(rx_timing_log) -M M])
 
   check(tx_bits_log, tx_bits_log_c, 'tx_bits');
   check(tx_symb_log, tx_symb_log_c, 'tx_symb');
@@ -557,6 +561,7 @@ if compare_with_c
   check(rx_amp_log, rx_amp_log_c, 'rx_amp_log',0.01);
   check(phi_log_diff, zeros(length(phi_log_diff), Nc*Nd), 'rx_phi_log',0.05);
   check(rx_symb_log, rx_symb_log_c, 'rx_symb',0.01);
+  check(rx_timing_log, rx_timing_log_c, 'rx_timing',0.001);
   check(rx_bits_log, rx_bits_log_c, 'rx_bits');
   check(f_est_log, f_est_log_c, 'f_est');
   
index 52e08c594ad734f6e63a5de86b6e03c5c0962abb..b4e227c52b2d3160553946fb27f56929e5703262 100644 (file)
@@ -32,7 +32,7 @@
 #define COHPSK_NC                  7              /* hard coded for now */
 #define COHPSK_SAMPLES_PER_FRAME 600
 #define COHPSK_RS                 75
-#define COHPSK_FS               7500
+#define COHPSK_FS               7500              /* note this is a wierd value to get an integer oversampling rate */
 
 #include "comp.h"
 #include "codec2_fdmdv.h"
@@ -42,6 +42,6 @@ struct COHPSK;
 struct COHPSK *cohpsk_create(void);
 void cohpsk_destroy(struct COHPSK *coh);
 void cohpsk_mod(struct COHPSK *cohpsk, COMP tx_fdm[], int tx_bits[]);
-void cohpsk_demod(struct COHPSK *cohpsk, int rx_bits[], int *reliable_sync_bit, COMP rx_fdm[]);
+void cohpsk_demod(struct COHPSK *cohpsk, int rx_bits[], int *reliable_sync_bit, COMP rx_fdm[], int *nin_frame);
 
 #endif
index 31758618d1f491ec4ea2b5fd1e9da634fb1a390d..5d04b4b4dfd492961148583570bc6c57d8e9584e 100644 (file)
@@ -118,6 +118,7 @@ struct COHPSK *cohpsk_create(void)
     coh->sync  = 0;
     coh->frame = 0;
     coh->ratio = 0.0;
+    coh->nin = COHPSK_M;
 
     /* clear sync window buffer */
 
@@ -160,6 +161,8 @@ struct COHPSK *cohpsk_create(void)
     coh->rx_filt_log_col_index = 0;
     coh->ch_symb_log = NULL;
     coh->ch_symb_log_r = 0;
+    coh->rx_timing_log = NULL;
+    coh->rx_timing_log_index = 0;
 
     return coh;
 }
@@ -751,7 +754,7 @@ void fdmdv_freq_shift_coh(COMP rx_fdm_fcorr[], COMP rx_fdm[], float foff,
 void rate_Fs_rx_processing(struct COHPSK *coh, COMP ch_symb[][COHPSK_NC*ND], COMP ch_fdm_frame[], float *f_est, int nsymb, int nin, int freq_track)
 {
     struct FDMDV *fdmdv = coh->fdmdv;
-    int   r, c, i;
+    int   r, c, i, ch_fdm_frame_index;
     COMP  rx_fdm_frame_bb[COHPSK_M];
     COMP  rx_baseband[COHPSK_NC*ND][COHPSK_M+COHPSK_M/P];
     COMP  rx_filt[COHPSK_NC*ND][P+1];
@@ -760,10 +763,11 @@ void rate_Fs_rx_processing(struct COHPSK *coh, COMP ch_symb[][COHPSK_NC*ND], COM
     float beta, g;
     COMP  adiff, amod_strip, mod_strip;
 
-    assert(nin < COHPSK_M*NSYMROWPILOT);
+    ch_fdm_frame_index = 0;
 
     for (r=0; r<nsymb; r++) {
-        fdmdv_freq_shift_coh(rx_fdm_frame_bb, &ch_fdm_frame[r*COHPSK_M], -(*f_est), &fdmdv->fbb_phase_rx, nin);
+        fdmdv_freq_shift_coh(rx_fdm_frame_bb, &ch_fdm_frame[ch_fdm_frame_index], -(*f_est), &fdmdv->fbb_phase_rx, nin);
+        ch_fdm_frame_index += nin;
         fdm_downconvert_coh(rx_baseband, COHPSK_NC*ND, rx_fdm_frame_bb, fdmdv->phase_rx, fdmdv->freq, nin);
         rx_filter_coh(rx_filt, COHPSK_NC*ND, 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, COHPSK_M);
@@ -823,12 +827,12 @@ void rate_Fs_rx_processing(struct COHPSK *coh, COMP ch_symb[][COHPSK_NC*ND], COM
         }
 
         if (coh->rx_filt_log) {
-         for(c=0; c<COHPSK_NC*ND; c++) {       
-            for(i=0; i<P; i++) {
+         for(c=0; c<COHPSK_NC*ND; c++) {     
+            for(i=0; i<nin/(COHPSK_M/P); i++) {
               coh->rx_filt_log[c*coh->rx_filt_log_col_sz + coh->rx_filt_log_col_index + i] = rx_filt[c][i]; 
             }
          }
-         coh->rx_filt_log_col_index += P;        
+         coh->rx_filt_log_col_index += nin/(COHPSK_M/P);        
         }
 
         if (coh->ch_symb_log) {
@@ -837,8 +841,20 @@ void rate_Fs_rx_processing(struct COHPSK *coh, COMP ch_symb[][COHPSK_NC*ND], COM
             }
             coh->ch_symb_log_r++;
         }
+
+        if (coh->rx_timing_log) {
+            coh->rx_timing_log[coh->rx_timing_log_index] = rx_timing;
+            coh->rx_timing_log_index++;
+            //printf("rx_timing_log_index: %d\n", coh->rx_timing_log_index);
+        }
+
+        /* we only allow a timing shift on one symbol per frame */
+
+        if (nin != COHPSK_M)
+            nin = COHPSK_M;
     }
 
+    coh->rx_timing = rx_timing;
 }
 
 
@@ -848,39 +864,31 @@ void rate_Fs_rx_processing(struct COHPSK *coh, COMP ch_symb[][COHPSK_NC*ND], COM
   AUTHOR......: David Rowe                           
   DATE CREATED: 5/4/2015
 
-  COHPSK demodulator, takes an array of COHPSK_SAMPLES_PER_FRAME
-  modulated samples, returns an array of COHPSK_BITS_PER_FRAME bits.
+  COHPSK demodulator, takes an array of (nominally) nin_frame =
+  COHPSK_SAMPLES_PER_FRAME modulated samples, returns an array of
+  COHPSK_BITS_PER_FRAME bits.
 
   The input signal is complex to support single sided frequency shifting
   before the demod input (e.g. click to tune feature).
 
-  The number of input samples is fixed, and unlike the FDMDV modem
-  doesn't change to adjust for differences in transmit and receive
-  sample clocks.  This means frame sync will occasionally be lost,
-  however this is hardly noticable for digital voice applications.
-
-  TODO: logic to check if we are still in sync, ride thru bad frames
-
 \*---------------------------------------------------------------------------*/
 
-void cohpsk_demod(struct COHPSK *coh, int rx_bits[], int *reliable_sync_bit, COMP rx_fdm[])
+void cohpsk_demod(struct COHPSK *coh, int rx_bits[], int *reliable_sync_bit, COMP rx_fdm[], int *nin_frame)
 {
     COMP  ch_symb[NSW*NSYMROWPILOT][COHPSK_NC*ND];
     int   i, j, sync, anext_sync, next_sync, nin, r, c;
     float max_ratio, f_est;
 
-    /* store two frames of received samples so we can rewind if we get a good candidate */
+    next_sync = sync = coh->sync;
 
-    for (i=0; i<(NSW-1)*NSYMROWPILOT*COHPSK_M; i++)
-        coh->ch_fdm_frame_buf[i] = coh->ch_fdm_frame_buf[i+NSYMROWPILOT*COHPSK_M];
+    for (i=0; i<NSW*NSYMROWPILOT*COHPSK_M-*nin_frame; i++)
+        coh->ch_fdm_frame_buf[i] = coh->ch_fdm_frame_buf[i+*nin_frame];
+    //printf("nin_frame: %d i: %d i+nin_frame: %d\n", *nin_frame, i, i+*nin_frame);
     for (j=0; i<NSW*NSYMROWPILOT*COHPSK_M; i++,j++)
         coh->ch_fdm_frame_buf[i] = rx_fdm[j];
     //printf("i: %d j: %d rx_fdm[0]: %f %f\n", i,j, rx_fdm[0].real, rx_fdm[0].imag);
 
-    next_sync = sync = coh->sync;
-    nin = COHPSK_M;
-
-    /* if out of sync do Initial Freq offset estimation using NSW frames to flush out filter memories */
+   /* if out of sync do Initial Freq offset estimation using NSW frames to flush out filter memories */
 
     if (sync == 0) {
 
@@ -893,7 +901,7 @@ void cohpsk_demod(struct COHPSK *coh, int rx_bits[], int *reliable_sync_bit, COM
 
             /* we are out of sync so reset f_est and process two frames to clean out memories */
 
-            rate_Fs_rx_processing(coh, ch_symb, coh->ch_fdm_frame_buf, &coh->f_est, NSW*NSYMROWPILOT, nin, 0);
+            rate_Fs_rx_processing(coh, ch_symb, coh->ch_fdm_frame_buf, &coh->f_est, NSW*NSYMROWPILOT, COHPSK_M, 0);
             for (i=0; i<NSW-1; i++) {
                 update_ct_symb_buf(coh->ct_symb_buf, &ch_symb[i*NSYMROWPILOT]);
             }
@@ -918,7 +926,7 @@ void cohpsk_demod(struct COHPSK *coh, int rx_bits[], int *reliable_sync_bit, COM
 
             fprintf(stderr, "  [%d] trying sync and f_est: %f\n", coh->frame, coh->f_est);
 
-            rate_Fs_rx_processing(coh, ch_symb, coh->ch_fdm_frame_buf, &coh->f_est, NSW*NSYMROWPILOT, nin, 0);
+            rate_Fs_rx_processing(coh, ch_symb, coh->ch_fdm_frame_buf, &coh->f_est, NSW*NSYMROWPILOT, COHPSK_M, 0);
             for (i=0; i<NSW-1; i++) {
                 update_ct_symb_buf(coh->ct_symb_buf, &ch_symb[i*NSYMROWPILOT]);
             }
@@ -954,7 +962,7 @@ void cohpsk_demod(struct COHPSK *coh, int rx_bits[], int *reliable_sync_bit, COM
     /* If in sync just do sample rate processing on latest frame */
 
     if (sync == 1) {
-        rate_Fs_rx_processing(coh, ch_symb, rx_fdm, &coh->f_est, NSYMROWPILOT, nin, 1);
+        rate_Fs_rx_processing(coh, ch_symb, rx_fdm, &coh->f_est, NSYMROWPILOT, coh->nin, 1);
         frame_sync_fine_freq_est(coh, ch_symb, sync, &next_sync);
  
         for(r=0; r<2; r++)
@@ -975,4 +983,18 @@ void cohpsk_demod(struct COHPSK *coh, int rx_bits[], int *reliable_sync_bit, COM
 
     sync = sync_state_machine(coh, sync, next_sync);        
     coh->sync = sync;
+
+    /* work out how many samples we need for the next call to account
+       for differences in tx and rx sample clocks */
+
+    nin = COHPSK_M;   
+    if (sync == 1) {
+        if (coh->rx_timing > COHPSK_M/P)
+            nin = COHPSK_M + COHPSK_M/P;
+        if (coh->rx_timing < -COHPSK_M/P)
+            nin = COHPSK_M - COHPSK_M/P;
+    }
+    coh->nin = nin;
+    *nin_frame = (NSYMROWPILOT-1)*COHPSK_M + nin;
+    //printf("%f %d %d\n", coh->rx_timing, nin, *nin_frame);
 }
index 4f580137e5405ac0dbf7be2e421288a0c33757b1..c98c580b9bd3b717221e07b5557d693f13f7a2a7 100644 (file)
@@ -51,7 +51,9 @@ struct COHPSK {
     float        f_est;
     COMP         rx_filter_memory[COHPSK_NC*ND][COHPSK_NFILTER];
     COMP         ct_symb_buf[NCT_SYMB_BUF][COHPSK_NC*ND];
-    int          ct;                                 /* coarse timing offset in symbols                       */
+    int          ct;                                    /* coarse timing offset in symbols                       */
+    float        rx_timing;                             /* fine timing for last symbol in frame                  */
+    int          nin;                                   /* number of samples to input for next symbol            */
     float        f_fine_est;
     COMP         ff_rect;
     COMP         ff_phase;
@@ -64,19 +66,22 @@ struct COHPSK {
 
     struct FDMDV *fdmdv;
     
-    /* optional log variables used for tetsing Octave to C port */
+    /* optional log variables used for testing Octave to C port */
 
-    COMP           *rx_baseband_log;
+    COMP          *rx_baseband_log;
     int            rx_baseband_log_col_index;
     int            rx_baseband_log_col_sz;
 
-    COMP           *rx_filt_log;
+    COMP          *rx_filt_log;
     int            rx_filt_log_col_index;
     int            rx_filt_log_col_sz;
 
-    COMP           *ch_symb_log;
+    COMP          *ch_symb_log;
     int            ch_symb_log_r;
     int            ch_symb_log_col_sz;
+
+    float         *rx_timing_log;
+    int            rx_timing_log_index;
 };
 
 void bits_to_qpsk_symbols(COMP tx_symb[][COHPSK_NC*COHPSK_ND], int tx_bits[], int nbits);
index 41774895065a31920a3a9afa2a24f5c372a6a070..7b16e4f0ad4144025bdd16b912334a98b35de73c 100644 (file)
@@ -99,6 +99,7 @@ int main(int argc, char *argv[])
     float          EsNo, variance;
     COMP           scaled_noise;
     int            reliable_sync_bit;
+    int            ch_fdm_frame_log_index, nin_frame, tmp;
 
     coh = cohpsk_create();
     fdmdv = coh->fdmdv;
@@ -114,6 +115,8 @@ int main(int argc, char *argv[])
 
     coh->ch_symb_log_col_sz = COHPSK_NC*ND;
     coh->ch_symb_log = (COMP *)malloc(sizeof(COMP)*NSYMROWPILOT*FRAMESL*coh->ch_symb_log_col_sz);
+
+    coh->rx_timing_log = (float*)malloc(sizeof(float)*NSYMROWPILOT*FRAMESL);
     
     /* init stuff */
 
@@ -136,7 +139,6 @@ int main(int argc, char *argv[])
     /* Main Loop ---------------------------------------------------------------------*/
 
     for(f=0; f<FRAMES; f++) {
-        coh->frame = f;
 
        /* --------------------------------------------------------*\
                                  Mod
@@ -176,27 +178,39 @@ int main(int argc, char *argv[])
             ch_fdm_frame[r] = cadd(ch_fdm_frame[r], scaled_noise);
         }
 
-
-       /* --------------------------------------------------------*\
-                                 Demod
-       \*---------------------------------------------------------*/
-
-        cohpsk_demod(coh, rx_bits, &reliable_sync_bit, ch_fdm_frame);
-
-       /* --------------------------------------------------------*\
-                              Log each vector 
-       \*---------------------------------------------------------*/
+        /* tx vector logging */
 
        memcpy(&tx_bits_log[COHPSK_BITS_PER_FRAME*f], tx_bits, sizeof(int)*COHPSK_BITS_PER_FRAME);
        memcpy(&tx_fdm_frame_log[COHPSK_M*NSYMROWPILOT*f], tx_fdm_frame, sizeof(COMP)*COHPSK_M*NSYMROWPILOT);
        memcpy(&ch_fdm_frame_log[COHPSK_M*NSYMROWPILOT*f], ch_fdm_frame, sizeof(COMP)*COHPSK_M*NSYMROWPILOT);
-               //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<COHPSK_NC*ND; c++) {
                tx_symb_log[log_r][c] = tx_symb[r][c]; 
             }
         }
+    }
+
+    nin_frame = COHPSK_SAMPLES_PER_FRAME;
+    ch_fdm_frame_log_index = 0;
+
+    for(f=0; f<FRAMES; f++) {
+        coh->frame = f;
+
+        //printf("nin_frame: %d\n", nin_frame);
+
+       /* --------------------------------------------------------*\
+                                 Demod
+       \*---------------------------------------------------------*/
+
+        assert(ch_fdm_frame_log_index < COHPSK_M*NSYMROWPILOT*FRAMES);
+        tmp = nin_frame;
+        cohpsk_demod(coh, rx_bits, &reliable_sync_bit, &ch_fdm_frame_log[ch_fdm_frame_log_index], &nin_frame);
+        ch_fdm_frame_log_index += tmp;
+
+       /* --------------------------------------------------------*\
+                              Log each vector 
+       \*---------------------------------------------------------*/
 
         if (coh->sync == 1) {
 
@@ -242,6 +256,7 @@ int main(int argc, char *argv[])
     octave_save_complex(fout, "rx_baseband_log_c", (COMP*)coh->rx_baseband_log, COHPSK_NC*ND, coh->rx_baseband_log_col_index, coh->rx_baseband_log_col_sz);  
     octave_save_complex(fout, "rx_filt_log_c", (COMP*)coh->rx_filt_log, COHPSK_NC*ND, coh->rx_filt_log_col_index, coh->rx_filt_log_col_sz);  
     octave_save_complex(fout, "ch_symb_log_c", (COMP*)coh->ch_symb_log, coh->ch_symb_log_r, COHPSK_NC*ND, COHPSK_NC*ND);  
+    octave_save_float(fout, "rx_timing_log_c", (float*)coh->rx_timing_log, 1, coh->rx_timing_log_index, coh->rx_timing_log_index);  
     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);  
index 2ef6f3c5019ed37251712bae7753ac8581d17aaa..cf4d6bbc1996fd0e3e00e603e89ae460b015e983 100644 (file)
@@ -64,7 +64,7 @@ int main(int argc, char *argv[])
     float          EsNo, variance;
     COMP           scaled_noise;
     float          EsNodB, foff_hz;
-    int            fading_en, nhfdelay, ret;
+    int            fading_en, nhfdelay, ret, nin;
     COMP          *ch_fdm_delay, aspread, aspread_2ms, delayed, direct;
     FILE          *ffading;
 
@@ -112,6 +112,8 @@ int main(int argc, char *argv[])
 
     /* Main Loop ---------------------------------------------------------------------*/
 
+    nin = COHPSK_SAMPLES_PER_FRAME;
+
     for(f=0; f<FRAMES; f++) {
         
        /* --------------------------------------------------------*\
@@ -173,7 +175,7 @@ int main(int argc, char *argv[])
                                  Demod
        \*---------------------------------------------------------*/
 
-       cohpsk_demod(coh, rx_bits, &reliable_sync_bit, ch_fdm);
+       cohpsk_demod(coh, rx_bits, &reliable_sync_bit, ch_fdm, &nin);
 
         errors = 0;
         for(i=0; i<COHPSK_BITS_PER_FRAME; i++) {