在开设了SDR软件无线电课程后,有余力的学生开始尝试开发自己的小通信电台,实现Hello World的无线传输。在实验过程中,一定会遇到纠错的问题。即使是在实验室,理想化的信道也是不存在的。没有纠错的小电台,稍微离开一两米就会发生传输错误。

在通信专业的实验课程里,通常只采用matlab等类似的高级语言进行原理性的测试。但此类高级语言过于顶层,使得学生无法了解算法内部究竟做了什么。此外,基于GUNRadio现有的纠错模块,基本是使用几类固定的编译码类型,且封装的很深。

为了配合学生借助 taskbus进行纯控制台STDIO模块的开发,我们收集了手头的通用纠错算法,便于学生进行开发学习。这里把资源中比较特殊的几个算法介绍一下,准备陆续写几篇短文。

1. 循环冗余纠错的能力极限

这类编码典型包括CRC, BCH等编码。当然,一般认为CRC是没有纠错能力的。但是,当参与校验的信息很少时,CRC就具备了不完备的纠错能力。定性的看,考虑一个多项式构造的校验结构有无纠错能力,就看两个方面:

  1. 纠错比特数能表达多少种错误类型。
  2. 多项式能不能保证图案的唯一性(纪念伟大的数学家伽罗华,建立了近世代数,奠定了图案唯一性的理论基础)。

比如,如果整体码长为N,校验位数为m,则如果 N<2mN < 2^mN<2m则有可能纠出1位错误。前提是采用的多项式是本原的(可类比素数)。在校验位数=4时,码长N必须小于16。因为4比特总共只能表达15种非0图案。类推下去,设最大可纠错的个数是e,则当
∑i=1eCni<2m\sum_{i=1}^{e} C_n^{i} <2^mi=1∑e​Cni​<2m
时,有望纠出e位以内的错误。这种理解相当于模拟出错的过程,假设错1位,则从n个位置取出1个位置进行翻转,共有Cn1C_n^1Cn1​=n种可能。假设错2位,则从n个位置取出2个进行翻转,共有Cn2=n(n−1)/2C_n^2=n(n-1)/2Cn2​=n(n−1)/2种可能,以此类推。校验的位数要能区分所有的错误图案,因此存在一个最小值,也就是∑i=1eCni\sum_{i=1}^{e} C_n^{i}∑i=1e​Cni​

同时,由于模二计算具备一定的性质,使得错误的图案(出现错误的位置)和校验的结果形成映射,因此在接收方只要通过比对结果,就可知道错误的位置。

2. 字典纠错算法

在计算机不发达的时代,科学家主要研究的是设计一种编码方法,可以通过余数直接求取错误图案。最著名的BCH编码、RS编码,不是单纯因为纠错能力强,而是在于有标准的逆推算法,可以在有限的存储和时间下完成纠错。字典方法在那个时代也是存在的,因为它是最朴素的算法。但是受制于只有1MB内存的286机器,该算法没有实用价值。

2.1 步骤

对当前动辄16GB的内存存储容量而言,借助现代通用计算机的大容量内存,可以轻松实现最为朴素的字典纠错。算法步骤:

  1. 确定基本参数,总长度(被除数长度)、校验多项式长度(除数)。假设出错个数e初始化=1
  2. 做CneC_n^{e}Cne​穷尽,用到了排列组合工具库简化过程。对每个错误位置,执行3-5步。
  3. 产生错误图案。
  4. 计算校验结果,求取余数。
  5. 记录图案:错误位置映射,如果发现重复图案或者字典过大,则结束(到7)。
  6. e=e+1,转2继续。
  7. 保存字典。

2. 2 局限与优势

主要的局限在于产生字典的过程较长。但字典的产生是一次性的,一次产生,多次使用。一旦字典生成,查表的过程很快。

3. 调用例子

