MATLAB完成DFT-S-OFDM信号的接收端编解码与调制解调

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


猜你喜欢

转载自blog.csdn.net/chenshiming1995/article/details/105178266
今日推荐