Bluetooth Low Energy for Smart Plug
Dependencies: BLE_API mbed nRF51822
Fork of SmartPlugBLE by
crc2.cpp@4:721ae30c92f8, 2015-07-14 (annotated)
- Committer:
- Slepnir
- Date:
- Tue Jul 14 10:10:19 2015 +0000
- Revision:
- 4:721ae30c92f8
- Parent:
- 3:aaa92c61931a
For debugging
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Slepnir | 3:aaa92c61931a | 1 | |
Slepnir | 3:aaa92c61931a | 2 | |
Slepnir | 3:aaa92c61931a | 3 | #include "crc2.h" |
Slepnir | 3:aaa92c61931a | 4 | |
Slepnir | 3:aaa92c61931a | 5 | |
Slepnir | 3:aaa92c61931a | 6 | /* |
Slepnir | 3:aaa92c61931a | 7 | * Derive parameters from the standard-specific parameters in crc.h. |
Slepnir | 3:aaa92c61931a | 8 | */ |
Slepnir | 3:aaa92c61931a | 9 | #define WIDTH (8 * sizeof(crc)) |
Slepnir | 3:aaa92c61931a | 10 | #define TOPBIT (1 << (WIDTH - 1)) |
Slepnir | 3:aaa92c61931a | 11 | |
Slepnir | 3:aaa92c61931a | 12 | #if (REFLECT_DATA == TRUE) |
Slepnir | 3:aaa92c61931a | 13 | #undef REFLECT_DATA |
Slepnir | 3:aaa92c61931a | 14 | #define REFLECT_DATA(X) ((unsigned char) reflect((X), 8)) |
Slepnir | 3:aaa92c61931a | 15 | #else |
Slepnir | 3:aaa92c61931a | 16 | #undef REFLECT_DATA |
Slepnir | 3:aaa92c61931a | 17 | #define REFLECT_DATA(X) (X) |
Slepnir | 3:aaa92c61931a | 18 | #endif |
Slepnir | 3:aaa92c61931a | 19 | |
Slepnir | 3:aaa92c61931a | 20 | #if (REFLECT_REMAINDER == TRUE) |
Slepnir | 3:aaa92c61931a | 21 | #undef REFLECT_REMAINDER |
Slepnir | 3:aaa92c61931a | 22 | #define REFLECT_REMAINDER(X) ((crc) reflect((X), WIDTH)) |
Slepnir | 3:aaa92c61931a | 23 | #else |
Slepnir | 3:aaa92c61931a | 24 | #undef REFLECT_REMAINDER |
Slepnir | 3:aaa92c61931a | 25 | #define REFLECT_REMAINDER(X) (X) |
Slepnir | 3:aaa92c61931a | 26 | #endif |
Slepnir | 3:aaa92c61931a | 27 | |
Slepnir | 3:aaa92c61931a | 28 | |
Slepnir | 3:aaa92c61931a | 29 | /********************************************************************* |
Slepnir | 3:aaa92c61931a | 30 | * |
Slepnir | 3:aaa92c61931a | 31 | * Function: reflect() |
Slepnir | 3:aaa92c61931a | 32 | * |
Slepnir | 3:aaa92c61931a | 33 | * Description: Reorder the bits of a binary sequence, by reflecting |
Slepnir | 3:aaa92c61931a | 34 | * them about the middle position. |
Slepnir | 3:aaa92c61931a | 35 | * |
Slepnir | 3:aaa92c61931a | 36 | * Notes: No checking is done that nBits <= 32. |
Slepnir | 3:aaa92c61931a | 37 | * |
Slepnir | 3:aaa92c61931a | 38 | * Returns: The reflection of the original data. |
Slepnir | 3:aaa92c61931a | 39 | * |
Slepnir | 3:aaa92c61931a | 40 | *********************************************************************/ |
Slepnir | 3:aaa92c61931a | 41 | static unsigned long |
Slepnir | 3:aaa92c61931a | 42 | reflect(unsigned long data, unsigned char nBits) |
Slepnir | 3:aaa92c61931a | 43 | { |
Slepnir | 3:aaa92c61931a | 44 | unsigned long reflection = 0x00000000; |
Slepnir | 3:aaa92c61931a | 45 | unsigned char bit; |
Slepnir | 3:aaa92c61931a | 46 | |
Slepnir | 3:aaa92c61931a | 47 | /* |
Slepnir | 3:aaa92c61931a | 48 | * Reflect the data about the center bit. |
Slepnir | 3:aaa92c61931a | 49 | */ |
Slepnir | 3:aaa92c61931a | 50 | for (bit = 0; bit < nBits; ++bit) |
Slepnir | 3:aaa92c61931a | 51 | { |
Slepnir | 3:aaa92c61931a | 52 | /* |
Slepnir | 3:aaa92c61931a | 53 | * If the LSB bit is set, set the reflection of it. |
Slepnir | 3:aaa92c61931a | 54 | */ |
Slepnir | 3:aaa92c61931a | 55 | if (data & 0x01) |
Slepnir | 3:aaa92c61931a | 56 | { |
Slepnir | 3:aaa92c61931a | 57 | reflection |= (1 << ((nBits - 1) - bit)); |
Slepnir | 3:aaa92c61931a | 58 | } |
Slepnir | 3:aaa92c61931a | 59 | |
Slepnir | 3:aaa92c61931a | 60 | data = (data >> 1); |
Slepnir | 3:aaa92c61931a | 61 | } |
Slepnir | 3:aaa92c61931a | 62 | |
Slepnir | 3:aaa92c61931a | 63 | return (reflection); |
Slepnir | 3:aaa92c61931a | 64 | |
Slepnir | 3:aaa92c61931a | 65 | } /* reflect() */ |
Slepnir | 3:aaa92c61931a | 66 | |
Slepnir | 3:aaa92c61931a | 67 | |
Slepnir | 3:aaa92c61931a | 68 | /********************************************************************* |
Slepnir | 3:aaa92c61931a | 69 | * |
Slepnir | 3:aaa92c61931a | 70 | * Function: crcSlow() |
Slepnir | 3:aaa92c61931a | 71 | * |
Slepnir | 3:aaa92c61931a | 72 | * Description: Compute the CRC of a given message. |
Slepnir | 3:aaa92c61931a | 73 | * |
Slepnir | 3:aaa92c61931a | 74 | * Notes: |
Slepnir | 3:aaa92c61931a | 75 | * |
Slepnir | 3:aaa92c61931a | 76 | * Returns: The CRC of the message. |
Slepnir | 3:aaa92c61931a | 77 | * |
Slepnir | 3:aaa92c61931a | 78 | *********************************************************************/ |
Slepnir | 3:aaa92c61931a | 79 | crc |
Slepnir | 3:aaa92c61931a | 80 | crcSlow(unsigned char const message[], int nBytes) |
Slepnir | 3:aaa92c61931a | 81 | { |
Slepnir | 3:aaa92c61931a | 82 | crc remainder = INITIAL_REMAINDER; |
Slepnir | 3:aaa92c61931a | 83 | int byte; |
Slepnir | 3:aaa92c61931a | 84 | unsigned char bit; |
Slepnir | 3:aaa92c61931a | 85 | |
Slepnir | 3:aaa92c61931a | 86 | |
Slepnir | 3:aaa92c61931a | 87 | /* |
Slepnir | 3:aaa92c61931a | 88 | * Perform modulo-2 division, a byte at a time. |
Slepnir | 3:aaa92c61931a | 89 | */ |
Slepnir | 3:aaa92c61931a | 90 | for (byte = 0; byte < nBytes; ++byte) |
Slepnir | 3:aaa92c61931a | 91 | { |
Slepnir | 3:aaa92c61931a | 92 | /* |
Slepnir | 3:aaa92c61931a | 93 | * Bring the next byte into the remainder. |
Slepnir | 3:aaa92c61931a | 94 | */ |
Slepnir | 3:aaa92c61931a | 95 | remainder ^= (REFLECT_DATA(message[byte]) << (WIDTH - 8)); |
Slepnir | 3:aaa92c61931a | 96 | |
Slepnir | 3:aaa92c61931a | 97 | /* |
Slepnir | 3:aaa92c61931a | 98 | * Perform modulo-2 division, a bit at a time. |
Slepnir | 3:aaa92c61931a | 99 | */ |
Slepnir | 3:aaa92c61931a | 100 | for (bit = 8; bit > 0; --bit) |
Slepnir | 3:aaa92c61931a | 101 | { |
Slepnir | 3:aaa92c61931a | 102 | /* |
Slepnir | 3:aaa92c61931a | 103 | * Try to divide the current data bit. |
Slepnir | 3:aaa92c61931a | 104 | */ |
Slepnir | 3:aaa92c61931a | 105 | if (remainder & TOPBIT) |
Slepnir | 3:aaa92c61931a | 106 | { |
Slepnir | 3:aaa92c61931a | 107 | remainder = (remainder << 1) ^ POLYNOMIAL; |
Slepnir | 3:aaa92c61931a | 108 | } |
Slepnir | 3:aaa92c61931a | 109 | else |
Slepnir | 3:aaa92c61931a | 110 | { |
Slepnir | 3:aaa92c61931a | 111 | remainder = (remainder << 1); |
Slepnir | 3:aaa92c61931a | 112 | } |
Slepnir | 3:aaa92c61931a | 113 | } |
Slepnir | 3:aaa92c61931a | 114 | } |
Slepnir | 3:aaa92c61931a | 115 | |
Slepnir | 3:aaa92c61931a | 116 | /* |
Slepnir | 3:aaa92c61931a | 117 | * The final remainder is the CRC result. |
Slepnir | 3:aaa92c61931a | 118 | */ |
Slepnir | 3:aaa92c61931a | 119 | return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE); |
Slepnir | 3:aaa92c61931a | 120 | |
Slepnir | 3:aaa92c61931a | 121 | } /* crcSlow() */ |
Slepnir | 3:aaa92c61931a | 122 | |
Slepnir | 3:aaa92c61931a | 123 | |
Slepnir | 3:aaa92c61931a | 124 | crc crcTable[256]; |
Slepnir | 3:aaa92c61931a | 125 | |
Slepnir | 3:aaa92c61931a | 126 | |
Slepnir | 3:aaa92c61931a | 127 | /********************************************************************* |
Slepnir | 3:aaa92c61931a | 128 | * |
Slepnir | 3:aaa92c61931a | 129 | * Function: crcInit() |
Slepnir | 3:aaa92c61931a | 130 | * |
Slepnir | 3:aaa92c61931a | 131 | * Description: Populate the partial CRC lookup table. |
Slepnir | 3:aaa92c61931a | 132 | * |
Slepnir | 3:aaa92c61931a | 133 | * Notes: This function must be rerun any time the CRC standard |
Slepnir | 3:aaa92c61931a | 134 | * is changed. If desired, it can be run "offline" and |
Slepnir | 3:aaa92c61931a | 135 | * the table results stored in an embedded system's ROM. |
Slepnir | 3:aaa92c61931a | 136 | * |
Slepnir | 3:aaa92c61931a | 137 | * Returns: None defined. |
Slepnir | 3:aaa92c61931a | 138 | * |
Slepnir | 3:aaa92c61931a | 139 | *********************************************************************/ |
Slepnir | 3:aaa92c61931a | 140 | void |
Slepnir | 3:aaa92c61931a | 141 | crcInit() |
Slepnir | 3:aaa92c61931a | 142 | { |
Slepnir | 3:aaa92c61931a | 143 | crc remainder; |
Slepnir | 3:aaa92c61931a | 144 | int dividend; |
Slepnir | 3:aaa92c61931a | 145 | unsigned char bit; |
Slepnir | 3:aaa92c61931a | 146 | |
Slepnir | 3:aaa92c61931a | 147 | |
Slepnir | 3:aaa92c61931a | 148 | /* |
Slepnir | 3:aaa92c61931a | 149 | * Compute the remainder of each possible dividend. |
Slepnir | 3:aaa92c61931a | 150 | */ |
Slepnir | 3:aaa92c61931a | 151 | for (dividend = 0; dividend < 256; ++dividend) |
Slepnir | 3:aaa92c61931a | 152 | { |
Slepnir | 3:aaa92c61931a | 153 | /* |
Slepnir | 3:aaa92c61931a | 154 | * Start with the dividend followed by zeros. |
Slepnir | 3:aaa92c61931a | 155 | */ |
Slepnir | 3:aaa92c61931a | 156 | remainder = dividend << (WIDTH - 8); |
Slepnir | 3:aaa92c61931a | 157 | |
Slepnir | 3:aaa92c61931a | 158 | /* |
Slepnir | 3:aaa92c61931a | 159 | * Perform modulo-2 division, a bit at a time. |
Slepnir | 3:aaa92c61931a | 160 | */ |
Slepnir | 3:aaa92c61931a | 161 | for (bit = 8; bit > 0; --bit) |
Slepnir | 3:aaa92c61931a | 162 | { |
Slepnir | 3:aaa92c61931a | 163 | /* |
Slepnir | 3:aaa92c61931a | 164 | * Try to divide the current data bit. |
Slepnir | 3:aaa92c61931a | 165 | */ |
Slepnir | 3:aaa92c61931a | 166 | if (remainder & TOPBIT) |
Slepnir | 3:aaa92c61931a | 167 | { |
Slepnir | 3:aaa92c61931a | 168 | remainder = (remainder << 1) ^ POLYNOMIAL; |
Slepnir | 3:aaa92c61931a | 169 | } |
Slepnir | 3:aaa92c61931a | 170 | else |
Slepnir | 3:aaa92c61931a | 171 | { |
Slepnir | 3:aaa92c61931a | 172 | remainder = (remainder << 1); |
Slepnir | 3:aaa92c61931a | 173 | } |
Slepnir | 3:aaa92c61931a | 174 | } |
Slepnir | 3:aaa92c61931a | 175 | |
Slepnir | 3:aaa92c61931a | 176 | /* |
Slepnir | 3:aaa92c61931a | 177 | * Store the result into the table. |
Slepnir | 3:aaa92c61931a | 178 | */ |
Slepnir | 3:aaa92c61931a | 179 | crcTable[dividend] = remainder; |
Slepnir | 3:aaa92c61931a | 180 | } |
Slepnir | 3:aaa92c61931a | 181 | |
Slepnir | 3:aaa92c61931a | 182 | } /* crcInit() */ |
Slepnir | 3:aaa92c61931a | 183 | |
Slepnir | 3:aaa92c61931a | 184 | |
Slepnir | 3:aaa92c61931a | 185 | /********************************************************************* |
Slepnir | 3:aaa92c61931a | 186 | * |
Slepnir | 3:aaa92c61931a | 187 | * Function: crcFast() |
Slepnir | 3:aaa92c61931a | 188 | * |
Slepnir | 3:aaa92c61931a | 189 | * Description: Compute the CRC of a given message. |
Slepnir | 3:aaa92c61931a | 190 | * |
Slepnir | 3:aaa92c61931a | 191 | * Notes: crcInit() must be called first. |
Slepnir | 3:aaa92c61931a | 192 | * |
Slepnir | 3:aaa92c61931a | 193 | * Returns: The CRC of the message. |
Slepnir | 3:aaa92c61931a | 194 | * |
Slepnir | 3:aaa92c61931a | 195 | *********************************************************************/ |
Slepnir | 3:aaa92c61931a | 196 | crc |
Slepnir | 3:aaa92c61931a | 197 | crcFast(unsigned char const message[], int nBytes) |
Slepnir | 3:aaa92c61931a | 198 | { |
Slepnir | 3:aaa92c61931a | 199 | crc remainder = INITIAL_REMAINDER; |
Slepnir | 3:aaa92c61931a | 200 | unsigned char data; |
Slepnir | 3:aaa92c61931a | 201 | int byte; |
Slepnir | 3:aaa92c61931a | 202 | |
Slepnir | 3:aaa92c61931a | 203 | |
Slepnir | 3:aaa92c61931a | 204 | /* |
Slepnir | 3:aaa92c61931a | 205 | * Divide the message by the polynomial, a byte at a time. |
Slepnir | 3:aaa92c61931a | 206 | */ |
Slepnir | 3:aaa92c61931a | 207 | for (byte = 0; byte < nBytes; ++byte) |
Slepnir | 3:aaa92c61931a | 208 | { |
Slepnir | 3:aaa92c61931a | 209 | data = REFLECT_DATA(message[byte]) ^ (remainder >> (WIDTH - 8)); |
Slepnir | 3:aaa92c61931a | 210 | remainder = crcTable[data] ^ (remainder << 8); |
Slepnir | 3:aaa92c61931a | 211 | } |
Slepnir | 3:aaa92c61931a | 212 | |
Slepnir | 3:aaa92c61931a | 213 | /* |
Slepnir | 3:aaa92c61931a | 214 | * The final remainder is the CRC. |
Slepnir | 3:aaa92c61931a | 215 | */ |
Slepnir | 3:aaa92c61931a | 216 | return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE); |
Slepnir | 3:aaa92c61931a | 217 | |
Slepnir | 3:aaa92c61931a | 218 | } /* crcFast() */ |
Slepnir | 3:aaa92c61931a | 219 |