From: baobrien Date: Tue, 9 Jan 2018 06:50:49 +0000 (+0000) Subject: Work on removing constants from ofdm; cleaning up test framework X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=0dbff0945e208384ffcc37cf3e6b2426fca8b971;p=freetel-svn-tracking.git Work on removing constants from ofdm; cleaning up test framework git-svn-id: https://svn.code.sf.net/p/freetel/code@3389 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/codec2-dev/octave/autotest.m b/codec2-dev/octave/autotest.m index 7a83184b..624d35a1 100644 --- a/codec2-dev/octave/autotest.m +++ b/codec2-dev/octave/autotest.m @@ -44,7 +44,7 @@ function plot_sig_and_error(plotnum, subplotnum, sig, error, titlestr, axisvec) endfunction -function check(a, b, test_name, tol, its_an_angle = 0) +function pass = check(a, b, test_name, tol, its_an_angle = 0) global passes; global fails; @@ -74,14 +74,16 @@ function check(a, b, test_name, tol, its_an_angle = 0) if e < tol printf("OK\n"); + pass = true; passes++; else printf("FAIL (%f)\n",e); + pass = false; fails++; end endfunction -function check_no_abs(a, b, test_name) +function pass = check_no_abs(a, b, test_name) global passes; global fails; @@ -103,9 +105,11 @@ function check_no_abs(a, b, test_name) e = sum(sum(a - b)/ll); if e < tol + pass = true; printf("OK\n"); passes++; else + pass = false; printf("FAIL (%f)\n",e); fails++; end diff --git a/codec2-dev/octave/tofdm.m b/codec2-dev/octave/tofdm.m index 73b99fea..7fab0858 100644 --- a/codec2-dev/octave/tofdm.m +++ b/codec2-dev/octave/tofdm.m @@ -4,156 +4,164 @@ % Octave script for comparing Octave and C versions of OFDZM modem % ------------------------------------------------------------------ +1; -Nframes = 30; -sample_clock_offset_ppm = 100; -foff_hz = 0.5; +function pass = run_ofdm_test(Nframes,sample_clock_offset_ppm,foff_hz) + %Nframes = 30; + %sample_clock_offset_ppm = 100; + %foff_hz = 5; -more off; format; -ofdm_lib; -autotest; + more off; format; + ofdm_lib; + autotest; -% --------------------------------------------------------------------- -% Run Octave version -% --------------------------------------------------------------------- + % --------------------------------------------------------------------- + % Run Octave version + % --------------------------------------------------------------------- -Ts = 0.018; Tcp = 0.002; Rs = 1/Ts; bps = 2; Nc = 16; Ns = 8; -states = ofdm_init(bps, Rs, Tcp, Ns, Nc); -ofdm_load_const; + Ts = 0.018; Tcp = 0.002; Rs = 1/Ts; bps = 2; Nc = 16; Ns = 8; + states = ofdm_init(bps, Rs, Tcp, Ns, Nc); + ofdm_load_const; -rand('seed',1); -tx_bits = round(rand(1,Nbitsperframe)); + rand('seed',1); + tx_bits = round(rand(1,Nbitsperframe)); -% Run tx loop + % Run tx loop -tx_bits_log = []; tx_log = []; -for f=1:Nframes - tx_bits_log = [tx_bits_log tx_bits]; - tx_log = [tx_log ofdm_mod(states, tx_bits)]; -end - -% Channel simulation ---------------------------------------------- + tx_bits_log = []; tx_log = []; + for f=1:Nframes + tx_bits_log = [tx_bits_log tx_bits]; + tx_log = [tx_log ofdm_mod(states, tx_bits)]; + end -rx_log = sample_clock_offset(tx_log, sample_clock_offset_ppm); -rx_log = freq_shift(rx_log, foff_hz, Fs); + % Channel simulation ---------------------------------------------- -% Rx --------------------------------------------------------------- + rx_log = sample_clock_offset(tx_log, sample_clock_offset_ppm); + rx_log = freq_shift(rx_log, foff_hz, Fs); -% Init rx with ideal timing so we can test with timing estimation disabled + % Rx --------------------------------------------------------------- -Nsam = length(rx_log); -prx = 1; -nin = Nsamperframe+2*(M+Ncp); -states.rxbuf(Nrxbuf-nin+1:Nrxbuf) = rx_log(prx:nin); -prx += nin; + % Init rx with ideal timing so we can test with timing estimation disabled -rxbuf_log = []; rxbuf_in_log = []; rx_sym_log = []; foff_hz_log = []; -timing_est_log = []; sample_point_log = []; -phase_est_pilot_log = []; rx_amp_log = []; -rx_np_log = []; rx_bits_log = []; + Nsam = length(rx_log); + prx = 1; + nin = Nsamperframe+2*(M+Ncp); + states.rxbuf(Nrxbuf-nin+1:Nrxbuf) = rx_log(prx:nin); + prx += nin; -states.timing_en = 1; -states.foff_est_en = 1; -states.phase_est_en = 1; + rxbuf_log = []; rxbuf_in_log = []; rx_sym_log = []; foff_hz_log = []; + timing_est_log = []; sample_point_log = []; + phase_est_pilot_log = []; rx_amp_log = []; + rx_np_log = []; rx_bits_log = []; -if states.timing_en == 0 - % manually set ideal timing instant - states.sample_point = Ncp; -end + states.timing_en = 1; + states.foff_est_en = 1; + states.phase_est_en = 1; -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); - %printf("nin: %d prx: %d lnew: %d\n", nin, prx, lnew); - if lnew - rxbuf_in(1:lnew) = rx_log(prx:prx+lnew-1); + if states.timing_en == 0 + % manually set ideal timing instant + states.sample_point = Ncp; end - prx += lnew; - - [rx_bits states aphase_est_pilot_log arx_np arx_amp] = ofdm_demod(states, rxbuf_in); - - % log some states for comparison to C - - rxbuf_in_log = [rxbuf_in_log rxbuf_in]; - rxbuf_log = [rxbuf_log states.rxbuf]; - rx_sym_log = [rx_sym_log; states.rx_sym]; - phase_est_pilot_log = [phase_est_pilot_log; aphase_est_pilot_log]; - rx_amp_log = [rx_amp_log arx_amp]; - foff_hz_log = [foff_hz_log; states.foff_est_hz]; - timing_est_log = [timing_est_log; states.timing_est]; - sample_point_log = [sample_point_log; states.sample_point]; - rx_np_log = [rx_np_log arx_np]; - rx_bits_log = [rx_bits_log rx_bits]; + + 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 -end + nin = states.nin; + lnew = min(Nsam-prx+1,nin); + rxbuf_in = zeros(1,nin); + %printf("nin: %d prx: %d lnew: %d\n", nin, prx, lnew); + if lnew + rxbuf_in(1:lnew) = rx_log(prx:prx+lnew-1); + end + prx += lnew; + + [rx_bits states aphase_est_pilot_log arx_np arx_amp] = ofdm_demod(states, rxbuf_in); + + % log some states for comparison to C + + rxbuf_in_log = [rxbuf_in_log rxbuf_in]; + rxbuf_log = [rxbuf_log states.rxbuf]; + rx_sym_log = [rx_sym_log; states.rx_sym]; + phase_est_pilot_log = [phase_est_pilot_log; aphase_est_pilot_log]; + rx_amp_log = [rx_amp_log arx_amp]; + foff_hz_log = [foff_hz_log; states.foff_est_hz]; + timing_est_log = [timing_est_log; states.timing_est]; + sample_point_log = [sample_point_log; states.sample_point]; + rx_np_log = [rx_np_log arx_np]; + rx_bits_log = [rx_bits_log rx_bits]; + + end -% --------------------------------------------------------------------- -% Run C version and plot Octave and C states and differences -% --------------------------------------------------------------------- + % --------------------------------------------------------------------- + % Run C version and plot Octave and C states and differences + % --------------------------------------------------------------------- -% Override default path by setting path_to_tofdm = "/your/path/to/tofdm" + % 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"; -end -system(path_to_tofdm); + if exist("path_to_tofdm", "var") == 0 + path_to_tofdm = "../build_linux/unittest/tofdm"; + end + system(path_to_tofdm); -load tofdm_out.txt; + load tofdm_out.txt; + % Generated with modem probe thing + load ofdm_test.txt; -fg = 1; -figure(fg++); clf; plot(rx_np_log,'+'); title('Octave Scatter Diagram'); axis([-1.5 1.5 -1.5 1.5]); -figure(fg++); clf; plot(rx_np_log_c,'+'); title('C Scatter Diagram'); axis([-1.5 1.5 -1.5 1.5]); + fg = 1; + figure(fg++); clf; plot(rx_np_log,'+'); title('Octave Scatter Diagram'); axis([-1.5 1.5 -1.5 1.5]); + figure(fg++); clf; plot(rx_np_log_c,'+'); title('C Scatter Diagram'); axis([-1.5 1.5 -1.5 1.5]); -stem_sig_and_error(fg++, 111, tx_bits_log_c, tx_bits_log - tx_bits_log_c, 'tx bits', [1 length(tx_bits_log) -1.5 1.5]) + stem_sig_and_error(fg++, 111, tx_bits_log_c, tx_bits_log - tx_bits_log_c, 'tx bits', [1 length(tx_bits_log) -1.5 1.5]) -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(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(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]) + 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]) -stem_sig_and_error(fg, 211, real(rxbuf_log_c), real(rxbuf_log - rxbuf_log_c), 'rxbuf re', [1 length(rxbuf_log_c) -0.1 0.1]) -stem_sig_and_error(fg++, 212, imag(rxbuf_log_c), imag(rxbuf_log - rxbuf_log_c), 'rxbuf im', [1 length(rxbuf_log_c) -0.1 0.1]) + stem_sig_and_error(fg, 211, real(rxbuf_log_c), real(rxbuf_log - rxbuf_log_c), 'rxbuf re', [1 length(rxbuf_log_c) -0.1 0.1]) + stem_sig_and_error(fg++, 212, imag(rxbuf_log_c), imag(rxbuf_log - rxbuf_log_c), 'rxbuf im', [1 length(rxbuf_log_c) -0.1 0.1]) -stem_sig_and_error(fg, 211, real(rx_sym_log_c), real(rx_sym_log - rx_sym_log_c), 'rx sym re', [1 length(rx_sym_log_c) -1.5 1.5]) -stem_sig_and_error(fg++, 212, imag(rx_sym_log_c), imag(rx_sym_log - rx_sym_log_c), 'rx sym im', [1 length(rx_sym_log_c) -1.5 1.5]) + stem_sig_and_error(fg, 211, real(rx_sym_log_c), real(rx_sym_log - rx_sym_log_c), 'rx sym re', [1 length(rx_sym_log_c) -1.5 1.5]) + stem_sig_and_error(fg++, 212, imag(rx_sym_log_c), imag(rx_sym_log - rx_sym_log_c), 'rx sym im', [1 length(rx_sym_log_c) -1.5 1.5]) -% for angles pi and -pi are the same + % for angles pi and -pi are the same -d = phase_est_pilot_log - phase_est_pilot_log_c; d = angle(exp(j*d)); + d = phase_est_pilot_log - phase_est_pilot_log_c; d = angle(exp(j*d)); -stem_sig_and_error(fg, 211, phase_est_pilot_log_c, d, 'phase est pilot', [1 length(phase_est_pilot_log_c) -1.5 1.5]) -stem_sig_and_error(fg++, 212, rx_amp_log_c, rx_amp_log - rx_amp_log_c, 'rx amp', [1 length(rx_amp_log_c) -1.5 1.5]) + stem_sig_and_error(fg, 211, phase_est_pilot_log_c, d, 'phase est pilot', [1 length(phase_est_pilot_log_c) -1.5 1.5]) + stem_sig_and_error(fg++, 212, rx_amp_log_c, rx_amp_log - rx_amp_log_c, 'rx amp', [1 length(rx_amp_log_c) -1.5 1.5]) -stem_sig_and_error(fg++, 111, foff_hz_log_c, (foff_hz_log - foff_hz_log_c), 'foff hz', [1 length(foff_hz_log_c) -1.5 1.5]) + stem_sig_and_error(fg++, 111, foff_hz_log_c, (foff_hz_log - foff_hz_log_c), 'foff hz', [1 length(foff_hz_log_c) -1.5 1.5]) -stem_sig_and_error(fg, 211, timing_est_log_c, (timing_est_log - timing_est_log_c), 'timing est', [1 length(timing_est_log_c) -1.5 1.5]) -stem_sig_and_error(fg++, 212, sample_point_log_c, (sample_point_log - sample_point_log_c), 'sample point', [1 length(sample_point_log_c) -1.5 1.5]) + stem_sig_and_error(fg, 211, timing_est_log_c, (timing_est_log - timing_est_log_c), 'timing est', [1 length(timing_est_log_c) -1.5 1.5]) + stem_sig_and_error(fg++, 212, sample_point_log_c, (sample_point_log - sample_point_log_c), 'sample point', [1 length(sample_point_log_c) -1.5 1.5]) -stem_sig_and_error(fg++, 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(fg++, 111, rx_bits_log_c, rx_bits_log - rx_bits_log_c, 'rx bits', [1 length(rx_bits_log) -1.5 1.5]) -% Run through checklist ----------------------------- + % Run through checklist ----------------------------- + pass = true; + pass = check_no_abs(W, W_c, 'W') && pass; + pass = check(tx_bits_log, tx_bits_log_c, 'tx_bits') && pass; + pass = check(tx_log, tx_log_c, 'tx') && pass; + pass = check(rx_log, rx_log_c, 'rx') && pass; + pass = check(rxbuf_in_log, rxbuf_in_log_c, 'rxbuf in') && pass; + pass = check(rxbuf_log, rxbuf_log_c, 'rxbuf') && pass; + pass = check(rx_sym_log, rx_sym_log_c, 'rx_sym') && pass; + pass = check(phase_est_pilot_log, phase_est_pilot_log_c, 'phase_est_pilot', tol=1E-3, its_an_angle=1) && pass; + pass = check(rx_amp_log, rx_amp_log_c, 'rx_amp') && pass; + pass = check(timing_est_log, timing_est_log_c', 'timing_est') && pass; + pass = check(sample_point_log, sample_point_log_c, 'sample_point') && pass; + pass = check(foff_hz_log, foff_hz_log_c', 'foff_est_hz') && pass; + pass = check(rx_bits_log, rx_bits_log_c, 'rx_bits') && pass; + -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'); -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'); -check(phase_est_pilot_log, phase_est_pilot_log_c, 'phase_est_pilot', tol=1E-3, its_an_angle=1); -check(rx_amp_log, rx_amp_log_c, 'rx_amp'); -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'); +end +run_ofdm_test(30,100,.1) \ No newline at end of file diff --git a/codec2-dev/src/codec2_ofdm.h b/codec2-dev/src/codec2_ofdm.h index b335df88..fc1833bd 100644 --- a/codec2-dev/src/codec2_ofdm.h +++ b/codec2-dev/src/codec2_ofdm.h @@ -55,8 +55,8 @@ void ofdm_destroy(struct OFDM *); void ofdm_mod(struct OFDM *, COMP *, const int *); void ofdm_demod(struct OFDM *, int *, COMP *); int ofdm_get_nin(struct OFDM *); -int ofdm_get_samples_per_frame(void); -int ofdm_get_max_samples_per_frame(void); +int ofdm_get_samples_per_frame(struct OFDM *ofdm); +int ofdm_get_max_samples_per_frame(struct OFDM *ofdm); /* option setters */ diff --git a/codec2-dev/src/modem_probe.c b/codec2-dev/src/modem_probe.c index 884a1a85..b4a61656 100644 --- a/codec2-dev/src/modem_probe.c +++ b/codec2-dev/src/modem_probe.c @@ -160,6 +160,7 @@ probe_trace_info * modem_probe_get_trace(char * tracename){ } + void modem_probe_samp_i_int(char * tracename,int32_t samp[],size_t cnt){ probe_trace_info *pti; datlink *ndat; diff --git a/codec2-dev/src/modem_probe.h b/codec2-dev/src/modem_probe.h index 2faada13..d5b76523 100644 --- a/codec2-dev/src/modem_probe.h +++ b/codec2-dev/src/modem_probe.h @@ -29,9 +29,9 @@ #define __MODEMPROBE_H #include #include +#include #include "comp.h" - #ifdef MODEMPROBE_ENABLE /* Internal functions */ @@ -88,6 +88,16 @@ static inline void modem_probe_samp_c(char *tracename,COMP samp[],size_t cnt){ modem_probe_samp_c_int(tracename,samp,cnt); } +/* + * Save some number of complex samples to a named trace + * char *tracename - name of trace being saved to + * float complex samp[] - int samples + * size_t cnt - how many samples to save + */ +static inline void modem_probe_samp_cft(char *tracename,complex float samp[],size_t cnt){ + modem_probe_samp_c_int(tracename,(COMP*)samp,cnt); +} + #else static inline void modem_probe_init(char *modname,char *runname){ @@ -110,6 +120,10 @@ static inline void modem_probe_samp_c(char *name,COMP samp[],size_t cnt){ return; } +static inline void modem_probe_samp_cft(char *name,complex float samp[],size_t cnt){ + return; +} + #endif #endif diff --git a/codec2-dev/src/ofdm.c b/codec2-dev/src/ofdm.c index 52079af4..cdaa9c0b 100644 --- a/codec2-dev/src/ofdm.c +++ b/codec2-dev/src/ofdm.c @@ -38,10 +38,26 @@ #include "ofdm_internal.h" #include "codec2_ofdm.h" #include "kiss_fft.h" +#include "modem_probe.h" /* Concrete definition of 700D parameters */ -const struct OFDM_CONFIG OFDM_CONFIG_700D_C = -{.a = 0}; +const struct OFDM_CONFIG OFDM_CONFIG_700D_C = { + .Nc = 16, + .Ts = -1, + .Rs = -1, + .Fs = 8000, + .bps = 2, + .Tcp = -1, + .Ns = 8, + .M = 144, + .Ncp = 16, + .FtWindowWidth = 11, + .BitsPerFrame = 224, + .SampsPerFrame = 1280, + .SampsPerFrameMax = 1320, + .RxBufSize = 4320, + .RowsPerFrame = 7 +}; /* Pointer to 700D config */ const struct OFDM_CONFIG * OFDM_CONFIG_700D = &OFDM_CONFIG_700D_C; @@ -106,12 +122,14 @@ static void qpsk_demod(complex float symbol, int *bits) { static void idft(struct OFDM *ofdm, complex float *result, complex float *vector) { int row, col; + int Nc = ofdm->config.Nc; + int M = ofdm->config.M; - for (row = 0; row < OFDM_M; row++) { + for (row = 0; row < M; row++) { result[row] = 0.0f + 0.0f * I; - for (col = 0; col < (OFDM_NC + 2); col++) { - result[row] = result[row] + (vector[col] * (ofdm->W[col][row] / (float) OFDM_M)); /* complex result */ + for (col = 0; col < (Nc + 2); col++) { + result[row] = result[row] + (vector[col] * (ofdm->W[col][row] / (float) M)); /* complex result */ } } } @@ -120,11 +138,13 @@ static void idft(struct OFDM *ofdm, complex float *result, complex float *vector static void dft(struct OFDM *ofdm, complex float *result, complex float *vector) { int row, col; + int Nc = ofdm->config.Nc; + int M = ofdm->config.M; - for (col = 0; col < (OFDM_NC + 2); col++) { + for (col = 0; col < (Nc + 2); col++) { result[col] = 0.0f + 0.0f * I; - for (row = 0; row < OFDM_M; row++) { + for (row = 0; row < M; row++) { result[col] = result[col] + (vector[row] * conjf(ofdm->W[col][row])); /* complex result */ } } @@ -150,16 +170,27 @@ static complex float vector_sum(complex float *a, int num_elements) { static int coarse_sync(struct OFDM *ofdm, complex float *rx, int length) { complex float csam; - int Ncorr = length - (OFDM_SAMPLESPERFRAME + (OFDM_M + OFDM_NCP)); - int Fs = OFDM_FS; - int SFrame = OFDM_SAMPLESPERFRAME; + int Fs = ofdm->config.Fs; + int Rs = ofdm->config.Rs; + int Bps = ofdm->config.bps; + int Nc = ofdm->config.Nc; + int M = ofdm->config.M; + int Ncp = ofdm->config.Ncp; + int Ns = ofdm->config.Ns; + int RowsPerFrame = ofdm->config.RowsPerFrame; + int SampsPerFrame = ofdm->config.SampsPerFrame; + int Fcenter = ofdm->config.Fcenter; + int Ncorr = length - (SampsPerFrame + (M + Ncp)); + + int SFrame = SampsPerFrame; float corr[Ncorr]; + int NPSamp = M + Ncp; int i, j; for (i = 0; i < Ncorr; i++) { complex float temp = 0.0f + 0.0f * I; - for (j = 0; j < (OFDM_M + OFDM_NCP); j++) { + for (j = 0; j < (M + Ncp); j++) { csam = conjf(ofdm->pilot_samples[j]); temp = temp + (rx[i + j] * csam); temp = temp + (rx[i + j + SFrame] * csam); @@ -185,8 +216,53 @@ static int coarse_sync(struct OFDM *ofdm, complex float *rx, int length) { kiss_fft_cfg fftcfg = kiss_fft_alloc(Fs,0,NULL,NULL); complex float fft_in[Fs]; complex float fft_out[Fs]; - - + float C[Fs]; + /* Zero FFT input array */ + for(i = 0; i < Fs; i++){ + fft_in[i] = 0; + } + /* shift and copy in NPsam samples to front of buffer for FFT'ing */ + for(i = 0; i < NPSamp; i++){ + fft_in[i] = rx[i + t_est] * conjf(ofdm->pilot_samples[i]); + } + kiss_fft(fftcfg,(kiss_fft_cpx*)fft_in,(kiss_fft_cpx*)fft_out); + + /* Copy into output corr array, taking magnitude */ + /* TODO: May be able to skip sqrt() in abs, since we're just looking for a maximum point down the line */ + for(i = 0; i < Fs; i++){ + C[i] = cabsf(fft_out[i]); + } + + /* shift and copy in NPsam samples to front of buffer for FFT'ing */ + for(i = 0; i < NPSamp; i++){ + fft_in[i] = rx[i + t_est + SFrame] * conjf(ofdm->pilot_samples[i]); + } + kiss_fft(fftcfg,(kiss_fft_cpx*)fft_in,(kiss_fft_cpx*)fft_out); + + /* Add into output corr array */ + for(i = 0; i < Fs; i++){ + C[i] += cabsf(fft_out[i]); + } + + int fmax = 30; + int pmax_i,nmax_i; + float pmax,nmax; + float foff_est; + pmax_i = nmax_i = 0; + pmax = nmax = 0; + /* Search the positive and negative sides of the FFT to +/-fmax for peak */ + for(i = 0; i < fmax; i++){ + if(C[i] > pmax){ + pmax = C[i]; + pmax_i = i; + } + if(C[Fs-i-1] > nmax){ + nmax = C[i]; + nmax_i = i; + } + } + foff_est = (pmax > nmax) ? pmax_i : (nmax_i - fmax); + fprintf(stderr,"foff_est is %f\n",foff_est); return t_est; } @@ -199,62 +275,109 @@ static int coarse_sync(struct OFDM *ofdm, complex float *rx, int length) { static void ofdm_txframe(struct OFDM *ofdm, complex float tx[OFDM_SAMPLESPERFRAME], complex float *tx_sym_lin) { - complex float aframe[OFDM_NS][OFDM_NC + 2]; - complex float asymbol[OFDM_M]; - complex float asymbol_cp[OFDM_M + OFDM_NCP]; + + int Fs = ofdm->config.Fs; + int Rs = ofdm->config.Rs; + int Bps = ofdm->config.bps; + int Nc = ofdm->config.Nc; + int M = ofdm->config.M; + int Ncp = ofdm->config.Ncp; + int Ns = ofdm->config.Ns; + int RowsPerFrame = ofdm->config.RowsPerFrame; + int SampsPerFrame = ofdm->config.SampsPerFrame; + int Fcenter = ofdm->config.Fcenter; + + complex float aframe[Ns][Nc + 2]; + complex float asymbol[M]; + complex float asymbol_cp[M + Ncp]; int i, j, k, m; /* initialize aframe to complex zero */ - for (i = 0; i < OFDM_NS; i++) { - for (j = 0; j < (OFDM_NC + 2); j++) { + for (i = 0; i < Ns; i++) { + for (j = 0; j < (Nc + 2); j++) { aframe[i][j] = 0.0f + 0.0f * I; } } /* copy in a row of complex pilots to first row */ - for (i = 0; i < (OFDM_NC + 2); i++) { + for (i = 0; i < (Nc + 2); i++) { aframe[0][i] = ofdm->pilots[i]; } /* Place symbols in multi-carrier frame with pilots */ /* This will place boundary values of complex zero around data */ - for (i = 1; i <= OFDM_ROWSPERFRAME; i++) { + for (i = 1; i <= RowsPerFrame; i++) { /* copy in the Nc complex values with [0 Nc 0] or (Nc + 2) total */ - for (j = 1; j < (OFDM_NC + 1); j++) { - aframe[i][j] = tx_sym_lin[((i - 1) * OFDM_NC) + (j - 1)]; + for (j = 1; j < (Nc + 1); j++) { + aframe[i][j] = tx_sym_lin[((i - 1) * Nc) + (j - 1)]; } } /* OFDM up-convert symbol by symbol so we can add CP */ - for (i = 0, m = 0; i < OFDM_NS; i++, m += (OFDM_M + OFDM_NCP)) { + for (i = 0, m = 0; i < Ns; i++, m += (M + Ncp)) { idft(ofdm, asymbol, aframe[i]); /* Copy the last Ncp columns to the front */ - for (j = (OFDM_M - OFDM_NCP), k = 0; j < OFDM_M; j++, k++) { + for (j = (M - Ncp), k = 0; j < M; j++, k++) { asymbol_cp[k] = asymbol[j]; } /* Now copy the whole row after it */ - for (j = OFDM_NCP, k = 0; k < OFDM_M; j++, k++) { + for (j = Ncp, k = 0; k < M; j++, k++) { asymbol_cp[j] = asymbol[k]; } /* Now move row to the tx reference */ - for (j = 0; j < (OFDM_M + OFDM_NCP); j++) { + for (j = 0; j < (M + Ncp); j++) { tx[m + j] = asymbol_cp[j]; } } } +/* + * Utility function to allocate a 2d array of dimension + * [sx][sy] with elements of elem size + */ +void **alloc_doubleary(size_t sx,size_t sy,size_t elem){ + size_t i; + char ** ary = malloc(sizeof(void*) * sx); + if(ary == NULL){ + return NULL; + } + *ary = malloc(elem * sx * sy); + if(*ary == NULL){ + free(ary); + return NULL; + } + for(i=0; iconfig,(void*)config,sizeof(struct OFDM_CONFIG)); + int Fs = ofdm->config.Fs; + int Rs = ofdm->config.Rs; + int Bps = ofdm->config.bps; + int Nc = ofdm->config.Nc; + int M = ofdm->config.M; + int Ncp = ofdm->config.Ncp; + int Ns = ofdm->config.Ns; + int RowsPerFrame = ofdm->config.RowsPerFrame; + int SampsPerFrame = ofdm->config.SampsPerFrame; + int Fcenter = ofdm->config.Fcenter; + + /* Allocate various buffers */ + /* TODO: cleanup after failed malloc */ + ofdm->pilot_samples = malloc(sizeof(complex float) * (M + Ncp)); + ofdm->pilots = malloc(sizeof(complex float) * (Nc+2)); + ofdm->rxbuf = malloc(sizeof(complex float) * ofdm->config.RxBufSize); + ofdm->w = malloc(sizeof(float) * (Nc+2)); + ofdm->rx_amp = malloc(sizeof(float) * RowsPerFrame * Nc); + ofdm->aphase_est_pilot_log = malloc(sizeof(float) * RowsPerFrame * Nc); /* store complex BPSK pilot symbols */ - for (i = 0; i < (OFDM_NC + 2); i++) { + for (i = 0; i < (Nc + 2); i++) { ofdm->pilots[i] = ((float) pilotvalues[i]) + 0.0f * I; } /* carrier tables for up and down conversion */ - int Nlower = floorf((OFDM_CENTRE - OFDM_RS * (OFDM_NC / 2)) / OFDM_RS); + int Nlower = floorf((OFDM_CENTRE - OFDM_RS * (Nc / 2)) / OFDM_RS); - for (i = 0, j = Nlower; i < (OFDM_NC + 2); i++, j++) { + for (i = 0, j = Nlower; i < (Nc + 2); i++, j++) { /* * 2 * pi * j/144 j=19..36 * j = 1 kHz to 2 kHz (1.5 kHz center) @@ -294,14 +436,18 @@ struct OFDM *ofdm_create(const struct OFDM_CONFIG * config) { ofdm->w[i] = TAU * (float) j / (OFDM_FS / OFDM_RS); } - for (i = 0; i < (OFDM_NC + 2); i++) { - for (j = 0; j < OFDM_M; j++) { + ofdm->W = (complex float **) alloc_doubleary(Nc+2,M,sizeof(complex float)); + ofdm->rx_sym = (complex float **) alloc_doubleary(Ns+3,Nc+2,sizeof(complex float)); + + for (i = 0; i < (Nc + 2); i++) { + + for (j = 0; j < M; j++) { ofdm->W[i][j] = cexpf(I * ofdm->w[i] * j); } } - for (i = 0; i < (OFDM_NS + 3); i++) { - for (j = 0; j < (OFDM_NC + 2); j++) { + for (i = 0; i < (Ns + 3); i++) { + for (j = 0; j < (Nc + 2); j++) { ofdm->rx_sym[i][j] = 0.0f + 0.0f * I; } } @@ -317,11 +463,11 @@ struct OFDM *ofdm_create(const struct OFDM_CONFIG * config) { ofdm->foff_est_hz = 0.0f; ofdm->sample_point = 0; ofdm->timing_est = 0; - ofdm->nin = OFDM_SAMPLESPERFRAME; + ofdm->nin = SampsPerFrame; /* create the OFDM waveform */ - complex float temp[OFDM_M]; + complex float temp[M]; idft(ofdm, temp, ofdm->pilots); @@ -331,13 +477,13 @@ struct OFDM *ofdm_create(const struct OFDM_CONFIG * config) { /* first copy the last Cyclic Prefix (CP) values */ - for (i = 0, j = (OFDM_M - OFDM_NCP); i < OFDM_NCP; i++, j++) { + for (i = 0, j = (M - Ncp); i < Ncp; i++, j++) { ofdm->pilot_samples[i] = temp[j]; } /* Now copy the whole thing after the above */ - for (i = OFDM_NCP, j = 0; j < OFDM_M; i++, j++) { + for (i = Ncp, j = 0; j < M; i++, j++) { ofdm->pilot_samples[i] = temp[j]; } @@ -352,12 +498,12 @@ int ofdm_get_nin(struct OFDM *ofdm) { return ofdm->nin; } -int ofdm_get_samples_per_frame() { - return OFDM_SAMPLESPERFRAME; +int ofdm_get_samples_per_frame(struct OFDM *ofdm) { + return ofdm->config.SampsPerFrame; } -int ofdm_get_max_samples_per_frame() { - return OFDM_MAX_SAMPLESPERFRAME; +int ofdm_get_max_samples_per_frame(struct OFDM *ofdm) { + return ofdm->config.SampsPerFrameMax; } void ofdm_set_verbose(struct OFDM *ofdm, int level) { @@ -369,7 +515,7 @@ void ofdm_set_timing_enable(struct OFDM *ofdm, bool val) { if (ofdm->timing_en == false) { /* manually set ideal timing instant */ - ofdm->sample_point = (OFDM_NCP - 1); + ofdm->sample_point = (ofdm->config.Ncp - 1); } } @@ -392,19 +538,32 @@ void ofdm_set_off_est_hz(struct OFDM *ofdm, float val) { */ void ofdm_mod(struct OFDM *ofdm, COMP result[OFDM_SAMPLESPERFRAME], const int *tx_bits) { - int length = OFDM_BITSPERFRAME / OFDM_BPS; - complex float tx[OFDM_SAMPLESPERFRAME]; + + int Fs = ofdm->config.Fs; + int Rs = ofdm->config.Rs; + int Bps = ofdm->config.bps; + int Nc = ofdm->config.Nc; + int M = ofdm->config.M; + int Ncp = ofdm->config.Ncp; + int Ns = ofdm->config.Ns; + int RowsPerFrame = ofdm->config.RowsPerFrame; + int SampsPerFrame = ofdm->config.SampsPerFrame; + int BitsPerFrame = ofdm->config.BitsPerFrame; + int Fcenter = ofdm->config.Fcenter; + + int length = BitsPerFrame / Bps; + complex float tx[SampsPerFrame]; complex float tx_sym_lin[length]; int dibit[2]; int s, i; - if (OFDM_BPS == 1) { + if (Bps == 1) { /* Here we will have Nbitsperframe / 1 */ for (s = 0; s < length; s++) { tx_sym_lin[s] = (float) (2 * tx_bits[s] - 1) + 0.0f * I; } - } else if (OFDM_BPS == 2) { + } else if (Bps == 2) { /* Here we will have Nbitsperframe / 2 */ for (s = 0, i = 0; i < length; s += 2, i++) { @@ -418,7 +577,7 @@ void ofdm_mod(struct OFDM *ofdm, COMP result[OFDM_SAMPLESPERFRAME], const int *t /* convert to comp */ - for (i = 0; i < OFDM_SAMPLESPERFRAME; i++) { + for (i = 0; i < SampsPerFrame; i++) { result[i].real = crealf(tx[i]); result[i].imag = cimagf(tx[i]); } @@ -432,20 +591,35 @@ void ofdm_mod(struct OFDM *ofdm, COMP result[OFDM_SAMPLESPERFRAME], const int *t void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) { complex float aphase_est_pilot_rect; - float aphase_est_pilot[OFDM_NC + 2]; - float aamp_est_pilot[OFDM_NC + 2]; + + int Fs = ofdm->config.Fs; + int Rs = ofdm->config.Rs; + int Bps = ofdm->config.bps; + int Nc = ofdm->config.Nc; + int M = ofdm->config.M; + int Ncp = ofdm->config.Ncp; + int Ns = ofdm->config.Ns; + int RowsPerFrame = ofdm->config.RowsPerFrame; + int SampsPerFrame = ofdm->config.SampsPerFrame; + int FtWindowWidth = ofdm->config.FtWindowWidth; + int BitsPerFrame = ofdm->config.BitsPerFrame; + int Fcenter = ofdm->config.Fcenter; + int RxBufSize = ofdm->config.RxBufSize; + + float aphase_est_pilot[Nc + 2]; + float aamp_est_pilot[Nc + 2]; float freq_err_hz; int i, j, k, rr, st, en, ft_est; /* shift the buffer left based on nin */ - for (i = 0, j = ofdm->nin; i < (OFDM_RXBUF - ofdm->nin); i++, j++) { + for (i = 0, j = ofdm->nin; i < (RxBufSize - ofdm->nin); i++, j++) { ofdm->rxbuf[i] = ofdm->rxbuf[j]; } /* insert latest input samples onto tail of rxbuf */ - for (i = (OFDM_RXBUF - ofdm->nin), j = 0; i < OFDM_RXBUF; i++, j++) { + for (i = (RxBufSize - ofdm->nin), j = 0; i < RxBufSize; i++, j++) { ofdm->rxbuf[i] = rxbuf_in[j].real + rxbuf_in[j].imag * I; } @@ -453,15 +627,15 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) { * get user and calculated freq offset */ - float woff_est = TAU * ofdm->foff_est_hz / OFDM_FS; + float woff_est = TAU * ofdm->foff_est_hz / (float)(Fs); /* update timing estimate -------------------------------------------------- */ if (ofdm->timing_en == true) { /* update timing at start of every frame */ - st = ((OFDM_M + OFDM_NCP) + OFDM_SAMPLESPERFRAME) - floorf(OFDM_FTWINDOWWIDTH / 2) + ofdm->timing_est; - en = st + OFDM_SAMPLESPERFRAME - 1 + (OFDM_M + OFDM_NCP) + OFDM_FTWINDOWWIDTH; + st = ((M + Ncp) + SampsPerFrame) - floorf(FtWindowWidth / 2) + ofdm->timing_est; + en = st + SampsPerFrame - 1 + (M + Nc) + FtWindowWidth; complex float work[(en - st)]; @@ -471,11 +645,12 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) { */ for (i = st, j = 0; i < en; i++, j++) { + /* TODO: Look into reducing cexpf usage */ work[j] = ofdm->rxbuf[i] * cexpf(-I * woff_est * i); } ft_est = coarse_sync(ofdm, work, (en - st)); - ofdm->timing_est += (ft_est - ceilf(OFDM_FTWINDOWWIDTH / 2)); + ofdm->timing_est += (ft_est - ceilf(FtWindowWidth / 2)); if (ofdm->verbose > 1) { fprintf(stdout, " ft_est: %2d timing_est: %2d sample_point: %2d\n", ft_est, ofdm->timing_est, ofdm->sample_point); @@ -483,8 +658,8 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) { /* Black magic to keep sample_point inside cyclic prefix. Or something like that. */ - ofdm->sample_point = max(ofdm->timing_est + (OFDM_NCP / 4), ofdm->sample_point); - ofdm->sample_point = min(ofdm->timing_est + OFDM_NCP, ofdm->sample_point); + ofdm->sample_point = max(ofdm->timing_est + (Ncp / 4), ofdm->sample_point); + ofdm->sample_point = min(ofdm->timing_est + Ncp, ofdm->sample_point); } /* @@ -526,8 +701,8 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) { * The average of the four pilot symbols is our phase estimation. */ - for (i = 0; i < (OFDM_NS + 3); i++) { - for (j = 0; j < (OFDM_NC + 2); j++) { + for (i = 0; i < (Ns + 3); i++) { + for (j = 0; j < (Nc + 2); j++) { ofdm->rx_sym[i][j] = 0.0f + 0.0f * I; } } @@ -536,10 +711,10 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) { * "Previous" pilot symbol is one modem frame above. */ - st = (OFDM_M + OFDM_NCP) + 1 + ofdm->sample_point; - en = st + OFDM_M; + st = (M + Ncp) + 1 + ofdm->sample_point; + en = st + M; - complex float work[OFDM_M]; + complex float work[M]; /* down-convert at current timing instant---------------------------------- */ @@ -575,9 +750,9 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) { * In this routine we also process the current data symbols. */ - for (rr = 0; rr < (OFDM_NS + 1); rr++) { - st = (OFDM_M + OFDM_NCP) + OFDM_SAMPLESPERFRAME + (rr * (OFDM_M + OFDM_NCP)) + 1 + ofdm->sample_point; - en = st + OFDM_M; + for (rr = 0; rr < (Ns + 1); rr++) { + st = (M + Ncp) + SampsPerFrame + (rr * (M + Ncp)) + 1 + ofdm->sample_point; + en = st + M; /* down-convert at current timing instant---------------------------------- */ @@ -624,8 +799,8 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) { * We only want the "future" pilot symbol, to perform the averaging of all pilots. */ - st = (OFDM_M + OFDM_NCP) + (3 * OFDM_SAMPLESPERFRAME) + 1 + ofdm->sample_point; - en = st + OFDM_M; + st = (M + Ncp) + (3 * SampsPerFrame) + 1 + ofdm->sample_point; + en = st + M; /* down-convert at current timing instant---------------------------------- */ @@ -644,7 +819,7 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) { * +----------------------+ */ - dft(ofdm, ofdm->rx_sym[OFDM_NS + 2], work); + dft(ofdm, ofdm->rx_sym[Ns + 2], work); /* * We are finished now with the DFT and down conversion @@ -662,19 +837,19 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) { */ complex float freq_err_rect = conjf(vector_sum(ofdm->rx_sym[1], - OFDM_NC + 2)) * vector_sum(ofdm->rx_sym[OFDM_NS + 1], OFDM_NC + 2); + Nc + 2)) * vector_sum(ofdm->rx_sym[Ns + 1], Nc + 2); /* prevent instability in atan(im/re) when real part near 0 */ freq_err_rect = freq_err_rect + 1E-6f; - freq_err_hz = cargf(freq_err_rect) * OFDM_RS / (TAU * OFDM_NS); + freq_err_hz = cargf(freq_err_rect) * OFDM_RS / (TAU * Ns); ofdm->foff_est_hz += (ofdm->foff_est_gain * freq_err_hz); } /* OK - now estimate and correct pilot phase ---------------------------------- */ - for (i = 0; i < (OFDM_NC + 2); i++) { + for (i = 0; i < (Nc + 2); i++) { aphase_est_pilot[i] = 10.0f; aamp_est_pilot[i] = 0.0f; } @@ -685,7 +860,7 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) { * Then average the phase surrounding each of the data symbols. */ - for (i = 1; i < (OFDM_NC + 1); i++) { + for (i = 1; i < (Nc + 1); i++) { complex float symbol[3]; for (j = (i - 1), k = 0; j < (i + 2); j++, k++) { @@ -695,7 +870,7 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) { aphase_est_pilot_rect = vector_sum(symbol, 3); for (j = (i - 1), k = 0; j < (i + 2); j++, k++) { - symbol[k] = ofdm->rx_sym[OFDM_NS + 1][j] * conjf(ofdm->pilots[j]); /* next pilot conjugate */ + symbol[k] = ofdm->rx_sym[Ns + 1][j] * conjf(ofdm->pilots[j]); /* next pilot conjugate */ } aphase_est_pilot_rect = aphase_est_pilot_rect + vector_sum(symbol, 3); @@ -709,7 +884,7 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) { aphase_est_pilot_rect = aphase_est_pilot_rect + vector_sum(symbol, 3); for (j = (i - 1), k = 0; j < (i + 2); j++, k++) { - symbol[k] = ofdm->rx_sym[OFDM_NS + 2][j] * ofdm->pilots[j]; /* last pilot */ + symbol[k] = ofdm->rx_sym[Ns + 2][j] * ofdm->pilots[j]; /* last pilot */ } aphase_est_pilot_rect = aphase_est_pilot_rect + vector_sum(symbol, 3); @@ -727,17 +902,18 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) { */ complex float rx_corr; + complex float rx_np[RowsPerFrame * Nc]; int abit[2]; int bit_index = 0; - for (rr = 0; rr < OFDM_ROWSPERFRAME; rr++) { + for (rr = 0; rr < RowsPerFrame; rr++) { /* * Note the i has an index of 1 to 16, so we ignore carriers 0 and 17. * * Also note we are using sym[2..8] or the seven data symbols. */ - for (i = 1; i < (OFDM_NC + 1); i++) { + for (i = 1; i < (Nc + 1); i++) { if (ofdm->phase_est_en == true) { rx_corr = ofdm->rx_sym[rr + 2][i] * cexpf(-I * aphase_est_pilot[i]); } else { @@ -749,7 +925,7 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) { * without the pilots. Thus, the name rx (no pilot) np */ - ofdm->rx_np[(rr * OFDM_NC) + (i - 1)] = rx_corr; + rx_np[(rr * Nc) + (i - 1)] = rx_corr; /* * Note even though amp ests are the same for each col, @@ -757,14 +933,14 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) { * so convenient to log them all */ - ofdm->rx_amp[(rr * OFDM_NC) + (i - 1)] = aamp_est_pilot[i]; + ofdm->rx_amp[(rr * Nc) + (i - 1)] = aamp_est_pilot[i]; /* * Note like amps in this implementation phase ests are the * same for each col, but we log them for each symbol anyway */ - ofdm->aphase_est_pilot_log[(rr * OFDM_NC) + (i - 1)] = aphase_est_pilot[i]; + ofdm->aphase_est_pilot_log[(rr * Nc) + (i - 1)] = aphase_est_pilot[i]; if (OFDM_BPS == 1) { rx_bits[bit_index++] = crealf(rx_corr) > 0.0f; @@ -782,21 +958,30 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) { /* Adjust nin to take care of sample clock offset */ - ofdm->nin = OFDM_SAMPLESPERFRAME; + ofdm->nin = SampsPerFrame; if (ofdm->timing_en == true) { - int thresh = (OFDM_M + OFDM_NCP) / 8; - int tshift = (OFDM_M + OFDM_NCP) / 4; + int thresh = (M + Ncp) / 8; + int tshift = (M + Ncp) / 4; if (ofdm->timing_est > thresh) { - ofdm->nin = OFDM_SAMPLESPERFRAME + tshift; + ofdm->nin = SampsPerFrame + tshift; ofdm->timing_est -= tshift; ofdm->sample_point -= tshift; } else if (ofdm->timing_est < -thresh) { - ofdm->nin = OFDM_SAMPLESPERFRAME - tshift; + ofdm->nin = SampsPerFrame - tshift; ofdm->timing_est += tshift; ofdm->sample_point += tshift; } } + + int timing_est_log = ofdm->timing_est + 1; + int sample_point_log = ofdm->sample_point + 1; + + modem_probe_samp_f("foff_hz_log_c",&(ofdm->foff_est_hz),1); + modem_probe_samp_i("timing_est_log_c",&timing_est_log,1); + modem_probe_samp_i("sample_point_log_c",&sample_point_log,1); + modem_probe_samp_cft("rxbuf_log_c",ofdm->rxbuf,ofdm->config.RxBufSize); + modem_probe_samp_cft("rx_np_log_c",&rx_np[0],RowsPerFrame * Nc); } diff --git a/codec2-dev/src/ofdm_internal.h b/codec2-dev/src/ofdm_internal.h index 1a1c576f..8ea4fc90 100644 --- a/codec2-dev/src/ofdm_internal.h +++ b/codec2-dev/src/ofdm_internal.h @@ -34,6 +34,7 @@ extern "C" { #include #include +#include #include "codec2_ofdm.h" @@ -43,13 +44,13 @@ extern "C" { #define TAU (2.0f * M_PI) /* mathematical constant */ -#define OFDM_NC 16 /* N Carriers */ +#define OFDM_NCX 16 /* N Carriers */ #define OFDM_TS 0.018f /* Symbol time */ #define OFDM_RS (1.0f / OFDM_TS) /* Symbol rate */ #define OFDM_FS 8000.0f /* Sample rate */ #define OFDM_BPS 2 /* Bits per symbol */ #define OFDM_TCP 0.002f /* ? */ -#define OFDM_NS 8 /* */ +#define OFDM_NS 8 /* Symbols per frame (number of rows incl pilot) */ #define OFDM_CENTRE 1500.0f /* Center frequency */ /* To prevent C99 warning */ @@ -67,9 +68,9 @@ extern "C" { /* ? */ #define OFDM_FTWINDOWWIDTH 11 /* Bits per frame (duh) */ -#define OFDM_BITSPERFRAME ((OFDM_NS - 1) * (OFDM_NC * OFDM_BPS)) +#define OFDM_BITSPERFRAME ((OFDM_NS - 1) * (OFDM_NCX * OFDM_BPS)) /* Rows per frame */ -#define OFDM_ROWSPERFRAME (OFDM_BITSPERFRAME / (OFDM_NC * OFDM_BPS)) +#define OFDM_ROWSPERFRAME (OFDM_BITSPERFRAME / (OFDM_NCX * OFDM_BPS)) /* Samps per frame */ #define OFDM_SAMPLESPERFRAME (OFDM_NS * (OFDM_M + OFDM_NCP)) @@ -79,10 +80,24 @@ extern "C" { /* Dummy struct for now, will contain constant configuration for OFDM modem */ struct OFDM_CONFIG{ - int a; + int32_t Nc; + int32_t Ts; + int32_t Rs; + int32_t Fs; + int32_t bps; + int32_t Tcp; + int32_t Ns; + int32_t Fcenter; + int32_t M; + int32_t Ncp; + int32_t FtWindowWidth; + int32_t BitsPerFrame; + int32_t SampsPerFrame; + int32_t SampsPerFrameMax; + int32_t RxBufSize; + int32_t RowsPerFrame; }; - struct OFDM { struct OFDM_CONFIG config; float foff_est_gain; @@ -97,18 +112,29 @@ struct OFDM { bool foff_est_en; bool phase_est_en; - complex float pilot_samples[OFDM_M + OFDM_NCP]; - complex float W[OFDM_NC + 2][OFDM_M]; - complex float rxbuf[OFDM_RXBUF]; - complex float pilots[OFDM_NC + 2]; - float w[OFDM_NC + 2]; + //complex float pilot_samples[OFDM_M + OFDM_NCP]; + //complex float W[OFDM_NCX + 2][OFDM_M]; + //complex float rxbuf[OFDM_RXBUF]; + //complex float pilots[OFDM_NC + 2]; + //float w[OFDM_NC + 2]; + + complex float ** W; + complex float * pilots; + complex float * pilot_samples; + complex float * rxbuf; + float * w; + /* Demodulator data */ - complex float rx_sym[OFDM_NS + 3][OFDM_NC + 2]; - complex float rx_np[OFDM_ROWSPERFRAME * OFDM_NC]; - float rx_amp[OFDM_ROWSPERFRAME * OFDM_NC]; - float aphase_est_pilot_log[OFDM_ROWSPERFRAME * OFDM_NC]; + //complex float rx_sym[OFDM_NS + 3][OFDM_NCX + 2]; + //complex float rx_np[OFDM_ROWSPERFRAME * OFDM_NCX]; + //float rx_amp[OFDM_ROWSPERFRAME * OFDM_NCX]; + //float aphase_est_pilot_log[OFDM_ROWSPERFRAME * OFDM_NCX]; + + complex float ** rx_sym; + float * rx_amp; + float * aphase_est_pilot_log; }; #ifdef __cplusplus diff --git a/codec2-dev/unittest/CMakeLists.txt b/codec2-dev/unittest/CMakeLists.txt index 1c5719a4..e5c12be8 100644 --- a/codec2-dev/unittest/CMakeLists.txt +++ b/codec2-dev/unittest/CMakeLists.txt @@ -51,7 +51,8 @@ target_link_libraries(tfmfsk m) add_executable(tdeframer tdeframer.c) target_link_libraries(tdeframer m codec2) -add_executable(tofdm tofdm.c ../src/ofdm.c ../src/octave.c ../src/kiss_fft.c) +add_definitions(-DMODEMPROBE_ENABLE -DXXXXX) +add_executable(tofdm tofdm.c ../src/ofdm.c ../src/octave.c ../src/kiss_fft.c ../src/modem_probe.c) target_link_libraries(tofdm m) add_executable(tfreedv_data_channel tfreedv_data_channel.c) diff --git a/codec2-dev/unittest/tofdm.c b/codec2-dev/unittest/tofdm.c index 2ffff9a2..21e52ae2 100644 --- a/codec2-dev/unittest/tofdm.c +++ b/codec2-dev/unittest/tofdm.c @@ -35,15 +35,20 @@ #include #include +#define MODEMPROBE_ENABLE + #include "ofdm_internal.h" #include "codec2_ofdm.h" #include "octave.h" #include "test_bits_ofdm.h" #include "comp_prim.h" +#include "modem_probe.h" + +#define OFDM_NC 16 #define NFRAMES 30 -#define SAMPLE_CLOCK_OFFSET_PPM 100 -#define FOFF_HZ 0.5f +//#define SAMPLE_CLOCK_OFFSET_PPM 100 +//#define FOFF_HZ 5.0f /*---------------------------------------------------------------------------*\ @@ -144,6 +149,10 @@ int main(int argc, char *argv[]) FILE *fout; int f,i,j; + int sample_clock_offset_ppm = 100; + float foff_hz = 0.1; + int nframes = 30; + ofdm = ofdm_create(OFDM_CONFIG_700D); assert(ofdm != NULL); @@ -170,11 +179,11 @@ int main(int argc, char *argv[]) Channel \*---------------------------------------------------------*/ - 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); COMP foff_phase_rect = {1.0f, 0.0f}; - freq_shift(rx_log, rx_log, FOFF_HZ, &foff_phase_rect, samples_per_frame * NFRAMES); + freq_shift(rx_log, rx_log, foff_hz, &foff_phase_rect, samples_per_frame * NFRAMES); /* --------------------------------------------------------*\ Demod @@ -195,6 +204,8 @@ int main(int argc, char *argv[]) int nin_tot = 0; + modem_probe_init("ofdm","ofdm_test.txt"); + /* disable estimators for initial testing */ ofdm_set_verbose(ofdm, true); @@ -237,13 +248,15 @@ int main(int argc, char *argv[]) /* rx vector logging -----------------------------------*/ assert(nin_tot < samples_per_frame*NFRAMES); - memcpy(&rxbuf_in_log[nin_tot], rxbuf_in, sizeof(COMP)*nin); + //memcpy(&rxbuf_in_log[nin_tot], rxbuf_in, sizeof(COMP)*nin); + modem_probe_samp_cft("rxbuf_in_log_c",rxbuf_in,nin); + nin_tot += nin; - for(i=0; irxbuf[i]); rxbuf_log[OFDM_RXBUF*f+i].imag = cimagf(ofdm->rxbuf[i]); - } + }*/ for (i = 0; i < (OFDM_NS + 3); i++) { for (j = 0; j < (OFDM_NC + 2); j++) { @@ -254,10 +267,10 @@ int main(int argc, char *argv[]) /* note corrected phase (rx no phase) is one big linear array for frame */ - for (i = 0; i < OFDM_ROWSPERFRAME*OFDM_NC; i++) { + /*for (i = 0; i < OFDM_ROWSPERFRAME*OFDM_NC; i++) { rx_np_log[OFDM_ROWSPERFRAME*OFDM_NC*f + i].real = crealf(ofdm->rx_np[i]); rx_np_log[OFDM_ROWSPERFRAME*OFDM_NC*f + i].imag = cimagf(ofdm->rx_np[i]); - } + }*/ /* note phase/amp ests the same for each col, but check them all anyway */ @@ -268,11 +281,12 @@ int main(int argc, char *argv[]) } } - foff_hz_log[f] = ofdm->foff_est_hz; - timing_est_log[f] = ofdm->timing_est + 1; /* offset by 1 to match Octave */ - sample_point_log[f] = ofdm->sample_point + 1; /* offset by 1 to match Octave */ - - memcpy(&rx_bits_log[OFDM_BITSPERFRAME*f], rx_bits, sizeof(rx_bits)); + //foff_hz_log[f] = ofdm->foff_est_hz; + //timing_est_log[f] = ofdm->timing_est + 1; /* offset by 1 to match Octave */ + //sample_point_log[f] = ofdm->sample_point + 1; /* offset by 1 to match Octave */ + + modem_probe_samp_i("rx_bits_log_c",rx_bits,OFDM_BITSPERFRAME); + //memcpy(&rx_bits_log[OFDM_BITSPERFRAME*f], rx_bits, sizeof(rx_bits)); } /*---------------------------------------------------------*\ @@ -280,6 +294,9 @@ int main(int argc, char *argv[]) by tofdm.m Octave script \*---------------------------------------------------------*/ + modem_probe_close(); + + fout = fopen("tofdm_out.txt","wt"); assert(fout != NULL); fprintf(fout, "# Created by tofdm.c\n"); @@ -287,16 +304,16 @@ int main(int argc, char *argv[]) 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, "rxbuf_in_log_c", (COMP*)rxbuf_in_log, 1, nin_tot, nin_tot); + //octave_save_complex(fout, "rxbuf_log_c_x", (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); octave_save_float(fout, "phase_est_pilot_log_c", (float*)phase_est_pilot_log, OFDM_ROWSPERFRAME*NFRAMES, OFDM_NC, OFDM_NC); octave_save_float(fout, "rx_amp_log_c", (float*)rx_amp_log, 1, OFDM_ROWSPERFRAME*OFDM_NC*NFRAMES, OFDM_ROWSPERFRAME*OFDM_NC*NFRAMES); - octave_save_float(fout, "foff_hz_log_c", foff_hz_log, NFRAMES, 1, 1); - octave_save_int(fout, "timing_est_log_c", timing_est_log, NFRAMES, 1); - octave_save_int(fout, "sample_point_log_c", sample_point_log, NFRAMES, 1); - octave_save_complex(fout, "rx_np_log_c", (COMP*)rx_np_log, 1, OFDM_ROWSPERFRAME*OFDM_NC*NFRAMES, OFDM_ROWSPERFRAME*OFDM_NC*NFRAMES); - octave_save_int(fout, "rx_bits_log_c", rx_bits_log, 1, OFDM_BITSPERFRAME*NFRAMES); + //octave_save_float(fout, "foff_hz_log_c", foff_hz_log, NFRAMES, 1, 1); + //octave_save_int(fout, "timing_est_log_c", timing_est_log, NFRAMES, 1); + //ctave_save_int(fout, "sample_point_log_c", sample_point_log, NFRAMES, 1); + //octave_save_complex(fout, "rx_np_log_c", (COMP*)rx_np_log, 1, OFDM_ROWSPERFRAME*OFDM_NC*NFRAMES, OFDM_ROWSPERFRAME*OFDM_NC*NFRAMES); + //octave_save_int(fout, "rx_bits_log_cx", rx_bits_log, 1, OFDM_BITSPERFRAME*NFRAMES); fclose(fout); ofdm_destroy(ofdm);