初识LTE(三):码率匹配和码率分块
一.码率匹配
1.码率匹配原理
什么是码率匹配呢?就是Turbo编码原本码率是1/3,如果信道很好,那我可以少发一点1/2就可以了,这就是码率匹配
码率匹配原理如下
那么,如何解码率匹配呢,那些比特可是结结实实的少发了呀!
实际上,就是用0填充,LTE称其为打孔和解打孔操作
2. 码率匹配代码
%------------------------码率匹配-----------------------%
%-----------------------author:lzx-------------------------%
%-----------------------date:2022年7月1日17点45分-----------------%
function y= RateMatcher(in, Kplus, Rate)
% Rate matching per coded block, with and without the bit selection.
% D是发送比特的长度
D = Kplus+4;
if numel(in)~=3*D, error('Kplus (2nd argument) times 3 must be size of input 1.');end
% Parameters
% 矩阵的列固定为32,然后去满足够的行以放下所有比特
% 多余的Nd个填Null
colTcSb = 32;
rowTcSb = ceil(D/colTcSb);
Kpi = colTcSb * rowTcSb;
Nd = Kpi - D;
% Bit streams
% 取出Turbo编码的三个比特流
d0 = in(1:3:end); % systematic
d1 = in(2:3:end); % parity 1st
d2 = in(3:3:end); % parity 2nd
% 交织
i0=(1:D)';
Index=indexGenerator(i0,colTcSb, rowTcSb, Nd);
Index2=indexGenerator2(i0,colTcSb, rowTcSb, Nd);
% Sub-block interleaving - per stream
v0 = subBlkInterl(d0,Index);
v1 = subBlkInterl(d1,Index);
v2 = subBlkInterl(d2,Index2);
vpre=[v1,v2].';
v12=vpre(:);
% Concat 0, interleave 1, 2 sub-blk streams
% Bit collection
% 比特收集
wk = zeros(numel(in), 1);
wk(1:D) = v0(~isnan( v0 ));
wk(D+1:end) = v12(~isnan( v12 ));
% Apply rate matching
% 裁剪
N=ceil(D/Rate);
y=wk(1:N);
end
function v = indexGenerator(d, colTcSb, rowTcSb, Nd)
% Sub-block interleaving - for d0 and d1 streams only
colPermPat = [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];
% For 1 and 2nd streams only
y = [NaN*ones(Nd, 1); d]; % null (NaN) filling
inpMat = reshape(y, colTcSb, rowTcSb).';
permInpMat = inpMat(:, colPermPat+1);
v = permInpMat(:);
end
function v = indexGenerator2(d, colTcSb, rowTcSb, Nd)
% Sub-block interleaving - for d2 stream only
colPermPat = [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];
pi = zeros(colTcSb*rowTcSb, 1);
for i = 1 : length(pi)
pi(i) = colPermPat(floor((i-1)/rowTcSb)+1) + colTcSb*(mod(i-1, rowTcSb)) + 1;
end
% For 3rd stream only
y = [NaN*ones(Nd, 1); d]; % null (NaN) filling
inpMat = reshape(y, colTcSb, rowTcSb).';
ytemp = inpMat.';
y = ytemp(:);
v = y(pi);
end
function out=subBlkInterl(d0,Index)
out=zeros(size(Index));
IndexG=~isnan(Index);
IndexB=isnan(Index);
MyIndex=Index(IndexG);
out(IndexG)=d0(MyIndex);
Nd=sum(IndexB);
out(IndexB)=nan(Nd,1);
end
%------------------------解码率匹配-----------------------%
%-----------------------author:lzx-------------------------%
%-----------------------date:2022年7月1日17点53分-----------------%
function out = RateDematcher(in, Kplus)
% Undoes the Rate matching per coded block.
%#codegen
% 之前被打孔掉的比特用0填充即可,为什么?
% Parameters
colTcSb = 32;
D = Kplus+4;
rowTcSb = ceil(D/colTcSb);
Kpi = colTcSb * rowTcSb;
Nd = Kpi - D;
tmp=zeros(3*D,1);
tmp(1:numel(in))=in;
% no bit selection - assume full buffer passed in
i0=(1:D)';
Index= indexGenerator(i0,colTcSb, rowTcSb, Nd);
Index2= indexGenerator2(i0,colTcSb, rowTcSb, Nd);
Indexpre=[Index,Index2+D].';
Index12=Indexpre(:);
% Bit streams
tmp0=tmp(1:D);
tmp12=tmp(D+1:end);
v0 = subBlkDeInterl(tmp0, Index);
d12=subBlkDeInterl(tmp12, Index12);
v1=d12(1:D);
v2=d12(D+(1:D));
% Interleave 1, 2, 3 sub-blk streams - for turbo decoding
temp = [v0 v1 v2].';
out = temp(:);
end
function v = indexGenerator(d, colTcSb, rowTcSb, Nd)
% Sub-block interleaving - for d0 and d1 streams only
colPermPat = [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];
% For 1 and 2nd streams only
y = [NaN*ones(Nd, 1); d]; % null (NaN) filling
inpMat = reshape(y, colTcSb, rowTcSb).';
permInpMat = inpMat(:, colPermPat+1);
v = permInpMat(:);
end
function v = indexGenerator2(d, colTcSb, rowTcSb, Nd)
% Sub-block interleaving - for d2 stream only
colPermPat = [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];
pi = zeros(colTcSb*rowTcSb, 1);
for i = 1 : length(pi)
pi(i) = colPermPat(floor((i-1)/rowTcSb)+1) + colTcSb*(mod(i-1, rowTcSb)) + 1;
end
% For 3rd stream only
y = [NaN*ones(Nd, 1); d]; % null (NaN) filling
inpMat = reshape(y, colTcSb, rowTcSb).';
ytemp = inpMat.';
y = ytemp(:);
v = y(pi);
end
function out=subBlkDeInterl(in,Index)
out=zeros(size(in));
IndexG=find(~isnan(Index)==1);
IndexOut=Index(IndexG);
out(IndexOut)=in;
end
二.码块分割
1.码块分割的原理
解码就是逆操作,这里就不展开了
2.代码
%------------------------码块分割-----------------------%
%-----------------------author:lzx-------------------------%
%-----------------------date:2022年7月2日20点35分-----------------%
function [C, Kplus] = CblkSegParams(tbLen)
%#codegen
%% Code block segmentation
% C: 被分为了多少个码块
% KPlus: 被分割完的会有两个长度,一个是K-一个是K+,详情看我博客
blkSize = tbLen + 24;
maxCBlkLen = 6144;
% 无需分块
if (blkSize <= maxCBlkLen)
C = 1; % number of code blocks
b = blkSize; % total bits
% 计算C
else
L = 24;
C = ceil(blkSize/(maxCBlkLen-L));
b = blkSize + C*L;
end
% Values of K from table 5.1.3-3
validK = [40:8:512 528:16:1024 1056:32:2048 2112:64:6144].';
% 找到Kplus
% First segment size
temp = find(validK >= b/C);
Kplus = validK(temp(1), 1); % minimum K
%------------------------找到分块后每块的长度-----------------------%
%-----------------------author:lzx-------------------------%
%-----------------------date:2022年7月2日20点50分-----------------%
function E = CbBitSelection(C, G, Nl, Qm)
%#codegen
% Bit selection parameters
% G = total number of output bits
% Nl Number of layers a TB is mapped to (Rel10)
% Qm modulation bits
Gprime = G/(Nl*Qm);
gamma = mod(Gprime, C);
E=zeros(C,1);
% Rate matching with bit selection
% 余数以下的小一点,大于的大一点
for cbIdx=1:C
if ((cbIdx-1) <= (C-1-gamma))
E(cbIdx) = Nl*Qm*floor(Gprime/C);
else
E(cbIdx) = Nl*Qm*ceil(Gprime/C);
end
end
这里做一个补充,代码中获得总比特数G的式子是
G=ceil((Kplus+4)/CodingRate);
这明显只适用于不分块的情况,正确的应该是
G=ceil((Kplus+4)*C/CodingRate);
分析一下为什么,正常总比特应该如何计算呢
应该是输入数据长度inLen加上CRC和Turbo编码的长度,CRC会增加24比特,Turbo增加四比特
合计就是(inLen+C*(4+24))再进行码率匹配
但是注意,为了方便Kplus的选取,我们的输入长度总是Kplus-24的长度,所有代码都是这样的,或是他的倍数,因此两者殊途同归!
但是要注意把C补上
三.CRC
CRC纠错遍布在整个LTE中,整个TB需要添加CRC,分割后每个码块也要添加CRC
CRC的远离大致是补零后整除,不会的可以在一些通信原理书上学习一下
四.LTE发送总流程
如下图,重组后进行扰码,调制,然后发送,这就是DLSCH的总流程