实验八-级联码的MATLAB实现

信息论编码实验3~9连载,更多看专栏。

一、级联码原理介绍

1.1 基本概念

级联码可分为串行级联码与并行级联码两类。我们只讨论 串行级联码:
在这里插入图片描述
可见,串行级联码就是采用内外两种编码方式进行编码,中间的交织只是对码流进行切割变换。

那么为什么我们需要级联码呢?
对于 AWGN 信道,多采用汉明码、BCH 码、卷积码等适合纠正随机独立差错的信道编码方式;
对于纯衰落信道,可以采用 RS 码、可纠正突发差错的分组码、卷积码等信道编码方式;
实际中随机错误和突发错误又同时发生,所以不同编码方式的级联会提高可靠性。
那么级联码中为什么有一个交织呢?
因为内编码器的码流遭受到突发错误时,有可能连着错一大片,错到内译码器也无能为力时,交织就可以发挥作用了。因为交织可以把连着错的码元分开,再交给外译码器,就有可能利用自动纠错功能再纠正回来(能救一个是一个)。

由于我们内编码器采用(2,1,3)卷积编码(实验七)、外编码器采用(7,4)汉明编码(实验六),之前都介绍过,所以下面只介绍 交织 的原理。

二、交织编译码

2.1 分组交织与去交织

原理如下:
在这里插入图片描述很简单,就是每次都输入 m×n 个码元(按行写入),再按列读出就行。
注意,对于长度不是 m×n 的整数倍的序列,程序会预先补零。

