From e8518efcc42ce92244a55e67bc4146e927036351 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Wed, 25 Jun 2014 05:56:56 +0000 Subject: [PATCH] octave and C versions of modem in sync git-svn-id: https://svn.code.sf.net/p/freetel/code@1708 01035d8c-6547-0410-b346-abe4f91aad63 --- codec2-dev/octave/fdmdv.m | 174 ++++++++++++++++++----------------- codec2-dev/octave/tfdmdv.m | 41 ++++----- codec2-dev/src/fdmdv.c | 4 +- codec2-dev/unittest/tfdmdv.c | 5 +- 4 files changed, 110 insertions(+), 114 deletions(-) diff --git a/codec2-dev/octave/fdmdv.m b/codec2-dev/octave/fdmdv.m index a092a54e..15fa128a 100644 --- a/codec2-dev/octave/fdmdv.m +++ b/codec2-dev/octave/fdmdv.m @@ -44,6 +44,8 @@ global snr_coeff; 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 @@ -312,7 +314,7 @@ function [foff imax pilot_lpf_out S] = lpf_peak_pick(pilot_baseband, pilot_lpf, % 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++; @@ -524,38 +526,60 @@ function [rx_bits sync_bit f_err phase_difference] = psk_to_bits(prev_rx_symbols 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); @@ -574,7 +598,7 @@ function [rx_bits sync_bit f_err phase_difference] = psk_to_bits(prev_rx_symbols % 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 @@ -836,89 +860,69 @@ 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 @@ -1077,10 +1081,10 @@ global Mpilotfft = 256; 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 @@ -1093,8 +1097,10 @@ global prev_pilot_lut_index; % 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 diff --git a/codec2-dev/octave/tfdmdv.m b/codec2-dev/octave/tfdmdv.m index 86907f28..26380214 100644 --- a/codec2-dev/octave/tfdmdv.m +++ b/codec2-dev/octave/tfdmdv.m @@ -9,6 +9,7 @@ % Version 2 % +more off NumCarriers = 14; fdmdv; % load modem code @@ -21,14 +22,17 @@ frames = 25; 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 = []; @@ -52,7 +56,7 @@ phase_difference_log = []; rx_symbols_log = []; rx_bits_log = []; sync_bit_log = []; -coarse_fine_log = []; +sync_log = []; nin_log = []; sig_est_log = []; noise_est_log = []; @@ -60,7 +64,7 @@ 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 @@ -78,16 +82,7 @@ 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; @@ -100,8 +95,6 @@ for f=1:frames [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 @@ -158,8 +151,8 @@ for f=1:frames % 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 @@ -176,9 +169,9 @@ function stem_sig_and_error(plotnum, subplotnum, sig, error, titlestr, axisvec) 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); @@ -195,9 +188,9 @@ function plot_sig_and_error(plotnum, subplotnum, sig, error, titlestr, 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); @@ -252,7 +245,7 @@ plot_sig_and_error(9, 211, foff_coarse_log, foff_coarse_log - foff_coarse_log_c, 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' ) @@ -273,7 +266,7 @@ c = 12; 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' ) diff --git a/codec2-dev/src/fdmdv.c b/codec2-dev/src/fdmdv.c index e58924da..255f209e 100644 --- a/codec2-dev/src/fdmdv.c +++ b/codec2-dev/src/fdmdv.c @@ -1215,7 +1215,7 @@ int freq_state(int *reliable_sync_bit, int sync_bit, int *state, int *timer, int corr += sync_mem[i]*sync_uw[i]; if (abs(corr) == NSYNC_MEM) unique_word = 1; - *reliable_sync_bit = (corr == NSYNC_MEM); + *reliable_sync_bit = (abs(corr) == NSYNC_MEM); /* iterate state machine */ @@ -1227,7 +1227,7 @@ int freq_state(int *reliable_sync_bit, int sync_bit, int *state, int *timer, int *timer = 0; } break; - case 1: /* tentative sync state */ + case 1: /* tentative sync state */ if (unique_word) { (*timer)++; if (*timer == 25) /* sync has been good for 500ms */ diff --git a/codec2-dev/unittest/tfdmdv.c b/codec2-dev/unittest/tfdmdv.c index 256ae556..cb6bf148 100644 --- a/codec2-dev/unittest/tfdmdv.c +++ b/codec2-dev/unittest/tfdmdv.c @@ -11,7 +11,6 @@ \*---------------------------------------------------------------------------*/ - /* Copyright (C) 2012 David Rowe @@ -159,11 +158,9 @@ int main(int argc, char *argv[]) /* freq offset estimation and correction */ foff_coarse = rx_est_freq_offset(fdmdv, rx_fdm, nin); - foff_coarse = 0; - fdmdv->sync = 0; if (fdmdv->sync == 0) fdmdv->foff = foff_coarse; - fdmdv_freq_shift(rx_fdm_fcorr, rx_fdm, foff_coarse, &fdmdv->foff_phase_rect, nin); + fdmdv_freq_shift(rx_fdm_fcorr, rx_fdm, -fdmdv->foff, &fdmdv->foff_phase_rect, nin); /* baseband processing */ -- 2.25.1