added sample clock offset to simulation, looks good!
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 22 Jun 2017 21:59:17 +0000 (21:59 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 22 Jun 2017 21:59:17 +0000 (21:59 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@3236 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/sample_clock_offset.m [new file with mode: 0644]
codec2-dev/octave/tofdm.m
codec2-dev/unittest/tofdm.c

diff --git a/codec2-dev/octave/sample_clock_offset.m b/codec2-dev/octave/sample_clock_offset.m
new file mode 100644 (file)
index 0000000..5169178
--- /dev/null
@@ -0,0 +1,21 @@
+% sample_clock_offset.m
+%
+% David Rowe June 2017
+%
+% To simulate a sample clock offset we resample by a small amount
+% using linear interpolation
+
+function rx = sample_clock_offset(tx, sample_clock_offset_ppm)
+  tin=1;
+  tout=1;
+  rx = zeros(1,length(tx));
+  while tin < length(tx)
+      t1 = floor(tin);
+      t2 = ceil(tin);
+      f = tin - t1;
+      rx(tout) = (1-f)*tx(t1) + f*tx(t2);
+      tout += 1;
+      tin  += 1+sample_clock_offset_ppm/1E6;
+  end
+end
+  
index 0abb1780e2bcee1e36437c009a0ccc63901f3959..f361fdd668a874c3262f858da38cd4830d9d370e 100644 (file)
@@ -3,8 +3,10 @@
 %
 % Octave script for comparing Octave and C versions of OFDZM modem
 
+% ------------------------------------------------------------------
 
-Nframes = 3;
+Nframes = 30;
+sample_clock_offset_ppm = 100;
 
 more off; format;
 ofdm_lib;
@@ -29,16 +31,18 @@ for f=1:Nframes
   tx_log = [tx_log ofdm_mod(states, tx_bits)];
 end
 
-% Channel simulation
+% Channel simulation ----------------------------------------------
 
-rx = tx_log;
+rx_log = sample_clock_offset(tx_log, sample_clock_offset_ppm);
+
+% Rx ---------------------------------------------------------------
 
 % Init rx with ideal timing so we can test with timing estimation disabled
 
-Nsam = length(rx);
+Nsam = length(rx_log);
 prx = 1;
 nin = Nsamperframe+2*(M+Ncp);
-states.rxbuf(Nrxbuf-nin+1:Nrxbuf) = rx(prx:nin);
+states.rxbuf(Nrxbuf-nin+1:Nrxbuf) = rx_log(prx:nin);
 prx += nin;
 
 rxbuf_log = []; rxbuf_in_log = []; rx_sym_log = []; foff_hz_log = []; 
@@ -66,7 +70,7 @@ for f=1:Nframes
   rxbuf_in = zeros(1,nin);
   %printf("nin: %d prx: %d lnew: %d\n", nin, prx, lnew);
   if lnew
-    rxbuf_in(1:lnew) = rx(prx:prx+lnew-1);
+    rxbuf_in(1:lnew) = rx_log(prx:prx+lnew-1);
   end
   prx += lnew;
 
@@ -109,6 +113,9 @@ stem_sig_and_error(fg++, 111, tx_bits_log_c, tx_bits_log - tx_bits_log_c, 'tx bi
 stem_sig_and_error(fg, 211, real(tx_log_c), real(tx_log - tx_log_c), 'tx re', [1 length(tx_log_c) -0.1 0.1])
 stem_sig_and_error(fg++, 212, imag(tx_log_c), imag(tx_log - tx_log_c), 'tx im', [1 length(tx_log_c) -0.1 0.1])
 
+stem_sig_and_error(fg, 211, real(rx_log_c), real(rx_log - rx_log_c), 'rx re', [1 length(rx_log_c) -0.1 0.1])
+stem_sig_and_error(fg++, 212, imag(rx_log_c), imag(rx_log - rx_log_c), 'rx im', [1 length(rx_log_c) -0.1 0.1])
+
 stem_sig_and_error(fg, 211, real(rxbuf_in_log_c), real(rxbuf_in_log - rxbuf_in_log_c), 'rxbuf in re', [1 length(rxbuf_in_log_c) -0.1 0.1])
 stem_sig_and_error(fg++, 212, imag(rxbuf_in_log_c), imag(rxbuf_in_log - rxbuf_in_log_c), 'rxbuf in im', [1 length(rxbuf_in_log_c) -0.1 0.1])
 
@@ -137,6 +144,7 @@ stem_sig_and_error(fg++, 111, rx_bits_log_c, rx_bits_log - rx_bits_log_c, 'rx bi
 check(W, W_c, 'W');
 check(tx_bits_log, tx_bits_log_c, 'tx_bits');
 check(tx_log, tx_log_c, 'tx');
+check(rx_log, rx_log_c, 'rx');
 check(rxbuf_in_log, rxbuf_in_log_c, 'rxbuf in');
 check(rxbuf_log, rxbuf_log_c, 'rxbuf');
 check(rx_sym_log, rx_sym_log_c, 'rx_sym');
@@ -146,3 +154,4 @@ check(timing_est_log, timing_est_log_c, 'timing_est');
 check(sample_point_log, sample_point_log_c, 'sample_point');
 check(foff_hz_log, foff_hz_log_c, 'foff_est_hz');
 check(rx_bits_log, rx_bits_log_c, 'rx_bits');
+
index 78638ea23662642fbb12e652ee5fd7813a2272cc..a3fe618cb25b2a8f3b6cb993c3d1f78f98958068 100644 (file)
 #include "octave.h"
 #include "test_bits_ofdm.h"
 
-#define NFRAMES 3
+#define NFRAMES 30
+#define SAMPLE_CLOCK_OFFSET_PPM 100
+
+int cohpsk_fs_offset(COMP out[], COMP in[], int n, float sample_rate_ppm);
 
 int main(int argc, char *argv[])
 {
@@ -56,6 +59,7 @@ int main(int argc, char *argv[])
 
     int            tx_bits_log[OFDM_BITSPERFRAME*NFRAMES];
     COMP           tx_log[samples_per_frame*NFRAMES];
+    COMP           rx_log[samples_per_frame*NFRAMES];
     COMP           rxbuf_in_log[max_samples_per_frame*NFRAMES];
     COMP           rxbuf_log[OFDM_RXBUF*NFRAMES];
     COMP           rx_sym_log[(OFDM_NS + 3)*NFRAMES][OFDM_NC + 2];
@@ -92,10 +96,14 @@ int main(int argc, char *argv[])
     }
 
     /* --------------------------------------------------------*\
-                               Demod
+                               Channel
     \*---------------------------------------------------------*/
 
-    COMP *rx = tx_log;
+    cohpsk_fs_offset(rx_log, tx_log, samples_per_frame*NFRAMES, SAMPLE_CLOCK_OFFSET_PPM);
+
+    /* --------------------------------------------------------*\
+                               Demod
+    \*---------------------------------------------------------*/
 
     /* Init rx with ideal timing so we can test with timing estimation disabled */
 
@@ -107,7 +115,7 @@ int main(int argc, char *argv[])
     COMP rxbuf_in[max_samples_per_frame];
 
     for (i=0; i<nin; i++,prx++) {
-         ofdm->rxbuf[OFDM_RXBUF-nin+i] = rx[prx].real + I*rx[prx].imag;
+         ofdm->rxbuf[OFDM_RXBUF-nin+i] = rx_log[prx].real + I*rx_log[prx].imag;
     }
 
     int nin_tot = 0;
@@ -144,7 +152,7 @@ int main(int argc, char *argv[])
 
         if (lnew) {
             for(i=0; i<lnew; i++, prx++) {
-                rxbuf_in[i] = rx[prx];
+                rxbuf_in[i] = rx_log[prx];
             }
         }
         assert(prx <= max_samples_per_frame*NFRAMES);
@@ -203,6 +211,7 @@ int main(int argc, char *argv[])
     octave_save_complex(fout, "W_c", (COMP*)ofdm->W, OFDM_NC + 2, OFDM_M, OFDM_M);
     octave_save_int(fout, "tx_bits_log_c", tx_bits_log, 1, OFDM_BITSPERFRAME*NFRAMES);
     octave_save_complex(fout, "tx_log_c", (COMP*)tx_log, 1, samples_per_frame*NFRAMES,  samples_per_frame*NFRAMES);
+    octave_save_complex(fout, "rx_log_c", (COMP*)rx_log, 1, samples_per_frame*NFRAMES,  samples_per_frame*NFRAMES);
     octave_save_complex(fout, "rxbuf_in_log_c", (COMP*)rxbuf_in_log, 1, nin_tot, nin_tot);
     octave_save_complex(fout, "rxbuf_log_c", (COMP*)rxbuf_log, 1, OFDM_RXBUF*NFRAMES,  OFDM_RXBUF*NFRAMES);
     octave_save_complex(fout, "rx_sym_log_c", (COMP*)rx_sym_log, (OFDM_NS + 3)*NFRAMES, OFDM_NC + 2, OFDM_NC + 2);
@@ -220,3 +229,33 @@ int main(int argc, char *argv[])
     return 0;
 }
 
+/*---------------------------------------------------------------------------*\
+
+  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;
+}
+