참고 논문 :
CP 를 이용해 Time Offset 과 Freq Offset 을 검출하는 수식을
1. 직관적인 유도 (쉬움)
2. 가우시안 분포와 log-likelihood(log+조건부 확률)을 이용한 수식적 유도 (어려움)
두 과정으로 보겠습니다.
직관적인 유도
Time Offset
한 심볼의 길이가 N
CP 의 길이가 L 일 때
임의의 신호 부분에서 2N+L 만큼 추출 하면
반드시 신호 (N) 과 CP (L) 이 포함되어 있습니다.
CP 는 N 이후의 신호(CP' 라고 칭하겠음)에 대해 동일한 값을 가지고
신호는 복소 값들로 이루어져 있으므로
임의의 신호와 N 이후의 신호를 곱했을 때
CP 에 해당하는 부분이 최대 값을 가지게 됩니다.
또한 이 과정을 CP 의 길이 동안 하면
CP 의 시작점에서 곱한 결과를 더한 값에서
최대 값을 나타나므로
CP 의 시작 지점 또한 알 수 있습니다.
이 값은 Time Offset 을 의미합니다.
Frequency Offset
ofdm 에서 각 심볼은 주파수 영역에서 생성한 데이터를
IDFT(IFFT) 를 거쳐 시간 영역으로 전환해 데이터를 전송합니다.
IDFT 의 식은 아래와 같습니다.
자연상수 e 의 승수가 위상의 회전을 의미 하는 것을 생각하면
IDFT 를 통해 나오는 수열의 각 요소들은
원에서 일정한 간격(2 pi / N)을 두고 배치 된 것임을 알 수있습니다.
또한 해당 신호에서 N 번째 이후의 성분은
동일한 위상을 가지는 것을 알 수 있습니다.
따라서 정상적인 상황에서 CP 와 CP' 는 동일한 위상을 가져야합니다.
하지만 만약 반송파 주파수의 오프셋(CFO)이 생기면
매 데이터 마다 CFO 가 누적되어 한바퀴를 돌고나면
CFO * N 에 해당하는 Offset 이 발생합니다.
CFO*N 값은 두 신호중 하나를 아래로 뒤집어서 (conjugate)
곱한 결과의 위상 성분에 해당합니다.
따라서 해당 위상에
(-N pi) 를 나눠 주면 반송파의 Offset 을 알 수 있습니다.
그리고 CFO 를 보상해줄 때는
(-k pi) 를 곱한 값으로 회전(e의 승수를 곱해줌) 시켜주면 됩니다.
(K 는 해당 데이터 번호)
수식적인 유도
MATLAB 코드 1 (Van de Beek 논문 코드 구글링)
%% ML estimation of time and frequency offset in OFDM systems
% Algorithm authors : J.J. van de Beek, M. Sandell, and P.O. B훟rjesson
% Prepared by Hiren Gami
clc
clear all;
%% Parameter declaration according to paper
Nfft = 1024;
Ncp = 128;
Nsym = 6;
FreqOffset = 2.3;
SNRdb = 10;
theta = 256;
%% OFDM symbol generation
data = 2*randi([0 1],1, Nsym*Nfft)-1; % BPSK data
Tx = zeros(1,Nsym*(Nfft+Ncp));
OFDMsym = zeros(1,Nfft);
for sym = 1:Nsym
OFDMsym = ifft(data(Nfft*(sym-1)+1:(Nfft*sym)),Nfft)*sqrt(Nfft); % data -> ifft sym (per sym)
Tx((Nfft+Ncp)*(sym-1)+1:(Nfft+Ncp)*sym) = [OFDMsym(Nfft-Ncp+1:Nfft) OFDMsym]; % add CP
end
%% AWGN channel
snr = 10^(-SNRdb/10);
noise = sqrt(snr/2)*(randn(1,Nsym*(Nfft+Ncp))+1i*randn(1,Nsym*(Nfft+Ncp)));
Rx = exp(1i*2*pi*FreqOffset*(0:length(Tx)-1)./Nfft).*Tx + noise;
c = length(Tx);
%% ML estimation of timing and frequency offset
PHI_sum = zeros(1,Nsym*(Nfft+Ncp)-Nfft);
GM_sum = zeros(1,Nsym*(Nfft+Ncp)-Nfft);
for n = 1:Nsym*(Nfft+Ncp)-(Nfft+Ncp)
PHI=0;GM=0;
for m = n:n+Ncp-1
PHI = PHI+ (Rx(m)*conj(Rx(m)) + Rx(m+Nfft)*conj(Rx(m+Nfft)));
GM = GM+ Rx(m)*conj(Rx(m+Nfft));
end
PHI_sum(n) = abs(GM)- (snr/(snr+1))*PHI;
GM_sum(n) = -angle(GM)/(2*pi);
end
%% Estimation results display
[~, timeOffset] = max(PHI_sum);
freqOffset = GM_sum(timeOffset);
subplot(2,1,1);plot(PHI_sum);title('Estimation of timing offset');grid on;
subplot(2,1,2);plot(GM_sum);title('Estimation of frequency offset');grid on;
[value,thetaEst]=findpeaks(PHI_sum,'minpeakdistance',Nfft);
disp(thetaEst);
disp(GM_sum(thetaEst));
MATLAB 코드 2 (PSS detection 에서 CFO estimation 을 추가한 코드)
만약 CFO estimation 을 안한 결과를 보고 싶으시면
상단 부근의 Initialize 영역에서
bCfoCpEstimation 을 false 로 하시면 됩니다 ;)
pNotPss 는 Pss 가 아닌 신호를 받을 때 correlation 이 threshold 보다 높은지 체크
pPss 는 루트 값이 맞는지, 시간 오프셋이 맞는지, correlation 이 threshold 보다 높은지 체크한 결과.
CP 를 이용해 CFO 를 조정하니 훨씬 좋은 결과가 나타남!!
clear all;
close all;
%% initialize ==============================================================
symbolSz = 1024; % this is used as fft size
NumSubcarrier = 600;
cpLen = 72;
cellID = randi([0 503]);
IdN1 = ceil(cellID / 3); % SSS
IdN2 = rem(cellID, 3); % PSS
corrFrameSize = 72;
padLen = corrFrameSize/2;
startPoint = cpLen / 4;
freqOffset = 0.3;
%% Generate data
data = rand(NumSubcarrier, 1) + 1i*rand(NumSubcarrier, 1);
data2 = rand(NumSubcarrier, 1) + 1i*rand(NumSubcarrier, 1);
data = [data(1:NumSubcarrier/2); 0; data(NumSubcarrier/2+1 : end)];
data2 = [data2(1:NumSubcarrier/2); 0; data2(NumSubcarrier/2+1 : end)];
%% Generate PSS ===========================================================
zcRootI = [25, 29, 34];
pss = [];
for n = 1 : 3
tmp = zadoffChuSeq(zcRootI(n), 63);
pss = cat(2, pss, [zeros(5, 1);tmp(1:31); zeros(1, 1); tmp(33:end);zeros(5, 1)]);
end
pss_tx = pss(1 + IdN2 * 73 : (1 + IdN2) * 73);
pss_tx = pss_tx';
%% generate SSS
[d0, d5] = generate_sss(IdN1);
tmp = randi(2);
if (tmp ~= 0)
sss = d0;
else
sss = d1;
end
sss_tx = [zeros(1,5) sss zeros(1,5)];
%% ifft
% n point ifft
pss_tx_time = ifft(pss_tx, symbolSz);
sss_tx_time = ifft(sss_tx, symbolSz)';
data_tx_time = ifft(data, symbolSz);
data2_tx_time = ifft(data2, symbolSz);
% add CP
pss_tx_cp_time = [pss_tx_time(1:cpLen); pss_tx_time];
data_tx_cp_time = [data_tx_time(1:1+cpLen); data_tx_time];
data2_tx_cp_time = [data2_tx_time(1:1+cpLen); data2_tx_time];
E_N = length(pss_tx_cp_time);
Eavg_tx_time = sum(abs(pss_tx_cp_time) .^ 2)/length(E_N);
%pssTxCpCfoTime = pss_tx_cp_time;
pssTxCpCfoTime = generateCFO(pss_tx_cp_time, freqOffset, symbolSz);
pss_ifft = [];
for n = 0:2
tmp = ifft(pss(1 + n * 73 : (1 + n) * 73)', symbolSz);
pss_ifft = [pss_ifft; tmp];
end
%% pss detection ==========================================================
threshhold = [0 0.001+0.0003*(1:6) inf];
pPss = zeros(length(threshhold), 1);
pNotPss = zeros(length(threshhold), 1);
iter_num = 1e+3;
snr_dB = 0;
Pd_error_offset_s = [];
Pe_error_offset_s = [];
for n = 1:length(threshhold)
for iter = 1:iter_num
%% pss sig
corr_maxs = zeros(3,1);
cors = zeros(corrFrameSize, 1);
detect_offsets = zeros(3,1);
for m = 0:2
% padding for time offset
rand_padding2 = zeros(padLen,1);
%sss_tx_n_time = my_awgn(sss_tx_time, snr_dB);
data_tx_cp_n_time = my_awgn(data_tx_cp_time, snr_dB);
pssTxCpNoiseCFOTime = my_awgn(pssTxCpCfoTime, snr_dB);
%pss_tx_n_pad_time = [sss_tx_n_time((1+symbol_sz-pad_len : symbol_sz)); pss_tx_n_time; data_tx_n_time(1 : pad_len)];
pss_tx_cp_n_pad_time = [pssTxCpNoiseCFOTime; data_tx_cp_n_time(1:corrFrameSize)];
% detecting
for l = 0 : corrFrameSize-1
pss_tx_sample = pss_tx_cp_n_pad_time(l+1 + startPoint:l+symbolSz + startPoint);
%pss_tx_n_fft = fft(pss_tx_sample);
% FD
%cor = abs(xcorr(pss_tx_n_fft(1:73), pss(1 + m * 73 : (1 + m) * 73)', 0));
% TD
tmp = xcorr(pss_tx_sample, pss_ifft(1 + m * symbolSz : (1 + m) * symbolSz), 0);
cors(1+l) = (real(tmp)^2+imag(tmp)^2);
end
[corr_maxs(m + 1), detect_offsets(m + 1)] = max(cors);
end
[max_cor, detect_ID_2] = max(corr_maxs);
detect_offset = detect_offsets(detect_ID_2);
% offset == pad_len because time offset is pad_len
if (threshhold(n) <= max_cor && ...
detect_ID_2-1 == IdN2)
if (detect_offset == cpLen - startPoint + 1)
pPss(n) = pPss(n) + 1;
else
Pd_error_offset_s = [Pd_error_offset_s detect_offset];
end
end
%% rand sig
corr_maxs = zeros(3,1);
detect_offsets = zeros(3,1);
for m = 0:2
data_pad_time = [data_tx_cp_time; data2_tx_cp_time];
data_tx_cp_n_time = my_awgn(data_pad_time, snr_dB);
% padding for time offset
padLen = symbolSz/4;
rand_padding2 = zeros(padLen,1);
% detecting
for l = 0 : corrFrameSize-1
rand_tx_sample = data_pad_time(l+1+startPoint:l+symbolSz+startPoint);
% FD
%cor = abs(xcorr(rand_n_fft(1:73), pss(1 + m * 73 : (1 + m) * 73)', 0));
% TD
tmp = xcorr(rand_tx_sample, pss_ifft(1 + m * symbolSz : (1 + m) * symbolSz), 0);
cors(1+l) = (real(tmp)^2+imag(tmp)^2);
end
corr_maxs(m + 1) = max(cors);
end
[max_cor, detect_ID_2] = max(corr_maxs);
%detect_offset = detect_offsets(detect_ID_2);
% offset == pad_len because time offset is pad_len
%detect_offset == pad_len && ...
if (threshhold(n) <= max_cor)
pNotPss(n) = pNotPss(n) + 1;
end
end
end
pNotPss = pNotPss / iter_num;
pPss = pPss / iter_num;
plot(pNotPss, pPss, 'b--o');
title('ROC')
xlabel('p Not PSS')
ylabel('p PSS')
%% get energy
function [energy] = get_energy(signal)
% Get the number of symbols
N = length(signal);
% Calculate Symbol Energy
energy = sum(abs(signal) .^ 2)/N;
end
%% awgn noise with power
function [noise] = get_wgn_energy(energy, signal, SNR_dB)
% Specify SNR in dB. Try setting various different value here and see how the result changes
% Get the number of symbols
N = length(signal);
% Convert SNR (in dB) to SNR (in Linear)
SNR_lin = 10 .^ (SNR_dB/10);
% Calculate the Sigma (Standard Deviation) of AWGN
awgnSigma = sqrt(energy/(2*SNR_lin));
% Generate a sequence of noise with Normal Distribution and rescale it with the sigma
noise = awgnSigma*(randn(1,N)+1i*randn(1,N));
noise = noise';
end
function signalCFO = generateCFO(signal, cfo, fftSize)
tmp =exp(1i*2*pi*cfo*(0:length(signal)-1)./fftSize);
signalCFO = tmp'.*signal;
end
function [timeOffset, freqOffset] = calculateCfoCp(signal, nFft, nCp, nSym, snrDb)
PHI_sum = zeros(1,nSym*(nFft+nCp)-nFft);
GM_sum = zeros(1,nSym*(nFft+nCp)-nFft);
for n = theta:nSym*(nFft+nCp)-(nFft+nCp)
PHI=0;GM=0;
for m = n:n+nCp-1
PHI = PHI+ (signal(m)*conj(signal(m)) + signal(m+nFft)*conj(signal(m+nFft)));
GM = GM+ signal(m)*conj(signal(m+nFft));
end
PHI_sum(n) = abs(GM)- (snrDb/(snrDb+1))*PHI;
GM_sum(n) = -angle(GM)/(2*pi);
end
[~, timeOffset] = max(PHI_sum);
freqOffset = GM_sum(timeOffset);
end
'통신 & 네트워크' 카테고리의 다른 글
초보자를 위한 LTE (1) - 셀 검색 (0) | 2022.09.22 |
---|---|
고주파를 사용할수록 안테나의 길이가 줄어든다.. 왜? (0) | 2022.09.15 |
SNR 이용한 AWGN 공식 (AWGN formula) (0) | 2022.09.14 |
LTE downlink SSS detection (PSS 신호를 이용한 방법) (0) | 2022.09.02 |
논문 요약 - Carrier Frequency Synchronization in the Downlink of 3GPP LTE (0) | 2022.08.19 |