From e75de5b86b9a89e8f574fa5197d6b51b05aae053 Mon Sep 17 00:00:00 2001 From: okcsampson Date: Sun, 9 Jul 2017 04:12:43 +0000 Subject: [PATCH] Add to ofdm testing git-svn-id: https://svn.code.sf.net/p/freetel/code@3285 01035d8c-6547-0410-b346-abe4f91aad63 --- codec2-dev/octave/autotest.m | 30 ++++++++++ codec2-dev/octave/ofdm_lib.m | 9 +++ codec2-dev/octave/tofdm.m | 9 +-- codec2-dev/unittest/tofdm.c | 110 ++++++++++++++++++++++++----------- 4 files changed, 121 insertions(+), 37 deletions(-) diff --git a/codec2-dev/octave/autotest.m b/codec2-dev/octave/autotest.m index 05ff935c..7a83184b 100644 --- a/codec2-dev/octave/autotest.m +++ b/codec2-dev/octave/autotest.m @@ -81,4 +81,34 @@ function check(a, b, test_name, tol, its_an_angle = 0) end endfunction +function check_no_abs(a, b, test_name) + global passes; + global fails; + + tol = 1E-3; + + [m n] = size(a); + if m > n + ll = m; + else + ll = n; + end + + printf("%s", test_name); + for i=1:(25-length(test_name)) + printf("."); + end + printf(": "); + + e = sum(sum(a - b)/ll); + + if e < tol + printf("OK\n"); + passes++; + else + printf("FAIL (%f)\n",e); + fails++; + end +endfunction + diff --git a/codec2-dev/octave/ofdm_lib.m b/codec2-dev/octave/ofdm_lib.m index 6d6b827d..32dd02f1 100644 --- a/codec2-dev/octave/ofdm_lib.m +++ b/codec2-dev/octave/ofdm_lib.m @@ -31,6 +31,15 @@ function two_bits = qpsk_demod(symbol) two_bits = [bit1 bit0]; endfunction +function out = freq_shift(in, foff, Fs) + foff_rect = exp(j*2*pi*foff/Fs); + foff_phase_rect = exp(j*0); + + for r=1:length(in) + foff_phase_rect *= foff_rect; + out(r) = in(r)*foff_phase_rect; + end +endfunction % Correlates the OFDM pilot symbol samples with a window of received % samples to determine the most likely timing offset. Combines two diff --git a/codec2-dev/octave/tofdm.m b/codec2-dev/octave/tofdm.m index f361fdd6..dee21c57 100644 --- a/codec2-dev/octave/tofdm.m +++ b/codec2-dev/octave/tofdm.m @@ -6,7 +6,7 @@ % ------------------------------------------------------------------ Nframes = 30; -sample_clock_offset_ppm = 100; +sample_clock_offset_ppm = 100.0; more off; format; ofdm_lib; @@ -34,6 +34,7 @@ end % Channel simulation ---------------------------------------------- rx_log = sample_clock_offset(tx_log, sample_clock_offset_ppm); +rx_log = freq_shift(rx_log, .01f, Fs); % Rx --------------------------------------------------------------- @@ -64,7 +65,7 @@ for f=1:Nframes % insert samples at end of buffer, set to zero if no samples % available to disable phase estimation on future pilots on last % frame of simulation - + nin = states.nin; lnew = min(Nsam-prx+1,nin); rxbuf_in = zeros(1,nin); @@ -98,7 +99,7 @@ end % Override default path by setting path_to_tofdm = "/your/path/to/tofdm" if exist("path_to_tofdm", "var") == 0 - path_to_tofdm = "../build_linux/unittest/tofdm"; + path_to_tofdm = "/home/ssampson/testing/tofdm"; end system(path_to_tofdm); @@ -141,7 +142,7 @@ stem_sig_and_error(fg++, 111, rx_bits_log_c, rx_bits_log - rx_bits_log_c, 'rx bi % Run through checklist ----------------------------- -check(W, W_c, 'W'); +check_no_abs(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'); diff --git a/codec2-dev/unittest/tofdm.c b/codec2-dev/unittest/tofdm.c index a3fe618c..b339998e 100644 --- a/codec2-dev/unittest/tofdm.c +++ b/codec2-dev/unittest/tofdm.c @@ -39,11 +39,78 @@ #include "codec2_ofdm.h" #include "octave.h" #include "test_bits_ofdm.h" +#include "comp_prim.h" #define NFRAMES 30 #define SAMPLE_CLOCK_OFFSET_PPM 100 -int cohpsk_fs_offset(COMP out[], COMP in[], int n, float sample_rate_ppm); +/*---------------------------------------------------------------------------*\ + + FUNCTION....: fs_offset() + AUTHOR......: David Rowe + DATE CREATED: May 2015 + + Simulates small Fs offset between mod and demod. + +\*---------------------------------------------------------------------------*/ + +static int fs_offset(COMP out[], COMP in[], int n, float sample_rate_ppm) { + float f; + int t1, t2; + + float tin = 0.0f; + int tout = 0; + + while (tin < n) { + t1 = floorf(tin); + t2 = ceilf(tin); + f = tin - t1; + + out[tout].real = (1.0f - f) * in[t1].real + f * in[t2].real; + out[tout].imag = (1.0f - f) * in[t1].imag + f * in[t2].imag; + + tout += 1; + tin += 1.0f + sample_rate_ppm / 1E6f; + } + + return tout; +} + +#ifndef ARM_MATH_CM4 + #define SINF(a) sinf(a) + #define COSF(a) cosf(a) +#else + #define SINF(a) arm_sin_f32(a) + #define COSF(a) arm_cos_f32(a) +#endif + +/*---------------------------------------------------------------------------*\ + + FUNCTION....: freq_shift() + AUTHOR......: David Rowe + DATE CREATED: 26/4/2012 + + Frequency shift modem signal. The use of complex input and output allows + single sided frequency shifting (no images). + +\*---------------------------------------------------------------------------*/ + +static void freq_shift(COMP rx_fdm_fcorr[], COMP rx_fdm[], float foff, COMP *foff_phase_rect, int nin) { + float temp = (TAU * foff / OFDM_FS); + COMP foff_rect = { COSF(temp), SINF(temp) }; + int i; + + for (i = 0; i < nin; i++) { + *foff_phase_rect = cmult(*foff_phase_rect, foff_rect); + rx_fdm_fcorr[i] = cmult(rx_fdm[i], *foff_phase_rect); + } + + /* normalise digital oscillator as the magnitude can drift over time */ + + float mag = cabsolute(*foff_phase_rect); + foff_phase_rect->real /= mag; + foff_phase_rect->imag /= mag; +} int main(int argc, char *argv[]) { @@ -74,7 +141,8 @@ int main(int argc, char *argv[]) FILE *fout; int f,i,j; - ofdm = ofdm_create(); assert(ofdm != NULL); + ofdm = ofdm_create(); + assert(ofdm != NULL); /* Main Loop ---------------------------------------------------------------------*/ @@ -99,7 +167,13 @@ int main(int argc, char *argv[]) Channel \*---------------------------------------------------------*/ - cohpsk_fs_offset(rx_log, tx_log, samples_per_frame*NFRAMES, SAMPLE_CLOCK_OFFSET_PPM); + fs_offset(rx_log, tx_log, samples_per_frame*NFRAMES, SAMPLE_CLOCK_OFFSET_PPM); + + float foff = 0.01f; + COMP foff_phase_rect = {1.0f, 0.0f}; + + freq_shift(rx_log, rx_log, foff, &foff_phase_rect, samples_per_frame * NFRAMES); + /* --------------------------------------------------------*\ Demod @@ -229,33 +303,3 @@ 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