global Nph;
Nph = 9; % number of symbols to estimate phase over
% must be odd number as we take centre symbol
+global Nsync_mem = 6
+global sync_uw = [1 -1 1 -1 1 -1];
% root raised cosine (Root Nyquist) filter
% LPF cutoff 200Hz, so we can handle max +/- 200 Hz freq offset
pilot_lpf(1:Npilotlpf-nin) = pilot_lpf(nin+1:Npilotlpf);
- k = Npilotcoeff+1;
+ k = Npilotbaseband-nin+1;;
for i = Npilotlpf-nin+1:Npilotlpf
pilot_lpf(i) = pilot_baseband(k-Npilotcoeff+1:k) * pilot_coeff';
k++;
phase_difference = zeros(Nc+1,1);
for c=1:Nc
- norm = 1/(1E-6+abs(prev_rx_symbols(c)));
- phase_difference(c) = prev_rx_symbols(c) .* conj(prev_rx_symbols(c)) * norm;
+ norm = 1/(1E-6+abs(prev_rx_symbols(c)));
+ phase_difference(c) = rx_symbols(c) .* conj(prev_rx_symbols(c)) * norm;
end
for c=1:Nc
+ phase_difference(c) *= exp(j*pi/4);
- % determine index of constellation point received 0,1,...,m-1
+ if m == 4
- index = floor(angle(phase_difference(c))*m/(2*pi) + 0.5);
+ % to get a good match between C and Octave during start up use same as C code
+
+ d = phase_difference(c);
+ if (real(d) >= 0) && (imag(d) >= 0)
+ msb = 0; lsb = 0;
+ end
+ if (real(d) < 0) && (imag(d) >= 0)
+ msb = 0; lsb = 1;
+ end
+ if (real(d) < 0) && (imag(d) < 0)
+ msb = 1; lsb = 1;
+ end
+ if (real(d) >= 0) && (imag(d) < 0)
+ msb = 1; lsb = 0;
+ end
+
+ rx_bits(2*(c-1)+1) = msb;
+ rx_bits(2*c) = lsb;
+ else
+ % determine index of constellation point received 0,1,...,m-1
- if index < 0
- index += m;
- end
+ index = floor(angle(phase_difference(c))*m/(2*pi) + 0.5);
- % map to decimal version of bits encoded in symbol
+ if index < 0
+ index += m;
+ end
- if m == 4
- bits_decimal = m4_binary_to_gray(index+1);
- else
- bits_decimal = m8_binary_to_gray(index+1);
- end
-
- % convert back to an array of received bits
+ % map to decimal version of bits encoded in symbol
- for i=1:Nb
- if bitand(bits_decimal, 2.^(Nb-i))
- rx_bits((c-1)*Nb+i) = 1;
+ if m == 4
+ bits_decimal = m4_binary_to_gray(index+1);
else
- rx_bits((c-1)*Nb+i) = 0;
+ bits_decimal = m8_binary_to_gray(index+1);
+ end
+
+ % convert back to an array of received bits
+
+ for i=1:Nb
+ if bitand(bits_decimal, 2.^(Nb-i))
+ rx_bits((c-1)*Nb+i) = 1;
+ else
+ rx_bits((c-1)*Nb+i) = 0;
+ end
end
end
-
end
assert(length(rx_bits) == Nc*Nb);
% extra pi/4 rotation as we need for snr_update and scatter diagram
- phase_difference *= exp(j*pi/4);
+ phase_difference(Nc+1) *= exp(j*pi/4);
endfunction
% then switch to a more robust tracking algorithm. If we lose sync we switch
% back to acquire mode for fast-requisition.
-function [entered_track track state bad_sync] = freq_state(sync_bit, state, bad_sync)
+function [sync reliable_sync_bit state timer sync_mem] = freq_state(sync_bit, state, timer, sync_mem)
+ global Nsync_mem;
+ global sync_uw;
- entered_track = 0;
+ % look for 6 symbol (120ms) 010101 of sync sequence
- % acquire state, look for 6 symbol 010101 sequence from sync bit
+ unique_word = 0;
+ for i=1:Nsync_mem-1
+ sync_mem(i) = sync_mem(i+1);
+ end
+ sync_mem(Nsync_mem) = 1 - 2*sync_bit;
+ corr = 0;
+ for i=1:Nsync_mem
+ corr += sync_mem(i)*sync_uw(i);
+ end
+ if abs(corr) == Nsync_mem
+ unique_word = 1;
+ end
+ reliable_sync_bit = (abs(corr) == Nsync_mem);
+
+ % iterate state machine
next_state = state;
if state == 0
- if sync_bit == 0
+ if unique_word
next_state = 1;
+ timer = 0;
end
end
if state == 1
- if sync_bit == 1
- next_state = 2;
+ if unique_word
+ timer++;
+ if timer == 25 % sync has been good for 500ms
+ next_state = 2;
+ end
else
next_state = 0;
end
end
- if state == 2
- if sync_bit == 0
+ if state == 2 % good sync state
+ if unique_word == 0
+ timer = 0;
next_state = 3;
- else
- next_state = 0;
- end
- end
- if state == 3
- if sync_bit == 1
- next_state = 4;
- else
- next_state = 0;
- end
- end
- if state == 4
- if sync_bit == 0
- next_state = 5;
- else
- next_state = 0;
- end
+ end
end
- if state == 5
- if sync_bit == 1
- entered_track = 1;
- next_state = 6;
- bad_sync = 0;
+ if state == 3 % tenative bad state, but could be a fade
+ if unique_word
+ next_state = 2;
else
- next_state = 0;
- end
- end
-
- % states 6 and above are track mode, make sure we keep getting 0101 sync bit sequence
-
- if state == 6
- next_state = 7;
- if sync_bit == 0
- bad_sync = 0;
- else
- bad_sync++;
- if bad_sync > 2
+ timer++;
+ if timer == 50 % wait for 1000ms in case sync comes back
next_state = 0;
end
end
end
- if state == 7
- next_state = 6;
- if sync_bit == 1
- bad_sync = 0;
- else
- bad_sync++;
- if bad_sync > 2
- next_state = 0;
- end
- end
- end
-
- %printf("state: %d next_state: %d sync_bit: %d bad_sync: %d\n", state, next_state, sync_bit, bad_sync);
-
+ %printf("corr: % -d state: %d next_state: %d uw: %d timer: %d\n", corr, state, next_state, unique_word, timer);
state = next_state;
- if state >= 6
- track = 1;
+
+ if state
+ sync = 1;
else
- track = 0;
+ sync = 0;
end
endfunction
global Npilotcoeff; % number of pilot LPF coeffs
Npilotcoeff = 30;
global pilot_coeff;
- pilot_coeff = fir1(Npilotcoeff-1, 100/(Fs/2))';% 200Hz LPF
+ 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; % number of symbols we DFT pilot over, pilot est window
- Npilotlpf = 8*M;
+ Npilotlpf = 4*M;
% pilot LUT, used for copy of pilot at rx
% Freq offset estimator states
+if 0
global bpf;
bpf = zeros(1, Nbpf); % BPF pilot input samples
+end
global pilot_baseband1;
global pilot_baseband2;
pilot_baseband1 = zeros(1, Npilotbaseband); % pilot baseband samples
% Version 2
%
+more off
NumCarriers = 14;
fdmdv; % load modem code
prev_tx_symbols = ones(Nc+1,1);
prev_rx_symbols = ones(Nc+1,1);
foff_phase_rect = 1;
-coarse_fine = 0;
-fest_state = 0;
channel = [];
channel_count = 0;
next_nin = M;
sig_est = zeros(Nc+1,1);
noise_est = zeros(Nc+1,1);
+sync = 0;
+fest_state = 0;
+fest_timer = 0;
+sync_mem = zeros(1,Nsync_mem);
+
% Octave outputs we want to collect for comparison to C version
tx_bits_log = [];
rx_symbols_log = [];
rx_bits_log = [];
sync_bit_log = [];
-coarse_fine_log = [];
+sync_log = [];
nin_log = [];
sig_est_log = [];
noise_est_log = [];
% adjust this if the screen is getting a bit cluttered
global no_plot_list;
-no_plot_list = [1 2 3 4 5 6 7 8 12];
+no_plot_list = [1 2 3 4 5 6 7 8 11 12 16];
for f=1:frames
% channel
- nin = next_nin;
- %nin = 120;
- %nin = M;
- %if (f == 3)
- % nin = 120;
- %elseif (f == 4)
- % nin = 200;
- %else
- % nin = M;
- %end
+ %nin = next_nin;
nin = M;
channel = [channel real(tx_fdm)];
channel_count += M;
[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);
- foff_coarse = 0;
- sync = 0;
if sync == 0
foff = foff_coarse;
end
% freq est state machine
- [sync fest_state] = freq_state(sync_bit, fest_state);
- sync_log = [coarse_fine_log sync];
+ [sync reliable_sync_bit fest_state fest_timer sync_mem] = freq_state(sync_bit, fest_state, fest_timer, sync_mem);
+ sync_log = [sync_log sync];
end
% Compare to the output from the C version
end
figure(plotnum)
subplot(subplotnum)
- stem(sig,'g;C version;');
+ stem(sig,'g;Octave version;');
hold on;
- stem(error,'r;Error between C and Octave;');
+ stem(error,'r;Octave - C version (hopefully 0);');
hold off;
if nargin == 6
axis(axisvec);
figure(plotnum)
subplot(subplotnum)
- plot(sig,'g;C version;');
+ plot(sig,'g;Octave version;');
hold on;
- plot(error,'r;Error between C and Octave;');
+ plot(error,'r;Octave - C version (hopefully 0);');
hold off;
if nargin == 6
axis(axisvec);
plot_sig_and_error(9, 212, foff_fine_log, foff_fine_log - foff_fine_log_c, 'Fine Freq Offset' )
plot_sig_and_error(10, 211, foff_log, foff_log - foff_log_c, 'Freq Offset' )
-plot_sig_and_error(10, 212, sync_log, sync_log - sync_log_c, 'Freq Est Coarse(0) Fine(1)', [1 frames -0.5 1.5] )
+plot_sig_and_error(10, 212, sync_log, sync_log - sync_log_c, 'Sync & Freq Est Coarse(0) Fine(1)', [1 frames -1.5 1.5] )
c=15;
plot_sig_and_error(11, 211, real(rx_baseband_log(c,:)), real(rx_baseband_log(c,:) - rx_baseband_log_c(c,:)), 'Rx baseband real' )
plot_sig_and_error(16, 211, sig_est_log(c,:), sig_est_log(c,:) - sig_est_log_c(c,:), 'sig est for SNR' )
plot_sig_and_error(16, 212, noise_est_log(c,:), noise_est_log(c,:) - noise_est_log_c(c,:), 'noise est for SNR' )
-f=2;
+f=12;
stem_sig_and_error(13, 211, real(rx_symbols_log(:,f)), real(rx_symbols_log(:,f) - rx_symbols_log_c(:,f)), 'rx symbols real' )
stem_sig_and_error(13, 212, imag(rx_symbols_log(:,f)), imag(rx_symbols_log(:,f) - rx_symbols_log_c(:,f)), 'rx symbols imag' )