From: drowe67 Date: Sat, 7 Apr 2018 22:10:04 +0000 (+0000) Subject: first pass at UW based sync - works really well, gives positive lock/false lock indic... X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=73869f7cf4f7da61586101827ef3d63077687ae9;p=freetel-svn-tracking.git first pass at UW based sync - works really well, gives positive lock/false lock indication, hangs on at rated 9% BER at 0dB AWGN and 4dB HF git-svn-id: https://svn.code.sf.net/p/freetel/code@3449 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/codec2-dev/octave/ofdm_lib.m b/codec2-dev/octave/ofdm_lib.m index b41b93c3..a424c42c 100644 --- a/codec2-dev/octave/ofdm_lib.m +++ b/codec2-dev/octave/ofdm_lib.m @@ -48,7 +48,7 @@ endfunction % used for acquisition (coarse timing and freq offset), and fine % timing -function [t_est foff_est timing_valid timing_mx1 timing_mx2] = coarse_sync(states, rx, rate_fs_pilot_samples) +function [t_est foff_est timing_valid timing_mx] = coarse_sync(states, rx, rate_fs_pilot_samples) ofdm_load_const; Npsam = length(rate_fs_pilot_samples); @@ -63,47 +63,25 @@ function [t_est foff_est timing_valid timing_mx1 timing_mx2] = coarse_sync(state % correlate with pilots at start and end of frame to determine timing offset for i=1:Ncorr - rx1 = rx(i:i+Npsam-1); rx2 = rx(i+Nsamperframe:i+Nsamperframe+Npsam-1); - corr_st = rx1 * rate_fs_pilot_samples'; corr_en = rx2 * rate_fs_pilot_samples'; - corr1(i) = abs(corr_st + corr_en)/av_level; - corr2(i) = (abs(corr_st) + abs(corr_en))/av_level; + rx1 = rx(i:i+Npsam-1); rx2 = rx(i+Nsamperframe:i+Nsamperframe+Npsam-1); + corr_st = rx1 * rate_fs_pilot_samples'; corr_en = rx2 * rate_fs_pilot_samples'; + corr(i) = (abs(corr_st) + abs(corr_en))/av_level; end - [timing_mx1 t_est] = max(corr1); - [timing_mx2 t_est] = max(corr2); - timing_valid = timing_mx2 > timing_mx_thresh; + [timing_mx t_est] = max(corr); + timing_valid = timing_mx > timing_mx_thresh; if verbose > 2 - printf(" mx1: %f mx2: %f timing_est: %d timing_valid: %d\n", timing_mx1, timing_mx2, timing_est, timing_valid); + printf(" mx: %f timing_est: %d timing_valid: %d\n", timing_mx, t_est, timing_valid); end - - #{ - % original freq offset est code that never made it into C. Have some concerns about CPU - % load of performing FFT, althout a smaller one could have been used with interpolation - % to get the peak - - C = abs(fft(rx(t_est:t_est+Npsam-1) .* conj(rate_fs_pilot_samples), Fs)); - C += abs(fft(rx(t_est+Nsamperframe:t_est+Nsamperframe+Npsam-1) .* conj(rate_fs_pilot_samples), Fs)); - - fmax = 30; - [mx_pos foff_est_pos] = max(C(1:fmax)); - [mx_neg foff_est_neg] = max(C(Fs-fmax+1:Fs)); - - if mx_pos > mx_neg - foff_est = foff_est_pos - 1; - else - foff_est = foff_est_neg - fmax - 1; - end - #} - + 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(corr2)) @@ -127,20 +105,6 @@ function [t_est foff_est timing_valid timing_mx1 timing_mx2] = coarse_sync(state figure(11) plot([p1 p2; p3 p4], '+') - %axis([1 Ncorr 0 2]) - #{ - figure(8) - plot(C) - axis([0 200 0 0.4]) - #} - #{ - figure(9) - %rate_fs_pilot_samples - plot([p1 p2 p3 p4] ,'b+') - %plot(rate_fs_pilot_samples * rate_fs_pilot_samples' ,'b+') - axis([-0.2 0.2 -0.2 0.2]) - %hold on; plot(rx(t_est+Nsamperframe:t_est+Npsam+Nsamperframe-1) .* rate_fs_pilot_samples','g+'); hold off; - #} end endfunction @@ -320,9 +284,9 @@ 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_mx1 timing_mx2] = coarse_sync(states, states.rxbuf(st:en), states.rate_fs_pilot_samples); + [ct_est foff_est timing_valid timing_mx] = coarse_sync(states, states.rxbuf(st:en), states.rate_fs_pilot_samples); if verbose - printf(" mx1: %3.2f mx2: %3.2f coarse_foff: %4.1f\n", timing_mx1, timing_mx2, foff_est); + printf(" ct_est: %d mx: %3.2f coarse_foff: %4.1f\n", ct_est, timing_mx, foff_est); end if timing_valid @@ -341,8 +305,7 @@ function [timing_valid states] = ofdm_sync_search(states, rxbuf_in) end states.timing_valid = timing_valid; - states.timing_mx1 = timing_mx1; - states.timing_mx2 = timing_mx2; + states.timing_mx = timing_mx; states.coarse_foff_est_hz = foff_est; endfunction @@ -388,7 +351,7 @@ 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_mx1 timing_mx2] = coarse_sync(states, rxbuf(st:en) .* exp(-j*woff_est*(st:en)), rate_fs_pilot_samples); + [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); if timing_valid timing_est = timing_est + ft_est - ceil(ftwindow_width/2); @@ -401,7 +364,7 @@ function [rx_bits states aphase_est_pilot_log rx_np rx_amp] = ofdm_demod(states, end if verbose > 1 - printf(" mx1: %3.2f mx2: %3.2f coarse_foff: %4.1f foff: %4.1f\n", timing_mx1, timing_mx2, coarse_foff_est_hz, foff_est_hz); + printf(" ft_est: %2d mx: %3.2f coarse_foff: %4.1f foff: %4.1f\n", ft_est, timing_mx, coarse_foff_est_hz, foff_est_hz); end end @@ -526,8 +489,7 @@ function [rx_bits states aphase_est_pilot_log rx_np rx_amp] = ofdm_demod(states, states.rxbuf = rxbuf; states.nin = nin; states.timing_valid = timing_valid; - states.timing_mx1 = timing_mx1; - states.timing_mx2 = timing_mx2; + states.timing_mx = timing_mx; states.timing_est = timing_est; states.sample_point = sample_point; states.delta_t = delta_t; diff --git a/codec2-dev/octave/ofdm_rx.m b/codec2-dev/octave/ofdm_rx.m index 3f28fdd8..6df10827 100644 --- a/codec2-dev/octave/ofdm_rx.m +++ b/codec2-dev/octave/ofdm_rx.m @@ -11,10 +11,10 @@ function ofdm_rx(filename, error_pattern_filename) % init modem - Ts = 0.018; Tcp = 0.002; Rs = 1/Ts; bps = 2; Nc = 16; Ns = 8; + Ts = 0.018; Tcp = 0.002; Rs = 1/Ts; bps = 2; Nc = 17; Ns = 8; states = ofdm_init(bps, Rs, Tcp, Ns, Nc); ofdm_load_const; - states.verbose = 2; + states.verbose = 0; % load real samples from file @@ -44,7 +44,7 @@ function ofdm_rx(filename, error_pattern_filename) %states.rxbuf(Nrxbuf-nin+1:Nrxbuf) = rx(prx:nin); %prx += nin; - state = 'searching'; frame_count = 0; Nerrs = 0; sync_counter = 0; + state = 'searching'; frame_count = 0; Nerrs = 0; sync_counter = 0; uw_errors = 0; states.timing_mx1 = states.timing_mx2 = 1; % main loop ---------------------------------------------------------------- @@ -62,13 +62,7 @@ function ofdm_rx(filename, error_pattern_filename) rxbuf_in(1:lnew) = rx(prx:prx+lnew-1); end prx += states.nin; - - ratio = states.timing_mx1/states.timing_mx2; - printf("f: %2d state: %-10s ratio: %3.2f %1d nin: %d Nerrs: %3d", f, state, ratio, sync_counter, nin, Nerrs); - % If looking for sync: check raw BER on frame just received - % against all possible positions in the interleaver frame. - % iterate state machine ------------------------------------ next_state = state; @@ -77,14 +71,8 @@ function ofdm_rx(filename, error_pattern_filename) [timing_valid states] = ofdm_sync_search(states, rxbuf_in); if states.timing_valid - woff_est = 2*pi*states.foff_est_hz/Fs; - st = M+Ncp + Nsamperframe + 1; en = st + 2*Nsamperframe; - [ct_est foff_est timing_valid timing_mx1 timing_mx2] = coarse_sync(states, states.rxbuf(st:en) .* exp(-j*woff_est*(st:en)), states.rate_fs_pilot_samples); - if states.verbose > 1 - printf(" mx1: %3.2f mx2: %3.2f coarse_foff: %4.1f\n", timing_mx1, timing_mx2, foff_est); - end - %states.foff_est_hz += foff_est; - states.foff_est_hz = 0; + Nerrs_log = []; + Terrs = Tbits = frame_count = 0; sync_counter = 0; next_state = 'trial_sync'; end @@ -126,28 +114,21 @@ function ofdm_rx(filename, error_pattern_filename) end % freq offset est may be too far out, and has aliases every 1/Ts - - if (states.timing_mx1/states.timing_mx2 < 0.8) || (abs(states.coarse_foff_est_hz) > 3) + + uw_len = (Ns-1)*bps; + uw_errors = sum(xor(tx_bits(1:uw_len), rx_bits(1:uw_len))); + if (uw_errors > 3) sync_counter++; - #{ if sync_counter == sync_counter_thresh next_state = 'searching'; sync_counter = Nerrs = 0; - - % print error stats for this sync period - - printf("\nBER..: %5.4f Tbits: %5d Terrs: %5d\n", Terrs/Tbits, Tbits, Terrs); - - % reset BER stats - - Terrs = Tbits = frame_count = 0; end - #} else sync_counter = 0; end end + printf("f: %2d state: %-10s uw_errors: %2d %1d nin: %d Nerrs: %3d foff: %3.1f\n", f, state, uw_errors, sync_counter, nin, Nerrs,states.foff_est_hz); state = next_state; end diff --git a/codec2-dev/octave/ofdm_tx.m b/codec2-dev/octave/ofdm_tx.m index 2262b480..4241f031 100644 --- a/codec2-dev/octave/ofdm_tx.m +++ b/codec2-dev/octave/ofdm_tx.m @@ -22,7 +22,7 @@ function ofdm_tx(filename, Nsec, EbNodB=100, channel='awgn', freq_offset_Hz=0) % init modem - Ts = 0.018; Tcp = 0.002; Rs = 1/Ts; bps = 2; Nc = 16; Ns = 8; + Ts = 0.018; Tcp = 0.002; Rs = 1/Ts; bps = 2; Nc = 17; Ns = 8; states = ofdm_init(bps, Rs, Tcp, Ns, Nc); ofdm_load_const; @@ -46,7 +46,7 @@ function ofdm_tx(filename, Nsec, EbNodB=100, channel='awgn', freq_offset_Hz=0) variance = 1/(M*EsNo/2); woffset = 2*pi*freq_offset_Hz/Fs; - SNRdB = EbNodB + 10*log10(700/3000); + SNRdB = EbNodB + 10*log10(Nc*bps*Rs/3000); printf("EbNo: %3.1f dB SNR(3k) est: %3.1f dB foff: %3.1fHz ", EbNodB, SNRdB, freq_offset_Hz); % set up HF model ---------------------------------------------------------------