coherent demod simulations
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sat, 19 Jan 2013 06:17:20 +0000 (06:17 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sat, 19 Jan 2013 06:17:20 +0000 (06:17 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@1156 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/fdmdv.m
codec2-dev/octave/fdmdv_demod.m
codec2-dev/octave/fdmdv_demod_coh.m [new file with mode: 0644]
codec2-dev/octave/fdmdv_ut.m
codec2-dev/octave/fdmdv_ut_coh.m

index 432be81ae692a7ba667aea79c6bb5b2b8fbe7704..150a3cd5f66a9878277fe32be78a40c1b395c195 100644 (file)
@@ -30,7 +30,11 @@ global P = 4;          % oversample factor used for rx symbol filtering
 global Nfilter = Nsym*M;
 global Nfiltertiming = M+Nfilter+M;
 alpha = 0.5;
-global snr_coeff = 0.9 % SNR est averaging filter coeff
+global snr_coeff;
+snr_coeff = 0.9;       % SNR est averaging filter coeff
+global Nph;
+Nph = 9;               % number of symbols to estimate phase over
+                       % must be odd number as we take centre symbol
 
 % root raised cosine (Root Nyquist) filter 
 
@@ -382,19 +386,56 @@ function [rx_symbols rx_timing env] = rx_est_timing(rx_filt, rx_baseband, nin)
 endfunction
 
 
-% Phase estimation function - probably won't work over a HF channel
-% Tries to operate over a single symbol but uses phase information from
-% all Nc carriers which should increase the SNR of phase estimate.
-% Maybe phase is coherent over a couple of symbols in HF channel,not
-% sure but it's worth 3dB so worth experimenting or using coherent as
-% an option.
+% Experimental "feed forward" phase estimation function - estimates
+% phase over a windows of Nph (e.g. Nph = 9) symbols.  May not work
+% well on HF channels but lets see.  Has a phase ambiguity of m(pi/4)
+% where m=0,1,2 which needs to be corrected outside of this function
 
-function rx_phase = rx_est_phase(prev_rx_symbols, rx_symbols)
+function [phase_offsets ferr] = rx_est_phase(rx_symbols)
+  global rx_symbols_mem;
+  global prev_phase_offsets;
+  global phase_amb;
+  global Nph;
+  global Nc;
 
-  % modulation strip
+  % keep record of Nph symbols
 
-  rx_phase = angle(sum(rx_symbols .^ 4))/4;
+  rx_symbols_mem(:,1:Nph-1) = rx_symbols_mem(:,2:Nph);
+  rx_symbols_mem(:,Nph) = rx_symbols;
  
+  % estimate and correct phase offset based of modulation stripped samples
+
+  phase_offsets = zeros(Nc+1,1);
+  for c=1:Nc+1
+
+    % rotate QPSK constellation to a single point
+    mod_stripped = abs(rx_symbols_mem(c,:)) .* exp(j*4*angle(rx_symbols_mem(c,:)));
+    
+    % find average phase offset, which will be on -pi/4 .. pi/4
+    sum_real = sum(real(mod_stripped));
+    sum_imag = sum(imag(mod_stripped));
+    phase_offsets(c) = atan2(sum_imag, sum_real)/4;
+
+    % determine if phase has jumped from - -> +    
+    if (prev_phase_offsets(c) < -pi/8) && (phase_offsets(c) > pi/8)
+      phase_amb(c) -= pi/2;
+      if (phase_amb(c) < -pi)
+        phase_amb(c) += 2*pi;
+      end
+    end
+    
+    % determine if phase has jumped from + -> -    
+    if (prev_phase_offsets(c) > pi/8) && (phase_offsets(c) < -pi/8)
+      phase_amb(c) += pi/2;
+      if (phase_amb(c) > pi)
+        phase_amb(c) -= 2*pi;
+      end
+    end
+  end
+
+  ferr = mean(phase_offsets - prev_phase_offsets);
+  prev_phase_offsets = phase_offsets;
+
 endfunction
 
 
@@ -415,6 +456,7 @@ function [rx_bits sync_bit f_err phase_difference] = qpsk_to_bits(prev_rx_symbol
     % map (Nc,1) DQPSK symbols back into an (1,Nc*Nb) array of bits
 
     for c=1:Nc
+      msb = lsb = 0;
       d = phase_difference(c);
       if ((real(d) >= 0) && (imag(d) >= 0))
          msb = 0; lsb = 0;
@@ -467,13 +509,15 @@ function [sig_est noise_est] = snr_update(sig_est, noise_est, phase_difference)
     % vector of mags, one for each carrier.
 
     s = abs(phase_difference);
-
+    
     % signal mag estimate for each carrier is a smoothed version
     % of instantaneous magntitude, this gives us a vector of smoothed
     % mag estimates, one for each carrier.
-
+    
     sig_est = snr_coeff*sig_est + (1 - snr_coeff)*s;
 
+    %printf("s: %f sig_est: %f snr_coeff: %f\n", s(1), sig_est(1), snr_coeff);
+
     % noise mag estimate is distance of current symbol from average
     % location of that symbol.  We reflect all symbols into the first
     % quadrant for convenience.
@@ -486,6 +530,7 @@ function [sig_est noise_est] = snr_update(sig_est, noise_est, phase_difference)
     % noise power estimates, one for each carrier.
 
     noise_est = snr_coeff*noise_est + (1 - snr_coeff)*n;
+
 endfunction
 
 
@@ -525,6 +570,12 @@ function bits = get_test_bits(nbits)
  
   for i=1:nbits
     bits(i) = test_bits(current_test_bit++);
+    %if (mod(i,2) == 0)
+    %  bits(i) = 1;
+    %else
+    %  bits(i) = 0;
+    %end
+    
     if (current_test_bit > Ntest_bits)
       current_test_bit = 1;
     endif
@@ -536,9 +587,8 @@ endfunction
 % Accepts nbits from rx and attempts to sync with test_bits sequence.
 % if sync OK measures bit errors
 
-function [sync bit_errors] = put_test_bits(rx_bits)
+function [sync bit_errors] = put_test_bits(test_bits, rx_bits)
   global Ntest_bits;       % length of test sequence
-  global test_bits;
   global rx_test_bits_mem;
 
   % Append to our memory
@@ -933,3 +983,11 @@ current_test_bit = 1;
 global rx_test_bits_mem;
 rx_test_bits_mem = zeros(1,Ntest_bits);
 
+% Experimental phase estimator states ----------------------
+
+global rx_symbols_mem;
+rx_symbols_mem = zeros(Nc+1, Nph);
+global prev_phase_offsets;
+prev_phase_offsets = zeros(Nc+1, 1);
+global phase_amb;
+phase_amb = zeros(Nc+1, 1);
index 489a616cc2fe8cced600f7a7a79796b23d65b7b0..0e7a4e8050455f658b58b86b76e2e5322f0e35be 100644 (file)
@@ -115,7 +115,7 @@ function fdmdv_demod(rawfilename, nbits, pngname)
 
     % count bit errors if we find a test frame
 
-    [test_frame_sync bit_errors] = put_test_bits(rx_bits);
+    [test_frame_sync bit_errors] = put_test_bits(test_bits, rx_bits);
     if (test_frame_sync == 1)
       total_bit_errors = total_bit_errors + bit_errors;
       total_bits = total_bits + Ntest_bits;
diff --git a/codec2-dev/octave/fdmdv_demod_coh.m b/codec2-dev/octave/fdmdv_demod_coh.m
new file mode 100644 (file)
index 0000000..94b0880
--- /dev/null
@@ -0,0 +1,253 @@
+% fdmdv_demod_coh.m
+%
+% Demodulator function for FDMDV modem (Octave version).  Requires
+% 8kHz sample rate raw files as input.  This version uses experimental
+% psuedo coherent demodulation.
+%
+% Copyright David Rowe 2013
+% This program is distributed under the terms of the GNU General Public License 
+% Version 2
+%
+
+function fdmdv_demod_coh(rawfilename, nbits, pngname)
+
+  fdmdv; % include modem code
+
+  modulation = 'dqpsk';
+
+  fin = fopen(rawfilename, "rb");
+  gain = 1000;
+  frames = nbits/(Nc*Nb);
+
+  prev_rx_symbols = ones(Nc+1,1);
+  foff_phase = 1;
+
+  % BER stats
+
+  total_bit_errors = 0;
+  total_bits = 0;
+  bit_errors_log = [];
+  sync_log = [];
+  test_frame_sync_log = [];
+  test_frame_sync_state = 0;
+
+  % SNR states
+
+  sig_est = zeros(Nc+1,1);
+  noise_est = zeros(Nc+1,1);
+
+  % logs of various states for plotting
+
+  rx_symbols_log = [];
+  rx_timing_log = [];
+  foff_log = [];
+  rx_fdm_log = [];
+  snr_est_log = [];
+
+  % misc states
+
+  nin = M; % timing correction for sample rate differences
+  foff = 0;
+  track_log = [];
+  track = 0;
+  fest_state = 0;
+
+  % psuedo coherent demod states
+
+  rx_symbols_ph_log = [];
+  prev_rx_symbols_ph = ones(Nc+1,1);
+  rx_phase_offsets_log = [];
+  phase_amb_log = [];
+
+  % Main loop ----------------------------------------------------
+
+  for f=1:frames
+    
+    % obtain nin samples of the test input signal
+    
+    for i=1:nin
+      rx_fdm(i) = fread(fin, 1, "short")/gain;
+    end
+    
+    rx_fdm_log = [rx_fdm_log rx_fdm(1:nin)];
+
+    % frequency offset estimation and correction
+
+    [pilot prev_pilot pilot_lut_index prev_pilot_lut_index] = get_pilot(pilot_lut_index, prev_pilot_lut_index, nin);
+    [foff_coarse S1 S2] = rx_est_freq_offset(rx_fdm, pilot, prev_pilot, nin);
+    
+    if track == 0
+      foff  = foff_coarse;
+    end
+    foff_log = [ foff_log foff ];
+    foff_rect = exp(j*2*pi*foff/Fs);
+
+    for i=1:nin
+      foff_phase *= foff_rect';
+      rx_fdm(i) = rx_fdm(i)*foff_phase;
+    end
+
+    % baseband processing
+
+    rx_baseband = fdm_downconvert(rx_fdm, nin);
+    rx_filt = rx_filter(rx_baseband, nin);
+
+    [rx_symbols rx_timing] = rx_est_timing(rx_filt, rx_baseband, nin);    
+    rx_timing_log = [rx_timing_log rx_timing];
+
+    nin = M;
+    if rx_timing > 2*M/P
+       nin += M/P;
+    end
+    if rx_timing < 0;
+       nin -= M/P;
+    end
+
+    rx_symbols_log = [rx_symbols_log rx_symbols.*(conj(prev_rx_symbols)./abs(prev_rx_symbols))*exp(j*pi/4)];
+
+    % coherent phase offset estimation ------------------------------------
+
+    [rx_phase_offsets ferr] = rx_est_phase(rx_symbols);
+    rx_phase_offsets_log = [rx_phase_offsets_log rx_phase_offsets];
+    phase_amb_log = [phase_amb_log phase_amb];
+    rx_symbols_ph = rx_symbols_mem(:,floor(Nph/2)+1) .* exp(-j*(rx_phase_offsets + phase_amb));
+    rx_symbols_ph_log = [rx_symbols_ph_log rx_symbols_ph .* exp(j*pi/4)];
+    rx_symbols_ph = -1 + 2*(real(rx_symbols_ph .* exp(j*pi/4)) > 0) + j*(-1 + 2*(imag(rx_symbols_ph .* exp(j*pi/4)) > 0));
+
+    % Std differential (used for freq offset est and BPSK sync) and psuedo coherent detection -----------------------
+
+    [rx_bits_unused sync        f_err       pd       ] = qpsk_to_bits(prev_rx_symbols, rx_symbols, modulation);
+    [rx_bits        sync_unused ferr_unused pd_unused] = qpsk_to_bits(prev_rx_symbols_ph, rx_symbols_ph, 'dqpsk');
+    foff -= 0.5*f_err;
+    prev_rx_symbols = rx_symbols;
+    prev_rx_symbols_ph = rx_symbols_ph;
+    sync_log = [sync_log sync];
+
+    [sig_est noise_est] = snr_update(sig_est, noise_est, pd);
+    snr_est = calc_snr(sig_est, noise_est);
+    snr_est_log = [snr_est_log snr_est];
+
+    % freq est state machine
+
+    [track fest_state] = freq_state(sync, fest_state);
+    track_log = [track_log track];
+
+    % count bit errors if we find a test frame
+
+    [test_frame_sync bit_errors] = put_test_bits(test_bits, rx_bits);
+    if (test_frame_sync == 1)
+      total_bit_errors = total_bit_errors + bit_errors;
+      total_bits = total_bits + Ntest_bits;
+      bit_errors_log = [bit_errors_log bit_errors/Ntest_bits];
+    else
+      bit_errors_log = [bit_errors_log 0];
+    end
+
+    % test frame sync state machine, just for more informative plots
+    
+    next_test_frame_sync_state = test_frame_sync_state;
+    if (test_frame_sync_state == 0)
+      if (test_frame_sync == 1)      
+        next_test_frame_sync_state = 1;
+       test_frame_count = 0;
+      end
+    end
+
+    if (test_frame_sync_state == 1)
+      % we only expect another test_frame_sync pulse every 4 symbols
+      test_frame_count++;
+      if (test_frame_count == 4)
+        test_frame_count = 0;
+        if ((test_frame_sync == 0))      
+          next_test_frame_sync_state = 0;
+        end
+      end
+    end
+    test_frame_sync_state = next_test_frame_sync_state;
+    test_frame_sync_log = [test_frame_sync_log test_frame_sync_state];
+
+  end
+  
+  % ---------------------------------------------------------------------
+  % Print Stats
+  % ---------------------------------------------------------------------
+
+  ber = total_bit_errors / total_bits;
+
+  printf("%d bits  %d errors  BER: %1.4f\n",total_bits, total_bit_errors, ber);
+
+  % ---------------------------------------------------------------------
+  % Plots
+  % ---------------------------------------------------------------------
+
+  xt = (1:frames)/Rs;
+  secs = frames/Rs;
+
+  figure(1)
+  clf;
+  [n m] = size(rx_symbols_log);
+  plot(real(rx_symbols_log(1:Nc+1,15:m)),imag(rx_symbols_log(1:Nc+1,15:m)),'+')
+  axis([-2 2 -2 2]);
+  title('Scatter Diagram');
+
+  figure(2)
+  clf;
+  subplot(211)
+  plot(xt, rx_timing_log)
+  title('timing offset (samples)');
+  subplot(212)
+  plot(xt, foff_log, '-;freq offset;')
+  hold on;
+  plot(xt, track_log*75, 'r;course-fine;');
+  hold off;
+  title('Freq offset (Hz)');
+  grid
+
+  figure(3)
+  clf;
+  subplot(211)
+  [a b] = size(rx_fdm_log);
+  xt1 = (1:b)/Fs;
+  plot(xt1, rx_fdm_log);
+  title('Rx FDM Signal');
+  subplot(212)
+  spec(rx_fdm_log,8000);
+  title('FDM Rx Spectrogram');
+
+  figure(4)
+  clf;
+  subplot(311)
+  stem(xt, sync_log)
+  axis([0 secs 0 1.5]);
+  title('BPSK Sync')
+  subplot(312)
+  stem(xt, bit_errors_log);
+  title('Bit Errors for test frames')
+  subplot(313)
+  plot(xt, test_frame_sync_log);
+  axis([0 secs 0 1.5]);
+  title('Test Frame Sync')
+
+  figure(5)
+  clf;
+  plot(xt, snr_est_log);
+  title('SNR Estimates')
+  figure(6)
+  clf;
+  [n m] = size(rx_symbols_ph_log);
+  plot(real(rx_symbols_ph_log(1:Nc+1,15:m)),imag(rx_symbols_ph_log(1:Nc+1,15:m)),'+')
+  %plot(real(rx_symbols_ph_log(2,15:m)),imag(rx_symbols_ph_log(2,15:m)),'+')
+  axis([-2 2 -2 2]);
+  title('Scatter Diagram - after phase correction');
+
+  figure(7)
+  clf;
+  subplot(211)
+  plot(rx_phase_offsets_log(1,:))
+  subplot(212)
+  plot(phase_amb_log(1,:))
+  title('Rx Phase Offset Est')
+
+endfunction
index a78eedfebdbe85832366ca5221fde211a6e635db..147322df422bf473835bdb3145f027e153837540 100644 (file)
@@ -12,7 +12,7 @@ fdmdv;               % load modem code
  
 % Simulation Parameters --------------------------------------
 
-frames = 25;
+frames = 100;
 EbNo_dB = 7.3;
 Foff_hz = 0;
 modulation = 'dqpsk';
@@ -96,6 +96,7 @@ fest_state = 0;
 track = 0;
 track_log = [];
 
+snr_log = [];
 
 % ---------------------------------------------------------------------
 % Main loop 
@@ -206,6 +207,7 @@ for f=1:frames
   % Update SNR est
 
   [sig_est noise_est] = snr_update(sig_est, noise_est, pd);
+  snr_log = [snr_log calc_snr(sig_est, noise_est)];
 
   % count bit errors if we find a test frame
   % Allow 15 frames for filter memories to fill and time est to settle
@@ -316,3 +318,6 @@ plot(test_frame_sync_log);
 axis([0 frames 0 1.5]);
 title('Test Frame Sync')
 
+figure(5)
+clf
+plot(snr_log)
index 7450b2fd85b2172c9c956619b6d6617c28c6f3c6..a1598878852851528f00eb3d9b4860d0b72a66c2 100644 (file)
@@ -19,9 +19,9 @@ fdmdv;               % load modem code
  
 % Simulation Parameters --------------------------------------
 
-frames = 100;
-EbNo_dB = 73;
-Foff_hz = 0;
+frames = 200;
+EbNo_dB = 7;
+Foff_hz = -100;
 hpa_clip = 150;
 
 % ------------------------------------------------------------
@@ -104,37 +104,10 @@ track_log = [];
 
 snr_log = [];
 
-% PSK demod ----
-
-% Set up matrix of tx symbols, one row for each carrier.  
-
-% The differential PSK encoder is driven by a sequence of test bits.
-% This test sequence is 4 frames (122 bits long), which means it
-% repeats every 4 frames.  However the DPSK encoder also has 4 states,
-% so it turns out that the transmitted sequence of PSK symbols repeats
-% itself every 16 frames.  Depending on the test data some carriers
-% repeat more often than that, but the sequence as a whole repeats
-% every 16 frames.
-
-% Each row in the matrix is the sequence of symbols for one carrier.
-% This repeats itself every 16 symbols.  We would like to demodulate
-% and measure the BER of this block of 16 symbols.  To do this we need
-% to correct any phase offset.
-
-prev_psk_test_symbols = ones(Nc+1,1);
-tx_symbols_mem = [];
-for i=1:6
-  psk_test_symbols = generate_psk_test_symbols(prev_psk_test_symbols);
-  prev_psk_test_symbols = psk_test_symbols(:,4);
-  tx_symbols_mem = [tx_symbols_mem psk_test_symbols .* exp(j*pi/4)];
-end
-
-% PSK BER counters
-
-psk_total_bits = 0;
-psk_total_bit_errors = 0;
-
 rx_symbols_ph_log = [];
+prev_rx_symbols_ph = ones(Nc+1,1);
+rx_phase_offsets_log = [];
+phase_amb_log = [];
 
 % ---------------------------------------------------------------------
 % Main loop 
@@ -206,7 +179,7 @@ for f=1:frames
     foff = foff_course;
   end
 
-  foff = 0; % disable for now
+  %foff = 0; % disable for now
 
   foff_log = [ foff_log foff ];
   foff_rect = exp(j*2*pi*foff/Fs);
@@ -223,13 +196,28 @@ for f=1:frames
   rx_filt = rx_filter(rx_baseband, M);
 
   [rx_symbols rx_timing] = rx_est_timing(rx_filt, rx_baseband, M);
+  rx_symbols_log = [rx_symbols_log rx_symbols.*(conj(prev_rx_symbols)./abs(prev_rx_symbols))*exp(j*pi/4)];
   rx_timing_log = [rx_timing_log rx_timing];
 
-  [rx_bits sync foff_fine pd] = qpsk_to_bits(prev_rx_symbols, rx_symbols, 'dqpsk');
-  rx_symbols_log = [rx_symbols_log rx_symbols .* exp(j*pi/4)];
+  % coherent phase offset estimation ------------------------------------
+
+  [rx_phase_offsets ferr] = rx_est_phase(rx_symbols);
+  rx_phase_offsets_log = [rx_phase_offsets_log rx_phase_offsets];
+  phase_amb_log = [phase_amb_log phase_amb];
+  rx_symbols_ph = rx_symbols_mem(:,floor(Nph/2)+1) .* exp(-j*(rx_phase_offsets + phase_amb));
+  rx_symbols_ph_log = [rx_symbols_ph_log rx_symbols_ph .* exp(j*pi/4)];
+  rx_symbols_ph = -1 + 2*(real(rx_symbols_ph .* exp(j*pi/4)) > 0) + j*(-1 + 2*(imag(rx_symbols_ph .* exp(j*pi/4)) > 0));
+
+  % Std differential (used for freq offset est and BPSK sync) and psuedo coherent detection -----------------------
+
+  [rx_bits_unused sync        ferr        pd] = qpsk_to_bits(prev_rx_symbols, rx_symbols, 'dqpsk');
+  [rx_bits        sync_unused ferr_unused pd] = qpsk_to_bits(prev_rx_symbols_ph, rx_symbols_ph, 'dqpsk');
+
+  %----------------------------------------------------------------------
 
   foff -= 0.5*ferr;
   prev_rx_symbols = rx_symbols;
+  prev_rx_symbols_ph = rx_symbols_ph;
   sync_log = [sync_log sync];
   
   % freq est state machine
@@ -242,48 +230,11 @@ for f=1:frames
   [sig_est noise_est] = snr_update(sig_est, noise_est, pd);
   snr_log = [snr_log calc_snr(sig_est, noise_est)];
 
-  % coherent PSK demod --------------------------------------
-
-  % update memory of the last Nph rx symbols
-
-  rx_symbols_mem(:,1:Npom-1) = rx_symbols_mem(:,2:Npom);
-  rx_symbols_mem(:,Npom) = rx_symbols .* exp(j*pi/4);
-
-  % estimate and correct phase of each received symbol in 16 symbol frame
-
-  for c=1:Nc                  
-    for s=Nph2+1:Nph2+Nstates  % symbols in middle of matrix that we correct 
-      st = s - Nph2; en = s + Nph2;
-      corr = rx_symbols_mem(c,st:en) * tx_symbols_mem(c,st:en)';
-      rx_symbols_mem_ph(c,s) = rx_symbols_mem(c,s) .* exp(-j*angle(corr));
-    end
-  end
-  
-  % count bit errors in centre of window
-
-  psk_bit_errors = 0;
-  psk_bits = Nc*Nstates;
-  st = Nph2+1; en = Nph2+Nstates;
-  for c=1:Nc
-    psk_bit_errors += sum(real(rx_symbols_mem_ph(c,st:en)) .* real(tx_symbols_mem(c,st:en)) < 0);
-    psk_bit_errors += sum(imag(rx_symbols_mem_ph(c,st:en)) .* imag(tx_symbols_mem(c,st:en)) < 0);
-  end
-  printf("psk_bit_errors: %d corr: %f\n", psk_bit_errors, angle(corr));
-  ber = psk_bit_errors/psk_bits;
-  if ber < 0.1
-    psk_total_bit_errors += psk_bit_errors;
-    psk_total_bits += psk_bits;
-    % phase correction only valid when we are in sync
-    rx_symbols_ph_log = [rx_symbols_ph_log rx_symbols_mem_ph(:,st:en)];
-  end
-
-  % ---------------------------------------------------------
-
   % count bit errors if we find a test frame
 
   [test_frame_sync bit_errors] = put_test_bits(test_bits, rx_bits);
 
-  if test_frame_sync == 1
+  if (test_frame_sync == 1) && (f > 15)
     total_bit_errors = total_bit_errors + bit_errors;
     total_bits = total_bits + Ntest_bits;
     bit_errors_log = [bit_errors_log bit_errors];
@@ -334,10 +285,6 @@ printf("\nDPSK\n");
 printf("  bits......: %d\n", total_bits);
 printf("  errors....: %d\n", total_bit_errors);
 printf("  BER.......: %1.4f\n",  ber);
-printf("PSK\n");
-printf("  bits......: %d\n", psk_total_bits);
-printf("  errors....: %d\n", psk_total_bit_errors);
-printf("  BER.......: %1.4f\n",  psk_total_bit_errors/psk_total_bits);
 
 % ---------------------------------------------------------------------
 % Plots
@@ -365,18 +312,6 @@ title('Freq offset (Hz)');
 
 figure(3)
 clf;
-subplot(211)
-plot(real(tx_fdm_log));
-title('FDM Tx Signal');
-subplot(212)
-Nfft=Fs;
-S=fft(rx_fdm_log,Nfft);
-SdB=20*log10(abs(S));
-plot(SdB(1:Fs/4))
-title('FDM Rx Spectrum');
-
-figure(4)
-clf;
 subplot(311)
 stem(sync_log)
 axis([0 frames 0 1.5]);
@@ -389,24 +324,18 @@ plot(test_frame_sync_log);
 axis([0 frames 0 1.5]);
 title('Test Frame Sync')
 
-figure(5)
-clf;
-subplot(211)
-stem(real(rx_symbols_mem(2,:)))
-subplot(212)
-stem(imag(rx_symbols_mem(2,:)))
-
-figure(6)
-clf;
-subplot(211)
-stem(real(tx_symbols_mem(2,:)))
-subplot(212)
-stem(imag(tx_symbols_mem(2,:)))
-
-figure(7)
+figure(4)
 clf;
 [n m] = size(rx_symbols_ph_log);
 plot(real(rx_symbols_ph_log(1:Nc+1,15:m)),imag(rx_symbols_ph_log(1:Nc+1,15:m)),'+')
 %plot(real(rx_symbols_ph_log(2,15:m)),imag(rx_symbols_ph_log(2,15:m)),'+')
 axis([-3 3 -3 3]);
 title('Scatter Diagram - after phase correction');
+
+figure(5)
+clf;
+subplot(211)
+plot(rx_phase_offsets_log(1,:))
+subplot(212)
+plot(phase_amb_log(1,:))
+title('Rx Phase Offset Est')