demo3/demo/hamming.c

109 lines
3.3 KiB
C
Raw Permalink Normal View History

2024-11-30 02:15:30 +00:00
#include "hamming.h"
/**
* @brief 1
* @param byte
* @return 1
*/
static inline int countOnes(unsigned char byte) {
static const unsigned char ones[16] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
return ones[byte & 0x0F] + ones[byte >> 4];
}
/**
* @brief
* @param data
* @param size
* @param parity 3
* @note
* -
* -
*/
void calculateParity(const unsigned char *data, int size, unsigned char *parity) {
// 初始化校验位数组
memset(parity, 0, PARITY_BYTES);
int totalOnes = 0;
// 对每个数据字节
for(int i = 0; i < size; i++) {
unsigned char byte = data[i];
totalOnes += countOnes(byte);
// 对字节中的每一位
for(int j = 0; j < 8; j++) {
if(byte & (1 << j)) {
// 计算该位在整个数据中的位置
int bitPos = i * 8 + j;
// 更新相应的校验位
for(int k = 0; k < 20; k++) {
if(bitPos & (1 << k)) {
if(k < 8)
parity[0] ^= (1 << k);
else if(k < 16)
parity[1] ^= (1 << (k - 8));
else
parity[2] ^= (1 << (k - 16));
}
}
}
}
}
// 添加总体奇偶校验
if(totalOnes % 2) {
parity[2] |= 0x08; // 设置最高位
}
}
/**
* @brief
* @param data
* @param size
* @param parity
* @return
* 0 -
* 1 -
* -1 -
* -2 -
*/
int detectAndCorrect(unsigned char *data, int size, const unsigned char *parity) {
unsigned char currentParity[PARITY_BYTES];
calculateParity(data, size, currentParity);
// printf("parity: %02X %02X %02X\n", parity[2], parity[1], parity[0]);
// printf("currentParity: %02X %02X %02X\n", currentParity[2], currentParity[1], currentParity[0]);
// 计算syndrome
unsigned int syndrome = 0;
syndrome |= (currentParity[0] ^ parity[0]);
syndrome |= (currentParity[1] ^ parity[1]) << 8;
syndrome |= ((currentParity[2] ^ parity[2]) & 0x07) << 16;
// 检查总体奇偶校验
int parityError = ((currentParity[2] ^ parity[2]) & 0x08) ? 1 : 0;
if(syndrome == 0) {
if(parityError) {
return -2; // 检测到多位错误
}
return 0; // 无错误
}
if(!parityError) {
return -1; // 校验位错误syndrome不为0但奇偶校验正确
}
// 单比特错误
int bitPos = syndrome;
int bytePos = bitPos / 8;
int bitInByte = bitPos % 8;
if(bytePos < size) {
data[bytePos] ^= (1 << bitInByte);
// printf("纠正位置:字节 %d位 %d\n", bytePos, bitInByte);
return 1;
}
return -2; // 检测到多位错误
}