PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

510 lines
13KB

  1. /* FastCRC library code is placed under the MIT license
  2. * Copyright (c) 2014,2015,2016 Frank Bösing
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining
  5. * a copy of this software and associated documentation files (the
  6. * "Software"), to deal in the Software without restriction, including
  7. * without limitation the rights to use, copy, modify, merge, publish,
  8. * distribute, sublicense, and/or sell copies of the Software, and to
  9. * permit persons to whom the Software is furnished to do so, subject to
  10. * the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be
  13. * included in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  19. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  20. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. * SOFTWARE.
  23. */
  24. //
  25. // Thanks to:
  26. // - Catalogue of parametrised CRC algorithms, CRC RevEng
  27. // http://reveng.sourceforge.net/crc-catalogue/
  28. //
  29. // - Danjel McGougan (CRC-Table-Generator)
  30. //
  31. #include "Arduino.h"
  32. #if !defined(KINETISK)
  33. #include "FastCRC.h"
  34. #include "FastCRC_cpu.h"
  35. #include "FastCRC_tables.h"
  36. // ================= 7-BIT CRC ===================
  37. /** Constructor
  38. */
  39. FastCRC7::FastCRC7(){}
  40. /** SMBUS CRC
  41. * aka CRC-8
  42. * @param data Pointer to Data
  43. * @param datalen Length of Data
  44. * @return CRC value
  45. */
  46. uint8_t FastCRC7::crc7_upd(const uint8_t *data, uint16_t datalen)
  47. {
  48. uint8_t crc = seed;
  49. if (datalen) do {
  50. crc = pgm_read_byte(&crc_table_crc7[crc ^ *data]);
  51. data++;
  52. } while (--datalen);
  53. seed = crc;
  54. return crc >> 1;
  55. }
  56. uint8_t FastCRC7::crc7(const uint8_t *data, const uint16_t datalen)
  57. {
  58. // poly=0x09 init=0x00 refin=false refout=false xorout=0x00 check=0x75
  59. seed = 0x00;
  60. return crc7_upd(data, datalen);
  61. }
  62. // ================= 8-BIT CRC ===================
  63. /** Constructor
  64. */
  65. FastCRC8::FastCRC8(){}
  66. /** SMBUS CRC
  67. * aka CRC-8
  68. * @param data Pointer to Data
  69. * @param datalen Length of Data
  70. * @return CRC value
  71. */
  72. uint8_t FastCRC8::smbus_upd(const uint8_t *data, uint16_t datalen)
  73. {
  74. uint8_t crc = seed;
  75. if (datalen) do {
  76. crc = pgm_read_byte(&crc_table_smbus[crc ^ *data]);
  77. data++;
  78. } while (--datalen);
  79. seed = crc;
  80. return crc;
  81. }
  82. uint8_t FastCRC8::smbus(const uint8_t *data, const uint16_t datalen)
  83. {
  84. // poly=0x07 init=0x00 refin=false refout=false xorout=0x00 check=0xf4
  85. seed = 0x00;
  86. return smbus_upd(data, datalen);
  87. }
  88. /** MAXIM 8-Bit CRC
  89. * equivalent to _crc_ibutton_update() in crc16.h from avr_libc
  90. * @param data Pointer to Data
  91. * @param datalen Length of Data
  92. * @return CRC value
  93. */
  94. uint8_t FastCRC8::maxim_upd(const uint8_t *data, uint16_t datalen)
  95. {
  96. uint8_t crc = seed;
  97. if (datalen) do {
  98. crc = pgm_read_byte(&crc_table_maxim[crc ^ *data]);
  99. data++;
  100. } while (--datalen);
  101. seed = crc;
  102. return crc;
  103. }
  104. uint8_t FastCRC8::maxim(const uint8_t *data, const uint16_t datalen)
  105. {
  106. // poly=0x31 init=0x00 refin=true refout=true xorout=0x00 check=0xa1
  107. seed = 0x00;
  108. return maxim_upd(data, datalen);
  109. }
  110. // ================= 16-BIT CRC ===================
  111. /** Constructor
  112. */
  113. FastCRC16::FastCRC16(){}
  114. #define crc_n4(crc, data, table) crc ^= data; \
  115. crc = pgm_read_word(&table[(crc & 0xff) + 0x300]) ^ \
  116. pgm_read_word(&table[((crc >> 8) & 0xff) + 0x200]) ^ \
  117. pgm_read_word(&table[((data >> 16) & 0xff) + 0x100]) ^ \
  118. pgm_read_word(&table[data >> 24]);
  119. /** CCITT
  120. * Alias "false CCITT"
  121. * @param data Pointer to Data
  122. * @param datalen Length of Data
  123. * @return CRC value
  124. */
  125. uint16_t FastCRC16::ccitt_upd(const uint8_t *data, uint16_t len)
  126. {
  127. uint16_t crc = seed;
  128. while (((uintptr_t)data & 3) && len) {
  129. crc = (crc >> 8) ^ pgm_read_word(&crc_table_ccitt[(crc & 0xff) ^ *data++]);
  130. len--;
  131. }
  132. while (len >= 16) {
  133. len -= 16;
  134. crc_n4(crc, ((uint32_t *)data)[0], crc_table_ccitt);
  135. crc_n4(crc, ((uint32_t *)data)[1], crc_table_ccitt);
  136. crc_n4(crc, ((uint32_t *)data)[2], crc_table_ccitt);
  137. crc_n4(crc, ((uint32_t *)data)[3], crc_table_ccitt);
  138. data += 16;
  139. }
  140. while (len--) {
  141. crc = (crc >> 8) ^ pgm_read_word(&crc_table_ccitt[(crc & 0xff) ^ *data++]);
  142. }
  143. seed = crc;
  144. crc = REV16(crc);
  145. return crc;
  146. }
  147. uint16_t FastCRC16::ccitt(const uint8_t *data,const uint16_t datalen)
  148. {
  149. // poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1
  150. seed = 0xffff;
  151. return ccitt_upd(data, datalen);
  152. }
  153. /** MCRF4XX
  154. * equivalent to _crc_ccitt_update() in crc16.h from avr_libc
  155. * @param data Pointer to Data
  156. * @param datalen Length of Data
  157. * @return CRC value
  158. */
  159. uint16_t FastCRC16::mcrf4xx_upd(const uint8_t *data, uint16_t len)
  160. {
  161. uint16_t crc = seed;
  162. while (((uintptr_t)data & 3) && len) {
  163. crc = (crc >> 8) ^ pgm_read_word(&crc_table_mcrf4xx[(crc & 0xff) ^ *data++]);
  164. len--;
  165. }
  166. while (len >= 16) {
  167. len -= 16;
  168. crc_n4(crc, ((uint32_t *)data)[0], crc_table_mcrf4xx);
  169. crc_n4(crc, ((uint32_t *)data)[1], crc_table_mcrf4xx);
  170. crc_n4(crc, ((uint32_t *)data)[2], crc_table_mcrf4xx);
  171. crc_n4(crc, ((uint32_t *)data)[3], crc_table_mcrf4xx);
  172. data += 16;
  173. }
  174. while (len--) {
  175. crc = (crc >> 8) ^ pgm_read_word(&crc_table_mcrf4xx[(crc & 0xff) ^ *data++]);
  176. }
  177. seed = crc;
  178. return crc;
  179. }
  180. uint16_t FastCRC16::mcrf4xx(const uint8_t *data,const uint16_t datalen)
  181. {
  182. // poly=0x1021 init=0xffff refin=true refout=true xorout=0x0000 check=0x6f91
  183. seed = 0xffff;
  184. return mcrf4xx_upd(data, datalen);
  185. }
  186. /** MODBUS
  187. * equivalent to _crc_16_update() in crc16.h from avr_libc
  188. * @param data Pointer to Data
  189. * @param datalen Length of Data
  190. * @return CRC value
  191. */
  192. uint16_t FastCRC16::modbus_upd(const uint8_t *data, uint16_t len)
  193. {
  194. uint16_t crc = seed;
  195. while (((uintptr_t)data & 3) && len) {
  196. crc = (crc >> 8) ^ pgm_read_word(&crc_table_modbus[(crc & 0xff) ^ *data++]);
  197. len--;
  198. }
  199. while (len >= 16) {
  200. len -= 16;
  201. crc_n4(crc, ((uint32_t *)data)[0], crc_table_modbus);
  202. crc_n4(crc, ((uint32_t *)data)[1], crc_table_modbus);
  203. crc_n4(crc, ((uint32_t *)data)[2], crc_table_modbus);
  204. crc_n4(crc, ((uint32_t *)data)[3], crc_table_modbus);
  205. data += 16;
  206. }
  207. while (len--) {
  208. crc = (crc >> 8) ^ pgm_read_word(&crc_table_modbus[(crc & 0xff) ^ *data++]);
  209. }
  210. seed = crc;
  211. return crc;
  212. }
  213. uint16_t FastCRC16::modbus(const uint8_t *data, const uint16_t datalen)
  214. {
  215. // poly=0x8005 init=0xffff refin=true refout=true xorout=0x0000 check=0x4b37
  216. seed = 0xffff;
  217. return modbus_upd(data, datalen);
  218. }
  219. /** KERMIT
  220. * Alias CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-CCITT
  221. * @param data Pointer to Data
  222. * @param datalen Length of Data
  223. * @return CRC value
  224. */
  225. uint16_t FastCRC16::kermit_upd(const uint8_t *data, uint16_t len)
  226. {
  227. uint16_t crc = seed;
  228. while (((uintptr_t)data & 3) && len) {
  229. crc = (crc >> 8) ^ pgm_read_word(&crc_table_kermit[(crc & 0xff) ^ *data++]);
  230. len--;
  231. }
  232. while (len >= 16) {
  233. len -= 16;
  234. crc_n4(crc, ((uint32_t *)data)[0], crc_table_kermit);
  235. crc_n4(crc, ((uint32_t *)data)[1], crc_table_kermit);
  236. crc_n4(crc, ((uint32_t *)data)[2], crc_table_kermit);
  237. crc_n4(crc, ((uint32_t *)data)[3], crc_table_kermit);
  238. data += 16;
  239. }
  240. while (len--) {
  241. crc = (crc >> 8) ^ pgm_read_word(&crc_table_kermit[(crc & 0xff) ^ *data++]);
  242. }
  243. seed = crc;
  244. return crc;
  245. }
  246. uint16_t FastCRC16::kermit(const uint8_t *data, const uint16_t datalen)
  247. {
  248. // poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189
  249. // sometimes byteswapped presentation of result
  250. seed = 0x0000;
  251. return kermit_upd(data, datalen);
  252. }
  253. /** XMODEM
  254. * Alias ZMODEM, CRC-16/ACORN
  255. * @param data Pointer to Data
  256. * @param datalen Length of Data
  257. * @return CRC value
  258. */
  259. uint16_t FastCRC16::xmodem_upd(const uint8_t *data, uint16_t len)
  260. {
  261. uint16_t crc = seed;
  262. while (((uintptr_t)data & 3) && len) {
  263. crc = (crc >> 8) ^ pgm_read_word(&crc_table_xmodem[(crc & 0xff) ^ *data++]);
  264. len--;
  265. }
  266. while (len >= 16) {
  267. len -= 16;
  268. crc_n4(crc, ((uint32_t *)data)[0], crc_table_xmodem);
  269. crc_n4(crc, ((uint32_t *)data)[1], crc_table_xmodem);
  270. crc_n4(crc, ((uint32_t *)data)[2], crc_table_xmodem);
  271. crc_n4(crc, ((uint32_t *)data)[3], crc_table_xmodem);
  272. data += 16;
  273. }
  274. while (len--) {
  275. crc = (crc >> 8) ^ pgm_read_word(&crc_table_xmodem[(crc & 0xff) ^ *data++]);
  276. }
  277. seed = crc;
  278. crc = REV16(crc);
  279. return crc;
  280. }
  281. uint16_t FastCRC16::xmodem(const uint8_t *data, const uint16_t datalen)
  282. {
  283. //width=16 poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 check=0x31c3
  284. seed = 0x0000;
  285. return xmodem_upd(data, datalen);
  286. }
  287. /** X25
  288. * Alias CRC-16/IBM-SDLC, CRC-16/ISO-HDLC, CRC-B
  289. * @param data Pointer to Data
  290. * @param datalen Length of Data
  291. * @return CRC value
  292. */
  293. uint16_t FastCRC16::x25_upd(const uint8_t *data, uint16_t len)
  294. {
  295. uint16_t crc = seed;
  296. while (((uintptr_t)data & 3) && len) {
  297. crc = (crc >> 8) ^ pgm_read_word(&crc_table_x25[(crc & 0xff) ^ *data++]);
  298. len--;
  299. }
  300. while (len >= 16) {
  301. len -= 16;
  302. crc_n4(crc, ((uint32_t *)data)[0], crc_table_x25);
  303. crc_n4(crc, ((uint32_t *)data)[1], crc_table_x25);
  304. crc_n4(crc, ((uint32_t *)data)[2], crc_table_x25);
  305. crc_n4(crc, ((uint32_t *)data)[3], crc_table_x25);
  306. data += 16;
  307. }
  308. while (len--) {
  309. crc = (crc >> 8) ^ pgm_read_word(&crc_table_x25[(crc & 0xff) ^ *data++]);
  310. }
  311. seed = crc;
  312. crc = ~crc;
  313. return crc;
  314. }
  315. uint16_t FastCRC16::x25(const uint8_t *data, const uint16_t datalen)
  316. {
  317. // poly=0x1021 init=0xffff refin=true refout=true xorout=0xffff check=0x906e
  318. seed = 0xffff;
  319. return x25_upd(data, datalen);
  320. }
  321. // ================= 32-BIT CRC ===================
  322. /** Constructor
  323. */
  324. FastCRC32::FastCRC32(){}
  325. #define crc_n4d(crc, data, table) crc ^= data; \
  326. crc = pgm_read_dword(&table[(crc & 0xff) + 0x300]) ^ \
  327. pgm_read_dword(&table[((crc >> 8) & 0xff) + 0x200]) ^ \
  328. pgm_read_dword(&table[((crc >> 16) & 0xff) + 0x100]) ^ \
  329. pgm_read_dword(&table[(crc >> 24) & 0xff]);
  330. #define crcsm_n4d(crc, data, table) crc ^= data; \
  331. crc = (crc >> 8) ^ pgm_read_dword(&table[crc & 0xff]); \
  332. crc = (crc >> 8) ^ pgm_read_dword(&table[crc & 0xff]); \
  333. crc = (crc >> 8) ^ pgm_read_dword(&table[crc & 0xff]); \
  334. crc = (crc >> 8) ^ pgm_read_dword(&table[crc & 0xff]);
  335. /** CRC32
  336. * Alias CRC-32/ADCCP, PKZIP, Ethernet, 802.3
  337. * @param data Pointer to Data
  338. * @param datalen Length of Data
  339. * @return CRC value
  340. */
  341. #if CRC_BIGTABLES
  342. #define CRC_TABLE_CRC32 crc_table_crc32_big
  343. #else
  344. #define CRC_TABLE_CRC32 crc_table_crc32
  345. #endif
  346. uint32_t FastCRC32::crc32_upd(const uint8_t *data, uint16_t len)
  347. {
  348. uint32_t crc = seed;
  349. while (((uintptr_t)data & 3) && len) {
  350. crc = (crc >> 8) ^ pgm_read_dword(&CRC_TABLE_CRC32[(crc & 0xff) ^ *data++]);
  351. len--;
  352. }
  353. while (len >= 16) {
  354. len -= 16;
  355. #if CRC_BIGTABLES
  356. crc_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CRC32);
  357. crc_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CRC32);
  358. crc_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CRC32);
  359. crc_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CRC32);
  360. #else
  361. crcsm_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CRC32);
  362. crcsm_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CRC32);
  363. crcsm_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CRC32);
  364. crcsm_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CRC32);
  365. #endif
  366. data += 16;
  367. }
  368. while (len--) {
  369. crc = (crc >> 8) ^ pgm_read_dword(&CRC_TABLE_CRC32[(crc & 0xff) ^ *data++]);
  370. }
  371. seed = crc;
  372. crc = ~crc;
  373. return crc;
  374. }
  375. uint32_t FastCRC32::crc32(const uint8_t *data, const uint16_t datalen)
  376. {
  377. // poly=0x04c11db7 init=0xffffffff refin=true refout=true xorout=0xffffffff check=0xcbf43926
  378. seed = 0xffffffff;
  379. return crc32_upd(data, datalen);
  380. }
  381. /** CKSUM
  382. * Alias CRC-32/POSIX
  383. * @param data Pointer to Data
  384. * @param datalen Length of Data
  385. * @return CRC value
  386. */
  387. #if CRC_BIGTABLES
  388. #define CRC_TABLE_CKSUM crc_table_cksum_big
  389. #else
  390. #define CRC_TABLE_CKSUM crc_table_cksum
  391. #endif
  392. uint32_t FastCRC32::cksum_upd(const uint8_t *data, uint16_t len)
  393. {
  394. uint32_t crc = seed;
  395. while (((uintptr_t)data & 3) && len) {
  396. crc = (crc >> 8) ^ pgm_read_dword(&CRC_TABLE_CKSUM[(crc & 0xff) ^ *data++]);
  397. len--;
  398. }
  399. while (len >= 16) {
  400. len -= 16;
  401. #if CRC_BIGTABLES
  402. crc_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CKSUM);
  403. crc_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CKSUM);
  404. crc_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CKSUM);
  405. crc_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CKSUM);
  406. #else
  407. crcsm_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CKSUM);
  408. crcsm_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CKSUM);
  409. crcsm_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CKSUM);
  410. crcsm_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CKSUM);
  411. #endif
  412. data += 16;
  413. }
  414. while (len--) {
  415. crc = (crc >> 8) ^ pgm_read_dword(&CRC_TABLE_CKSUM[(crc & 0xff) ^ *data++]);
  416. }
  417. seed = crc;
  418. crc = ~REV32(crc);
  419. return crc;
  420. }
  421. uint32_t FastCRC32::cksum(const uint8_t *data, const uint16_t datalen)
  422. {
  423. // width=32 poly=0x04c11db7 init=0x00000000 refin=false refout=false xorout=0xffffffff check=0x765e7680
  424. seed = 0x00;
  425. return cksum_upd(data, datalen);
  426. }
  427. #endif // #if !defined(KINETISK)