tom dunigan / FastCRC

Dependents:   fastCRCperf

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FastCRCsw.cpp Source File

FastCRCsw.cpp

00001 /* FastCRC library code is placed under the MIT license
00002  * Copyright (c) 2014,2015 Frank Bösing
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining
00005  * a copy of this software and associated documentation files (the
00006  * "Software"), to deal in the Software without restriction, including
00007  * without limitation the rights to use, copy, modify, merge, publish,
00008  * distribute, sublicense, and/or sell copies of the Software, and to
00009  * permit persons to whom the Software is furnished to do so, subject to
00010  * the following conditions:
00011  *
00012  * The above copyright notice and this permission notice shall be
00013  * included in all copies or substantial portions of the Software.
00014  *
00015  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00016  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00017  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00018  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
00019  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
00020  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00021  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00022  * SOFTWARE.
00023  */
00024 
00025 //
00026 // Thanks to:
00027 // - Catalogue of parametrised CRC algorithms, CRC RevEng
00028 // http://reveng.sourceforge.net/crc-catalogue/
00029 //
00030 // - Danjel McGougan (CRC-Table-Generator)
00031 //
00032 
00033 
00034 #if !defined(__CORTEX_M4) 
00035 
00036 #include "FastCRC.h"
00037 #include "FastCRC_cpu.h"
00038 #include "FastCRC_tables.h"
00039 
00040 
00041 // ================= 8-BIT CRC ===================
00042 
00043 /** Constructor
00044  */
00045 FastCRC8::FastCRC8(){}
00046 
00047 /** SMBUS CRC
00048  * aka CRC-8
00049  * @param data Pointer to Data
00050  * @param datalen Length of Data
00051  * @return CRC value
00052  */
00053 uint8_t FastCRC8::smbus_upd(const uint8_t *data, uint16_t datalen)
00054 {
00055     uint8_t crc = seed;
00056     if (datalen) do {
00057         crc =  crc_table_smbus[crc ^ *data];
00058         data++;
00059     } while (--datalen);
00060     seed = crc;
00061     return crc;
00062 }
00063 
00064 uint8_t FastCRC8::smbus(const uint8_t *data, const uint16_t datalen)
00065 {
00066   // poly=0x07 init=0x00 refin=false refout=false xorout=0x00 check=0xf4
00067   seed = 0x00;
00068   return smbus_upd(data, datalen);
00069 }
00070 
00071 /** MAXIM 8-Bit CRC
00072  * equivalent to _crc_ibutton_update() in crc16.h from avr_libc
00073  * @param data Pointer to Data
00074  * @param datalen Length of Data
00075  * @return CRC value
00076  */
00077 uint8_t FastCRC8::maxim_upd(const uint8_t *data, uint16_t datalen)
00078 {
00079     uint8_t crc = seed;
00080     if (datalen) do {
00081         crc = crc_table_maxim[crc ^ *data];
00082         data++;
00083     } while (--datalen);
00084     seed = crc;
00085     return crc;
00086 }
00087 uint8_t FastCRC8::maxim(const uint8_t *data, const uint16_t datalen)
00088 {
00089   // poly=0x31 init=0x00 refin=true refout=true xorout=0x00  check=0xa1
00090   seed = 0x00;
00091   return maxim_upd(data, datalen);
00092 }
00093 
00094 // ================= 16-BIT CRC ===================
00095 /** Constructor
00096  */
00097 FastCRC16::FastCRC16(){}
00098 
00099 #define crc_n4(crc, data, table) crc ^= data; \
00100     crc = table[(crc & 0xff) + 0x300] ^     \
00101     table[((crc >> 8) & 0xff) + 0x200] ^    \
00102     table[((data >> 16) & 0xff) + 0x100] ^  \
00103     table[data >> 24];
00104 
00105 /** CCITT
00106  * Alias "false CCITT"
00107  * @param data Pointer to Data
00108  * @param datalen Length of Data
00109  * @return CRC value
00110  */
00111 uint16_t FastCRC16::ccitt_upd(const uint8_t *data, uint16_t len)
00112 {
00113 
00114     uint16_t crc = seed;
00115 
00116     while (((uintptr_t)data & 3) && len) {
00117         crc = (crc >> 8) ^ crc_table_ccitt[(crc & 0xff) ^ *data++];
00118         len--;
00119     }
00120 
00121     while (len >= 16) {
00122         len -= 16;
00123         crc_n4(crc, ((uint32_t *)data)[0], crc_table_ccitt);
00124         crc_n4(crc, ((uint32_t *)data)[1], crc_table_ccitt);
00125         crc_n4(crc, ((uint32_t *)data)[2], crc_table_ccitt);
00126         crc_n4(crc, ((uint32_t *)data)[3], crc_table_ccitt);
00127         data += 16;
00128     }
00129 
00130     while (len--) {
00131         crc = (crc >> 8) ^ crc_table_ccitt[(crc & 0xff) ^ *data++];
00132     }
00133 
00134     crc = REV16(crc);
00135 
00136     seed = crc;
00137     return crc;
00138 }
00139 uint16_t FastCRC16::ccitt(const uint8_t *data,const uint16_t datalen)
00140 {
00141  // poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1
00142   seed = 0xffff;
00143   return ccitt_upd(data, datalen);
00144 }
00145 
00146 /** MCRF4XX
00147  * equivalent to _crc_ccitt_update() in crc16.h from avr_libc
00148  * @param data Pointer to Data
00149  * @param datalen Length of Data
00150  * @return CRC value
00151  */
00152 
00153 uint16_t FastCRC16::mcrf4xx_upd(const uint8_t *data, uint16_t len)
00154 {
00155 
00156     uint16_t crc = seed;
00157 
00158     while (((uintptr_t)data & 3) && len) {
00159         crc = (crc >> 8) ^ crc_table_mcrf4xx[(crc & 0xff) ^ *data++];
00160         len--;
00161     }
00162 
00163     while (len >= 16) {
00164         len -= 16;
00165         crc_n4(crc, ((uint32_t *)data)[0], crc_table_mcrf4xx);
00166         crc_n4(crc, ((uint32_t *)data)[1], crc_table_mcrf4xx);
00167         crc_n4(crc, ((uint32_t *)data)[2], crc_table_mcrf4xx);
00168         crc_n4(crc, ((uint32_t *)data)[3], crc_table_mcrf4xx);
00169         data += 16;
00170     }
00171 
00172     while (len--) {
00173         crc = (crc >> 8) ^ crc_table_mcrf4xx[(crc & 0xff) ^ *data++];
00174     }
00175 
00176     seed = crc;
00177     return crc;
00178 }
00179 
00180 uint16_t FastCRC16::mcrf4xx(const uint8_t *data,const uint16_t datalen)
00181 {
00182  // poly=0x1021 init=0xffff refin=true refout=true xorout=0x0000 check=0x6f91
00183   seed = 0xffff;
00184   return mcrf4xx_upd(data, datalen);
00185 }
00186 
00187 /** MODBUS
00188  * equivalent to _crc_16_update() in crc16.h from avr_libc
00189  * @param data Pointer to Data
00190  * @param datalen Length of Data
00191  * @return CRC value
00192  */
00193 uint16_t FastCRC16::modbus_upd(const uint8_t *data, uint16_t len)
00194 {
00195 
00196     uint16_t crc = seed;
00197 
00198     while (((uintptr_t)data & 3) && len) {
00199         crc = (crc >> 8) ^ crc_table_modbus[(crc & 0xff) ^ *data++];
00200         len--;
00201     }
00202 
00203     while (len >= 16) {
00204         len -= 16;
00205         crc_n4(crc, ((uint32_t *)data)[0], crc_table_modbus);
00206         crc_n4(crc, ((uint32_t *)data)[1], crc_table_modbus);
00207         crc_n4(crc, ((uint32_t *)data)[2], crc_table_modbus);
00208         crc_n4(crc, ((uint32_t *)data)[3], crc_table_modbus);
00209         data += 16;
00210     }
00211 
00212     while (len--) {
00213         crc = (crc >> 8) ^ crc_table_modbus[(crc & 0xff) ^ *data++];
00214     }
00215 
00216     seed = crc;
00217     return crc;
00218 }
00219 
00220 uint16_t FastCRC16::modbus(const uint8_t *data, const uint16_t datalen)
00221 {
00222  // poly=0x8005 init=0xffff refin=true refout=true xorout=0x0000 check=0x4b37
00223   seed = 0xffff;
00224   return modbus_upd(data, datalen);
00225 }
00226 
00227 /** KERMIT
00228  * Alias CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-CCITT
00229  * @param data Pointer to Data
00230  * @param datalen Length of Data
00231  * @return CRC value
00232  */
00233 uint16_t FastCRC16::kermit_upd(const uint8_t *data, uint16_t len)
00234 {
00235 
00236     uint16_t crc = seed;
00237 
00238     while (((uintptr_t)data & 3) && len) {
00239         crc = (crc >> 8) ^ crc_table_kermit[(crc & 0xff) ^ *data++];
00240         len--;
00241     }
00242 
00243     while (len >= 16) {
00244         len -= 16;
00245         crc_n4(crc, ((uint32_t *)data)[0], crc_table_kermit);
00246         crc_n4(crc, ((uint32_t *)data)[1], crc_table_kermit);
00247         crc_n4(crc, ((uint32_t *)data)[2], crc_table_kermit);
00248         crc_n4(crc, ((uint32_t *)data)[3], crc_table_kermit);
00249         data += 16;
00250     }
00251 
00252     while (len--) {
00253         crc = (crc >> 8) ^ crc_table_kermit[(crc & 0xff) ^ *data++];
00254     }
00255 
00256     seed = crc;
00257     return crc;
00258 }
00259 
00260 uint16_t FastCRC16::kermit(const uint8_t *data, const uint16_t datalen)
00261 {
00262  // poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189
00263  // sometimes byteswapped presentation of result
00264   seed = 0x0000;
00265   return kermit_upd(data, datalen);
00266 }
00267 
00268 /** XMODEM
00269  * Alias ZMODEM, CRC-16/ACORN
00270  * @param data Pointer to Data
00271  * @param datalen Length of Data
00272  * @return CRC value
00273  */
00274 uint16_t FastCRC16::xmodem_upd(const uint8_t *data, uint16_t len)
00275 {
00276 
00277     uint16_t crc = seed;
00278 
00279     while (((uintptr_t)data & 3) && len) {
00280         crc = (crc >> 8) ^ crc_table_xmodem[(crc & 0xff) ^ *data++];
00281         len--;
00282     }
00283 
00284     while (len >= 16) {
00285         len -= 16;
00286         crc_n4(crc, ((uint32_t *)data)[0], crc_table_xmodem);
00287         crc_n4(crc, ((uint32_t *)data)[1], crc_table_xmodem);
00288         crc_n4(crc, ((uint32_t *)data)[2], crc_table_xmodem);
00289         crc_n4(crc, ((uint32_t *)data)[3], crc_table_xmodem);
00290         data += 16;
00291     }
00292 
00293     while (len--) {
00294         crc = (crc >> 8) ^ crc_table_xmodem[(crc & 0xff) ^ *data++];
00295     }
00296 
00297     crc = REV16(crc);
00298 
00299     seed = crc;
00300     return crc;
00301 }
00302 
00303 uint16_t FastCRC16::xmodem(const uint8_t *data, const uint16_t datalen)
00304 {
00305   //width=16 poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 check=0x31c3
00306   seed = 0x0000;
00307   return xmodem_upd(data, datalen);
00308 }
00309 
00310 /** X25
00311  * Alias CRC-16/IBM-SDLC, CRC-16/ISO-HDLC, CRC-B
00312  * @param data Pointer to Data
00313  * @param datalen Length of Data
00314  * @return CRC value
00315  */
00316 uint16_t FastCRC16::x25_upd(const uint8_t *data, uint16_t len)
00317 {
00318 
00319     uint16_t crc = seed;
00320 
00321     while (((uintptr_t)data & 3) && len) {
00322         crc = (crc >> 8) ^ crc_table_x25[(crc & 0xff) ^ *data++];
00323         len--;
00324     }
00325 
00326     while (len >= 16) {
00327         len -= 16;
00328         crc_n4(crc, ((uint32_t *)data)[0], crc_table_x25);
00329         crc_n4(crc, ((uint32_t *)data)[1], crc_table_x25);
00330         crc_n4(crc, ((uint32_t *)data)[2], crc_table_x25);
00331         crc_n4(crc, ((uint32_t *)data)[3], crc_table_x25);
00332         data += 16;
00333     }
00334 
00335     while (len--) {
00336         crc = (crc >> 8) ^ crc_table_x25[(crc & 0xff) ^ *data++];
00337     }
00338 
00339     crc = ~crc;
00340 
00341     seed = crc;
00342     return crc;
00343 }
00344 
00345 uint16_t FastCRC16::x25(const uint8_t *data, const uint16_t datalen)
00346 {
00347   // poly=0x1021 init=0xffff refin=true refout=true xorout=0xffff check=0x906e
00348   seed = 0xffff;
00349   return x25_upd(data, datalen);
00350 }
00351 
00352 
00353 
00354 
00355 
00356 // ================= 32-BIT CRC ===================
00357 /** Constructor
00358  */
00359 FastCRC32::FastCRC32(){}
00360 
00361 #define crc_n4d(crc, data, table) crc ^= data; \
00362     crc = table[(crc & 0xff) + 0x300] ^    \
00363     table[((crc >> 8) & 0xff) + 0x200] ^   \
00364     table[((crc >> 16) & 0xff) + 0x100] ^ \
00365     table[(crc >> 24) & 0xff];
00366     
00367 #define crcsm_n4d(crc, data, table) crc ^= data; \
00368     crc = (crc >> 8) ^ table[crc & 0xff]; \
00369     crc = (crc >> 8) ^ table[crc & 0xff]; \
00370     crc = (crc >> 8) ^ table[crc & 0xff]; \
00371     crc = (crc >> 8) ^ table[crc & 0xff];
00372 
00373 /** CRC32
00374  * Alias CRC-32/ADCCP, PKZIP, Ethernet, 802.3
00375  * @param data Pointer to Data
00376  * @param datalen Length of Data
00377  * @return CRC value
00378  */
00379 
00380 #if CRC_BIGTABLES
00381 #define CRC_TABLE_CRC32 crc_table_crc32_big
00382 #else
00383 #define CRC_TABLE_CRC32 crc_table_crc32
00384 #endif
00385 
00386 uint32_t FastCRC32::crc32_upd(const uint8_t *data, uint16_t len)
00387 {
00388 
00389     uint32_t crc = seed;
00390 
00391     while (((uintptr_t)data & 3) && len) {
00392         crc = (crc >> 8) ^ CRC_TABLE_CRC32[(crc & 0xff) ^ *data++];
00393         len--;
00394     }
00395 
00396     while (len >= 16) {
00397         len -= 16;
00398         #if CRC_BIGTABLES
00399         crc_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CRC32);
00400         crc_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CRC32);
00401         crc_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CRC32);
00402         crc_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CRC32);
00403         #else
00404         crcsm_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CRC32);
00405         crcsm_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CRC32);
00406         crcsm_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CRC32);
00407         crcsm_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CRC32);
00408         #endif
00409         data += 16;
00410     }
00411 
00412     while (len--) {
00413         crc = (crc >> 8) ^ CRC_TABLE_CRC32[(crc & 0xff) ^ *data++];
00414     }
00415 
00416     crc = ~crc;
00417 
00418     seed = crc;
00419     return crc;
00420 }
00421 
00422 uint32_t FastCRC32::crc32(const uint8_t *data, const uint16_t datalen)
00423 {
00424   // poly=0x04c11db7 init=0xffffffff refin=true refout=true xorout=0xffffffff check=0xcbf43926
00425   seed = 0xffffffff;
00426   return crc32_upd(data, datalen);
00427 }
00428 
00429 /** CKSUM
00430  * Alias CRC-32/POSIX
00431  * @param data Pointer to Data
00432  * @param datalen Length of Data
00433  * @return CRC value
00434  */
00435 #if CRC_BIGTABLES
00436 #define CRC_TABLE_CKSUM crc_table_cksum_big
00437 #else
00438 #define CRC_TABLE_CKSUM crc_table_cksum
00439 #endif
00440 uint32_t FastCRC32::cksum_upd(const uint8_t *data, uint16_t len)
00441 {
00442 
00443     uint32_t crc = seed;
00444 
00445     while (((uintptr_t)data & 3) && len) {
00446         crc = (crc >> 8) ^ CRC_TABLE_CKSUM[(crc & 0xff) ^ *data++];
00447         len--;
00448     }
00449 
00450     while (len >= 16) {
00451         len -= 16;
00452         #if CRC_BIGTABLES
00453         crc_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CKSUM);
00454         crc_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CKSUM);
00455         crc_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CKSUM);
00456         crc_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CKSUM);
00457         #else
00458         crcsm_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CKSUM);
00459         crcsm_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CKSUM);
00460         crcsm_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CKSUM);
00461         crcsm_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CKSUM);
00462         #endif
00463         data += 16;
00464     }
00465 
00466     while (len--) {
00467         crc = (crc >> 8) ^ CRC_TABLE_CKSUM[(crc & 0xff) ^ *data++];
00468     }
00469 
00470     crc = ~REV32(crc);
00471 
00472     seed = crc;
00473     return crc;
00474 }
00475 
00476 uint32_t FastCRC32::cksum(const uint8_t *data, const uint16_t datalen)
00477 {
00478   // width=32 poly=0x04c11db7 init=0x00000000 refin=false refout=false xorout=0xffffffff check=0x765e7680
00479   seed = 0x00;
00480   return cksum_upd(data, datalen);
00481 }
00482 
00483 #endif // __MK20DX128__ || __MK20DX256__