Fs offset tests passing, C and Octave match over 35 frames
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 26 May 2015 10:51:01 +0000 (10:51 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 26 May 2015 10:51:01 +0000 (10:51 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2150 01035d8c-6547-0410-b346-abe4f91aad63

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

index 7364a06b49a7c60e455f095273aa90d4d82aab8a..4e4de76fa62951b2153547661193209e78b6ad30 100644 (file)
@@ -71,13 +71,13 @@ Fs           = 7500;
 
 if strcmp(test, 'compare to c')
   frames = 35;
-  foff =  0;
-  dfoff = 0;
+  foff =  58.7;
+  dfoff = -0.5/Fs;
   EsNodB = 8;
   fading_en = 0;
   hf_delay_ms = 2;
   compare_with_c = 1;
-  sample_rate_ppm = 0;
+  sample_rate_ppm = -1000;
   ssb_tx_filt  = 0;
 end
 
@@ -91,7 +91,7 @@ if strcmp(test, 'awgn')
   fading_en = 0;
   hf_delay_ms = 2;
   compare_with_c = 0;
-  sample_rate_ppm = 0;
+  sample_rate_ppm = -1000;
 end
 
 % Similar to AWGN - should be BER around 0.015 to 0.02
@@ -333,7 +333,21 @@ end
 
 % simulate difference in sample clocks
 
-ch_fdm_frame_log = resample(ch_fdm_frame_log, (1E6 + sample_rate_ppm), 1E6);
+%ch_fdm_frame_log = resample(ch_fdm_frame_log, (1E6 + sample_rate_ppm), 1E6);
+
+ch_fdm_frame_log_out = zeros(1, length(ch_fdm_frame_log));
+tin=1;
+tout=1;
+while tin < length(ch_fdm_frame_log)
+      t1 = floor(tin);
+      t2 = ceil(tin);
+      f = tin - t1;
+      ch_fdm_frame_log_out(tout) = (1-f)*ch_fdm_frame_log(t1) + f*ch_fdm_frame_log(t2);
+      tout += 1;
+      tin  += 1+sample_rate_ppm/1E6;
+      %printf("tin: %f tout: %f f: %f\n", tin, tout, f);
+end
+ch_fdm_frame_log = ch_fdm_frame_log_out;
 
 % Now run demod ----------------------------------------------------------------
 
@@ -543,12 +557,13 @@ if compare_with_c
   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])
   phi_log_diff = rx_phi_log - rx_phi_log_c;
   phi_log_diff(find(phi_log_diff > pi)) -= 2*pi;
