From 28f63d5d855f52ec2d1e53415354296e58b24127 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 21 Jul 2022 14:27:27 -0500 Subject: [PATCH] utils/math: add crc32 function This matches the STM32 hardware CRC. --- src/utils/math.test.ts | 16 ++++++++++++++-- src/utils/math.ts | 28 +++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/utils/math.test.ts b/src/utils/math.test.ts index eaa60641..aa53d699 100644 --- a/src/utils/math.test.ts +++ b/src/utils/math.test.ts @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT -// Copyright (c) 2020 The Pybricks Authors +// Copyright (c) 2020-2022 The Pybricks Authors -import { fmod, sumComplement32, xor8 } from './math'; +import { crc32, fmod, sumComplement32, xor8 } from './math'; describe('fmod', () => { test('positive numbers', () => { @@ -22,6 +22,18 @@ describe('sumComplement32', () => { }); }); +describe('crc32', () => { + test('trivial', () => { + expect(crc32([0])).toBe(0); + }); + test('trivial2', () => { + expect(crc32([0xffffffff])).toBe(0); + }); + test('basic', () => { + expect(crc32([1, 2, 3, 4, 5])).toBe(-2048796416); + }); +}); + describe('xor8', () => { test('basic', () => { expect(xor8([0])).toBe(0xff); diff --git a/src/utils/math.ts b/src/utils/math.ts index 0b2c7445..9af478e7 100644 --- a/src/utils/math.ts +++ b/src/utils/math.ts @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// Copyright (c) 2020 The Pybricks Authors +// Copyright (c) 2020-2022 The Pybricks Authors /** * Compute modulo using floored division @@ -28,6 +28,32 @@ export function sumComplement32(data: Iterable): number { // checksum is two's complement of total return ~total + 1; } +// thanks https://stackoverflow.com/a/33152544/1976323 + +const crc32Table: ReadonlyArray = [ + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, + 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, + 0x3c8ea00a, 0x384fbdbd, +]; + +/** + * Calculates the 32-bit CRC32 checksum. + * @data an iterable of 32-bit integers + * @returns the checksum + */ +export function crc32(data: Iterable): number { + let crc = 0xffffffff; + + for (const word of data) { + crc ^= word; + + for (let i = 0; i < 8; i++) { + crc = (crc << 4) ^ crc32Table[crc >> 28]; + } + } + + return crc; +} /** * Calculates the 8-bit "xor" checksum