%% 分组交织测试主函数
clc
clear all
C = 1:20;   % 自定义原序列
m=7;n=4;    % 分组交织参数
C_pock_IL = pock_IL(C,m,n);
%C_IL47re = reshape(C_IL47.',B,length(C_IL47)/B).';
C_de_pock_IL = de_pock_IL(C_pock_IL,m,n);
%C_deIL47re = reshape(C_deIL47.',B,length(C_deIL47)/B).';
%{
disp(['原序列:',num2str(C)]);
disp(['交织结果:',num2str(C_IL47re)]);
disp(['去交织结果:',num2str(C_deIL47re)]);
disp(num2str(C));
disp(num2str(C_IL47re));
disp(num2str(C_deIL47re));
%}
fprintf('原序列:%s\n',num2str(C));
fprintf('交织结果:%s\n',num2str(C_pock_IL));
fprintf('去交织结果:%s\n',num2str(C_de_pock_IL));
%本函数实现分组交织编码
%输入参数:
%   待编码序列C
%   m*n分组交织编码
%输出参数:
%   分组交织后的序列C_out
function C_out = pock_IL(C,m,n)
    N = length(C);
    % 对输入序列进行补0至m*n的整倍数
    num0 = mod(m*n-mod(N,m*n),m*n);
    C_add0 = [C,zeros(1,num0)];

    % 对每一组进行处理
    N_add0 = length(C_add0);
    C_out = zeros(1,N_add0);
    for i=1:length(C_add0)/n/m
        % 取出m*n位
        Ci = C_add0(1,(1:m*n)+m*n*(i-1));
        % 进行分组交织编码
        Couti = reshape(reshape(Ci.',n,m).',1,m*n);
        % 输出
        C_out(1,(1:m*n)+m*n*(i-1)) = Couti;
    end
end
%%本程序用于实现分组去交织
%C_deIL = de_pock_IL(C_IL,B,M)
%输入参数:
%   卷积交织编码序列C_IL
%   (B,M)卷积交织编码
%输出参数:
%   去卷积交织后的序列C_deIL
function C_deIL = de_pock_IL(C_IL,m,n)
    N = length(C_IL);
    C_deIL = zeros(1,N);
    for i=1:N/n/m    % 对每一组进行处理
        % 取出m*n位
        Ci = C_IL(1,(1:m*n)+m*n*(i-1));
        % 进行分组交织编码
        C_deILi = reshape(reshape(Ci.',m,n).',1,n*m);
        % 输出
        C_deIL(1,(1:m*n)+m*n*(i-1)) = C_deILi;
    end

end

运行主程序可以得到如下结果:
在这里插入图片描述

2.2 (B,M)卷积交织与去交织

卷积交织本质上就是向后大量的偏移。下面看(3,1)卷积交织与去交织(B=3,M=1)的例子:
卷积交织过程基本就是将序列分割,每组大小为B,再将这B个码元按照 M的递增整数倍延迟 (M就是D中包含的寄存器的数量,这里是1)依次放到输出序列中,空余的地方用零补上。去交织反过来就行。
卷积应该是就体现在那个旋转开关了,真的是…感觉叫 超离谱延迟交织 也不错。开个玩笑,可能是我对卷积的理解不够深入吧。
另外注意,假如输入序列不是B的整倍数也要预先补零。

%% 实验二:卷积交织测试主函数
clear all
clc
C = 1:20;
B=4;M=7;
C_IL47 = conv_IL(C,B,M);
%C_IL47re = reshape(C_IL47.',B,length(C_IL47)/B).';
C_deIL47 = de_conv_IL(C_IL47,B,M);
%C_deIL47re = reshape(C_deIL47.',B,length(C_deIL47)/B).';
%{
disp(['原序列:',num2str(C)]);
disp(['交织结果:',num2str(C_IL47re)]);
disp(['去交织结果:',num2str(C_deIL47re)]);
disp(num2str(C));
disp(num2str(C_IL47re));
disp(num2str(C_deIL47re));
%}
fprintf('原序列:%s\n',num2str(C));
fprintf('交织结果:%s\n',num2str(C_IL47));
fprintf('去交织结果:%s\n',num2str(C_deIL47));
%本子程序用来进行(B,M)卷积交织编码
%function C_out = conv_IL(C,B,M)
%输入参数:
%   待编码序列C
%   (B,M)卷积交织编码
%输出参数:
%   卷积交织后的序列C_out
function C_out = conv_IL(C,B,M)
    % 将序列补0到长度为B的整倍数
    N = length(C);
    num0 = mod(B-mod(N,B),B);
    C_add0 = [C,zeros(1,num0)];

    % 进行卷积交织
    N_add0 = length(C_add0);
    C_out = zeros(1,N_add0+B*(B-1)*M);
    for i=1:N_add0   %length(C_add0)/B
        %QUO = floor(N/B);% 获得商
        RE = mod(i-1,B);% 获得偏移量
        C_out(1,i+RE*B*M) = C_add0(1,i);
    end    
end
%本程序用于实现卷积去交织
%C_deIL = de_conv_IL(C_IL,B,M)
%输入参数:
%   卷积交织编码序列C_IL
%   (B,M)卷积交织编码
%输出参数:
%   去卷积交织后的序列C_deIL
function C_deIL = de_conv_IL(C_IL,B,M)
    N = length(C_IL);
    
    % 进行卷积去交织
    C_deIL = zeros(1,N+B*(B-1)*M);
    for i=1:N   %length(C_add0)/B
        %QUO = floor(N/B);% 获得商
        RE = mod(B-mod(i,B),B);   % 获得偏移量
        C_deIL(1,i+RE*B*M) = C_IL(1,i);
    end    
    
    % 去除前后多余的B*(B-1)*M个0元素
    C_deIL(end-B*(B-1)*M+1:end) = [];
    C_deIL(1:B*(B-1)*M) = [];

end

代码运行结果如下:
值得一提的是,假如修改卷积交织的参数,随着B和M的乘积越大(比如B=4,M=7,这是我们的作业),就越能理解为啥我叫它 超离谱延迟卷积。

2.3 随机交织与去交织

随机交织就好说了,原理中仅有一个参数为 N。交织过程就是把原始序列分割,每一组大小为N,然后将[1-N]这N个数随机排列(matlab自带子函数 randperm),然后按照这个序列映射出输出序列。
注意,要将这个映射关系传递到去交织的函数里。去交织思路相反。

%% 实验二:随机交织测试主函数
clear all
clc
C = 1:20;
N = 28;
[C_rand_IL,s] = rand_IL(C,N);
%C_IL47re = reshape(C_IL47.',B,length(C_IL47)/B).';
C_de_rand_IL = de_rand_IL(C_rand_IL,s);
%C_deIL47re = reshape(C_deIL47.',B,length(C_deIL47)/B).';
%{
disp(['原序列:',num2str(C)]);
disp(['交织结果:',num2str(C_IL47re)]);
disp(['去交织结果:',num2str(C_deIL47re)]);
disp(num2str(C));
disp(num2str(C_IL47re));
disp(num2str(C_deIL47re));
%}
fprintf('原序列:%s\n',num2str(C));
fprintf('随机映射关系:%s\n',num2str(s));
fprintf('交织结果:%s\n',num2str(C_rand_IL));
fprintf('去交织结果:%s\n',num2str(C_de_rand_IL));
%本程序实现随机交织编码
%function [C_out,s] = rand_IL(C,N)
%输入参数:
%   待编码序列C
%   (B,M)卷积交织编码
%输出参数:
%   卷积交织后的序列C_out
function [C_out,s] = rand_IL(C,N)
    % 对输入序列进行补0至N的整倍数
    len_C = length(C);
    num0 = mod(N-mod(len_C,N),N);
    C_add0 = [C,zeros(1,num0)];
   
    % 生成随机映射关系s
    s = randperm(N);
    
    % 对每一块序列,根据映射关系映射矩阵
    len_add0 = length(C_add0);
    C_out = zeros(1,len_add0);
    Couti = zeros(1,N); % 初始化单个输出块
    for m=1:len_add0/N    % 遍历每一块
        % 获取单个块
        Ci = C_add0(1,(1:N)+(m-1)*N);
        % 进行映射
        for i=1:N
            Couti(1,s(i)) = Ci(i);
        end
        % 输出
        C_out(1,(1:N)+N*(m-1)) = Couti;
    end

end
%本程序实现随机去交织
%function C_deIL = de_rand_IL(C_IL,s)
%输入参数:
%   随机交织编码序列C_IL
%   随机映射关系s
%输出参数:
%   去随机交织后的序列C_deIL
%鲁棒性缺陷:未考虑输入长度非N的整数倍的情况
function C_deIL = de_rand_IL(C_IL,s)
    len = length(C_IL);
    N = length(s);
    
    % 根据映射关系恢复原矩阵
    C_deIL = zeros(1,len);
    C_deILi = zeros(1,N);    % 初始化单块输出序列
    for m=1:len/N
        % 获取本块序列
        C_ILi = C_IL(1,(1:N)+(m-1)*N);
        for i=1:N    % 遍历单块中每一个元素
            C_deILi(1,i) = C_ILi(1,s(i));
        end
        C_deIL(1,(1:N)+(m-1)*N) = C_deILi;
    end

end

运行结果如下:
在这里插入图片描述

三、级联码的编译码

下面来探究一下三种交织方式对于级联码的影响。规定内外编码如下:
在这里插入图片描述还是AWGN信道、BPSK调制。主函数调用的子函数有“hamming”、“ham_decode”、“BPSK_AWGN”、“conv_encode”(这四个在实验七),子函数“conv_decode”是老师给的就不放了,以及在 “二、交织编译码” 提到的三种交织方式的编码与译码函数(一共6个)。主函数如下:

%% 实验七-交织器分别采用(74)分组交织、(47)卷积交织和长度N=28的随机交织的BER-SNR对比
%其他条件:AWGN信道、BPSK调制、外编码(7,4)汉明码、内编码(2,1,3)卷积码
clear all
clc
%% 主函数
N = input('每个信噪比条件下要发送多少个样本点:');
snrdB_min = 0; snrdB_max = 4;% SNR范围是0-4dB
snrdB = snrdB_min:1:snrdB_max;
sym_initial = round(rand(1,N));% 生成原始序列

fprintf('原序列:%s\n',num2str(sym_initial));

% 外编码器:(7,4)汉明码
G_ham = [1 0 0 0 1 1 0;...
         0 1 0 0 1 0 1;...
         0 0 1 0 0 1 1;...
         0 0 0 1 1 1 1];    % 生成矩阵G
[k1,n1] = size(G_ham);
C_ham = ham_encode(sym_initial,G_ham);
[groups1,~] = size(C_ham);
A = reshape(C_ham.',[1,length(C_ham(:))]);% 转换成码流

% 交织方式一:(74)分组交织
m=7;n=4;
B1 = pock_IL(A,m,n);
% 交织方式二:(47)卷积交织
B=4;M=7;
B2 = conv_IL(A,B,M);
% 交织方式三:长度为28的随机交织
N_inter = 28;
[B3,s] = rand_IL(A,N_inter);

% 内编码器:(2,1,3)卷积码
G_conv = [1,0,1;1,1,1];
C1 = conv_encode(B1,G_conv);
C2 = conv_encode(B2,G_conv);
C3 = conv_encode(B3,G_conv);

% 三种序列都在AWGN信道下,进行BPSK调制解调,得到接收端接收序列
[D1,~] = BPSK_AWGN(C1,snrdB);
[D2,~] = BPSK_AWGN(C2,snrdB);
[D3,~] = BPSK_AWGN(C3,snrdB);

% 交织方式一的解调端
errors1 = zeros(1,length(snrdB));  % 预分配错误内存
for i=1:length(snrdB)
    % 内译码器:(213)卷积码解码
    E1 = conv_decode(G_conv,1,D1(i,:));
    
    % 去交织:(74)分组交织
    F1 = de_pock_IL(E1,m,n);
    
    % 外译码器:(74)汉明译码
    % 先将序列补0成n1的整数倍
    len_F1 = length(F1);
    num0 = mod(n1-mod(len_F1,n1),n1);
    F1 = [F1,zeros(1,num0)];
    F1_re = reshape(F1,n1,length(F1)/n1).';% 串并转换
    sym_re1 = ham_decode(F1_re,G_ham);% 解码
    sym_recover1 = reshape(sym_re1.',length(sym_re1(:)),1).';% 并串转换
    
    % 计算该信噪比下的BER
    len_sym = length(sym_initial);
    % 因为上述编码方式会补零,所以仅按照原始序列的长度取出输出序列进行比较
    errors1(i) = sum(mod(sym_recover1(1:len_sym)+sym_initial,2));
end
BER1 = errors1/N; % 得到BER

fprintf('序列一:%s\n',num2str(sym_recover1));

% 交织方式二的解调端
errors2 = zeros(1,length(snrdB));  % 预分配错误内存
for i=1:length(snrdB)
    % 内译码器:(213)卷积码解码
    E2 = conv_decode(G_conv,1,D2(i,:));
    
    % 去交织:(47)卷积交织
    F2 = de_conv_IL(E2,B,M);
    
    % 外译码器:(74)汉明译码
    % 先将序列补0成n1的整数倍
    len_F2 = length(F2);
    num0 = mod(n1-mod(len_F2,n1),n1);
    F2 = [F2,zeros(1,num0)];
    F2_re = reshape(F2,n1,length(F2)/n1).';% 串并转换
    sym_re2 = ham_decode(F2_re,G_ham);% 解码
    sym_recover2 = reshape(sym_re2.',length(sym_re2(:)),1).';% 并串转换
    
    % 计算该信噪比下的BER\
    len_sym = length(sym_initial);
    errors2(i) = sum(mod(sym_recover2(1:len_sym)+sym_initial,2));
end
BER2 = errors2/N; % 得到BER

fprintf('序列二:%s\n',num2str(sym_recover2));

% 交织方式三的解调端
errors3 = zeros(1,length(snrdB));  % 预分配错误内存
for i=1:length(snrdB)
    % 内译码器:(213)卷积码解码
    E3 = conv_decode(G_conv,1,D3(i,:));
    
    % 去交织:长度为28的随机交织
    F3 = de_rand_IL(E3,s);
    
    % 外译码器:(74)汉明译码
    % 先将序列补0成n1的整数倍
    len_F3 = length(F3);
    num0 = mod(n1-mod(len_F3,n1),n1);
    F3 = [F3,zeros(1,num0)];
    F3_re = reshape(F3,n1,length(F3)/n1).';% 串并转换
    sym_re3 = ham_decode(F3_re,G_ham);% 解码
    sym_recover3 = reshape(sym_re3.',length(sym_re3(:)),1).';% 并串转换
    
    % 计算该信噪比下的BER
    len_sym = length(sym_initial);
    errors3(i) = sum(mod(sym_recover3(1:len_sym)+sym_initial,2));
end
BER3 = errors3/N; % 得到BER

fprintf('序列三:%s\n',num2str(sym_recover3));

% 画出三种方案的BER-SNR曲线
figure
semilogy(snrdB,BER1,'*-',snrdB,BER2,'o-',snrdB,BER3,'-x');
grid on;
xlabel('信噪比 SNR / dB');ylabel('误码率 BER');
title(['发送的信息序列长度为 ',num2str(N)]);
legend('(7,4)分组交织','(4,7)卷积交织','长度N=28的随机交织');
% 直接显示数值
disp(['(7,4)分组交织',num2str(BER1)]);
disp(['(4,7)卷积交织',num2str(BER2)]);
disp(['长度N=28的随机交织',num2str(BER3)]);

运行结果如下:
在这里插入图片描述关于原因我也说不出来所以然,有哪位大神知道的话请指点一下。

四、程序自评价

1.串并转换。最后的那个主函数中,汉明解码的前期串并转换在主函数中,改进可以放到子函数中;并且输出的并串转换也是。(老问题了属于是)
2.程序的命名。我把子函数都保存下来发现一个大问题!就是,文件名称好乱啊。可见,按照“分组-交织”、“卷积-交织”、“随机-交织”这样的中文顺序翻译成英文的子函数名称有很大问题。应该像这样命名“交织-编码-分组”、“交织-解码-分组”、“交织-编码-卷积”、“交织-解码-卷积”……下次写工程的时候注意。

代码原创,但因为原理编写参考到了实验课的指导书,假如有什么不对的地方,侵删。

  • 9
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

虎慕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值