信道编码:MATLAB使用卷积编译码函数

信道编码:MATLAB 使用Conv函数

1. 相关函数

在进行卷积编码的过程中,使用的函数是convenc()函数和vitdec()函数,同时需要poly2trellis()函数。

1.1 poly2trellis()函数

先看poly2trellis()函数,用来生成卷积编码所需要的网表。

trellis = poly2trellis(ConstraintLength,CodeGenerator)

这个函数相当于定义了编码器中寄存器的结构,一般来说,在查看卷积编码的相关资料中都是类似于(2,1,3)这种结构,但是这这个函数只需要两个参数:

  • ConstraintLength参数代表约束长度
  • CodeGenerator 代码生成器,指定为八进制数的KN矩阵、多项式字符向量的KN单元阵列或KN字符串阵列。CodeGenerator为编码器的K个输入比特流中的每一个指定N个输出连接。

通俗理解这两个参数的含义和作用,首先约束长度决定了再译码时候的回溯深度的大小,根据不同的编码速率有不同的关系,技术文档中对此有介绍:

信道编码:MATLAB使用卷积编译码函数_第1张图片

根据设定的n,k,和L值来确定,如对于(2,1,3)结构类型的卷积编码器,其中rate = k/n = 1/2,对应第一种计算方式,那么回溯深度为5*(L-1),结果为10,在进行译码的时候利用这个值对齐或者截断,这个在下面使用过程中会有。

回到函数本身,如设计(2,1,7)类型的编码器,可以用:

L = 7;
trellis = poly2trellis(L,[171 133]);

其中的第二个参数是8进制数据的表现形式,对应二进制为[111_1111, 101_1011]。可以理解为进入1bit数据,输出2bit数据,所以这个是2维的,同时这个7bit每一位代表寄存器的抽头,可以根据这个画出编码器的连接形式。

有了这些概念就可以使用这个函数了。

1.2 convenc()函数

再看convenc()函数

codedout = convenc(msg,trellis)
codedout = convenc(msg,trellis,puncpat)

简单使用卷积编码就用这个第1种调用方式就可以了,其中

  • msg参数是需要编码的信息,这个需要输入0,1二进制数据。
  • trellis参数就是上面函数生成的结果,传输到这里。

在使用时,需要注意的是 msg数据的长度要是k的整数倍,同时利用上面的约束长度,计算回溯深度,利用回溯深度在信息后面添加0

1.3 vitdec()函数

最后看译码函数。

decodedout = vitdec(codedin,trellis,tbdepth,opmode,dectype)
decodedout = vitdec(codedin,trellis,tbdepth,opmode,'soft',nsdec)
decodedout = vitdec(codedin,trellis,tbdepth,opmode,dectype,puncpat)

译码函数的参数相对校多,主要是需要设置模式:

  • codedin参数是需要译码的结果,模式选择硬判决的时候必须输入是整数,模式选择软判决的时候可以输入小数。
  • trellis参数也编码函数的一致。
  • tbdepth这个参数参数就是回溯深度,前面利用约束长度计算的结果。
  • opmode 这个参数有三个不同的选项,分别为cont,termtrunc
  • dectype参数用来设置是硬解码hard还是软解码soft,硬解码输入的数据都是01,软解码可以说输入小数。

有一点需要注意的是,对于termtrunk模式,回溯深度tbdepth必须是一个正整数,并且小于或等于输入编码中的输入符号数,说白了就是在编码前的信息msg长度就得大于等于回溯深度,要不然不够译码的。

这三个参数的差别,term模式下没有延时,就是译码的第一个数据就是编码的第一个数据。trunc参数也没有延时,cont参数有延时,是回溯深度。还有差别就是连续编码的区别。

下面用程序看具体的区别。

2.使用方法

利用(2,1,7)结构的形式进行卷积编译码,如下是测试代码,首先选择conthard模式。

close all;
clear;
clc;

msg_source = [randi([0 1],1,50),zeros([1,30])];  % 一共10e4个点 
n = 2;
k = 1;
rate = k/n; % rate为 1/2
L = 7;
tblen = 5*(L-1); % 回溯深度
trellis = poly2trellis(L,[171 133]);

code_data = convenc(msg_source,trellis);

d = vitdec(code_data,trellis,tblen,'cont','hard');

figure(1);
stairs(msg_source(1:end-30),':*r');
hold on;
stairs(d(31:end),':+b');
ylim([-0.1,1.1]);
grid on;
legend('原始信息','恢复信息');

得到的实验结果为:

当译码函数在使用term模式的时候

close all;
clear;
clc;
msg_source = [randi([0 1],1,50),zeros([1,30])];  % 一共10e4个点 
% msg_source2 = [randi([0 1],1,50),zeros([1,30])];  % 一共10e4个点
n = 2;
k = 1;
rate = k/n; % rate为 1/2
L = 7;
tblen = 5*(L-1); % 回溯深度
trellis = poly2trellis(L,[171 133]);

code_data = convenc(msg_source,trellis);

d = vitdec(code_data,trellis,tblen,'term','hard');

figure(1);
stairs(msg_source(1:end),':*r');
hold on;
stairs(d(1:end),':+b');
ylim([-0.1,1.1]);
grid on;
legend('原始信息','恢复信息');

此时的到的结果为:

从上图中可以看出来,译码之后的信息直接从第一位开始,不需要利用回溯深度来截断之后对比数据,但是这种模式适用的情况是需要编码的信息后面存在足够的多的0数据才可以,当把上一段的代码中的原始数据msg_source后面的30个0,改为20个1时

msg_source = [randi([0 1],1,50),ones([1,30])];

得到的试验结果为:

可以发现虽然译码的结果可以从与原始数据从第1位对齐,但是最后的数据会出现错误。

在测试连续编码的情况:对两段信息分别编码,然后把编码后的信息拼接在一起进行解码,采用的模式为trunchard,程序代码如下:

close all;
clear;
clc;

msg_source1 = [randi([0 1],1,50)];  % 一共10e4个点 
msg_source2 = [randi([0 1],1,50),zeros([1,30])];  % 一共10e4个点 
msg_source = [msg_source1,msg_source2];
n = 2;
k = 1;
rate = k/n; % rate为 1/2
L = 7;
tblen = 5*(L-1); % 回溯深度
trellis = poly2trellis(L,[171 133]);

code_data1 = convenc(msg_source1,trellis);
code_data2 = convenc(msg_source2,trellis);

code_data = [code_data1, code_data2];

d = vitdec(code_data,trellis,tblen,'trunc','hard');

figure(1);
stairs(msg_source(1:end),':*r');
hold on;
stairs(d(1:end),':+b');
ylim([-0.1,1.1]);
grid on;
legend('原始信息','恢复信息');

得到的结果为:

信道编码:MATLAB使用卷积编译码函数_第2张图片

从结果中可以看出来译码是存在错误的。

可以对上面的msg_source1进行更改,改为

msg_source1 = [randi([0 1],1,50),zeros([1,30])];

在后面添加回溯深度个0,再次运行,可以得到结果

信道编码:MATLAB使用卷积编译码函数_第3张图片

可以得到正确的结果,总结起来方便操作就是在信息的末尾添加回溯深度个0

你可能感兴趣的:(通信系统,matlab,信道编码,卷积编码,通信系统)