From 72a47d9a1234c6496e8825ee2cbad45d993536c5 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sat, 21 Apr 2012 07:11:44 +0000 Subject: [PATCH] fft input of lpf_peak_pick working git-svn-id: https://svn.code.sf.net/p/freetel/code@373 01035d8c-6547-0410-b346-abe4f91aad63 --- codec2-dev/octave/fdmdv.m | 43 ++- codec2-dev/octave/fdmdv_demod.m | 3 +- codec2-dev/octave/tfdmdv.m | 172 ++++++--- codec2-dev/src/fdmdv.c | 269 ++++++++++++- codec2-dev/src/fdmdv_internal.h | 26 +- codec2-dev/src/hanning.h | 644 ++++++++++++++++++++++++++++++++ codec2-dev/src/pilot_coeff.h | 34 ++ codec2-dev/unittest/Makefile.am | 2 +- codec2-dev/unittest/Makefile.in | 5 +- codec2-dev/unittest/tfdmdv.c | 37 +- 10 files changed, 1151 insertions(+), 84 deletions(-) create mode 100644 codec2-dev/src/hanning.h create mode 100644 codec2-dev/src/pilot_coeff.h diff --git a/codec2-dev/octave/fdmdv.m b/codec2-dev/octave/fdmdv.m index afa5d186..be274c3d 100644 --- a/codec2-dev/octave/fdmdv.m +++ b/codec2-dev/octave/fdmdv.m @@ -243,7 +243,7 @@ endfunction % Estimate frequency offset of FDM signal using BPSK pilot. This is quite % sensitive to pilot tone level wrt other carriers -function foff = rx_est_freq_offset(rx_fdm, pilot, pilot_prev, nin) +function [foff s1 s2] = rx_est_freq_offset(rx_fdm, pilot, pilot_prev, nin) global M; global Npilotbaseband; global pilot_baseband1; @@ -264,8 +264,8 @@ function foff = rx_est_freq_offset(rx_fdm, pilot, pilot_prev, nin) pilot_baseband2(Npilotbaseband-nin+i) = rx_fdm(i) * conj(pilot_prev(i)); end - [foff1 max1 pilot_lpf1] = lpf_peak_pick(pilot_baseband1, pilot_lpf1, nin); - [foff2 max2 pilot_lpf2] = lpf_peak_pick(pilot_baseband2, pilot_lpf2, nin); + [foff1 max1 pilot_lpf1 s1] = lpf_peak_pick(pilot_baseband1, pilot_lpf1, nin); + [foff2 max2 pilot_lpf2 s2] = lpf_peak_pick(pilot_baseband2, pilot_lpf2, nin); if max1 > max2 foff = foff1; @@ -277,7 +277,7 @@ endfunction % LPF and peak pick part of freq est, put in a function as we call it twice -function [foff imax pilot_lpf] = lpf_peak_pick(pilot_baseband, pilot_lpf, nin) +function [foff imax pilot_lpf S] = lpf_peak_pick(pilot_baseband, pilot_lpf, nin) global M; global Npilotlpf; global Npilotcoeff; @@ -290,14 +290,15 @@ function [foff imax pilot_lpf] = lpf_peak_pick(pilot_baseband, pilot_lpf, nin) pilot_lpf(1:Npilotlpf-nin) = pilot_lpf(nin+1:Npilotlpf); j = 1; for i = Npilotlpf-nin+1:Npilotlpf - pilot_lpf(i) = pilot_baseband(j:j+Npilotcoeff) * pilot_coeff'; + pilot_lpf(i) = pilot_baseband(j:j+Npilotcoeff-1) * pilot_coeff'; j++; end % decimate to improve DFT resolution, window and DFT Mpilot = Fs/(2*200); % calc decimation rate given new sample rate is twice LPF freq - s = pilot_lpf(1:Mpilot:Npilotlpf) .* hanning(Npilotlpf/Mpilot)'; + h = hanning(Npilotlpf); + s = pilot_lpf(1:Mpilot:Npilotlpf) .* h(1:Mpilot:Npilotlpf)'; S = abs(fft(s, Mpilotfft)); % peak pick and convert to Hz @@ -744,20 +745,34 @@ function rn_file(filename) fclose(f); endfunction - -% Saves 200Hz LPF filter coeffs to a text file in the form of a C array - function pilot_coeff_file(filename) global pilot_coeff; - global Nfilter; + global Npilotcoeff; f=fopen(filename,"wt"); fprintf(f,"/* Generated by pilot_coeff_file() Octave function */\n\n"); fprintf(f,"const float pilot_coeff[]={\n"); for m=1:Npilotcoeff-1 - fprintf(f," %g,\n", pilot_coeff(m)); + fprintf(f," %g,\n",pilot_coeff(m)); + endfor + fprintf(f," %g\n};\n",pilot_coeff(Npilotcoeff)); + fclose(f); +endfunction + +% Saves hanning window coeffs to a text file in the form of a C array + +function hanning_file(filename) + global Npilotlpf; + + h = hanning(Npilotlpf); + + f=fopen(filename,"wt"); + fprintf(f,"/* Generated by hanning_file() Octave function */\n\n"); + fprintf(f,"const float hanning[]={\n"); + for m=1:Npilotlpf-1 + fprintf(f," %g,\n", h(m)); endfor - fprintf(f," %g\n};\n", pilot_coeff(Npilotcoeff)); + fprintf(f," %g\n};\n", h(Npilotlpf)); fclose(f); endfunction @@ -801,8 +816,8 @@ phase_rx = ones(Nc+1,1); global Mpilotfft = 256; global Npilotcoeff = 30; % number of pilot LPF coeffs -global pilot_coeff = fir1(Npilotcoeff, 200/(Fs/2))'; % 200Hz LPF -global Npilotbaseband = Npilotcoeff + 4*M; % number of pilot baseband samples reqd for pilot LPF +global pilot_coeff = fir1(Npilotcoeff-1, 200/(Fs/2))'; % 200Hz LPF +global Npilotbaseband = Npilotcoeff + M + M/P; % number of pilot baseband samples reqd for pilot LPF global Npilotlpf = 4*M; % number of samples we DFT pilot over, pilot est window % pilot LUT, used for copy of pilot at rx diff --git a/codec2-dev/octave/fdmdv_demod.m b/codec2-dev/octave/fdmdv_demod.m index e1fb3b43..2ba10437 100644 --- a/codec2-dev/octave/fdmdv_demod.m +++ b/codec2-dev/octave/fdmdv_demod.m @@ -46,6 +46,7 @@ function fdmdv_demod(rawfilename, nbits) % Main loop ---------------------------------------------------- for f=1:frames + % obtain nin samples of the test input signal for i=1:nin @@ -134,7 +135,7 @@ function fdmdv_demod(rawfilename, nbits) test_frame_sync_log = [test_frame_sync_log test_frame_sync_state]; end - + % --------------------------------------------------------------------- % Print Stats % --------------------------------------------------------------------- diff --git a/codec2-dev/octave/tfdmdv.m b/codec2-dev/octave/tfdmdv.m index ad606d2a..020a5840 100644 --- a/codec2-dev/octave/tfdmdv.m +++ b/codec2-dev/octave/tfdmdv.m @@ -16,12 +16,24 @@ fdmdv; % load modem code passes = fails = 0; frames = 25; prev_tx_symbols = ones(Nc+1,1); + +% Octave outputs we want to collect for comparison to C version + tx_bits_log = []; tx_symbols_log = []; tx_baseband_log = []; tx_fdm_log = []; +pilot_baseband1_log = []; +pilot_baseband2_log = []; +pilot_lpf1_log = []; +pilot_lpf2_log = []; +s1_log = []; +s2_log = []; for f=1:frames + + % modulator + tx_bits = get_test_bits(Nc*Nb); tx_bits_log = [tx_bits_log tx_bits]; tx_symbols = bits_to_qpsk(prev_tx_symbols, tx_bits, 'dqpsk'); @@ -31,75 +43,97 @@ for f=1:frames tx_baseband_log = [tx_baseband_log tx_baseband]; tx_fdm = fdm_upconvert(tx_baseband); tx_fdm_log = [tx_fdm_log tx_fdm]; + + rx_fdm = real(tx_fdm); + + % demodulator + + [pilot prev_pilot pilot_lut_index prev_pilot_lut_index] = get_pilot(pilot_lut_index, prev_pilot_lut_index, M); + + [foff s1 s2] = rx_est_freq_offset(rx_fdm, pilot, prev_pilot, M); + + pilot_baseband1_log = [pilot_baseband1_log pilot_baseband1]; + pilot_baseband2_log = [pilot_baseband2_log pilot_baseband2]; + pilot_lpf1_log = [pilot_lpf1_log pilot_lpf1]; + pilot_lpf2_log = [pilot_lpf2_log pilot_lpf2]; + s1_log = [s1_log s1]; + s2_log = [s2_log s2]; + end % Compare to the output from the C version load ../unittest/tfdmdv_out.txt -figure(1) -subplot(211) +% Helper functions to plot output of C verson and difference between Octave and C versions + +function stem_sig_and_error(plotnum, subplotnum, sig, error, titlestr, axisvec) + figure(plotnum) + subplot(subplotnum) + stem(sig); + hold on; + stem(error,'g'); + hold off; + if nargin == 6 + axis(axisvec); + end + title(titlestr); +endfunction + +function plot_sig_and_error(plotnum, subplotnum, sig, error, titlestr, axisvec) + figure(plotnum) + subplot(subplotnum) + plot(sig); + hold on; + plot(error,'g'); + hold off; + if nargin == 6 + axis(axisvec); + end + title(titlestr); +endfunction + +% --------------------------------------------------------------------------------------- +% Plot output and test each C function +% --------------------------------------------------------------------------------------- + +% fdmdv_get_test_bits() & bits_to_dqpsk_symbols() + n = 28; -stem(tx_bits_log_c(1:n)); -hold on; -stem(tx_bits_log(1:n) - tx_bits_log_c(1:n),'g'); -hold off; -axis([1 n -1.5 1.5]) -title('tx bits') -subplot(212) -stem(real(tx_symbols_log_c(1:n/2))); -hold on; -stem(tx_symbols_log(1:n/2) - tx_symbols_log_c(1:n/2),'g'); -hold off; -axis([1 n/2 -1.5 1.5]) -title('tx symbols real') - -figure(2) -clf; +stem_sig_and_error(1, 211, tx_bits_log_c(1:n), tx_bits_log(1:n) - tx_bits_log_c(1:n), 'tx bits', [1 n -1.5 1.5]) +stem_sig_and_error(1, 212, real(tx_symbols_log_c(1:n/2)), tx_symbols_log(1:n/2) - tx_symbols_log_c(1:n/2), 'tx symbols real', [1 n/2 -1.5 1.5]) + +% tx_filter() + diff = tx_baseband_log - tx_baseband_log_c; -subplot(211) c=3; -plot(real(tx_baseband_log_c(c,:))); -hold on; -plot(real(sum(diff)),'g') -hold off; -title('tx baseband real') -subplot(212) -plot(imag(tx_baseband_log_c(c,:))); -hold on; -plot(imag(sum(diff)),'g') -hold off; -title('tx baseband imag') - -figure(3) -clf -subplot(211) -plot(real(tx_fdm_log_c)); -hold on; -plot(real(tx_fdm_log - tx_fdm_log_c),'g'); -hold off; -title('tx fdm real') -subplot(212) -plot(imag(tx_fdm_log_c)); -hold on; -plot(imag(tx_fdm_log - tx_fdm_log_c),'g'); -hold off; -title('tx fdm imag') - -figure(4) -clf -subplot(211) -plot(real(pilot_lut_c)); -hold on; -plot(real(pilot_lut - pilot_lut_c),'g'); -hold off; -title('pilot lut real') -subplot(212) -plot(imag(pilot_lut_c)); -hold on; -plot(imag(pilot_lut - pilot_lut_c),'g'); -hold off; -title('pilot lut imag') +plot_sig_and_error(2, 211, real(tx_baseband_log_c(c,:)), real(sum(diff)), 'tx baseband real') +plot_sig_and_error(2, 212, imag(tx_baseband_log_c(c,:)), imag(sum(diff)), 'tx baseband imag') + +% fdm_upconvert() + +plot_sig_and_error(3, 211, real(tx_fdm_log_c), real(tx_fdm_log - tx_fdm_log_c), 'tx fdm real') +plot_sig_and_error(3, 212, imag(tx_fdm_log_c), imag(tx_fdm_log - tx_fdm_log_c), 'tx fdm imag') + +% generate_pilot_lut() + +plot_sig_and_error(4, 211, real(pilot_lut_c), real(pilot_lut - pilot_lut_c), 'pilot lut real') +plot_sig_and_error(4, 212, imag(pilot_lut_c), imag(pilot_lut - pilot_lut_c), 'pilot lut imag') + +% rx_est_freq_offset() + +plot_sig_and_error(5, 211, real(pilot_baseband1_log), real(pilot_baseband1_log - pilot_baseband1_log_c), 'pilot baseband1 real' ) +plot_sig_and_error(5, 212, real(pilot_baseband2_log), real(pilot_baseband2_log - pilot_baseband2_log_c), 'pilot baseband2 real' ) + +plot_sig_and_error(6, 211, real(pilot_lpf1_log), real(pilot_lpf1_log - pilot_lpf1_log_c), 'pilot lpf1 real' ) +plot_sig_and_error(6, 212, real(pilot_lpf2_log), real(pilot_lpf2_log - pilot_lpf2_log_c), 'pilot lpf2 real' ) + +plot_sig_and_error(7, 211, real(s1_log), real(s1_log - s1_log_c), 's1 real' ) +plot_sig_and_error(7, 212, real(s2_log), real(s2_log - s2_log_c), 's2 real' ) + +% --------------------------------------------------------------------------------------- +% AUTOMATED CHECKS ------------------------------------------ +% --------------------------------------------------------------------------------------- if sum(tx_bits_log - tx_bits_log_c) == 0 printf("fdmdv_get_test_bits..: OK\n"); @@ -141,4 +175,22 @@ else; fails++; end +[m n] = size(pilot_baseband1_log); +if sum(pilot_baseband1_log - pilot_baseband1_log_c)/n < 1E-3 + printf("pilot_baseband1_log..: OK\n"); + passes++; +else; + printf("pilot_baseband1_log..: FAIL\n"); + fails++; +end + +[m n] = size(pilot_baseband2_log); +if sum(pilot_baseband2_log - pilot_baseband2_log_c)/n < 1E-3 + printf("pilot_baseband2_log..: OK\n"); + passes++; +else; + printf("pilot_baseband2_log..: FAIL\n"); + fails++; +end + printf("\npasses: %d fails: %d\n", passes, fails); diff --git a/codec2-dev/src/fdmdv.c b/codec2-dev/src/fdmdv.c index 895c6efa..7f0b9d77 100644 --- a/codec2-dev/src/fdmdv.c +++ b/codec2-dev/src/fdmdv.c @@ -35,12 +35,16 @@ #include #include #include +#include #include #include "fdmdv_internal.h" #include "fdmdv.h" #include "rn.h" #include "test_bits.h" +#include "pilot_coeff.h" +#include "fft.h" +#include "hanning.h" /*---------------------------------------------------------------------------*\ @@ -58,6 +62,16 @@ static COMP cneg(COMP a) return res; } +static COMP cconj(COMP a) +{ + COMP res; + + res.real = a.real; + res.imag = -a.imag; + + return res; +} + static COMP cmult(COMP a, COMP b) { COMP res; @@ -68,6 +82,16 @@ static COMP cmult(COMP a, COMP b) return res; } +static COMP fcmult(float a, COMP b) +{ + COMP res; + + res.real = a*b.real; + res.imag = a*b.imag; + + return res; +} + static COMP cadd(COMP a, COMP b) { COMP res; @@ -114,7 +138,7 @@ static void cbuf_shift_update(COMP buf[], COMP update[], int buflen, int updatel struct FDMDV *fdmdv_create(void) { struct FDMDV *f; - int c, k; + int c, i, k; float carrier_freq; assert(FDMDV_BITS_PER_FRAME == NC*NB); @@ -143,6 +167,8 @@ struct FDMDV *fdmdv_create(void) } + /* Set up frequency of each carrier */ + for(c=0; cfreq[c].real = cos(2.0*PI*carrier_freq/FS); @@ -158,6 +184,24 @@ struct FDMDV *fdmdv_create(void) f->freq[NC].real = cos(2.0*PI*FCENTRE/FS); f->freq[NC].imag = sin(2.0*PI*FCENTRE/FS); + /* Generate DBPSK pilot Look Up Table (LUT) */ + + generate_pilot_lut(f->pilot_lut, &f->freq[NC]); + + /* Freq Offset estimation */ + + for(i=0; ipilot_baseband1[i].real = f->pilot_baseband2[i].real = 0.0; + f->pilot_baseband1[i].imag = f->pilot_baseband2[i].imag = 0.0; + } + f->pilot_lut_index = 0; + f->prev_pilot_lut_index = 3*M; + + for(i=0; ipilot_lpf1[i].real = f->pilot_lpf2[i].real = 0.0; + f->pilot_lpf1[i].imag = f->pilot_lpf2[i].imag = 0.0; + } + return f; } @@ -367,3 +411,226 @@ void fdm_upconvert(COMP tx_fdm[], COMP tx_baseband[NC+1][M], COMP phase_tx[], CO tx_fdm[i] = cmult(two, tx_fdm[i]); } + +/*---------------------------------------------------------------------------*\ + + FUNCTION....: generate_pilot_fdm() + AUTHOR......: David Rowe + DATE CREATED: 19/4/2012 + + Generate M samples of DBPSK pilot signal for Freq offset estimation + +\*---------------------------------------------------------------------------*/ + +void generate_pilot_fdm(COMP *pilot_fdm, int *bit, float *symbol, + float *filter_mem, COMP *phase, COMP *freq) +{ + int i,j,k; + float tx_baseband[M]; + + /* +1 -1 +1 -1 DBPSK sync carrier, once filtered becomes (roughly) + two spectral lines at +/- RS/2 */ + + if (*bit) + *symbol = -*symbol; + else + *symbol = *symbol; + if (*bit) + *bit = 0; + else + *bit = 1; + + /* filter DPSK symbol to create M baseband samples */ + + filter_mem[NFILTER-1] = (sqrt(2)/2) * *symbol; + for(i=0; ireal; + pilot_fdm[i].imag = sqrt(2)*2*tx_baseband[i] * phase->imag; + } +} + +/*---------------------------------------------------------------------------*\ + + FUNCTION....: generate_pilot_lut() + AUTHOR......: David Rowe + DATE CREATED: 19/4/2012 + + Generate a 4M sample vector of DBPSK pilot signal. As the pilot signal + is periodic in 4M samples we can then use this vector as a look up table + for pilot signal generation in the demod. + +\*---------------------------------------------------------------------------*/ + +void generate_pilot_lut(COMP pilot_lut[], COMP *pilot_freq) +{ + int pilot_rx_bit = 0; + float pilot_symbol = sqrt(2.0); + COMP pilot_phase = {1.0, 0.0}; + float pilot_filter_mem[NFILTER]; + COMP pilot[M]; + int i,f; + + for(i=0; i= 4) + memcpy(&pilot_lut[M*(f-4)], pilot, M*sizeof(COMP)); + } + +} + +/*---------------------------------------------------------------------------*\ + + FUNCTION....: lpf_peak_pick() + AUTHOR......: David Rowe + DATE CREATED: 20/4/2012 + + LPF and peak pick part of freq est, put in a function as we call it twice. + +\*---------------------------------------------------------------------------*/ + +void lpf_peak_pick(float *foff, float *max, COMP pilot_baseband[], COMP pilot_lpf[], COMP s[], int nin) +{ + int i,j,k; + int mpilot; + float mag, imax; + int ix; + float r; + + /* LPF cutoff 200Hz, so we can handle max +/- 200 Hz freq offset */ + + for(i=0; i imax) { + imax = mag; + ix = i; + } + } + r = 2.0*200.0/MPILOTFFT; /* maps FFT bin to frequency in Hz */ + + if (ix >= MPILOTFFT/2) + *foff = (ix - MPILOTFFT)*r; + else + *foff = (ix)*r; + *max = imax; +#endif +} + +/*---------------------------------------------------------------------------*\ + + FUNCTION....: rx_est_freq_offset() + AUTHOR......: David Rowe + DATE CREATED: 19/4/2012 + + Estimate frequency offset of FDM signal using BPSK pilot. Note that + this algorithm is quite sensitive to pilot tone level wrt other + carriers, so test variations to the pilot amplitude carefully. + +\*---------------------------------------------------------------------------*/ + +float rx_est_freq_offset(struct FDMDV *f, float rx_fdm[], int nin) +{ + int i,j; + COMP pilot[M+M/P]; + COMP prev_pilot[M+M/P]; + float foff, foff1, foff2; + float max1, max2; + + assert(nin <= M+M/P); + + /* get pilot samples used for correlation/down conversion of rx signal */ + + for (i=0; ipilot_lut[f->pilot_lut_index]; + f->pilot_lut_index++; + if (f->pilot_lut_index >= 4*M) + f->pilot_lut_index = 0; + + prev_pilot[i] = f->pilot_lut[f->prev_pilot_lut_index]; + f->prev_pilot_lut_index++; + if (f->prev_pilot_lut_index >= 4*M) + f->prev_pilot_lut_index = 0; + } + + /* + Down convert latest M samples of pilot by multiplying by ideal + BPSK pilot signal we have generated locally. This peak of the + resulting signal is sensitive to the time shift between the + received and local version of the pilot, so we do it twice at + different time shifts and choose the maximum. + */ + + for(i=0; ipilot_baseband1[i] = f->pilot_baseband1[i+nin]; + f->pilot_baseband2[i] = f->pilot_baseband2[i+nin]; + } + + for(i=0,j=NPILOTBASEBAND-nin; ipilot_baseband1[j] = fcmult(rx_fdm[i], cconj(pilot[i])); + f->pilot_baseband2[j] = fcmult(rx_fdm[i], cconj(prev_pilot[i])); + } + + lpf_peak_pick(&foff1, &max1, f->pilot_baseband1, f->pilot_lpf1, f->s1, nin); + lpf_peak_pick(&foff2, &max2, f->pilot_baseband2, f->pilot_lpf2, f->s2, nin); + //for(i=0; is1[i].real, f->s1[i].imag); + //} + +#ifdef T + if (max1 > max2) + foff = foff1; + else + foff = foff2; + + return foff; +#endif + return 0; +} diff --git a/codec2-dev/src/fdmdv_internal.h b/codec2-dev/src/fdmdv_internal.h index 590e4a8b..68d334b0 100644 --- a/codec2-dev/src/fdmdv_internal.h +++ b/codec2-dev/src/fdmdv_internal.h @@ -37,6 +37,7 @@ \*---------------------------------------------------------------------------*/ +#define PI 3.141592654 #define FS 8000 /* sample rate in Hz */ #define T (1.0/FS) /* sample period in seconds */ #define RS 50 /* symbol rate in Hz */ @@ -45,16 +46,22 @@ #define RB (NC*RS*NB) /* bit rate */ #define M (FS/RS) /* oversampling factor */ #define NSYM 6 /* number of symbols to filter over */ +#define NFILTER (NSYM*M) /* size of tx/rx filters at sample rate M */ + #define FSEP 75 /* Separation between carriers (Hz) */ #define FCENTRE 1200 /* Centre frequency, Nc/2 carriers below this, Nc/2 carriers above (Hz) */ + #define NT 5 /* number of symbols we estimate timing over */ #define P 4 /* oversample factor used for initial rx symbol filtering */ -#define NFILTER (NSYM*M) /* size of tx/rx filters at sample rate M */ #define NFILTERTIMING (M+Nfilter+M) /* filter memory used for resampling after timing estimation */ #define NTEST_BITS (NC*NB*4) /* length of test bit sequence */ -#define PI 3.141592654 +#define NPILOT_LUT (4*M) /* number of pilot look up table samples */ +#define NPILOTCOEFF 30 /* number of FIR filter coeffs in LP filter */ +#define NPILOTBASEBAND (NPILOTCOEFF+M+M/P) /* number of pilot baseband samples reqd for pilot LPF */ +#define NPILOTLPF (4*M) /* number of samples we DFT pilot over, pilot est window */ +#define MPILOTFFT 256 /*---------------------------------------------------------------------------*\ @@ -69,6 +76,17 @@ struct FDMDV { COMP tx_filter_memory[NC+1][NFILTER]; COMP phase_tx[NC+1]; COMP freq[NC+1]; + + COMP pilot_lut[NPILOT_LUT]; + int pilot_lut_index; + int prev_pilot_lut_index; + + COMP pilot_baseband1[NPILOTBASEBAND]; + COMP pilot_baseband2[NPILOTBASEBAND]; + COMP pilot_lpf1[NPILOTLPF]; + COMP pilot_lpf2[NPILOTLPF]; + COMP s1[MPILOTFFT]; + COMP s2[MPILOTFFT]; }; /*---------------------------------------------------------------------------*\ @@ -80,5 +98,9 @@ struct FDMDV { void bits_to_dqpsk_symbols(COMP tx_symbols[], COMP prev_tx_symbols[], int tx_bits[], int *pilot_bit); void tx_filter(COMP tx_baseband[NC+1][M], COMP tx_symbols[], COMP tx_filter_memory[NC+1][NFILTER]); void fdm_upconvert(COMP tx_fdm[], COMP tx_baseband[NC+1][M], COMP phase_tx[], COMP freq_tx[]); +void generate_pilot_fdm(COMP *pilot_fdm, int *bit, float *symbol, float *filter_mem, COMP *phase, COMP *freq); +void generate_pilot_lut(COMP pilot_lut[], COMP *pilot_freq); +float rx_est_freq_offset(struct FDMDV *f, float rx_fdm[], int nin); +void lpf_peak_pick(float *foff, float *max, COMP pilot_baseband[], COMP pilot_lpf[], COMP s[], int nin); #endif diff --git a/codec2-dev/src/hanning.h b/codec2-dev/src/hanning.h new file mode 100644 index 00000000..81d88dcb --- /dev/null +++ b/codec2-dev/src/hanning.h @@ -0,0 +1,644 @@ +/* Generated by hanning_file() Octave function */ + +const float hanning[]={ + 0, + 2.4171e-05, + 9.66816e-05, + 0.000217525, + 0.000386689, + 0.000604158, + 0.00086991, + 0.00118392, + 0.00154616, + 0.00195659, + 0.00241517, + 0.00292186, + 0.00347661, + 0.00407937, + 0.00473008, + 0.00542867, + 0.00617507, + 0.00696922, + 0.00781104, + 0.00870045, + 0.00963736, + 0.0106217, + 0.0116533, + 0.0127322, + 0.0138581, + 0.0150311, + 0.0162509, + 0.0175175, + 0.0188308, + 0.0201906, + 0.0215968, + 0.0230492, + 0.0245478, + 0.0260923, + 0.0276826, + 0.0293186, + 0.0310001, + 0.032727, + 0.034499, + 0.036316, + 0.0381779, + 0.0400844, + 0.0420354, + 0.0440307, + 0.04607, + 0.0481533, + 0.0502802, + 0.0524506, + 0.0546643, + 0.056921, + 0.0592206, + 0.0615627, + 0.0639473, + 0.0663741, + 0.0688427, + 0.0713531, + 0.0739048, + 0.0764978, + 0.0791318, + 0.0818064, + 0.0845214, + 0.0872767, + 0.0900718, + 0.0929066, + 0.0957807, + 0.0986939, + 0.101646, + 0.104636, + 0.107665, + 0.110732, + 0.113836, + 0.116978, + 0.120156, + 0.123372, + 0.126624, + 0.129912, + 0.133235, + 0.136594, + 0.139989, + 0.143418, + 0.146881, + 0.150379, + 0.153911, + 0.157476, + 0.161074, + 0.164705, + 0.168368, + 0.172063, + 0.17579, + 0.179549, + 0.183338, + 0.187158, + 0.191008, + 0.194888, + 0.198798, + 0.202737, + 0.206704, + 0.2107, + 0.214724, + 0.218775, + 0.222854, + 0.226959, + 0.231091, + 0.235249, + 0.239432, + 0.243641, + 0.247874, + 0.252132, + 0.256414, + 0.260719, + 0.265047, + 0.269398, + 0.273772, + 0.278167, + 0.282584, + 0.287021, + 0.29148, + 0.295958, + 0.300456, + 0.304974, + 0.30951, + 0.314065, + 0.318638, + 0.323228, + 0.327835, + 0.332459, + 0.3371, + 0.341756, + 0.346427, + 0.351113, + 0.355814, + 0.360528, + 0.365256, + 0.369997, + 0.374751, + 0.379516, + 0.384293, + 0.389082, + 0.393881, + 0.398691, + 0.40351, + 0.408338, + 0.413176, + 0.418022, + 0.422876, + 0.427737, + 0.432605, + 0.43748, + 0.44236, + 0.447247, + 0.452138, + 0.457034, + 0.461935, + 0.466839, + 0.471746, + 0.476655, + 0.481568, + 0.486481, + 0.491397, + 0.496313, + 0.501229, + 0.506145, + 0.511061, + 0.515976, + 0.520889, + 0.5258, + 0.530708, + 0.535614, + 0.540516, + 0.545414, + 0.550308, + 0.555197, + 0.560081, + 0.564958, + 0.56983, + 0.574695, + 0.579552, + 0.584402, + 0.589244, + 0.594077, + 0.598901, + 0.603715, + 0.60852, + 0.613314, + 0.618097, + 0.622868, + 0.627628, + 0.632375, + 0.63711, + 0.641831, + 0.646538, + 0.651232, + 0.655911, + 0.660574, + 0.665222, + 0.669855, + 0.67447, + 0.679069, + 0.683651, + 0.688215, + 0.69276, + 0.697287, + 0.701795, + 0.706284, + 0.710752, + 0.7152, + 0.719627, + 0.724033, + 0.728418, + 0.73278, + 0.73712, + 0.741437, + 0.74573, + 0.75, + 0.754246, + 0.758467, + 0.762663, + 0.766833, + 0.770978, + 0.775097, + 0.779189, + 0.783254, + 0.787291, + 0.791301, + 0.795283, + 0.799236, + 0.80316, + 0.807055, + 0.810921, + 0.814756, + 0.81856, + 0.822334, + 0.826077, + 0.829788, + 0.833468, + 0.837115, + 0.840729, + 0.844311, + 0.847859, + 0.851374, + 0.854855, + 0.858301, + 0.861713, + 0.86509, + 0.868431, + 0.871737, + 0.875007, + 0.87824, + 0.881437, + 0.884598, + 0.887721, + 0.890806, + 0.893854, + 0.896864, + 0.899835, + 0.902768, + 0.905661, + 0.908516, + 0.911331, + 0.914106, + 0.916841, + 0.919536, + 0.92219, + 0.924804, + 0.927376, + 0.929907, + 0.932397, + 0.934845, + 0.93725, + 0.939614, + 0.941935, + 0.944213, + 0.946448, + 0.94864, + 0.950789, + 0.952894, + 0.954955, + 0.956972, + 0.958946, + 0.960874, + 0.962759, + 0.964598, + 0.966393, + 0.968142, + 0.969846, + 0.971505, + 0.973118, + 0.974686, + 0.976207, + 0.977683, + 0.979112, + 0.980495, + 0.981832, + 0.983122, + 0.984365, + 0.985561, + 0.986711, + 0.987813, + 0.988868, + 0.989876, + 0.990837, + 0.99175, + 0.992616, + 0.993434, + 0.994204, + 0.994927, + 0.995601, + 0.996228, + 0.996807, + 0.997337, + 0.99782, + 0.998255, + 0.998641, + 0.998979, + 0.999269, + 0.999511, + 0.999704, + 0.999849, + 0.999946, + 0.999994, + 0.999994, + 0.999946, + 0.999849, + 0.999704, + 0.999511, + 0.999269, + 0.998979, + 0.998641, + 0.998255, + 0.99782, + 0.997337, + 0.996807, + 0.996228, + 0.995601, + 0.994927, + 0.994204, + 0.993434, + 0.992616, + 0.99175, + 0.990837, + 0.989876, + 0.988868, + 0.987813, + 0.986711, + 0.985561, + 0.984365, + 0.983122, + 0.981832, + 0.980495, + 0.979112, + 0.977683, + 0.976207, + 0.974686, + 0.973118, + 0.971505, + 0.969846, + 0.968142, + 0.966393, + 0.964598, + 0.962759, + 0.960874, + 0.958946, + 0.956972, + 0.954955, + 0.952894, + 0.950789, + 0.94864, + 0.946448, + 0.944213, + 0.941935, + 0.939614, + 0.93725, + 0.934845, + 0.932397, + 0.929907, + 0.927376, + 0.924804, + 0.92219, + 0.919536, + 0.916841, + 0.914106, + 0.911331, + 0.908516, + 0.905661, + 0.902768, + 0.899835, + 0.896864, + 0.893854, + 0.890806, + 0.887721, + 0.884598, + 0.881437, + 0.87824, + 0.875007, + 0.871737, + 0.868431, + 0.86509, + 0.861713, + 0.858301, + 0.854855, + 0.851374, + 0.847859, + 0.844311, + 0.840729, + 0.837115, + 0.833468, + 0.829788, + 0.826077, + 0.822334, + 0.81856, + 0.814756, + 0.810921, + 0.807055, + 0.80316, + 0.799236, + 0.795283, + 0.791301, + 0.787291, + 0.783254, + 0.779189, + 0.775097, + 0.770978, + 0.766833, + 0.762663, + 0.758467, + 0.754246, + 0.75, + 0.74573, + 0.741437, + 0.73712, + 0.73278, + 0.728418, + 0.724033, + 0.719627, + 0.7152, + 0.710752, + 0.706284, + 0.701795, + 0.697287, + 0.69276, + 0.688215, + 0.683651, + 0.679069, + 0.67447, + 0.669855, + 0.665222, + 0.660574, + 0.655911, + 0.651232, + 0.646538, + 0.641831, + 0.63711, + 0.632375, + 0.627628, + 0.622868, + 0.618097, + 0.613314, + 0.60852, + 0.603715, + 0.598901, + 0.594077, + 0.589244, + 0.584402, + 0.579552, + 0.574695, + 0.56983, + 0.564958, + 0.560081, + 0.555197, + 0.550308, + 0.545414, + 0.540516, + 0.535614, + 0.530708, + 0.5258, + 0.520889, + 0.515976, + 0.511061, + 0.506145, + 0.501229, + 0.496313, + 0.491397, + 0.486481, + 0.481568, + 0.476655, + 0.471746, + 0.466839, + 0.461935, + 0.457034, + 0.452138, + 0.447247, + 0.44236, + 0.43748, + 0.432605, + 0.427737, + 0.422876, + 0.418022, + 0.413176, + 0.408338, + 0.40351, + 0.398691, + 0.393881, + 0.389082, + 0.384293, + 0.379516, + 0.374751, + 0.369997, + 0.365256, + 0.360528, + 0.355814, + 0.351113, + 0.346427, + 0.341756, + 0.3371, + 0.332459, + 0.327835, + 0.323228, + 0.318638, + 0.314065, + 0.30951, + 0.304974, + 0.300456, + 0.295958, + 0.29148, + 0.287021, + 0.282584, + 0.278167, + 0.273772, + 0.269398, + 0.265047, + 0.260719, + 0.256414, + 0.252132, + 0.247874, + 0.243641, + 0.239432, + 0.235249, + 0.231091, + 0.226959, + 0.222854, + 0.218775, + 0.214724, + 0.2107, + 0.206704, + 0.202737, + 0.198798, + 0.194888, + 0.191008, + 0.187158, + 0.183338, + 0.179549, + 0.17579, + 0.172063, + 0.168368, + 0.164705, + 0.161074, + 0.157476, + 0.153911, + 0.150379, + 0.146881, + 0.143418, + 0.139989, + 0.136594, + 0.133235, + 0.129912, + 0.126624, + 0.123372, + 0.120156, + 0.116978, + 0.113836, + 0.110732, + 0.107665, + 0.104636, + 0.101646, + 0.0986939, + 0.0957807, + 0.0929066, + 0.0900718, + 0.0872767, + 0.0845214, + 0.0818064, + 0.0791318, + 0.0764978, + 0.0739048, + 0.0713531, + 0.0688427, + 0.0663741, + 0.0639473, + 0.0615627, + 0.0592206, + 0.056921, + 0.0546643, + 0.0524506, + 0.0502802, + 0.0481533, + 0.04607, + 0.0440307, + 0.0420354, + 0.0400844, + 0.0381779, + 0.036316, + 0.034499, + 0.032727, + 0.0310001, + 0.0293186, + 0.0276826, + 0.0260923, + 0.0245478, + 0.0230492, + 0.0215968, + 0.0201906, + 0.0188308, + 0.0175175, + 0.0162509, + 0.0150311, + 0.0138581, + 0.0127322, + 0.0116533, + 0.0106217, + 0.00963736, + 0.00870045, + 0.00781104, + 0.00696922, + 0.00617507, + 0.00542867, + 0.00473008, + 0.00407937, + 0.00347661, + 0.00292186, + 0.00241517, + 0.00195659, + 0.00154616, + 0.00118392, + 0.00086991, + 0.000604158, + 0.000386689, + 0.000217525, + 9.66816e-05, + 2.4171e-05, + 0 +}; diff --git a/codec2-dev/src/pilot_coeff.h b/codec2-dev/src/pilot_coeff.h new file mode 100644 index 00000000..66e7501d --- /dev/null +++ b/codec2-dev/src/pilot_coeff.h @@ -0,0 +1,34 @@ +/* Generated by pilot_coeff_file() Octave function */ + +const float pilot_coeff[]={ + 0.00204705, + 0.00276339, + 0.00432595, + 0.00697042, + 0.0108452, + 0.0159865, + 0.0223035, + 0.029577, + 0.0374709, + 0.045557, + 0.0533491, + 0.0603458, + 0.0660751, + 0.070138, + 0.0722452, + 0.0722452, + 0.070138, + 0.0660751, + 0.0603458, + 0.0533491, + 0.045557, + 0.0374709, + 0.029577, + 0.0223035, + 0.0159865, + 0.0108452, + 0.00697042, + 0.00432595, + 0.00276339, + 0.00204705 +}; diff --git a/codec2-dev/unittest/Makefile.am b/codec2-dev/unittest/Makefile.am index 60a4aa5a..d5b1d934 100644 --- a/codec2-dev/unittest/Makefile.am +++ b/codec2-dev/unittest/Makefile.am @@ -52,7 +52,7 @@ scalarlsptest_SOURCES = scalarlsptest.c ../src/quantise.c ../src/lpc.c ../src/ls scalarlsptest_LDADD = $(lib_LTLIBRARIES) scalarlsptest_LDFLAGS = $(LIBS) -tfdmdv_SOURCES = tfdmdv.c ../src/fdmdv.c +tfdmdv_SOURCES = tfdmdv.c ../src/fdmdv.c ../src/fft.c ../src/kiss_fft.c tfdmdv_LDADD = $(lib_LTLIBRARIES) tfdmdv_LDFLAGS = $(LIBS) diff --git a/codec2-dev/unittest/Makefile.in b/codec2-dev/unittest/Makefile.in index 801a6e3f..b705e5b3 100644 --- a/codec2-dev/unittest/Makefile.in +++ b/codec2-dev/unittest/Makefile.in @@ -74,7 +74,8 @@ am_tcodec2_OBJECTS = tcodec2.$(OBJEXT) quantise.$(OBJEXT) \ interp.$(OBJEXT) pack.$(OBJEXT) $(am__objects_1) tcodec2_OBJECTS = $(am_tcodec2_OBJECTS) tcodec2_DEPENDENCIES = -am_tfdmdv_OBJECTS = tfdmdv.$(OBJEXT) fdmdv.$(OBJEXT) +am_tfdmdv_OBJECTS = tfdmdv.$(OBJEXT) fdmdv.$(OBJEXT) fft.$(OBJEXT) \ + kiss_fft.$(OBJEXT) tfdmdv_OBJECTS = $(am_tfdmdv_OBJECTS) tfdmdv_DEPENDENCIES = am_tinterp_OBJECTS = tinterp.$(OBJEXT) sine.$(OBJEXT) fft.$(OBJEXT) \ @@ -269,7 +270,7 @@ tcodec2_LDFLAGS = $(LIBS) scalarlsptest_SOURCES = scalarlsptest.c ../src/quantise.c ../src/lpc.c ../src/lsp.c ../src/dump.c ../src/fft.c ../src/kiss_fft.c $(CODEBOOKS) scalarlsptest_LDADD = $(lib_LTLIBRARIES) scalarlsptest_LDFLAGS = $(LIBS) -tfdmdv_SOURCES = tfdmdv.c ../src/fdmdv.c +tfdmdv_SOURCES = tfdmdv.c ../src/fdmdv.c ../src/fft.c ../src/kiss_fft.c tfdmdv_LDADD = $(lib_LTLIBRARIES) tfdmdv_LDFLAGS = $(LIBS) all: all-am diff --git a/codec2-dev/unittest/tfdmdv.c b/codec2-dev/unittest/tfdmdv.c index 4c3c5de6..f2b3bd63 100644 --- a/codec2-dev/unittest/tfdmdv.c +++ b/codec2-dev/unittest/tfdmdv.c @@ -49,11 +49,19 @@ int main(int argc, char *argv[]) COMP tx_symbols[(NC+1)]; COMP tx_baseband[(NC+1)][M]; COMP tx_fdm[M]; + float rx_fdm[M]; + float foff; int tx_bits_log[FDMDV_BITS_PER_FRAME*FRAMES]; COMP tx_symbols_log[(NC+1)*FRAMES]; COMP tx_baseband_log[(NC+1)][M*FRAMES]; COMP tx_fdm_log[M*FRAMES]; + COMP pilot_baseband1_log[NPILOTBASEBAND*FRAMES]; + COMP pilot_baseband2_log[NPILOTBASEBAND*FRAMES]; + COMP pilot_lpf1_log[NPILOTLPF*FRAMES]; + COMP pilot_lpf2_log[NPILOTLPF*FRAMES]; + COMP s1_log[32*FRAMES]; + COMP s2_log[32*FRAMES]; FILE *fout; int f,c,i; @@ -61,12 +69,22 @@ int main(int argc, char *argv[]) fdmdv = fdmdv_create(); for(f=0; fprev_tx_symbols, tx_bits, &fdmdv->tx_pilot_bit); memcpy(fdmdv->prev_tx_symbols, tx_symbols, sizeof(COMP)*(NC+1)); tx_filter(tx_baseband, tx_symbols, fdmdv->tx_filter_memory); fdm_upconvert(tx_fdm, tx_baseband, fdmdv->phase_tx, fdmdv->freq); - + + for(i=0; ipilot_baseband1, sizeof(COMP)*NPILOTBASEBAND); + memcpy(&pilot_baseband2_log[f*NPILOTBASEBAND], fdmdv->pilot_baseband2, sizeof(COMP)*NPILOTBASEBAND); + memcpy(&pilot_lpf1_log[f*NPILOTLPF], fdmdv->pilot_lpf1, sizeof(COMP)*NPILOTLPF); + memcpy(&pilot_lpf2_log[f*NPILOTLPF], fdmdv->pilot_lpf2, sizeof(COMP)*NPILOTLPF); + memcpy(&s1_log[f*32], fdmdv->s1, sizeof(COMP)*32); + memcpy(&s2_log[f*32], fdmdv->s2, sizeof(COMP)*32); } - codec2_destroy(fdmdv); - /* dump logs to Octave file for evaluation by tfdmdv.m Octave script */ fout = fopen("tfdmdv_out.txt","wt"); @@ -88,8 +110,17 @@ int main(int argc, char *argv[]) octave_save_complex(fout, "tx_symbols_log_c", tx_symbols_log, 1, (NC+1)*FRAMES); octave_save_complex(fout, "tx_baseband_log_c", (COMP*)tx_baseband_log, (NC+1), M*FRAMES); octave_save_complex(fout, "tx_fdm_log_c", (COMP*)tx_fdm_log, 1, M*FRAMES); + octave_save_complex(fout, "pilot_lut_c", (COMP*)fdmdv->pilot_lut, 1, NPILOT_LUT); + octave_save_complex(fout, "pilot_baseband1_log_c", pilot_baseband1_log, 1, NPILOTBASEBAND*FRAMES); + octave_save_complex(fout, "pilot_baseband2_log_c", pilot_baseband2_log, 1, NPILOTBASEBAND*FRAMES); + octave_save_complex(fout, "pilot_lpf1_log_c", pilot_lpf1_log, 1, NPILOTLPF*FRAMES); + octave_save_complex(fout, "pilot_lpf2_log_c", pilot_lpf2_log, 1, NPILOTLPF*FRAMES); + octave_save_complex(fout, "s1_log_c", s1_log, 1, 32*FRAMES); + octave_save_complex(fout, "s2_log_c", s2_log, 1, 32*FRAMES); fclose(fout); + codec2_destroy(fdmdv); + return 0; } -- 2.25.1