int demo_bch()
{using namespace  RC_DICTCODEC;using std::vector;using std::string;//0. 定义编码多项式size_t pins[7] = {10,8,5,4,2,1,0};rc_codec_bch codec(15,5,pins,7);rc_dict<char> dict;//1. 构造字典size_t s = dict.init(&codec);printf ("Dict size = %u\n",s);//2. 提供信息,共5比特,11001char code[15] = {1,1,0,0,1,0,0,0,0,0,0,0,0,0,0};//3. 编码codec.encode(code,code);//4. 模拟传输错误code[3] = 1-code[3];code[7] = 1-code[7];//5. 执行校验char check[15] = {0};codec.chcode(code,check);//6. 查表纠错string errk = codec.hash(check);vector<rc_dict<char>::err_mask > err = dict.err_find( errk);for (size_t i=0;i<err.size();++i){printf("Pos = %d, Add = %d\n",err[i].index,err[i].err);if (err[i].index>=0 && err[i].index<15)code[err[i].index] = codec.mod_m_add(code[err[i].index],err[i].err);}//输出,判断余数是不是0codec.chcode(code,check);printf ("chk code=");for (int i=0;i<15;++i)printf("%d",check[i]);printf ("\n");return 0;
}

4. C语言封装

由于C++语言对其他语言包括python,C#不友好,我们参考这篇文章的方法,提供一个非常通用的C语言接口。

/*** @brief oc_bch_new_codec 分配一个BCH码编译码器* @param n 整个编码后的块长度* @param k 信息长度* @param gindex 非零多项式位置,如10,9,8,6,0* @param len 位置项个数,如 5 个(上面的例子)* @param dict_size 字典大小(条)* @return  BCH纠错码编译码器句柄*/
void * oc_bch_new_codec(size_t n, size_t k, const size_t gindex[], size_t len, int dict_size);/*** @brief oc_bch_delete_codec 释放BCH码编译码器 codec* @param codec BCH码编译码器*/
void oc_bch_delete_codec(void * codec);/*** @brief oc_bch_initcodec 首次使用前,要创建字典进行初始化。* @param codec BCH纠错码编译码器* @param status  指定余数初态(默认是全0)* @param bigendian gindex的大小端。* @return*/
int oc_bch_initcodec(void * codec,const char status[/*n-k*/],int bigendian);/*** @brief oc_bch_encode 对字节型的信息data进行纠错编码,存储到code中。* @param codec BCH纠错码编译码器* @param data 信息data* @param code 编码code* @return 0表示成功*/
int oc_bch_encode(void * codec,const char data[/*k*/], char code[/*n*/]) ;/*** @brief oc_bch_decode 对字节型的数据code进行纠错译码* @param codec BCH纠错码编译码器* @param code 待纠错的数据* @param result 纠错后的数据存储到result中* @param checkedCode 可选择对result进行校验,输出到checkedCode里。可以传入nullptr* @return*/
int oc_bch_decode(void * codec,const char code[/*n*/], char result[/*n*/], char * checkedCode) ;

5. GUI测试界面

如果有Qt,则可以编译并使用ocgui测试:

可以发现,经过纠错后,图片可以被正确打开。

6. 代码链接

相关代码参考

https://gitcode.net/coloreaglestdio/open_codec

