Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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__
Generated on Mon Jul 25 2022 09:04:30 by
1.7.2