+  phi_log_diff(find(phi_log_diff < -pi)) += 2*pi;
   stem_sig_and_error(8, 212, rx_phi_log_c, phi_log_diff, '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])
   stem_sig_and_error(9, 212, imag(rx_symb_log_c), imag(rx_symb_log - rx_symb_log_c), 'rx symb im', [1 n -1.5 1.5])
 
   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(11, 111, f_est_log_c, f_est_log - f_est_log_c, 'f est', [1 length(f_est_log) min(f_est_log) max(f_est_log)])
   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');
index e26c310edbcf8e9ea40a585c2f425490a747d7ea..69806802048b3f37d6d0a0e5a715d7551c829be4 100644 (file)
@@ -1027,3 +1027,35 @@ void cohpsk_demod(struct COHPSK *coh, int rx_bits[], int *reliable_sync_bit, COM
     *nin_frame = (NSYMROWPILOT-1)*COHPSK_M + nin;
     //printf("%f %d %d\n", coh->rx_timing, nin, *nin_frame);
 }
+
+
+/*---------------------------------------------------------------------------*\
+                                                       
+  FUNCTION....: cohpsk_fs_offset()          
+  AUTHOR......: David Rowe                           
+  DATE CREATED: May 2015
+
+  Simulates small Fs offset between mod and demod.
+
+\*---------------------------------------------------------------------------*/
+
+int cohpsk_fs_offset(COMP out[], COMP in[], int n, float sample_rate_ppm)
+{
+    double tin, f;
+    int   tout, t1, t2;
+
+    tin = 0.0; tout = 0; 
+    while (tin < n) {
+      t1 = floor(tin);
+      t2 = ceil(tin);
+      f = tin - t1;
+      out[tout].real = (1.0-f)*in[t1].real + f*in[t2].real;
+      out[tout].imag = (1.0-f)*in[t1].imag + f*in[t2].imag;
+      tout += 1;
+      tin  += 1.0 + sample_rate_ppm/1E6;
+      //printf("tin: %f tout: %d f: %f\n", tin, tout, f);
+    }
+
+    return tout;
+}
+
index 5a8c047440f633371a2ee3ad1c0f6527f087094a..9fc82963d5654d404b45b0a77797154d3e7a29a0 100644 (file)
@@ -98,4 +98,6 @@ void fine_freq_correct(struct COHPSK *coh, int sync, int next_sync);
 int sync_state_machine(struct COHPSK *coh, int sync, int next_sync);
 void fdmdv_freq_shift_coh(COMP rx_fdm_fcorr[], COMP rx_fdm[], float foff, 
                           COMP *foff_phase_rect, int nin);
+int cohpsk_fs_offset(COMP out[], COMP in[], int n, float sample_rate_ppm);
+
 #endif
index 49a0c9cec0645db6f62a29994c73e6f09e1afbd5..d0cc5d593dd5261146d63268181e94219db76b30 100644 (file)
 #define SYNC_FRAMES 12                    /* sync state uses up extra log storage as we reprocess several times */
 #define FRAMESL     (SYNC_FRAMES*FRAMES)  /* worst case is every frame is out of sync                           */
 
-#define FOFF        0 //55.5
-#define DFOFF       0 //(-0.5/(float)COHPSK_FS)
+#define FOFF        58.7
+#define DFOFF       (-0.5/(float)COHPSK_FS)
 #define ESNODB      8
+#define PPM         -1000
 
 extern float pilots_coh[][PILOTS_NC];
 
@@ -69,6 +70,7 @@ int main(int argc, char *argv[])
     COMP           tx_symb_log[NSYMROWPILOT*FRAMES][COHPSK_NC*ND];
     COMP           tx_fdm_frame_log[COHPSK_M*NSYMROWPILOT*FRAMES];
     COMP           ch_fdm_frame_log[COHPSK_M*NSYMROWPILOT*FRAMES];
+    COMP           ch_fdm_frame_log_out[(COHPSK_M*NSYMROWPILOT+1)*FRAMES];
     //COMP           rx_fdm_frame_bb_log[M*NSYMROWPILOT*FRAMES];
     //COMP           ch_symb_log[NSYMROWPILOT*FRAMES][COHPSK_NC*ND];
     COMP           ct_symb_ff_log[NSYMROWPILOT*FRAMES][COHPSK_NC*ND];
@@ -99,7 +101,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;
+    int            ch_fdm_frame_log_index, nin_frame, tmp, nout;
 
     coh = cohpsk_create();
     fdmdv = coh->fdmdv;
@@ -192,6 +194,11 @@ int main(int argc, char *argv[])
         }
     }
 
+    /* Fs offset simulation */
+
+    nout = cohpsk_fs_offset(ch_fdm_frame_log_out, ch_fdm_frame_log, COHPSK_M*NSYMROWPILOT*FRAMES, PPM);
+    assert(nout < (COHPSK_M*NSYMROWPILOT+1)*FRAMES);
+
     nin_frame = COHPSK_SAMPLES_PER_FRAME;
     ch_fdm_frame_log_index = 0;
 
@@ -206,7 +213,7 @@ int main(int argc, char *argv[])
 
         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);
+        cohpsk_demod(coh, rx_bits, &reliable_sync_bit, &ch_fdm_frame_log_out[ch_fdm_frame_log_index], &nin_frame);
         ch_fdm_frame_log_index += tmp;
 
        /* --------------------------------------------------------*\
@@ -252,7 +259,7 @@ int main(int argc, char *argv[])
     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, COHPSK_NC*ND, COHPSK_NC*ND);  
     octave_save_complex(fout, "tx_fdm_frame_log_c", (COMP*)tx_fdm_frame_log, 1, COHPSK_M*NSYMROWPILOT*FRAMES, COHPSK_M*NSYMROWPILOT*FRAMES);  
-    octave_save_complex(fout, "ch_fdm_frame_log_c", (COMP*)ch_fdm_frame_log, 1, COHPSK_M*NSYMROWPILOT*FRAMES, COHPSK_M*NSYMROWPILOT*FRAMES);  
+    octave_save_complex(fout, "ch_fdm_frame_log_c", (COMP*)ch_fdm_frame_log_out, 1, nout-1, nout-1);  
     //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*)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);