OFDM整理
1 原理部分
2 仿真验证部分
2.1 峰均比
2.2 SC-FDMA
close all;clear all;
% rng default
%**********************************
% 仿真参数
SNR_dBlist = (3:0.25:5.5);
SlotBitLen = 1536;
%------------------------------------
%1/2编码
Length = 2048;
%------------------------------------
Num1 = 1024;
Num2 = 2048;
fs = 2e5; % 码片速率,单位kHz
delta_f = 10.0; % 频偏,单位kHz
L_delay = 16;
[sort_tmp,sort_index] = sort(rand(1,Num1));
%------------------------------------
SubInterBitLen = SlotBitLen + 4; % 子交织器输入的个数
ColNum = 32; % 行列交织器的列数
RowNum = ceil(SubInterBitLen/ColNum); % 行列交织器的行数
SubMatEleNum = ColNum*RowNum; % 行列交织后总比特数
PadONum = SubMatEleNum - SubInterBitLen; % 填充比特个数
% PunNum = round(PunRation*Length);
ColIndex = [0 16 8 24 4 20 12 28 2 18 10 26 6 22 14 30 1 17 9 25 5 21 13 29 3 19 11 27 7 23 15 31 ]; % 列交织器
TbsC = 1; % 传输块分块个数
TCRvIdx = 0;
% QpskTab1 = exp(1j*pi*[1,-1,3,-3]/4); % QPSK调制星座图
Qm = 2; % 调制阶数, QPSK
RateMatchLenList = Length; % 速率匹配长度 从而保证输出是1/3编码
Length1 = Length/Qm;
%**********************************
[f1, f2] = getf1f2(SlotBitLen);
InterTbl = zeros(1,SlotBitLen);
for ii = 0:SlotBitLen-1
InterTbl(ii+1) = mod(f1*ii+f2*ii^2,SlotBitLen);
end
hTEnc = comm.TurboEncoder(poly2trellis(4, [13 15], 13), InterTbl + 1); % 简化方式
hTDec = comm.TurboDecoder(poly2trellis(4, [13 15], 13), InterTbl + 1, 10,'Algorithm','Max'); % 简化方式
QPSK_func = 1/sqrt(2)*[1+1i,1-1i,-1+1i,-1-1i];
%**********************************
tic
Pe_Block = zeros(1,length(SNR_dBlist));err_rate = zeros(1,length(SNR_dBlist));
% 这里的滤波器时干啥用的?好像和码片偏差有点关系啊
RcosCoef = rcosine(1,8,'fir',0.35,6);
SmplBias = 0;
if (SmplBias==0)
h_list_1(1:13) = RcosCoef(SmplBias+1:8:end);
else
h_list_1(1:12) = RcosCoef(SmplBias+1:8:end);
end
for SnrNum = 1:length(SNR_dBlist)
error = 0;Numbit = 0;BlockNum = 0; BlockErr = 0; SNR = SNR_dBlist(SnrNum);
while( ( (BlockErr < 100)||(BlockNum < 500) ) && (BlockNum < 5000) )
% for zzzz = 1:100
%------------------------------------------------------------------
% 生成基本数据源
BlockNum = BlockNum + 1;
Numbit = Numbit + SlotBitLen ; % 每次的仿真点数增加SrcLen
%------------------------------------
TCSrc = randi([0 1],1,SlotBitLen);
% Turbo编码
TurboCodeOut = step(hTEnc, TCSrc.').'; % 1/3码率 X0A0B0X1A1B1
%------------------------------------------------------------------
% 交织
TCBuffMat = zeros(1,3*SubMatEleNum);
SubInterMat = zeros(3,SubMatEleNum); % 子交织矩阵
%==================================================================
% 交织
for jj = 1:3
% 提取第jj路数据
SubTCSrc = TurboCodeOut(jj:3:end);
SigPad = [NaN*ones(1,PadONum),SubTCSrc]; % LTE标准中以Null进行比特填充, 仿真中以NaN代替
if (jj==3)
SigPad = [SigPad(2:end),SigPad(1)]; % 第二路校验比特要错开1比特
end
% 进行子块交织, 行进列出的过程
SigPadMat = reshape(SigPad, ColNum, RowNum).'; % 行入
SigMatColInter = SigPadMat(:,ColIndex + 1); % 交织
SubInterMat(jj,:) = reshape(SigMatColInter,1,[]); % 列出
end
% 输出得到 3*SubMatEleNum 长度的序列
TCBuffMat(1:SubMatEleNum) = SubInterMat(1,:);
TCBuffMat(SubMatEleNum + 1:2:3*SubMatEleNum) = SubInterMat(2,:);
TCBuffMat(SubMatEleNum + 2:2:3*SubMatEleNum) = SubInterMat(3,:);
%==================================================================
%==================================================================
% 速率匹配
% 确定匹配范围
TCKw = 3*SubMatEleNum; % 理想循环缓存器总长度
TCNcb = TCKw;
% 根据冗余版本号 TCRvIdx 和 TCNcb 确定开始位置
RMBeginPos = RowNum*(2*ceil(TCNcb/8/RowNum)*TCRvIdx + 2);
% 循环读取(mod TCNcb)直到匹配的长度
kk = 0;
jj = 0;
MatchOut = zeros(1,RateMatchLenList);
while (kk<RateMatchLenList)
% 候选的比特
CandiBit = TCBuffMat( mod(RMBeginPos + jj, TCNcb) + 1);
if (~isnan(CandiBit))
MatchOut(kk+1) = CandiBit;
kk = kk + 1;
end
% 缓存区位置加1
jj = jj + 1;
end
%==================================================================
%------------------------------------------------------------------
% QPSK星座映射和加入噪声
Tx_0 = zeros(1,Length1);
Tx_0(1:length(MatchOut)/2) = QPSK_func(2*MatchOut(1:2:end)+MatchOut(2:2:end)+1);
%---------------------------------------
% SC_FDMA
Tx = zeros(1,(Num2+L_delay)*Length1/Num1);
% tmp_index = randperm(Num2,Num1);
tmp_index1 = [(1:Num1/2),(Num2-Num1/2+1:Num2)];
[sort_tmp,sort_index] = sort(rand(1,Num1));
tmp_index = tmp_index1(sort_index);
for kk = 1:Length1/Num1
tmp = Tx_0(Num1*(kk-1)+1:Num1*kk);
tmp_fft = 1/sqrt(Num1)*fft(tmp,Num1);
tmp_fft1 = zeros(1,Num2);
tmp_fft1(tmp_index) = tmp_fft;
tmp1 = sqrt(Num2^2/Num1)*ifft(tmp_fft1,Num2);
Tx((Num2+L_delay)*(kk-1)+1:(Num2+L_delay)*kk) = [tmp1(end-L_delay+1:end),tmp1];
end
%---------------------------------------
% 发送信号
h_list = zeros(1,L_delay);
% h_list(1:5) = [0.29,0.5,0.58,0.5,0.29];
% h_list(1:5) = [1,0,0,0,0];
h_list(1:length(h_list_1)) = h_list_1;% 真实的信道相应?
% 调制和加入噪声
SigChann = zeros(1,length(Tx));
for kk = 1:L_delay
SigChann = SigChann+h_list(kk)*[zeros(1,kk-1),Tx(1:end+1-kk)];
end
SigChann = exp(1j*2*pi*delta_f/fs*(1:length(SigChann))).*SigChann + wgn(1,length(SigChann),-SNR_dBlist(SnrNum),'complex');
%------------------------------------
% h_est = [zeros(1,6),1];
h_est = h_list_1;
H_est = fft(h_est,Num2);% 这里转换成频域响应
% figure;plot(20*log10(abs(fftshift(H_est))),'r');grid on;
H_est_inv = conj(H_est)./(H_est.*conj(H_est)+10^(-SNR_dBlist(SnrNum)/10));
Rx = zeros(1,Length1);
for kk = 1:Length1/Num1
Rx_tmp = SigChann((Num2+L_delay)*(kk-1)+1+L_delay:(Num2+L_delay)*kk);
Rx_tmp_fft = fft(Rx_tmp,Num2);
Rx_tmp_fft1 = Rx_tmp_fft.*H_est_inv;
Rx_tmp_fft2 = Rx_tmp_fft1(tmp_index);
Rx_tmp1 = ifft(Rx_tmp_fft2,Num1);
Rx(Num1*(kk-1)+1:Num1*kk) = Rx_tmp1;
end
% figure;plot(Rx,'.r');grid on;
%------------------------------------
% QPSK软解调
y_QPSK_soft = zeros(1,Length);
y_QPSK_soft(1:2:end) = real(Rx);
y_QPSK_soft(2:2:end) = imag(Rx);
%==================================================================
% 解速率匹配
RcvRMMat = zeros(1,3*SubMatEleNum);
% 初始化接收缓存
RcvCirBufTmp = zeros(1,3*SubMatEleNum);
% 确定系统比特和校验比特序列中Null的位置
RcvCirBufTmp(ColIndex(1:PadONum)*RowNum + 1) = NaN;
RcvCirBufTmp(SubMatEleNum + 2*ColIndex(1:PadONum)*RowNum + 1) = NaN;
RcvCirBufTmp(SubMatEleNum + 2*ColIndex(1:PadONum - 1)*RowNum + 2) = NaN;
if (PadONum >0 )
RcvCirBufTmp(end) = NaN;
end
% 解速率匹配过程
kk = 0;
jj = 0;
% 根据冗余版本号 TCRvIdx 和 TCNcb 确定开始位置
RMBeginPos = RowNum*(2*ceil(TCNcb/8/RowNum)*TCRvIdx + 2);
AddTimeList = zeros(1, 3*SubMatEleNum); % 累加次数统计
while (kk<RateMatchLenList)
% 候选的比特
CandiBit = RcvCirBufTmp(mod(RMBeginPos + jj, TCNcb) + 1);
if (~isnan(CandiBit))
RcvCirBufTmp(mod(RMBeginPos + jj, TCNcb) + 1) = y_QPSK_soft(kk+1) + CandiBit;
% AddTimeList(mod(RMBeginPos + jj, TCNcb) + 1) = AddTimeList(mod(RMBeginPos + jj, TCNcb) + 1) + 1; % 累积次数加1
kk = kk + 1;
end
% 缓存区位置加1
jj = jj + 1;
end
% RcvRMMat = floor(RcvCirBufTmp./max(AddTimeList,1));
RcvRMMat = RcvCirBufTmp;
RcvCirBuf = RcvRMMat;
RcvSubBuffMat = zeros(3,SubMatEleNum);
RcvSubBuffMat(1,:) = RcvCirBuf(1:SubMatEleNum);
RcvSubBuffMat(2,:) = RcvCirBuf(SubMatEleNum+1:2:3*SubMatEleNum);
RcvSubBuffMat(3,:) = RcvCirBuf(SubMatEleNum+2:2:3*SubMatEleNum);
%=================================================================
% 解交织
TCDecSoftInfo = zeros(1,3*SubInterBitLen);
for jj = 1:3
RcvTCSoftMatTmp = reshape(RcvSubBuffMat(jj,:),RowNum,ColNum); % 列入
RcvTCSoftMat(1:RowNum,ColIndex + 1) = RcvTCSoftMatTmp; % 解交织
RcvSoftDeInter = reshape(RcvTCSoftMat.',1,[]);
if (jj==3)
RcvSoftDeInter = [RcvSoftDeInter(end),RcvSoftDeInter(1:end-1)]; % 第二路校验比特要错开1比特
end
% Turbo译码输入软信息
TCDecSoftInfo(jj:3:end) = RcvSoftDeInter(PadONum+1:end);
end
%------------------------------------
% 译码
TCDDecOut = step(hTDec,-real(TCDecSoftInfo.')).'; % APP算法是按照0映射成-1设计的, 与实际的映射0--1 相反,所以要取负数
TCDecErr = sum(abs(TCSrc - TCDDecOut));
% 进行当次译码结果的错误分析统计
error = error + TCDecErr ; % 错误数目累加
BlockErr = BlockErr + (TCDecErr>0); % 错误分组统计
end
%---------------------------------------------------------
% 统计所有的错误概率
err_rate( SnrNum) = error / Numbit ; % 错误概率输出
BlockNum = Numbit/SlotBitLen; % 分组总数
Pe_Block(SnrNum) = BlockErr/BlockNum; % 误分组概率输出
fprintf('EsN0 = %5.2f,error = %d, NumBit = %d , pe = %5.3d,SlotNum = %d,SlotErr = %d,Pe_Slot = %5.4f ,\n', SNR_dBlist(SnrNum), error, Numbit, err_rate(SnrNum) ,BlockNum ,BlockErr,Pe_Block(SnrNum));
end
toc