-
Notifications
You must be signed in to change notification settings - Fork 0
/
crc.h
165 lines (140 loc) · 3.85 KB
/
crc.h
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#pragma once
#include "Arduino.h"
template<uint16_t polynomial, bool reverse = false, uint16_t initialValue = 0xFFFF>
class CRC16 {
public:
CRC16();
void clear();
uint16_t update(uint8_t value);
uint16_t update(const char *string);
uint16_t update(const uint8_t *data, uint16_t length);
static void makeTable();
private:
uint16_t getRemainder(uint8_t dividend);
uint16_t remainder;
static uint16_t crcTable[256];
static bool tableReady;
};
template<uint16_t polynomial, bool reverse, uint16_t initialValue>
uint16_t CRC16<polynomial, reverse, initialValue>::crcTable[256];
template<uint16_t polynomial, bool reverse, uint16_t initialValue>
bool CRC16<polynomial, reverse, initialValue>::tableReady = false;
template<uint16_t polynomial, bool reverse, uint16_t initialValue>
CRC16<polynomial, reverse, initialValue>::CRC16()
{
makeTable();
clear();
}
template<uint16_t polynomial, bool reverse, uint16_t initialValue>
void CRC16<polynomial, reverse, initialValue>::clear()
{
remainder = initialValue;
}
template<uint16_t polynomial, bool reverse, uint16_t initialValue>
uint16_t CRC16<polynomial, reverse, initialValue>::getRemainder(uint8_t dividend)
{
uint16_t remainder;
/*
* Start with the dividend followed by zeros.
*/
if (reverse) {
remainder = dividend;
}
else {
remainder = dividend << 8;
}
/*
* Perform modulo-2 division, a bit at a time.
*/
for (uint8_t bit = 8; bit > 0; --bit)
{
/*
* Try to divide the current data bit.
*/
if (reverse) {
if (remainder & 0x0001)
{
remainder = (remainder >> 1) ^ polynomial;
}
else
{
remainder = (remainder >> 1);
}
}
else {
if (remainder & 0x8000)
{
remainder = (remainder << 1) ^ polynomial;
}
else
{
remainder = (remainder << 1);
}
}
}
return remainder;
}
template<uint16_t polynomial, bool reverse, uint16_t initialValue>
void CRC16<polynomial, reverse, initialValue>::makeTable(void)
{
if (tableReady) return;
uint16_t remainder;
/*
* Compute the remainder of each possible dividend.
*/
for (uint16_t dividend = 0; dividend < 256; ++dividend)
{
/*
* Store the result into the table.
*/
//crcTable[dividend] = getRemainder(dividend);
}
tableReady = true;
}
template<uint16_t polynomial, bool reverse, uint16_t initialValue>
uint16_t CRC16<polynomial, reverse, initialValue>::update(uint8_t value)
{
/*
* Divide the message by the polynomial, a byte at a time.
*/
if (reverse) {
uint8_t data = value ^ remainder;
//remainder = crcTable[data] ^ (remainder >> 8);
remainder = getRemainder(data) ^ (remainder >> 8);
}
else {
uint8_t data = value ^ (remainder >> 8);
//remainder = crcTable[data] ^ (remainder << 8);
remainder = getRemainder(data) ^ (remainder << 8);
}
/*
* The final remainder is the CRC.
*/
return remainder;
}
template<uint16_t polynomial, bool reverse, uint16_t initialValue>
uint16_t CRC16<polynomial, reverse, initialValue>::update(const char *string)
{
if (!string) return remainder;
while (*string) {
update(*string);
string++;
}
return remainder;
}
template<uint16_t polynomial, bool reverse, uint16_t initialValue>
uint16_t CRC16<polynomial, reverse, initialValue>::update(const uint8_t *data, uint16_t length)
{
//Serial.print("CRC: ");
while (length > 0) {
//Serial.print((char)*data);
update(*data);
data++;
length--;
}
//Serial.print(" = ");
//Serial.print(remainder, HEX);
//Serial.println();
return remainder;
}
typedef CRC16<0x1021, false, 0xFFFF> CRC16_CCITT;