1. 程式人生 > >從零開始的鐳射通訊(第1章 協議棧)——4、原始資料編解碼

從零開始的鐳射通訊(第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__