DSPRelated.com
Forums

OFDM symbol timing Schmidl & Cox

Started by spetcavich 6 years ago1 replylatest reply 6 years ago1395 views

I'm implementing Schmidl and Cox in Matlab and attempting to recover the data being transmitted. However, I have a problem even with 0 carrier frequency offset, 0 carrier phase shift, and my channel vector just being [1], sometimes my timing estimation will be +/- 2 symbols off (due to noise I've injected) and my data will be 'spinning'. The schmidl & cox paper is below. I can't tell what I'm doing wrong and how to fix the issue if my timing is a couple symbols off. My intuition tells me I should be able to make a full recovery if the timing is within the guard band (cyclic prefix)

http://140.117.160.140/course/pdfdownload/94_2/%E6...


close all

clear all

%parameters for sim

%carrier frequency offset

cfo = 0.00;

%phase offset

cpo = 0;

%channel 

chan = [1]

%fft length

N=64;

%cyclic prefix length

cycPre = 16;

%symbol length

symLen = N + cycPre; 

%create the schmidl-cox preamble

sw1 =  [zeros(1,6), 2*randi([0,1],1,26)-1, 0, 2*randi([0,1],1,26)-1, zeros(1,5)];

sw1(find(sw1==-1)) = -sqrt(2);

sw1(find(sw1==1))  =   sqrt(2);

%zero out out frequencies 33 = DC [odds on even]

sw1(2:2:end) = 0;

pre1 = ifft(sw1,N);

syncword1= [pre1(49:64) pre1];

%create second preamble

sw2 =  [zeros(1,6), 2*randi([0,1],1,26)-1, 0, 2*randi([0,1],1,26)-1, zeros(1,5)];

pre2 = ifft(sw2,N);

syncword2 = [pre2(49:64) pre2];


%create the data to send

inputiFFT = [zeros(1,6), 2*randi([0,1],1,26)-1, 0, 2*randi([0,1],1,26)-1, zeros(1,5)];

outputiFFT = ifft((inputiFFT),N);

%cyclic prefix

outputiFFT_with_CP = [outputiFFT(49:64) outputiFFT];

%construct the signal in the middle of 2000 points

tx = 20*[syncword1 syncword2 outputiFFT_with_CP];

sig = 0.0001*(randn(1,160)+1j*randn(1,160));

txall = [sig tx sig] 


noise =0.01*(randn(1,length(txall))+1j*randn(1,length(txall)));

IQ = filter(chan,1,txall) + noise;

nn = [0:length(IQ)-1];

w = 2*pi*cfo

ejwn = exp(1i*(w*nn + cpo));

IQ= (IQ/20).*ejwn;


L =  N/2-1;

M = N/2;

%schmidl and cox P, R, and M 

for j = 1:length(IQ)-2*M

    P(j) = sum(conj(IQ(j:j+L)).*(IQ(j+(L+1):j+2*(L+1)-1)));

    R(j) = sum(abs(IQ(j+(L+1):j+2*(L+1)-1)).^2);

end

M = (abs(P).^2)./(R.^2);

%find start via schmidl and cox method

sync = 0;

strt = cycPre + 1;

cntr = 0; 

for j = 1:length(M)-1

  if(M(j) > .96 & M(j) < 1.5)

        if(M(j-1) > .96 )

            cntr = cntr + 1;

        end

        if(cntr == cycPre)

            sync = j;

            cntr=0

        end

    else

      cntr =0 ;

    end

end

%actual start for testing

%sync = 177

%eq (39) , (40), 

phi = angle(P(sync));

CFO =  phi/(N*pi);

%check if phi > pi

flag_cfo = 0;

if(phi > pi)

  flag_cfo = 1;

end

%sanity check

realstart= 161+symLen*2+16;

actual_data = fft(txall(realstart:realstart+63),64);

bins = [0:63];

%calculate start

start = sync+(N)+symLen+cycPre;

%fft sync word 1

x1k = fft(IQ(sync:sync+N-1),N);

%fft sync word 2

x2k = fft(IQ(sync+N+cycPre:sync+N+cycPre+N-1),N);

%the data that is spun

data_corrected = fft(IQ(start:start+63),64);

%correct preamble 1 & 2 

x1ks = fft(IQ(sync:sync+N-1).*exp(-1j*2*pi*bins*CFO),N);