可用于SDR的C语言纠错编码通用算法收集(1)-朴素字典查表BCH纠错相关推荐

  1. 可用于SDR的C语言纠错编码通用算法收集(3)-卷积码与Viterbi译码

    为了配合学生借助 taskbus进行纯控制台STDIO模块的开发,我们收集了手头的通用纠错算法,便于学生进行开发学习.今天介绍卷积码以及维特比译码算法.在我自己以前学习<通信原理>的时候, ...

  2. 可用于SDR的C语言纠错编码通用算法收集(4)-LDPC低密度奇偶校验码

    为了配合学生借助 taskbus进行纯控制台STDIO模块的开发,我们收集了手头的通用纠错算法,便于学生进行开发学习.今天介绍LDPC编码. 1. 低密度奇偶校验编码LDPC 低密度奇偶校验码LDPC ...

  3. 算法训练+乘法表c语言,[蓝桥杯][算法提高VIP]输出九九乘法表 (C语言代码)

    解题思路:Nine那些直接复制输出 注意事项: 参考代码: #include int main() { int i,j; printf("  Nine-by-nine Multiplicat ...

  4. c语言如何热敏电阻转成温度,NTC热敏电阻查表程序如何转换成温度显示?

    昨天弄一整天,把数据表更新下,测试发现在用烙铁靠近NTC时,温度最高只有70多度就上不去了,测了NTC输入电压是有变化的,但显示基本没什么变化,将上偏电阻原5.1K改为2.4K后,还是这样子.不知是那 ...

  5. 一步一步写算法(之通用算法的编写)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 前面我们写过各种各样的算法,什么排序.查找.二叉树.队列.堆栈等等.但是我们在编写这些代码的时 ...

  6. c语言系统的通用数据结构,(转载)C语言实现通用数据结构的高效设计

    (转载)C语言实现通用数据结构的高效设计 [复制链接] 使用宏替代模板的方案 最近在阅读一个开源的C++代码,里面用到了大量的STL里面的东西.也许是自己一直用C而很少用C++来实现算法的原因,STL ...

  7. 基于 Ruby 谈谈——程序设计语言的通用框架

    基于 Ruby GScript 谈谈--程序设计语言的通用框架 目录 基于 Ruby GScript 谈谈--程序设计语言的通用框架 一.架构思维导图 1.Ruby GScript 介绍 2.实践: ...

  8. ICCV 2021| GRF: 用于三维表征和渲染的通用神经辐射场(已开源)

    作者丨Bo Yang@知乎 来源丨https://zhuanlan.zhihu.com/p/399867075 编辑丨3D视觉工坊 论文链接: https://arxiv.org/abs/2010.0 ...

  9. C语言实现通用链表初步(一)

    注意:本文讨论的是无头单向非循环链表. 假设不采用Linux内核链表的思路,怎样用C语言实现通用链表呢? 一种常用的做法是: typedef int element_t; struct node_in ...

最新文章

  1. go语言的defer语句
  2. linux 搭建Tomcat
  3. 基于hexo搭建个人免费博客——基本设置和了解
  4. EIGRP Metric计算
  5. PAT (Advanced Level) 1140~1143:1140模拟 1141模拟 1142暴力 1143 BST+LCA
  6. LeetCode 74. 搜索二维矩阵(二分查找)
  7. 云函数查询_速览 | 京东云5月重要产品与功能更新
  8. Dataguard学习笔记
  9. AMD因虚假宣传遭集体诉讼 向消费者赔偿1210万美元
  10. AI助特朗普当选?FB史上最大数据滥用曝光,牵出ACL终身奖得主
  11. Python学习入门基础教程(learning Python)--5.7 Python文件数据记录存储与处理
  12. python编程例子-python网络编程实例简析
  13. mysql常见字符串处理函数
  14. Python + vs +Opencv
  15. 苹果6s上市时间_苹果6s主板坏了的症状,苹果6s换主板多少钱
  16. 第5章 软件质量标准概述
  17. 精易论坛多线程培训第二期
  18. 4. 查询表orders——检索所有订单订购物品的总数
  19. 六轴机械臂下位机(arduino)+上位机(ROS+Moveit)---(一)机械臂硬件
  20. 用计算机唱歌弹奏china,新目标英语专题练习:句型转换(附答案)

热门文章

  1. 使用canvas对图片进行裁切
  2. mysql 实例和数据库名_oracle 实例名和服务名以及数据库名区别
  3. Win10隐藏状态栏图标的方法
  4. 解决windows 2003 sp1下安装arcsde 9.0 for sql server 2000 sp4概要方案
  5. 第四章、面向对象(2)
  6. 英语表达的收集类游戏
  7. python画图颜色填充_【Python】Matplotlib画图(十一)——箱线图
  8. 分享一款好用的微信相册小程序《群相册大师》
  9. 计算机怎么一键返回桌面,回到桌面的快捷键是啥_快速桌面快捷键怎么操作-win7之家...
  10. 华为智慧办公全系列终端介绍