fft input of lpf_peak_pick working
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sat, 21 Apr 2012 07:11:44 +0000 (07:11 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sat, 21 Apr 2012 07:11:44 +0000 (07:11 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@373 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/fdmdv.m
codec2-dev/octave/fdmdv_demod.m
codec2-dev/octave/tfdmdv.m
codec2-dev/src/fdmdv.c
codec2-dev/src/fdmdv_internal.h
codec2-dev/src/hanning.h [new file with mode: 0644]
codec2-dev/src/pilot_coeff.h [new file with mode: 0644]
codec2-dev/unittest/Makefile.am
codec2-dev/unittest/Makefile.in
codec2-dev/unittest/tfdmdv.c

index afa5d186e999855433efd277e3649c7bf07db979..be274c3dfab628feecfafb7b568c44b107a608fe 100644 (file)
@@ -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
index e1fb3b43bdc8575865d9239669548f4c1924e9b9..2ba1043729048a2e1cfbf7add8425b880d0c6b44 100644 (file)
@@ -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
   % ---------------------------------------------------------------------
index ad606d2a2155dc01270a673e991122f3647222d6..020a5840dcadb0f1ddc2cd5745679c2400389643 100644 (file)
@@ -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);
index 895c6efa41c46da3e8ce16a360949e4a618ebacb..7f0b9d77c434e9db6094d76cbc09cb1768d20f31 100644 (file)
 #include <assert.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <string.h>
 #include <math.h>
 
 #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; c<NC/2; c++) {
        carrier_freq = (-NC/2 + c)*FSEP + FCENTRE;
        f->freq[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; i<NPILOTBASEBAND; i++) {
+       f->pilot_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; i<NPILOTLPF; i++) {
+       f->pilot_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; i<M; i++) {
+       tx_baseband[i] = 0.0; 
+       for(j=M-1,k=M-i-1; j<NFILTER; j+=M,k+=M)
+           tx_baseband[i] += M * filter_mem[j] * gt_alpha5_root[k];
+    }
+
+    /* shift memory, inserting zeros at end */
+
+    for(i=0; i<NFILTER-M; i++)
+       filter_mem[i] = filter_mem[i+M];
+
+    for(i=NFILTER-M; i<NFILTER; i++)
+       filter_mem[i] = 0.0;
+
+    /* upconvert */
+
+    for(i=0; i<M; i++) {
+       *phase = cmult(*phase, *freq);
+       pilot_fdm[i].real = sqrt(2)*2*tx_baseband[i] * phase->real;
+       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<NFILTER; i++)
+       pilot_filter_mem[i] = 0.0;
+
+    /* discard first 4 symbols as filter memory is filling, just keep
+       last four symbols */
+
+    for(f=0; f<8; f++) {
+       generate_pilot_fdm(pilot, &pilot_rx_bit, &pilot_symbol, pilot_filter_mem, &pilot_phase, pilot_freq);
+       if (f >= 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<NPILOTLPF-nin; i++)
+       pilot_lpf[i] = pilot_lpf[nin+i];
+    for(i=NPILOTLPF-nin, j=0; i<NPILOTLPF; i++,j++) {
+       pilot_lpf[i].real = 0.0; pilot_lpf[i].imag = 0.0;
+       for(k=0; k<NPILOTCOEFF; k++)
+           pilot_lpf[i] = cadd(pilot_lpf[i], fcmult(pilot_coeff[k], pilot_baseband[j+k]));
+    }
+
+    /* decimate to improve DFT resolution, window and DFT */
+
+    mpilot = FS/(2*200);  /* calc decimation rate given new sample rate is twice LPF freq */
+    for(i=0; i<MPILOTFFT; i++) {
+       s[i].real = 0.0; s[i].imag = 0.0;
+    }
+
+    for(i=0,j=0; i<NPILOTLPF; i+=mpilot,j++) {
+       s[j] = fcmult(hanning[i], pilot_lpf[i]);
+       //s[j] = pilot_lpf[i];
+    }
+#ifdef TT
+    fft(&s[0].real, MPILOTFFT, 1);
+
+    /* peak pick and convert to Hz */
+
+    imax = 0.0;
+    ix = 0;
+    for(i=0; i<MPILOTFFT; i++) {
+       mag = s[i].real*s[i].real + s[i].imag*s[i].imag;
+       if (mag > 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; i<nin; i++) {
+       pilot[i] = f->pilot_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; i<NPILOTBASEBAND-nin; i++) {
+       f->pilot_baseband1[i] = f->pilot_baseband1[i+nin];
+       f->pilot_baseband2[i] = f->pilot_baseband2[i+nin];
+    }
+
+    for(i=0,j=NPILOTBASEBAND-nin; i<nin; i++,j++) {
+               f->pilot_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; i<MPILOTFFT; i++) {
+    // printf("%f %f\n", f->s1[i].real, f->s1[i].imag);
+    //}
+
+#ifdef T
+    if (max1 > max2)
+       foff = foff1;
+    else
+       foff = foff2;
+       
+    return foff;
+#endif
+    return 0;
+}
index 590e4a8b77e9905e140739530cc03b9dc5ca8988..68d334b0db87e1c25d999c36f8753a25f9982b6c 100644 (file)
@@ -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                                                    */
 #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 (file)
index 0000000..81d88dc
--- /dev/null
@@ -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 (file)
index 0000000..66e7501
--- /dev/null
@@ -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
+};
index 60a4aa5a16cd5240a91aacc80002b469b85dee2c..d5b1d934fe4f9739314926a353ffeb8155759b40 100644 (file)
@@ -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)
 
index 801a6e3f901a5a9f0caa9b29ec636a67d8084a85..b705e5b398bed9d01bbeb4a97b66d865a1285a65 100644 (file)
@@ -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
index 4c3c5de69e16a559ed555311157bc1d9aecb286a..f2b3bd63286ae1c83e15d5dad9de244954b3414c 100644 (file)
@@ -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; f<FRAMES; f++) {
+
+       /* modulator */
+
        fdmdv_get_test_bits(fdmdv, tx_bits);
        bits_to_dqpsk_symbols(tx_symbols, fdmdv->prev_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; i<M; i++)
+           rx_fdm[i] = tx_fdm[i].real;
+
+       /* demodulator */
+
+       foff = rx_est_freq_offset(fdmdv, rx_fdm, M);
        /* save log of outputs */
 
        memcpy(&tx_bits_log[FDMDV_BITS_PER_FRAME*f], tx_bits, sizeof(int)*FDMDV_BITS_PER_FRAME);
@@ -75,10 +93,14 @@ int main(int argc, char *argv[])
            for(i=0; i<M; i++)
                tx_baseband_log[c][f*M+i] = tx_baseband[c][i]; 
        memcpy(&tx_fdm_log[M*f], tx_fdm, sizeof(COMP)*M);
+       memcpy(&pilot_baseband1_log[f*NPILOTBASEBAND], fdmdv->pilot_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;
 }