From 74c15321a10c5ee55c5ddb0f07f3af7105afd731 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Thu, 22 Jun 2017 21:59:17 +0000 Subject: [PATCH] added sample clock offset to simulation, looks good! git-svn-id: https://svn.code.sf.net/p/freetel/code@3236 01035d8c-6547-0410-b346-abe4f91aad63 --- codec2-dev/octave/sample_clock_offset.m | 21 +++++++++++ codec2-dev/octave/tofdm.m | 21 ++++++++--- codec2-dev/unittest/tofdm.c | 49 ++++++++++++++++++++++--- 3 files changed, 80 insertions(+), 11 deletions(-) create mode 100644 codec2-dev/octave/sample_clock_offset.m diff --git a/codec2-dev/octave/sample_clock_offset.m b/codec2-dev/octave/sample_clock_offset.m new file mode 100644 index 00000000..51691782 --- /dev/null +++ b/codec2-dev/octave/sample_clock_offset.m @@ -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 + diff --git a/codec2-dev/octave/tofdm.m b/codec2-dev/octave/tofdm.m index 0abb1780..f361fdd6 100644 --- a/codec2-dev/octave/tofdm.m +++ b/codec2-dev/octave/tofdm.m @@ -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'); + diff --git a/codec2-dev/unittest/tofdm.c b/codec2-dev/unittest/tofdm.c index 78638ea2..a3fe618c 100644 --- a/codec2-dev/unittest/tofdm.c +++ b/codec2-dev/unittest/tofdm.c @@ -40,7 +40,10 @@ #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; irxbuf[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; iW, 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; +} + -- 2.25.1