x2ks = fft(IQ(sync+(N)+cycPre:sync+(N)+cycPre+N-1).*exp(-1j*2*pi*bins*CFO),N);

%vk 

vkt = sqrt(2) * x2ks./x1ks;

vk = vkt(2:2:end);

%find B(g) to maximize eq(41)

denom = 2*(sum(abs(x2ks(1:2:end).^2))).^2

for k = 1:32

  x1t = circshift(x1ks(2:2:end), [1 2*k]);

  x2t = circshift(x2ks(2:2:end), [1 2*k]);

  B2(k) = abs(sum(conj(x1t).*conj(vk).*x2t)).^2/denom;

end

%find index for max B

[~, g0] = max(B2);

if(abs(CFO) > 3e-5)

  %if phi is greater than pi then we need an integer shift too

  if( flag_cfo == 0 )

    printOverPi = 1

    delF =  2*g0/N

    data_spin1 = IQ(start:start+63).*exp(-1j*2*pi*bins*CFO);

    data_spin2 = data_spin1.*exp(-1j*2*pi*delF);

    data_corrected2 = fft(data_spin2, N);

  %else just correct the CFO

  else

    data_spin1 = IQ(start:start+63).*exp(-1j*2*pi*bins*CFO);

    data_corrected2 = fft(data_spin1, N);

  end

else

  data_corrected2 = fft(IQ(start:start+63), N);

end

figure

plot(M(1:300))

hold on

plot(sync, M(sync), 'rx')

hold off

axis([1 length(M) 0 2])

title('M timing metric eq (8) in schmidl & cox paper')

figure

subplot(411)

plot(real(inputiFFT), imag(inputiFFT),'x');

title('input to FFT')

subplot(412)

plot(real(actual_data)*1/20, imag(actual_data)*1/20,'x')

title('sanity check actual data')

axis([-1 1 -1 1])

subplot(413)

plot(real(data_corrected), imag(data_corrected),'x')

title('data uncorrected')

subplot(414)

plot(real(data_corrected2), imag(data_corrected2),'x')

title('corrected data')

if(abs(CFO)>3e-5)

figure

subplot(311)

plot(real(data_spin1), imag(data_spin1),'x')

title('sanity check actual data')

subplot(312)

plot(real(data_spin2), imag(data_spin2),'x')

title('sanity check actual data')

axis([-1 1 -1 1])

subplot(313)

plot(real(data_corrected2), imag(data_corrected2),'x')

title('corrected data')

end

data_corrected(find(real(data_corrected)>.1)) = 1;

data_corrected(find(real(data_corrected)<-.1)) = -1;

data_corrected(find(abs(data_corrected)~=1)) = 0;

figure

plot(real(inputiFFT))

hold on

plot(real(data_corrected),'color','r')

hold off

title('input to fft, uncorrected data overlayed')

data_corrected2(find(real(data_corrected2)>.1)) = 1;

data_corrected2(find(real(data_corrected2)<-.1)) = -1;

data_corrected2(find(abs(data_corrected2)~=1)) = 0;

figure

plot(real(inputiFFT))

hold on

plot(real(data_corrected2),'color','r')

hold off

title('input to fft, corrected data overlayed')

[ - ]
Reply by jbrunoMarch 28, 2018

Hi spetcavich,

The time synchronizers are not perfect and Cox's is not the best of them. The detection of the start of frame (SOF) has a certain uncertainty (for example +/- 2 samples) and you must work with it. This is not a problem because there is a cyclic prefix but you must include a channel equalizer to resolved it.

When the detector error is +1 sample, you are taking N-1 samples from the current OFDM symbol and a sample from the next OFDM symbol. This is solved using a fixed correction of the TSA output, for example -3 samples, so that you can ensure that you are always taking samples of the same OFDM symbol. 

When the detector error is -1 sample, you are taking a sample of the cyclic prefix of the current OFDM symbol and N-1 samples of the current OFDM symbol, which is not wrong.

In both cases you must correct the phase change with an equalizer.

Take a look at this article where some TSAs for OFDM are compared: "A Novel Timing Estimation Method for OFDM Systems". And this one designed for WLAN: "Low Complexity Time Synchronization Algorithm for OFDM Systems with Repetitive Preambles"

Regards,

Julián