ecc8.c
2.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include "ecc256.h"
void
ecc8_calculate(const unsigned char buf[8], unsigned char ecc[2]) {
int i;
unsigned char x1, x2, a0, a1, b, e0, e1;
e1 = x1 = x2 = 0;
for(i = 0; i < 8; i++) {
unsigned char z = buf[i], cp0, cp1, cp2, cp3, cp4, cp5;
cp0 = (z&1) ^ ((z>>2)&1) ^ ((z>>4)&1) ^ ((z>>6)&1); /* xx0 */
cp1 = ((z>>1)&1) ^ ((z>>3)&1) ^ ((z>>5)&1) ^ ((z>>7)&1); /* xx1 */
cp2 = (z&1) ^ ((z>>1)&1) ^ ((z>>4)&1) ^ ((z>>5)&1); /* x0x */
cp3 = ((z>>2)&1) ^ ((z>>3)&1) ^ ((z>>6)&1) ^ ((z>>7)&1); /* x1x */
cp4 = (z&1) ^ ((z>>1)&1) ^ ((z>>2)&1) ^ ((z>>3)&1); /* 0xx */
cp5 = ((z>>4)&1) ^ ((z>>5)&1) ^ ((z>>6)&1) ^ ((z>>7)&1); /* 1xx */
e1 ^= cp0|(cp1<<1)|(cp2<<2)|(cp3<<3)|(cp4<<4)|(cp5<<6); /* column parity */
if (cp4^cp5) { /* odd byte parity */
x1 ^= ~i;
x2 ^= i;
}
}
a1 = b = 0x80; a0 = 0x8;
e0 = 0;
for(i = 0; i < 4; i++) { /* compute ecc[0] */
if (x2 & a0) e0 |= b; /* line parity 7, 5, 3, 1 */
b >>= 1;
if (x1 & a0) e0 |= b; /* line parity 6, 4, 2, 0 */
a0 >>= 1; a1 >>= 1; b >>= 1;
}
ecc[0] = ~e0; /* lp7..lp0 */
ecc[1] = ~(e1 << 2); /* cp5..cp0 0 0 */
}
int
ecc8_correct(unsigned char buf[8], unsigned char read_ecc[2], const unsigned char calc_ecc[2]) {
unsigned char a, b, c, d, x0, x1;
x0 = calc_ecc[0] ^ read_ecc[0];
x1 = calc_ecc[1] ^ read_ecc[1];
if ((x0 | x1) == 0) /* No errors */
return ECC_ERROR_NONE;
a = (x0 ^ (x0 >> 1)) & 0x55;
b = (x1 ^ (x1 >> 1)) & 0x54;
/* Check for and correct single bit error in the data */
if (a == 0x55 && b == 0x54) {
unsigned char i, address = 0, bit = 0;
a = c = 0x8; d = 0x4;
for (i = 0; i < 4; i++) { /* compute bit address */
if (x0 & c) address |= a;
if (x1 & c) bit |= d;
a >>= 1; d >>= 1;
c >>= 2;
}
buf[address] ^= 1 << bit;
return ECC_ERROR_CORRECTED;
} else {
/* count bits */
c = 0;
while (x0 | x1) {
c += x0 & 1;
c += x1 & 1;
x0 >>= 1;
x1 >>= 1;
}
if (c == 1) { read_ecc[0] = calc_ecc[0]; read_ecc[1] = calc_ecc[1]; }
/* Error in the ECC code : Uncorrectable error */
return (c == 1) ? ECC_ERROR_ECC : ECC_ERROR_UNCORRECTABLE;
}
}