从零开始的激光通讯(第1章 协议栈)——4、原始数据编解码

从零开始的激光通讯(第1章 协议栈)——4、原始数据编解码

github

https://github.com/HaHaHaHaHaGe/mynetstack

简介

在上一小节中,提到过为了防止传输的数据中出现包头,导致误判,我们需要对原始数据做一些修改,以保证数据传输时不会造成误判发生。

解决的办法也很简单,只需要将所有的数据最高位恒为零(因为包头是0xff 0xff 0xff 0xff),这样永远不会出现误判情况了,即使因为外部环境干扰造成的错误。连续出现四个0xff的概率也是微乎其微。更何况后面还会增加crc32的检验

思路就是这样,但是由于实际使用中要考虑很多因素,比如内存分配的问题。效率的问题,所以我做了三种不同的函数,但是由于其中一种只不过是另一种的优化版本,实际上只是两种不同的算法

移动位置法

在这里插入图片描述
将所有数据顺序右移,在最高位X的地方 补零

void trans_8to7b_64bytes(u8 *src, u8 *dst, u32 dst_len)
{
	u32 len = dst_len;
	u32 ss1;
	while (len)
	{
		len -= 8;
		ss1 = len - (((len << 3) + 1) >> 6);

		dst[len] = src[ss1] >> 1;

		dst[len + 1] = ((src[ss1] << 6) & 0x7f) | src[ss1 + 1] >> 2;

		dst[len + 2] = ((src[ss1 + 1] << 5) & 0x7f) | src[ss1 + 2] >> 3;

		dst[len + 3] = ((src[ss1 + 2] << 4) & 0x7f) | src[ss1 + 3] >> 4;

		dst[len + 4] = ((src[ss1 + 3] << 3) & 0x7f) | src[ss1 + 4] >> 5;

		dst[len + 5] = ((src[ss1 + 4] << 2) & 0x7f) | src[ss1 + 5] >> 6;

		dst[len + 6] = ((src[ss1 + 5] << 1) & 0x7f) | src[ss1 + 6] >> 7;

		dst[len + 7] = src[ss1 + 6] & 0x7f;


	}
}

提取最高位法

在这里插入图片描述
将所有数据的最高位单独存储起来后,将其设置为0

注:使用这种方法会额外需要1字节空间(在对赋值操作时只能以64位或32位的方式去操作,但是每次操作只能对7个字节操作,会多出一个字节),并且需要已经初始化好的内存空间(为了不覆盖之前的数据只能采用 或 运算去赋值)

void trans_8to7b_64bytes_fast(u8 *src, u8 *dst, u32 src_len)
{
	u32 len = src_len;
	u32 len_2 = src_len;
	u32 ss1,ss2;
	while (len)
	{
		len -= 7;
		
		ss1 = *(u32*)&src[len] & 0x80808080;
		ss2 = *(u32*)&src[len+4] & 0x00808080;

		dst[len_2] = (ss1 >> 1) |

					(ss1 >> 10) |

					(ss1 >> 19) |

					(ss1 >> 28) |

					(ss2 >> 5) |

					(ss2 >> 14) |

					(ss2 >> 23);

		len_2++;

		*(u64*)&dst[len] |= *(u64*)&src[len] & 0x007f7f7f7f7f7f7f;

	}
}

函数说明

所有函数只针对32位系统进行了优化。对64位的系统没有做过优化,但是实验表明还是会比32位模式快一点点

有关数据编解码的文件在\mynetstack\Source\BasicDataStream\inc 与\mynetstack\Source\BasicDataStream\src 中
名称为 sdata_trans.c 与 sdata_trans.h

注:程序还在更新,以GITHUB为准

///////////////////////////////////////////////////////////////////
//创建时间:2018-12-9
//修改时间:2018-12-9
//创建人员:HaHaHaHaHaGe
//修改人员:HaHaHaHaHaGe
//主要功能:将原始数据进行转化(7bit->8bit)
//或将数据转化为可供硬件底层发送的数据(8bit->7bit)
//
//日志:
//
//2018-12-9
//(从packeg_taken剪切过来,真实修改日期:2018-12-8)
//增加函数trans_8to7b与trans_7to8b
//用于将原始数据进行转化,为了进行封包/拆包操作
//未进行优化,100MB的数据进行一次拆\装 共需要5秒(4GHZ的CPU 2700X)
//更新算法trans_8to7b_64bytes、trans_7to8b_64bytes
//优化后的函数,100MB的数据进行一次拆\装 共需要0.28秒(4GHZ的CPU 2700X)
//
//优化后的函数trans_8to7b_64bytes_fast、trans_7to8b_64bytes_fast
//100MB的数据进行一次拆\装 共需要0.167秒(4GHZ的CPU 2700X)
///////////////////////////////////////////////////////////////////


#ifndef __SDATA_TRANS_H__
#define __SDATA_TRANS_H__
#include "../../Factory/basic_header.h"
#include "../../Factory/inc/basic_function.h"

/*
将8bit数据转化成7bit数据
src:输入的8bit数据
dst:保存7bit数据的位置
dst_len:保存的数组大小
*/
void trans_8to7b(u8 *src, u8 *dst, u32 dst_len);

/*
将7bit数据转化成8bit数据
src:输入的7bit数据
dst:保存8bit数据的位置
src_len:输入的7bit数据大小
*/
void trans_7to8b(u8 *src, u8 *dst, u32 src_len);


/*
将8bit数据转化成7bit数据(快速算法)
src:输入的8bit数据
dst:保存7bit数据的位置
dst_len:输出的7bit数据大小
*/
void trans_8to7b_64bytes(u8 *src, u8 *dst, u32 dst_len);


/*
将7bit数据转化成8bit数据(快速算法)
src:输入的7bit数据
dst:保存8bit数据的位置
src_len:输入的7bit数据大小
*/
void trans_7to8b_64bytes(u8 *src, u8 *dst, u32 src_len);


/*
将8bit数据转化成7bit数据(超快速算法)
dst需要额外1bit空间
src空间需要被初始化为0

src:输入的7bit数据
dst:保存8bit数据的位置
src_len:输入的7bit数据大小
*/
void trans_8to7b_64bytes_fast(u8 *src, u8 *dst, u32 src_len);



/*
将7bit数据转化成8bit数据(超快速算法)
dst需要额外1bit空间
src空间需要被初始化为0

src:输入的7bit数据
dst:保存8bit数据的位置
src_len:输入的7bit数据大小
*/
void trans_7to8b_64bytes_fast(u8 *src, u8 *dst, u32 src_len);
#endif // !__SDATA_TRANS_H__


猜你喜欢

转载自blog.csdn.net/weixin_41738734/article/details/84955812