spend a day working on coarse freq est, including ofdm_dev.m functions to graph stati...
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 8 May 2018 00:40:51 +0000 (00:40 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 8 May 2018 00:40:51 +0000 (00:40 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@3583 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/ofdm_dev.m
codec2-dev/octave/ofdm_ldpc_rx.m
codec2-dev/octave/ofdm_lib.m
codec2-dev/octave/ofdm_load_const.m

index d68a0b29ffa8879b3eb36035768e0fd6b35cccbd..1d47f882cfc0c7dd1893a73f4aa7f64fdff5e692 100644 (file)
@@ -925,7 +925,11 @@ function run_curves_snr
 end
 
 
-% Run an acquisition test, returning vectors of estimation errors
+% Run an acquisition test, returning vectors of estimation errors.
+% Generates a vector of rx samples.  Acuisition simultion is on a
+% continuous signal.  Freq est will improve over time as we have an
+% averaging statistic.  This doesn't really test sync prob on a no
+% signal -> signal transition, which is tough at these SNRs.
 
 function [delta_ct delta_foff timing_mx_log] = acquisition_test(Ntests=10, EbNodB=100, foff_hz=0, hf_en=0, fine_en=0)
 
@@ -935,18 +939,19 @@ function [delta_ct delta_foff timing_mx_log] = acquisition_test(Ntests=10, EbNod
 
   sim_in.Nsec = (Ntests+1)*(sim_in.Ns+1)/sim_in.Rs;
 
-  sim_in.EbNodB = EbNodB;
+  sim_in.EbNodB = EbNodB;  % note uncoded modem operationg point, e.g -1dB for AWGN
   sim_in.verbose = 0;
   sim_in.hf_en = hf_en;
-  sim_in.foff_hz = foff_hz; 
+  sim_in.foff_hz = foff_hz;
+  sim_in.gain = 1;
   sim_in.timing_en = 1;
   sim_in.foff_est_en = 1;
   sim_in.phase_est_en = 1;
   sim_in.ldpc_en = 0;
   
   [sim_out rx states] = run_sim(sim_in);
-  
-  states.verbose = 2;
+
+  states.verbose = 0;
   
   % set up acquistion 
 
@@ -955,9 +960,9 @@ function [delta_ct delta_foff timing_mx_log] = acquisition_test(Ntests=10, EbNod
 
   % test fine or acquisition over test signal
 
-  delta_ct = []; delta_foff = []; timing_mx_log = [];
+  delta_ct = []; delta_foff = []; timing_mx_log = []; foff_metric_log = [];
 
-  % a fine simulation is a bit like what ofsd_demod() does, just searches a few samples
+  % a fine simulation is a bit like what ofdm_demod() does, just searches a few samples
   % either side of current coarse est
   
   if fine_en
@@ -969,21 +974,25 @@ function [delta_ct delta_foff timing_mx_log] = acquisition_test(Ntests=10, EbNod
     while timing_instant < (length(rx) - (Nsamperframe + length(rate_fs_pilot_samples) + window_width))
       st = timing_instant - ceil(window_width/2); 
       en = st + Nsamperframe-1 + length(rate_fs_pilot_samples) + window_width-1;
-      [ft_est foff_est] = coarse_sync(states, rx(st:en), rate_fs_pilot_samples);
+      [ft_est foff_est] = est_timing(states, rx(st:en), rate_fs_pilot_samples);
       printf("ft_est: %d timing_instant %d %d\n", ft_est, timing_instant, mod(timing_instant, Nsamperframe));
       timing_instant += Nsamperframe + ft_est - ceil(window_width/2);
       delta_t = [delta_ft ft_est - ceil(window_width/2)];
     end
   else
-    % coarse is like initial acquiistion - we have no idea of timing or freq offset
-    % for coarse we just use constant window shifts to simulate a bunch of trials
+  
+    % coarse/acquiistion - we have no idea of timing or freq offset
+    % for coarse we just use constant window shifts to simulate a
+    % bunch of trials, this also simulates averaging of freq est
+    % metric over time as we receiver more and more frames
 
     st = 0.5*Nsamperframe; 
     en = 2.5*Nsamperframe - 1;    % note this gives Nsamperframe possibilities for coarse timing
     ct_target = Nsamperframe/2;   % actual known position of correct coarse timing
 
     for w=1:Nsamperframe:length(rx)-4*Nsamperframe
-      [ct_est foff_est timing_valid timing_mx] = coarse_sync(states, real(rx(w+st:w+en)), rate_fs_pilot_samples);
+      [ct_est timing_valid timing_mx] = est_timing(states, real(rx(w+st:w+en)), rate_fs_pilot_samples);
+      [foff_est states] = est_freq_offset(states, real(rx(w+st:w+en)), rate_fs_pilot_samples, ct_est);
       if states.verbose
         printf("w: %5d ct_est: %4d foff_est: %5.1f timing_mx: %3.2f\n", w, ct_est, foff_est, timing_mx);
       end
@@ -993,110 +1002,150 @@ function [delta_ct delta_foff timing_mx_log] = acquisition_test(Ntests=10, EbNod
       delta_ct = [delta_ct ct_est-ct_target];
       delta_foff = [delta_foff (foff_est-foff_hz)];
       timing_mx_log = [timing_mx_log; timing_mx];
+      foff_metric_log = [foff_metric_log states.foff_metric];
     end
   end
 
+  if states.verbose > 1
+    printf("mean: %f std: %f\n", mean(delta_foff), std(delta_foff));
+    figure(1); clf; plot(delta_foff);
+    figure(2); clf; plot(foff_metric_log,'+');
+  end
+  
 endfunction
 
 
 #{
-   Run some tests for various acquisition conditions. Probability of
-   acquistion is what matters, e.g. if it's 50% we can expect sync
-   within 2 frames
 
-  Results on 17 Mar 2018:
-  
-  foff Hz  Channel Eb/No  P(t)  P(f)
-  -20      AWGN    -1     0.99  0.42
-  -20      HF       3     0.94  0.43
-  +20      AWGN    -1     1.00  0.37
-  +20      HF       3     0.93  0.24
-  -5       AWGN    -1     1.00  0.56
-  -5       HF       3     0.98  0.50
-  +5       AWGN    -1     1.00  0.54
-  +5       HF       3     0.98  0.39
-   0       AWGN    10     1.00  0.98
-   0       HF      10     1.00  0.65
-
-   -> Suggests we will sync up in 2-3 frames which is pretty cool.  Would be good
-      to have freq est about as reliable as timing est.....
+   Generates aquisistion statistics for AWGN and HF channels for
+   continuous signals. Probability of acquistion is what matters,
+   e.g. if it's 50% we can expect sync within 2 frames.
+
 #}
 
-function acquisition_histograms(fine_en = 0, foff)
+function res = acquisition_histograms(fine_en = 0, foff, EbNoAWGN=-1, EbNoHF=3, verbose=1)
   Fs = 8000;
   Ntests = 100;
 
   % allowable tolerance for acquistion
 
-  ftol_hz = 2.0;            % fine freq can track this out
+  ftol_hz = 1.5;            % we can sync up on this
   ttol_samples = 0.002*Fs;  % 2ms, ie CP length
 
-  % AWGN channel operating point
+  % AWGN channel at uncoded Eb/No operating point
 
-  [dct dfoff] = acquisition_test(Ntests, -1, foff, 0, fine_en);
+  [dct dfoff] = acquisition_test(Ntests, EbNoAWGN, foff, 0, fine_en);
 
   % Probability of acquistion is what matters, e.g. if it's 50% we can
   % expect sync within 2 frames
 
-  printf("AWGN P(time offset acq) = %3.2f\n", length(find (abs(dct) < ttol_samples))/length(dct));
+  PtAWGN = length(find (abs(dct) < ttol_samples))/length(dct);
+  printf("AWGN P(time offset acq) = %3.2f\n", PtAWGN);
   if fine_en == 0
-    printf("AWGN P(freq offset acq) = %3.2f\n", length(find (abs(dfoff) < ftol_hz))/length(dfoff));
+    PfAWGN = length(find (abs(dfoff) < ftol_hz))/length(dfoff);
+    printf("AWGN P(freq offset acq) = %3.2f\n", PfAWGN);
   end
 
-  figure(1)
-  hist(dct(find (abs(dct) < ttol_samples)))
-  title('Coarse Timing error AWGN')
-  if fine_en == 0
-    figure(2)
-    hist(dfoff)
-  title('Coarse Freq error AWGN')
-  end
+  if verbose
+    figure(1); clf;
+    hist(dct(find (abs(dct) < ttol_samples)))
+    t = sprintf("Coarse Timing Error AWGN EbNo = %3.2f foff = %3.1f", EbNoAWGN, foff);
+    title(t)
+    if fine_en == 0
+      figure(2)
+      hist(dfoff(find(abs(dfoff) < 2*ftol_hz)))
+      t = sprintf("Coarse Freq Error AWGN EbNo = %3.2f foff = %3.1f", EbNoAWGN, foff);
+      title(t);
+    end
+ end
 
-  % HF channel operating point
+  % HF channel at uncoded operating point
 
-  [dct dfoff] = acquisition_test(Ntests, -3, foff, 1, fine_en);
+  [dct dfoff] = acquisition_test(Ntests, EbNoHF, foff, 1, fine_en);
 
-  printf("HF P(time offset acq) = %3.2f\n", length(find (abs(dct) < ttol_samples))/length(dct));
+  PtHF = length(find (abs(dct) < ttol_samples))/length(dct);
+  printf("HF P(time offset acq) = %3.2f\n", PtHF);
   if fine_en == 0
-    printf("HF P(freq offset acq) = %3.2f\n", length(find (abs(dfoff) < ftol_hz))/length(dfoff));
+    PfHF = length(find (abs(dfoff) < ftol_hz))/length(dfoff)
+    printf("HF P(freq offset acq) = %3.2f\n", PfHF);
   end
 
-  figure(3)
-  hist(dct(find (abs(dct) < ttol_samples)))
-  title('Coarse Timing error HF')
-  if fine_en == 0
-    figure(4)
-    hist(dfoff)
-    title('Coarse Freq error HF')
+  if verbose
+    figure(3); clf;
+    hist(dct(find (abs(dct) < ttol_samples)))
+    t = sprintf("Coarse Timing Error HF EbNo = %3.2f foff = %3.1f", EbNoHF, foff);
+    title(t)
+    if fine_en == 0
+      figure(4)
+      hist(dfoff(find(abs(dfoff) < 2*ftol_hz)))
+      t = sprintf("Coarse Freq Error HF EbNo = %3.2f foff = %3.1f", EbNoHF, foff);
+      title(t);
+    end
   end
+  
+  res = [PtAWGN PfAWGN PtHF PfHF];
+endfunction
 
+
+% plot some curves of Acquisition probability against EbNo and freq offset
+
+function acquistion_curves
+
+  EbNo = [-1 2 5 8];
+  %foff = [-20 -15 -10 -5 0 5 10 15 20];
+  foff = [-15 -5 0 5 15];
+  cc = ['b' 'g' 'k' 'c' 'm'];
+  
+  figure(1); clf; hold on; title('P(timing) AWGN'); xlabel('Eb/No dB'); legend('location', 'southeast');
+  figure(2); clf; hold on; title('P(freq) AWGN'); xlabel('Eb/No dB'); legend('location', 'southeast');
+  figure(3); clf; hold on; title('P(timing) HF'); xlabel('Eb/No dB'); legend('location', 'southeast');
+  figure(4); clf; hold on; title('P(freq) HF'); xlabel('Eb/No dB'); legend('location', 'southeast');
+  
+  for f = 1:length(foff)
+    afoff = foff(f);
+    res_log = [];
+    for e = 1:length(EbNo)
+      aEbNo = EbNo(e);
+      res = zeros(1,4);
+      res = acquisition_histograms(fine_en = 0, afoff, aEbNo, aEbNo+4, verbose = 0);
+      res_log = [res_log; res];
+    end
+    figure(1); l = sprintf('%c+-;%3.1f Hz;', cc(f), afoff); plot(EbNo, res_log(:,1), l);
+    figure(2); l = sprintf('%c+-;%3.1f Hz;', cc(f), afoff); plot(EbNo, res_log(:,3), l);
+    figure(3); l = sprintf('%c+-;%3.1f Hz;', cc(f), afoff); plot(EbNo+4, res_log(:,2), l);
+    figure(4); l = sprintf('%c+-;%3.1f Hz;', cc(f), afoff); plot(EbNo+4, res_log(:,4), l);
+  end
+
+  figure(1); print('-deps', '-color', "ofdm_dev_acq_curves_time_awgn.eps")
+  figure(2); print('-deps', '-color', "ofdm_dev_acq_curves_freq_awgn.eps")
+  figure(3); print('-deps', '-color', "ofdm_dev_acq_curves_time_hf.eps")
+  figure(4); print('-deps', '-color', "ofdm_dev_acq_curves_freq_hf.eps")
 endfunction
 
 
 % Used to develop sync state machine - in particular a metric to show
 % we are out of sync, or have sync with a bad freq offset est, or have
-% lost nodem signal
+% lost modem signal
 
 function sync_metrics(x_axis = 'EbNo')
   Fs      = 8000;
   Ntests  = 4;
   f_offHz = [-25:25];
-  EbNodB  = [-10 4 20];
+  EbNodB  = [-10 0 3 6 10 20];
 
-  mean_mx1_log = mean_mx2_log = mean_dfoff_log = [];
+  mean_mx1_log = mean_dfoff_log = [];
   for f = 1:length(f_offHz)
     af_offHz = f_offHz(f);
-    mean_mx1_row = mean_mx2_row = mean_dfoff_row = [];
+    mean_mx1_row = mean_dfoff_row = [];
     for e = 1:length(EbNodB)
       aEbNodB = EbNodB(e);
       [dct dfoff timing_mx_log] = acquisition_test(Ntests, aEbNodB, af_offHz);
       mean_mx1 = mean(timing_mx_log(:,1));
-      mean_mx2 = mean(timing_mx_log(:,2));
-      printf("f_offHz: %5.2f EbNodB: % 6.2f mx1: %3.2f mx2: %3.2f\n", af_offHz, aEbNodB, mean_mx1, mean_mx2);
-      mean_mx1_row = [mean_mx1_row mean_mx1]; mean_mx2_row = [mean_mx2_row mean_mx2];
+      printf("f_offHz: %5.2f EbNodB: % 6.2f mx1: %3.2f\n", af_offHz, aEbNodB, mean_mx1);
+      mean_mx1_row = [mean_mx1_row mean_mx1];
       mean_dfoff_row = [mean_dfoff_row mean(dfoff)];
     end
-    mean_mx1_log = [mean_mx1_log; mean_mx1_row]; mean_mx2_log = [mean_mx2_log; mean_mx2_row];
+    mean_mx1_log = [mean_mx1_log; mean_mx1_row];
     mean_dfoff_log = [mean_dfoff_log; mean_dfoff_row];
   end
 
@@ -1107,14 +1156,10 @@ function sync_metrics(x_axis = 'EbNo')
       leg1 = sprintf("b+-;mx1 %4.1f Hz;", f_offHz(f));
       plot(EbNodB, mean_mx1_log(f,:), leg1)
     end
-    for f = 1:length(f_offHz)
-      leg2 = sprintf("g*-;mx2 %4.1f Hz;", f_offHz(f));
-      plot(EbNodB, mean_mx2_log(f,:), leg2)
-    end
     hold off;
     xlabel('Eb/No (dB)');
     ylabel('Coefficient')
-    title('Pilot Correlation Metric 1 and 2 against Eb/No for different Freq Offsets');
+    title('Pilot Correlation Metric against Eb/No for different Freq Offsets');
     legend("location", "northwest"); legend("boxoff");
     axis([min(EbNodB) max(EbNodB) 0 1.2])
     print('-deps', '-color', "ofdm_dev_pilot_correlation_ebno.eps")
@@ -1122,19 +1167,16 @@ function sync_metrics(x_axis = 'EbNo')
 
   if strcmp(x_axis,'freq')
     % x axis is freq
+
     for e = 1:length(EbNodB)
       if e == 2, hold on, end;
       leg1 = sprintf("b+-;mx1 %3.0f dB;", EbNodB(e));
       plot(f_offHz, mean_mx1_log(:,e), leg1)
     end
-    for e = 1:length(EbNodB)
-      leg2 = sprintf("g*-;mx2 %3.0f dB;", EbNodB(e));
-      plot(f_offHz, mean_mx2_log(:,e), leg2)
-    end
     hold off;
     xlabel('freq offset (Hz)');
     ylabel('Coefficient')
-    title('Pilot Correlation Metric 1 and 2 against Freq Offset for different Eb/No dB');
+    title('Pilot Correlation Metric against Freq Offset for different Eb/No dB');
     legend("location", "northwest"); legend("boxoff");
     axis([min(f_offHz) max(f_offHz) 0 1.2])
     print('-deps', '-color', "ofdm_dev_pilot_correlation_freq.eps")
@@ -1157,6 +1199,7 @@ function sync_metrics(x_axis = 'EbNo')
 endfunction
 
 
+
 % ---------------------------------------------------------
 % choose simulation to run here 
 % ---------------------------------------------------------
@@ -1166,10 +1209,12 @@ more off;
 
 init_cml('~/cml/');
 
-run_single(10);
+%run_single(10);
 %run_curves
 %run_curves_estimators
-%acquisition_histograms(0, 0)
-%acquisition_test(Ntests=3, EbNodB=100, foff_hz=0)
-%sync_metrics('freq')
+%acquisition_histograms(fin_en=0, foff_hz=-15, EbNoAWGN=-1, EbNoHF=3)
+%acquisition_test(Ntests=100, EbNodB=-1, foff_hz=-10, hf_en=0)
+sync_metrics('freq')
 %run_curves_snr
+%acquisition_dev(Ntests=10, EbNodB=100, foff_hz=0)
+%acquistion_curves
index f37eafa7599c40993668de3655fa386b08681604..4fedb11d509a9b1fc2dfa69ade80f00fc7e272f8 100644 (file)
@@ -167,7 +167,10 @@ function ofdm_ldpc_rx(filename, interleave_frames = 1, error_pattern_filename)
         [rx_codeword parity_checks] = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, rx_np_de(st:en)/mean_amp, min(EsNo,30), rx_amp_de(st:en)/mean_amp);
         Nerrs = code_param.data_bits_per_frame - max(parity_checks);
         %printf("Nerrs: %d\n", Nerrs);
-        if Nerrs < 10
+
+        % note we just go straight into sync if interleave_frames == 1
+        
+        if (Nerrs < 10) || (interleave_frames == 1)
           % sucessful(ish) decode!
           next_sync_state_interleaver = 'synced';
           states.frame_count_interleaver = interleave_frames;
index 0be7425378deb5366870f0a22597454934e0147c..cb1152124e5730585c326a44c33be519fed32383 100644 (file)
@@ -41,14 +41,16 @@ function out = freq_shift(in, foff, Fs)
   end
 endfunction
 
-% Correlates the OFDM pilot symbol samples with a window of received
-% samples to determine the most likely timing offset.  Combines two
-% frames pilots so we need at least Nsamperframe+M+Ncp samples in rx.
-% Also determines frequency offset at maximimum correlation.  Can be
-% used for acquisition (coarse timing and freq offset), and fine
-% timing
-
-function [t_est foff_est timing_valid timing_mx] = coarse_sync(states, rx, rate_fs_pilot_samples)
+
+#{
+  Correlates the OFDM pilot symbol samples with a window of received
+  samples to determine the most likely timing offset.  Combines two
+  frames pilots so we need at least Nsamperframe+M+Ncp samples in rx.
+
+  Can be used for acquisition (coarse timing), and fine timing.
+#}
+
+function [t_est timing_valid timing_mx] = est_timing(states, rx, rate_fs_pilot_samples)
     ofdm_load_const;
     Npsam = length(rate_fs_pilot_samples);
 
@@ -71,43 +73,42 @@ function [t_est foff_est timing_valid timing_mx] = coarse_sync(states, rx, rate_
     [timing_mx t_est] = max(corr);
     timing_valid = timing_mx > timing_mx_thresh;
     
-    if verbose > 2
+    if verbose > 1
       printf("   mx: %f timing_est: %d timing_valid: %d\n", timing_mx, t_est, timing_valid);
     end
-        
+
+endfunction
+
+#{
+  Determines frequency offset at current timing estimate, used for
+  coarse freq offset estimation during acquisition.
+
+  Freq offset is based on an averaged statistic that was found to be
+  necessary to generate good quality estimates.
+
+  Keep calling it when in trial or actual sync to keep statistic
+  updated, in case we lose sync.
+#}
+
+function [foff_est states] = est_freq_offset(states, rx, rate_fs_pilot_samples, t_est)
+    ofdm_load_const;
+    Npsam = length(rate_fs_pilot_samples);
+
+    % Freq offset can be considered as change in phase over two halves
+    % of pilot symbols.  We average this statistic over this and next
+    % frames pilots.
+
     p1 = rx(t_est:t_est+Npsam/2-1) * rate_fs_pilot_samples(1:Npsam/2)';
     p2 = rx(t_est+Npsam/2:t_est+Npsam-1) * rate_fs_pilot_samples(Npsam/2+1:Npsam)';
     p3 = rx(t_est+Nsamperframe:t_est+Nsamperframe+Npsam/2-1) * rate_fs_pilot_samples(1:Npsam/2)';
     p4 = rx(t_est+Nsamperframe+Npsam/2:t_est+Nsamperframe+Npsam-1) * rate_fs_pilot_samples(Npsam/2+1:Npsam)';
    
     Fs1 = Fs/(Npsam/2);
-    foff_est = Fs1*angle(conj(p1)*p2 + conj(p3)*p4)/(2*pi);
-        
-    if verbose > 1
-      figure(7); clf;
-      plot(abs(corr))
-
-      figure(8)
-      subplot(211)
-      plot(real(rate_fs_pilot_samples))
-      hold on; plot(real(rx(t_est:t_est+Npsam-1)),'g'); hold off
-      subplot(212)
-      plot(imag(rate_fs_pilot_samples))
-      hold on; plot(imag(rx(t_est:t_est+Npsam-1)),'g'); hold off
-
-      figure(9)
-      dp = rx(t_est:t_est+Npsam-1) .* conj(rate_fs_pilot_samples);
-      subplot(211); plot(real(dp));
-      subplot(212); plot(imag(dp));
-
-      figure(10)
-      plot(dp,'+')
-      
-      figure(11)
-      plot([p1 p2; p3 p4], '+')
-      
-    end
 
+    % averaging metric was found to be really important for reliable acquisition at low SNRs
+
+    states.foff_metric = 0.9*states.foff_metric + 0.1*(conj(p1)*p2 + conj(p3)*p4);
+    foff_est = Fs1*angle(states.foff_metric)/(2*pi);    
 endfunction
 
 
@@ -192,13 +193,20 @@ function states = ofdm_init(bps, Rs, Tcp, Ns, Nc)
   states.timing_valid = 0;
   states.timing_mx = 0;
   states.coarse_foff_est_hz = 0;
+
+  states.foff_metric = 0;
   
   % generate OFDM pilot symbol, used for timing and freq offset est
 
   rate_fs_pilot_samples = states.pilots * W/states.M;
-  states.rate_fs_pilot_samples = [rate_fs_pilot_samples(states.M-states.Ncp+1:states.M) rate_fs_pilot_samples];
 
-  % pre-compute a constant used in coarse_sync()
+  % During tuning it was found that not inclduing the cyc prefix in
+  % rate_fs_pilot_samples produced better fest results
+  
+  %states.rate_fs_pilot_samples = [rate_fs_pilot_samples(states.M-states.Ncp+1:states.M) rate_fs_pilot_samples];
+  states.rate_fs_pilot_samples = [zeros(1,states.Ncp) rate_fs_pilot_samples];
+
+  % pre-compute a constant used to detect valid modem frames
 
   Npsam = length(states.rate_fs_pilot_samples);
   states.timing_norm = Npsam*(states.rate_fs_pilot_samples * states.rate_fs_pilot_samples');
@@ -314,7 +322,8 @@ function [timing_valid states] = ofdm_sync_search(states, rxbuf_in)
   % Attempt coarse timing estimate (i.e. detect start of frame)
 
   st = M+Ncp + Nsamperframe + 1; en = st + 2*Nsamperframe; 
-  [ct_est foff_est timing_valid timing_mx] = coarse_sync(states, states.rxbuf(st:en), states.rate_fs_pilot_samples);
+  [ct_est timing_valid timing_mx] = est_timing(states, states.rxbuf(st:en), states.rate_fs_pilot_samples);
+  [foff_est states] = est_freq_offset(states, states.rxbuf(st:en), states.rate_fs_pilot_samples, ct_est);
   if verbose
     printf("  ct_est: %d mx: %3.2f coarse_foff: %4.1f\n", ct_est, timing_mx, foff_est);
   end
@@ -381,7 +390,11 @@ function [rx_bits states aphase_est_pilot_log rx_np rx_amp] = ofdm_demod(states,
     st = M+Ncp + Nsamperframe + 1 - floor(ftwindow_width/2) + (timing_est-1);
     en = st + Nsamperframe-1 + M+Ncp + ftwindow_width-1;
           
-    [ft_est coarse_foff_est_hz timing_valid timing_mx] = coarse_sync(states, rxbuf(st:en) .* exp(-j*woff_est*(st:en)), rate_fs_pilot_samples);
+    [ft_est timing_valid timing_mx] = est_timing(states, rxbuf(st:en) .* exp(-j*woff_est*(st:en)), rate_fs_pilot_samples);
+
+    % keep the freq est statistic updated in case we lose sync, not we supply it with uncorrected rxbuf
+    
+    [unused_foff_est states] = est_freq_offset(states, rxbuf(st:en), states.rate_fs_pilot_samples, ft_est);
 
     if timing_valid
       timing_est = timing_est + ft_est - ceil(ftwindow_width/2);
@@ -660,16 +673,6 @@ function states = sync_state_machine(states, rx_uw)
   if strcmp(states.sync_state,'search') 
 
     if states.timing_valid
-
-      % freq offset est has some bias, but this refinement step fixes bias
-
-      st = M+Ncp + Nsamperframe + 1; en = st + 2*Nsamperframe;
-      woff_est = 2*pi*states.foff_est_hz/Fs;
-      [ct_est foff_est timing_valid timing_mx] = coarse_sync(states, states.rxbuf(st:en) .* exp(-j*woff_est*(st:en)), states.rate_fs_pilot_samples);
-      if verbose
-        printf("  coarse_foff: %4.1f refine: %4.1f combined: %4.1f\n", states.foff_est_hz, foff_est, states.foff_est_hz+foff_est);
-      end
-      states.foff_est_hz += foff_est;
       states.frame_count = 0;
       states.sync_counter = 0;
       states.sync_start = 1;
@@ -705,7 +708,7 @@ function states = sync_state_machine(states, rx_uw)
         states.sync_counter = 0;
       end
 
-      if states.sync_counter == 6
+      if states.sync_counter == 12
         next_state = "search";
         states.sync_state_interleaver = "search";
       end
index dd6342416bd6146ee51d8078668b91e99683c00d..bfcb636eee2e60be4e613818c1c1f11c2ade2634 100644 (file)
@@ -12,7 +12,7 @@ bps = states.bps;
 Nbitsperframe = states.Nbitsperframe;
 Nrowsperframe = states.Nrowsperframe;
 Nsamperframe = states.Nsamperframe;
-timing_mx_thresh = 0.3;
+timing_mx_thresh = 0.25;
 Nuwbits = states.Nuwbits;
 Ntxtbits = states.Ntxtbits;
 tx_uw =  states.tx_uw;